diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2005-03-09 15:14:46 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2005-03-09 15:14:46 +0000 |
commit | 279294ebc432bbb53b66eff8c91d1d59c6bb06c1 (patch) | |
tree | 410bb0580d13f91dea61961606621495cda8a1db | |
parent | 3cdc1ee505bde7fe93b1ebdb1530be3670e0877c (diff) | |
download | mpfr-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.c | 44 | ||||
-rw-r--r-- | tests/tadd1sp.c | 13 |
2 files changed, 37 insertions, 20 deletions
@@ -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); } |