summaryrefslogtreecommitdiff
path: root/src/fmma.c
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2016-01-16 08:29:34 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2016-01-16 08:29:34 +0000
commita672495b2d38557c2ea044f3ae48d619d1dcdc6d (patch)
tree8f6f274fd8bdd1403f2042c77c0f6a8da98cc66a /src/fmma.c
parentb12a5184c074f0756527379522df35e5357ae68c (diff)
downloadmpfr-a672495b2d38557c2ea044f3ae48d619d1dcdc6d.tar.gz
try to fix bugs in fmma (work in progress)
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@9820 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'src/fmma.c')
-rw-r--r--src/fmma.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/fmma.c b/src/fmma.c
index 8692061ab..80b1f9edc 100644
--- a/src/fmma.c
+++ b/src/fmma.c
@@ -53,6 +53,7 @@ mpfr_fmma_fast (mpfr_ptr z, mpfr_srcptr a, mpfr_srcptr b, mpfr_srcptr c,
mpfr_t u, v;
mp_size_t an, bn, cn, dn;
mpfr_limb_ptr up, vp;
+ unsigned int saved_flags = __gmpfr_flags;
MPFR_TMP_DECL(marker);
MPFR_SAVE_EXPO_DECL (expo);
@@ -76,6 +77,8 @@ mpfr_fmma_fast (mpfr_ptr z, mpfr_srcptr a, mpfr_srcptr b, mpfr_srcptr c,
{
mpn_lshift (up, up, an + bn, 1);
MPFR_SET_EXP (u, MPFR_EXP(a) + MPFR_EXP(b) - 1);
+ if (MPFR_UNLIKELY(MPFR_EXP(u) == __MPFR_EXP_INF))
+ goto failure;
}
else
MPFR_SET_EXP (u, MPFR_EXP(a) + MPFR_EXP(b));
@@ -89,6 +92,8 @@ mpfr_fmma_fast (mpfr_ptr z, mpfr_srcptr a, mpfr_srcptr b, mpfr_srcptr c,
{
mpn_lshift (vp, vp, cn + dn, 1);
MPFR_SET_EXP (v, MPFR_EXP(c) + MPFR_EXP(d) - 1);
+ if (MPFR_UNLIKELY(MPFR_EXP(v) == __MPFR_EXP_INF))
+ goto failure;
}
else
MPFR_SET_EXP (v, MPFR_EXP(c) + MPFR_EXP(d));
@@ -107,6 +112,12 @@ mpfr_fmma_fast (mpfr_ptr z, mpfr_srcptr a, mpfr_srcptr b, mpfr_srcptr c,
MPFR_SAVE_EXPO_FREE (expo);
return mpfr_check_range (z, inex, rnd);
+
+ failure:
+ __gmpfr_flags = saved_flags;
+ MPFR_TMP_FREE(marker);
+ MPFR_SAVE_EXPO_FREE (expo);
+ return mpfr_fmma_slow (z, a, b, c, d, rnd);
}
/* z <- a*b + c*d */