1 /* Miscellaneous test program support routines.
2
3 Copyright 2000-2003, 2005, 2013 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 "config.h"
21
22 #include <ctype.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h> /* for getenv */
26 #include <string.h>
27
28 #if HAVE_FLOAT_H
29 #include <float.h> /* for DBL_MANT_DIG */
30 #endif
31
32 #if TIME_WITH_SYS_TIME
33 # include <sys/time.h> /* for struct timeval */
34 # include <time.h>
35 #else
36 # if HAVE_SYS_TIME_H
37 # include <sys/time.h>
38 # else
39 # include <time.h>
40 # endif
41 #endif
42
43 #include "gmp.h"
44 #include "gmp-impl.h"
45 #include "tests.h"
46
47
48 /* The various tests setups and final checks, collected up together. */
49 void
tests_start(void)50 tests_start (void)
51 {
52 char version[10];
53 snprintf (version, 10, "%u.%u.%u",
54 __GNU_MP_VERSION,
55 __GNU_MP_VERSION_MINOR,
56 __GNU_MP_VERSION_PATCHLEVEL);
57
58 if (strcmp (gmp_version, version) != 0)
59 {
60 fprintf (stderr, "tests are not linked to the newly compiled library\n");
61 fprintf (stderr, " local version is: %s\n", version);
62 fprintf (stderr, " linked version is: %s\n", gmp_version);
63 abort ();
64 }
65
66 /* don't buffer, so output is not lost if a test causes a segv etc */
67 setbuf (stdout, NULL);
68 setbuf (stderr, NULL);
69
70 tests_memory_start ();
71 tests_rand_start ();
72 }
73 void
tests_end(void)74 tests_end (void)
75 {
76 tests_rand_end ();
77 tests_memory_end ();
78 }
79
80
81 void
tests_rand_start(void)82 tests_rand_start (void)
83 {
84 gmp_randstate_ptr rands;
85 char *perform_seed;
86 unsigned long seed;
87
88 if (__gmp_rands_initialized)
89 {
90 printf ("Please let tests_start() initialize the global __gmp_rands.\n");
91 printf ("ie. ensure that function is called before the first use of RANDS.\n");
92 abort ();
93 }
94
95 gmp_randinit_default (__gmp_rands);
96 __gmp_rands_initialized = 1;
97 rands = __gmp_rands;
98
99 perform_seed = getenv ("GMP_CHECK_RANDOMIZE");
100 if (perform_seed != NULL)
101 {
102 #ifdef HAVE_STRTOUL
103 seed = strtoul (perform_seed, 0, 0);
104 #else
105 /* This will not work right for seeds >= 2^31 on 64-bit machines.
106 Perhaps use atol unconditionally? Is that ubiquitous? */
107 seed = atoi (perform_seed);
108 #endif
109 if (! (seed == 0 || seed == 1))
110 {
111 printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed);
112 gmp_randseed_ui (rands, seed);
113 }
114 else
115 {
116 #if HAVE_GETTIMEOFDAY
117 struct timeval tv;
118 gettimeofday (&tv, NULL);
119 seed = tv.tv_sec ^ ((unsigned long) tv.tv_usec << 12);
120 seed &= 0xffffffff;
121 #else
122 time_t tv;
123 time (&tv);
124 seed = tv;
125 #endif
126 gmp_randseed_ui (rands, seed);
127 printf ("Seed GMP_CHECK_RANDOMIZE=%lu (include this in bug reports)\n", seed);
128 }
129 fflush (stdout);
130 }
131 }
132 void
tests_rand_end(void)133 tests_rand_end (void)
134 {
135 RANDS_CLEAR ();
136 }
137
138
139 /* Only used if CPU calling conventions checking is available. */
140 mp_limb_t (*calling_conventions_function) (ANYARGS);
141
142
143 /* Return p advanced to the next multiple of "align" bytes. "align" must be
144 a power of 2. Care is taken not to assume sizeof(int)==sizeof(pointer).
145 Using "unsigned long" avoids a warning on hpux. */
146 void *
align_pointer(void * p,size_t align)147 align_pointer (void *p, size_t align)
148 {
149 gmp_intptr_t d;
150 d = ((gmp_intptr_t) p) & (align-1);
151 d = (d != 0 ? align-d : 0);
152 return (void *) (((char *) p) + d);
153 }
154
155
156 /* Note that memory allocated with this function can never be freed, because
157 the start address of the block allocated is lost. */
158 void *
__gmp_allocate_func_aligned(size_t bytes,size_t align)159 __gmp_allocate_func_aligned (size_t bytes, size_t align)
160 {
161 return align_pointer ((*__gmp_allocate_func) (bytes + align-1), align);
162 }
163
164
165 void *
__gmp_allocate_or_reallocate(void * ptr,size_t oldsize,size_t newsize)166 __gmp_allocate_or_reallocate (void *ptr, size_t oldsize, size_t newsize)
167 {
168 if (ptr == NULL)
169 return (*__gmp_allocate_func) (newsize);
170 else
171 return (*__gmp_reallocate_func) (ptr, oldsize, newsize);
172 }
173
174 char *
__gmp_allocate_strdup(const char * s)175 __gmp_allocate_strdup (const char *s)
176 {
177 size_t len;
178 char *t;
179 len = strlen (s);
180 t = (char *) (*__gmp_allocate_func) (len+1);
181 memcpy (t, s, len+1);
182 return t;
183 }
184
185
186 char *
strtoupper(char * s_orig)187 strtoupper (char *s_orig)
188 {
189 char *s;
190 for (s = s_orig; *s != '\0'; s++)
191 if (isascii (*s))
192 *s = toupper (*s);
193 return s_orig;
194 }
195
196
197 void
mpz_set_n(mpz_ptr z,mp_srcptr p,mp_size_t size)198 mpz_set_n (mpz_ptr z, mp_srcptr p, mp_size_t size)
199 {
200 ASSERT (size >= 0);
201 MPN_NORMALIZE (p, size);
202 MPZ_REALLOC (z, size);
203 MPN_COPY (PTR(z), p, size);
204 SIZ(z) = size;
205 }
206
207 void
mpz_init_set_n(mpz_ptr z,mp_srcptr p,mp_size_t size)208 mpz_init_set_n (mpz_ptr z, mp_srcptr p, mp_size_t size)
209 {
210 ASSERT (size >= 0);
211
212 MPN_NORMALIZE (p, size);
213 ALLOC(z) = MAX (size, 1);
214 PTR(z) = __GMP_ALLOCATE_FUNC_LIMBS (ALLOC(z));
215 SIZ(z) = size;
216 MPN_COPY (PTR(z), p, size);
217 }
218
219
220 /* Find least significant limb position where p1,size and p2,size differ. */
221 mp_size_t
mpn_diff_lowest(mp_srcptr p1,mp_srcptr p2,mp_size_t size)222 mpn_diff_lowest (mp_srcptr p1, mp_srcptr p2, mp_size_t size)
223 {
224 mp_size_t i;
225
226 for (i = 0; i < size; i++)
227 if (p1[i] != p2[i])
228 return i;
229
230 /* no differences */
231 return -1;
232 }
233
234
235 /* Find most significant limb position where p1,size and p2,size differ. */
236 mp_size_t
mpn_diff_highest(mp_srcptr p1,mp_srcptr p2,mp_size_t size)237 mpn_diff_highest (mp_srcptr p1, mp_srcptr p2, mp_size_t size)
238 {
239 mp_size_t i;
240
241 for (i = size-1; i >= 0; i--)
242 if (p1[i] != p2[i])
243 return i;
244
245 /* no differences */
246 return -1;
247 }
248
249
250 /* Find least significant byte position where p1,size and p2,size differ. */
251 mp_size_t
byte_diff_lowest(const void * p1,const void * p2,mp_size_t size)252 byte_diff_lowest (const void *p1, const void *p2, mp_size_t size)
253 {
254 mp_size_t i;
255
256 for (i = 0; i < size; i++)
257 if (((const char *) p1)[i] != ((const char *) p2)[i])
258 return i;
259
260 /* no differences */
261 return -1;
262 }
263
264
265 /* Find most significant limb position where p1,size and p2,size differ. */
266 mp_size_t
byte_diff_highest(const void * p1,const void * p2,mp_size_t size)267 byte_diff_highest (const void *p1, const void *p2, mp_size_t size)
268 {
269 mp_size_t i;
270
271 for (i = size-1; i >= 0; i--)
272 if (((const char *) p1)[i] != ((const char *) p2)[i])
273 return i;
274
275 /* no differences */
276 return -1;
277 }
278
279
280 void
mpz_set_str_or_abort(mpz_ptr z,const char * str,int base)281 mpz_set_str_or_abort (mpz_ptr z, const char *str, int base)
282 {
283 if (mpz_set_str (z, str, base) != 0)
284 {
285 fprintf (stderr, "ERROR: mpz_set_str failed\n");
286 fprintf (stderr, " str = \"%s\"\n", str);
287 fprintf (stderr, " base = %d\n", base);
288 abort();
289 }
290 }
291
292 void
mpq_set_str_or_abort(mpq_ptr q,const char * str,int base)293 mpq_set_str_or_abort (mpq_ptr q, const char *str, int base)
294 {
295 if (mpq_set_str (q, str, base) != 0)
296 {
297 fprintf (stderr, "ERROR: mpq_set_str failed\n");
298 fprintf (stderr, " str = \"%s\"\n", str);
299 fprintf (stderr, " base = %d\n", base);
300 abort();
301 }
302 }
303
304 void
mpf_set_str_or_abort(mpf_ptr f,const char * str,int base)305 mpf_set_str_or_abort (mpf_ptr f, const char *str, int base)
306 {
307 if (mpf_set_str (f, str, base) != 0)
308 {
309 fprintf (stderr, "ERROR mpf_set_str failed\n");
310 fprintf (stderr, " str = \"%s\"\n", str);
311 fprintf (stderr, " base = %d\n", base);
312 abort();
313 }
314 }
315
316
317 /* Whether the absolute value of z is a power of 2. */
318 int
mpz_pow2abs_p(mpz_srcptr z)319 mpz_pow2abs_p (mpz_srcptr z)
320 {
321 mp_size_t size, i;
322 mp_srcptr ptr;
323
324 size = SIZ (z);
325 if (size == 0)
326 return 0; /* zero is not a power of 2 */
327 size = ABS (size);
328
329 ptr = PTR (z);
330 for (i = 0; i < size-1; i++)
331 if (ptr[i] != 0)
332 return 0; /* non-zero low limb means not a power of 2 */
333
334 return POW2_P (ptr[i]); /* high limb power of 2 */
335 }
336
337
338 /* Exponentially distributed between 0 and 2^nbits-1, meaning the number of
339 bits in the result is uniformly distributed between 0 and nbits-1.
340
341 FIXME: This is not a proper exponential distribution, since the
342 probability function will have a stepped shape due to using a uniform
343 distribution after choosing how many bits. */
344
345 void
mpz_erandomb(mpz_ptr rop,gmp_randstate_t rstate,unsigned long nbits)346 mpz_erandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
347 {
348 mpz_urandomb (rop, rstate, gmp_urandomm_ui (rstate, nbits));
349 }
350
351 void
mpz_erandomb_nonzero(mpz_ptr rop,gmp_randstate_t rstate,unsigned long nbits)352 mpz_erandomb_nonzero (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
353 {
354 mpz_erandomb (rop, rstate, nbits);
355 if (mpz_sgn (rop) == 0)
356 mpz_set_ui (rop, 1L);
357 }
358
359 void
mpz_errandomb(mpz_ptr rop,gmp_randstate_t rstate,unsigned long nbits)360 mpz_errandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
361 {
362 mpz_rrandomb (rop, rstate, gmp_urandomm_ui (rstate, nbits));
363 }
364
365 void
mpz_errandomb_nonzero(mpz_ptr rop,gmp_randstate_t rstate,unsigned long nbits)366 mpz_errandomb_nonzero (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
367 {
368 mpz_errandomb (rop, rstate, nbits);
369 if (mpz_sgn (rop) == 0)
370 mpz_set_ui (rop, 1L);
371 }
372
373 void
mpz_negrandom(mpz_ptr rop,gmp_randstate_t rstate)374 mpz_negrandom (mpz_ptr rop, gmp_randstate_t rstate)
375 {
376 mp_limb_t n;
377 _gmp_rand (&n, rstate, 1);
378 if (n != 0)
379 mpz_neg (rop, rop);
380 }
381
382 mp_limb_t
urandom(void)383 urandom (void)
384 {
385 #if GMP_NAIL_BITS == 0
386 mp_limb_t n;
387 _gmp_rand (&n, RANDS, GMP_LIMB_BITS);
388 return n;
389 #else
390 mp_limb_t n[2];
391 _gmp_rand (n, RANDS, GMP_LIMB_BITS);
392 return n[0] + (n[1] << GMP_NUMB_BITS);
393 #endif
394 }
395
396
397 /* Call (*func)() with various random number generators. */
398 void
call_rand_algs(void (* func)(const char *,gmp_randstate_ptr))399 call_rand_algs (void (*func) (const char *, gmp_randstate_ptr))
400 {
401 gmp_randstate_t rstate;
402 mpz_t a;
403
404 mpz_init (a);
405
406 gmp_randinit_default (rstate);
407 (*func) ("gmp_randinit_default", rstate);
408 gmp_randclear (rstate);
409
410 gmp_randinit_mt (rstate);
411 (*func) ("gmp_randinit_mt", rstate);
412 gmp_randclear (rstate);
413
414 gmp_randinit_lc_2exp_size (rstate, 8L);
415 (*func) ("gmp_randinit_lc_2exp_size 8", rstate);
416 gmp_randclear (rstate);
417
418 gmp_randinit_lc_2exp_size (rstate, 16L);
419 (*func) ("gmp_randinit_lc_2exp_size 16", rstate);
420 gmp_randclear (rstate);
421
422 gmp_randinit_lc_2exp_size (rstate, 128L);
423 (*func) ("gmp_randinit_lc_2exp_size 128", rstate);
424 gmp_randclear (rstate);
425
426 /* degenerate always zeros */
427 mpz_set_ui (a, 0L);
428 gmp_randinit_lc_2exp (rstate, a, 0L, 8L);
429 (*func) ("gmp_randinit_lc_2exp a=0 c=0 m=8", rstate);
430 gmp_randclear (rstate);
431
432 /* degenerate always FFs */
433 mpz_set_ui (a, 0L);
434 gmp_randinit_lc_2exp (rstate, a, 0xFFL, 8L);
435 (*func) ("gmp_randinit_lc_2exp a=0 c=0xFF m=8", rstate);
436 gmp_randclear (rstate);
437
438 mpz_clear (a);
439 }
440
441
442 /* Return +infinity if available, or 0 if not.
443 We don't want to use libm, so INFINITY or other system values are not
444 used here. */
445 double
tests_infinity_d(void)446 tests_infinity_d (void)
447 {
448 #if _GMP_IEEE_FLOATS
449 union ieee_double_extract x;
450 x.s.exp = 2047;
451 x.s.manl = 0;
452 x.s.manh = 0;
453 x.s.sig = 0;
454 return x.d;
455 #else
456 return 0;
457 #endif
458 }
459
460
461 /* Return non-zero if d is an infinity (either positive or negative).
462 Don't want libm, so don't use isinf() or other system tests. */
463 int
tests_isinf(double d)464 tests_isinf (double d)
465 {
466 #if _GMP_IEEE_FLOATS
467 union ieee_double_extract x;
468 x.d = d;
469 return (x.s.exp == 2047 && x.s.manl == 0 && x.s.manh == 0);
470 #else
471 return 0;
472 #endif
473 }
474
475
476 /* Set the hardware floating point rounding mode. Same mode values as mpfr,
477 namely 0=nearest, 1=tozero, 2=up, 3=down. Return 1 if successful, 0 if
478 not. */
479 int
tests_hardware_setround(int mode)480 tests_hardware_setround (int mode)
481 {
482 #if ! defined NO_ASM && HAVE_HOST_CPU_FAMILY_x86
483 int rc;
484 switch (mode) {
485 case 0: rc = 0; break; /* nearest */
486 case 1: rc = 3; break; /* tozero */
487 case 2: rc = 2; break; /* up */
488 case 3: rc = 1; break; /* down */
489 default:
490 return 0;
491 }
492 x86_fldcw ((x86_fstcw () & ~0xC00) | (rc << 10));
493 return 1;
494 #endif
495
496 return 0;
497 }
498
499 /* Return the hardware floating point rounding mode, or -1 if unknown. */
500 int
tests_hardware_getround(void)501 tests_hardware_getround (void)
502 {
503 #if ! defined NO_ASM && HAVE_HOST_CPU_FAMILY_x86
504 switch ((x86_fstcw () & ~0xC00) >> 10) {
505 case 0: return 0; break; /* nearest */
506 case 1: return 3; break; /* down */
507 case 2: return 2; break; /* up */
508 case 3: return 1; break; /* tozero */
509 }
510 #endif
511
512 return -1;
513 }
514
515
516 /* tests_dbl_mant_bits() determines by experiment the number of bits in the
517 mantissa of a "double". If it's not possible to find a value (perhaps
518 due to the compiler optimizing too aggressively), then return 0.
519
520 This code is used rather than DBL_MANT_DIG from <float.h> since ancient
521 systems like SunOS don't have that file, and since one GNU/Linux ARM
522 system was seen where the float emulation seemed to have only 32 working
523 bits, not the 53 float.h claimed. */
524
525 int
tests_dbl_mant_bits(void)526 tests_dbl_mant_bits (void)
527 {
528 static int n = -1;
529 volatile double x, y, d;
530
531 if (n != -1)
532 return n;
533
534 n = 1;
535 x = 2.0;
536 for (;;)
537 {
538 /* see if 2^(n+1)+1 can be formed without rounding, if so then
539 continue, if not then "n" is the answer */
540 y = x + 1.0;
541 d = y - x;
542 if (d != 1.0)
543 {
544 #if defined (DBL_MANT_DIG) && DBL_RADIX == 2
545 if (n != DBL_MANT_DIG)
546 printf ("Warning, tests_dbl_mant_bits got %d but DBL_MANT_DIG says %d\n", n, DBL_MANT_DIG);
547 #endif
548 break;
549 }
550
551 x *= 2;
552 n++;
553
554 if (n > 1000)
555 {
556 printf ("Oops, tests_dbl_mant_bits can't determine mantissa size\n");
557 n = 0;
558 break;
559 }
560 }
561 return n;
562 }
563
564
565 /* See tests_setjmp_sigfpe in tests.h. */
566
567 jmp_buf tests_sigfpe_target;
568
569 RETSIGTYPE
tests_sigfpe_handler(int sig)570 tests_sigfpe_handler (int sig)
571 {
572 longjmp (tests_sigfpe_target, 1);
573 }
574
575 void
tests_sigfpe_done(void)576 tests_sigfpe_done (void)
577 {
578 signal (SIGFPE, SIG_DFL);
579 }
580