summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2017-12-23 10:15:10 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2017-12-23 10:15:10 +0000
commit140fa08a162cb62aee9f63d325d78f77b3803aba (patch)
treec59f0e06b725e4fb62091f9f4dd3129cad4e7099
parent7733b3e1a28763816d3df3d4c763a72b5951b0f4 (diff)
downloadmpfr-140fa08a162cb62aee9f63d325d78f77b3803aba.tar.gz
Merged changesets r12046-12048 from the trunk (bug fix and test).
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/4.0@12049 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--src/exp_2.c13
-rw-r--r--src/subnormal.c5
-rw-r--r--tests/texp.c20
3 files changed, 31 insertions, 7 deletions
diff --git a/src/exp_2.c b/src/exp_2.c
index a9439b8b0..64a9fd286 100644
--- a/src/exp_2.c
+++ b/src/exp_2.c
@@ -198,14 +198,15 @@ mpfr_exp_2 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
mpfr_sub (r, x, r, MPFR_RNDU);
+ while (MPFR_IS_PURE_FP(r) && MPFR_IS_NEG (r))
+ { /* initial approximation n was too large */
+ n--;
+ mpfr_add (r, r, s, MPFR_RNDU);
+ }
+
+ /* if r is 0, we cannot round correctly */
if (MPFR_LIKELY(MPFR_IS_PURE_FP (r)))
{
- while (MPFR_IS_NEG (r))
- { /* initial approximation n was too large */
- n--;
- mpfr_add (r, r, s, MPFR_RNDU);
- }
-
/* since there was a cancellation in x - n*log(2), the low error_r
bits from r are zero and thus non significant, thus we can reduce
the working precision */
diff --git a/src/subnormal.c b/src/subnormal.c
index 0a135aa9f..1b75ce8b7 100644
--- a/src/subnormal.c
+++ b/src/subnormal.c
@@ -145,7 +145,10 @@ mpfr_subnormalize (mpfr_ptr y, int old_inexact, mpfr_rnd_t rnd)
if (SAME_SIGN (inexact, MPFR_INT_SIGN (y)))
mpfr_nexttozero (dest);
else /* subnormal range, thus no overflow */
- mpfr_nexttoinf (dest);
+ {
+ mpfr_nexttoinf (dest);
+ MPFR_ASSERTD(!MPFR_IS_INF (dest));
+ }
inexact = -inexact;
}
}
diff --git a/tests/texp.c b/tests/texp.c
index 1d002bd2e..b27e51068 100644
--- a/tests/texp.c
+++ b/tests/texp.c
@@ -972,6 +972,24 @@ underflow (void)
}
}
+/* bug found with GMP_CHECK_RANDOMIZE=1514290185 */
+static void
+bug20171223 (void)
+{
+ mpfr_t x, y;
+ int inex;
+
+ mpfr_init2 (x, 372);
+ mpfr_init2 (y, 2);
+ mpfr_set_str (x, "-6.9314716128384587678466323621915206417385796077947874471662159283492445979241549847386366371775938082803907383582e-01", 10, MPFR_RNDN);
+ /* exp(x) = 0.500000009638..., should be rounded to 0.5 */
+ inex = mpfr_exp (y, x, MPFR_RNDD);
+ MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 1, -1) == 0);
+ MPFR_ASSERTN(inex < 0);
+ mpfr_clear (x);
+ mpfr_clear (y);
+}
+
int
main (int argc, char *argv[])
{
@@ -980,6 +998,8 @@ main (int argc, char *argv[])
if (argc > 1)
check_large ();
+ bug20171223 ();
+
check_inexact ();
check_special ();