xref: /dflybsd-src/contrib/mpfr/src/add1.c (revision 2786097444a0124b5d33763854de247e230c6629)
14a238c70SJohn Marino /* mpfr_add1 -- internal function to perform a "real" addition
24a238c70SJohn Marino 
3*ab6d115fSJohn Marino Copyright 1999, 2000, 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|), assuming b and c have same sign,
264a238c70SJohn Marino    and are not NaN, Inf, nor zero. */
274a238c70SJohn Marino int
mpfr_add1(mpfr_ptr a,mpfr_srcptr b,mpfr_srcptr c,mpfr_rnd_t rnd_mode)284a238c70SJohn Marino mpfr_add1 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
294a238c70SJohn Marino {
304a238c70SJohn Marino   mp_limb_t *ap, *bp, *cp;
314a238c70SJohn Marino   mpfr_prec_t aq, bq, cq, aq2;
324a238c70SJohn Marino   mp_size_t an, bn, cn;
334a238c70SJohn Marino   mpfr_exp_t difw, exp;
344a238c70SJohn Marino   int sh, rb, fb, inex;
354a238c70SJohn Marino   mpfr_uexp_t diff_exp;
364a238c70SJohn Marino   MPFR_TMP_DECL(marker);
374a238c70SJohn Marino 
384a238c70SJohn Marino   MPFR_ASSERTD(MPFR_IS_PURE_FP(b));
394a238c70SJohn Marino   MPFR_ASSERTD(MPFR_IS_PURE_FP(c));
404a238c70SJohn Marino 
414a238c70SJohn Marino   MPFR_TMP_MARK(marker);
424a238c70SJohn Marino 
434a238c70SJohn Marino   aq = MPFR_PREC(a);
444a238c70SJohn Marino   bq = MPFR_PREC(b);
454a238c70SJohn Marino   cq = MPFR_PREC(c);
464a238c70SJohn Marino 
47*ab6d115fSJohn Marino   an = MPFR_PREC2LIMBS (aq); /* number of limbs of a */
484a238c70SJohn Marino   aq2 = (mpfr_prec_t) an * GMP_NUMB_BITS;
494a238c70SJohn Marino   sh = aq2 - aq;                  /* non-significant bits in low limb */
504a238c70SJohn Marino 
51*ab6d115fSJohn Marino   bn = MPFR_PREC2LIMBS (bq); /* number of limbs of b */
52*ab6d115fSJohn Marino   cn = MPFR_PREC2LIMBS (cq); /* number of limbs of c */
534a238c70SJohn Marino 
544a238c70SJohn Marino   ap = MPFR_MANT(a);
554a238c70SJohn Marino   bp = MPFR_MANT(b);
564a238c70SJohn Marino   cp = MPFR_MANT(c);
574a238c70SJohn Marino 
584a238c70SJohn Marino   if (MPFR_UNLIKELY(ap == bp))
594a238c70SJohn Marino     {
604a238c70SJohn Marino       bp = MPFR_TMP_LIMBS_ALLOC (bn);
614a238c70SJohn Marino       MPN_COPY (bp, ap, bn);
624a238c70SJohn Marino       if (ap == cp)
634a238c70SJohn Marino         { cp = bp; }
644a238c70SJohn Marino     }
654a238c70SJohn Marino   else if (MPFR_UNLIKELY(ap == cp))
664a238c70SJohn Marino     {
674a238c70SJohn Marino       cp = MPFR_TMP_LIMBS_ALLOC (cn);
684a238c70SJohn Marino       MPN_COPY(cp, ap, cn);
694a238c70SJohn Marino     }
704a238c70SJohn Marino 
714a238c70SJohn Marino   exp = MPFR_GET_EXP (b);
724a238c70SJohn Marino   MPFR_SET_SAME_SIGN(a, b);
734a238c70SJohn Marino   MPFR_UPDATE2_RND_MODE(rnd_mode, MPFR_SIGN(b));
744a238c70SJohn Marino   /* now rnd_mode is either MPFR_RNDN, MPFR_RNDZ or MPFR_RNDA */
754a238c70SJohn Marino   /* Note: exponents can be negative, but the unsigned subtraction is
764a238c70SJohn Marino      a modular subtraction, so that one gets the correct result. */
774a238c70SJohn Marino   diff_exp = (mpfr_uexp_t) exp - MPFR_GET_EXP(c);
784a238c70SJohn Marino 
794a238c70SJohn Marino   /*
804a238c70SJohn Marino    * 1. Compute the significant part A', the non-significant bits of A
814a238c70SJohn Marino    * are taken into account.
824a238c70SJohn Marino    *
834a238c70SJohn Marino    * 2. Perform the rounding. At each iteration, we remember:
844a238c70SJohn Marino    *     _ r = rounding bit
854a238c70SJohn Marino    *     _ f = following bits (same value)
864a238c70SJohn Marino    * where the result has the form: [number A]rfff...fff + a remaining
874a238c70SJohn Marino    * value in the interval [0,2) ulp. We consider the most significant
884a238c70SJohn Marino    * bits of the remaining value to update the result; a possible carry
894a238c70SJohn Marino    * is immediately taken into account and A is updated accordingly. As
904a238c70SJohn Marino    * soon as the bits f don't have the same value, A can be rounded.
914a238c70SJohn Marino    * Variables:
924a238c70SJohn Marino    *     _ rb = rounding bit (0 or 1).
934a238c70SJohn Marino    *     _ fb = following bits (0 or 1), then sticky bit.
944a238c70SJohn Marino    * If fb == 0, the only thing that can change is the sticky bit.
954a238c70SJohn Marino    */
964a238c70SJohn Marino 
974a238c70SJohn Marino   rb = fb = -1; /* means: not initialized */
984a238c70SJohn Marino 
994a238c70SJohn Marino   if (MPFR_UNLIKELY (MPFR_UEXP (aq2) <= diff_exp))
1004a238c70SJohn Marino     { /* c does not overlap with a' */
1014a238c70SJohn Marino       if (MPFR_UNLIKELY(an > bn))
1024a238c70SJohn Marino         { /* a has more limbs than b */
1034a238c70SJohn Marino           /* copy b to the most significant limbs of a */
1044a238c70SJohn Marino           MPN_COPY(ap + (an - bn), bp, bn);
1054a238c70SJohn Marino           /* zero the least significant limbs of a */
1064a238c70SJohn Marino           MPN_ZERO(ap, an - bn);
1074a238c70SJohn Marino         }
1084a238c70SJohn Marino       else /* an <= bn */
1094a238c70SJohn Marino         {
1104a238c70SJohn Marino           /* copy the most significant limbs of b to a */
1114a238c70SJohn Marino           MPN_COPY(ap, bp + (bn - an), an);
1124a238c70SJohn Marino         }
1134a238c70SJohn Marino     }
1144a238c70SJohn Marino   else /* aq2 > diff_exp */
1154a238c70SJohn Marino     { /* c overlaps with a' */
1164a238c70SJohn Marino       mp_limb_t *a2p;
1174a238c70SJohn Marino       mp_limb_t cc;
1184a238c70SJohn Marino       mpfr_prec_t dif;
1194a238c70SJohn Marino       mp_size_t difn, k;
1204a238c70SJohn Marino       int shift;
1214a238c70SJohn Marino 
1224a238c70SJohn Marino       /* copy c (shifted) into a */
1234a238c70SJohn Marino 
1244a238c70SJohn Marino       dif = aq2 - diff_exp;
1254a238c70SJohn Marino       /* dif is the number of bits of c which overlap with a' */
1264a238c70SJohn Marino 
127*ab6d115fSJohn Marino       difn = MPFR_PREC2LIMBS (dif);
1284a238c70SJohn Marino       /* only the highest difn limbs from c have to be considered */
1294a238c70SJohn Marino       if (MPFR_UNLIKELY(difn > cn))
1304a238c70SJohn Marino         {
1314a238c70SJohn Marino           /* c doesn't have enough limbs; take into account the virtual
1324a238c70SJohn Marino              zero limbs now by zeroing the least significant limbs of a' */
1334a238c70SJohn Marino           MPFR_ASSERTD(difn - cn <= an);
1344a238c70SJohn Marino           MPN_ZERO(ap, difn - cn);
1354a238c70SJohn Marino           difn = cn;
1364a238c70SJohn Marino         }
1374a238c70SJohn Marino       k = diff_exp / GMP_NUMB_BITS;
1384a238c70SJohn Marino 
1394a238c70SJohn Marino       /* zero the most significant k limbs of a */
1404a238c70SJohn Marino       a2p = ap + (an - k);
1414a238c70SJohn Marino       MPN_ZERO(a2p, k);
1424a238c70SJohn Marino 
1434a238c70SJohn Marino       shift = diff_exp % GMP_NUMB_BITS;
1444a238c70SJohn Marino 
1454a238c70SJohn Marino       if (MPFR_LIKELY(shift))
1464a238c70SJohn Marino         {
1474a238c70SJohn Marino           MPFR_ASSERTD(a2p - difn >= ap);
1484a238c70SJohn Marino           cc = mpn_rshift(a2p - difn, cp + (cn - difn), difn, shift);
1494a238c70SJohn Marino           if (MPFR_UNLIKELY(a2p - difn > ap))
1504a238c70SJohn Marino             *(a2p - difn - 1) = cc;
1514a238c70SJohn Marino         }
1524a238c70SJohn Marino       else
1534a238c70SJohn Marino         MPN_COPY(a2p - difn, cp + (cn - difn), difn);
1544a238c70SJohn Marino 
1554a238c70SJohn Marino       /* add b to a */
1564a238c70SJohn Marino       cc = MPFR_UNLIKELY(an > bn)
1574a238c70SJohn Marino         ? mpn_add_n(ap + (an - bn), ap + (an - bn), bp, bn)
1584a238c70SJohn Marino         : mpn_add_n(ap, ap, bp + (bn - an), an);
1594a238c70SJohn Marino 
1604a238c70SJohn Marino       if (MPFR_UNLIKELY(cc)) /* carry */
1614a238c70SJohn Marino         {
1624a238c70SJohn Marino           if (MPFR_UNLIKELY(exp == __gmpfr_emax))
1634a238c70SJohn Marino             {
1644a238c70SJohn Marino               inex = mpfr_overflow (a, rnd_mode, MPFR_SIGN(a));
1654a238c70SJohn Marino               goto end_of_add;
1664a238c70SJohn Marino             }
1674a238c70SJohn Marino           exp++;
1684a238c70SJohn Marino           rb = (ap[0] >> sh) & 1; /* LSB(a) --> rounding bit after the shift */
1694a238c70SJohn Marino           if (MPFR_LIKELY(sh))
1704a238c70SJohn Marino             {
1714a238c70SJohn Marino               mp_limb_t mask, bb;
1724a238c70SJohn Marino 
1734a238c70SJohn Marino               mask = MPFR_LIMB_MASK (sh);
1744a238c70SJohn Marino               bb = ap[0] & mask;
1754a238c70SJohn Marino               ap[0] &= (~mask) << 1;
1764a238c70SJohn Marino               if (bb == 0)
1774a238c70SJohn Marino                 fb = 0;
1784a238c70SJohn Marino               else if (bb == mask)
1794a238c70SJohn Marino                 fb = 1;
1804a238c70SJohn Marino             }
1814a238c70SJohn Marino           mpn_rshift(ap, ap, an, 1);
1824a238c70SJohn Marino           ap[an-1] += MPFR_LIMB_HIGHBIT;
1834a238c70SJohn Marino           if (sh && fb < 0)
1844a238c70SJohn Marino             goto rounding;
1854a238c70SJohn Marino         } /* cc */
1864a238c70SJohn Marino     } /* aq2 > diff_exp */
1874a238c70SJohn Marino 
1884a238c70SJohn Marino   /* non-significant bits of a */
1894a238c70SJohn Marino   if (MPFR_LIKELY(rb < 0 && sh))
1904a238c70SJohn Marino     {
1914a238c70SJohn Marino       mp_limb_t mask, bb;
1924a238c70SJohn Marino 
1934a238c70SJohn Marino       mask = MPFR_LIMB_MASK (sh);
1944a238c70SJohn Marino       bb = ap[0] & mask;
1954a238c70SJohn Marino       ap[0] &= ~mask;
1964a238c70SJohn Marino       rb = bb >> (sh - 1);
1974a238c70SJohn Marino       if (MPFR_LIKELY(sh > 1))
1984a238c70SJohn Marino         {
1994a238c70SJohn Marino           mask >>= 1;
2004a238c70SJohn Marino           bb &= mask;
2014a238c70SJohn Marino           if (bb == 0)
2024a238c70SJohn Marino             fb = 0;
2034a238c70SJohn Marino           else if (bb == mask)
2044a238c70SJohn Marino             fb = 1;
2054a238c70SJohn Marino           else
2064a238c70SJohn Marino             goto rounding;
2074a238c70SJohn Marino         }
2084a238c70SJohn Marino     }
2094a238c70SJohn Marino 
2104a238c70SJohn Marino   /* determine rounding and sticky bits (and possible carry) */
2114a238c70SJohn Marino 
2124a238c70SJohn Marino   difw = (mpfr_exp_t) an - (mpfr_exp_t) (diff_exp / GMP_NUMB_BITS);
2134a238c70SJohn Marino   /* difw is the number of limbs from b (regarded as having an infinite
2144a238c70SJohn Marino      precision) that have already been combined with c; -n if the next
2154a238c70SJohn Marino      n limbs from b won't be combined with c. */
2164a238c70SJohn Marino 
2174a238c70SJohn Marino   if (MPFR_UNLIKELY(bn > an))
2184a238c70SJohn Marino     { /* there are still limbs from b that haven't been taken into account */
2194a238c70SJohn Marino       mp_size_t bk;
2204a238c70SJohn Marino 
2214a238c70SJohn Marino       if (fb == 0 && difw <= 0)
2224a238c70SJohn Marino         {
2234a238c70SJohn Marino           fb = 1; /* c hasn't been taken into account ==> sticky bit != 0 */
2244a238c70SJohn Marino           goto rounding;
2254a238c70SJohn Marino         }
2264a238c70SJohn Marino 
2274a238c70SJohn Marino       bk = bn - an; /* index of lowest considered limb from b, > 0 */
2284a238c70SJohn Marino       while (difw < 0)
2294a238c70SJohn Marino         { /* ulp(next limb from b) > msb(c) */
2304a238c70SJohn Marino           mp_limb_t bb;
2314a238c70SJohn Marino 
2324a238c70SJohn Marino           bb = bp[--bk];
2334a238c70SJohn Marino 
2344a238c70SJohn Marino           MPFR_ASSERTD(fb != 0);
2354a238c70SJohn Marino           if (fb > 0)
2364a238c70SJohn Marino             {
2374a238c70SJohn Marino               if (bb != MP_LIMB_T_MAX)
2384a238c70SJohn Marino                 {
2394a238c70SJohn Marino                   fb = 1; /* c hasn't been taken into account
2404a238c70SJohn Marino                              ==> sticky bit != 0 */
2414a238c70SJohn Marino                   goto rounding;
2424a238c70SJohn Marino                 }
2434a238c70SJohn Marino             }
2444a238c70SJohn Marino           else /* fb not initialized yet */
2454a238c70SJohn Marino             {
2464a238c70SJohn Marino               if (rb < 0) /* rb not initialized yet */
2474a238c70SJohn Marino                 {
2484a238c70SJohn Marino                   rb = bb >> (GMP_NUMB_BITS - 1);
2494a238c70SJohn Marino                   bb |= MPFR_LIMB_HIGHBIT;
2504a238c70SJohn Marino                 }
2514a238c70SJohn Marino               fb = 1;
2524a238c70SJohn Marino               if (bb != MP_LIMB_T_MAX)
2534a238c70SJohn Marino                 goto rounding;
2544a238c70SJohn Marino             }
2554a238c70SJohn Marino 
2564a238c70SJohn Marino           if (bk == 0)
2574a238c70SJohn Marino             { /* b has entirely been read */
2584a238c70SJohn Marino               fb = 1; /* c hasn't been taken into account
2594a238c70SJohn Marino                          ==> sticky bit != 0 */
2604a238c70SJohn Marino               goto rounding;
2614a238c70SJohn Marino             }
2624a238c70SJohn Marino 
2634a238c70SJohn Marino           difw++;
2644a238c70SJohn Marino         } /* while */
2654a238c70SJohn Marino       MPFR_ASSERTD(bk > 0 && difw >= 0);
2664a238c70SJohn Marino 
2674a238c70SJohn Marino       if (difw <= cn)
2684a238c70SJohn Marino         {
2694a238c70SJohn Marino           mp_size_t ck;
2704a238c70SJohn Marino           mp_limb_t cprev;
2714a238c70SJohn Marino           int difs;
2724a238c70SJohn Marino 
2734a238c70SJohn Marino           ck = cn - difw;
2744a238c70SJohn Marino           difs = diff_exp % GMP_NUMB_BITS;
2754a238c70SJohn Marino 
2764a238c70SJohn Marino           if (difs == 0 && ck == 0)
2774a238c70SJohn Marino             goto c_read;
2784a238c70SJohn Marino 
2794a238c70SJohn Marino           cprev = ck == cn ? 0 : cp[ck];
2804a238c70SJohn Marino 
2814a238c70SJohn Marino           if (fb < 0)
2824a238c70SJohn Marino             {
2834a238c70SJohn Marino               mp_limb_t bb, cc;
2844a238c70SJohn Marino 
2854a238c70SJohn Marino               if (difs)
2864a238c70SJohn Marino                 {
2874a238c70SJohn Marino                   cc = cprev << (GMP_NUMB_BITS - difs);
2884a238c70SJohn Marino                   if (--ck >= 0)
2894a238c70SJohn Marino                     {
2904a238c70SJohn Marino                       cprev = cp[ck];
2914a238c70SJohn Marino                       cc += cprev >> difs;
2924a238c70SJohn Marino                     }
2934a238c70SJohn Marino                 }
2944a238c70SJohn Marino               else
2954a238c70SJohn Marino                 cc = cp[--ck];
2964a238c70SJohn Marino 
2974a238c70SJohn Marino               bb = bp[--bk] + cc;
2984a238c70SJohn Marino 
2994a238c70SJohn Marino               if (bb < cc /* carry */
3004a238c70SJohn Marino                   && (rb < 0 || (rb ^= 1) == 0)
3014a238c70SJohn Marino                   && mpn_add_1(ap, ap, an, MPFR_LIMB_ONE << sh))
3024a238c70SJohn Marino                 {
3034a238c70SJohn Marino                   if (exp == __gmpfr_emax)
3044a238c70SJohn Marino                     {
3054a238c70SJohn Marino                       inex = mpfr_overflow (a, rnd_mode, MPFR_SIGN(a));
3064a238c70SJohn Marino                       goto end_of_add;
3074a238c70SJohn Marino                     }
3084a238c70SJohn Marino                   exp++;
3094a238c70SJohn Marino                   ap[an-1] = MPFR_LIMB_HIGHBIT;
3104a238c70SJohn Marino                   rb = 0;
3114a238c70SJohn Marino                 }
3124a238c70SJohn Marino 
3134a238c70SJohn Marino               if (rb < 0) /* rb not initialized yet */
3144a238c70SJohn Marino                 {
3154a238c70SJohn Marino                   rb = bb >> (GMP_NUMB_BITS - 1);
3164a238c70SJohn Marino                   bb <<= 1;
3174a238c70SJohn Marino                   bb |= bb >> (GMP_NUMB_BITS - 1);
3184a238c70SJohn Marino                 }
3194a238c70SJohn Marino 
3204a238c70SJohn Marino               fb = bb != 0;
3214a238c70SJohn Marino               if (fb && bb != MP_LIMB_T_MAX)
3224a238c70SJohn Marino                 goto rounding;
3234a238c70SJohn Marino             } /* fb < 0 */
3244a238c70SJohn Marino 
3254a238c70SJohn Marino           while (bk > 0)
3264a238c70SJohn Marino             {
3274a238c70SJohn Marino               mp_limb_t bb, cc;
3284a238c70SJohn Marino 
3294a238c70SJohn Marino               if (difs)
3304a238c70SJohn Marino                 {
3314a238c70SJohn Marino                   if (ck < 0)
3324a238c70SJohn Marino                     goto c_read;
3334a238c70SJohn Marino                   cc = cprev << (GMP_NUMB_BITS - difs);
3344a238c70SJohn Marino                   if (--ck >= 0)
3354a238c70SJohn Marino                     {
3364a238c70SJohn Marino                       cprev = cp[ck];
3374a238c70SJohn Marino                       cc += cprev >> difs;
3384a238c70SJohn Marino                     }
3394a238c70SJohn Marino                 }
3404a238c70SJohn Marino               else
3414a238c70SJohn Marino                 {
3424a238c70SJohn Marino                   if (ck == 0)
3434a238c70SJohn Marino                     goto c_read;
3444a238c70SJohn Marino                   cc = cp[--ck];
3454a238c70SJohn Marino                 }
3464a238c70SJohn Marino 
3474a238c70SJohn Marino               bb = bp[--bk] + cc;
3484a238c70SJohn Marino               if (bb < cc) /* carry */
3494a238c70SJohn Marino                 {
3504a238c70SJohn Marino                   fb ^= 1;
3514a238c70SJohn Marino                   if (fb)
3524a238c70SJohn Marino                     goto rounding;
3534a238c70SJohn Marino                   rb ^= 1;
3544a238c70SJohn Marino                   if (rb == 0 && mpn_add_1(ap, ap, an, MPFR_LIMB_ONE << sh))
3554a238c70SJohn Marino                     {
3564a238c70SJohn Marino                       if (MPFR_UNLIKELY(exp == __gmpfr_emax))
3574a238c70SJohn Marino                         {
3584a238c70SJohn Marino                           inex = mpfr_overflow (a, rnd_mode, MPFR_SIGN(a));
3594a238c70SJohn Marino                           goto end_of_add;
3604a238c70SJohn Marino                         }
3614a238c70SJohn Marino                       exp++;
3624a238c70SJohn Marino                       ap[an-1] = MPFR_LIMB_HIGHBIT;
3634a238c70SJohn Marino                     }
3644a238c70SJohn Marino                 } /* bb < cc */
3654a238c70SJohn Marino 
3664a238c70SJohn Marino               if (!fb && bb != 0)
3674a238c70SJohn Marino                 {
3684a238c70SJohn Marino                   fb = 1;
3694a238c70SJohn Marino                   goto rounding;
3704a238c70SJohn Marino                 }
3714a238c70SJohn Marino               if (fb && bb != MP_LIMB_T_MAX)
3724a238c70SJohn Marino                 goto rounding;
3734a238c70SJohn Marino             } /* while */
3744a238c70SJohn Marino 
3754a238c70SJohn Marino           /* b has entirely been read */
3764a238c70SJohn Marino 
3774a238c70SJohn Marino           if (fb || ck < 0)
3784a238c70SJohn Marino             goto rounding;
3794a238c70SJohn Marino           if (difs && cprev << (GMP_NUMB_BITS - difs))
3804a238c70SJohn Marino             {
3814a238c70SJohn Marino               fb = 1;
3824a238c70SJohn Marino               goto rounding;
3834a238c70SJohn Marino             }
3844a238c70SJohn Marino           while (ck)
3854a238c70SJohn Marino             {
3864a238c70SJohn Marino               if (cp[--ck])
3874a238c70SJohn Marino                 {
3884a238c70SJohn Marino                   fb = 1;
3894a238c70SJohn Marino                   goto rounding;
3904a238c70SJohn Marino                 }
3914a238c70SJohn Marino             } /* while */
3924a238c70SJohn Marino         } /* difw <= cn */
3934a238c70SJohn Marino       else
3944a238c70SJohn Marino         { /* c has entirely been read */
3954a238c70SJohn Marino         c_read:
3964a238c70SJohn Marino           if (fb < 0) /* fb not initialized yet */
3974a238c70SJohn Marino             {
3984a238c70SJohn Marino               mp_limb_t bb;
3994a238c70SJohn Marino 
4004a238c70SJohn Marino               MPFR_ASSERTD(bk > 0);
4014a238c70SJohn Marino               bb = bp[--bk];
4024a238c70SJohn Marino               if (rb < 0) /* rb not initialized yet */
4034a238c70SJohn Marino                 {
4044a238c70SJohn Marino                   rb = bb >> (GMP_NUMB_BITS - 1);
4054a238c70SJohn Marino                   bb &= ~MPFR_LIMB_HIGHBIT;
4064a238c70SJohn Marino                 }
4074a238c70SJohn Marino               fb = bb != 0;
4084a238c70SJohn Marino             } /* fb < 0 */
4094a238c70SJohn Marino           if (fb)
4104a238c70SJohn Marino             goto rounding;
4114a238c70SJohn Marino           while (bk)
4124a238c70SJohn Marino             {
4134a238c70SJohn Marino               if (bp[--bk])
4144a238c70SJohn Marino                 {
4154a238c70SJohn Marino                   fb = 1;
4164a238c70SJohn Marino                   goto rounding;
4174a238c70SJohn Marino                 }
4184a238c70SJohn Marino             } /* while */
4194a238c70SJohn Marino         } /* difw > cn */
4204a238c70SJohn Marino     } /* bn > an */
4214a238c70SJohn Marino   else if (fb != 1) /* if fb == 1, the sticky bit is 1 (no possible carry) */
4224a238c70SJohn Marino     { /* b has entirely been read */
4234a238c70SJohn Marino       if (difw > cn)
4244a238c70SJohn Marino         { /* c has entirely been read */
4254a238c70SJohn Marino           if (rb < 0)
4264a238c70SJohn Marino             rb = 0;
4274a238c70SJohn Marino           fb = 0;
4284a238c70SJohn Marino         }
4294a238c70SJohn Marino       else if (diff_exp > MPFR_UEXP (aq2))
4304a238c70SJohn Marino         { /* b is followed by at least a zero bit, then by c */
4314a238c70SJohn Marino           if (rb < 0)
4324a238c70SJohn Marino             rb = 0;
4334a238c70SJohn Marino           fb = 1;
4344a238c70SJohn Marino         }
4354a238c70SJohn Marino       else
4364a238c70SJohn Marino         {
4374a238c70SJohn Marino           mp_size_t ck;
4384a238c70SJohn Marino           int difs;
4394a238c70SJohn Marino 
4404a238c70SJohn Marino           MPFR_ASSERTD(difw >= 0 && cn >= difw);
4414a238c70SJohn Marino           ck = cn - difw;
4424a238c70SJohn Marino           difs = diff_exp % GMP_NUMB_BITS;
4434a238c70SJohn Marino 
4444a238c70SJohn Marino           if (difs == 0 && ck == 0)
4454a238c70SJohn Marino             { /* c has entirely been read */
4464a238c70SJohn Marino               if (rb < 0)
4474a238c70SJohn Marino                 rb = 0;
4484a238c70SJohn Marino               fb = 0;
4494a238c70SJohn Marino             }
4504a238c70SJohn Marino           else
4514a238c70SJohn Marino             {
4524a238c70SJohn Marino               mp_limb_t cc;
4534a238c70SJohn Marino 
4544a238c70SJohn Marino               cc = difs ? (MPFR_ASSERTD(ck < cn),
4554a238c70SJohn Marino                            cp[ck] << (GMP_NUMB_BITS - difs)) : cp[--ck];
4564a238c70SJohn Marino               if (rb < 0)
4574a238c70SJohn Marino                 {
4584a238c70SJohn Marino                   rb = cc >> (GMP_NUMB_BITS - 1);
4594a238c70SJohn Marino                   cc &= ~MPFR_LIMB_HIGHBIT;
4604a238c70SJohn Marino                 }
4614a238c70SJohn Marino               while (cc == 0)
4624a238c70SJohn Marino                 {
4634a238c70SJohn Marino                   if (ck == 0)
4644a238c70SJohn Marino                     {
4654a238c70SJohn Marino                       fb = 0;
4664a238c70SJohn Marino                       goto rounding;
4674a238c70SJohn Marino                     }
4684a238c70SJohn Marino                   cc = cp[--ck];
4694a238c70SJohn Marino                 } /* while */
4704a238c70SJohn Marino               fb = 1;
4714a238c70SJohn Marino             }
4724a238c70SJohn Marino         }
4734a238c70SJohn Marino     } /* fb != 1 */
4744a238c70SJohn Marino 
4754a238c70SJohn Marino  rounding:
4764a238c70SJohn Marino   /* rnd_mode should be one of MPFR_RNDN, MPFR_RNDZ or MPFR_RNDA */
4774a238c70SJohn Marino   if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
4784a238c70SJohn Marino     {
4794a238c70SJohn Marino       if (fb == 0)
4804a238c70SJohn Marino         {
4814a238c70SJohn Marino           if (rb == 0)
4824a238c70SJohn Marino             {
4834a238c70SJohn Marino               inex = 0;
4844a238c70SJohn Marino               goto set_exponent;
4854a238c70SJohn Marino             }
4864a238c70SJohn Marino           /* round to even */
4874a238c70SJohn Marino           if (ap[0] & (MPFR_LIMB_ONE << sh))
4884a238c70SJohn Marino             goto rndn_away;
4894a238c70SJohn Marino           else
4904a238c70SJohn Marino             goto rndn_zero;
4914a238c70SJohn Marino         }
4924a238c70SJohn Marino       if (rb == 0)
4934a238c70SJohn Marino         {
4944a238c70SJohn Marino         rndn_zero:
4954a238c70SJohn Marino           inex = MPFR_IS_NEG(a) ? 1 : -1;
4964a238c70SJohn Marino           goto set_exponent;
4974a238c70SJohn Marino         }
4984a238c70SJohn Marino       else
4994a238c70SJohn Marino         {
5004a238c70SJohn Marino         rndn_away:
5014a238c70SJohn Marino           inex = MPFR_IS_POS(a) ? 1 : -1;
5024a238c70SJohn Marino           goto add_one_ulp;
5034a238c70SJohn Marino         }
5044a238c70SJohn Marino     }
5054a238c70SJohn Marino   else if (rnd_mode == MPFR_RNDZ)
5064a238c70SJohn Marino     {
5074a238c70SJohn Marino       inex = rb || fb ? (MPFR_IS_NEG(a) ? 1 : -1) : 0;
5084a238c70SJohn Marino       goto set_exponent;
5094a238c70SJohn Marino     }
5104a238c70SJohn Marino   else
5114a238c70SJohn Marino     {
5124a238c70SJohn Marino       MPFR_ASSERTN (rnd_mode == MPFR_RNDA);
5134a238c70SJohn Marino       inex = rb || fb ? (MPFR_IS_POS(a) ? 1 : -1) : 0;
5144a238c70SJohn Marino       if (inex)
5154a238c70SJohn Marino         goto add_one_ulp;
5164a238c70SJohn Marino       else
5174a238c70SJohn Marino         goto set_exponent;
5184a238c70SJohn Marino     }
5194a238c70SJohn Marino 
5204a238c70SJohn Marino  add_one_ulp: /* add one unit in last place to a */
5214a238c70SJohn Marino   if (MPFR_UNLIKELY(mpn_add_1 (ap, ap, an, MPFR_LIMB_ONE << sh)))
5224a238c70SJohn Marino     {
5234a238c70SJohn Marino       if (MPFR_UNLIKELY(exp == __gmpfr_emax))
5244a238c70SJohn Marino         {
5254a238c70SJohn Marino           inex = mpfr_overflow (a, rnd_mode, MPFR_SIGN(a));
5264a238c70SJohn Marino           goto end_of_add;
5274a238c70SJohn Marino         }
5284a238c70SJohn Marino       exp++;
5294a238c70SJohn Marino       ap[an-1] = MPFR_LIMB_HIGHBIT;
5304a238c70SJohn Marino     }
5314a238c70SJohn Marino 
5324a238c70SJohn Marino  set_exponent:
5334a238c70SJohn Marino   MPFR_SET_EXP (a, exp);
5344a238c70SJohn Marino 
5354a238c70SJohn Marino  end_of_add:
5364a238c70SJohn Marino   MPFR_TMP_FREE(marker);
5374a238c70SJohn Marino   MPFR_RET (inex);
5384a238c70SJohn Marino }
539