diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2008-08-20 04:12:36 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2008-08-20 04:12:36 +0000 |
commit | 1251a04519dbbc22ab7d11b2830fcd97836c0921 (patch) | |
tree | e7582c45ab411646521bd5f44d604f2c9ea2f258 | |
parent | b9fddf5ae17cb53798dec8df635a8ce72e9f83a8 (diff) | |
download | mpfr-1251a04519dbbc22ab7d11b2830fcd97836c0921.tar.gz |
Fixed the following problem:
The overflow flag can be lost in many functions called with the
maximum exponent equal to MPFR_EMAX_MAX (this is the default on
32-bit machines) when the temporary result (in a higher precision)
is representable but once rounded, it yields an overflow.
This needed a slight change of behavior of the mpfr_check_range function
(defined in exceptions.c). Described this change in mpfr.texi and NEWS.
[Merged changeset 5545 from the trunk.]
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/2.3@5546 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | exceptions.c | 22 | ||||
-rw-r--r-- | mpfr.texi | 6 |
3 files changed, 30 insertions, 0 deletions
@@ -23,6 +23,8 @@ MA 02110-1301, USA. Changes from version 2.3.1 to version 2.3.2: - Bug fixes. - Improved MPFR manual. +- Behavior of mpfr_check_range changed: if the value is an inexact + infinity, the overflow flag is set (in case it was lost). Changes from version 2.3.0 to version 2.3.1: - Changes in the behavior of mpfr_strtofr and in its documentation diff --git a/exceptions.c b/exceptions.c index 8aeb80d8c..f97c66f34 100644 --- a/exceptions.c +++ b/exceptions.c @@ -215,6 +215,28 @@ mpfr_check_range (mpfr_ptr x, int t, mp_rnd_t rnd_mode) 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))) + { + /* We need to do the following because most MPFR functions are + * implemented in the following way: + * Ziv's loop: + * | Compute an approximation to the result and an error bound. + * | Possible underflow/overflow detection -> return. + * | If can_round, break (exit the loop). + * | Otherwise, increase the working precision and loop. + * Round the approximation in the target precision. + * Restore the flags (that could have been set due to underflows + * or overflows during the internal computations). + * Execute: return mpfr_check_range (...). + * The problem is that an overflow could be generated when rounding the + * approximation (in general, such an overflow could not be detected + * earlier), and the overflow flag is lost when the flags are restored. + * So, the simplest solution is to detect this overflow case here in + * mpfr_check_range, which is easy to do since the rounded result is + * necessarily an inexact infinity. + */ + __gmpfr_flags |= MPFR_FLAGS_OVERFLOW; + } MPFR_RET (t); /* propagate inexact ternary value, unlike most functions */ } @@ -2148,6 +2148,12 @@ result is larger than the exact one, a negative value if the rounded result is smaller than the exact one. Note that unlike most functions, the result is compared to the exact one, not the input value @var{x}, i.e.@: the ternary value is propagated. + +Note: If @var{x} is an infinity and @var{t} is different from zero (i.e., +if the rounded result is an inexact infinity), then the overflow flag is +set. This is useful because @code{mpfr_check_range} is typically called +(at least in MPFR functions) after restoring the flags that could have +been set due to internal computations. @end deftypefun @deftypefun int mpfr_subnormalize (mpfr_t @var{x}, int @var{t}, mp_rnd_t @var{rnd}) |