summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2017-12-19 03:38:58 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2017-12-19 03:38:58 +0000
commit81c69f01f0200536cfc2d38977f6950112c40c6e (patch)
tree0c6cca222f14b2c585c4fdf9ecc49001222d7d59
parentb4eb98a18379e1ebeddf448ecb4ff31ef9b58545 (diff)
downloadmpfr-81c69f01f0200536cfc2d38977f6950112c40c6e.tar.gz
[src/exp2.c] Update concerning the underflow/overflow cases.
Still incomplete. git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@12011 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--src/exp2.c42
1 files changed, 22 insertions, 20 deletions
diff --git a/src/exp2.c b/src/exp2.c
index 9f9d9bbab..4a536e13d 100644
--- a/src/exp2.c
+++ b/src/exp2.c
@@ -29,7 +29,7 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
int
mpfr_exp2 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
- int inexact;
+ int inexact, inex2;
long xint;
mpfr_t xfrac;
MPFR_SAVE_EXPO_DECL (expo);
@@ -62,27 +62,22 @@ mpfr_exp2 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
}
}
- /* Since the smallest representable non-zero float is 1/2*2^__gmpfr_emin,
- if x <= __gmpfr_emin - 2, the result is either 1/2*2^__gmpfr_emin or 0.
- Warning, for __gmpfr_emin - 2 < x < __gmpfr_emin - 1, we cannot conclude,
- since 2^x might round to 2^(__gmpfr_emin - 1) for rounding away or to nearest,
- and there might be no underflow. */
+ /* Since the smallest representable non-zero float is 1/2 * 2^emin,
+ if x <= emin - 2, the result is either 1/2 * 2^emin or 0.
+ Warning, for emin - 2 < x < emin - 1, we cannot conclude, since 2^x
+ might round to 2^(emin - 1) for rounding away or to nearest, and there
+ might be no underflow, since we consider underflow "after rounding". */
MPFR_ASSERTN (MPFR_EMIN_MIN >= LONG_MIN + 2);
if (MPFR_UNLIKELY (mpfr_cmp_si (x, __gmpfr_emin - 2) <= 0))
- {
- mpfr_rnd_t rnd2 = rnd_mode;
- /* in round to nearest mode, round to zero */
- if (rnd_mode == MPFR_RNDN)
- rnd2 = MPFR_RNDZ;
- return mpfr_underflow (y, rnd2, 1);
- }
+ return mpfr_underflow (y, rnd_mode == MPFR_RNDN ? MPFR_RNDZ : rnd_mode, 1);
MPFR_ASSERTN (MPFR_EMAX_MAX <= LONG_MAX);
if (MPFR_UNLIKELY (mpfr_cmp_si (x, __gmpfr_emax) >= 0))
return mpfr_overflow (y, rnd_mode, 1);
- /* We now know that emin - 1 <= x < emax. */
+ /* We now know that emin - 2 < x < emax. Note that an underflow or
+ overflow is still possible (we have eliminated only easy cases). */
MPFR_SAVE_EXPO_MARK (expo);
@@ -94,10 +89,13 @@ mpfr_exp2 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
xint = mpfr_get_si (x, MPFR_RNDZ);
mpfr_init2 (xfrac, MPFR_PREC (x));
- mpfr_sub_si (xfrac, x, xint, MPFR_RNDN); /* exact */
+ MPFR_DBGRES (inexact = mpfr_sub_si (xfrac, x, xint, MPFR_RNDN));
+ MPFR_ASSERTD (inexact == 0);
if (MPFR_IS_ZERO (xfrac))
{
+ /* Here, emin - 1 <= x <= emax - 1, so that an underflow or overflow
+ will not be possible. */
mpfr_set_ui (y, 1, MPFR_RNDN);
inexact = 0;
}
@@ -144,12 +142,16 @@ mpfr_exp2 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
}
mpfr_clear (xfrac);
+
MPFR_CLEAR_FLAGS ();
- /* FIXME: in case of underflow, MPFR_RNDN might return 0.5*2^emin, which will
- remain unchanged below, whereas with RNDZ, we want +0 as result. */
- mpfr_mul_2si (y, y, xint, MPFR_RNDN); /* exact or under/overflow */
- /* Note: We can have an overflow only when t was rounded up to 2. */
- MPFR_ASSERTD (MPFR_IS_PURE_FP (y) || inexact > 0);
+ /* FIXME: possible double rounding issue in the underflow case
+ (xint = emin - 1, y = 1/2 before the scaling). This should
+ be handled a bit like in mpfr_check_range. But first, add a
+ non-regression test. */
+ inex2 = mpfr_mul_2si (y, y, xint, rnd_mode);
+ if (inex2 != 0) /* underflow or overflow */
+ inexact = inex2;
+
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
MPFR_SAVE_EXPO_FREE (expo);
return mpfr_check_range (y, inexact, rnd_mode);