1/* Miscellaneous test program support routines. 2 3Copyright 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library. 6 7The GNU MP Library is free software; you can redistribute it and/or modify 8it under the terms of the GNU Lesser General Public License as published by 9the Free Software Foundation; either version 3 of the License, or (at your 10option) any later version. 11 12The GNU MP Library is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15License for more details. 16 17You should have received a copy of the GNU Lesser General Public License 18along with the GNU MP Library. If not, see http://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. */ 49void 50tests_start (void) 51{ 52 /* don't buffer, so output is not lost if a test causes a segv etc */ 53 setbuf (stdout, NULL); 54 setbuf (stderr, NULL); 55 56 tests_memory_start (); 57 tests_rand_start (); 58} 59void 60tests_end (void) 61{ 62 tests_rand_end (); 63 tests_memory_end (); 64} 65 66 67void 68tests_rand_start (void) 69{ 70 gmp_randstate_ptr rands; 71 char *perform_seed; 72 unsigned long seed; 73 74 if (__gmp_rands_initialized) 75 { 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"); 78 abort (); 79 } 80 81 gmp_randinit_default (__gmp_rands); 82 __gmp_rands_initialized = 1; 83 rands = __gmp_rands; 84 85 perform_seed = getenv ("GMP_CHECK_RANDOMIZE"); 86 if (perform_seed != NULL) 87 { 88#ifdef HAVE_STRTOUL 89 seed = strtoul (perform_seed, 0, 0); 90#else 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); 94#endif 95 if (! (seed == 0 || seed == 1)) 96 { 97 printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed); 98 gmp_randseed_ui (rands, seed); 99 } 100 else 101 { 102#if HAVE_GETTIMEOFDAY 103 struct timeval tv; 104 gettimeofday (&tv, NULL); 105 seed = tv.tv_sec ^ (tv.tv_usec << 12); 106 seed &= 0xffffffff; 107#else 108 time_t tv; 109 time (&tv); 110 seed = tv; 111#endif 112 gmp_randseed_ui (rands, seed); 113 printf ("Seed GMP_CHECK_RANDOMIZE=%lu (include this in bug reports)\n", seed); 114 } 115 fflush (stdout); 116 } 117} 118void 119tests_rand_end (void) 120{ 121 RANDS_CLEAR (); 122} 123 124 125/* Only used if CPU calling conventions checking is available. */ 126mp_limb_t (*calling_conventions_function) __GMP_PROTO ((ANYARGS)); 127 128 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. */ 132void * 133align_pointer (void *p, size_t align) 134{ 135 gmp_intptr_t d; 136 d = ((gmp_intptr_t) p) & (align-1); 137 d = (d != 0 ? align-d : 0); 138 return (void *) (((char *) p) + d); 139} 140 141 142/* Note that memory allocated with this function can never be freed, because 143 the start address of the block allocated is lost. */ 144void * 145__gmp_allocate_func_aligned (size_t bytes, size_t align) 146{ 147 return align_pointer ((*__gmp_allocate_func) (bytes + align-1), align); 148} 149 150 151void * 152__gmp_allocate_or_reallocate (void *ptr, size_t oldsize, size_t newsize) 153{ 154 if (ptr == NULL) 155 return (*__gmp_allocate_func) (newsize); 156 else 157 return (*__gmp_reallocate_func) (ptr, oldsize, newsize); 158} 159 160char * 161__gmp_allocate_strdup (const char *s) 162{ 163 size_t len; 164 char *t; 165 len = strlen (s); 166 t = (*__gmp_allocate_func) (len+1); 167 memcpy (t, s, len+1); 168 return t; 169} 170 171 172char * 173strtoupper (char *s_orig) 174{ 175 char *s; 176 for (s = s_orig; *s != '\0'; s++) 177 if (isascii (*s)) 178 *s = toupper (*s); 179 return s_orig; 180} 181 182 183void 184mpz_set_n (mpz_ptr z, mp_srcptr p, mp_size_t size) 185{ 186 ASSERT (size >= 0); 187 MPN_NORMALIZE (p, size); 188 MPZ_REALLOC (z, size); 189 MPN_COPY (PTR(z), p, size); 190 SIZ(z) = size; 191} 192 193void 194mpz_init_set_n (mpz_ptr z, mp_srcptr p, mp_size_t size) 195{ 196 ASSERT (size >= 0); 197 198 MPN_NORMALIZE (p, size); 199 ALLOC(z) = MAX (size, 1); 200 PTR(z) = __GMP_ALLOCATE_FUNC_LIMBS (ALLOC(z)); 201 SIZ(z) = size; 202 MPN_COPY (PTR(z), p, size); 203} 204 205 206/* Find least significant limb position where p1,size and p2,size differ. */ 207mp_size_t 208mpn_diff_lowest (mp_srcptr p1, mp_srcptr p2, mp_size_t size) 209{ 210 mp_size_t i; 211 212 for (i = 0; i < size; i++) 213 if (p1[i] != p2[i]) 214 return i; 215 216 /* no differences */ 217 return -1; 218} 219 220 221/* Find most significant limb position where p1,size and p2,size differ. */ 222mp_size_t 223mpn_diff_highest (mp_srcptr p1, mp_srcptr p2, mp_size_t size) 224{ 225 mp_size_t i; 226 227 for (i = size-1; i >= 0; i--) 228 if (p1[i] != p2[i]) 229 return i; 230 231 /* no differences */ 232 return -1; 233} 234 235 236/* Find least significant byte position where p1,size and p2,size differ. */ 237mp_size_t 238byte_diff_lowest (const void *p1, const void *p2, mp_size_t size) 239{ 240 mp_size_t i; 241 242 for (i = 0; i < size; i++) 243 if (((const char *) p1)[i] != ((const char *) p2)[i]) 244 return i; 245 246 /* no differences */ 247 return -1; 248} 249 250 251/* Find most significant limb position where p1,size and p2,size differ. */ 252mp_size_t 253byte_diff_highest (const void *p1, const void *p2, mp_size_t size) 254{ 255 mp_size_t i; 256 257 for (i = size-1; i >= 0; i--) 258 if (((const char *) p1)[i] != ((const char *) p2)[i]) 259 return i; 260 261 /* no differences */ 262 return -1; 263} 264 265 266void 267mpz_set_str_or_abort (mpz_ptr z, const char *str, int base) 268{ 269 if (mpz_set_str (z, str, base) != 0) 270 { 271 fprintf (stderr, "ERROR: mpz_set_str failed\n"); 272 fprintf (stderr, " str = \"%s\"\n", str); 273 fprintf (stderr, " base = %d\n", base); 274 abort(); 275 } 276} 277 278void 279mpq_set_str_or_abort (mpq_ptr q, const char *str, int base) 280{ 281 if (mpq_set_str (q, str, base) != 0) 282 { 283 fprintf (stderr, "ERROR: mpq_set_str failed\n"); 284 fprintf (stderr, " str = \"%s\"\n", str); 285 fprintf (stderr, " base = %d\n", base); 286 abort(); 287 } 288} 289 290void 291mpf_set_str_or_abort (mpf_ptr f, const char *str, int base) 292{ 293 if (mpf_set_str (f, str, base) != 0) 294 { 295 fprintf (stderr, "ERROR mpf_set_str failed\n"); 296 fprintf (stderr, " str = \"%s\"\n", str); 297 fprintf (stderr, " base = %d\n", base); 298 abort(); 299 } 300} 301 302 303/* Whether the absolute value of z is a power of 2. */ 304int 305mpz_pow2abs_p (mpz_srcptr z) 306{ 307 mp_size_t size, i; 308 mp_srcptr ptr; 309 310 size = SIZ (z); 311 if (size == 0) 312 return 0; /* zero is not a power of 2 */ 313 size = ABS (size); 314 315 ptr = PTR (z); 316 for (i = 0; i < size-1; i++) 317 if (ptr[i] != 0) 318 return 0; /* non-zero low limb means not a power of 2 */ 319 320 return POW2_P (ptr[i]); /* high limb power of 2 */ 321} 322 323 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. 326 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. */ 330 331void 332mpz_erandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits) 333{ 334 mpz_urandomb (rop, rstate, gmp_urandomm_ui (rstate, nbits)); 335} 336 337void 338mpz_erandomb_nonzero (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits) 339{ 340 mpz_erandomb (rop, rstate, nbits); 341 if (mpz_sgn (rop) == 0) 342 mpz_set_ui (rop, 1L); 343} 344 345void 346mpz_errandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits) 347{ 348 mpz_rrandomb (rop, rstate, gmp_urandomm_ui (rstate, nbits)); 349} 350 351void 352mpz_errandomb_nonzero (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits) 353{ 354 mpz_errandomb (rop, rstate, nbits); 355 if (mpz_sgn (rop) == 0) 356 mpz_set_ui (rop, 1L); 357} 358 359void 360mpz_negrandom (mpz_ptr rop, gmp_randstate_t rstate) 361{ 362 mp_limb_t n; 363 _gmp_rand (&n, rstate, 1); 364 if (n != 0) 365 mpz_neg (rop, rop); 366} 367 368mp_limb_t 369urandom (void) 370{ 371#if GMP_NAIL_BITS == 0 372 mp_limb_t n; 373 _gmp_rand (&n, RANDS, GMP_LIMB_BITS); 374 return n; 375#else 376 mp_limb_t n[2]; 377 _gmp_rand (n, RANDS, GMP_LIMB_BITS); 378 return n[0] + (n[1] << GMP_NUMB_BITS); 379#endif 380} 381 382 383/* Call (*func)() with various random number generators. */ 384void 385call_rand_algs (void (*func) __GMP_PROTO ((const char *, gmp_randstate_ptr))) 386{ 387 gmp_randstate_t rstate; 388 mpz_t a; 389 390 mpz_init (a); 391 392 gmp_randinit_default (rstate); 393 (*func) ("gmp_randinit_default", rstate); 394 gmp_randclear (rstate); 395 396 gmp_randinit_mt (rstate); 397 (*func) ("gmp_randinit_mt", rstate); 398 gmp_randclear (rstate); 399 400 gmp_randinit_lc_2exp_size (rstate, 8L); 401 (*func) ("gmp_randinit_lc_2exp_size 8", rstate); 402 gmp_randclear (rstate); 403 404 gmp_randinit_lc_2exp_size (rstate, 16L); 405 (*func) ("gmp_randinit_lc_2exp_size 16", rstate); 406 gmp_randclear (rstate); 407 408 gmp_randinit_lc_2exp_size (rstate, 128L); 409 (*func) ("gmp_randinit_lc_2exp_size 128", rstate); 410 gmp_randclear (rstate); 411 412 /* degenerate always zeros */ 413 mpz_set_ui (a, 0L); 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); 417 418 /* degenerate always FFs */ 419 mpz_set_ui (a, 0L); 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); 423 424 mpz_clear (a); 425} 426 427 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 430 used here. */ 431double 432tests_infinity_d (void) 433{ 434#if _GMP_IEEE_FLOATS 435 union ieee_double_extract x; 436 x.s.exp = 2047; 437 x.s.manl = 0; 438 x.s.manh = 0; 439 x.s.sig = 0; 440 return x.d; 441#else 442 return 0; 443#endif 444} 445 446 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. */ 449int 450tests_isinf (double d) 451{ 452#if _GMP_IEEE_FLOATS 453 union ieee_double_extract x; 454 x.d = d; 455 return (x.s.exp == 2047 && x.s.manl == 0 && x.s.manh == 0); 456#else 457 return 0; 458#endif 459} 460 461 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 464 not. */ 465int 466tests_hardware_setround (int mode) 467{ 468#if HAVE_HOST_CPU_FAMILY_x86 469 int rc; 470 switch (mode) { 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 */ 475 default: 476 return 0; 477 } 478 x86_fldcw ((x86_fstcw () & ~0xC00) | (rc << 10)); 479 return 1; 480#endif 481 482 return 0; 483} 484 485/* Return the hardware floating point rounding mode, or -1 if unknown. */ 486int 487tests_hardware_getround (void) 488{ 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 */ 495 } 496#endif 497 498 return -1; 499} 500 501 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. 505 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. */ 510 511int 512tests_dbl_mant_bits (void) 513{ 514 static int n = -1; 515 volatile double x, y, d; 516 517 if (n != -1) 518 return n; 519 520 n = 1; 521 x = 2.0; 522 for (;;) 523 { 524 /* see if 2^(n+1)+1 can be formed without rounding, if so then 525 continue, if not then "n" is the answer */ 526 y = x + 1.0; 527 d = y - x; 528 if (d != 1.0) 529 { 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); 533#endif 534 break; 535 } 536 537 x *= 2; 538 n++; 539 540 if (n > 1000) 541 { 542 printf ("Oops, tests_dbl_mant_bits can't determine mantissa size\n"); 543 n = 0; 544 break; 545 } 546 } 547 return n; 548} 549 550 551/* See tests_setjmp_sigfpe in tests.h. */ 552 553jmp_buf tests_sigfpe_target; 554 555RETSIGTYPE 556tests_sigfpe_handler (int sig) 557{ 558 longjmp (tests_sigfpe_target, 1); 559} 560 561void 562tests_sigfpe_done (void) 563{ 564 signal (SIGFPE, SIG_DFL); 565} 566