xref: /netbsd-src/external/lgpl3/gmp/dist/mini-gmp/tests/testutils.c (revision 72c7faa4dbb41dbb0238d6b4a109da0d4b236dd4)
1 /*
2 
3 Copyright 2013-2015, 2018 Free Software Foundation, Inc.
4 
5 This file is part of the GNU MP Library test suite.
6 
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11 
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
19 
20 #include "testutils.h"
21 
22 /* Include it here, so we we could tweak, e.g., how MPZ_REALLOC
23    works. */
24 #include "../mini-gmp.c"
25 #include "../mini-mpq.c"
26 
27 static size_t total_alloc = 0;
28 
29 /* Custom memory allocation to track memory usage, and add a small red
30    zone.
31 
32    About alignment: In general, getting a block from malloc, and
33    incrementing it by sizeof(size_t), like we do here, might give a
34    pointer which is not properly aligned for all types. But the
35    largest type we allocate space for is unsigned long (mp_limb_t),
36    which shouldn't have stricter alignment requirements than
37    size_t. */
38 
39 static unsigned char block_end[8] =
40   { 0x7c, 0x37, 0xd6, 0x12, 0xa8, 0x6c, 0x01, 0xd1 };
41 
42 static void *
block_init(size_t * block,size_t size)43 block_init (size_t *block, size_t size)
44 {
45   char *p;
46   *block++ = size;
47 
48   p = (char *) block;
49   memcpy (p + size, block_end, sizeof(block_end));
50 
51   total_alloc += size;
52   return p;
53 }
54 
55 /* Check small redzone, return pointer to malloced block. */
56 static size_t *
block_check(void * p)57 block_check  (void *p)
58 {
59   size_t *block = (size_t *) p - 1;
60   size_t size = block[0];
61 
62   if (memcmp ((char *)p + size, block_end, sizeof(block_end)) != 0)
63     {
64       fprintf (stderr, "red zone overwritten.\n");
65       abort ();
66     }
67   total_alloc -= size;
68   return block;
69 }
70 
71 static void *
tu_alloc(size_t size)72 tu_alloc (size_t size)
73 {
74   size_t *block = (size_t *) malloc (sizeof(size_t) + size + sizeof(block_end));
75   if (!block)
76     {
77       fprintf (stderr, "Virtual memory exhausted.\n");
78       abort ();
79     }
80 
81   return block_init (block, size);
82 }
83 
84 static void *
tu_realloc(void * p,size_t old_size,size_t new_size)85 tu_realloc (void *p, size_t old_size, size_t new_size)
86 {
87   size_t *block = block_check (p);
88   block = (size_t *) realloc (block, sizeof(size_t) + new_size + sizeof(block_end));
89   if (!block)
90     {
91       fprintf (stderr, "Virtual memory exhausted.\n");
92       abort ();
93     }
94 
95   return block_init (block, new_size);
96 }
97 
98 static void
tu_free(void * p,size_t old_size)99 tu_free (void *p, size_t old_size)
100 {
101   free (block_check (p));
102 }
103 
104 /* Free memory allocated via mini-gmp allocation function. */
105 void
testfree(void * p)106 testfree (void *p)
107 {
108   void (*freefunc) (void *, size_t);
109   mp_get_memory_functions (NULL, NULL, &freefunc);
110 
111   freefunc (p, 0);
112 }
113 
114 int
main(int argc,char ** argv)115 main (int argc, char **argv)
116 {
117   hex_random_init ();
118 
119   mp_set_memory_functions (tu_alloc, tu_realloc, tu_free);
120 
121   /* Currently, t-comb seems to be the only program accepting any
122      arguments. It might make sense to parse common arguments here. */
123   testmain (argc, argv);
124 
125   if (total_alloc != 0)
126     {
127       fprintf (stderr, "Memory leaked: %lu bytes.\n",
128 	       (unsigned long) total_alloc);
129       abort ();
130     }
131   return 0;
132 }
133 
134 void
testhalves(int count,void (* tested_fun)(int))135 testhalves (int count, void (*tested_fun) (int))
136 {
137   void (*freefunc) (void *, size_t);
138   void *(*reallocfunc) (void *, size_t, size_t);
139   void *(*allocfunc) (size_t);
140   size_t initial_alloc;
141 
142   mp_get_memory_functions (&allocfunc, &reallocfunc, &freefunc);
143   initial_alloc = total_alloc;
144   (*tested_fun) (count / 2);
145   if (initial_alloc != total_alloc)
146     {
147       fprintf (stderr, "First half, memory leaked: %lu bytes.\n",
148 	       (unsigned long) total_alloc - initial_alloc);
149       abort ();
150     }
151   mp_set_memory_functions (NULL, NULL, NULL);
152   (*tested_fun) (count / 2);
153   mp_set_memory_functions (allocfunc, reallocfunc, freefunc);
154 }
155 
156 void
dump(const char * label,const mpz_t x)157 dump (const char *label, const mpz_t x)
158 {
159   char *buf = mpz_get_str (NULL, 16, x);
160   fprintf (stderr, "%s: %s\n", label, buf);
161   testfree (buf);
162 }
163 
164 void
mpz_set_str_or_abort(mpz_ptr z,const char * str,int base)165 mpz_set_str_or_abort (mpz_ptr z, const char *str, int base)
166 {
167   if (mpz_set_str (z, str, base) != 0)
168     {
169       fprintf (stderr, "ERROR: mpz_set_str failed\n");
170       fprintf (stderr, "   str  = \"%s\"\n", str);
171       fprintf (stderr, "   base = %d\n", base);
172       abort();
173     }
174 }
175 
176 int
mpz_lucas_mod(mpz_t V,mpz_t Qk,long Q,mp_bitcnt_t b0,const mpz_t n)177 mpz_lucas_mod (mpz_t V, mpz_t Qk, long Q,
178 	       mp_bitcnt_t b0, const mpz_t n)
179 {
180   return gmp_lucas_mod (V, Qk, Q, b0, n);
181 }
182