1 /* Exception flags and utilities. Constructors and destructors (debug). 2 3 Copyright 2001-2023 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 /* This function does not have logging messages. As it is also partly 256 implemented as a macro, if messages are added in the future, the macro 257 may need to be disabled when logging is enabled. */ 258 int 259 mpfr_check_range (mpfr_ptr x, int t, mpfr_rnd_t rnd_mode) 260 { 261 if (MPFR_LIKELY (! MPFR_IS_SINGULAR (x))) 262 { /* x is a non-zero FP */ 263 mpfr_exp_t exp = MPFR_EXP (x); /* Do not use MPFR_GET_EXP */ 264 265 MPFR_ASSERTD (MPFR_IS_NORMALIZED (x)); 266 if (MPFR_UNLIKELY (exp < __gmpfr_emin)) 267 { 268 /* The following test is necessary because in the rounding to the 269 * nearest mode, mpfr_underflow always rounds away from 0. In 270 * this rounding mode, we need to round to 0 if: 271 * _ |x| < 2^(emin-2), or 272 * _ |x| = 2^(emin-2) and the absolute value of the exact 273 * result is <= 2^(emin-2). 274 */ 275 if (rnd_mode == MPFR_RNDN && 276 (exp + 1 < __gmpfr_emin || 277 (mpfr_powerof2_raw(x) && 278 (MPFR_IS_NEG(x) ? t <= 0 : t >= 0)))) 279 rnd_mode = MPFR_RNDZ; 280 return mpfr_underflow (x, rnd_mode, MPFR_SIGN(x)); 281 } 282 if (MPFR_UNLIKELY (exp > __gmpfr_emax)) 283 return mpfr_overflow (x, rnd_mode, MPFR_SIGN(x)); 284 } 285 else if (MPFR_UNLIKELY (t != 0 && MPFR_IS_INF (x))) 286 { 287 /* We need to do the following because most MPFR functions are 288 * implemented in the following way: 289 * Ziv's loop: 290 * | Compute an approximation to the result and an error bound. 291 * | Possible underflow/overflow detection -> return. 292 * | If can_round, break (exit the loop). 293 * | Otherwise, increase the working precision and loop. 294 * Round the approximation in the target precision. <== See below 295 * Restore the flags (that could have been set due to underflows 296 * or overflows during the internal computations). 297 * Execute: return mpfr_check_range (...). 298 * The problem is that an overflow could be generated when rounding the 299 * approximation (in general, such an overflow could not be detected 300 * earlier), and the overflow flag is lost when the flags are restored. 301 * This can occur only when the rounding yields an exponent change 302 * and the new exponent is larger than the maximum exponent, so that 303 * an infinity is necessarily obtained. 304 * So, the simplest solution is to detect this overflow case here in 305 * mpfr_check_range, which is easy to do since the rounded result is 306 * necessarily an inexact infinity. 307 */ 308 __gmpfr_flags |= MPFR_FLAGS_OVERFLOW; 309 } 310 MPFR_RET (t); /* propagate inexact ternary value, unlike most functions */ 311 } 312 313 314 #undef mpfr_underflow_p 315 316 MPFR_COLD_FUNCTION_ATTR int 317 mpfr_underflow_p (void) 318 { 319 MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_UNDERFLOW <= INT_MAX); 320 return __gmpfr_flags & MPFR_FLAGS_UNDERFLOW; 321 } 322 323 #undef mpfr_overflow_p 324 325 MPFR_COLD_FUNCTION_ATTR int 326 mpfr_overflow_p (void) 327 { 328 MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_OVERFLOW <= INT_MAX); 329 return __gmpfr_flags & MPFR_FLAGS_OVERFLOW; 330 } 331 332 #undef mpfr_divby0_p 333 334 MPFR_COLD_FUNCTION_ATTR int 335 mpfr_divby0_p (void) 336 { 337 MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_DIVBY0 <= INT_MAX); 338 return __gmpfr_flags & MPFR_FLAGS_DIVBY0; 339 } 340 341 #undef mpfr_nanflag_p 342 343 MPFR_COLD_FUNCTION_ATTR int 344 mpfr_nanflag_p (void) 345 { 346 MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_NAN <= INT_MAX); 347 return __gmpfr_flags & MPFR_FLAGS_NAN; 348 } 349 350 #undef mpfr_inexflag_p 351 352 MPFR_COLD_FUNCTION_ATTR int 353 mpfr_inexflag_p (void) 354 { 355 MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_INEXACT <= INT_MAX); 356 return __gmpfr_flags & MPFR_FLAGS_INEXACT; 357 } 358 359 #undef mpfr_erangeflag_p 360 361 MPFR_COLD_FUNCTION_ATTR int 362 mpfr_erangeflag_p (void) 363 { 364 MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_ERANGE <= INT_MAX); 365 return __gmpfr_flags & MPFR_FLAGS_ERANGE; 366 } 367 368 369 /* #undef mpfr_underflow */ 370 371 /* Note: In the rounding to the nearest mode, mpfr_underflow 372 always rounds away from 0. In this rounding mode, you must call 373 mpfr_underflow with rnd_mode = MPFR_RNDZ if the exact result 374 is <= 2^(emin-2) in absolute value. 375 We chose the default to round away from zero instead of toward zero 376 because rounding away from zero (MPFR_RNDA) wasn't supported at that 377 time (r1910), so that the caller had no way to change rnd_mode to 378 this mode. */ 379 380 MPFR_COLD_FUNCTION_ATTR int 381 mpfr_underflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign) 382 { 383 int inex; 384 385 MPFR_LOG_FUNC 386 (("rnd=%d sign=%d", rnd_mode, sign), 387 ("x[%Pd]=%.*Rg", mpfr_get_prec (x), mpfr_log_prec, x)); 388 389 MPFR_ASSERT_SIGN (sign); 390 391 if (MPFR_IS_LIKE_RNDZ(rnd_mode, sign < 0)) 392 { 393 MPFR_SET_ZERO(x); 394 inex = -1; 395 } 396 else 397 { 398 mpfr_setmin (x, __gmpfr_emin); 399 inex = 1; 400 } 401 MPFR_SET_SIGN(x, sign); 402 __gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW; 403 return sign > 0 ? inex : -inex; 404 } 405 406 /* #undef mpfr_overflow */ 407 408 MPFR_COLD_FUNCTION_ATTR int 409 mpfr_overflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign) 410 { 411 int inex; 412 413 MPFR_LOG_FUNC 414 (("rnd=%d sign=%d", rnd_mode, sign), 415 ("x[%Pd]=%.*Rg", mpfr_get_prec (x), mpfr_log_prec, x)); 416 417 MPFR_ASSERT_SIGN (sign); 418 419 if (MPFR_IS_LIKE_RNDZ(rnd_mode, sign < 0)) 420 { 421 mpfr_setmax (x, __gmpfr_emax); 422 inex = -1; 423 } 424 else 425 { 426 MPFR_SET_INF(x); 427 inex = 1; 428 } 429 MPFR_SET_SIGN(x, sign); 430 __gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW; 431 return sign > 0 ? inex : -inex; 432 } 433 434 /**************************************************************************/ 435 436 /* Code related to constructors and destructors (for debugging) should 437 be put here. The reason is that such code must be in an object file 438 that will be kept by the linker for symbol resolution, and symbols 439 __gmpfr_emin and __gmpfr_emax from this file will be used by every 440 program calling a MPFR math function (where rounding is involved). */ 441 442 #if defined MPFR_DEBUG_PREDICTION 443 444 /* Print prediction statistics at the end of a program. 445 * 446 * Code to debug branch prediction, based on Ulrich Drepper's paper 447 * "What Every Programmer Should Know About Memory": 448 * https://people.freebsd.org/~lstewart/articles/cpumemory.pdf 449 */ 450 451 extern long int __start_predict_data; 452 extern long int __stop_predict_data; 453 extern long int __start_predict_line; 454 extern const char *__start_predict_file; 455 456 static void __attribute__ ((destructor)) 457 predprint (void) 458 { 459 long int *s = &__start_predict_data; 460 long int *e = &__stop_predict_data; 461 long int *sl = &__start_predict_line; 462 const char **sf = &__start_predict_file; 463 464 while (s < e) 465 { 466 printf("%s:%ld: incorrect=%ld, correct=%ld%s\n", 467 *sf, *sl, s[0], s[1], 468 s[0] > s[1] ? " <==== WARNING" : ""); 469 ++sl; 470 ++sf; 471 s += 2; 472 } 473 } 474 475 #endif 476 477 #if MPFR_WANT_ASSERT >= 2 478 479 /* Similar to flags_out in tests/tests.c */ 480 481 void 482 flags_fout (FILE *stream, mpfr_flags_t flags) 483 { 484 int none = 1; 485 486 if (flags & MPFR_FLAGS_UNDERFLOW) 487 none = 0, fprintf (stream, " underflow"); 488 if (flags & MPFR_FLAGS_OVERFLOW) 489 none = 0, fprintf (stream, " overflow"); 490 if (flags & MPFR_FLAGS_NAN) 491 none = 0, fprintf (stream, " nan"); 492 if (flags & MPFR_FLAGS_INEXACT) 493 none = 0, fprintf (stream, " inexact"); 494 if (flags & MPFR_FLAGS_ERANGE) 495 none = 0, fprintf (stream, " erange"); 496 if (none) 497 fprintf (stream, " none"); 498 fprintf (stream, " (%u)\n", flags); 499 } 500 501 #endif 502