14a238c70SJohn Marino /* mpfr_sub1 -- internal function to perform a "real" subtraction
24a238c70SJohn Marino
3*ab6d115fSJohn Marino Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4*ab6d115fSJohn Marino Contributed by the AriC and Caramel projects, INRIA.
54a238c70SJohn Marino
64a238c70SJohn Marino This file is part of the GNU MPFR Library.
74a238c70SJohn Marino
84a238c70SJohn Marino The GNU MPFR Library is free software; you can redistribute it and/or modify
94a238c70SJohn Marino it under the terms of the GNU Lesser General Public License as published by
104a238c70SJohn Marino the Free Software Foundation; either version 3 of the License, or (at your
114a238c70SJohn Marino option) any later version.
124a238c70SJohn Marino
134a238c70SJohn Marino The GNU MPFR Library is distributed in the hope that it will be useful, but
144a238c70SJohn Marino WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
154a238c70SJohn Marino or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
164a238c70SJohn Marino License for more details.
174a238c70SJohn Marino
184a238c70SJohn Marino You should have received a copy of the GNU Lesser General Public License
194a238c70SJohn Marino along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
204a238c70SJohn Marino http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
214a238c70SJohn Marino 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
224a238c70SJohn Marino
234a238c70SJohn Marino #include "mpfr-impl.h"
244a238c70SJohn Marino
254a238c70SJohn Marino /* compute sign(b) * (|b| - |c|), with |b| > |c|, diff_exp = EXP(b) - EXP(c)
264a238c70SJohn Marino Returns 0 iff result is exact,
274a238c70SJohn Marino a negative value when the result is less than the exact value,
284a238c70SJohn Marino a positive value otherwise.
294a238c70SJohn Marino */
304a238c70SJohn Marino
314a238c70SJohn Marino int
mpfr_sub1(mpfr_ptr a,mpfr_srcptr b,mpfr_srcptr c,mpfr_rnd_t rnd_mode)324a238c70SJohn Marino mpfr_sub1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
334a238c70SJohn Marino {
344a238c70SJohn Marino int sign;
354a238c70SJohn Marino mpfr_uexp_t diff_exp;
364a238c70SJohn Marino mpfr_prec_t cancel, cancel1;
374a238c70SJohn Marino mp_size_t cancel2, an, bn, cn, cn0;
384a238c70SJohn Marino mp_limb_t *ap, *bp, *cp;
394a238c70SJohn Marino mp_limb_t carry, bb, cc;
404a238c70SJohn Marino int inexact, shift_b, shift_c, add_exp = 0;
414a238c70SJohn Marino int cmp_low = 0; /* used for rounding to nearest: 0 if low(b) = low(c),
424a238c70SJohn Marino negative if low(b) < low(c), positive if low(b)>low(c) */
434a238c70SJohn Marino int sh, k;
444a238c70SJohn Marino MPFR_TMP_DECL(marker);
454a238c70SJohn Marino
464a238c70SJohn Marino MPFR_TMP_MARK(marker);
474a238c70SJohn Marino ap = MPFR_MANT(a);
484a238c70SJohn Marino an = MPFR_LIMB_SIZE(a);
494a238c70SJohn Marino
504a238c70SJohn Marino sign = mpfr_cmp2 (b, c, &cancel);
514a238c70SJohn Marino if (MPFR_UNLIKELY(sign == 0))
524a238c70SJohn Marino {
534a238c70SJohn Marino if (rnd_mode == MPFR_RNDD)
544a238c70SJohn Marino MPFR_SET_NEG (a);
554a238c70SJohn Marino else
564a238c70SJohn Marino MPFR_SET_POS (a);
574a238c70SJohn Marino MPFR_SET_ZERO (a);
584a238c70SJohn Marino MPFR_RET (0);
594a238c70SJohn Marino }
604a238c70SJohn Marino
614a238c70SJohn Marino /*
624a238c70SJohn Marino * If subtraction: sign(a) = sign * sign(b)
634a238c70SJohn Marino * If addition: sign(a) = sign of the larger argument in absolute value.
644a238c70SJohn Marino *
654a238c70SJohn Marino * Both cases can be simplidied in:
664a238c70SJohn Marino * if (sign>0)
674a238c70SJohn Marino * if addition: sign(a) = sign * sign(b) = sign(b)
684a238c70SJohn Marino * if subtraction, b is greater, so sign(a) = sign(b)
694a238c70SJohn Marino * else
704a238c70SJohn Marino * if subtraction, sign(a) = - sign(b)
714a238c70SJohn Marino * if addition, sign(a) = sign(c) (since c is greater)
724a238c70SJohn Marino * But if it is an addition, sign(b) and sign(c) are opposed!
734a238c70SJohn Marino * So sign(a) = - sign(b)
744a238c70SJohn Marino */
754a238c70SJohn Marino
764a238c70SJohn Marino if (sign < 0) /* swap b and c so that |b| > |c| */
774a238c70SJohn Marino {
784a238c70SJohn Marino mpfr_srcptr t;
794a238c70SJohn Marino MPFR_SET_OPPOSITE_SIGN (a,b);
804a238c70SJohn Marino t = b; b = c; c = t;
814a238c70SJohn Marino }
824a238c70SJohn Marino else
834a238c70SJohn Marino MPFR_SET_SAME_SIGN (a,b);
844a238c70SJohn Marino
854a238c70SJohn Marino /* Check if c is too small.
864a238c70SJohn Marino A more precise test is to replace 2 by
874a238c70SJohn Marino (rnd == MPFR_RNDN) + mpfr_power2_raw (b)
884a238c70SJohn Marino but it is more expensive and not very useful */
894a238c70SJohn Marino if (MPFR_UNLIKELY (MPFR_GET_EXP (c) <= MPFR_GET_EXP (b)
904a238c70SJohn Marino - (mpfr_exp_t) MAX (MPFR_PREC (a), MPFR_PREC (b)) - 2))
914a238c70SJohn Marino {
924a238c70SJohn Marino /* Remember, we can't have an exact result! */
934a238c70SJohn Marino /* A.AAAAAAAAAAAAAAAAA
944a238c70SJohn Marino = B.BBBBBBBBBBBBBBB
954a238c70SJohn Marino - C.CCCCCCCCCCCCC */
964a238c70SJohn Marino /* A = S*ABS(B) +/- ulp(a) */
974a238c70SJohn Marino MPFR_SET_EXP (a, MPFR_GET_EXP (b));
984a238c70SJohn Marino MPFR_RNDRAW_EVEN (inexact, a, MPFR_MANT (b), MPFR_PREC (b),
994a238c70SJohn Marino rnd_mode, MPFR_SIGN (a),
1004a238c70SJohn Marino if (MPFR_UNLIKELY ( ++MPFR_EXP (a) > __gmpfr_emax))
1014a238c70SJohn Marino inexact = mpfr_overflow (a, rnd_mode, MPFR_SIGN (a)));
1024a238c70SJohn Marino /* inexact = mpfr_set4 (a, b, rnd_mode, MPFR_SIGN (a)); */
1034a238c70SJohn Marino if (inexact == 0)
1044a238c70SJohn Marino {
1054a238c70SJohn Marino /* a = b (Exact)
1064a238c70SJohn Marino But we know it isn't (Since we have to remove `c')
1074a238c70SJohn Marino So if we round to Zero, we have to remove one ulp.
1084a238c70SJohn Marino Otherwise the result is correctly rounded. */
1094a238c70SJohn Marino if (MPFR_IS_LIKE_RNDZ (rnd_mode, MPFR_IS_NEG (a)))
1104a238c70SJohn Marino {
1114a238c70SJohn Marino mpfr_nexttozero (a);
1124a238c70SJohn Marino MPFR_RET (- MPFR_INT_SIGN (a));
1134a238c70SJohn Marino }
1144a238c70SJohn Marino MPFR_RET (MPFR_INT_SIGN (a));
1154a238c70SJohn Marino }
1164a238c70SJohn Marino else
1174a238c70SJohn Marino {
1184a238c70SJohn Marino /* A.AAAAAAAAAAAAAA
1194a238c70SJohn Marino = B.BBBBBBBBBBBBBBB
1204a238c70SJohn Marino - C.CCCCCCCCCCCCC */
1214a238c70SJohn Marino /* It isn't exact so Prec(b) > Prec(a) and the last
1224a238c70SJohn Marino Prec(b)-Prec(a) bits of `b' are not zeros.
1234a238c70SJohn Marino Which means that removing c from b can't generate a carry
1244a238c70SJohn Marino execpt in case of even rounding.
1254a238c70SJohn Marino In all other case the result and the inexact flag should be
1264a238c70SJohn Marino correct (We can't have an exact result).
1274a238c70SJohn Marino In case of EVEN rounding:
1284a238c70SJohn Marino 1.BBBBBBBBBBBBBx10
1294a238c70SJohn Marino - 1.CCCCCCCCCCCC
1304a238c70SJohn Marino = 1.BBBBBBBBBBBBBx01 Rounded to Prec(b)
1314a238c70SJohn Marino = 1.BBBBBBBBBBBBBx Nearest / Rounded to Prec(a)
1324a238c70SJohn Marino Set gives:
1334a238c70SJohn Marino 1.BBBBBBBBBBBBB0 if inexact == EVEN_INEX (x == 0)
1344a238c70SJohn Marino 1.BBBBBBBBBBBBB1+1 if inexact == -EVEN_INEX (x == 1)
1354a238c70SJohn Marino which means we get a wrong rounded result if x==1,
1364a238c70SJohn Marino i.e. inexact= MPFR_EVEN_INEX */
1374a238c70SJohn Marino if (MPFR_UNLIKELY (inexact == MPFR_EVEN_INEX*MPFR_INT_SIGN (a)))
1384a238c70SJohn Marino {
1394a238c70SJohn Marino mpfr_nexttozero (a);
1404a238c70SJohn Marino inexact = -MPFR_INT_SIGN (a);
1414a238c70SJohn Marino }
1424a238c70SJohn Marino MPFR_RET (inexact);
1434a238c70SJohn Marino }
1444a238c70SJohn Marino }
1454a238c70SJohn Marino
1464a238c70SJohn Marino diff_exp = (mpfr_uexp_t) MPFR_GET_EXP (b) - MPFR_GET_EXP (c);
1474a238c70SJohn Marino
1484a238c70SJohn Marino /* reserve a space to store b aligned with the result, i.e. shifted by
1494a238c70SJohn Marino (-cancel) % GMP_NUMB_BITS to the right */
1504a238c70SJohn Marino bn = MPFR_LIMB_SIZE (b);
1514a238c70SJohn Marino MPFR_UNSIGNED_MINUS_MODULO (shift_b, cancel);
1524a238c70SJohn Marino cancel1 = (cancel + shift_b) / GMP_NUMB_BITS;
1534a238c70SJohn Marino
1544a238c70SJohn Marino /* the high cancel1 limbs from b should not be taken into account */
1554a238c70SJohn Marino if (MPFR_UNLIKELY (shift_b == 0))
1564a238c70SJohn Marino {
1574a238c70SJohn Marino bp = MPFR_MANT(b); /* no need of an extra space */
1584a238c70SJohn Marino /* Ensure ap != bp */
1594a238c70SJohn Marino if (MPFR_UNLIKELY (ap == bp))
1604a238c70SJohn Marino {
1614a238c70SJohn Marino bp = MPFR_TMP_LIMBS_ALLOC (bn);
1624a238c70SJohn Marino MPN_COPY (bp, ap, bn);
1634a238c70SJohn Marino }
1644a238c70SJohn Marino }
1654a238c70SJohn Marino else
1664a238c70SJohn Marino {
1674a238c70SJohn Marino bp = MPFR_TMP_LIMBS_ALLOC (bn + 1);
1684a238c70SJohn Marino bp[0] = mpn_rshift (bp + 1, MPFR_MANT(b), bn++, shift_b);
1694a238c70SJohn Marino }
1704a238c70SJohn Marino
1714a238c70SJohn Marino /* reserve a space to store c aligned with the result, i.e. shifted by
1724a238c70SJohn Marino (diff_exp-cancel) % GMP_NUMB_BITS to the right */
1734a238c70SJohn Marino cn = MPFR_LIMB_SIZE(c);
1744a238c70SJohn Marino if ((UINT_MAX % GMP_NUMB_BITS) == (GMP_NUMB_BITS-1)
1754a238c70SJohn Marino && ((-(unsigned) 1)%GMP_NUMB_BITS > 0))
1764a238c70SJohn Marino shift_c = ((mpfr_uexp_t) diff_exp - cancel) % GMP_NUMB_BITS;
1774a238c70SJohn Marino else
1784a238c70SJohn Marino {
1794a238c70SJohn Marino shift_c = diff_exp - (cancel % GMP_NUMB_BITS);
1804a238c70SJohn Marino shift_c = (shift_c + GMP_NUMB_BITS) % GMP_NUMB_BITS;
1814a238c70SJohn Marino }
1824a238c70SJohn Marino MPFR_ASSERTD( shift_c >= 0 && shift_c < GMP_NUMB_BITS);
1834a238c70SJohn Marino
1844a238c70SJohn Marino if (MPFR_UNLIKELY(shift_c == 0))
1854a238c70SJohn Marino {
1864a238c70SJohn Marino cp = MPFR_MANT(c);
1874a238c70SJohn Marino /* Ensure ap != cp */
1884a238c70SJohn Marino if (ap == cp)
1894a238c70SJohn Marino {
1904a238c70SJohn Marino cp = MPFR_TMP_LIMBS_ALLOC (cn);
1914a238c70SJohn Marino MPN_COPY(cp, ap, cn);
1924a238c70SJohn Marino }
1934a238c70SJohn Marino }
1944a238c70SJohn Marino else
1954a238c70SJohn Marino {
1964a238c70SJohn Marino cp = MPFR_TMP_LIMBS_ALLOC (cn + 1);
1974a238c70SJohn Marino cp[0] = mpn_rshift (cp + 1, MPFR_MANT(c), cn++, shift_c);
1984a238c70SJohn Marino }
1994a238c70SJohn Marino
2004a238c70SJohn Marino #ifdef DEBUG
2014a238c70SJohn Marino printf ("rnd=%s shift_b=%d shift_c=%d diffexp=%lu\n",
2024a238c70SJohn Marino mpfr_print_rnd_mode (rnd_mode), shift_b, shift_c,
2034a238c70SJohn Marino (unsigned long) diff_exp);
2044a238c70SJohn Marino #endif
2054a238c70SJohn Marino
2064a238c70SJohn Marino MPFR_ASSERTD (ap != cp);
2074a238c70SJohn Marino MPFR_ASSERTD (bp != cp);
2084a238c70SJohn Marino
2094a238c70SJohn Marino /* here we have shift_c = (diff_exp - cancel) % GMP_NUMB_BITS,
2104a238c70SJohn Marino 0 <= shift_c < GMP_NUMB_BITS
2114a238c70SJohn Marino thus we want cancel2 = ceil((cancel - diff_exp) / GMP_NUMB_BITS) */
2124a238c70SJohn Marino
2134a238c70SJohn Marino /* Possible optimization with a C99 compiler (i.e. well-defined
2144a238c70SJohn Marino integer division): if MPFR_PREC_MAX is reduced to
2154a238c70SJohn Marino ((mpfr_prec_t)((mpfr_uprec_t)(~(mpfr_uprec_t)0)>>1) - GMP_NUMB_BITS + 1)
2164a238c70SJohn Marino and diff_exp is of type mpfr_exp_t (no need for mpfr_uexp_t, since
2174a238c70SJohn Marino the sum or difference of 2 exponents must be representable, as used
2184a238c70SJohn Marino by the multiplication code), then the computation of cancel2 could
2194a238c70SJohn Marino be simplified to
2204a238c70SJohn Marino cancel2 = (cancel - (diff_exp - shift_c)) / GMP_NUMB_BITS;
2214a238c70SJohn Marino because cancel, diff_exp and shift_c are all non-negative and
2224a238c70SJohn Marino these variables are signed. */
2234a238c70SJohn Marino
2244a238c70SJohn Marino MPFR_ASSERTD (cancel >= 0);
2254a238c70SJohn Marino if (cancel >= diff_exp)
2264a238c70SJohn Marino /* Note that cancel is signed and will be converted to mpfr_uexp_t
2274a238c70SJohn Marino (type of diff_exp) in the expression below, so that this will
2284a238c70SJohn Marino work even if cancel is very large and diff_exp = 0. */
2294a238c70SJohn Marino cancel2 = (cancel - diff_exp + (GMP_NUMB_BITS - 1)) / GMP_NUMB_BITS;
2304a238c70SJohn Marino else
2314a238c70SJohn Marino cancel2 = - (mp_size_t) ((diff_exp - cancel) / GMP_NUMB_BITS);
2324a238c70SJohn Marino /* the high cancel2 limbs from b should not be taken into account */
2334a238c70SJohn Marino #ifdef DEBUG
2344a238c70SJohn Marino printf ("cancel=%lu cancel1=%lu cancel2=%ld\n",
2354a238c70SJohn Marino (unsigned long) cancel, (unsigned long) cancel1, (long) cancel2);
2364a238c70SJohn Marino #endif
2374a238c70SJohn Marino
2384a238c70SJohn Marino /* ap[an-1] ap[0]
2394a238c70SJohn Marino <----------------+-----------|---->
2404a238c70SJohn Marino <----------PREC(a)----------><-sh->
2414a238c70SJohn Marino cancel1
2424a238c70SJohn Marino limbs bp[bn-cancel1-1]
2434a238c70SJohn Marino <--...-----><----------------+-----------+----------->
2444a238c70SJohn Marino cancel2
2454a238c70SJohn Marino limbs cp[cn-cancel2-1] cancel2 >= 0
2464a238c70SJohn Marino <--...--><----------------+----------------+---------------->
2474a238c70SJohn Marino (-cancel2) cancel2 < 0
2484a238c70SJohn Marino limbs <----------------+---------------->
2494a238c70SJohn Marino */
2504a238c70SJohn Marino
2514a238c70SJohn Marino /* first part: put in ap[0..an-1] the value of high(b) - high(c),
2524a238c70SJohn Marino where high(b) consists of the high an+cancel1 limbs of b,
2534a238c70SJohn Marino and high(c) consists of the high an+cancel2 limbs of c.
2544a238c70SJohn Marino */
2554a238c70SJohn Marino
2564a238c70SJohn Marino /* copy high(b) into a */
2574a238c70SJohn Marino if (MPFR_LIKELY(an + (mp_size_t) cancel1 <= bn))
2584a238c70SJohn Marino /* a: <----------------+-----------|---->
2594a238c70SJohn Marino b: <-----------------------------------------> */
2604a238c70SJohn Marino MPN_COPY (ap, bp + bn - (an + cancel1), an);
2614a238c70SJohn Marino else
2624a238c70SJohn Marino /* a: <----------------+-----------|---->
2634a238c70SJohn Marino b: <-------------------------> */
2644a238c70SJohn Marino if ((mp_size_t) cancel1 < bn) /* otherwise b does not overlap with a */
2654a238c70SJohn Marino {
2664a238c70SJohn Marino MPN_ZERO (ap, an + cancel1 - bn);
2674a238c70SJohn Marino MPN_COPY (ap + (an + cancel1 - bn), bp, bn - cancel1);
2684a238c70SJohn Marino }
2694a238c70SJohn Marino else
2704a238c70SJohn Marino MPN_ZERO (ap, an);
2714a238c70SJohn Marino
2724a238c70SJohn Marino #ifdef DEBUG
2734a238c70SJohn Marino printf("after copying high(b), a="); mpfr_print_binary(a); putchar('\n');
2744a238c70SJohn Marino #endif
2754a238c70SJohn Marino
2764a238c70SJohn Marino /* subtract high(c) */
2774a238c70SJohn Marino if (MPFR_LIKELY(an + cancel2 > 0)) /* otherwise c does not overlap with a */
2784a238c70SJohn Marino {
2794a238c70SJohn Marino mp_limb_t *ap2;
2804a238c70SJohn Marino
2814a238c70SJohn Marino if (cancel2 >= 0)
2824a238c70SJohn Marino {
2834a238c70SJohn Marino if (an + cancel2 <= cn)
2844a238c70SJohn Marino /* a: <----------------------------->
2854a238c70SJohn Marino c: <-----------------------------------------> */
2864a238c70SJohn Marino mpn_sub_n (ap, ap, cp + cn - (an + cancel2), an);
2874a238c70SJohn Marino else
2884a238c70SJohn Marino /* a: <---------------------------->
2894a238c70SJohn Marino c: <-------------------------> */
2904a238c70SJohn Marino {
2914a238c70SJohn Marino ap2 = ap + an + (cancel2 - cn);
2924a238c70SJohn Marino if (cn > cancel2)
2934a238c70SJohn Marino mpn_sub_n (ap2, ap2, cp, cn - cancel2);
2944a238c70SJohn Marino }
2954a238c70SJohn Marino }
2964a238c70SJohn Marino else /* cancel2 < 0 */
2974a238c70SJohn Marino {
2984a238c70SJohn Marino mp_limb_t borrow;
2994a238c70SJohn Marino
3004a238c70SJohn Marino if (an + cancel2 <= cn)
3014a238c70SJohn Marino /* a: <----------------------------->
3024a238c70SJohn Marino c: <-----------------------------> */
3034a238c70SJohn Marino borrow = mpn_sub_n (ap, ap, cp + cn - (an + cancel2),
3044a238c70SJohn Marino an + cancel2);
3054a238c70SJohn Marino else
3064a238c70SJohn Marino /* a: <---------------------------->
3074a238c70SJohn Marino c: <----------------> */
3084a238c70SJohn Marino {
3094a238c70SJohn Marino ap2 = ap + an + cancel2 - cn;
3104a238c70SJohn Marino borrow = mpn_sub_n (ap2, ap2, cp, cn);
3114a238c70SJohn Marino }
3124a238c70SJohn Marino ap2 = ap + an + cancel2;
3134a238c70SJohn Marino mpn_sub_1 (ap2, ap2, -cancel2, borrow);
3144a238c70SJohn Marino }
3154a238c70SJohn Marino }
3164a238c70SJohn Marino
3174a238c70SJohn Marino #ifdef DEBUG
3184a238c70SJohn Marino printf("after subtracting high(c), a=");
3194a238c70SJohn Marino mpfr_print_binary(a);
3204a238c70SJohn Marino putchar('\n');
3214a238c70SJohn Marino #endif
3224a238c70SJohn Marino
3234a238c70SJohn Marino /* now perform rounding */
3244a238c70SJohn Marino sh = (mpfr_prec_t) an * GMP_NUMB_BITS - MPFR_PREC(a);
3254a238c70SJohn Marino /* last unused bits from a */
3264a238c70SJohn Marino carry = ap[0] & MPFR_LIMB_MASK (sh);
3274a238c70SJohn Marino ap[0] -= carry;
3284a238c70SJohn Marino
3294a238c70SJohn Marino if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
3304a238c70SJohn Marino {
3314a238c70SJohn Marino if (MPFR_LIKELY(sh))
3324a238c70SJohn Marino {
3334a238c70SJohn Marino /* can decide except when carry = 2^(sh-1) [middle]
3344a238c70SJohn Marino or carry = 0 [truncate, but cannot decide inexact flag] */
3354a238c70SJohn Marino if (carry > (MPFR_LIMB_ONE << (sh - 1)))
3364a238c70SJohn Marino goto add_one_ulp;
3374a238c70SJohn Marino else if ((0 < carry) && (carry < (MPFR_LIMB_ONE << (sh - 1))))
3384a238c70SJohn Marino {
3394a238c70SJohn Marino inexact = -1; /* result if smaller than exact value */
3404a238c70SJohn Marino goto truncate;
3414a238c70SJohn Marino }
3424a238c70SJohn Marino /* now carry = 2^(sh-1), in which case cmp_low=2,
3434a238c70SJohn Marino or carry = 0, in which case cmp_low=0 */
3444a238c70SJohn Marino cmp_low = (carry == 0) ? 0 : 2;
3454a238c70SJohn Marino }
3464a238c70SJohn Marino }
3474a238c70SJohn Marino else /* directed rounding: set rnd_mode to RNDZ iff toward zero */
3484a238c70SJohn Marino {
3494a238c70SJohn Marino if (MPFR_IS_RNDUTEST_OR_RNDDNOTTEST(rnd_mode, MPFR_IS_NEG(a)))
3504a238c70SJohn Marino rnd_mode = MPFR_RNDZ;
3514a238c70SJohn Marino
3524a238c70SJohn Marino if (carry)
3534a238c70SJohn Marino {
3544a238c70SJohn Marino if (rnd_mode == MPFR_RNDZ)
3554a238c70SJohn Marino {
3564a238c70SJohn Marino inexact = -1;
3574a238c70SJohn Marino goto truncate;
3584a238c70SJohn Marino }
3594a238c70SJohn Marino else /* round away */
3604a238c70SJohn Marino goto add_one_ulp;
3614a238c70SJohn Marino }
3624a238c70SJohn Marino }
3634a238c70SJohn Marino
3644a238c70SJohn Marino /* we have to consider the low (bn - (an+cancel1)) limbs from b,
3654a238c70SJohn Marino and the (cn - (an+cancel2)) limbs from c. */
3664a238c70SJohn Marino bn -= an + cancel1;
3674a238c70SJohn Marino cn0 = cn;
3684a238c70SJohn Marino cn -= an + cancel2;
3694a238c70SJohn Marino
3704a238c70SJohn Marino #ifdef DEBUG
3714a238c70SJohn Marino printf ("last sh=%d bits from a are %lu, bn=%ld, cn=%ld\n",
3724a238c70SJohn Marino sh, (unsigned long) carry, (long) bn, (long) cn);
3734a238c70SJohn Marino #endif
3744a238c70SJohn Marino
3754a238c70SJohn Marino /* for rounding to nearest, we couldn't conclude up to here in the following
3764a238c70SJohn Marino cases:
3774a238c70SJohn Marino 1. sh = 0, then cmp_low=0: we can either truncate, subtract one ulp
3784a238c70SJohn Marino or add one ulp: -1 ulp < low(b)-low(c) < 1 ulp
3794a238c70SJohn Marino 2. sh > 0 but the low sh bits from high(b)-high(c) equal 2^(sh-1):
3804a238c70SJohn Marino -0.5 ulp <= -1/2^sh < low(b)-low(c)-0.5 < 1/2^sh <= 0.5 ulp
3814a238c70SJohn Marino we can't decide the rounding, in that case cmp_low=2:
3824a238c70SJohn Marino either we truncate and flag=-1, or we add one ulp and flag=1
3834a238c70SJohn Marino 3. the low sh>0 bits from high(b)-high(c) equal 0: we know we have to
3844a238c70SJohn Marino truncate but we can't decide the ternary value, here cmp_low=0:
3854a238c70SJohn Marino -0.5 ulp <= -1/2^sh < low(b)-low(c) < 1/2^sh <= 0.5 ulp
3864a238c70SJohn Marino we always truncate and inexact can be any of -1,0,1
3874a238c70SJohn Marino */
3884a238c70SJohn Marino
3894a238c70SJohn Marino /* note: here cn might exceed cn0, in which case we consider a zero limb */
3904a238c70SJohn Marino for (k = 0; (bn > 0) || (cn > 0); k = 1)
3914a238c70SJohn Marino {
3924a238c70SJohn Marino /* if cmp_low < 0, we know low(b) - low(c) < 0
3934a238c70SJohn Marino if cmp_low > 0, we know low(b) - low(c) > 0
3944a238c70SJohn Marino (more precisely if cmp_low = 2, low(b) - low(c) = 0.5 ulp so far)
3954a238c70SJohn Marino if cmp_low = 0, so far low(b) - low(c) = 0 */
3964a238c70SJohn Marino
3974a238c70SJohn Marino /* get next limbs */
3984a238c70SJohn Marino bb = (bn > 0) ? bp[--bn] : 0;
3994a238c70SJohn Marino if ((cn > 0) && (cn-- <= cn0))
4004a238c70SJohn Marino cc = cp[cn];
4014a238c70SJohn Marino else
4024a238c70SJohn Marino cc = 0;
4034a238c70SJohn Marino
4044a238c70SJohn Marino /* cmp_low compares low(b) and low(c) */
4054a238c70SJohn Marino if (cmp_low == 0) /* case 1 or 3 */
4064a238c70SJohn Marino cmp_low = (bb < cc) ? -2+k : (bb > cc) ? 1 : 0;
4074a238c70SJohn Marino
4084a238c70SJohn Marino /* Case 1 for k=0 splits into 7 subcases:
4094a238c70SJohn Marino 1a: bb > cc + half
4104a238c70SJohn Marino 1b: bb = cc + half
4114a238c70SJohn Marino 1c: 0 < bb - cc < half
4124a238c70SJohn Marino 1d: bb = cc
4134a238c70SJohn Marino 1e: -half < bb - cc < 0
4144a238c70SJohn Marino 1f: bb - cc = -half
4154a238c70SJohn Marino 1g: bb - cc < -half
4164a238c70SJohn Marino
4174a238c70SJohn Marino Case 2 splits into 3 subcases:
4184a238c70SJohn Marino 2a: bb > cc
4194a238c70SJohn Marino 2b: bb = cc
4204a238c70SJohn Marino 2c: bb < cc
4214a238c70SJohn Marino
4224a238c70SJohn Marino Case 3 splits into 3 subcases:
4234a238c70SJohn Marino 3a: bb > cc
4244a238c70SJohn Marino 3b: bb = cc
4254a238c70SJohn Marino 3c: bb < cc
4264a238c70SJohn Marino */
4274a238c70SJohn Marino
4284a238c70SJohn Marino /* the case rounding to nearest with sh=0 is special since one couldn't
4294a238c70SJohn Marino subtract above 1/2 ulp in the trailing limb of the result */
4304a238c70SJohn Marino if (rnd_mode == MPFR_RNDN && sh == 0 && k == 0) /* case 1 for k=0 */
4314a238c70SJohn Marino {
4324a238c70SJohn Marino mp_limb_t half = MPFR_LIMB_HIGHBIT;
4334a238c70SJohn Marino
4344a238c70SJohn Marino /* add one ulp if bb > cc + half
4354a238c70SJohn Marino truncate if cc - half < bb < cc + half
4364a238c70SJohn Marino sub one ulp if bb < cc - half
4374a238c70SJohn Marino */
4384a238c70SJohn Marino
4394a238c70SJohn Marino if (cmp_low < 0) /* bb < cc: -1 ulp < low(b) - low(c) < 0,
4404a238c70SJohn Marino cases 1e, 1f and 1g */
4414a238c70SJohn Marino {
4424a238c70SJohn Marino if (cc >= half)
4434a238c70SJohn Marino cc -= half;
4444a238c70SJohn Marino else /* since bb < cc < half, bb+half < 2*half */
4454a238c70SJohn Marino bb += half;
4464a238c70SJohn Marino /* now we have bb < cc + half:
4474a238c70SJohn Marino we have to subtract one ulp if bb < cc,
4484a238c70SJohn Marino and truncate if bb > cc */
4494a238c70SJohn Marino }
4504a238c70SJohn Marino else if (cmp_low >= 0) /* bb >= cc, cases 1a to 1d */
4514a238c70SJohn Marino {
4524a238c70SJohn Marino if (cc < half)
4534a238c70SJohn Marino cc += half;
4544a238c70SJohn Marino else /* since bb >= cc >= half, bb - half >= 0 */
4554a238c70SJohn Marino bb -= half;
4564a238c70SJohn Marino /* now we have bb > cc - half: we have to add one ulp if bb > cc,
4574a238c70SJohn Marino and truncate if bb < cc */
4584a238c70SJohn Marino if (cmp_low > 0)
4594a238c70SJohn Marino cmp_low = 2;
4604a238c70SJohn Marino }
4614a238c70SJohn Marino }
4624a238c70SJohn Marino
4634a238c70SJohn Marino #ifdef DEBUG
4644a238c70SJohn Marino printf ("k=%u bb=%lu cc=%lu cmp_low=%d\n", k,
4654a238c70SJohn Marino (unsigned long) bb, (unsigned long) cc, cmp_low);
4664a238c70SJohn Marino #endif
4674a238c70SJohn Marino if (cmp_low < 0) /* low(b) - low(c) < 0: either truncate or subtract
4684a238c70SJohn Marino one ulp */
4694a238c70SJohn Marino {
4704a238c70SJohn Marino if (rnd_mode == MPFR_RNDZ)
4714a238c70SJohn Marino goto sub_one_ulp; /* set inexact=-1 */
4724a238c70SJohn Marino else if (rnd_mode != MPFR_RNDN) /* round away */
4734a238c70SJohn Marino {
4744a238c70SJohn Marino inexact = 1;
4754a238c70SJohn Marino goto truncate;
4764a238c70SJohn Marino }
4774a238c70SJohn Marino else /* round to nearest */
4784a238c70SJohn Marino {
4794a238c70SJohn Marino /* If cmp_low < 0 and bb > cc, then -0.5 ulp < low(b)-low(c) < 0,
4804a238c70SJohn Marino whatever the value of sh.
4814a238c70SJohn Marino If sh>0, then cmp_low < 0 implies that the initial neglected
4824a238c70SJohn Marino sh bits were 0 (otherwise cmp_low=2 initially), thus the
4834a238c70SJohn Marino weight of the new bits is less than 0.5 ulp too.
4844a238c70SJohn Marino If k > 0 (and sh=0) this means that either the first neglected
4854a238c70SJohn Marino limbs bb and cc were equal (thus cmp_low was 0 for k=0),
4864a238c70SJohn Marino or we had bb - cc = -0.5 ulp or 0.5 ulp.
4874a238c70SJohn Marino The last case is not possible here since we would have
4884a238c70SJohn Marino cmp_low > 0 which is sticky.
4894a238c70SJohn Marino In the first case (where we have cmp_low = -1), we truncate,
4904a238c70SJohn Marino whereas in the 2nd case we have cmp_low = -2 and we subtract
4914a238c70SJohn Marino one ulp.
4924a238c70SJohn Marino */
4934a238c70SJohn Marino if (bb > cc || sh > 0 || cmp_low == -1)
4944a238c70SJohn Marino { /* -0.5 ulp < low(b)-low(c) < 0,
4954a238c70SJohn Marino bb > cc corresponds to cases 1e and 1f1
4964a238c70SJohn Marino sh > 0 corresponds to cases 3c and 3b3
4974a238c70SJohn Marino cmp_low = -1 corresponds to case 1d3 (also 3b3) */
4984a238c70SJohn Marino inexact = 1;
4994a238c70SJohn Marino goto truncate;
5004a238c70SJohn Marino }
5014a238c70SJohn Marino else if (bb < cc) /* here sh = 0 and low(b)-low(c) < -0.5 ulp,
5024a238c70SJohn Marino this corresponds to cases 1g and 1f3 */
5034a238c70SJohn Marino goto sub_one_ulp;
5044a238c70SJohn Marino /* the only case where we can't conclude is sh=0 and bb=cc,
5054a238c70SJohn Marino i.e., we have low(b) - low(c) = -0.5 ulp (up to now), thus
5064a238c70SJohn Marino we don't know if we must truncate or subtract one ulp.
5074a238c70SJohn Marino Note: for sh=0 we can't have low(b) - low(c) = -0.5 ulp up to
5084a238c70SJohn Marino now, since low(b) - low(c) > 1/2^sh */
5094a238c70SJohn Marino }
5104a238c70SJohn Marino }
5114a238c70SJohn Marino else if (cmp_low > 0) /* 0 < low(b) - low(c): either truncate or
5124a238c70SJohn Marino add one ulp */
5134a238c70SJohn Marino {
5144a238c70SJohn Marino if (rnd_mode == MPFR_RNDZ)
5154a238c70SJohn Marino {
5164a238c70SJohn Marino inexact = -1;
5174a238c70SJohn Marino goto truncate;
5184a238c70SJohn Marino }
5194a238c70SJohn Marino else if (rnd_mode != MPFR_RNDN) /* round away */
5204a238c70SJohn Marino goto add_one_ulp;
5214a238c70SJohn Marino else /* round to nearest */
5224a238c70SJohn Marino {
5234a238c70SJohn Marino if (bb > cc)
5244a238c70SJohn Marino {
5254a238c70SJohn Marino /* if sh=0, then bb>cc means that low(b)-low(c) > 0.5 ulp,
5264a238c70SJohn Marino and similarly when cmp_low=2 */
5274a238c70SJohn Marino if (cmp_low == 2) /* cases 1a, 1b1, 2a and 2b1 */
5284a238c70SJohn Marino goto add_one_ulp;
5294a238c70SJohn Marino /* sh > 0 and cmp_low > 0: this implies that the sh initial
5304a238c70SJohn Marino neglected bits were 0, and the remaining low(b)-low(c)>0,
5314a238c70SJohn Marino but its weight is less than 0.5 ulp */
5324a238c70SJohn Marino else /* 0 < low(b) - low(c) < 0.5 ulp, this corresponds to
5334a238c70SJohn Marino cases 3a, 1d1 and 3b1 */
5344a238c70SJohn Marino {
5354a238c70SJohn Marino inexact = -1;
5364a238c70SJohn Marino goto truncate;
5374a238c70SJohn Marino }
5384a238c70SJohn Marino }
5394a238c70SJohn Marino else if (bb < cc) /* 0 < low(b) - low(c) < 0.5 ulp, cases 1c,
5404a238c70SJohn Marino 1b3, 2b3 and 2c */
5414a238c70SJohn Marino {
5424a238c70SJohn Marino inexact = -1;
5434a238c70SJohn Marino goto truncate;
5444a238c70SJohn Marino }
5454a238c70SJohn Marino /* the only case where we can't conclude is bb=cc, i.e.,
5464a238c70SJohn Marino low(b) - low(c) = 0.5 ulp (up to now), thus we don't know
5474a238c70SJohn Marino if we must truncate or add one ulp. */
5484a238c70SJohn Marino }
5494a238c70SJohn Marino }
5504a238c70SJohn Marino /* after k=0, we cannot conclude in the following cases, we split them
5514a238c70SJohn Marino according to the values of bb and cc for k=1:
5524a238c70SJohn Marino 1b. sh=0 and cmp_low = 1 and bb-cc = half [around 0.5 ulp]
5534a238c70SJohn Marino 1b1. bb > cc: add one ulp, inex = 1
5544a238c70SJohn Marino 1b2: bb = cc: cannot conclude
5554a238c70SJohn Marino 1b3: bb < cc: truncate, inex = -1
5564a238c70SJohn Marino 1d. sh=0 and cmp_low = 0 and bb-cc = 0 [around 0]
5574a238c70SJohn Marino 1d1: bb > cc: truncate, inex = -1
5584a238c70SJohn Marino 1d2: bb = cc: cannot conclude
5594a238c70SJohn Marino 1d3: bb < cc: truncate, inex = +1
5604a238c70SJohn Marino 1f. sh=0 and cmp_low = -1 and bb-cc = -half [around -0.5 ulp]
5614a238c70SJohn Marino 1f1: bb > cc: truncate, inex = +1
5624a238c70SJohn Marino 1f2: bb = cc: cannot conclude
5634a238c70SJohn Marino 1f3: bb < cc: sub one ulp, inex = -1
5644a238c70SJohn Marino 2b. sh > 0 and cmp_low = 2 and bb=cc [around 0.5 ulp]
5654a238c70SJohn Marino 2b1. bb > cc: add one ulp, inex = 1
5664a238c70SJohn Marino 2b2: bb = cc: cannot conclude
5674a238c70SJohn Marino 2b3: bb < cc: truncate, inex = -1
5684a238c70SJohn Marino 3b. sh > 0 and cmp_low = 0 [around 0]
5694a238c70SJohn Marino 3b1. bb > cc: truncate, inex = -1
5704a238c70SJohn Marino 3b2: bb = cc: cannot conclude
5714a238c70SJohn Marino 3b3: bb < cc: truncate, inex = +1
5724a238c70SJohn Marino */
5734a238c70SJohn Marino }
5744a238c70SJohn Marino
5754a238c70SJohn Marino if ((rnd_mode == MPFR_RNDN) && cmp_low != 0)
5764a238c70SJohn Marino {
5774a238c70SJohn Marino /* even rounding rule */
5784a238c70SJohn Marino if ((ap[0] >> sh) & 1)
5794a238c70SJohn Marino {
5804a238c70SJohn Marino if (cmp_low < 0)
5814a238c70SJohn Marino goto sub_one_ulp;
5824a238c70SJohn Marino else
5834a238c70SJohn Marino goto add_one_ulp;
5844a238c70SJohn Marino }
5854a238c70SJohn Marino else
5864a238c70SJohn Marino inexact = (cmp_low > 0) ? -1 : 1;
5874a238c70SJohn Marino }
5884a238c70SJohn Marino else
5894a238c70SJohn Marino inexact = 0;
5904a238c70SJohn Marino goto truncate;
5914a238c70SJohn Marino
5924a238c70SJohn Marino sub_one_ulp: /* sub one unit in last place to a */
5934a238c70SJohn Marino mpn_sub_1 (ap, ap, an, MPFR_LIMB_ONE << sh);
5944a238c70SJohn Marino inexact = -1;
5954a238c70SJohn Marino goto end_of_sub;
5964a238c70SJohn Marino
5974a238c70SJohn Marino add_one_ulp: /* add one unit in last place to a */
5984a238c70SJohn Marino if (MPFR_UNLIKELY(mpn_add_1 (ap, ap, an, MPFR_LIMB_ONE << sh)))
5994a238c70SJohn Marino /* result is a power of 2: 11111111111111 + 1 = 1000000000000000 */
6004a238c70SJohn Marino {
6014a238c70SJohn Marino ap[an-1] = MPFR_LIMB_HIGHBIT;
6024a238c70SJohn Marino add_exp = 1;
6034a238c70SJohn Marino }
6044a238c70SJohn Marino inexact = 1; /* result larger than exact value */
6054a238c70SJohn Marino
6064a238c70SJohn Marino truncate:
6074a238c70SJohn Marino if (MPFR_UNLIKELY((ap[an-1] >> (GMP_NUMB_BITS - 1)) == 0))
6084a238c70SJohn Marino /* case 1 - epsilon */
6094a238c70SJohn Marino {
6104a238c70SJohn Marino ap[an-1] = MPFR_LIMB_HIGHBIT;
6114a238c70SJohn Marino add_exp = 1;
6124a238c70SJohn Marino }
6134a238c70SJohn Marino
6144a238c70SJohn Marino end_of_sub:
6154a238c70SJohn Marino /* we have to set MPFR_EXP(a) to MPFR_EXP(b) - cancel + add_exp, taking
6164a238c70SJohn Marino care of underflows/overflows in that computation, and of the allowed
6174a238c70SJohn Marino exponent range */
6184a238c70SJohn Marino if (MPFR_LIKELY(cancel))
6194a238c70SJohn Marino {
6204a238c70SJohn Marino mpfr_exp_t exp_a;
6214a238c70SJohn Marino
6224a238c70SJohn Marino cancel -= add_exp; /* OK: add_exp is an int equal to 0 or 1 */
6234a238c70SJohn Marino exp_a = MPFR_GET_EXP (b) - cancel;
6244a238c70SJohn Marino if (MPFR_UNLIKELY(exp_a < __gmpfr_emin))
6254a238c70SJohn Marino {
6264a238c70SJohn Marino MPFR_TMP_FREE(marker);
6274a238c70SJohn Marino if (rnd_mode == MPFR_RNDN &&
6284a238c70SJohn Marino (exp_a < __gmpfr_emin - 1 ||
6294a238c70SJohn Marino (inexact >= 0 && mpfr_powerof2_raw (a))))
6304a238c70SJohn Marino rnd_mode = MPFR_RNDZ;
6314a238c70SJohn Marino return mpfr_underflow (a, rnd_mode, MPFR_SIGN(a));
6324a238c70SJohn Marino }
6334a238c70SJohn Marino MPFR_SET_EXP (a, exp_a);
6344a238c70SJohn Marino }
6354a238c70SJohn Marino else /* cancel = 0: MPFR_EXP(a) <- MPFR_EXP(b) + add_exp */
6364a238c70SJohn Marino {
6374a238c70SJohn Marino /* in case cancel = 0, add_exp can still be 1, in case b is just
6384a238c70SJohn Marino below a power of two, c is very small, prec(a) < prec(b),
6394a238c70SJohn Marino and rnd=away or nearest */
6404a238c70SJohn Marino mpfr_exp_t exp_b;
6414a238c70SJohn Marino
6424a238c70SJohn Marino exp_b = MPFR_GET_EXP (b);
6434a238c70SJohn Marino if (MPFR_UNLIKELY(add_exp && exp_b == __gmpfr_emax))
6444a238c70SJohn Marino {
6454a238c70SJohn Marino MPFR_TMP_FREE(marker);
6464a238c70SJohn Marino return mpfr_overflow (a, rnd_mode, MPFR_SIGN(a));
6474a238c70SJohn Marino }
6484a238c70SJohn Marino MPFR_SET_EXP (a, exp_b + add_exp);
6494a238c70SJohn Marino }
6504a238c70SJohn Marino MPFR_TMP_FREE(marker);
6514a238c70SJohn Marino #ifdef DEBUG
6524a238c70SJohn Marino printf ("result is a="); mpfr_print_binary(a); putchar('\n');
6534a238c70SJohn Marino #endif
6544a238c70SJohn Marino /* check that result is msb-normalized */
6554a238c70SJohn Marino MPFR_ASSERTD(ap[an-1] > ~ap[an-1]);
6564a238c70SJohn Marino MPFR_RET (inexact * MPFR_INT_SIGN (a));
6574a238c70SJohn Marino }
658