diff options
author | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2018-08-21 14:39:43 +0000 |
---|---|---|
committer | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2018-08-21 14:39:43 +0000 |
commit | 0308b7aabbcda50a2ee8c339fb5f1995d5ed4b1b (patch) | |
tree | 230b141b6ed9e8cef0d285a2b9873eb81a2147da /src/sub1sp.c | |
parent | 5520154b55917b0e707c23cf0a7f7b55796d9b9c (diff) | |
download | mpfr-0308b7aabbcda50a2ee8c339fb5f1995d5ed4b1b.tar.gz |
[src/sub1sp.c] fixed bug20180813
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@13001 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'src/sub1sp.c')
-rw-r--r-- | src/sub1sp.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/src/sub1sp.c b/src/sub1sp.c index efd4802ac..c1012728e 100644 --- a/src/sub1sp.c +++ b/src/sub1sp.c @@ -1661,15 +1661,25 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) /* We don't have anymore a valid Cp+1! But since B-C >= 2^p+1, the final sub can't unnormalize */ } - /* if {ap, n} is a power of 2 and rb <> 0, we can subtract 1 */ - else if (rb && MPFR_UNLIKELY(MPFR_LIMB_MSB(ap[n-1]) == MPFR_LIMB_HIGHBIT - && mpfr_powerof2_raw (a))) + /* special case if {ap, n} is a power of 2, since rb/sb correspond to + negative values, thus we have to consider rbb and sbb instead */ + else if (MPFR_UNLIKELY(MPFR_LIMB_MSB(ap[n-1]) == MPFR_LIMB_HIGHBIT + && mpfr_powerof2_raw (a))) { - mpn_sub_1 (ap, ap, n, MPFR_LIMB_ONE << sh); - ap[n-1] |= MPFR_LIMB_HIGHBIT; - bx--; - rb = rbb; - sb = sbb; + if (rb) /* we can already subtract 1 */ + { + mpn_sub_1 (ap, ap, n, MPFR_LIMB_ONE << sh); + ap[n-1] |= MPFR_LIMB_HIGHBIT; + bx--; + rb = rbb; + } + else /* case rb = 0: we set rb to rbb to force the 'next_below' + branch when rbb != 0 and sbb != 0 */ + { + rb = rbb; + rbb = 0; + } + sb = sbb; } MPFR_ASSERTD( !(ap[0] & ~mask) ); @@ -1678,9 +1688,11 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) goto truncate; else if (MPFR_LIKELY(rnd_mode == MPFR_RNDN)) { - if (rb == 0) + if (rb == 0) /* we have to subtract less than 1/2 ulp */ goto truncate; else if (sb != 0 || (ap[0] & (MPFR_LIMB_ONE << sh)) != 0) + /* rb = 1 here: if sb != 0 we have to subtract more than 1/2 ulp, + likewise if sb = 0 and the significand is odd */ goto next_below; else /* rb = 1, sb = 0, even rule */ goto truncate; @@ -1723,7 +1735,9 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) we need one more bit! */ MPFR_ASSERTD(rbb != MPFR_LIMB_MAX); if ((rnd_mode == MPFR_RNDZ && rb == 0) || /* case 2b */ - (rnd_mode == MPFR_RNDN && rb == 0 && rbb != 0 && sb != 0) || /* case 2e */ + /* note for the following line: even if rb=0, rbb<>0 and sb=0, + we round to 111...111 */ + (rnd_mode == MPFR_RNDN && rb == 0 && rbb != 0) || /* case 2e */ (rnd_mode == MPFR_RNDN && rb != 0 && rbb == 0) || /* case 2h */ (rnd_mode == MPFR_RNDA && rb != 0) || /* case 2c' */ (rb != 0 && sb == 0)) /* exact */ |