summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2005-03-09 15:14:46 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2005-03-09 15:14:46 +0000
commit279294ebc432bbb53b66eff8c91d1d59c6bb06c1 (patch)
tree410bb0580d13f91dea61961606621495cda8a1db
parent3cdc1ee505bde7fe93b1ebdb1530be3670e0877c (diff)
downloadmpfr-279294ebc432bbb53b66eff8c91d1d59c6bb06c1.tar.gz
Ported bug fix in case of reuse of variable (a,b,a) with
Exp(b) = Exp(a) + Prec(b) to the 2.1 branch. git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/mpfr-2-1-branch@3382 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r--add1sp.c44
-rw-r--r--tests/tadd1sp.c13
2 files changed, 37 insertions, 20 deletions
diff --git a/add1sp.c b/add1sp.c
index 6d51b55f3..1690ff88d 100644
--- a/add1sp.c
+++ b/add1sp.c
@@ -1,7 +1,7 @@
/* mpfr_add1sp -- internal function to perform a "real" addition
All the op must have the same precision
-Copyright 2004 Free Software Foundation.
+Copyright 2004, 2005 Free Software Foundation.
Contributed by the Spaces project, INRIA Lorraine.
This file is part of the MPFR Library.
@@ -101,29 +101,34 @@ mpfr_add1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mp_rnd_t rnd_mode)
else
goto add_one_ulp;
}
- else if (MPFR_UNLIKELY(d >= p))
+ else if (MPFR_UNLIKELY (d >= p))
{
- if (MPFR_LIKELY(d > p))
+ if (MPFR_LIKELY (d > p))
{
/* d > p : Copy B in A */
- ap = MPFR_MANT(a);
- MPN_COPY (ap, MPFR_MANT(b), n);
/* Away: Add 1
Nearest: Trunc
Zero: Trunc */
- if (MPFR_LIKELY(rnd_mode==GMP_RNDN))
- { inexact = -1; goto set_exponent; }
- MPFR_UPDATE_RND_MODE(rnd_mode, MPFR_IS_NEG(b));
- if (rnd_mode==GMP_RNDZ)
- { inexact = -1; goto set_exponent; }
+ if (MPFR_LIKELY (rnd_mode==GMP_RNDN
+ || MPFR_IS_LIKE_RNDZ (rnd_mode, MPFR_IS_NEG (b))))
+ {
+ copy_set_exponent:
+ ap = MPFR_MANT (a);
+ MPN_COPY (ap, MPFR_MANT(b), n);
+ inexact = -1;
+ goto set_exponent;
+ }
else
- goto add_one_ulp;
+ {
+ copy_add_one_ulp:
+ ap = MPFR_MANT(a);
+ MPN_COPY (ap, MPFR_MANT(b), n);
+ goto add_one_ulp;
+ }
}
else
{
/* d==p : Copy B in A */
- ap = MPFR_MANT(a);
- MPN_COPY (ap, MPFR_MANT(b), n);
/* Away: Add 1
Nearest: Even Rule if C is a power of 2, else Add 1
Zero: Trunc */
@@ -139,17 +144,16 @@ mpfr_add1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mp_rnd_t rnd_mode)
} while (k>=0 && cp[k]==0);
if (MPFR_UNLIKELY(k<0))
/* Power of 2: Even rule */
- if ((ap[0]&(MPFR_LIMB_ONE<<sh))==0)
- { inexact = -1; goto set_exponent; }
+ if ((MPFR_MANT (b)[0]&(MPFR_LIMB_ONE<<sh))==0)
+ goto copy_set_exponent;
}
/* Not a Power of 2 */
- goto add_one_ulp;
+ goto copy_add_one_ulp;
}
- MPFR_UPDATE_RND_MODE(rnd_mode, MPFR_IS_NEG(b));
- if (rnd_mode==GMP_RNDZ)
- { inexact = -1; goto set_exponent; }
+ else if (MPFR_IS_LIKE_RNDZ (rnd_mode, MPFR_IS_NEG (b)))
+ goto copy_set_exponent;
else
- goto add_one_ulp;
+ goto copy_add_one_ulp;
}
}
else
diff --git a/tests/tadd1sp.c b/tests/tadd1sp.c
index 52a7f9bc2..b7f1c28da 100644
--- a/tests/tadd1sp.c
+++ b/tests/tadd1sp.c
@@ -158,5 +158,18 @@ void check_special(void)
STD_ERROR2;
}
+ mpfr_set_prec (c, 2);
+ mpfr_set_prec (a1, 2);
+ mpfr_set_prec (a2, 2);
+ mpfr_set_str_binary (c, "1.0e1");
+ mpfr_set_str_binary (a2, "1.1e-1");
+ mpfr_set_str_binary (a1, "0.11E2");
+ mpfr_add1sp (a2, c, a2, GMP_RNDN);
+ if (mpfr_cmp (a1, a2))
+ {
+ printf ("Regression reuse test failed!\n");
+ exit (1);
+ }
+
mpfr_clears(a1,a2,b,c,NULL);
}