summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2018-04-12 13:34:16 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2018-04-12 13:34:16 +0000
commitcbc0d14869b7df645ad4526dfa108bc21142c6da (patch)
tree1ad4d3f298bb45a8da3bfbae223f0aa9809f6dd5
parente0f43e58ead1df3d365aa72ec30477bf2a743823 (diff)
downloadmpfr-cbc0d14869b7df645ad4526dfa108bc21142c6da.tar.gz
[src/fma.c] Fixed sign related bug in overflow case.
[tests/tfma.c] Added test_overflow5 test for this bug. git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@12587 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--src/fma.c2
-rw-r--r--tests/tfma.c83
2 files changed, 84 insertions, 1 deletions
diff --git a/src/fma.c b/src/fma.c
index 9794bbf8b..eec08cf99 100644
--- a/src/fma.c
+++ b/src/fma.c
@@ -240,7 +240,7 @@ mpfr_fma (mpfr_ptr s, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z,
{
MPFR_GROUP_CLEAR (group);
MPFR_SAVE_EXPO_FREE (expo);
- return mpfr_overflow (s, rnd_mode, MPFR_SIGN (z));
+ return mpfr_overflow (s, rnd_mode, MPFR_SIGN (u));
}
/* E(x) + E(y) <= emax+2, therefore |x*y| < 2^(emax+2), and
diff --git a/tests/tfma.c b/tests/tfma.c
index 82554a272..aa77de2da 100644
--- a/tests/tfma.c
+++ b/tests/tfma.c
@@ -335,6 +335,88 @@ test_overflow4 (void)
}
static void
+test_overflow5 (void)
+{
+ mpfr_t x, y, z, r1, r2;
+ mpfr_exp_t old_emax, emax;
+ int inex1, inex2;
+ int ei, i, rnd;
+ unsigned int neg, negr;
+
+ old_emax = mpfr_get_emax ();
+
+ for (ei = 0; ei <= 1; ei++)
+ {
+ emax = ei ? MPFR_EMAX_MAX : 1024;
+ set_emax (emax);
+
+ mpfr_init2 (x, 123);
+ mpfr_init2 (y, 45);
+ mpfr_init2 (z, 67);
+ mpfr_inits2 (89, r1, r2, (mpfr_ptr) 0);
+
+ mpfr_set_ui_2exp (x, 1, emax - 1, MPFR_RNDN);
+
+ for (i = 3; i <= 17; i++)
+ {
+ mpfr_set_ui (y, i, MPFR_RNDN);
+ mpfr_set_ui_2exp (z, 1, emax - 1, MPFR_RNDN);
+ for (neg = 0; neg < 8; neg++)
+ {
+ mpfr_setsign (x, x, neg & 1, MPFR_RNDN);
+ mpfr_setsign (y, y, neg & 2, MPFR_RNDN);
+ mpfr_setsign (z, z, neg & 4, MPFR_RNDN);
+
+ /* |x*y + z| = (i +/- 1) * 2^(emax - 1) >= 2^emax (overflow)
+ and x*y + z has the same sign as x*y. */
+ negr = (neg ^ (neg >> 1)) & 1;
+
+ RND_LOOP (rnd)
+ {
+ mpfr_set_inf (r1, 1);
+ if (MPFR_IS_LIKE_RNDZ ((mpfr_rnd_t) rnd, negr))
+ {
+ mpfr_nextbelow (r1);
+ inex1 = -1;
+ }
+ else
+ inex1 = 1;
+
+ if (negr)
+ {
+ mpfr_neg (r1, r1, MPFR_RNDN);
+ inex1 = - inex1;
+ }
+
+ mpfr_clear_flags ();
+ inex2 = mpfr_fma (r2, x, y, z, rnd);
+ MPFR_ASSERTN (__gmpfr_flags ==
+ (MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW));
+
+ if (! (mpfr_equal_p (r1, r2) && SAME_SIGN (inex1, inex2)))
+ {
+ printf ("Error in test_overflow5 for "
+ "ei=%d i=%d neg=%u %s\n", ei, i, neg,
+ mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
+ printf ("Expected ");
+ mpfr_dump (r1);
+ printf ("with inex = %d\n", inex1);
+ printf ("Got ");
+ mpfr_dump (r2);
+ printf ("with inex = %d\n", inex2);
+ exit (1);
+ }
+ } /* rnd */
+ } /* neg */
+ } /* i */
+
+ mpfr_clears (x, y, z, r1, r2, (mpfr_ptr) 0);
+ } /* ei */
+
+ set_emax (old_emax);
+}
+
+static void
test_underflow1 (void)
{
mpfr_t x, y, z, r;
@@ -1013,6 +1095,7 @@ main (int argc, char *argv[])
test_overflow2 ();
test_overflow3 ();
test_overflow4 ();
+ test_overflow5 ();
test_underflow1 ();
test_underflow2 ();
test_underflow3 (1);