diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2002-07-23 16:02:30 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2002-07-23 16:02:30 +0000 |
commit | 95f2dade6f9d010b15888d957a4e154bcb31fee0 (patch) | |
tree | 07865b3ac3f0701bda851197395dcd2df497395f /exceptions.c | |
parent | 4e921f32f097983043f2776c43863b6361a347de (diff) | |
download | mpfr-95f2dade6f9d010b15888d957a4e154bcb31fee0.tar.gz |
Function mpfr_check_range improved in the underflow case.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@1983 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'exceptions.c')
-rw-r--r-- | exceptions.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/exceptions.c b/exceptions.c index 5c94798cb..adcb8d043 100644 --- a/exceptions.c +++ b/exceptions.c @@ -119,19 +119,28 @@ mpfr_clear_inexflag (void) #undef mpfr_check_range -/* Warning! If there is an underflow in the rounding to the nearest mode, - the result may not be the one expected. Either this should be fixed - (a 3rd argument giving the current ternary value is necessary) or the - caller should do some checks for particular cases before the call. */ - int -mpfr_check_range (mpfr_ptr x, mp_rnd_t rnd_mode) +mpfr_check_range (mpfr_ptr x, int t, mp_rnd_t rnd_mode) { if (MPFR_IS_FP(x) && MPFR_NOTZERO(x)) { /* x is a non-zero FP */ mp_exp_t exp = MPFR_EXP(x); if (exp < __mpfr_emin) - return mpfr_set_underflow(x, rnd_mode, MPFR_SIGN(x)); + { + /* The following test is necessary because in the rounding to the + * nearest mode, mpfr_set_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 == GMP_RNDN && + (exp + 1 < __mpfr_emin || + (mpfr_powerof2_raw(x) && + (MPFR_SIGN(x) < 0 ? t <= 0 : t >= 0)))) + rnd_mode = GMP_RNDZ; + return mpfr_set_underflow(x, rnd_mode, MPFR_SIGN(x)); + } if (exp > __mpfr_emax) return mpfr_set_overflow(x, rnd_mode, MPFR_SIGN(x)); } |