diff options
author | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2018-02-15 18:42:18 +0000 |
---|---|---|
committer | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2018-02-15 18:42:18 +0000 |
commit | 2d620bac6f1ac70d854da8d5c91c0e8c05e24a62 (patch) | |
tree | c7be672e886e4f7f315bf9a837ee186c2595ac51 /src/sub1sp.c | |
parent | c52d8468fcdfb68470eb191e2bdbcfdead5d5a62 (diff) | |
download | mpfr-2d620bac6f1ac70d854da8d5c91c0e8c05e24a62.tar.gz |
[src/sub1sp.c] fixed bug20180215()
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@12251 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'src/sub1sp.c')
-rw-r--r-- | src/sub1sp.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/src/sub1sp.c b/src/sub1sp.c index de22c5284..4f2360fe4 100644 --- a/src/sub1sp.c +++ b/src/sub1sp.c @@ -1620,8 +1620,8 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) mpn_sub_n (ap, MPFR_MANT(b), cp, n); /* mpfr_print_mant_binary("Sub= ", ap, p); */ - /* Normalize: we lose at most one bit */ - if (MPFR_UNLIKELY(MPFR_LIMB_MSB(ap[n-1]) == 0)) + /* Normalize: we lose at most one bit */ + if (MPFR_LIMB_MSB(ap[n-1]) == 0) { /* High bit is not set and we have to fix it! */ /* We can assume B >= 2^(p+1) up to scaling by 2^e, @@ -1645,16 +1645,27 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) } MPFR_ASSERTD( !(ap[0] & ~mask) ); + /* if {ap, n} is a power of 2 and rb <> 0, we subtract 1 */ + 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; + } + /* Rounding */ if (MPFR_LIKELY(rnd_mode == MPFR_RNDF)) goto truncate; else if (MPFR_LIKELY(rnd_mode == MPFR_RNDN)) { - if (MPFR_LIKELY(rb == 0)) + if (rb == 0) goto truncate; else if (sb != 0 || (ap[0] & (MPFR_LIMB_ONE << sh)) != 0) goto next_below; - else + else /* rb = 1, sb = 0, even rule */ goto truncate; } else |