xref: /dflybsd-src/contrib/mpfr/src/sub1.c (revision 2786097444a0124b5d33763854de247e230c6629)
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