summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2008-08-20 04:12:36 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2008-08-20 04:12:36 +0000
commit1251a04519dbbc22ab7d11b2830fcd97836c0921 (patch)
treee7582c45ab411646521bd5f44d604f2c9ea2f258
parentb9fddf5ae17cb53798dec8df635a8ce72e9f83a8 (diff)
downloadmpfr-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--NEWS2
-rw-r--r--exceptions.c22
-rw-r--r--mpfr.texi6
3 files changed, 30 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index dd2fbc69d..1bf08424c 100644
--- a/NEWS
+++ b/NEWS
@@ -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 */
}
diff --git a/mpfr.texi b/mpfr.texi
index 1d7ea34f5..864e30fb9 100644
--- a/mpfr.texi
+++ b/mpfr.texi
@@ -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})