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