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 | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/exceptions.c b/Build/source/libs/mpfr/mpfr-src/src/exceptions.c new file mode 100644 index 00000000000..dacca4eaa1b --- /dev/null +++ b/Build/source/libs/mpfr/mpfr-src/src/exceptions.c @@ -0,0 +1,360 @@ +/* Exception flags and utilities. + +Copyright 2001-2015 Free Software Foundation, Inc. +Contributed by the AriC and Caramel projects, INRIA. + +This file is part of the GNU MPFR Library. + +The GNU MPFR Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The GNU MPFR Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see +http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include "mpfr-impl.h" + +unsigned int MPFR_THREAD_ATTR __gmpfr_flags = 0; + +mpfr_exp_t MPFR_THREAD_ATTR __gmpfr_emin = MPFR_EMIN_DEFAULT; +mpfr_exp_t MPFR_THREAD_ATTR __gmpfr_emax = MPFR_EMAX_DEFAULT; + +#undef mpfr_get_emin + +mpfr_exp_t +mpfr_get_emin (void) +{ + return __gmpfr_emin; +} + +#undef mpfr_set_emin + +int +mpfr_set_emin (mpfr_exp_t exponent) +{ + if (exponent >= MPFR_EMIN_MIN && exponent <= MPFR_EMIN_MAX) + { + __gmpfr_emin = exponent; + return 0; + } + else + { + return 1; + } +} + +mpfr_exp_t +mpfr_get_emin_min (void) +{ + return MPFR_EMIN_MIN; +} + +mpfr_exp_t +mpfr_get_emin_max (void) +{ + return MPFR_EMIN_MAX; +} + +#undef mpfr_get_emax + +mpfr_exp_t +mpfr_get_emax (void) +{ + return __gmpfr_emax; +} + +#undef mpfr_set_emax + +int +mpfr_set_emax (mpfr_exp_t exponent) +{ + if (exponent >= MPFR_EMAX_MIN && exponent <= MPFR_EMAX_MAX) + { + __gmpfr_emax = exponent; + return 0; + } + else + { + return 1; + } +} + +mpfr_exp_t +mpfr_get_emax_min (void) +{ + return MPFR_EMAX_MIN; +} +mpfr_exp_t +mpfr_get_emax_max (void) +{ + return MPFR_EMAX_MAX; +} + + +#undef mpfr_clear_flags + +void +mpfr_clear_flags (void) +{ + __gmpfr_flags = 0; +} + +#undef mpfr_clear_underflow + +void +mpfr_clear_underflow (void) +{ + __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_UNDERFLOW; +} + +#undef mpfr_clear_overflow + +void +mpfr_clear_overflow (void) +{ + __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_OVERFLOW; +} + +#undef mpfr_clear_divby0 + +void +mpfr_clear_divby0 (void) +{ + __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_DIVBY0; +} + +#undef mpfr_clear_nanflag + +void +mpfr_clear_nanflag (void) +{ + __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_NAN; +} + +#undef mpfr_clear_inexflag + +void +mpfr_clear_inexflag (void) +{ + __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_INEXACT; +} + +#undef mpfr_clear_erangeflag + +void +mpfr_clear_erangeflag (void) +{ + __gmpfr_flags &= MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE; +} + +#undef mpfr_set_underflow + +void +mpfr_set_underflow (void) +{ + __gmpfr_flags |= MPFR_FLAGS_UNDERFLOW; +} + +#undef mpfr_set_overflow + +void +mpfr_set_overflow (void) +{ + __gmpfr_flags |= MPFR_FLAGS_OVERFLOW; +} + +#undef mpfr_set_divby0 + +void +mpfr_set_divby0 (void) +{ + __gmpfr_flags |= MPFR_FLAGS_DIVBY0; +} + +#undef mpfr_set_nanflag + +void +mpfr_set_nanflag (void) +{ + __gmpfr_flags |= MPFR_FLAGS_NAN; +} + +#undef mpfr_set_inexflag + +void +mpfr_set_inexflag (void) +{ + __gmpfr_flags |= MPFR_FLAGS_INEXACT; +} + +#undef mpfr_set_erangeflag + +void +mpfr_set_erangeflag (void) +{ + __gmpfr_flags |= MPFR_FLAGS_ERANGE; +} + + +#undef mpfr_check_range + +int +mpfr_check_range (mpfr_ptr x, int t, mpfr_rnd_t rnd_mode) +{ + if (MPFR_LIKELY( MPFR_IS_PURE_FP(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) ) + { + /* The following test is necessary because in the rounding to the + * nearest mode, mpfr_underflow always rounds away from 0. In + * this rounding mode, we need to round to 0 if: + * _ |x| < 2^(emin-2), or + * _ |x| = 2^(emin-2) and the absolute value of the exact + * result is <= 2^(emin-2). + */ + if (rnd_mode == MPFR_RNDN && + (exp + 1 < __gmpfr_emin || + (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)); + } + 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))) + { + /* We need to do the following because most MPFR functions are + * implemented in the following way: + * Ziv's loop: + * | Compute an approximation to the result and an error bound. + * | Possible underflow/overflow detection -> return. + * | If can_round, break (exit the loop). + * | Otherwise, increase the working precision and loop. + * Round the approximation in the target precision. <== See below + * Restore the flags (that could have been set due to underflows + * or overflows during the internal computations). + * Execute: return mpfr_check_range (...). + * The problem is that an overflow could be generated when rounding the + * approximation (in general, such an overflow could not be detected + * earlier), and the overflow flag is lost when the flags are restored. + * This can occur only when the rounding yields an exponent change + * and the new exponent is larger than the maximum exponent, so that + * an infinity is necessarily obtained. + * So, the simplest solution is to detect this overflow case here in + * mpfr_check_range, which is easy to do since the rounded result is + * necessarily an inexact infinity. + */ + __gmpfr_flags |= MPFR_FLAGS_OVERFLOW; + } + MPFR_RET (t); /* propagate inexact ternary value, unlike most functions */ +} + +#undef mpfr_underflow_p + +int +mpfr_underflow_p (void) +{ + return __gmpfr_flags & MPFR_FLAGS_UNDERFLOW; +} + +#undef mpfr_overflow_p + +int +mpfr_overflow_p (void) +{ + return __gmpfr_flags & MPFR_FLAGS_OVERFLOW; +} + +#undef mpfr_divby0_p + +int +mpfr_divby0_p (void) +{ + return __gmpfr_flags & MPFR_FLAGS_DIVBY0; +} + +#undef mpfr_nanflag_p + +int +mpfr_nanflag_p (void) +{ + return __gmpfr_flags & MPFR_FLAGS_NAN; +} + +#undef mpfr_inexflag_p + +int +mpfr_inexflag_p (void) +{ + return __gmpfr_flags & MPFR_FLAGS_INEXACT; +} + +#undef mpfr_erangeflag_p + +int +mpfr_erangeflag_p (void) +{ + 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. */ + +int +mpfr_underflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign) +{ + int inex; + + MPFR_ASSERT_SIGN (sign); + + if (MPFR_IS_LIKE_RNDZ(rnd_mode, sign < 0)) + { + MPFR_SET_ZERO(x); + inex = -1; + } + else + { + mpfr_setmin (x, __gmpfr_emin); + inex = 1; + } + MPFR_SET_SIGN(x, sign); + __gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW; + return sign > 0 ? inex : -inex; +} + +/* #undef mpfr_overflow */ + +int +mpfr_overflow (mpfr_ptr x, mpfr_rnd_t rnd_mode, int sign) +{ + int inex; + + MPFR_ASSERT_SIGN(sign); + if (MPFR_IS_LIKE_RNDZ(rnd_mode, sign < 0)) + { + mpfr_setmax (x, __gmpfr_emax); + inex = -1; + } + else + { + MPFR_SET_INF(x); + inex = 1; + } + MPFR_SET_SIGN(x,sign); + __gmpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW; + return sign > 0 ? inex : -inex; +} |