summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2017-02-06 12:58:48 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2017-02-06 12:58:48 +0000
commit96dd59b90fc985162ed290d5788b52a032d65802 (patch)
tree99b373bb0827f51bacf96563ee6cff702fe7dd93
parentef16a0e0c1c1e9f4240c8e8bad1e66e36e48c3b2 (diff)
downloadmpfr-96dd59b90fc985162ed290d5788b52a032d65802.tar.gz
[tests/tsqr.c] added a corner underflow case
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@11258 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--src/sqr.c8
-rw-r--r--tests/tsqr.c30
2 files changed, 37 insertions, 1 deletions
diff --git a/src/sqr.c b/src/sqr.c
index 0be9ba19d..36587cec7 100644
--- a/src/sqr.c
+++ b/src/sqr.c
@@ -65,6 +65,14 @@ mpfr_sqr_1 (mpfr_ptr a, mpfr_srcptr b, mpfr_rnd_t rnd_mode, mpfr_prec_t p)
a >= 0.111...111[1]*2^(emin-1), there is no underflow. */
if (MPFR_UNLIKELY(ax < __gmpfr_emin))
{
+ /* Note: for emin=2*k+1, a >= 0.111...111*2^(emin-1) is not possible,
+ i.e., a >= (1 - 2^(-p))*2^(2k), since we need a = b^2 with EXP(b)=k,
+ and the largest such b is (1 - 2^(-p))*2^k satisfies
+ b^2 < (1 - 2^(-p))*2^(2k).
+ For emin=2*k, it is only possible for some values of p: it is not
+ possible for p=53, because the largest significand is 6369051672525772
+ but its square has only 52 leading ones. For p=24 it is possible,
+ with b = 11863283, whose square has 24 leading ones. */
if ((ax == __gmpfr_emin - 1) && (ap[0] == ~mask) &&
((rnd_mode == MPFR_RNDN && rb) ||
(MPFR_IS_LIKE_RNDA(rnd_mode, MPFR_IS_NEG (a)) && (rb | sb))))
diff --git a/tests/tsqr.c b/tests/tsqr.c
index c8d0ea340..2d9169747 100644
--- a/tests/tsqr.c
+++ b/tests/tsqr.c
@@ -118,6 +118,33 @@ check_special (void)
mpfr_clear (x);
}
+/* check ax < __gmpfr_emin with rnd_mode == MPFR_RNDN, rb = 0 and sb <> 0 */
+static void
+test_underflow (void)
+{
+ mpfr_t x, y;
+ mpfr_exp_t emin;
+
+ emin = mpfr_get_emin ();
+ mpfr_set_emin (0);
+
+ mpfr_init2 (x, 24);
+ mpfr_init2 (y, 24);
+
+ mpfr_set_ui_2exp (x, 11863283, -24, MPFR_RNDN);
+ /* x^2 = 0.011111111111111111111111101101100111111010101001*2^(-48)
+ thus we have an underflow */
+ mpfr_clear_underflow ();
+ mpfr_sqr (y, x, MPFR_RNDN);
+ MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 1, -1) == 0);
+ MPFR_ASSERTN(mpfr_underflow_p ());
+
+ mpfr_clear (y);
+ mpfr_clear (x);
+
+ mpfr_set_emin (emin);
+}
+
/* Test of a bug seen with GCC 4.5.2 and GMP 5.0.1 on m68k (m68000 target).
https://sympa.inria.fr/sympa/arc/mpfr/2011-05/msg00003.html
https://sympa.inria.fr/sympa/arc/mpfr/2011-05/msg00041.html
@@ -161,8 +188,9 @@ main (void)
tests_start_mpfr ();
check_mpn_sqr ();
-
check_special ();
+ test_underflow ();
+
for (p = MPFR_PREC_MIN; p < 200; p++)
check_random (p);