summaryrefslogtreecommitdiff
path: root/Build/source/libs/mpfr/mpfr-src/src/frexp.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/frexp.c')
-rw-r--r--Build/source/libs/mpfr/mpfr-src/src/frexp.c39
1 files changed, 35 insertions, 4 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/frexp.c b/Build/source/libs/mpfr/mpfr-src/src/frexp.c
index 0f8de7ed5e3..c5bcf0f442c 100644
--- a/Build/source/libs/mpfr/mpfr-src/src/frexp.c
+++ b/Build/source/libs/mpfr/mpfr-src/src/frexp.c
@@ -1,7 +1,7 @@
/* mpfr_frexp -- convert to integral and fractional parts
-Copyright 2011-2015 Free Software Foundation, Inc.
-Contributed by the AriC and Caramel projects, INRIA.
+Copyright 2011-2016 Free Software Foundation, Inc.
+Contributed by the AriC and Caramba projects, INRIA.
This file is part of the GNU MPFR Library.
@@ -26,6 +26,13 @@ int
mpfr_frexp (mpfr_exp_t *exp, mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd)
{
int inex;
+ unsigned int saved_flags = __gmpfr_flags;
+ MPFR_BLOCK_DECL (flags);
+
+ MPFR_LOG_FUNC
+ (("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd),
+ ("y[%Pu]=%.*Rg exp=%" MPFR_EXP_FSPEC "d inex=%d", mpfr_get_prec (y),
+ mpfr_log_prec, y, (mpfr_eexp_t) *exp, inex));
if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(x)))
{
@@ -49,8 +56,32 @@ mpfr_frexp (mpfr_exp_t *exp, mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd)
}
}
- inex = mpfr_set (y, x, rnd);
+ MPFR_BLOCK (flags, inex = mpfr_set (y, x, rnd));
+ __gmpfr_flags = saved_flags;
+
+ /* Possible overflow due to the rounding, no possible underflow. */
+
+ if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags)))
+ {
+ int inex2;
+
+ /* An overflow here means that the exponent of y would be larger than
+ the one of x, thus x would be rounded to the next power of 2, and
+ the returned y should be 1/2 in absolute value, rounded (i.e. with
+ possible underflow or overflow). This also implies that x and y are
+ different objects, so that the exponent of x has not been lost. */
+ MPFR_LOG_MSG (("Internal overflow\n", 0));
+ MPFR_ASSERTD (x != y);
+ *exp = MPFR_GET_EXP (x) + 1;
+ inex2 = mpfr_set_si_2exp (y, MPFR_INT_SIGN (x), -1, rnd);
+ MPFR_LOG_MSG (("inex=%d inex2=%d\n", inex, inex2));
+ if (inex2 != 0)
+ inex = inex2;
+ MPFR_RET (inex);
+ }
+
*exp = MPFR_GET_EXP (y);
- MPFR_SET_EXP (y, 0);
+ /* Do not use MPFR_SET_EXP because the range has not been checked yet. */
+ MPFR_EXP (y) = 0;
return mpfr_check_range (y, inex, rnd);
}