github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/mpn/t-get_d.c (about) 1 /* Test mpn_get_d. 2 3 Copyright 2002-2004 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 <setjmp.h> 23 #include <signal.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 27 #include "gmp.h" 28 #include "gmp-impl.h" 29 #include "tests.h" 30 31 32 #ifndef _GMP_IEEE_FLOATS 33 #define _GMP_IEEE_FLOATS 0 34 #endif 35 36 37 /* Exercise various 2^n values, with various exponents and positive and 38 negative. */ 39 void 40 check_onebit (void) 41 { 42 static const int bit_table[] = { 43 0, 1, 2, 3, 44 GMP_NUMB_BITS - 2, GMP_NUMB_BITS - 1, 45 GMP_NUMB_BITS, 46 GMP_NUMB_BITS + 1, GMP_NUMB_BITS + 2, 47 2 * GMP_NUMB_BITS - 2, 2 * GMP_NUMB_BITS - 1, 48 2 * GMP_NUMB_BITS, 49 2 * GMP_NUMB_BITS + 1, 2 * GMP_NUMB_BITS + 2, 50 3 * GMP_NUMB_BITS - 2, 3 * GMP_NUMB_BITS - 1, 51 3 * GMP_NUMB_BITS, 52 3 * GMP_NUMB_BITS + 1, 3 * GMP_NUMB_BITS + 2, 53 4 * GMP_NUMB_BITS - 2, 4 * GMP_NUMB_BITS - 1, 54 4 * GMP_NUMB_BITS, 55 4 * GMP_NUMB_BITS + 1, 4 * GMP_NUMB_BITS + 2, 56 5 * GMP_NUMB_BITS - 2, 5 * GMP_NUMB_BITS - 1, 57 5 * GMP_NUMB_BITS, 58 5 * GMP_NUMB_BITS + 1, 5 * GMP_NUMB_BITS + 2, 59 6 * GMP_NUMB_BITS - 2, 6 * GMP_NUMB_BITS - 1, 60 6 * GMP_NUMB_BITS, 61 6 * GMP_NUMB_BITS + 1, 6 * GMP_NUMB_BITS + 2, 62 }; 63 static const int exp_table[] = { 64 0, -100, -10, -1, 1, 10, 100, 65 }; 66 67 /* FIXME: It'd be better to base this on the float format. */ 68 #if defined (__vax) || defined (__vax__) 69 int limit = 127; /* vax fp numbers have limited range */ 70 #else 71 int limit = 511; 72 #endif 73 74 int bit_i, exp_i, i; 75 double got, want; 76 mp_size_t nsize, sign; 77 long bit, exp, want_bit; 78 mp_limb_t np[20]; 79 80 for (bit_i = 0; bit_i < numberof (bit_table); bit_i++) 81 { 82 bit = bit_table[bit_i]; 83 84 nsize = BITS_TO_LIMBS (bit+1); 85 refmpn_zero (np, nsize); 86 np[bit/GMP_NUMB_BITS] = CNST_LIMB(1) << (bit % GMP_NUMB_BITS); 87 88 for (exp_i = 0; exp_i < numberof (exp_table); exp_i++) 89 { 90 exp = exp_table[exp_i]; 91 92 want_bit = bit + exp; 93 if (want_bit >= limit || want_bit <= -limit) 94 continue; 95 96 want = 1.0; 97 for (i = 0; i < want_bit; i++) 98 want *= 2.0; 99 for (i = 0; i > want_bit; i--) 100 want *= 0.5; 101 102 for (sign = 0; sign >= -1; sign--, want = -want) 103 { 104 got = mpn_get_d (np, nsize, sign, exp); 105 if (got != want) 106 { 107 printf ("mpn_get_d wrong on 2^n\n"); 108 printf (" bit %ld\n", bit); 109 printf (" exp %ld\n", exp); 110 printf (" want_bit %ld\n", want_bit); 111 printf (" sign %ld\n", (long) sign); 112 mpn_trace (" n ", np, nsize); 113 printf (" nsize %ld\n", (long) nsize); 114 d_trace (" want ", want); 115 d_trace (" got ", got); 116 abort(); 117 } 118 } 119 } 120 } 121 } 122 123 124 /* Exercise values 2^n+1, while such a value fits the mantissa of a double. */ 125 void 126 check_twobit (void) 127 { 128 int i, mant_bits; 129 double got, want; 130 mp_size_t nsize, sign; 131 mp_ptr np; 132 133 mant_bits = tests_dbl_mant_bits (); 134 if (mant_bits == 0) 135 return; 136 137 np = refmpn_malloc_limbs (BITS_TO_LIMBS (mant_bits)); 138 want = 3.0; 139 for (i = 1; i < mant_bits; i++) 140 { 141 nsize = BITS_TO_LIMBS (i+1); 142 refmpn_zero (np, nsize); 143 np[i/GMP_NUMB_BITS] = CNST_LIMB(1) << (i % GMP_NUMB_BITS); 144 np[0] |= 1; 145 146 for (sign = 0; sign >= -1; sign--) 147 { 148 got = mpn_get_d (np, nsize, sign, 0); 149 if (got != want) 150 { 151 printf ("mpn_get_d wrong on 2^%d + 1\n", i); 152 printf (" sign %ld\n", (long) sign); 153 mpn_trace (" n ", np, nsize); 154 printf (" nsize %ld\n", (long) nsize); 155 d_trace (" want ", want); 156 d_trace (" got ", got); 157 abort(); 158 } 159 want = -want; 160 } 161 162 want = 2.0 * want - 1.0; 163 } 164 165 free (np); 166 } 167 168 169 /* Expect large negative exponents to underflow to 0.0. 170 Some systems might have hardware traps for such an underflow (though 171 usually it's not the default), so watch out for SIGFPE. */ 172 void 173 check_underflow (void) 174 { 175 static const long exp_table[] = { 176 -999999L, LONG_MIN, 177 }; 178 static const mp_limb_t np[1] = { 1 }; 179 180 static long exp; 181 mp_size_t nsize, sign; 182 double got; 183 int exp_i; 184 185 nsize = numberof (np); 186 187 if (tests_setjmp_sigfpe() == 0) 188 { 189 for (exp_i = 0; exp_i < numberof (exp_table); exp_i++) 190 { 191 exp = exp_table[exp_i]; 192 193 for (sign = 0; sign >= -1; sign--) 194 { 195 got = mpn_get_d (np, nsize, sign, exp); 196 if (got != 0.0) 197 { 198 printf ("mpn_get_d wrong, didn't get 0.0 on underflow\n"); 199 printf (" nsize %ld\n", (long) nsize); 200 printf (" exp %ld\n", exp); 201 printf (" sign %ld\n", (long) sign); 202 d_trace (" got ", got); 203 abort (); 204 } 205 } 206 } 207 } 208 else 209 { 210 printf ("Warning, underflow to zero tests skipped due to SIGFPE (exp=%ld)\n", exp); 211 } 212 tests_sigfpe_done (); 213 } 214 215 216 /* Expect large values to result in +/-inf, on IEEE systems. */ 217 void 218 check_inf (void) 219 { 220 static const long exp_table[] = { 221 999999L, LONG_MAX, 222 }; 223 static const mp_limb_t np[4] = { 1, 1, 1, 1 }; 224 long exp; 225 mp_size_t nsize, sign, got_sign; 226 double got; 227 int exp_i; 228 229 if (! _GMP_IEEE_FLOATS) 230 return; 231 232 for (nsize = 1; nsize <= numberof (np); nsize++) 233 { 234 for (exp_i = 0; exp_i < numberof (exp_table); exp_i++) 235 { 236 exp = exp_table[exp_i]; 237 238 for (sign = 0; sign >= -1; sign--) 239 { 240 got = mpn_get_d (np, nsize, sign, exp); 241 got_sign = (got >= 0 ? 0 : -1); 242 if (! tests_isinf (got)) 243 { 244 printf ("mpn_get_d wrong, didn't get infinity\n"); 245 bad: 246 printf (" nsize %ld\n", (long) nsize); 247 printf (" exp %ld\n", exp); 248 printf (" sign %ld\n", (long) sign); 249 d_trace (" got ", got); 250 printf (" got sign %ld\n", (long) got_sign); 251 abort (); 252 } 253 if (got_sign != sign) 254 { 255 printf ("mpn_get_d wrong sign on infinity\n"); 256 goto bad; 257 } 258 } 259 } 260 } 261 } 262 263 /* Check values 2^n approaching and into IEEE denorm range. 264 Some systems might not support denorms, or might have traps setup, so 265 watch out for SIGFPE. */ 266 void 267 check_ieee_denorm (void) 268 { 269 static long exp; 270 mp_limb_t n = 1; 271 long i; 272 mp_size_t sign; 273 double want, got; 274 275 if (! _GMP_IEEE_FLOATS) 276 return; 277 278 if (tests_setjmp_sigfpe() == 0) 279 { 280 exp = -1020; 281 want = 1.0; 282 for (i = 0; i > exp; i--) 283 want *= 0.5; 284 285 for ( ; exp > -1500 && want != 0.0; exp--) 286 { 287 for (sign = 0; sign >= -1; sign--) 288 { 289 got = mpn_get_d (&n, (mp_size_t) 1, sign, exp); 290 if (got != want) 291 { 292 printf ("mpn_get_d wrong on denorm\n"); 293 printf (" n=1\n"); 294 printf (" exp %ld\n", exp); 295 printf (" sign %ld\n", (long) sign); 296 d_trace (" got ", got); 297 d_trace (" want ", want); 298 abort (); 299 } 300 want = -want; 301 } 302 want *= 0.5; 303 FORCE_DOUBLE (want); 304 } 305 } 306 else 307 { 308 printf ("Warning, IEEE denorm tests skipped due to SIGFPE (exp=%ld)\n", exp); 309 } 310 tests_sigfpe_done (); 311 } 312 313 314 /* Check values 2^n approaching exponent overflow. 315 Some systems might trap on overflow, so watch out for SIGFPE. */ 316 void 317 check_ieee_overflow (void) 318 { 319 static long exp; 320 mp_limb_t n = 1; 321 long i; 322 mp_size_t sign; 323 double want, got; 324 325 if (! _GMP_IEEE_FLOATS) 326 return; 327 328 if (tests_setjmp_sigfpe() == 0) 329 { 330 exp = 1010; 331 want = 1.0; 332 for (i = 0; i < exp; i++) 333 want *= 2.0; 334 335 for ( ; exp < 1050; exp++) 336 { 337 for (sign = 0; sign >= -1; sign--) 338 { 339 got = mpn_get_d (&n, (mp_size_t) 1, sign, exp); 340 if (got != want) 341 { 342 printf ("mpn_get_d wrong on overflow\n"); 343 printf (" n=1\n"); 344 printf (" exp %ld\n", exp); 345 printf (" sign %ld\n", (long) sign); 346 d_trace (" got ", got); 347 d_trace (" want ", want); 348 abort (); 349 } 350 want = -want; 351 } 352 want *= 2.0; 353 FORCE_DOUBLE (want); 354 } 355 } 356 else 357 { 358 printf ("Warning, IEEE overflow tests skipped due to SIGFPE (exp=%ld)\n", exp); 359 } 360 tests_sigfpe_done (); 361 } 362 363 364 /* ARM gcc 2.95.4 was seen generating bad code for ulong->double 365 conversions, resulting in for instance 0x81c25113 incorrectly converted. 366 This test exercises that value, to see mpn_get_d has avoided the 367 problem. */ 368 void 369 check_0x81c25113 (void) 370 { 371 #if GMP_NUMB_BITS >= 32 372 double want = 2176995603.0; 373 double got; 374 mp_limb_t np[4]; 375 mp_size_t nsize; 376 long exp; 377 378 if (tests_dbl_mant_bits() < 32) 379 return; 380 381 for (nsize = 1; nsize <= numberof (np); nsize++) 382 { 383 refmpn_zero (np, nsize-1); 384 np[nsize-1] = CNST_LIMB(0x81c25113); 385 exp = - (nsize-1) * GMP_NUMB_BITS; 386 got = mpn_get_d (np, nsize, (mp_size_t) 0, exp); 387 if (got != want) 388 { 389 printf ("mpn_get_d wrong on 2176995603 (0x81c25113)\n"); 390 printf (" nsize %ld\n", (long) nsize); 391 printf (" exp %ld\n", exp); 392 d_trace (" got ", got); 393 d_trace (" want ", want); 394 abort (); 395 } 396 } 397 #endif 398 } 399 400 401 void 402 check_rand (void) 403 { 404 gmp_randstate_ptr rands = RANDS; 405 int rep, i; 406 unsigned long mant_bits; 407 long exp, exp_min, exp_max; 408 double got, want, d; 409 mp_size_t nalloc, nsize, sign; 410 mp_limb_t nhigh_mask; 411 mp_ptr np; 412 413 mant_bits = tests_dbl_mant_bits (); 414 if (mant_bits == 0) 415 return; 416 417 /* Allow for vax D format with exponent 127 to -128 only. 418 FIXME: Do something to probe for a valid exponent range. */ 419 exp_min = -100 - mant_bits; 420 exp_max = 100 - mant_bits; 421 422 /* space for mant_bits */ 423 nalloc = BITS_TO_LIMBS (mant_bits); 424 np = refmpn_malloc_limbs (nalloc); 425 nhigh_mask = MP_LIMB_T_MAX 426 >> (GMP_NAIL_BITS + nalloc * GMP_NUMB_BITS - mant_bits); 427 428 for (rep = 0; rep < 200; rep++) 429 { 430 /* random exp_min to exp_max, inclusive */ 431 exp = exp_min + (long) gmp_urandomm_ui (rands, exp_max - exp_min + 1); 432 433 /* mant_bits worth of random at np */ 434 if (rep & 1) 435 mpn_random (np, nalloc); 436 else 437 mpn_random2 (np, nalloc); 438 nsize = nalloc; 439 np[nsize-1] &= nhigh_mask; 440 MPN_NORMALIZE (np, nsize); 441 if (nsize == 0) 442 continue; 443 444 sign = (mp_size_t) gmp_urandomb_ui (rands, 1L) - 1; 445 446 /* want = {np,nsize}, converting one bit at a time */ 447 want = 0.0; 448 for (i = 0, d = 1.0; i < mant_bits; i++, d *= 2.0) 449 if (np[i/GMP_NUMB_BITS] & (CNST_LIMB(1) << (i%GMP_NUMB_BITS))) 450 want += d; 451 if (sign < 0) 452 want = -want; 453 454 /* want = want * 2^exp */ 455 for (i = 0; i < exp; i++) 456 want *= 2.0; 457 for (i = 0; i > exp; i--) 458 want *= 0.5; 459 460 got = mpn_get_d (np, nsize, sign, exp); 461 462 if (got != want) 463 { 464 printf ("mpn_get_d wrong on random data\n"); 465 printf (" sign %ld\n", (long) sign); 466 mpn_trace (" n ", np, nsize); 467 printf (" nsize %ld\n", (long) nsize); 468 printf (" exp %ld\n", exp); 469 d_trace (" want ", want); 470 d_trace (" got ", got); 471 abort(); 472 } 473 } 474 475 free (np); 476 } 477 478 479 int 480 main (void) 481 { 482 tests_start (); 483 mp_trace_base = -16; 484 485 check_onebit (); 486 check_twobit (); 487 check_inf (); 488 check_underflow (); 489 check_ieee_denorm (); 490 check_ieee_overflow (); 491 check_0x81c25113 (); 492 #if ! (defined (__vax) || defined (__vax__)) 493 check_rand (); 494 #endif 495 496 tests_end (); 497 exit (0); 498 }