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