1 /* Miscellaneous test program support routines. 2 3 Copyright 2000, 2001, 2002, 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 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. */ 49 void 50 tests_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 } 59 void 60 tests_end (void) 61 { 62 tests_rand_end (); 63 tests_memory_end (); 64 } 65 66 67 void 68 tests_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 } 118 void 119 tests_rand_end (void) 120 { 121 RANDS_CLEAR (); 122 } 123 124 125 /* Only used if CPU calling conventions checking is available. */ 126 mp_limb_t (*calling_conventions_function) (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. */ 132 void * 133 align_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. */ 144 void * 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 151 void * 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 160 char * 161 __gmp_allocate_strdup (const char *s) 162 { 163 size_t len; 164 char *t; 165 len = strlen (s); 166 t = (char *) (*__gmp_allocate_func) (len+1); 167 memcpy (t, s, len+1); 168 return t; 169 } 170 171 172 char * 173 strtoupper (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 183 void 184 mpz_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 193 void 194 mpz_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. */ 207 mp_size_t 208 mpn_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. */ 222 mp_size_t 223 mpn_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. */ 237 mp_size_t 238 byte_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. */ 252 mp_size_t 253 byte_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 266 void 267 mpz_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 278 void 279 mpq_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 290 void 291 mpf_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. */ 304 int 305 mpz_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 331 void 332 mpz_erandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits) 333 { 334 mpz_urandomb (rop, rstate, gmp_urandomm_ui (rstate, nbits)); 335 } 336 337 void 338 mpz_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 345 void 346 mpz_errandomb (mpz_ptr rop, gmp_randstate_t rstate, unsigned long nbits) 347 { 348 mpz_rrandomb (rop, rstate, gmp_urandomm_ui (rstate, nbits)); 349 } 350 351 void 352 mpz_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 359 void 360 mpz_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 368 mp_limb_t 369 urandom (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. */ 384 void 385 call_rand_algs (void (*func) (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. */ 431 double 432 tests_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. */ 449 int 450 tests_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. */ 465 int 466 tests_hardware_setround (int mode) 467 { 468 #if WANT_ASSEMBLY && 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. */ 486 int 487 tests_hardware_getround (void) 488 { 489 #if WANT_ASSEMBLY && 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 511 int 512 tests_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 553 jmp_buf tests_sigfpe_target; 554 555 RETSIGTYPE 556 tests_sigfpe_handler (int sig) 557 { 558 longjmp (tests_sigfpe_target, 1); 559 } 560 561 void 562 tests_sigfpe_done (void) 563 { 564 signal (SIGFPE, SIG_DFL); 565 } 566