1 /* Exception flags and utilities. Constructors and destructors (debug). 2 3 Copyright 2001-2020 Free Software Foundation, Inc. 4 Contributed by the AriC and Caramba projects, INRIA. 5 6 This file is part of the GNU MPFR Library. 7 8 The GNU MPFR Library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU Lesser General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or (at your 11 option) any later version. 12 13 The GNU MPFR Library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23 #include "mpfr-impl.h" 24 25 MPFR_THREAD_VAR (mpfr_flags_t, __gmpfr_flags, 0) 26 MPFR_THREAD_VAR (mpfr_exp_t, __gmpfr_emin, MPFR_EMIN_DEFAULT) 27 MPFR_THREAD_VAR (mpfr_exp_t, __gmpfr_emax, MPFR_EMAX_DEFAULT) 28 29 #undef mpfr_get_emin 30 31 MPFR_COLD_FUNCTION_ATTR mpfr_exp_t 32 mpfr_get_emin (void) 33 { 34 return __gmpfr_emin; 35 } 36 37 #undef mpfr_set_emin 38 39 int 40 mpfr_set_emin (mpfr_exp_t exponent) 41 { 42 if (MPFR_LIKELY (exponent >= MPFR_EMIN_MIN && exponent <= MPFR_EMIN_MAX)) 43 { 44 __gmpfr_emin = exponent; 45 return 0; 46 } 47 else 48 { 49 return 1; 50 } 51 } 52 53 MPFR_COLD_FUNCTION_ATTR mpfr_exp_t 54 mpfr_get_emin_min (void) 55 { 56 return MPFR_EMIN_MIN; 57 } 58 59 MPFR_COLD_FUNCTION_ATTR mpfr_exp_t 60 mpfr_get_emin_max (void) 61 { 62 return MPFR_EMIN_MAX; 63 } 64 65 #undef mpfr_get_emax 66 67 MPFR_COLD_FUNCTION_ATTR mpfr_exp_t 68 mpfr_get_emax (void) 69 { 70 return __gmpfr_emax; 71 } 72 73 #undef mpfr_set_emax 74 75 int 76 mpfr_set_emax (mpfr_exp_t exponent) 77 { 78 if (MPFR_LIKELY (exponent >= MPFR_EMAX_MIN && exponent <= MPFR_EMAX_MAX)) 79 { 80 __gmpfr_emax = exponent; 81 return 0; 82 } 83 else 84 { 85 return 1; 86 } 87 } 88 89 MPFR_COLD_FUNCTION_ATTR mpfr_exp_t 90 mpfr_get_emax_min (void) 91 { 92 return MPFR_EMAX_MIN; 93 } 94 95 MPFR_COLD_FUNCTION_ATTR mpfr_exp_t 96 mpfr_get_emax_max (void) 97 { 98 return MPFR_EMAX_MAX; 99 } 100 101 102 #undef mpfr_flags_clear 103 104 MPFR_COLD_FUNCTION_ATTR void 105 mpfr_flags_clear (mpfr_flags_t mask) 106 { 107 __gmpfr_flags &= MPFR_FLAGS_ALL ^ mask; 108 } 109 110 #undef mpfr_flags_set 111 112 MPFR_COLD_FUNCTION_ATTR void 113 mpfr_flags_set (mpfr_flags_t mask) 114 { 115 __gmpfr_flags |= mask; 116 } 117 118 #undef mpfr_flags_test 119 120 MPFR_COLD_FUNCTION_ATTR mpfr_flags_t 121 mpfr_flags_test (mpfr_flags_t mask) 122 { 123 return __gmpfr_flags & mask; 124 } 125 126 #undef mpfr_flags_save 127 128 MPFR_COLD_FUNCTION_ATTR mpfr_flags_t 129 mpfr_flags_save (void) 130 { 131 return __gmpfr_flags; 132 } 133 134 #undef mpfr_flags_restore 135 136 MPFR_COLD_FUNCTION_ATTR void 137 mpfr_flags_restore (mpfr_flags_t flags, mpfr_flags_t mask) 138 { 139 __gmpfr_flags = 140 (__gmpfr_flags & (MPFR_FLAGS_ALL ^ mask)) | 141 (flags & mask); 142 } 143 144 145 #undef mpfr_clear_flags 146 147 void 148 mpfr_clear_flags (void) 149 { 150 __gmpfr_flags = 0; 151 } 152 153 #undef mpfr_clear_underflow 154 155 MPFR_COLD_FUNCTION_ATTR void 156 mpfr_clear_underflow (void) 157 { 158 __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_UNDERFLOW; 159 } 160 161 #undef mpfr_clear_overflow 162 163 MPFR_COLD_FUNCTION_ATTR void 164 mpfr_clear_overflow (void) 165 { 166 __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_OVERFLOW; 167 } 168 169 #undef mpfr_clear_divby0 170 171 MPFR_COLD_FUNCTION_ATTR void 172 mpfr_clear_divby0 (void) 173 { 174 __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_DIVBY0; 175 } 176 177 #undef mpfr_clear_nanflag 178 179 MPFR_COLD_FUNCTION_ATTR void 180 mpfr_clear_nanflag (void) 181 { 182 __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_NAN; 183 } 184 185 #undef mpfr_clear_inexflag 186 187 MPFR_COLD_FUNCTION_ATTR void 188 mpfr_clear_inexflag (void) 189 { 190 __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_INEXACT; 191 } 192 193 #undef mpfr_clear_erangeflag 194 195 MPFR_COLD_FUNCTION_ATTR void 196 mpfr_clear_erangeflag (void) 197 { 198 __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE; 199 } 200 201 #undef mpfr_set_underflow 202 203 MPFR_COLD_FUNCTION_ATTR void 204 mpfr_set_underflow (void) 205 { 206 __gmpfr_flags |= MPFR_FLAGS_UNDERFLOW; 207 } 208 209 #undef mpfr_set_overflow 210 211 MPFR_COLD_FUNCTION_ATTR void 212 mpfr_set_overflow (void) 213 { 214 __gmpfr_flags |= MPFR_FLAGS_OVERFLOW; 215 } 216 217 #undef mpfr_set_divby0 218 219 MPFR_COLD_FUNCTION_ATTR void 220 mpfr_set_divby0 (void) 221 { 222 __gmpfr_flags |= MPFR_FLAGS_DIVBY0; 223 } 224 225 #undef mpfr_set_nanflag 226 227 MPFR_COLD_FUNCTION_ATTR void 228 mpfr_set_nanflag (void) 229 { 230 __gmpfr_flags |= MPFR_FLAGS_NAN; 231 } 232 233 #undef mpfr_set_inexflag 234 235 MPFR_COLD_FUNCTION_ATTR void 236 mpfr_set_inexflag (void) 237 { 238 __gmpfr_flags |= MPFR_FLAGS_INEXACT; 239 } 240 241 #undef mpfr_set_erangeflag 242 243 MPFR_COLD_FUNCTION_ATTR void 244 mpfr_set_erangeflag (void) 245 { 246 __gmpfr_flags |= MPFR_FLAGS_ERANGE; 247 } 248 249 250 #undef mpfr_check_range 251 252 /* Note: It is possible that for pure FP numbers, EXP(x) < MPFR_EMIN_MIN, 253 but the caller must make sure that the difference remains small enough 254 to avoid reaching the special exponent values. */ 255 int 256 mpfr_check_range (mpfr_ptr x, int t, mpfr_rnd_t rnd_mode) 257 { 258 if (MPFR_LIKELY (! MPFR_IS_SINGULAR (x))) 259 { /* x is a non-zero FP */ 260 mpfr_exp_t exp = MPFR_EXP (x); /* Do not use MPFR_GET_EXP */ 261 262 MPFR_ASSERTD (MPFR_IS_NORMALIZED (x)); 263 if (MPFR_UNLIKELY (exp < __gmpfr_emin)) 264 { 265 /* The following test is necessary because in the rounding to the 266 * nearest mode, mpfr_underflow always rounds away from 0. In 267 * this rounding mode, we need to round to 0 if: 268 * _ |x| < 2^(emin-2), or 269 * _ |x| = 2^(emin-2) and the absolute value of the exact 270 * result is <= 2^(emin-2). 271 */ 272 if (rnd_mode == MPFR_RNDN && 273 (exp + 1 < __gmpfr_emin || 274 (mpfr_powerof2_raw(x) && 275 (MPFR_IS_NEG(x) ? t <= 0 : t >= 0)))) 276 rnd_mode = MPFR_RNDZ; 277 return mpfr_underflow (x, rnd_mode, MPFR_SIGN(x)); 278 } 279 if (MPFR_UNLIKELY (exp > __gmpfr_emax)) 280 return mpfr_overflow (x, rnd_mode, MPFR_SIGN(x)); 281 } 282 else if (MPFR_UNLIKELY (t != 0 && MPFR_IS_INF (x))) 283 { 284 /* We need to do the following because most MPFR functions are 285 * implemented in the following way: 286 * Ziv's loop: 287 * | Compute an approximation to the result and an error bound. 288 * | Possible underflow/overflow detection -> return. 289 * | If can_round, break (exit the loop). 290 * | Otherwise, increase the working precision and loop. 291 * Round the approximation in the target precision. <== See below 292 * Restore the flags (that could have been set due to underflows 293 * or overflows during the internal computations). 294 * Execute: return mpfr_check_range (...). 295 * The problem is that an overflow could be generated when rounding the 296 * approximation (in general, such an overflow could not be detected 297 * earlier), and the overflow flag is lost when the flags are restored. 298 * This can occur only when the rounding yields an exponent change 299 * and the new exponent is larger than the maximum exponent, so that 300 * an infinity is necessarily obtained. 301 * So, the simplest solution is to detect this overflow case here in 302 * mpfr_check_range, which is easy to do since the rounded result is 303 * necessarily an inexact infinity. 304 */ 305 __gmpfr_flags |= MPFR_FLAGS_OVERFLOW; 306 } 307 MPFR_RET (t); /* propagate inexact ternary value, unlike most functions */ 308 } 309 310 311 #undef mpfr_underflow_p 312 313 MPFR_COLD_FUNCTION_ATTR int 314 mpfr_underflow_p (void) 315 { 316 MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_UNDERFLOW <= INT_MAX); 317 return __gmpfr_flags & MPFR_FLAGS_UNDERFLOW; 318 } 319 320 #undef mpfr_overflow_p 321 322 MPFR_COLD_FUNCTION_ATTR int 323 mpfr_overflow_p (void) 324 { 325 MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_OVERFLOW <= INT_MAX); 326 return __gmpfr_flags & MPFR_FLAGS_OVERFLOW; 327 } 328 329 #undef mpfr_divby0_p 330 331 MPFR_COLD_FUNCTION_ATTR int 332 mpfr_divby0_p (void) 333 { 334 MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_DIVBY0 <= INT_MAX); 335 return __gmpfr_flags & MPFR_FLAGS_DIVBY0; 336 } 337 338 #undef mpfr_nanflag_p 339 340 MPFR_COLD_FUNCTION_ATTR int 341 mpfr_nanflag_p (void) 342 { 343 MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_NAN <= INT_MAX); 344 return __gmpfr_flags & MPFR_FLAGS_NAN; 345 } 346 347 #undef mpfr_inexflag_p 348 349 MPFR_COLD_FUNCTION_ATTR int 350 mpfr_inexflag_p (void) 351 { 352 MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_INEXACT <= INT_MAX); 353 return __gmpfr_flags & MPFR_FLAGS_INEXACT; 354 } 355 356 #undef mpfr_erangeflag_p 357 358 MPFR_COLD_FUNCTION_ATTR int 359 mpfr_erangeflag_p (void) 360 { 361 MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_ERANGE <= INT_MAX); 362 return __gmpfr_flags & MPFR_FLAGS_ERANGE; 363 } 364 365 366 /* #undef mpfr_underflow */ 367 368 /* Note: In the rounding to the nearest mode, mpfr_underflow 369 always rounds away from 0. In this rounding mode, you must call 370 mpfr_underflow with rnd_mode = MPFR_RNDZ if the exact result 371 is <= 2^(emin-2) in absolute value. 372 We chose the default to round away from zero instead of toward zero 373 because rounding away from zero (MPFR_RNDA) wasn't supported at that 374 time (r1910), so that the caller had no way to change rnd_mode to 375 this mode. */ 376 377 MPFR_COLD_FUNCTION_ATTR int 378 mpfr_underflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign) 379 { 380 int inex; 381 382 MPFR_LOG_FUNC 383 (("rnd=%d sign=%d", rnd_mode, sign), 384 ("x[%Pu]=%.*Rg", mpfr_get_prec (x), mpfr_log_prec, x)); 385 386 MPFR_ASSERT_SIGN (sign); 387 388 if (MPFR_IS_LIKE_RNDZ(rnd_mode, sign < 0)) 389 { 390 MPFR_SET_ZERO(x); 391 inex = -1; 392 } 393 else 394 { 395 mpfr_setmin (x, __gmpfr_emin); 396 inex = 1; 397 } 398 MPFR_SET_SIGN(x, sign); 399 __gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW; 400 return sign > 0 ? inex : -inex; 401 } 402 403 /* #undef mpfr_overflow */ 404 405 MPFR_COLD_FUNCTION_ATTR int 406 mpfr_overflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign) 407 { 408 int inex; 409 410 MPFR_LOG_FUNC 411 (("rnd=%d sign=%d", rnd_mode, sign), 412 ("x[%Pu]=%.*Rg", mpfr_get_prec (x), mpfr_log_prec, x)); 413 414 MPFR_ASSERT_SIGN (sign); 415 416 if (MPFR_IS_LIKE_RNDZ(rnd_mode, sign < 0)) 417 { 418 mpfr_setmax (x, __gmpfr_emax); 419 inex = -1; 420 } 421 else 422 { 423 MPFR_SET_INF(x); 424 inex = 1; 425 } 426 MPFR_SET_SIGN(x, sign); 427 __gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW; 428 return sign > 0 ? inex : -inex; 429 } 430 431 /**************************************************************************/ 432 433 /* Code related to constructors and destructors (for debugging) should 434 be put here. The reason is that such code must be in an object file 435 that will be kept by the linker for symbol resolution, and symbols 436 __gmpfr_emin and __gmpfr_emax from this file will be used by every 437 program calling a MPFR math function (where rounding is involved). */ 438 439 #if defined MPFR_DEBUG_PREDICTION 440 441 /* Print prediction statistics at the end of a program. 442 * 443 * Code to debug branch prediction, based on Ulrich Drepper's paper 444 * "What Every Programmer Should Know About Memory": 445 * http://people.freebsd.org/~lstewart/articles/cpumemory.pdf 446 */ 447 448 extern long int __start_predict_data; 449 extern long int __stop_predict_data; 450 extern long int __start_predict_line; 451 extern const char *__start_predict_file; 452 453 static void __attribute__ ((destructor)) 454 predprint (void) 455 { 456 long int *s = &__start_predict_data; 457 long int *e = &__stop_predict_data; 458 long int *sl = &__start_predict_line; 459 const char **sf = &__start_predict_file; 460 461 while (s < e) 462 { 463 printf("%s:%ld: incorrect=%ld, correct=%ld%s\n", 464 *sf, *sl, s[0], s[1], 465 s[0] > s[1] ? " <==== WARNING" : ""); 466 ++sl; 467 ++sf; 468 s += 2; 469 } 470 } 471 472 #endif 473 474 #if MPFR_WANT_ASSERT >= 2 475 476 /* Similar to flags_out in tests/tests.c */ 477 478 void 479 flags_fout (FILE *stream, mpfr_flags_t flags) 480 { 481 int none = 1; 482 483 if (flags & MPFR_FLAGS_UNDERFLOW) 484 none = 0, fprintf (stream, " underflow"); 485 if (flags & MPFR_FLAGS_OVERFLOW) 486 none = 0, fprintf (stream, " overflow"); 487 if (flags & MPFR_FLAGS_NAN) 488 none = 0, fprintf (stream, " nan"); 489 if (flags & MPFR_FLAGS_INEXACT) 490 none = 0, fprintf (stream, " inexact"); 491 if (flags & MPFR_FLAGS_ERANGE) 492 none = 0, fprintf (stream, " erange"); 493 if (none) 494 fprintf (stream, " none"); 495 fprintf (stream, " (%u)\n", flags); 496 } 497 498 #endif 499