summaryrefslogtreecommitdiff
path: root/Build/source/libs/mpfr/mpfr-src/src/exceptions.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/exceptions.c')
-rw-r--r--Build/source/libs/mpfr/mpfr-src/src/exceptions.c187
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