diff options
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/exceptions.c')
-rw-r--r-- | Build/source/libs/mpfr/mpfr-src/src/exceptions.c | 187 |
1 files changed, 150 insertions, 37 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/exceptions.c b/Build/source/libs/mpfr/mpfr-src/src/exceptions.c index e250be0a537..b457bbdf2eb 100644 --- a/Build/source/libs/mpfr/mpfr-src/src/exceptions.c +++ b/Build/source/libs/mpfr/mpfr-src/src/exceptions.c @@ -1,4 +1,4 @@ -/* Exception flags and utilities. +/* Exception flags and utilities. Constructors and destructors (debug). Copyright 2001-2017 Free Software Foundation, Inc. Contributed by the AriC and Caramba projects, INRIA. @@ -22,13 +22,13 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., #include "mpfr-impl.h" -MPFR_THREAD_VAR (unsigned int, __gmpfr_flags, 0) +MPFR_THREAD_VAR (mpfr_flags_t, __gmpfr_flags, 0) MPFR_THREAD_VAR (mpfr_exp_t, __gmpfr_emin, MPFR_EMIN_DEFAULT) MPFR_THREAD_VAR (mpfr_exp_t, __gmpfr_emax, MPFR_EMAX_DEFAULT) #undef mpfr_get_emin -mpfr_exp_t +MPFR_COLD_FUNCTION_ATTR mpfr_exp_t mpfr_get_emin (void) { return __gmpfr_emin; @@ -39,7 +39,7 @@ mpfr_get_emin (void) int mpfr_set_emin (mpfr_exp_t exponent) { - if (exponent >= MPFR_EMIN_MIN && exponent <= MPFR_EMIN_MAX) + if (MPFR_LIKELY (exponent >= MPFR_EMIN_MIN && exponent <= MPFR_EMIN_MAX)) { __gmpfr_emin = exponent; return 0; @@ -50,13 +50,13 @@ mpfr_set_emin (mpfr_exp_t exponent) } } -mpfr_exp_t +MPFR_COLD_FUNCTION_ATTR mpfr_exp_t mpfr_get_emin_min (void) { return MPFR_EMIN_MIN; } -mpfr_exp_t +MPFR_COLD_FUNCTION_ATTR mpfr_exp_t mpfr_get_emin_max (void) { return MPFR_EMIN_MAX; @@ -64,7 +64,7 @@ mpfr_get_emin_max (void) #undef mpfr_get_emax -mpfr_exp_t +MPFR_COLD_FUNCTION_ATTR mpfr_exp_t mpfr_get_emax (void) { return __gmpfr_emax; @@ -75,7 +75,7 @@ mpfr_get_emax (void) int mpfr_set_emax (mpfr_exp_t exponent) { - if (exponent >= MPFR_EMAX_MIN && exponent <= MPFR_EMAX_MAX) + if (MPFR_LIKELY (exponent >= MPFR_EMAX_MIN && exponent <= MPFR_EMAX_MAX)) { __gmpfr_emax = exponent; return 0; @@ -86,18 +86,62 @@ mpfr_set_emax (mpfr_exp_t exponent) } } -mpfr_exp_t +MPFR_COLD_FUNCTION_ATTR mpfr_exp_t mpfr_get_emax_min (void) { return MPFR_EMAX_MIN; } -mpfr_exp_t + +MPFR_COLD_FUNCTION_ATTR mpfr_exp_t mpfr_get_emax_max (void) { return MPFR_EMAX_MAX; } +#undef mpfr_flags_clear + +MPFR_COLD_FUNCTION_ATTR void +mpfr_flags_clear (mpfr_flags_t mask) +{ + __gmpfr_flags &= MPFR_FLAGS_ALL ^ mask; +} + +#undef mpfr_flags_set + +MPFR_COLD_FUNCTION_ATTR void +mpfr_flags_set (mpfr_flags_t mask) +{ + __gmpfr_flags |= mask; +} + +#undef mpfr_flags_test + +MPFR_COLD_FUNCTION_ATTR mpfr_flags_t +mpfr_flags_test (mpfr_flags_t mask) +{ + return __gmpfr_flags & mask; +} + +#undef mpfr_flags_save + +MPFR_COLD_FUNCTION_ATTR mpfr_flags_t +mpfr_flags_save (void) +{ + return __gmpfr_flags; +} + +#undef mpfr_flags_restore + +MPFR_COLD_FUNCTION_ATTR void +mpfr_flags_restore (mpfr_flags_t flags, mpfr_flags_t mask) +{ + __gmpfr_flags = + (__gmpfr_flags & (MPFR_FLAGS_ALL ^ mask)) | + (flags & mask); +} + + #undef mpfr_clear_flags void @@ -108,7 +152,7 @@ mpfr_clear_flags (void) #undef mpfr_clear_underflow -void +MPFR_COLD_FUNCTION_ATTR void mpfr_clear_underflow (void) { __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_UNDERFLOW; @@ -116,7 +160,7 @@ mpfr_clear_underflow (void) #undef mpfr_clear_overflow -void +MPFR_COLD_FUNCTION_ATTR void mpfr_clear_overflow (void) { __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_OVERFLOW; @@ -124,7 +168,7 @@ mpfr_clear_overflow (void) #undef mpfr_clear_divby0 -void +MPFR_COLD_FUNCTION_ATTR void mpfr_clear_divby0 (void) { __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_DIVBY0; @@ -132,7 +176,7 @@ mpfr_clear_divby0 (void) #undef mpfr_clear_nanflag -void +MPFR_COLD_FUNCTION_ATTR void mpfr_clear_nanflag (void) { __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_NAN; @@ -140,7 +184,7 @@ mpfr_clear_nanflag (void) #undef mpfr_clear_inexflag -void +MPFR_COLD_FUNCTION_ATTR void mpfr_clear_inexflag (void) { __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_INEXACT; @@ -148,7 +192,7 @@ mpfr_clear_inexflag (void) #undef mpfr_clear_erangeflag -void +MPFR_COLD_FUNCTION_ATTR void mpfr_clear_erangeflag (void) { __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE; @@ -156,7 +200,7 @@ mpfr_clear_erangeflag (void) #undef mpfr_set_underflow -void +MPFR_COLD_FUNCTION_ATTR void mpfr_set_underflow (void) { __gmpfr_flags |= MPFR_FLAGS_UNDERFLOW; @@ -164,7 +208,7 @@ mpfr_set_underflow (void) #undef mpfr_set_overflow -void +MPFR_COLD_FUNCTION_ATTR void mpfr_set_overflow (void) { __gmpfr_flags |= MPFR_FLAGS_OVERFLOW; @@ -172,7 +216,7 @@ mpfr_set_overflow (void) #undef mpfr_set_divby0 -void +MPFR_COLD_FUNCTION_ATTR void mpfr_set_divby0 (void) { __gmpfr_flags |= MPFR_FLAGS_DIVBY0; @@ -180,7 +224,7 @@ mpfr_set_divby0 (void) #undef mpfr_set_nanflag -void +MPFR_COLD_FUNCTION_ATTR void mpfr_set_nanflag (void) { __gmpfr_flags |= MPFR_FLAGS_NAN; @@ -188,7 +232,7 @@ mpfr_set_nanflag (void) #undef mpfr_set_inexflag -void +MPFR_COLD_FUNCTION_ATTR void mpfr_set_inexflag (void) { __gmpfr_flags |= MPFR_FLAGS_INEXACT; @@ -196,7 +240,7 @@ mpfr_set_inexflag (void) #undef mpfr_set_erangeflag -void +MPFR_COLD_FUNCTION_ATTR void mpfr_set_erangeflag (void) { __gmpfr_flags |= MPFR_FLAGS_ERANGE; @@ -205,13 +249,18 @@ mpfr_set_erangeflag (void) #undef mpfr_check_range +/* Note: It is possible that for pure FP numbers, EXP(x) < MPFR_EMIN_MIN, + but the caller must make sure that the difference remains small enough + to avoid reaching the special exponent values. */ int mpfr_check_range (mpfr_ptr x, int t, mpfr_rnd_t rnd_mode) { - if (MPFR_LIKELY( MPFR_IS_PURE_FP(x)) ) + if (MPFR_LIKELY (! MPFR_IS_SINGULAR (x))) { /* x is a non-zero FP */ mpfr_exp_t exp = MPFR_EXP (x); /* Do not use MPFR_GET_EXP */ - if (MPFR_UNLIKELY( exp < __gmpfr_emin) ) + + MPFR_ASSERTD (MPFR_IS_NORMALIZED (x)); + if (MPFR_UNLIKELY (exp < __gmpfr_emin)) { /* The following test is necessary because in the rounding to the * nearest mode, mpfr_underflow always rounds away from 0. In @@ -225,9 +274,9 @@ mpfr_check_range (mpfr_ptr x, int t, mpfr_rnd_t rnd_mode) (mpfr_powerof2_raw(x) && (MPFR_IS_NEG(x) ? t <= 0 : t >= 0)))) rnd_mode = MPFR_RNDZ; - return mpfr_underflow(x, rnd_mode, MPFR_SIGN(x)); + return mpfr_underflow (x, rnd_mode, MPFR_SIGN(x)); } - if (MPFR_UNLIKELY( exp > __gmpfr_emax) ) + if (MPFR_UNLIKELY (exp > __gmpfr_emax)) return mpfr_overflow (x, rnd_mode, MPFR_SIGN(x)); } else if (MPFR_UNLIKELY (t != 0 && MPFR_IS_INF (x))) @@ -258,66 +307,82 @@ mpfr_check_range (mpfr_ptr x, int t, mpfr_rnd_t rnd_mode) MPFR_RET (t); /* propagate inexact ternary value, unlike most functions */ } + #undef mpfr_underflow_p -int +MPFR_COLD_FUNCTION_ATTR int mpfr_underflow_p (void) { + MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_UNDERFLOW <= INT_MAX); return __gmpfr_flags & MPFR_FLAGS_UNDERFLOW; } #undef mpfr_overflow_p -int +MPFR_COLD_FUNCTION_ATTR int mpfr_overflow_p (void) { + MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_OVERFLOW <= INT_MAX); return __gmpfr_flags & MPFR_FLAGS_OVERFLOW; } #undef mpfr_divby0_p -int +MPFR_COLD_FUNCTION_ATTR int mpfr_divby0_p (void) { + MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_DIVBY0 <= INT_MAX); return __gmpfr_flags & MPFR_FLAGS_DIVBY0; } #undef mpfr_nanflag_p -int +MPFR_COLD_FUNCTION_ATTR int mpfr_nanflag_p (void) { + MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_NAN <= INT_MAX); return __gmpfr_flags & MPFR_FLAGS_NAN; } #undef mpfr_inexflag_p -int +MPFR_COLD_FUNCTION_ATTR int mpfr_inexflag_p (void) { + MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_INEXACT <= INT_MAX); return __gmpfr_flags & MPFR_FLAGS_INEXACT; } #undef mpfr_erangeflag_p -int +MPFR_COLD_FUNCTION_ATTR int mpfr_erangeflag_p (void) { + MPFR_STAT_STATIC_ASSERT (MPFR_FLAGS_ERANGE <= INT_MAX); return __gmpfr_flags & MPFR_FLAGS_ERANGE; } + /* #undef mpfr_underflow */ /* Note: In the rounding to the nearest mode, mpfr_underflow always rounds away from 0. In this rounding mode, you must call mpfr_underflow with rnd_mode = MPFR_RNDZ if the exact result - is <= 2^(emin-2) in absolute value. */ + is <= 2^(emin-2) in absolute value. + We chose the default to round away from zero instead of toward zero + because rounding away from zero (MPFR_RNDA) wasn't supported at that + time (r1910), so that the caller had no way to change rnd_mode to + this mode. */ -int +MPFR_COLD_FUNCTION_ATTR int mpfr_underflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign) { int inex; + MPFR_LOG_FUNC + (("rnd=%d sign=%d", rnd_mode, sign), + ("x[%Pu]=%.*Rg", mpfr_get_prec (x), mpfr_log_prec, x)); + MPFR_ASSERT_SIGN (sign); if (MPFR_IS_LIKE_RNDZ(rnd_mode, sign < 0)) @@ -337,12 +402,17 @@ mpfr_underflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign) /* #undef mpfr_overflow */ -int +MPFR_COLD_FUNCTION_ATTR int mpfr_overflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign) { int inex; - MPFR_ASSERT_SIGN(sign); + MPFR_LOG_FUNC + (("rnd=%d sign=%d", rnd_mode, sign), + ("x[%Pu]=%.*Rg", mpfr_get_prec (x), mpfr_log_prec, x)); + + MPFR_ASSERT_SIGN (sign); + if (MPFR_IS_LIKE_RNDZ(rnd_mode, sign < 0)) { mpfr_setmax (x, __gmpfr_emax); @@ -353,7 +423,50 @@ mpfr_overflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign) MPFR_SET_INF(x); inex = 1; } - MPFR_SET_SIGN(x,sign); + MPFR_SET_SIGN(x, sign); __gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW; return sign > 0 ? inex : -inex; } + +/**************************************************************************/ + +/* Code related to constructors and destructors (for debugging) should + be put here. The reason is that such code must be in an object file + that will be kept by the linker for symbol resolution, and symbols + __gmpfr_emin and __gmpfr_emax from this file will be used by every + program calling a MPFR math function (where rounding is involved). */ + +#if defined MPFR_DEBUG_PREDICTION + +/* Print prediction statistics at the end of a program. + * + * Code to debug branch prediction, based on Ulrich Drepper's paper + * "What Every Programmer Should Know About Memory": + * http://people.freebsd.org/~lstewart/articles/cpumemory.pdf + */ + +extern long int __start_predict_data; +extern long int __stop_predict_data; +extern long int __start_predict_line; +extern const char *__start_predict_file; + +static void __attribute__ ((destructor)) +predprint (void) +{ + long int *s = &__start_predict_data; + long int *e = &__stop_predict_data; + long int *sl = &__start_predict_line; + const char **sf = &__start_predict_file; + + while (s < e) + { + printf("%s:%ld: incorrect=%ld, correct=%ld%s\n", + *sf, *sl, s[0], s[1], + s[0] > s[1] ? " <==== WARNING" : ""); + ++sl; + ++sf; + s += 2; + } +} + +#endif |