1 /* Miscellaneous test program support routines.
3 Copyright 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
5 This file is part of the GNU MP Library.
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
25 #include <stdlib.h> /* for getenv */
29 #include <float.h> /* for DBL_MANT_DIG */
32 #if TIME_WITH_SYS_TIME
33 # include <sys/time.h> /* for struct timeval */
37 # include <sys/time.h>
48 /* The various tests setups and final checks, collected up together. */
52 /* don't buffer, so output is not lost if a test causes a segv etc */
53 setbuf (stdout, NULL);
54 setbuf (stderr, NULL);
56 tests_memory_start ();
68 tests_rand_start (void)
70 gmp_randstate_ptr rands;
74 if (__gmp_rands_initialized)
76 printf ("Please let tests_start() initialize the global __gmp_rands.\n");
77 printf ("ie. ensure that function is called before the first use of RANDS.\n");
81 gmp_randinit_default (__gmp_rands);
82 __gmp_rands_initialized = 1;
85 perform_seed = getenv ("GMP_CHECK_RANDOMIZE");
86 if (perform_seed != NULL)
89 seed = strtoul (perform_seed, 0, 0);
91 /* This will not work right for seeds >= 2^31 on 64-bit machines.
92 Perhaps use atol unconditionally? Is that ubiquitous? */
93 seed = atoi (perform_seed);
95 if (! (seed == 0 || seed == 1))
97 printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed);
98 gmp_randseed_ui (rands, seed);
102 #if HAVE_GETTIMEOFDAY
104 gettimeofday (&tv, NULL);
105 seed = tv.tv_sec ^ (tv.tv_usec << 12);
112 gmp_randseed_ui (rands, seed);
113 printf ("Seed GMP_CHECK_RANDOMIZE=%lu (include this in bug reports)\n", seed);
119 tests_rand_end (void)
125 /* Only used if CPU calling conventions checking is available. */
126 mp_limb_t (*calling_conventions_function) __GMP_PROTO ((ANYARGS));
129 /* Return p advanced to the next multiple of "align" bytes. "align" must be
130 a power of 2. Care is taken not to assume sizeof(int)==sizeof(pointer).
131 Using "unsigned long" avoids a warning on hpux. */
133 align_pointer (void *p, size_t align)
136 d = ((gmp_intptr_t) p) & (align-1);
137 d = (d != 0 ? align-d : 0);
138 return (void *) (((char *) p) + d);
142 /* Note that memory allocated with this function can never be freed, because
143 the start address of the block allocated is lost. */
145 __gmp_allocate_func_aligned (size_t bytes, size_t align)
147 return align_pointer ((*__gmp_allocate_func) (bytes + align-1), align);
152 __gmp_allocate_or_reallocate (void *ptr, size_t oldsize, size_t newsize)
155 return (*__gmp_allocate_func) (newsize);
157 return (*__gmp_reallocate_func) (ptr, oldsize, newsize);
161 __gmp_allocate_strdup (const char *s)
166 t = (*__gmp_allocate_func) (len+1);
167 memcpy (t, s, len+1);
173 strtoupper (char *s_orig)
176 for (s = s_orig; *s != '\0'; s++)
184 mpz_set_n (mpz_ptr z, mp_srcptr p, mp_size_t size)
187 MPN_NORMALIZE (p, size);
188 MPZ_REALLOC (z, size);
189 MPN_COPY (PTR(z), p, size);
194 mpz_init_set_n (mpz_ptr z, mp_srcptr p, mp_size_t size)
198 MPN_NORMALIZE (p, size);
199 ALLOC(z) = MAX (size, 1);
200 PTR(z) = __GMP_ALLOCATE_FUNC_LIMBS (ALLOC(z));
202 MPN_COPY (PTR(z), p, size);
206 /* Find least significant limb position where p1,size and p2,size differ. */
208 mpn_diff_lowest (mp_srcptr p1, mp_srcptr p2, mp_size_t size)
212 for (i = 0; i < size; i++)
221 /* Find most significant limb position where p1,size and p2,size differ. */
223 mpn_diff_highest (mp_srcptr p1, mp_srcptr p2, mp_size_t size)
227 for (i = size-1; i >= 0; i--)
236 /* Find least significant byte position where p1,size and p2,size differ. */
238 byte_diff_lowest (const void *p1, const void *p2, mp_size_t size)
242 for (i = 0; i < size; i++)
243 if (((const char *) p1)[i] != ((const char *) p2)[i])
251 /* Find most significant limb position where p1,size and p2,size differ. */
253 byte_diff_highest (const void *p1, const void *p2, mp_size_t size)
257 for (i = size-1; i >= 0; i--)
258 if (((const char *) p1)[i] != ((const char *) p2)[i])
267 mpz_set_str_or_abort (mpz_ptr z, const char *str, int base)
269 if (mpz_set_str (z, str, base) != 0)
271 fprintf (stderr, "ERROR: mpz_set_str failed\n");
272 fprintf (stderr, " str = \"%s\"\n", str);
273 fprintf (stderr, " base = %d\n", base);
279 mpq_set_str_or_abort (mpq_ptr q, const char *str, int base)
281 if (mpq_set_str (q, str, base) != 0)
283 fprintf (stderr, "ERROR: mpq_set_str failed\n");
284 fprintf (stderr, " str = \"%s\"\n", str);
285 fprintf (stderr, " base = %d\n", base);
291 mpf_set_str_or_abort (mpf_ptr f, const char *str, int base)
293 if (mpf_set_str (f, str, base) != 0)
295 fprintf (stderr, "ERROR mpf_set_str failed\n");
296 fprintf (stderr, " str = \"%s\"\n", str);
297 fprintf (stderr, " base = %d\n", base);
303 /* Whether the absolute value of z is a power of 2. */
305 mpz_pow2abs_p (mpz_srcptr z)
312 return 0; /* zero is not a power of 2 */
316 for (i = 0; i < size-1; i++)
318 return 0; /* non-zero low limb means not a power of 2 */
320 return POW2_P (ptr[i]); /* high limb power of 2 */
324 /* Exponentially distributed between 0 and 2^nbits-1, meaning the number of
325 bits in the result is uniformly distributed between 0 and nbits-1.
327 FIXME: This is not a proper exponential distribution, since the
328 probability function will have a stepped shape due to using a uniform
329 distribution after choosing how many bits. */
332 mpz_erandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
334 mpz_urandomb (rop, rstate, gmp_urandomm_ui (rstate, nbits));
338 mpz_erandomb_nonzero (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
340 mpz_erandomb (rop, rstate, nbits);
341 if (mpz_sgn (rop) == 0)
342 mpz_set_ui (rop, 1L);
346 mpz_errandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
348 mpz_rrandomb (rop, rstate, gmp_urandomm_ui (rstate, nbits));
352 mpz_errandomb_nonzero (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits)
354 mpz_errandomb (rop, rstate, nbits);
355 if (mpz_sgn (rop) == 0)
356 mpz_set_ui (rop, 1L);
360 mpz_negrandom (mpz_ptr rop, gmp_randstate_t rstate)
363 _gmp_rand (&n, rstate, 1);
371 #if GMP_NAIL_BITS == 0
373 _gmp_rand (&n, RANDS, GMP_LIMB_BITS);
377 _gmp_rand (n, RANDS, GMP_LIMB_BITS);
378 return n[0] + (n[1] << GMP_NUMB_BITS);
383 /* Call (*func)() with various random number generators. */
385 call_rand_algs (void (*func) __GMP_PROTO ((const char *, gmp_randstate_ptr)))
387 gmp_randstate_t rstate;
392 gmp_randinit_default (rstate);
393 (*func) ("gmp_randinit_default", rstate);
394 gmp_randclear (rstate);
396 gmp_randinit_mt (rstate);
397 (*func) ("gmp_randinit_mt", rstate);
398 gmp_randclear (rstate);
400 gmp_randinit_lc_2exp_size (rstate, 8L);
401 (*func) ("gmp_randinit_lc_2exp_size 8", rstate);
402 gmp_randclear (rstate);
404 gmp_randinit_lc_2exp_size (rstate, 16L);
405 (*func) ("gmp_randinit_lc_2exp_size 16", rstate);
406 gmp_randclear (rstate);
408 gmp_randinit_lc_2exp_size (rstate, 128L);
409 (*func) ("gmp_randinit_lc_2exp_size 128", rstate);
410 gmp_randclear (rstate);
412 /* degenerate always zeros */
414 gmp_randinit_lc_2exp (rstate, a, 0L, 8L);
415 (*func) ("gmp_randinit_lc_2exp a=0 c=0 m=8", rstate);
416 gmp_randclear (rstate);
418 /* degenerate always FFs */
420 gmp_randinit_lc_2exp (rstate, a, 0xFFL, 8L);
421 (*func) ("gmp_randinit_lc_2exp a=0 c=0xFF m=8", rstate);
422 gmp_randclear (rstate);
428 /* Return +infinity if available, or 0 if not.
429 We don't want to use libm, so INFINITY or other system values are not
432 tests_infinity_d (void)
435 union ieee_double_extract x;
447 /* Return non-zero if d is an infinity (either positive or negative).
448 Don't want libm, so don't use isinf() or other system tests. */
450 tests_isinf (double d)
453 union ieee_double_extract x;
455 return (x.s.exp == 2047 && x.s.manl == 0 && x.s.manh == 0);
462 /* Set the hardware floating point rounding mode. Same mode values as mpfr,
463 namely 0=nearest, 1=tozero, 2=up, 3=down. Return 1 if successful, 0 if
466 tests_hardware_setround (int mode)
468 #if HAVE_HOST_CPU_FAMILY_x86
471 case 0: rc = 0; break; /* nearest */
472 case 1: rc = 3; break; /* tozero */
473 case 2: rc = 2; break; /* up */
474 case 3: rc = 1; break; /* down */
478 x86_fldcw ((x86_fstcw () & ~0xC00) | (rc << 10));
485 /* Return the hardware floating point rounding mode, or -1 if unknown. */
487 tests_hardware_getround (void)
489 #if HAVE_HOST_CPU_FAMILY_x86
490 switch ((x86_fstcw () & ~0xC00) >> 10) {
491 case 0: return 0; break; /* nearest */
492 case 1: return 3; break; /* down */
493 case 2: return 2; break; /* up */
494 case 3: return 1; break; /* tozero */
502 /* tests_dbl_mant_bits() determines by experiment the number of bits in the
503 mantissa of a "double". If it's not possible to find a value (perhaps
504 due to the compiler optimizing too aggressively), then return 0.
506 This code is used rather than DBL_MANT_DIG from <float.h> since ancient
507 systems like SunOS don't have that file, and since one GNU/Linux ARM
508 system was seen where the float emulation seemed to have only 32 working
509 bits, not the 53 float.h claimed. */
512 tests_dbl_mant_bits (void)
515 volatile double x, y, d;
524 /* see if 2^(n+1)+1 can be formed without rounding, if so then
525 continue, if not then "n" is the answer */
530 #if defined (DBL_MANT_DIG) && DBL_RADIX == 2
531 if (n != DBL_MANT_DIG)
532 printf ("Warning, tests_dbl_mant_bits got %d but DBL_MANT_DIG says %d\n", n, DBL_MANT_DIG);
542 printf ("Oops, tests_dbl_mant_bits can't determine mantissa size\n");
551 /* See tests_setjmp_sigfpe in tests.h. */
553 jmp_buf tests_sigfpe_target;
556 tests_sigfpe_handler (int sig)
558 longjmp (tests_sigfpe_target, 1);
562 tests_sigfpe_done (void)
564 signal (SIGFPE, SIG_DFL);