diff options
Diffstat (limited to 'Build/source/libs/mpfr/mpfr-src/src/sub1sp.c')
-rw-r--r-- | Build/source/libs/mpfr/mpfr-src/src/sub1sp.c | 1418 |
1 files changed, 1211 insertions, 207 deletions
diff --git a/Build/source/libs/mpfr/mpfr-src/src/sub1sp.c b/Build/source/libs/mpfr/mpfr-src/src/sub1sp.c index 67d597677bb..bc776ee1b55 100644 --- a/Build/source/libs/mpfr/mpfr-src/src/sub1sp.c +++ b/Build/source/libs/mpfr/mpfr-src/src/sub1sp.c @@ -1,4 +1,4 @@ -/* mpfr_sub1sp -- internal function to perform a "real" substraction +/* mpfr_sub1sp -- internal function to perform a "real" subtraction All the op must have the same precision Copyright 2003-2017 Free Software Foundation, Inc. @@ -25,15 +25,20 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., #include "mpfr-impl.h" /* Check if we have to check the result of mpfr_sub1sp with mpfr_sub1 */ -#ifdef MPFR_WANT_ASSERT -# if MPFR_WANT_ASSERT >= 2 +#if MPFR_WANT_ASSERT >= 2 -int mpfr_sub1sp2 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode); +int mpfr_sub1sp_ref (mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_rnd_t); int mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) { mpfr_t tmpa, tmpb, tmpc; + mpfr_flags_t old_flags, flags, flags2; int inexb, inexc, inexact, inexact2; + if (rnd_mode == MPFR_RNDF) + return mpfr_sub1sp_ref (a, b, c, rnd_mode); + + old_flags = __gmpfr_flags; + mpfr_init2 (tmpa, MPFR_PREC (a)); mpfr_init2 (tmpb, MPFR_PREC (b)); mpfr_init2 (tmpc, MPFR_PREC (c)); @@ -44,40 +49,993 @@ int mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) inexc = mpfr_set (tmpc, c, MPFR_RNDN); MPFR_ASSERTN (inexc == 0); + MPFR_ASSERTN (__gmpfr_flags == old_flags); + inexact2 = mpfr_sub1 (tmpa, tmpb, tmpc, rnd_mode); - inexact = mpfr_sub1sp2(a, b, c, rnd_mode); + flags2 = __gmpfr_flags; - if (mpfr_cmp (tmpa, a) || inexact != inexact2) + __gmpfr_flags = old_flags; + inexact = mpfr_sub1sp_ref (a, b, c, rnd_mode); + flags = __gmpfr_flags; + + if (! mpfr_equal_p (tmpa, a) || inexact != inexact2 || flags != flags2) { fprintf (stderr, "sub1 & sub1sp return different values for %s\n" "Prec_a = %lu, Prec_b = %lu, Prec_c = %lu\nB = ", - mpfr_print_rnd_mode (rnd_mode), (unsigned long) MPFR_PREC (a), - (unsigned long) MPFR_PREC (b), (unsigned long) MPFR_PREC (c)); - mpfr_fprint_binary (stderr, tmpb); - fprintf (stderr, "\nC = "); - mpfr_fprint_binary (stderr, tmpc); - fprintf (stderr, "\nSub1 : "); - mpfr_fprint_binary (stderr, tmpa); - fprintf (stderr, "\nSub1sp: "); - mpfr_fprint_binary (stderr, a); - fprintf (stderr, "\nInexact sp = %d | Inexact = %d\n", - inexact, inexact2); + mpfr_print_rnd_mode (rnd_mode), + (unsigned long) MPFR_PREC (a), + (unsigned long) MPFR_PREC (b), + (unsigned long) MPFR_PREC (c)); + mpfr_fdump (stderr, tmpb); + fprintf (stderr, "C = "); + mpfr_fdump (stderr, tmpc); + fprintf (stderr, "sub1 : "); + mpfr_fdump (stderr, tmpa); + fprintf (stderr, "sub1sp: "); + mpfr_fdump (stderr, a); + fprintf (stderr, "Inexact sp = %d | Inexact = %d\n" + "Flags sp = %u | Flags = %u\n", + inexact, inexact2, flags, flags2); MPFR_ASSERTN (0); } mpfr_clears (tmpa, tmpb, tmpc, (mpfr_ptr) 0); return inexact; } -# define mpfr_sub1sp mpfr_sub1sp2 -# endif -#endif +# define mpfr_sub1sp mpfr_sub1sp_ref +#endif /* MPFR_WANT_ASSERT >= 2 */ + +#if !defined(MPFR_GENERIC_ABI) + +/* special code for p < GMP_NUMB_BITS */ +static int +mpfr_sub1sp1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode, + mpfr_prec_t p) +{ + mpfr_exp_t bx = MPFR_GET_EXP (b); + mpfr_exp_t cx = MPFR_GET_EXP (c); + mp_limb_t *ap = MPFR_MANT(a); + mp_limb_t *bp = MPFR_MANT(b); + mp_limb_t *cp = MPFR_MANT(c); + mpfr_prec_t cnt, INITIALIZED(sh); + mp_limb_t rb; /* round bit */ + mp_limb_t sb; /* sticky bit */ + mp_limb_t a0; + mp_limb_t mask; + mpfr_uexp_t d; + + MPFR_ASSERTD(p < GMP_NUMB_BITS); + + if (bx == cx) + { + a0 = bp[0] - cp[0]; + if (a0 == 0) /* result is zero */ + { + if (rnd_mode == MPFR_RNDD) + MPFR_SET_NEG(a); + else + MPFR_SET_POS(a); + MPFR_SET_ZERO(a); + MPFR_RET (0); + } + else if (a0 > bp[0]) /* borrow: |c| > |b| */ + { + MPFR_SET_OPPOSITE_SIGN (a, b); + a0 = -a0; + } + else /* bp[0] > cp[0] */ + MPFR_SET_SAME_SIGN (a, b); + + /* now a0 != 0 */ + MPFR_ASSERTD(a0 != 0); + count_leading_zeros (cnt, a0); + ap[0] = a0 << cnt; + bx -= cnt; + rb = sb = 0; + /* Note: sh is not initialized, but will not be used in this case. */ + } + else if (bx > cx) + { + MPFR_SET_SAME_SIGN (a, b); + BGreater1: + d = (mpfr_uexp_t) bx - cx; + sh = GMP_NUMB_BITS - p; + mask = MPFR_LIMB_MASK(sh); + if (d < GMP_NUMB_BITS) + { + sb = - (cp[0] << (GMP_NUMB_BITS - d)); /* neglected part of -c */ + /* Note that "a0 = bp[0] - (cp[0] >> d) - (sb != 0);" is faster + on some other machines and has no immediate dependencies for + the first subtraction. In the future, make sure that the code + is recognized as a *single* subtraction with borrow and/or use + a builtin when available (currently provided by Clang, but not + by GCC); create a new macro for that. See the TODO later. + Note also that with Clang, the constant 0 for the first + subtraction instead of a variable breaks the optimization: + https://llvm.org/bugs/show_bug.cgi?id=31754 */ + a0 = bp[0] - (sb != 0) - (cp[0] >> d); + /* a0 cannot be zero here since: + a) if d >= 2, then a0 >= 2^(w-1) - (2^(w-2)-1) with + w = GMP_NUMB_BITS, thus a0 - 1 >= 2^(w-2), + b) if d = 1, then since p < GMP_NUMB_BITS we have sb=0. + */ + MPFR_ASSERTD(a0 > 0); + count_leading_zeros (cnt, a0); + if (cnt) + a0 = (a0 << cnt) | (sb >> (GMP_NUMB_BITS - cnt)); + sb <<= cnt; + bx -= cnt; + /* sh > 0 since p < GMP_NUMB_BITS */ + MPFR_ASSERTD(sh > 0); + rb = a0 & (MPFR_LIMB_ONE << (sh - 1)); + sb |= (a0 & mask) ^ rb; + ap[0] = a0 & ~mask; + } + else /* d >= GMP_NUMB_BITS */ + { + if (bp[0] > MPFR_LIMB_HIGHBIT) + { + /* We compute b - ulp(b), and the remainder ulp(b) - c satisfies: + 1/2 ulp(b) < ulp(b) - c < ulp(b), thus rb = sb = 1. */ + ap[0] = bp[0] - (MPFR_LIMB_ONE << sh); + rb = 1; + } + else + { + /* Warning: since we have an exponent decrease, when + p = GMP_NUMB_BITS - 1 and d = GMP_NUMB_BITS, the round bit + corresponds to the upper bit of -c. In that case rb = 0 and + sb = 1, except when c0 = MPFR_LIMB_HIGHBIT where rb = 1 and + sb = 0. */ + rb = sh > 1 || d > GMP_NUMB_BITS || cp[0] == MPFR_LIMB_HIGHBIT; + /* sb=1 below is incorrect when p = GMP_NUMB_BITS - 1, + d = GMP_NUMB_BITS and c0 = MPFR_LIMB_HIGHBIT, but in + that case the even rule wound round up too. */ + ap[0] = ~mask; + bx --; + /* Warning: if d = GMP_NUMB_BITS and c0 = 1000...000, then + b0 - c0 = |0111...111|1000...000|, which after the shift + becomes |111...111|000...000| thus if p = GMP_NUMB_BITS-1 + we have rb = 1 but sb = 0. However in this case the round + even rule will round up, which is what we get with sb = 1: + the final result will be correct, while sb is incorrect. */ + } + sb = 1; + } + } + else /* cx > bx */ + { + mpfr_exp_t tx; + mp_limb_t *tp; + tx = bx; bx = cx; cx = tx; + tp = bp; bp = cp; cp = tp; + MPFR_SET_OPPOSITE_SIGN (a, b); + goto BGreater1; + } + + /* now perform rounding */ + + /* Warning: MPFR considers underflow *after* rounding with an unbounded + exponent range. However since b and c have same precision p, they are + multiples of 2^(emin-p), likewise for b-c. Thus if bx < emin, the + subtraction (with an unbounded exponent range) is exact, so that bx is + also the exponent after rounding with an unbounded exponent range. */ + if (MPFR_UNLIKELY(bx < __gmpfr_emin)) + { + /* For RNDN, mpfr_underflow always rounds away, thus for |a| <= 2^(emin-2) + we have to change to RNDZ. This corresponds to: + (a) either bx < emin - 1 + (b) or bx = emin - 1 and ap[0] = 1000....000 (in this case necessarily + rb = sb = 0 since b-c is multiple of 2^(emin-p) */ + if (rnd_mode == MPFR_RNDN && + (bx < __gmpfr_emin - 1 || ap[0] == MPFR_LIMB_HIGHBIT)) + { + MPFR_ASSERTD(rb == 0 && sb == 0); + rnd_mode = MPFR_RNDZ; + } + return mpfr_underflow (a, rnd_mode, MPFR_SIGN(a)); + } + + MPFR_SET_EXP (a, bx); + if ((rb == 0 && sb == 0) || rnd_mode == MPFR_RNDF) + MPFR_RET (0); + else if (rnd_mode == MPFR_RNDN) + { + if (rb == 0 || (sb == 0 && (ap[0] & (MPFR_LIMB_ONE << sh)) == 0)) + goto truncate; + else + goto add_one_ulp; + } + else if (MPFR_IS_LIKE_RNDZ(rnd_mode, MPFR_IS_NEG(a))) + { + truncate: + MPFR_RET(-MPFR_SIGN(a)); + } + else /* round away from zero */ + { + add_one_ulp: + ap[0] += MPFR_LIMB_ONE << sh; + if (MPFR_UNLIKELY(ap[0] == 0)) + { + ap[0] = MPFR_LIMB_HIGHBIT; + /* Note: bx+1 cannot exceed __gmpfr_emax, since |a| <= |b|, thus + bx+1 is at most equal to the original exponent of b. */ + MPFR_ASSERTD(bx + 1 <= __gmpfr_emax); + MPFR_SET_EXP (a, bx + 1); + } + MPFR_RET(MPFR_SIGN(a)); + } +} + +/* special code for p = GMP_NUMB_BITS */ +static int +mpfr_sub1sp1n (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) +{ + mpfr_exp_t bx = MPFR_GET_EXP (b); + mpfr_exp_t cx = MPFR_GET_EXP (c); + mp_limb_t *ap = MPFR_MANT(a); + mp_limb_t *bp = MPFR_MANT(b); + mp_limb_t *cp = MPFR_MANT(c); + mpfr_prec_t cnt; + mp_limb_t rb; /* round bit */ + mp_limb_t sb; /* sticky bit */ + mp_limb_t a0; + mpfr_uexp_t d; + + MPFR_ASSERTD(MPFR_PREC(a) == GMP_NUMB_BITS); + MPFR_ASSERTD(MPFR_PREC(b) == GMP_NUMB_BITS); + MPFR_ASSERTD(MPFR_PREC(c) == GMP_NUMB_BITS); + + if (bx == cx) + { + a0 = bp[0] - cp[0]; + if (a0 == 0) /* result is zero */ + { + if (rnd_mode == MPFR_RNDD) + MPFR_SET_NEG(a); + else + MPFR_SET_POS(a); + MPFR_SET_ZERO(a); + MPFR_RET (0); + } + else if (a0 > bp[0]) /* borrow: |c| > |b| */ + { + MPFR_SET_OPPOSITE_SIGN (a, b); + a0 = -a0; + } + else /* bp[0] > cp[0] */ + MPFR_SET_SAME_SIGN (a, b); + + /* now a0 != 0 */ + MPFR_ASSERTD(a0 != 0); + count_leading_zeros (cnt, a0); + ap[0] = a0 << cnt; + bx -= cnt; + rb = sb = 0; + } + else if (bx > cx) + { + MPFR_SET_SAME_SIGN (a, b); + BGreater1: + d = (mpfr_uexp_t) bx - cx; + if (d < GMP_NUMB_BITS) + { + sb = - (cp[0] << (GMP_NUMB_BITS - d)); /* neglected part of -c */ + a0 = bp[0] - (sb != 0) - (cp[0] >> d); + /* a0 can only be zero when d=1, b0 = B/2, and c0 = B-1, where + B = 2^GMP_NUMB_BITS, thus b0 - c0/2 = 1/2 */ + if (a0 == MPFR_LIMB_ZERO) + { + bx -= GMP_NUMB_BITS; + ap[0] = MPFR_LIMB_HIGHBIT; + rb = sb = 0; + } + else + { + count_leading_zeros (cnt, a0); + if (cnt) + a0 = (a0 << cnt) | (sb >> (GMP_NUMB_BITS - cnt)); + sb <<= cnt; + bx -= cnt; + rb = sb & MPFR_LIMB_HIGHBIT; + sb &= ~MPFR_LIMB_HIGHBIT; + ap[0] = a0; + } + } + else /* d >= GMP_NUMB_BITS */ + { + /* We compute b - ulp(b) */ + if (bp[0] > MPFR_LIMB_HIGHBIT) + { + /* If d = GMP_NUMB_BITS, rb = 0 and sb = 1, + unless c0 = MPFR_LIMB_HIGHBIT in which case rb = 1 and sb = 0. + If d > GMP_NUMB_BITS, rb = sb = 1. */ + rb = d > GMP_NUMB_BITS || cp[0] == MPFR_LIMB_HIGHBIT; + sb = d > GMP_NUMB_BITS || cp[0] != MPFR_LIMB_HIGHBIT; + ap[0] = bp[0] - MPFR_LIMB_ONE; + } + else + { + /* Warning: in this case a0 is shifted by one! + If d=GMP_NUMB_BITS: + (a) if c0 = MPFR_LIMB_HIGHBIT, a0 = 111...111, rb = sb = 0 + (b) otherwise, a0 = 111...110, rb = -c0 >= 01000...000, + sb = (-c0) << 2 + If d=GMP_NUMB_BITS+1: a0 = 111...111 + (c) if c0 = MPFR_LIMB_HIGHBIT, rb = 1 and sb = 0 + (d) otherwise rb = 0 and sb = 1 + If d > GMP_NUMB_BITS+1: + (e) a0 = 111...111, rb = sb = 1 + */ + bx --; + if (d == GMP_NUMB_BITS && cp[0] > MPFR_LIMB_HIGHBIT) + { /* case (b) */ + rb = (-cp[0]) >= (MPFR_LIMB_HIGHBIT >> 1); + sb = (-cp[0]) << 2; + ap[0] = -(MPFR_LIMB_ONE << 1); + } + else /* cases (a), (c), (d) and (e) */ + { + ap[0] = -MPFR_LIMB_ONE; + /* rb=1 in case (e) and case (c) */ + rb = d > GMP_NUMB_BITS + 1 + || (d == GMP_NUMB_BITS + 1 && cp[0] == MPFR_LIMB_HIGHBIT); + /* sb = 1 in case (d) and (e) */ + sb = d > GMP_NUMB_BITS + 1 + || (d == GMP_NUMB_BITS + 1 && cp[0] > MPFR_LIMB_HIGHBIT); + } + } + } + } + else /* cx > bx */ + { + mpfr_exp_t tx; + mp_limb_t *tp; + tx = bx; bx = cx; cx = tx; + tp = bp; bp = cp; cp = tp; + MPFR_SET_OPPOSITE_SIGN (a, b); + goto BGreater1; + } + + /* now perform rounding */ + + /* Warning: MPFR considers underflow *after* rounding with an unbounded + exponent range. However since b and c have same precision p, they are + multiples of 2^(emin-p), likewise for b-c. Thus if bx < emin, the + subtraction (with an unbounded exponent range) is exact, so that bx is + also the exponent after rounding with an unbounded exponent range. */ + if (MPFR_UNLIKELY(bx < __gmpfr_emin)) + { + /* For RNDN, mpfr_underflow always rounds away, thus for |a| <= 2^(emin-2) + we have to change to RNDZ. This corresponds to: + (a) either bx < emin - 1 + (b) or bx = emin - 1 and ap[0] = 1000....000 (in this case necessarily + rb = sb = 0 since b-c is multiple of 2^(emin-p) */ + if (rnd_mode == MPFR_RNDN && + (bx < __gmpfr_emin - 1 || ap[0] == MPFR_LIMB_HIGHBIT)) + { + MPFR_ASSERTD(rb == 0 && sb == 0); + rnd_mode = MPFR_RNDZ; + } + return mpfr_underflow (a, rnd_mode, MPFR_SIGN(a)); + } -/* Debugging support */ -#ifdef DEBUG -# undef DEBUG -# define DEBUG(x) (x) + MPFR_SET_EXP (a, bx); + if ((rb == 0 && sb == 0) || rnd_mode == MPFR_RNDF) + MPFR_RET (0); + else if (rnd_mode == MPFR_RNDN) + { + if (rb == 0 || (sb == 0 && (ap[0] & MPFR_LIMB_ONE) == 0)) + goto truncate; + else + goto add_one_ulp; + } + else if (MPFR_IS_LIKE_RNDZ(rnd_mode, MPFR_IS_NEG(a))) + { + truncate: + MPFR_RET(-MPFR_SIGN(a)); + } + else /* round away from zero */ + { + add_one_ulp: + ap[0] += MPFR_LIMB_ONE; + if (MPFR_UNLIKELY(ap[0] == 0)) + { + ap[0] = MPFR_LIMB_HIGHBIT; + /* Note: bx+1 cannot exceed __gmpfr_emax, since |a| <= |b|, thus + bx+1 is at most equal to the original exponent of b. */ + MPFR_ASSERTD(bx + 1 <= __gmpfr_emax); + MPFR_SET_EXP (a, bx + 1); + } + MPFR_RET(MPFR_SIGN(a)); + } +} + +/* special code for GMP_NUMB_BITS < p < 2*GMP_NUMB_BITS */ +static int +mpfr_sub1sp2 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode, + mpfr_prec_t p) +{ + mpfr_exp_t bx = MPFR_GET_EXP (b); + mpfr_exp_t cx = MPFR_GET_EXP (c); + mp_limb_t *ap = MPFR_MANT(a); + mp_limb_t *bp = MPFR_MANT(b); + mp_limb_t *cp = MPFR_MANT(c); + mpfr_prec_t cnt, INITIALIZED(sh); + mp_limb_t rb; /* round bit */ + mp_limb_t sb; /* sticky bit */ + mp_limb_t mask, a0, a1; + mpfr_uexp_t d; + + MPFR_ASSERTD(GMP_NUMB_BITS < p && p < 2 * GMP_NUMB_BITS); + + if (bx == cx) /* subtraction is exact in this case */ + { + /* first compute a0: if the compiler is smart enough, it will use the generated + borrow to get for free the term (bp[0] < cp[0]) */ + a0 = bp[0] - cp[0]; + a1 = bp[1] - cp[1] - (bp[0] < cp[0]); + if (a1 == 0 && a0 == 0) /* result is zero */ + { + if (rnd_mode == MPFR_RNDD) + MPFR_SET_NEG(a); + else + MPFR_SET_POS(a); + MPFR_SET_ZERO(a); + MPFR_RET (0); + } + else if (a1 >= bp[1]) /* borrow: |c| > |b| */ + { + MPFR_SET_OPPOSITE_SIGN (a, b); + /* a = b-c mod 2^(2*GMP_NUMB_BITS) */ + a0 = -a0; + a1 = -a1 - (a0 != 0); + } + else /* bp[0] > cp[0] */ + MPFR_SET_SAME_SIGN (a, b); + + if (a1 == 0) + { + a1 = a0; + a0 = 0; + bx -= GMP_NUMB_BITS; + } + + /* now a1 != 0 */ + MPFR_ASSERTD(a1 != 0); + count_leading_zeros (cnt, a1); + if (cnt) + { + ap[1] = (a1 << cnt) | (a0 >> (GMP_NUMB_BITS - cnt)); + ap[0] = a0 << cnt; + bx -= cnt; + } + else + { + ap[1] = a1; + ap[0] = a0; + } + rb = sb = 0; + /* Note: sh is not initialized, but will not be used in this case. */ + } + else if (bx > cx) + { + mp_limb_t t; + + MPFR_SET_SAME_SIGN (a, b); + BGreater2: + d = (mpfr_uexp_t) bx - cx; + sh = 2 * GMP_NUMB_BITS - p; + mask = MPFR_LIMB_MASK(sh); + if (d < GMP_NUMB_BITS) + { + t = (cp[1] << (GMP_NUMB_BITS - d)) | (cp[0] >> d); + /* TODO: Change the code to generate a full subtraction with borrow, + avoiding the test on sb and the corresponding correction. Note + that Clang has builtins: + http://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins + but the generated code may not be good: + https://llvm.org/bugs/show_bug.cgi?id=20748 + With the current source code, Clang generates on x86_64: + 1. sub %rsi,%rbx for the first subtraction in a1; + 2. sub %rdi,%rax for the subtraction in a0; + 3. sbb $0x0,%rbx for the second subtraction in a1, i.e. just + subtracting the borrow out from (2). + So, Clang recognizes the borrow, but doesn't merge (1) and (3). + Bug: https://llvm.org/bugs/show_bug.cgi?id=25858 + For GCC: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79173 + */ +#ifndef MPFR_FULLSUB + a0 = bp[0] - t; + a1 = bp[1] - (cp[1] >> d) - (bp[0] < t); + sb = cp[0] << (GMP_NUMB_BITS - d); /* neglected part of c */ + if (sb) + { + a1 -= (a0 == 0); + a0 --; + /* a = a1,a0 cannot become zero here, since: + a) if d >= 2, then a1 >= 2^(w-1) - (2^(w-2)-1) with + w = GMP_NUMB_BITS, thus a1 - 1 >= 2^(w-2), + b) if d = 1, then since p < 2*GMP_NUMB_BITS we have sb=0. */ + MPFR_ASSERTD(a1 > 0 || a0 > 0); + sb = -sb; /* 2^GMP_NUMB_BITS - sb */ + } #else -# define DEBUG(x) /**/ + sb = - (cp[0] << (GMP_NUMB_BITS - d)); + a0 = bp[0] - t - (sb != 0); + a1 = bp[1] - (cp[1] >> d) - (bp[0] < t || (bp[0] == t && sb != 0)); #endif + if (a1 == 0) + { + /* this implies d=1, which in turn implies sb=0 */ + MPFR_ASSERTD(sb == 0); + a1 = a0; + a0 = 0; /* should be a0 = sb */ + /* since sb=0 already, no need to set it to 0 */ + bx -= GMP_NUMB_BITS; + } + /* now a1 != 0 */ + MPFR_ASSERTD(a1 != 0); + count_leading_zeros (cnt, a1); + if (cnt) + { + ap[1] = (a1 << cnt) | (a0 >> (GMP_NUMB_BITS - cnt)); + a0 = (a0 << cnt) | (sb >> (GMP_NUMB_BITS - cnt)); + sb <<= cnt; + bx -= cnt; + } + else + ap[1] = a1; + /* sh > 0 since p < 2*GMP_NUMB_BITS */ + MPFR_ASSERTD(sh > 0); + rb = a0 & (MPFR_LIMB_ONE << (sh - 1)); + sb |= (a0 & mask) ^ rb; + ap[0] = a0 & ~mask; + } + else if (d < 2 * GMP_NUMB_BITS) + { /* GMP_NUMB_BITS <= d < 2*GMP_NUMB_BITS */ + /* warning: the most significant bit of sb might become the least + significant bit of a0 below */ + sb = (d == GMP_NUMB_BITS) ? cp[0] + : (cp[1] << (2*GMP_NUMB_BITS - d)) | (cp[0] != 0); + t = (cp[1] >> (d - GMP_NUMB_BITS)) + (sb != 0); + /* warning: t might overflow to 0 if d=GMP_NUMB_BITS and sb <> 0 */ + a0 = bp[0] - t; + a1 = bp[1] - (bp[0] < t) - (t == 0 && sb != 0); + sb = -sb; + /* since bp[1] has its most significant bit set, we can have an + exponent decrease of at most one */ + if (a1 < MPFR_LIMB_HIGHBIT) + { + ap[1] = (a1 << 1) | (a0 >> (GMP_NUMB_BITS - 1)); + a0 = (a0 << 1) | (sb >> (GMP_NUMB_BITS - 1)); + sb <<= 1; + bx --; + } + else + ap[1] = a1; + rb = a0 & (MPFR_LIMB_ONE << (sh - 1)); + sb |= (a0 & mask) ^ rb; + ap[0] = a0 & ~mask; + } + else /* d >= 2*GMP_NUMB_BITS */ + { + /* We compute b - ulp(b), and the remainder ulp(b) - c satisfies: + 1/2 ulp(b) < ulp(b) - c < ulp(b), thus rb = sb = 1, unless we + had an exponent decrease. */ + t = MPFR_LIMB_ONE << sh; + a0 = bp[0] - t; + a1 = bp[1] - (bp[0] < t); + if (a1 < MPFR_LIMB_HIGHBIT) + { + /* necessarily we had b = 1000...000 */ + /* Warning: since we have an exponent decrease, when + p = 2*GMP_NUMB_BITS - 1 and d = 2*GMP_NUMB_BITS, the round bit + corresponds to the upper bit of -c. In that case rb = 0 and + sb = 1, except when c = 1000...000 where rb = 1 and sb = 0. */ + rb = sh > 1 || d > 2 * GMP_NUMB_BITS + || (cp[1] == MPFR_LIMB_HIGHBIT && cp[0] == MPFR_LIMB_ZERO); + /* sb=1 below is incorrect when p = 2*GMP_NUMB_BITS - 1, + d = 2*GMP_NUMB_BITS and c = 1000...000, but in + that case the even rule wound round up too. */ + ap[0] = ~mask; + ap[1] = MPFR_LIMB_MAX; + bx --; + } + else + { + ap[0] = a0; + ap[1] = a1; + rb = 1; + } + sb = 1; + } + } + else /* cx > bx */ + { + mpfr_exp_t tx; + mp_limb_t *tp; + tx = bx; bx = cx; cx = tx; + tp = bp; bp = cp; cp = tp; + MPFR_SET_OPPOSITE_SIGN (a, b); + goto BGreater2; + } + + /* now perform rounding */ + + /* Warning: MPFR considers underflow *after* rounding with an unbounded + exponent range. However since b and c have same precision p, they are + multiples of 2^(emin-p), likewise for b-c. Thus if bx < emin, the + subtraction (with an unbounded exponent range) is exact, so that bx is + also the exponent after rounding with an unbounded exponent range. */ + if (MPFR_UNLIKELY(bx < __gmpfr_emin)) + { + /* for RNDN, mpfr_underflow always rounds away, thus for |a|<=2^(emin-2) + we have to change to RNDZ */ + if (rnd_mode == MPFR_RNDN && + (bx < __gmpfr_emin - 1 || + (ap[1] == MPFR_LIMB_HIGHBIT && ap[0] == 0))) + rnd_mode = MPFR_RNDZ; + return mpfr_underflow (a, rnd_mode, MPFR_SIGN(a)); + } + + MPFR_SET_EXP (a, bx); + if ((rb == 0 && sb == 0) || rnd_mode == MPFR_RNDF) + MPFR_RET (0); + else if (rnd_mode == MPFR_RNDN) + { + if (rb == 0 || (sb == 0 && (ap[0] & (MPFR_LIMB_ONE << sh)) == 0)) + goto truncate; + else + goto add_one_ulp; + } + else if (MPFR_IS_LIKE_RNDZ(rnd_mode, MPFR_IS_NEG(a))) + { + truncate: + MPFR_RET(-MPFR_SIGN(a)); + } + else /* round away from zero */ + { + add_one_ulp: + ap[0] += MPFR_LIMB_ONE << sh; + ap[1] += (ap[0] == 0); + if (MPFR_UNLIKELY(ap[1] == 0)) + { + ap[1] = MPFR_LIMB_HIGHBIT; + /* Note: bx+1 cannot exceed __gmpfr_emax, since |a| <= |b|, thus + bx+1 is at most equal to the original exponent of b. */ + MPFR_ASSERTD(bx + 1 <= __gmpfr_emax); + MPFR_SET_EXP (a, bx + 1); + } + MPFR_RET(MPFR_SIGN(a)); + } +} + +/* special code for 2*GMP_NUMB_BITS < p < 3*GMP_NUMB_BITS */ +static int +mpfr_sub1sp3 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode, + mpfr_prec_t p) +{ + mpfr_exp_t bx = MPFR_GET_EXP (b); + mpfr_exp_t cx = MPFR_GET_EXP (c); + mp_limb_t *ap = MPFR_MANT(a); + mp_limb_t *bp = MPFR_MANT(b); + mp_limb_t *cp = MPFR_MANT(c); + mpfr_prec_t cnt, INITIALIZED(sh); + mp_limb_t rb; /* round bit */ + mp_limb_t sb; /* sticky bit */ + mp_limb_t mask, a0, a1, a2; + mpfr_uexp_t d; + + MPFR_ASSERTD(2 * GMP_NUMB_BITS < p && p < 3 * GMP_NUMB_BITS); + + if (bx == cx) /* subtraction is exact in this case */ + { + a0 = bp[0] - cp[0]; + a1 = bp[1] - cp[1] - (bp[0] < cp[0]); + /* a borrow is generated for a when either bp[1] < cp[1], + or bp[1] = cp[1] and bp[0] < cp[0] */ + a2 = bp[2] - cp[2] + - (bp[1] < cp[1] || (bp[1] == cp[1] && bp[0] < cp[0])); + if (a2 == 0 && a1 == 0 && a0 == 0) /* result is zero */ + { + if (rnd_mode == MPFR_RNDD) + MPFR_SET_NEG(a); + else + MPFR_SET_POS(a); + MPFR_SET_ZERO(a); + MPFR_RET (0); + } + else if (a2 >= bp[2]) /* borrow: |c| > |b| */ + { + MPFR_SET_OPPOSITE_SIGN (a, b); + /* a = b-c mod 2^(3*GMP_NUMB_BITS) */ + a0 = -a0; + a1 = -a1 - (a0 != 0); + a2 = -a2 - (a0 != 0 || a1 != 0); + } + else /* bp[0] > cp[0] */ + MPFR_SET_SAME_SIGN (a, b); + + if (a2 == 0) + { + a2 = a1; + a1 = a0; + a0 = 0; + bx -= GMP_NUMB_BITS; + if (a2 == 0) + { + a2 = a1; + a1 = 0; + bx -= GMP_NUMB_BITS; + } + } + + /* now a2 != 0 */ + MPFR_ASSERTD(a2 != 0); + count_leading_zeros (cnt, a2); + if (cnt) + { + ap[2] = (a2 << cnt) | (a1 >> (GMP_NUMB_BITS - cnt)); + ap[1] = (a1 << cnt) | (a0 >> (GMP_NUMB_BITS - cnt)); + ap[0] = a0 << cnt; + bx -= cnt; + } + else + { + ap[2] = a2; + ap[1] = a1; + ap[0] = a0; + } + rb = sb = 0; + /* Note: sh is not initialized, but will not be used in this case. */ + } + else if (bx > cx) + { + MPFR_SET_SAME_SIGN (a, b); + BGreater2: + d = (mpfr_uexp_t) bx - cx; + sh = 3 * GMP_NUMB_BITS - p; + mask = MPFR_LIMB_MASK(sh); + if (d < GMP_NUMB_BITS) + { + mp_limb_t cy; + /* warning: we must have the most significant bit of sb correct + since it might become the round bit below */ + sb = cp[0] << (GMP_NUMB_BITS - d); /* neglected part of c */ + a0 = bp[0] - ((cp[1] << (GMP_NUMB_BITS - d)) | (cp[0] >> d)); + a1 = bp[1] - ((cp[2] << (GMP_NUMB_BITS - d)) | (cp[1] >> d)) + - (a0 > bp[0]); + cy = a1 > bp[1] || (a1 == bp[1] && a0 > bp[0]); /* borrow in a1 */ + a2 = bp[2] - (cp[2] >> d) - cy; + /* if sb is non-zero, subtract 1 from a2, a1, a0 since we want a + non-negative neglected part */ + if (sb) + { + a2 -= (a1 == 0 && a0 == 0); + a1 -= (a0 == 0); + a0 --; + /* a = a2,a1,a0 cannot become zero here, since: + a) if d >= 2, then a2 >= 2^(w-1) - (2^(w-2)-1) with + w = GMP_NUMB_BITS, thus a2 - 1 >= 2^(w-2), + b) if d = 1, then since p < 3*GMP_NUMB_BITS we have sb=0. */ + MPFR_ASSERTD(a2 > 0 || a1 > 0 || a0 > 0); + sb = -sb; /* 2^GMP_NUMB_BITS - sb */ + } + if (a2 == 0) + { + /* this implies d=1, which in turn implies sb=0 */ + MPFR_ASSERTD(sb == 0); + a2 = a1; + a1 = a0; + a0 = 0; /* should be a0 = sb */ + /* since sb=0 already, no need to set it to 0 */ + bx -= GMP_NUMB_BITS; + if (a2 == 0) + { + a2 = a1; + a1 = 0; /* should be a1 = a0 */ + bx -= GMP_NUMB_BITS; + } + } + /* now a1 != 0 */ + MPFR_ASSERTD(a2 != 0); + count_leading_zeros (cnt, a2); + if (cnt) + { + ap[2] = (a2 << cnt) | (a1 >> (GMP_NUMB_BITS - cnt)); + ap[1] = (a1 << cnt) | (a0 >> (GMP_NUMB_BITS - cnt)); + a0 = (a0 << cnt) | (sb >> (GMP_NUMB_BITS - cnt)); + sb <<= cnt; + bx -= cnt; + } + else + { + ap[2] = a2; + ap[1] = a1; + } + /* sh > 0 since p < 2*GMP_NUMB_BITS */ + MPFR_ASSERTD(sh > 0); + rb = a0 & (MPFR_LIMB_ONE << (sh - 1)); + sb |= (a0 & mask) ^ rb; + ap[0] = a0 & ~mask; + } + else if (d < 2 * GMP_NUMB_BITS) + { + mp_limb_t c0shifted; + /* warning: we must have the most significant bit of sb correct + since it might become the round bit below */ + sb = (d == GMP_NUMB_BITS) ? cp[0] + : (cp[1] << (2*GMP_NUMB_BITS - d)) | (cp[0] != 0); + c0shifted = (d == GMP_NUMB_BITS) ? cp[1] + : (cp[2] << (2*GMP_NUMB_BITS-d)) | (cp[1] >> (d - GMP_NUMB_BITS)); + a0 = bp[0] - c0shifted; + /* TODO: add a non-regression test for cp[2] == MPFR_LIMB_MAX, + d == GMP_NUMB_BITS and a0 > bp[0]. */ + a1 = bp[1] - (cp[2] >> (d - GMP_NUMB_BITS)) - (a0 > bp[0]); + a2 = bp[2] - (a1 > bp[1] || (a1 == bp[1] && a0 > bp[0])); + /* if sb is non-zero, subtract 1 from a2, a1, a0 since we want a + non-negative neglected part */ + if (sb) + { + a2 -= (a1 == 0 && a0 == 0); + a1 -= (a0 == 0); + a0 --; + /* a = a2,a1,a0 cannot become zero here, since: + a) if d >= 2, then a2 >= 2^(w-1) - (2^(w-2)-1) with + w = GMP_NUMB_BITS, thus a2 - 1 >= 2^(w-2), + b) if d = 1, then since p < 3*GMP_NUMB_BITS we have sb=0. */ + MPFR_ASSERTD(a2 > 0 || a1 > 0 || a0 > 0); + sb = -sb; /* 2^GMP_NUMB_BITS - sb */ + } + /* since bp[2] has its most significant bit set, we can have an + exponent decrease of at most one */ + if (a2 < MPFR_LIMB_HIGHBIT) + { + ap[2] = (a2 << 1) | (a1 >> (GMP_NUMB_BITS - 1)); + ap[1] = (a1 << 1) | (a0 >> (GMP_NUMB_BITS - 1)); + a0 = (a0 << 1) | (sb >> (GMP_NUMB_BITS - 1)); + sb <<= 1; + bx --; + } + else + { + ap[2] = a2; + ap[1] = a1; + } + rb = a0 & (MPFR_LIMB_ONE << (sh - 1)); + sb |= (a0 & mask) ^ rb; + ap[0] = a0 & ~mask; + } + else if (d < 3 * GMP_NUMB_BITS) /* 2*GMP_NUMB_BITS<=d<3*GMP_NUMB_BITS */ + { + MPFR_ASSERTD (2*GMP_NUMB_BITS <= d && d < 3*GMP_NUMB_BITS); + /* warning: we must have the most significant bit of sb correct + since it might become the round bit below */ + if (d == 2 * GMP_NUMB_BITS) + sb = cp[1] | (cp[0] != 0); + else + sb = cp[2] << (3*GMP_NUMB_BITS - d) | (cp[1] != 0) | (cp[0] != 0); + sb = -sb; + /* TODO: add a non-regression test for cp[2] == MPFR_LIMB_MAX, + d == 2*GMP_NUMB_BITS and sb != 0. */ + a0 = bp[0] - (cp[2] >> (d - 2*GMP_NUMB_BITS)) - (sb != 0); + a1 = bp[1] - (a0 > bp[0] || (a0 == bp[0] && sb != 0)); + a2 = bp[2] - (a1 > bp[1]); + if (a2 < MPFR_LIMB_HIGHBIT) + { + ap[2] = (a2 << 1) | (a1 >> (GMP_NUMB_BITS - 1)); + ap[1] = (a1 << 1) | (a0 >> (GMP_NUMB_BITS - 1)); + a0 = (a0 << 1) | (sb >> (GMP_NUMB_BITS - 1)); + sb <<= 1; + bx --; + } + else + { + ap[2] = a2; + ap[1] = a1; + } + rb = a0 & (MPFR_LIMB_ONE << (sh - 1)); + sb |= (a0 & mask) ^ rb; + ap[0] = a0 & ~mask; + } + else /* d >= 3*GMP_NUMB_BITS */ + { + /* We compute b - ulp(b), and the remainder ulp(b) - c satisfies: + 1/2 ulp(b) < ulp(b) - c < ulp(b), thus rb = sb = 1. */ + mp_limb_t t = MPFR_LIMB_ONE << sh; + a0 = bp[0] - t; + a1 = bp[1] - (bp[0] < t); + a2 = bp[2] - (a1 > bp[1]); + if (a2 < MPFR_LIMB_HIGHBIT) + { + /* necessarily we had b = 1000...000 */ + /* Warning: since we have an exponent decrease, when + p = 3*GMP_NUMB_BITS - 1 and d = 3*GMP_NUMB_BITS, the round bit + corresponds to the upper bit of -c. In that case rb = 0 and + sb = 1, except when c = 1000...000 where rb = 1 and sb = 0. */ + rb = sh > 1 || d > 3 * GMP_NUMB_BITS + || (cp[2] == MPFR_LIMB_HIGHBIT && cp[1] == MPFR_LIMB_ZERO && + cp[0] == MPFR_LIMB_ZERO); + /* sb=1 below is incorrect when p = 2*GMP_NUMB_BITS - 1, + d = 2*GMP_NUMB_BITS and c = 1000...000, but in + that case the even rule wound round up too. */ + ap[0] = ~mask; + ap[1] = MPFR_LIMB_MAX; + ap[2] = MPFR_LIMB_MAX; + bx --; + } + else + { + ap[0] = a0; + ap[1] = a1; + ap[2] = a2; + rb = 1; + } + sb = 1; + } + } + else /* cx > bx */ + { + mpfr_exp_t tx; + mp_limb_t *tp; + tx = bx; bx = cx; cx = tx; + tp = bp; bp = cp; cp = tp; + MPFR_SET_OPPOSITE_SIGN (a, b); + goto BGreater2; + } + + /* now perform rounding */ + + /* Warning: MPFR considers underflow *after* rounding with an unbounded + exponent range. However since b and c have same precision p, they are + multiples of 2^(emin-p), likewise for b-c. Thus if bx < emin, the + subtraction (with an unbounded exponent range) is exact, so that bx is + also the exponent after rounding with an unbounded exponent range. */ + if (MPFR_UNLIKELY(bx < __gmpfr_emin)) + { + /* for RNDN, mpfr_underflow always rounds away, thus for |a|<=2^(emin-2) + we have to change to RNDZ */ + if (rnd_mode == MPFR_RNDN && + (bx < __gmpfr_emin - 1 || + (ap[2] == MPFR_LIMB_HIGHBIT && ap[1] == 0 && ap[0] == 0))) + rnd_mode = MPFR_RNDZ; + return mpfr_underflow (a, rnd_mode, MPFR_SIGN(a)); + } + + MPFR_SET_EXP (a, bx); + if ((rb == 0 && sb == 0) || rnd_mode == MPFR_RNDF) + MPFR_RET (0); + else if (rnd_mode == MPFR_RNDN) + { + if (rb == 0 || (sb == 0 && (ap[0] & (MPFR_LIMB_ONE << sh)) == 0)) + goto truncate; + else + goto add_one_ulp; + } + else if (MPFR_IS_LIKE_RNDZ(rnd_mode, MPFR_IS_NEG(a))) + { + truncate: + MPFR_RET(-MPFR_SIGN(a)); + } + else /* round away from zero */ + { + add_one_ulp: + ap[0] += MPFR_LIMB_ONE << sh; + ap[1] += (ap[0] == 0); + ap[2] += (ap[1] == 0 && ap[0] == 0); + if (MPFR_UNLIKELY(ap[2] == 0)) + { + ap[2] = MPFR_LIMB_HIGHBIT; + /* Note: bx+1 cannot exceed __gmpfr_emax, since |a| <= |b|, thus + bx+1 is at most equal to the original exponent of b. */ + MPFR_ASSERTD(bx + 1 <= __gmpfr_emax); + MPFR_SET_EXP (a, bx + 1); + } + MPFR_RET(MPFR_SIGN(a)); + } +} + +#endif /* !defined(MPFR_GENERIC_ABI) */ /* Rounding Sub */ @@ -131,10 +1089,10 @@ int mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) * */ -int +MPFR_HOT_FUNCTION_ATTR int mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) { - mpfr_exp_t bx,cx; + mpfr_exp_t bx, cx; mpfr_uexp_t d; mpfr_prec_t p, sh, cnt; mp_size_t n; @@ -142,34 +1100,54 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) mp_limb_t limb; int inexact; mp_limb_t bcp,bcp1; /* Cp and C'p+1 */ - mp_limb_t bbcp = (mp_limb_t) -1, bbcp1 = (mp_limb_t) -1; /* Cp+1 and C'p+2, + mp_limb_t bbcp = MPFR_LIMB_MAX, bbcp1 = MPFR_LIMB_MAX; /* Cp+1 and C'p+2, gcc claims that they might be used uninitialized. We fill them with invalid values, which should produce a failure if so. See README.dev file. */ MPFR_TMP_DECL(marker); - MPFR_TMP_MARK(marker); - MPFR_ASSERTD(MPFR_PREC(a) == MPFR_PREC(b) && MPFR_PREC(b) == MPFR_PREC(c)); MPFR_ASSERTD(MPFR_IS_PURE_FP(b)); MPFR_ASSERTD(MPFR_IS_PURE_FP(c)); /* Read prec and num of limbs */ - p = MPFR_PREC (b); - n = MPFR_PREC2LIMBS (p); + p = MPFR_GET_PREC (b); + +#if !defined(MPFR_GENERIC_ABI) + /* special case for p < GMP_NUMB_BITS */ + if (p < GMP_NUMB_BITS) + return mpfr_sub1sp1 (a, b, c, rnd_mode, p); + + /* special case for GMP_NUMB_BITS < p < 2*GMP_NUMB_BITS */ + if (GMP_NUMB_BITS < p && p < 2 * GMP_NUMB_BITS) + return mpfr_sub1sp2 (a, b, c, rnd_mode, p); + + /* special case for p = GMP_NUMB_BITS: we put it *after* mpfr_sub1sp2, + in order not to slow down mpfr_sub1sp2, which should be more frequent */ + if (p == GMP_NUMB_BITS) + return mpfr_sub1sp1n (a, b, c, rnd_mode); - /* Fast cmp of |b| and |c|*/ + /* special case for 2*GMP_NUMB_BITS < p < 3*GMP_NUMB_BITS */ + if (2 * GMP_NUMB_BITS < p && p < 3 * GMP_NUMB_BITS) + return mpfr_sub1sp3 (a, b, c, rnd_mode, p); +#endif + + n = MPFR_PREC2LIMBS (p); + /* Fast cmp of |b| and |c| */ bx = MPFR_GET_EXP (b); cx = MPFR_GET_EXP (c); - if (MPFR_UNLIKELY(bx == cx)) + + MPFR_TMP_MARK(marker); + + if (bx == cx) { mp_size_t k = n - 1; - /* Check mantissa since exponent are equals */ + /* Check mantissa since exponents are equal */ bp = MPFR_MANT(b); cp = MPFR_MANT(c); - while (k>=0 && MPFR_UNLIKELY(bp[k] == cp[k])) + while (k >= 0 && MPFR_UNLIKELY(bp[k] == cp[k])) k--; - if (MPFR_UNLIKELY(k < 0)) + if (k < 0) /* b == c ! */ { /* Return exact number 0 */ @@ -184,11 +1162,11 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) goto BGreater; else { - MPFR_ASSERTD(bp[k]<cp[k]); + MPFR_ASSERTD(bp[k] < cp[k]); goto CGreater; } } - else if (MPFR_UNLIKELY(bx < cx)) + else if (bx < cx) { /* Swap b and c and set sign */ mpfr_srcptr t; @@ -200,19 +1178,19 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) } else { - /* b > c */ + /* |b| > |c| */ BGreater: MPFR_SET_SAME_SIGN(a,b); } - /* Now b > c */ + /* Now |b| > |c| */ MPFR_ASSERTD(bx >= cx); d = (mpfr_uexp_t) bx - cx; - DEBUG (printf ("New with diff=%lu\n", (unsigned long) d)); + /* printf ("New with diff=%lu\n", (unsigned long) d); */ - if (MPFR_UNLIKELY(d <= 1)) + if (d <= 1) { - if (MPFR_LIKELY(d < 1)) + if (d == 0) { /* <-- b --> <-- c --> : exact sub */ @@ -221,7 +1199,7 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) /* Normalize */ ExactNormalize: limb = ap[n-1]; - if (MPFR_LIKELY(limb)) + if (MPFR_LIKELY (limb != 0)) { /* First limb is not zero. */ count_leading_zeros(cnt, limb); @@ -231,7 +1209,7 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) mpn_lshift(ap, ap, n, cnt); /* Normalize number */ bx -= cnt; /* Update final expo */ } - /* Last limb should be ok */ + /* Last limb should be OK */ MPFR_ASSERTD(!(ap[0] & MPFR_LIMB_MASK((unsigned int) (-p) % GMP_NUMB_BITS))); } @@ -239,8 +1217,8 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) { /* First limb is zero */ mp_size_t k = n-1, len; - /* Find the first limb not equal to zero. - FIXME:It is assume it exists (since |b| > |c| and same prec)*/ + /* Find the first limb not equal to zero. It necessarily exists + since |b| > |c|. */ do { MPFR_ASSERTD( k > 0 ); @@ -252,28 +1230,30 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) k++; len = n - k; /* Number of last limb */ MPFR_ASSERTD(k >= 0); - if (MPFR_LIKELY(cnt)) - mpn_lshift(ap+len, ap, k, cnt); /* Normalize the High Limb*/ + if (cnt) + mpn_lshift (ap + len, ap, k, cnt); /* Normalize the High Limb*/ else { - /* Must use DECR since src and dest may overlap & dest>=src*/ - MPN_COPY_DECR(ap+len, ap, k); + /* Must use copyd since src and dst may overlap & dst>=src */ + mpn_copyd (ap+len, ap, k); } MPN_ZERO(ap, len); /* Zeroing the last limbs */ bx -= cnt + len*GMP_NUMB_BITS; /* Update Expo */ - /* Last limb should be ok */ - MPFR_ASSERTD(!(ap[len]&MPFR_LIMB_MASK((unsigned int) (-p) - % GMP_NUMB_BITS))); + /* Last limb should be OK */ + MPFR_ASSERTD(!(ap[len] & MPFR_LIMB_MASK((unsigned int) (-p) + % GMP_NUMB_BITS))); } /* Check expo underflow */ if (MPFR_UNLIKELY(bx < __gmpfr_emin)) { MPFR_TMP_FREE(marker); - /* inexact=0 */ - DEBUG( printf("(D==0 Underflow)\n") ); + /* since b and c have same sign, exponent and precision, the + subtraction is exact */ + /* printf("(D==0 Underflow)\n"); */ + /* for MPFR_RNDN, mpfr_underflow always rounds away from zero, + thus for |a| <= 2^(emin-2) we change to RNDZ. */ if (rnd_mode == MPFR_RNDN && - (bx < __gmpfr_emin - 1 || - (/*inexact >= 0 &&*/ mpfr_powerof2_raw (a)))) + (bx < __gmpfr_emin - 1 || mpfr_powerof2_raw (a))) rnd_mode = MPFR_RNDZ; return mpfr_underflow (a, rnd_mode, MPFR_SIGN(a)); } @@ -296,41 +1276,48 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) cp = MPFR_MANT(c); k = n-1; limb = bp[k] - cp[k]/2; + /* we have |b|-|c| >= limb*W^k - (2*W^k-1)/2 >= limb*W^k - W^k + 1/2 + thus if limb > W^k/2, |b|-|c| >= 1/2*W^n. + Moreover if trunc(|c|) represents the first p-1 bits of |c|, + minus the last significant bit called c0 below, then we have + |b|-trunc(|c|) >= 1/2*W^n+1, thus the two mpn_sub_n calls + below necessarily yield a > 1/2*W^n. */ if (limb > MPFR_LIMB_HIGHBIT) { - /* We can't lose precision: compute b-c/2 */ + /* The exponent cannot decrease: compute b-c/2 */ /* Shift c in the allocated temporary block */ SubD1NoLose: - c0 = cp[0] & (MPFR_LIMB_ONE<<sh); + c0 = cp[0] & (MPFR_LIMB_ONE << sh); + mask = ~MPFR_LIMB_MASK(sh); + ap = MPFR_MANT(a); cp = MPFR_TMP_LIMBS_ALLOC (n); - mpn_rshift(cp, MPFR_MANT(c), n, 1); + /* FIXME: it might be faster to have one function shifting c by 1 + to the right and adding with b to a, which would read c once + only, and avoid a temporary allocation. */ + mpn_rshift (cp, MPFR_MANT(c), n, 1); + cp[0] &= mask; /* Zero last bit of c if set */ + mpn_sub_n (ap, bp, cp, n); + MPFR_SET_EXP(a, bx); /* No expo overflow! */ + MPFR_ASSERTD(ap[n-1] > ~ap[n-1]); if (MPFR_LIKELY(c0 == 0)) { /* Result is exact: no need of rounding! */ - ap = MPFR_MANT(a); - mpn_sub_n (ap, bp, cp, n); - MPFR_SET_EXP(a, bx); /* No expo overflow! */ - /* No truncate or normalize is needed */ - MPFR_ASSERTD(ap[n-1] > ~ap[n-1]); - /* No rounding is necessary since the result is exact */ MPFR_TMP_FREE(marker); return 0; } - ap = MPFR_MANT(a); - mask = ~MPFR_LIMB_MASK(sh); - cp[0] &= mask; /* Delete last bit of c */ - mpn_sub_n (ap, bp, cp, n); - MPFR_SET_EXP(a, bx); /* No expo overflow! */ MPFR_ASSERTD( !(ap[0] & ~mask) ); /* Check last bits */ /* No normalize is needed */ - MPFR_ASSERTD(ap[n-1] > ~ap[n-1]); - /* Rounding is necessary since c0 = 1*/ + /* Rounding is necessary since c0 = 1 */ /* Cp =-1 and C'p+1=0 */ bcp = 1; bcp1 = 0; - if (MPFR_LIKELY(rnd_mode == MPFR_RNDN)) + + if (rnd_mode == MPFR_RNDF) + goto truncate; /* low(b) = 0 and low(c) is 0 or 1/2 ulp(b), thus + low(b) - low(c) = 0 or -1/2 ulp(b) */ + else if (rnd_mode == MPFR_RNDN) { - /* Even Rule apply: Check Ap-1 */ - if (MPFR_LIKELY( (ap[0] & (MPFR_LIMB_ONE<<sh)) == 0) ) + /* Even Rule apply: Check last bit of a. */ + if (MPFR_LIKELY( (ap[0] & (MPFR_LIMB_ONE << sh)) == 0) ) goto truncate; else goto sub_one_ulp; @@ -343,14 +1330,23 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) } else if (MPFR_LIKELY(limb < MPFR_LIMB_HIGHBIT)) { - /* We lose at least one bit of prec */ - /* Calcul of 2*b-c (Exact) */ - /* Shift b in the allocated temporary block */ + /* |b| - |c| <= (W/2-1)*W^k + W^k-1 = 1/2*W^n - 1 */ + /* The exponent decreases by one. */ SubD1Lose: + ap = MPFR_MANT(a); + /* Compute 2*b-c (Exact) */ + /* Experiments with __gmpn_rsblsh_n show that it is not always + faster than mpn_lshift + mpn_sub_n, thus we don't enable it + for now (HAVE___GMPN_RSBLSH_N -> HAVE___GMPN_RSBLSH_Nxxx). */ +#if defined(WANT_GMP_INTERNALS) && defined(HAVE___GMPN_RSBLSH_Nxxx) + /* {ap, n} = 2*{bp, n} - {cp, n} */ + __gmpn_rsblsh_n (ap, MPFR_MANT(c), MPFR_MANT(b), n, 1); +#else bp = MPFR_TMP_LIMBS_ALLOC (n); + /* Shift b in the allocated temporary block */ mpn_lshift (bp, MPFR_MANT(b), n, 1); - ap = MPFR_MANT(a); mpn_sub_n (ap, bp, cp, n); +#endif bx--; goto ExactNormalize; } @@ -363,42 +1359,55 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) /* If k==-1 => We don't lose any bit AND the result is 100000000000 0000000000 00000000000 */ mp_limb_t carry; - do { - carry = cp[k]&MPFR_LIMB_ONE; - k--; - } while (k>=0 && - bp[k]==(carry=cp[k]/2+(carry<<(GMP_NUMB_BITS-1)))); - if (MPFR_UNLIKELY(k<0)) + do + { + carry = cp[k] << (GMP_NUMB_BITS - 1); + if (--k < 0) + break; + carry += cp[k] >> 1; + } + while (bp[k] == carry); + if (MPFR_UNLIKELY(k < 0)) { - /*If carry then (sh==0 and Virtual c'[-1] > Virtual b[-1]) */ - if (MPFR_UNLIKELY(carry)) /* carry = cp[0]&MPFR_LIMB_ONE */ + ap = MPFR_MANT (a); + if (MPFR_UNLIKELY(carry)) { - /* FIXME: Can be faster? */ - MPFR_ASSERTD(sh == 0); - goto SubD1Lose; + /* If carry then necessarily the precision is an exact + multiple of GMP_NUMB_BITS, and we lose one bit, + thus the (exact) result is a power of 2 minus 1. */ + memset (ap, -1, n * MPFR_BYTES_PER_MP_LIMB); + MPFR_SET_EXP (a, bx - 1); + /* No underflow is possible since cx = bx-1 is a valid + exponent. */ } - /* Result is a power of 2 */ - ap = MPFR_MANT (a); - MPN_ZERO (ap, n); - ap[n-1] = MPFR_LIMB_HIGHBIT; - MPFR_SET_EXP (a, bx); /* No expo overflow! */ - /* No Normalize is needed*/ + else + { + /* No carry: result is a power of 2. */ + MPN_ZERO (ap, n - 1); + ap[n-1] = MPFR_LIMB_HIGHBIT; + MPFR_SET_EXP (a, bx); /* No expo overflow! */ + } + /* No Normalize is needed */ /* No Rounding is needed */ MPFR_TMP_FREE (marker); return 0; } /* carry = cp[k]/2+(cp[k-1]&1)<<(GMP_NUMB_BITS-1) = c'[k]*/ else if (bp[k] > carry) - goto SubD1NoLose; + goto SubD1NoLose; /* |b|-|c| >= 1/2*W^n */ else { - MPFR_ASSERTD(bp[k]<carry); - goto SubD1Lose; + MPFR_ASSERTD(bp[k] < carry); + goto SubD1Lose; /* |b|-|c| <= 1/2*W^n-1 and is exact */ } } } } - else if (MPFR_UNLIKELY(d >= p)) + else if (MPFR_UNLIKELY(d >= p)) /* the difference of exponents is larger + than the precision of all operands, thus + the result is either b or b - 1 ulp, + with a possible exact result when + d = p, b = 2^e and c = 1/2 ulp(b) */ { ap = MPFR_MANT(a); MPFR_UNSIGNED_MINUS_MODULO(sh, p); @@ -419,24 +1428,31 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) if (MPFR_UNLIKELY(cp[n-1] == MPFR_LIMB_HIGHBIT)) { mp_size_t k = n-1; - do { + do k--; - } while (k>=0 && cp[k]==0); - bcp1 = (k>=0); + while (k >= 0 && cp[k] == 0); + bcp1 = (k >= 0); } else bcp1 = 1; } - DEBUG( printf("(D=P) Cp=-1 Cp+1=%d C'p+1=%d \n", bbcp!=0, bcp1!=0) ); + /* printf("(D=P) Cp=-1 Cp+1=%d C'p+1=%d \n", bbcp!=0, bcp1!=0); */ bp = MPFR_MANT (b); - /* Even if src and dest overlap, it is ok using MPN_COPY */ - if (MPFR_LIKELY(rnd_mode == MPFR_RNDN)) + /* Even if src and dest overlap, it is OK using MPN_COPY */ + if (MPFR_LIKELY(rnd_mode == MPFR_RNDF)) + /* then d = p, and subtracting one ulp of b is ok even in the + exact case b = 2^e and c = 1/2 ulp(b) */ { - if (MPFR_UNLIKELY( bcp && bcp1==0 )) + MPN_COPY(ap, bp, n); + goto sub_one_ulp; + } + else if (rnd_mode == MPFR_RNDN) + { + if (MPFR_UNLIKELY (bcp != 0 && bcp1 == 0)) /* Cp=-1 and C'p+1=0: Even rule Apply! */ /* Check Ap-1 = Bp-1 */ - if ((bp[0] & (MPFR_LIMB_ONE<<sh)) == 0) + if ((bp[0] & (MPFR_LIMB_ONE << sh)) == 0) { MPN_COPY(ap, bp, n); goto truncate; @@ -460,7 +1476,7 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) { /* Cp=0, Cp+1=-1 if d==p+1, C'p+1=-1 */ bcp = 0; bbcp = (d==p+1); bcp1 = 1; - DEBUG( printf("(D>P) Cp=%d Cp+1=%d C'p+1=%d\n", bcp!=0,bbcp!=0,bcp1!=0) ); + /* printf("(D>P) Cp=%d Cp+1=%d C'p+1=%d\n", bcp!=0,bbcp!=0,bcp1!=0); */ /* Need to compute C'p+2 if d==p+1 and if rnd_mode=NEAREST (Because of a very improbable case) */ if (MPFR_UNLIKELY(d==p+1 && rnd_mode==MPFR_RNDN)) @@ -469,19 +1485,19 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) if (MPFR_UNLIKELY(cp[n-1] == MPFR_LIMB_HIGHBIT)) { mp_size_t k = n-1; - do { + do k--; - } while (k>=0 && cp[k]==0); - bbcp1 = (k>=0); + while (k >= 0 && cp[k] == 0); + bbcp1 = (k >= 0); } else bbcp1 = 1; - DEBUG( printf("(D>P) C'p+2=%d\n", bbcp1!=0) ); + /* printf("(D>P) C'p+2=%d\n", bbcp1!=0); */ } /* Copy mantissa B in A */ MPN_COPY(ap, MPFR_MANT(b), n); /* Round */ - if (MPFR_LIKELY(rnd_mode == MPFR_RNDN)) + if (rnd_mode == MPFR_RNDF || rnd_mode == MPFR_RNDN) goto truncate; MPFR_UPDATE_RND_MODE(rnd_mode, MPFR_IS_NEG(a)); if (rnd_mode == MPFR_RNDZ) @@ -490,13 +1506,12 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) goto truncate; } } - else + else /* case 2 <= d < p */ { mpfr_uexp_t dm; mp_size_t m; mp_limb_t mask; - /* General case: 2 <= d < p */ MPFR_UNSIGNED_MINUS_MODULO(sh, p); cp = MPFR_TMP_LIMBS_ALLOC (n); @@ -506,7 +1521,7 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) if (MPFR_UNLIKELY(dm == 0)) { /* dm = 0 and m > 0: Just copy */ - MPFR_ASSERTD(m!=0); + MPFR_ASSERTD(m != 0); MPN_COPY(cp, MPFR_MANT(c)+m, n-m); MPN_ZERO(cp+n-m, m); } @@ -523,16 +1538,16 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) MPN_ZERO(cp+n-m, m); } - DEBUG( mpfr_print_mant_binary("Before", MPFR_MANT(c), p) ); - DEBUG( mpfr_print_mant_binary("B= ", MPFR_MANT(b), p) ); - DEBUG( mpfr_print_mant_binary("After ", cp, p) ); + /* mpfr_print_mant_binary("Before", MPFR_MANT(c), p); */ + /* mpfr_print_mant_binary("B= ", MPFR_MANT(b), p); */ + /* mpfr_print_mant_binary("After ", cp, p); */ /* Compute bcp=Cp and bcp1=C'p+1 */ if (MPFR_LIKELY(sh)) { /* Try to compute them from C' rather than C (FIXME: Faster?) */ bcp = (cp[0] & (MPFR_LIMB_ONE<<(sh-1))) ; - if (MPFR_LIKELY( cp[0] & MPFR_LIMB_MASK(sh-1) )) + if (cp[0] & MPFR_LIMB_MASK(sh-1)) bcp1 = 1; else { @@ -540,7 +1555,7 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) /* Start from bit x=p-d+sh in mantissa C (+sh since we have already looked sh bits in C'!) */ mpfr_prec_t x = p-d+sh-1; - if (MPFR_LIKELY(x>p)) + if (x > p) /* We are already looked at all the bits of c, so C'p+1 = 0*/ bcp1 = 0; else @@ -548,9 +1563,8 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) mp_limb_t *tp = MPFR_MANT(c); mp_size_t kx = n-1 - (x / GMP_NUMB_BITS); mpfr_prec_t sx = GMP_NUMB_BITS-1-(x%GMP_NUMB_BITS); - DEBUG (printf ("(First) x=%lu Kx=%ld Sx=%lu\n", - (unsigned long) x, (long) kx, - (unsigned long) sx)); + /* printf ("(First) x=%lu Kx=%ld Sx=%lu\n", + (unsigned long) x, (long) kx, (unsigned long) sx); */ /* Looks at the last bits of limb kx (if sx=0 does nothing)*/ if (tp[kx] & MPFR_LIMB_MASK(sx)) bcp1 = 1; @@ -558,9 +1572,9 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) { /*kx += (sx==0);*/ /*If sx==0, tp[kx] hasn't been checked*/ - do { + do kx--; - } while (kx>=0 && tp[kx]==0); + while (kx >= 0 && tp[kx] == 0); bcp1 = (kx >= 0); } } @@ -582,17 +1596,17 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) else { /*kx += (sx==0);*/ /*If sx==0, tp[kx] hasn't been checked*/ - do { + do kx--; - } while (kx>=0 && tp[kx]==0); - bcp1 = (kx>=0); + while (kx >= 0 && tp[kx] == 0); + bcp1 = (kx >= 0); } } - DEBUG( printf("sh=%lu Cp=%d C'p+1=%d\n", sh, bcp!=0, bcp1!=0) ); + /* printf("sh=%lu Cp=%d C'p+1=%d\n", sh, bcp!=0, bcp1!=0); */ /* Check if we can lose a bit, and if so compute Cp+1 and C'p+2 */ bp = MPFR_MANT(b); - if (MPFR_UNLIKELY((bp[n-1]-cp[n-1]) <= MPFR_LIMB_HIGHBIT)) + if (MPFR_UNLIKELY (bp[n-1] - cp[n-1] <= MPFR_LIMB_HIGHBIT)) { /* We can lose a bit so we precompute Cp+1 and C'p+2 */ /* Test for trivial case: since C'p+1=0, Cp+1=0 and C'p+2 =0 */ @@ -608,28 +1622,28 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) mp_limb_t *tp = MPFR_MANT(c); /* Start from bit x=(p+1)-d in mantissa C */ mpfr_prec_t x = p+1-d; - mp_size_t kx = n-1 - (x/GMP_NUMB_BITS); - mpfr_prec_t sx = GMP_NUMB_BITS-1-(x%GMP_NUMB_BITS); + mp_size_t kx = n-1 - (x / GMP_NUMB_BITS); + mpfr_prec_t sx = GMP_NUMB_BITS-1 - (x % GMP_NUMB_BITS); + MPFR_ASSERTD(p > d); - DEBUG (printf ("(pre) x=%lu Kx=%ld Sx=%lu\n", - (unsigned long) x, (long) kx, - (unsigned long) sx)); + /* printf ("(pre) x=%lu Kx=%ld Sx=%lu\n", + (unsigned long) x, (long) kx, (unsigned long) sx); */ bbcp = (tp[kx] & (MPFR_LIMB_ONE<<sx)) ; /* Looks at the last bits of limb kx (If sx=0, does nothing)*/ /* If Cp+1=0, since C'p+1!=0, C'p+2=1 ! */ - if (MPFR_LIKELY(bbcp==0 || (tp[kx]&MPFR_LIMB_MASK(sx)))) + if (MPFR_LIKELY (bbcp == 0 || (tp[kx] & MPFR_LIMB_MASK(sx)))) bbcp1 = 1; else { /*kx += (sx==0);*/ /*If sx==0, tp[kx] hasn't been checked*/ - do { + do kx--; - } while (kx>=0 && tp[kx]==0); - bbcp1 = (kx>=0); - DEBUG (printf ("(Pre) Scan done for %ld\n", (long) kx)); + while (kx >= 0 && tp[kx] == 0); + bbcp1 = (kx >= 0); + /* printf ("(Pre) Scan done for %ld\n", (long) kx); */ } } /*End of Bcp1 != 0*/ - DEBUG( printf("(Pre) Cp+1=%d C'p+2=%d\n", bbcp!=0, bbcp1!=0) ); + /* printf("(Pre) Cp+1=%d C'p+2=%d\n", bbcp!=0, bbcp1!=0); */ } /* End of "can lose a bit" */ /* Clean shifted C' */ @@ -639,7 +1653,7 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) /* Subtract the mantissa c from b in a */ ap = MPFR_MANT(a); mpn_sub_n (ap, bp, cp, n); - DEBUG( mpfr_print_mant_binary("Sub= ", ap, p) ); + /* mpfr_print_mant_binary("Sub= ", ap, p); */ /* Normalize: we lose at max one bit*/ if (MPFR_UNLIKELY(MPFR_LIMB_MSB(ap[n-1]) == 0)) @@ -648,8 +1662,8 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) /* Ap >= 010000xxx001 */ mpn_lshift(ap, ap, n, 1); /* Ap >= 100000xxx010 */ - if (MPFR_UNLIKELY(bcp!=0)) /* Check if Cp = -1 */ - /* Since Cp == -1, we have to substract one more */ + if (MPFR_UNLIKELY(bcp != 0)) /* Check if Cp = -1 */ + /* Since Cp == -1, we have to subtract one more */ { mpn_sub_1(ap, ap, n, MPFR_LIMB_ONE<<sh); MPFR_ASSERTD(MPFR_LIMB_MSB(ap[n-1]) != 0); @@ -658,21 +1672,23 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) /* Final exponent -1 since we have shifted the mantissa */ bx--; /* Update bcp and bcp1 */ - MPFR_ASSERTN(bbcp != (mp_limb_t) -1); - MPFR_ASSERTN(bbcp1 != (mp_limb_t) -1); + MPFR_ASSERTD(bbcp != MPFR_LIMB_MAX); + MPFR_ASSERTD(bbcp1 != MPFR_LIMB_MAX); bcp = bbcp; bcp1 = bbcp1; - /* We dont't have anymore a valid Cp+1! + /* We don't have anymore a valid Cp+1! But since Ap >= 100000xxx001, the final sub can't unnormalize!*/ } MPFR_ASSERTD( !(ap[0] & ~mask) ); /* Rounding */ - if (MPFR_LIKELY(rnd_mode == MPFR_RNDN)) + if (MPFR_LIKELY(rnd_mode == MPFR_RNDF)) + goto truncate; + else if (MPFR_LIKELY(rnd_mode == MPFR_RNDN)) { - if (MPFR_LIKELY(bcp==0)) + if (MPFR_LIKELY(bcp == 0)) goto truncate; - else if ((bcp1) || ((ap[0] & (MPFR_LIMB_ONE<<sh)) != 0)) + else if (bcp1 != 0 || (ap[0] & (MPFR_LIMB_ONE << sh)) != 0) goto sub_one_ulp; else goto truncate; @@ -680,7 +1696,7 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) /* Update rounding mode */ MPFR_UPDATE_RND_MODE(rnd_mode, MPFR_IS_NEG(a)); - if (rnd_mode == MPFR_RNDZ && (MPFR_LIKELY(bcp || bcp1))) + if (rnd_mode == MPFR_RNDZ && MPFR_LIKELY (bcp != 0 || bcp1 != 0)) goto sub_one_ulp; goto truncate; } @@ -691,37 +1707,40 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) mpn_sub_1 (ap, ap, n, MPFR_LIMB_ONE << sh); /* Result should be smaller than exact value: inexact=-1 */ inexact = -1; - /* Check normalisation */ - if (MPFR_UNLIKELY(MPFR_LIMB_MSB(ap[n-1]) == 0)) + /* Check normalization */ + if (MPFR_UNLIKELY(ap[n-1] < MPFR_LIMB_HIGHBIT)) { /* ap was a power of 2, and we lose a bit */ /* Now it is 0111111111111111111[00000 */ - mpn_lshift(ap, ap, n, 1); + /* The following 2 lines are equivalent to: mpn_lshift(ap, ap, n, 1); */ + ap[0] <<= 1; + ap[n-1] |= MPFR_LIMB_HIGHBIT; bx--; /* And the lost bit x depends on Cp+1, and Cp */ - /* Compute Cp+1 if it isn't already compute (ie d==1) */ - /* FIXME: Is this case possible? */ - if (MPFR_UNLIKELY(d == 1)) - bbcp = 0; - DEBUG( printf("(SubOneUlp)Cp=%d, Cp+1=%d C'p+1=%d\n", bcp!=0,bbcp!=0,bcp1!=0)); + /* Compute Cp+1 if it isn't already computed (ie d==1) */ + /* Note: we can't have d = 1 here, since the only "goto sub_one_ulp" + for d = 1 are in the "SubD1NoLose" case, and in that case + |b|-|c| >= 1/2*W^n, thus round(|b|-|c|) >= 1/2*W^n, and ap[n-1] + cannot go below MPFR_LIMB_HIGHBIT. */ + /* printf("(SubOneUlp)Cp=%d, Cp+1=%d C'p+1=%d\n", bcp!=0,bbcp!=0,bcp1!=0); */ /* Compute the last bit (Since we have shifted the mantissa) - we need one more bit!*/ - MPFR_ASSERTN(bbcp != (mp_limb_t) -1); - if ( (rnd_mode == MPFR_RNDZ && bcp==0) - || (rnd_mode==MPFR_RNDN && bbcp==0) - || (bcp && bcp1==0) ) /*Exact result*/ + we need one more bit! */ + MPFR_ASSERTD(bbcp != MPFR_LIMB_MAX); + if ((rnd_mode == MPFR_RNDZ && bcp == 0) || + (rnd_mode == MPFR_RNDN && bbcp == 0) || + (bcp != 0 && bcp1 == 0)) /* Exact result */ { - ap[0] |= MPFR_LIMB_ONE<<sh; + ap[0] |= MPFR_LIMB_ONE << sh; if (rnd_mode == MPFR_RNDN) inexact = 1; - DEBUG( printf("(SubOneUlp) Last bit set\n") ); + /* printf("(SubOneUlp) Last bit set\n"); */ } /* Result could be exact if C'p+1 = 0 and rnd == Zero since we have had one more bit to the result */ /* Fixme: rnd_mode == MPFR_RNDZ needed ? */ - if (bcp1==0 && rnd_mode==MPFR_RNDZ) + if (rnd_mode == MPFR_RNDZ && bcp1 == 0) { - DEBUG( printf("(SubOneUlp) Exact result\n") ); + /* printf("(SubOneUlp) Exact result\n"); */ inexact = 0; } } @@ -744,46 +1763,43 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) if (MPFR_UNLIKELY(ap[n-1] == MPFR_LIMB_HIGHBIT)) { mp_size_t k = n-1; - do { + do k--; - } while (k>=0 && ap[k]==0); - if (MPFR_UNLIKELY(k<0)) + while (k >= 0 && ap[k] == 0); + if (MPFR_UNLIKELY (k < 0)) { /* It is a power of 2! */ /* Compute Cp+1 if it isn't already compute (ie d==1) */ - /* FIXME: Is this case possible? */ - if (d == 1) - bbcp=0; - DEBUG( printf("(Truncate) Cp=%d, Cp+1=%d C'p+1=%d C'p+2=%d\n", \ - bcp!=0, bbcp!=0, bcp1!=0, bbcp1!=0) ); - MPFR_ASSERTN(bbcp != (mp_limb_t) -1); - MPFR_ASSERTN((rnd_mode != MPFR_RNDN) || (bcp != 0) || (bbcp == 0) || (bbcp1 != (mp_limb_t) -1)); - if (((rnd_mode != MPFR_RNDZ) && bcp) - || - ((rnd_mode == MPFR_RNDN) && (bcp == 0) && (bbcp) && (bbcp1))) - { - DEBUG( printf("(Truncate) Do sub\n") ); + /* Note: if d=1, we have {a, n} > 1/2*W^n, thus we cannot have k < 0. */ + /* printf("(Truncate) Cp=%d, Cp+1=%d C'p+1=%d C'p+2=%d\n", + bcp!=0, bbcp!=0, bcp1!=0, bbcp1!=0); */ + MPFR_ASSERTD(bbcp != MPFR_LIMB_MAX); + MPFR_ASSERTD(rnd_mode != MPFR_RNDN || bcp != 0 || + bbcp == 0 || bbcp1 != MPFR_LIMB_MAX); + if ((rnd_mode != MPFR_RNDZ && bcp != 0) || + (rnd_mode == MPFR_RNDN && bcp == 0 && bbcp != 0 && bbcp1 != 0)) + { + /* printf("(Truncate) Do sub\n"); */ mpn_sub_1 (ap, ap, n, MPFR_LIMB_ONE << sh); - mpn_lshift(ap, ap, n, 1); - ap[0] |= MPFR_LIMB_ONE<<sh; + ap[n-1] |= MPFR_LIMB_HIGHBIT; bx--; /* FIXME: Explain why it works (or why not)... */ - inexact = (bcp1 == 0) ? 0 : (rnd_mode==MPFR_RNDN) ? -1 : 1; + inexact = (bcp1 == 0) ? 0 : (rnd_mode == MPFR_RNDN) ? -1 : 1; goto end_of_sub; } } } /* Calcul of Inexact flag.*/ - inexact = MPFR_LIKELY(bcp || bcp1) ? 1 : 0; + inexact = (bcp != 0 || bcp1 != 0); end_of_sub: - /* Update Expo */ - /* FIXME: Is this test really useful? + /* Update Exponent */ + /* bx >= emin. Proof: If d==0 : Exact case. This is never called. if 1 < d < p : bx=MPFR_EXP(b) or MPFR_EXP(b)-1 > MPFR_EXP(c) > emin if d == 1 : bx=MPFR_EXP(b). If we could lose any bits, the exact - normalisation is called. + normalization is called. if d >= p : bx=MPFR_EXP(b) >= MPFR_EXP(c) + p > emin After SubOneUlp, we could have one bit less. if 1 < d < p : bx >= MPFR_EXP(b)-2 >= MPFR_EXP(c) > emin @@ -791,18 +1807,6 @@ mpfr_sub1sp (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) if d >= p : bx >= MPFR_EXP(b)-1 > emin since p>=2. */ MPFR_ASSERTD( bx >= __gmpfr_emin); - /* - if (MPFR_UNLIKELY(bx < __gmpfr_emin)) - { - DEBUG( printf("(Final Underflow)\n") ); - if (rnd_mode == MPFR_RNDN && - (bx < __gmpfr_emin - 1 || - (inexact >= 0 && mpfr_powerof2_raw (a)))) - rnd_mode = MPFR_RNDZ; - MPFR_TMP_FREE(marker); - return mpfr_underflow (a, rnd_mode, MPFR_SIGN(a)); - } - */ MPFR_SET_EXP (a, bx); MPFR_TMP_FREE(marker); |