14a238c70SJohn Marino /* mpfr_div -- divide two floating-point numbers
24a238c70SJohn Marino
3*ab6d115fSJohn Marino Copyright 1999, 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 /* References:
244a238c70SJohn Marino [1] Short Division of Long Integers, David Harvey and Paul Zimmermann,
254a238c70SJohn Marino Proceedings of the 20th Symposium on Computer Arithmetic (ARITH-20),
264a238c70SJohn Marino July 25-27, 2011, pages 7-14.
274a238c70SJohn Marino */
284a238c70SJohn Marino
294a238c70SJohn Marino #define MPFR_NEED_LONGLONG_H
304a238c70SJohn Marino #include "mpfr-impl.h"
314a238c70SJohn Marino
324a238c70SJohn Marino #ifdef DEBUG2
334a238c70SJohn Marino #define mpfr_mpn_print(ap,n) mpfr_mpn_print3 (ap,n,MPFR_LIMB_ZERO)
344a238c70SJohn Marino static void
mpfr_mpn_print3(mpfr_limb_ptr ap,mp_size_t n,mp_limb_t cy)354a238c70SJohn Marino mpfr_mpn_print3 (mpfr_limb_ptr ap, mp_size_t n, mp_limb_t cy)
364a238c70SJohn Marino {
374a238c70SJohn Marino mp_size_t i;
384a238c70SJohn Marino for (i = 0; i < n; i++)
394a238c70SJohn Marino printf ("+%lu*2^%lu", (unsigned long) ap[i], (unsigned long)
404a238c70SJohn Marino (GMP_NUMB_BITS * i));
414a238c70SJohn Marino if (cy)
424a238c70SJohn Marino printf ("+2^%lu", (unsigned long) (GMP_NUMB_BITS * n));
434a238c70SJohn Marino printf ("\n");
444a238c70SJohn Marino }
454a238c70SJohn Marino #endif
464a238c70SJohn Marino
474a238c70SJohn Marino /* check if {ap, an} is zero */
484a238c70SJohn Marino static int
mpfr_mpn_cmpzero(mpfr_limb_ptr ap,mp_size_t an)494a238c70SJohn Marino mpfr_mpn_cmpzero (mpfr_limb_ptr ap, mp_size_t an)
504a238c70SJohn Marino {
514a238c70SJohn Marino while (an > 0)
524a238c70SJohn Marino if (MPFR_LIKELY(ap[--an] != MPFR_LIMB_ZERO))
534a238c70SJohn Marino return 1;
544a238c70SJohn Marino return 0;
554a238c70SJohn Marino }
564a238c70SJohn Marino
574a238c70SJohn Marino /* compare {ap, an} and {bp, bn} >> extra,
584a238c70SJohn Marino aligned by the more significant limbs.
594a238c70SJohn Marino Takes into account bp[0] for extra=1.
604a238c70SJohn Marino */
614a238c70SJohn Marino static int
mpfr_mpn_cmp_aux(mpfr_limb_ptr ap,mp_size_t an,mpfr_limb_ptr bp,mp_size_t bn,int extra)624a238c70SJohn Marino mpfr_mpn_cmp_aux (mpfr_limb_ptr ap, mp_size_t an,
634a238c70SJohn Marino mpfr_limb_ptr bp, mp_size_t bn, int extra)
644a238c70SJohn Marino {
654a238c70SJohn Marino int cmp = 0;
664a238c70SJohn Marino mp_size_t k;
674a238c70SJohn Marino mp_limb_t bb;
684a238c70SJohn Marino
694a238c70SJohn Marino if (an >= bn)
704a238c70SJohn Marino {
714a238c70SJohn Marino k = an - bn;
724a238c70SJohn Marino while (cmp == 0 && bn > 0)
734a238c70SJohn Marino {
744a238c70SJohn Marino bn --;
754a238c70SJohn Marino bb = (extra) ? ((bp[bn+1] << (GMP_NUMB_BITS - 1)) | (bp[bn] >> 1))
764a238c70SJohn Marino : bp[bn];
774a238c70SJohn Marino cmp = (ap[k + bn] > bb) ? 1 : ((ap[k + bn] < bb) ? -1 : 0);
784a238c70SJohn Marino }
794a238c70SJohn Marino bb = (extra) ? bp[0] << (GMP_NUMB_BITS - 1) : MPFR_LIMB_ZERO;
804a238c70SJohn Marino while (cmp == 0 && k > 0)
814a238c70SJohn Marino {
824a238c70SJohn Marino k--;
834a238c70SJohn Marino cmp = (ap[k] > bb) ? 1 : ((ap[k] < bb) ? -1 : 0);
844a238c70SJohn Marino bb = MPFR_LIMB_ZERO; /* ensure we consider only once bp[0] & 1 */
854a238c70SJohn Marino }
864a238c70SJohn Marino if (cmp == 0 && bb != MPFR_LIMB_ZERO)
874a238c70SJohn Marino cmp = -1;
884a238c70SJohn Marino }
894a238c70SJohn Marino else /* an < bn */
904a238c70SJohn Marino {
914a238c70SJohn Marino k = bn - an;
924a238c70SJohn Marino while (cmp == 0 && an > 0)
934a238c70SJohn Marino {
944a238c70SJohn Marino an --;
954a238c70SJohn Marino bb = (extra) ? ((bp[k+an+1] << (GMP_NUMB_BITS - 1)) | (bp[k+an] >> 1))
964a238c70SJohn Marino : bp[k+an];
974a238c70SJohn Marino if (ap[an] > bb)
984a238c70SJohn Marino cmp = 1;
994a238c70SJohn Marino else if (ap[an] < bb)
1004a238c70SJohn Marino cmp = -1;
1014a238c70SJohn Marino }
1024a238c70SJohn Marino while (cmp == 0 && k > 0)
1034a238c70SJohn Marino {
1044a238c70SJohn Marino k--;
1054a238c70SJohn Marino bb = (extra) ? ((bp[k+1] << (GMP_NUMB_BITS - 1)) | (bp[k] >> 1))
1064a238c70SJohn Marino : bp[k];
1074a238c70SJohn Marino cmp = (bb != MPFR_LIMB_ZERO) ? -1 : 0;
1084a238c70SJohn Marino }
1094a238c70SJohn Marino if (cmp == 0 && extra && (bp[0] & MPFR_LIMB_ONE))
1104a238c70SJohn Marino cmp = -1;
1114a238c70SJohn Marino }
1124a238c70SJohn Marino return cmp;
1134a238c70SJohn Marino }
1144a238c70SJohn Marino
1154a238c70SJohn Marino /* {ap, n} <- {ap, n} - {bp, n} >> extra - cy, with cy = 0 or 1.
1164a238c70SJohn Marino Return borrow out.
1174a238c70SJohn Marino */
1184a238c70SJohn Marino static mp_limb_t
mpfr_mpn_sub_aux(mpfr_limb_ptr ap,mpfr_limb_ptr bp,mp_size_t n,mp_limb_t cy,int extra)1194a238c70SJohn Marino mpfr_mpn_sub_aux (mpfr_limb_ptr ap, mpfr_limb_ptr bp, mp_size_t n,
1204a238c70SJohn Marino mp_limb_t cy, int extra)
1214a238c70SJohn Marino {
1224a238c70SJohn Marino mp_limb_t bb, rp;
1234a238c70SJohn Marino
1244a238c70SJohn Marino MPFR_ASSERTD (cy <= 1);
1254a238c70SJohn Marino while (n--)
1264a238c70SJohn Marino {
1274a238c70SJohn Marino bb = (extra) ? ((bp[1] << (GMP_NUMB_BITS-1)) | (bp[0] >> 1)) : bp[0];
1284a238c70SJohn Marino rp = ap[0] - bb - cy;
1294a238c70SJohn Marino cy = (ap[0] < bb) || (cy && ~rp == MPFR_LIMB_ZERO) ?
1304a238c70SJohn Marino MPFR_LIMB_ONE : MPFR_LIMB_ZERO;
1314a238c70SJohn Marino ap[0] = rp;
1324a238c70SJohn Marino ap ++;
1334a238c70SJohn Marino bp ++;
1344a238c70SJohn Marino }
1354a238c70SJohn Marino MPFR_ASSERTD (cy <= 1);
1364a238c70SJohn Marino return cy;
1374a238c70SJohn Marino }
1384a238c70SJohn Marino
1394a238c70SJohn Marino int
mpfr_div(mpfr_ptr q,mpfr_srcptr u,mpfr_srcptr v,mpfr_rnd_t rnd_mode)1404a238c70SJohn Marino mpfr_div (mpfr_ptr q, mpfr_srcptr u, mpfr_srcptr v, mpfr_rnd_t rnd_mode)
1414a238c70SJohn Marino {
1424a238c70SJohn Marino mp_size_t q0size = MPFR_LIMB_SIZE(q); /* number of limbs of destination */
1434a238c70SJohn Marino mp_size_t usize = MPFR_LIMB_SIZE(u);
1444a238c70SJohn Marino mp_size_t vsize = MPFR_LIMB_SIZE(v);
1454a238c70SJohn Marino mp_size_t qsize; /* number of limbs wanted for the computed quotient */
1464a238c70SJohn Marino mp_size_t qqsize;
1474a238c70SJohn Marino mp_size_t k;
1484a238c70SJohn Marino mpfr_limb_ptr q0p = MPFR_MANT(q), qp;
1494a238c70SJohn Marino mpfr_limb_ptr up = MPFR_MANT(u);
1504a238c70SJohn Marino mpfr_limb_ptr vp = MPFR_MANT(v);
1514a238c70SJohn Marino mpfr_limb_ptr ap;
1524a238c70SJohn Marino mpfr_limb_ptr bp;
1534a238c70SJohn Marino mp_limb_t qh;
1544a238c70SJohn Marino mp_limb_t sticky_u = MPFR_LIMB_ZERO;
1554a238c70SJohn Marino mp_limb_t low_u;
1564a238c70SJohn Marino mp_limb_t sticky_v = MPFR_LIMB_ZERO;
1574a238c70SJohn Marino mp_limb_t sticky;
1584a238c70SJohn Marino mp_limb_t sticky3;
1594a238c70SJohn Marino mp_limb_t round_bit = MPFR_LIMB_ZERO;
1604a238c70SJohn Marino mpfr_exp_t qexp;
1614a238c70SJohn Marino int sign_quotient;
1624a238c70SJohn Marino int extra_bit;
1634a238c70SJohn Marino int sh, sh2;
1644a238c70SJohn Marino int inex;
1654a238c70SJohn Marino int like_rndz;
1664a238c70SJohn Marino MPFR_TMP_DECL(marker);
1674a238c70SJohn Marino
1684a238c70SJohn Marino MPFR_LOG_FUNC (
1694a238c70SJohn Marino ("u[%Pu]=%.*Rg v[%Pu]=%.*Rg rnd=%d",
1704a238c70SJohn Marino mpfr_get_prec(u), mpfr_log_prec, u,
1714a238c70SJohn Marino mpfr_get_prec (v),mpfr_log_prec, v, rnd_mode),
1724a238c70SJohn Marino ("q[%Pu]=%.*Rg inexact=%d", mpfr_get_prec(q), mpfr_log_prec, q, inex));
1734a238c70SJohn Marino
1744a238c70SJohn Marino /**************************************************************************
1754a238c70SJohn Marino * *
1764a238c70SJohn Marino * This part of the code deals with special cases *
1774a238c70SJohn Marino * *
1784a238c70SJohn Marino **************************************************************************/
1794a238c70SJohn Marino
1804a238c70SJohn Marino if (MPFR_UNLIKELY(MPFR_ARE_SINGULAR(u,v)))
1814a238c70SJohn Marino {
1824a238c70SJohn Marino if (MPFR_IS_NAN(u) || MPFR_IS_NAN(v))
1834a238c70SJohn Marino {
1844a238c70SJohn Marino MPFR_SET_NAN(q);
1854a238c70SJohn Marino MPFR_RET_NAN;
1864a238c70SJohn Marino }
1874a238c70SJohn Marino sign_quotient = MPFR_MULT_SIGN( MPFR_SIGN(u) , MPFR_SIGN(v) );
1884a238c70SJohn Marino MPFR_SET_SIGN(q, sign_quotient);
1894a238c70SJohn Marino if (MPFR_IS_INF(u))
1904a238c70SJohn Marino {
1914a238c70SJohn Marino if (MPFR_IS_INF(v))
1924a238c70SJohn Marino {
1934a238c70SJohn Marino MPFR_SET_NAN(q);
1944a238c70SJohn Marino MPFR_RET_NAN;
1954a238c70SJohn Marino }
1964a238c70SJohn Marino else
1974a238c70SJohn Marino {
1984a238c70SJohn Marino MPFR_SET_INF(q);
1994a238c70SJohn Marino MPFR_RET(0);
2004a238c70SJohn Marino }
2014a238c70SJohn Marino }
2024a238c70SJohn Marino else if (MPFR_IS_INF(v))
2034a238c70SJohn Marino {
2044a238c70SJohn Marino MPFR_SET_ZERO (q);
2054a238c70SJohn Marino MPFR_RET (0);
2064a238c70SJohn Marino }
2074a238c70SJohn Marino else if (MPFR_IS_ZERO (v))
2084a238c70SJohn Marino {
2094a238c70SJohn Marino if (MPFR_IS_ZERO (u))
2104a238c70SJohn Marino {
2114a238c70SJohn Marino MPFR_SET_NAN(q);
2124a238c70SJohn Marino MPFR_RET_NAN;
2134a238c70SJohn Marino }
2144a238c70SJohn Marino else
2154a238c70SJohn Marino {
2164a238c70SJohn Marino MPFR_ASSERTD (! MPFR_IS_INF (u));
2174a238c70SJohn Marino MPFR_SET_INF(q);
2184a238c70SJohn Marino mpfr_set_divby0 ();
2194a238c70SJohn Marino MPFR_RET(0);
2204a238c70SJohn Marino }
2214a238c70SJohn Marino }
2224a238c70SJohn Marino else
2234a238c70SJohn Marino {
2244a238c70SJohn Marino MPFR_ASSERTD (MPFR_IS_ZERO (u));
2254a238c70SJohn Marino MPFR_SET_ZERO (q);
2264a238c70SJohn Marino MPFR_RET (0);
2274a238c70SJohn Marino }
2284a238c70SJohn Marino }
2294a238c70SJohn Marino
2304a238c70SJohn Marino /**************************************************************************
2314a238c70SJohn Marino * *
2324a238c70SJohn Marino * End of the part concerning special values. *
2334a238c70SJohn Marino * *
2344a238c70SJohn Marino **************************************************************************/
2354a238c70SJohn Marino
2364a238c70SJohn Marino MPFR_TMP_MARK(marker);
2374a238c70SJohn Marino
2384a238c70SJohn Marino /* set sign */
2394a238c70SJohn Marino sign_quotient = MPFR_MULT_SIGN( MPFR_SIGN(u) , MPFR_SIGN(v) );
2404a238c70SJohn Marino MPFR_SET_SIGN(q, sign_quotient);
2414a238c70SJohn Marino
2424a238c70SJohn Marino /* determine if an extra bit comes from the division, i.e. if the
2434a238c70SJohn Marino significand of u (as a fraction in [1/2, 1[) is larger than that
2444a238c70SJohn Marino of v */
2454a238c70SJohn Marino if (MPFR_LIKELY(up[usize - 1] != vp[vsize - 1]))
2464a238c70SJohn Marino extra_bit = (up[usize - 1] > vp[vsize - 1]) ? 1 : 0;
2474a238c70SJohn Marino else /* most significant limbs are equal, must look at further limbs */
2484a238c70SJohn Marino {
2494a238c70SJohn Marino mp_size_t l;
2504a238c70SJohn Marino
2514a238c70SJohn Marino k = usize - 1;
2524a238c70SJohn Marino l = vsize - 1;
2534a238c70SJohn Marino while (k != 0 && l != 0 && up[--k] == vp[--l]);
2544a238c70SJohn Marino /* now k=0 or l=0 or up[k] != vp[l] */
2554a238c70SJohn Marino if (up[k] > vp[l])
2564a238c70SJohn Marino extra_bit = 1;
2574a238c70SJohn Marino else if (up[k] < vp[l])
2584a238c70SJohn Marino extra_bit = 0;
2594a238c70SJohn Marino /* now up[k] = vp[l], thus either k=0 or l=0 */
2604a238c70SJohn Marino else if (l == 0) /* no more divisor limb */
2614a238c70SJohn Marino extra_bit = 1;
2624a238c70SJohn Marino else /* k=0: no more dividend limb */
2634a238c70SJohn Marino extra_bit = mpfr_mpn_cmpzero (vp, l) == 0;
2644a238c70SJohn Marino }
2654a238c70SJohn Marino #ifdef DEBUG
2664a238c70SJohn Marino printf ("extra_bit=%d\n", extra_bit);
2674a238c70SJohn Marino #endif
2684a238c70SJohn Marino
2694a238c70SJohn Marino /* set exponent */
2704a238c70SJohn Marino qexp = MPFR_GET_EXP (u) - MPFR_GET_EXP (v) + extra_bit;
2714a238c70SJohn Marino
2724a238c70SJohn Marino /* sh is the number of zero bits in the low limb of the quotient */
2734a238c70SJohn Marino MPFR_UNSIGNED_MINUS_MODULO(sh, MPFR_PREC(q));
2744a238c70SJohn Marino
2754a238c70SJohn Marino like_rndz = rnd_mode == MPFR_RNDZ ||
2764a238c70SJohn Marino rnd_mode == (sign_quotient < 0 ? MPFR_RNDU : MPFR_RNDD);
2774a238c70SJohn Marino
2784a238c70SJohn Marino /**************************************************************************
2794a238c70SJohn Marino * *
2804a238c70SJohn Marino * We first try Mulders' short division (for large operands) *
2814a238c70SJohn Marino * *
2824a238c70SJohn Marino **************************************************************************/
2834a238c70SJohn Marino
2844a238c70SJohn Marino if (MPFR_UNLIKELY(q0size >= MPFR_DIV_THRESHOLD &&
2854a238c70SJohn Marino vsize >= MPFR_DIV_THRESHOLD))
2864a238c70SJohn Marino {
2874a238c70SJohn Marino mp_size_t n = q0size + 1; /* we will perform a short (2n)/n division */
2884a238c70SJohn Marino mpfr_limb_ptr ap, bp, qp;
2894a238c70SJohn Marino mpfr_prec_t p;
2904a238c70SJohn Marino
2914a238c70SJohn Marino /* since Mulders' short division clobbers the dividend, we have to
2924a238c70SJohn Marino copy it */
2934a238c70SJohn Marino ap = MPFR_TMP_LIMBS_ALLOC (n + n);
2944a238c70SJohn Marino if (usize >= n + n) /* truncate the dividend */
2954a238c70SJohn Marino MPN_COPY(ap, up + usize - (n + n), n + n);
2964a238c70SJohn Marino else /* zero-pad the dividend */
2974a238c70SJohn Marino {
2984a238c70SJohn Marino MPN_COPY(ap + (n + n) - usize, up, usize);
2994a238c70SJohn Marino MPN_ZERO(ap, (n + n) - usize);
3004a238c70SJohn Marino }
3014a238c70SJohn Marino
3024a238c70SJohn Marino if (vsize >= n) /* truncate the divisor */
3034a238c70SJohn Marino bp = vp + vsize - n;
3044a238c70SJohn Marino else /* zero-pad the divisor */
3054a238c70SJohn Marino {
3064a238c70SJohn Marino bp = MPFR_TMP_LIMBS_ALLOC (n);
3074a238c70SJohn Marino MPN_COPY(bp + n - vsize, vp, vsize);
3084a238c70SJohn Marino MPN_ZERO(bp, n - vsize);
3094a238c70SJohn Marino }
3104a238c70SJohn Marino
3114a238c70SJohn Marino qp = MPFR_TMP_LIMBS_ALLOC (n);
3124a238c70SJohn Marino qh = mpfr_divhigh_n (qp, ap, bp, n);
3134a238c70SJohn Marino /* in all cases, the error is at most (2n+2) ulps on qh*B^n+{qp,n},
3144a238c70SJohn Marino cf algorithms.tex */
3154a238c70SJohn Marino
3164a238c70SJohn Marino p = n * GMP_NUMB_BITS - MPFR_INT_CEIL_LOG2 (2 * n + 2);
3174a238c70SJohn Marino /* if qh is 1, then we need only PREC(q)-1 bits of {qp,n},
3184a238c70SJohn Marino if rnd=RNDN, we need to be able to round with a directed rounding
3194a238c70SJohn Marino and one more bit */
3204a238c70SJohn Marino if (MPFR_LIKELY (mpfr_round_p (qp, n, p,
3214a238c70SJohn Marino MPFR_PREC(q) + (rnd_mode == MPFR_RNDN) - qh)))
3224a238c70SJohn Marino {
3234a238c70SJohn Marino /* we can round correctly whatever the rounding mode */
3244a238c70SJohn Marino if (qh == 0)
3254a238c70SJohn Marino MPN_COPY (q0p, qp + 1, q0size);
3264a238c70SJohn Marino else
3274a238c70SJohn Marino {
3284a238c70SJohn Marino mpn_rshift (q0p, qp + 1, q0size, 1);
3294a238c70SJohn Marino q0p[q0size - 1] ^= MPFR_LIMB_HIGHBIT;
3304a238c70SJohn Marino }
3314a238c70SJohn Marino q0p[0] &= ~MPFR_LIMB_MASK(sh); /* put to zero low sh bits */
3324a238c70SJohn Marino
3334a238c70SJohn Marino if (rnd_mode == MPFR_RNDN) /* round to nearest */
3344a238c70SJohn Marino {
3354a238c70SJohn Marino /* we know we can round, thus we are never in the even rule case:
3364a238c70SJohn Marino if the round bit is 0, we truncate
3374a238c70SJohn Marino if the round bit is 1, we add 1 */
3384a238c70SJohn Marino if (qh == 0)
3394a238c70SJohn Marino {
3404a238c70SJohn Marino if (sh > 0)
3414a238c70SJohn Marino round_bit = (qp[1] >> (sh - 1)) & 1;
3424a238c70SJohn Marino else
3434a238c70SJohn Marino round_bit = qp[0] >> (GMP_NUMB_BITS - 1);
3444a238c70SJohn Marino }
3454a238c70SJohn Marino else /* qh = 1 */
3464a238c70SJohn Marino round_bit = (qp[1] >> sh) & 1;
3474a238c70SJohn Marino if (round_bit == 0)
3484a238c70SJohn Marino {
3494a238c70SJohn Marino inex = -1;
3504a238c70SJohn Marino goto truncate;
3514a238c70SJohn Marino }
3524a238c70SJohn Marino else /* round_bit = 1 */
3534a238c70SJohn Marino goto add_one_ulp;
3544a238c70SJohn Marino }
3554a238c70SJohn Marino else if (like_rndz == 0) /* round away */
3564a238c70SJohn Marino goto add_one_ulp;
3574a238c70SJohn Marino /* else round to zero: nothing to do */
3584a238c70SJohn Marino else
3594a238c70SJohn Marino {
3604a238c70SJohn Marino inex = -1;
3614a238c70SJohn Marino goto truncate;
3624a238c70SJohn Marino }
3634a238c70SJohn Marino }
3644a238c70SJohn Marino }
3654a238c70SJohn Marino
3664a238c70SJohn Marino /**************************************************************************
3674a238c70SJohn Marino * *
3684a238c70SJohn Marino * Mulders' short division failed: we revert to integer division *
3694a238c70SJohn Marino * *
3704a238c70SJohn Marino **************************************************************************/
3714a238c70SJohn Marino
3724a238c70SJohn Marino if (MPFR_UNLIKELY(rnd_mode == MPFR_RNDN && sh == 0))
3734a238c70SJohn Marino { /* we compute the quotient with one more limb, in order to get
3744a238c70SJohn Marino the round bit in the quotient, and the remainder only contains
3754a238c70SJohn Marino sticky bits */
3764a238c70SJohn Marino qsize = q0size + 1;
3774a238c70SJohn Marino /* need to allocate memory for the quotient */
3784a238c70SJohn Marino qp = MPFR_TMP_LIMBS_ALLOC (qsize);
3794a238c70SJohn Marino }
3804a238c70SJohn Marino else
3814a238c70SJohn Marino {
3824a238c70SJohn Marino qsize = q0size;
3834a238c70SJohn Marino qp = q0p; /* directly put the quotient in the destination */
3844a238c70SJohn Marino }
3854a238c70SJohn Marino qqsize = qsize + qsize;
3864a238c70SJohn Marino
3874a238c70SJohn Marino /* prepare the dividend */
3884a238c70SJohn Marino ap = MPFR_TMP_LIMBS_ALLOC (qqsize);
3894a238c70SJohn Marino if (MPFR_LIKELY(qqsize > usize)) /* use the full dividend */
3904a238c70SJohn Marino {
3914a238c70SJohn Marino k = qqsize - usize; /* k > 0 */
3924a238c70SJohn Marino MPN_ZERO(ap, k);
3934a238c70SJohn Marino if (extra_bit)
3944a238c70SJohn Marino ap[k - 1] = mpn_rshift (ap + k, up, usize, 1);
3954a238c70SJohn Marino else
3964a238c70SJohn Marino MPN_COPY(ap + k, up, usize);
3974a238c70SJohn Marino }
3984a238c70SJohn Marino else /* truncate the dividend */
3994a238c70SJohn Marino {
4004a238c70SJohn Marino k = usize - qqsize;
4014a238c70SJohn Marino if (extra_bit)
4024a238c70SJohn Marino sticky_u = mpn_rshift (ap, up + k, qqsize, 1);
4034a238c70SJohn Marino else
4044a238c70SJohn Marino MPN_COPY(ap, up + k, qqsize);
4054a238c70SJohn Marino sticky_u = sticky_u || mpfr_mpn_cmpzero (up, k);
4064a238c70SJohn Marino }
4074a238c70SJohn Marino low_u = sticky_u;
4084a238c70SJohn Marino
4094a238c70SJohn Marino /* now sticky_u is non-zero iff the truncated part of u is non-zero */
4104a238c70SJohn Marino
4114a238c70SJohn Marino /* prepare the divisor */
4124a238c70SJohn Marino if (MPFR_LIKELY(vsize >= qsize))
4134a238c70SJohn Marino {
4144a238c70SJohn Marino k = vsize - qsize;
4154a238c70SJohn Marino if (qp != vp)
4164a238c70SJohn Marino bp = vp + k; /* avoid copying the divisor */
4174a238c70SJohn Marino else /* need to copy, since mpn_divrem doesn't allow overlap
4184a238c70SJohn Marino between quotient and divisor, necessarily k = 0
4194a238c70SJohn Marino since quotient and divisor are the same mpfr variable */
4204a238c70SJohn Marino {
4214a238c70SJohn Marino bp = MPFR_TMP_LIMBS_ALLOC (qsize);
4224a238c70SJohn Marino MPN_COPY(bp, vp, vsize);
4234a238c70SJohn Marino }
4244a238c70SJohn Marino sticky_v = sticky_v || mpfr_mpn_cmpzero (vp, k);
4254a238c70SJohn Marino k = 0;
4264a238c70SJohn Marino }
4274a238c70SJohn Marino else /* vsize < qsize: small divisor case */
4284a238c70SJohn Marino {
4294a238c70SJohn Marino bp = vp;
4304a238c70SJohn Marino k = qsize - vsize;
4314a238c70SJohn Marino }
4324a238c70SJohn Marino
4334a238c70SJohn Marino /**************************************************************************
4344a238c70SJohn Marino * *
4354a238c70SJohn Marino * Here we perform the real division of {ap+k,qqsize-k} by {bp,qsize-k} *
4364a238c70SJohn Marino * *
4374a238c70SJohn Marino **************************************************************************/
4384a238c70SJohn Marino
4394a238c70SJohn Marino /* if Mulders' short division failed, we revert to division with remainder */
4404a238c70SJohn Marino qh = mpn_divrem (qp, 0, ap + k, qqsize - k, bp, qsize - k);
4414a238c70SJohn Marino /* warning: qh may be 1 if u1 == v1, but u < v */
4424a238c70SJohn Marino #ifdef DEBUG2
4434a238c70SJohn Marino printf ("q="); mpfr_mpn_print (qp, qsize);
4444a238c70SJohn Marino printf ("r="); mpfr_mpn_print (ap, qsize);
4454a238c70SJohn Marino #endif
4464a238c70SJohn Marino
4474a238c70SJohn Marino k = qsize;
4484a238c70SJohn Marino sticky_u = sticky_u || mpfr_mpn_cmpzero (ap, k);
4494a238c70SJohn Marino
4504a238c70SJohn Marino sticky = sticky_u | sticky_v;
4514a238c70SJohn Marino
4524a238c70SJohn Marino /* now sticky is non-zero iff one of the following holds:
4534a238c70SJohn Marino (a) the truncated part of u is non-zero
4544a238c70SJohn Marino (b) the truncated part of v is non-zero
4554a238c70SJohn Marino (c) the remainder from division is non-zero */
4564a238c70SJohn Marino
4574a238c70SJohn Marino if (MPFR_LIKELY(qsize == q0size))
4584a238c70SJohn Marino {
4594a238c70SJohn Marino sticky3 = qp[0] & MPFR_LIMB_MASK(sh); /* does nothing when sh=0 */
4604a238c70SJohn Marino sh2 = sh;
4614a238c70SJohn Marino }
4624a238c70SJohn Marino else /* qsize = q0size + 1: only happens when rnd_mode=MPFR_RNDN and sh=0 */
4634a238c70SJohn Marino {
4644a238c70SJohn Marino MPN_COPY (q0p, qp + 1, q0size);
4654a238c70SJohn Marino sticky3 = qp[0];
4664a238c70SJohn Marino sh2 = GMP_NUMB_BITS;
4674a238c70SJohn Marino }
4684a238c70SJohn Marino qp[0] ^= sticky3;
4694a238c70SJohn Marino /* sticky3 contains the truncated bits from the quotient,
4704a238c70SJohn Marino including the round bit, and 1 <= sh2 <= GMP_NUMB_BITS
4714a238c70SJohn Marino is the number of bits in sticky3 */
4724a238c70SJohn Marino inex = (sticky != MPFR_LIMB_ZERO) || (sticky3 != MPFR_LIMB_ZERO);
4734a238c70SJohn Marino #ifdef DEBUG
4744a238c70SJohn Marino printf ("sticky=%lu sticky3=%lu inex=%d\n",
4754a238c70SJohn Marino (unsigned long) sticky, (unsigned long) sticky3, inex);
4764a238c70SJohn Marino #endif
4774a238c70SJohn Marino
4784a238c70SJohn Marino /* to round, we distinguish two cases:
4794a238c70SJohn Marino (a) vsize <= qsize: we used the full divisor
4804a238c70SJohn Marino (b) vsize > qsize: the divisor was truncated
4814a238c70SJohn Marino */
4824a238c70SJohn Marino
4834a238c70SJohn Marino #ifdef DEBUG
4844a238c70SJohn Marino printf ("vsize=%lu qsize=%lu\n",
4854a238c70SJohn Marino (unsigned long) vsize, (unsigned long) qsize);
4864a238c70SJohn Marino #endif
4874a238c70SJohn Marino if (MPFR_LIKELY(vsize <= qsize)) /* use the full divisor */
4884a238c70SJohn Marino {
4894a238c70SJohn Marino if (MPFR_LIKELY(rnd_mode == MPFR_RNDN))
4904a238c70SJohn Marino {
4914a238c70SJohn Marino round_bit = sticky3 & (MPFR_LIMB_ONE << (sh2 - 1));
4924a238c70SJohn Marino sticky = (sticky3 ^ round_bit) | sticky_u;
4934a238c70SJohn Marino }
4944a238c70SJohn Marino else if (like_rndz || inex == 0)
4954a238c70SJohn Marino sticky = (inex == 0) ? MPFR_LIMB_ZERO : MPFR_LIMB_ONE;
4964a238c70SJohn Marino else /* round away from zero */
4974a238c70SJohn Marino sticky = MPFR_LIMB_ONE;
4984a238c70SJohn Marino goto case_1;
4994a238c70SJohn Marino }
5004a238c70SJohn Marino else /* vsize > qsize: need to truncate the divisor */
5014a238c70SJohn Marino {
5024a238c70SJohn Marino if (inex == 0)
5034a238c70SJohn Marino goto truncate;
5044a238c70SJohn Marino else
5054a238c70SJohn Marino {
5064a238c70SJohn Marino /* We know the estimated quotient is an upper bound of the exact
5074a238c70SJohn Marino quotient (with rounding toward zero), with a difference of at
5084a238c70SJohn Marino most 2 in qp[0].
5094a238c70SJohn Marino Thus we can round except when sticky3 is 000...000 or 000...001
5104a238c70SJohn Marino for directed rounding, and 100...000 or 100...001 for rounding
5114a238c70SJohn Marino to nearest. (For rounding to nearest, we cannot determine the
5124a238c70SJohn Marino inexact flag for 000...000 or 000...001.)
5134a238c70SJohn Marino */
5144a238c70SJohn Marino mp_limb_t sticky3orig = sticky3;
5154a238c70SJohn Marino if (rnd_mode == MPFR_RNDN)
5164a238c70SJohn Marino {
5174a238c70SJohn Marino round_bit = sticky3 & (MPFR_LIMB_ONE << (sh2 - 1));
5184a238c70SJohn Marino sticky3 = sticky3 ^ round_bit;
5194a238c70SJohn Marino #ifdef DEBUG
5204a238c70SJohn Marino printf ("rb=%lu sb=%lu\n",
5214a238c70SJohn Marino (unsigned long) round_bit, (unsigned long) sticky3);
5224a238c70SJohn Marino #endif
5234a238c70SJohn Marino }
5244a238c70SJohn Marino if (sticky3 != MPFR_LIMB_ZERO && sticky3 != MPFR_LIMB_ONE)
5254a238c70SJohn Marino {
5264a238c70SJohn Marino sticky = sticky3;
5274a238c70SJohn Marino goto case_1;
5284a238c70SJohn Marino }
5294a238c70SJohn Marino else /* hard case: we have to compare q1 * v0 and r + low(u),
5304a238c70SJohn Marino where q1 * v0 has qsize + (vsize-qsize) = vsize limbs, and
5314a238c70SJohn Marino r + low(u) has qsize + (usize-2*qsize) = usize-qsize limbs */
5324a238c70SJohn Marino {
5334a238c70SJohn Marino mp_size_t l;
5344a238c70SJohn Marino mpfr_limb_ptr sp;
5354a238c70SJohn Marino int cmp_s_r;
5364a238c70SJohn Marino mp_limb_t qh2;
5374a238c70SJohn Marino
5384a238c70SJohn Marino sp = MPFR_TMP_LIMBS_ALLOC (vsize);
5394a238c70SJohn Marino k = vsize - qsize;
5404a238c70SJohn Marino /* sp <- {qp, qsize} * {vp, vsize-qsize} */
5414a238c70SJohn Marino qp[0] ^= sticky3orig; /* restore original quotient */
5424a238c70SJohn Marino if (qsize >= k)
5434a238c70SJohn Marino mpn_mul (sp, qp, qsize, vp, k);
5444a238c70SJohn Marino else
5454a238c70SJohn Marino mpn_mul (sp, vp, k, qp, qsize);
5464a238c70SJohn Marino if (qh)
5474a238c70SJohn Marino qh2 = mpn_add_n (sp + qsize, sp + qsize, vp, k);
5484a238c70SJohn Marino else
5494a238c70SJohn Marino qh2 = (mp_limb_t) 0;
5504a238c70SJohn Marino qp[0] ^= sticky3orig; /* restore truncated quotient */
5514a238c70SJohn Marino
5524a238c70SJohn Marino /* compare qh2 + {sp, k + qsize} to {ap, qsize} + low(u) */
5534a238c70SJohn Marino cmp_s_r = (qh2 != 0) ? 1 : mpn_cmp (sp + k, ap, qsize);
5544a238c70SJohn Marino if (cmp_s_r == 0) /* compare {sp, k} and low(u) */
5554a238c70SJohn Marino {
5564a238c70SJohn Marino cmp_s_r = (usize >= qqsize) ?
5574a238c70SJohn Marino mpfr_mpn_cmp_aux (sp, k, up, usize - qqsize, extra_bit) :
5584a238c70SJohn Marino mpfr_mpn_cmpzero (sp, k);
5594a238c70SJohn Marino }
5604a238c70SJohn Marino #ifdef DEBUG
5614a238c70SJohn Marino printf ("cmp(q*v0,r+u0)=%d\n", cmp_s_r);
5624a238c70SJohn Marino #endif
5634a238c70SJohn Marino /* now cmp_s_r > 0 if {sp, vsize} > {ap, qsize} + low(u)
5644a238c70SJohn Marino cmp_s_r = 0 if {sp, vsize} = {ap, qsize} + low(u)
5654a238c70SJohn Marino cmp_s_r < 0 if {sp, vsize} < {ap, qsize} + low(u) */
5664a238c70SJohn Marino if (cmp_s_r <= 0) /* quotient is in [q1, q1+1) */
5674a238c70SJohn Marino {
5684a238c70SJohn Marino sticky = (cmp_s_r == 0) ? sticky3 : MPFR_LIMB_ONE;
5694a238c70SJohn Marino goto case_1;
5704a238c70SJohn Marino }
5714a238c70SJohn Marino else /* cmp_s_r > 0, quotient is < q1: to determine if it is
5724a238c70SJohn Marino in [q1-2,q1-1] or in [q1-1,q1], we need to subtract
5734a238c70SJohn Marino the low part u0 of the dividend u0 from q*v0 */
5744a238c70SJohn Marino {
5754a238c70SJohn Marino mp_limb_t cy = MPFR_LIMB_ZERO;
5764a238c70SJohn Marino
5774a238c70SJohn Marino /* subtract low(u)>>extra_bit if non-zero */
5784a238c70SJohn Marino if (qh2 != 0) /* whatever the value of {up, m + k}, it
5794a238c70SJohn Marino will be smaller than qh2 + {sp, k} */
5804a238c70SJohn Marino cmp_s_r = 1;
5814a238c70SJohn Marino else
5824a238c70SJohn Marino {
5834a238c70SJohn Marino if (low_u != MPFR_LIMB_ZERO)
5844a238c70SJohn Marino {
5854a238c70SJohn Marino mp_size_t m;
5864a238c70SJohn Marino l = usize - qqsize; /* number of low limbs in u */
5874a238c70SJohn Marino m = (l > k) ? l - k : 0;
5884a238c70SJohn Marino cy = (extra_bit) ?
5894a238c70SJohn Marino (up[m] & MPFR_LIMB_ONE) : MPFR_LIMB_ZERO;
5904a238c70SJohn Marino if (l >= k) /* u0 has more limbs than s:
5914a238c70SJohn Marino first look if {up, m} is not zero,
5924a238c70SJohn Marino and compare {sp, k} and {up + m, k} */
5934a238c70SJohn Marino {
5944a238c70SJohn Marino cy = cy || mpfr_mpn_cmpzero (up, m);
5954a238c70SJohn Marino low_u = cy;
5964a238c70SJohn Marino cy = mpfr_mpn_sub_aux (sp, up + m, k,
5974a238c70SJohn Marino cy, extra_bit);
5984a238c70SJohn Marino }
5994a238c70SJohn Marino else /* l < k: s has more limbs than u0 */
6004a238c70SJohn Marino {
6014a238c70SJohn Marino low_u = MPFR_LIMB_ZERO;
6024a238c70SJohn Marino if (cy != MPFR_LIMB_ZERO)
6034a238c70SJohn Marino cy = mpn_sub_1 (sp + k - l - 1, sp + k - l - 1,
6044a238c70SJohn Marino 1, MPFR_LIMB_HIGHBIT);
6054a238c70SJohn Marino cy = mpfr_mpn_sub_aux (sp + k - l, up, l,
6064a238c70SJohn Marino cy, extra_bit);
6074a238c70SJohn Marino }
6084a238c70SJohn Marino }
6094a238c70SJohn Marino MPFR_ASSERTD (cy <= 1);
6104a238c70SJohn Marino cy = mpn_sub_1 (sp + k, sp + k, qsize, cy);
6114a238c70SJohn Marino /* subtract r */
6124a238c70SJohn Marino cy += mpn_sub_n (sp + k, sp + k, ap, qsize);
6134a238c70SJohn Marino MPFR_ASSERTD (cy <= 1);
6144a238c70SJohn Marino /* now compare {sp, ssize} to v */
6154a238c70SJohn Marino cmp_s_r = mpn_cmp (sp, vp, vsize);
6164a238c70SJohn Marino if (cmp_s_r == 0 && low_u != MPFR_LIMB_ZERO)
6174a238c70SJohn Marino cmp_s_r = 1; /* since in fact we subtracted
6184a238c70SJohn Marino less than 1 */
6194a238c70SJohn Marino }
6204a238c70SJohn Marino #ifdef DEBUG
6214a238c70SJohn Marino printf ("cmp(q*v0-(r+u0),v)=%d\n", cmp_s_r);
6224a238c70SJohn Marino #endif
6234a238c70SJohn Marino if (cmp_s_r <= 0) /* q1-1 <= u/v < q1 */
6244a238c70SJohn Marino {
6254a238c70SJohn Marino if (sticky3 == MPFR_LIMB_ONE)
6264a238c70SJohn Marino { /* q1-1 is either representable (directed rounding),
6274a238c70SJohn Marino or the middle of two numbers (nearest) */
6284a238c70SJohn Marino sticky = (cmp_s_r) ? MPFR_LIMB_ONE : MPFR_LIMB_ZERO;
6294a238c70SJohn Marino goto case_1;
6304a238c70SJohn Marino }
6314a238c70SJohn Marino /* now necessarily sticky3=0 */
6324a238c70SJohn Marino else if (round_bit == MPFR_LIMB_ZERO)
6334a238c70SJohn Marino { /* round_bit=0, sticky3=0: q1-1 is exact only
6344a238c70SJohn Marino when sh=0 */
6354a238c70SJohn Marino inex = (cmp_s_r || sh) ? -1 : 0;
6364a238c70SJohn Marino if (rnd_mode == MPFR_RNDN ||
6374a238c70SJohn Marino (! like_rndz && inex != 0))
6384a238c70SJohn Marino {
6394a238c70SJohn Marino inex = 1;
6404a238c70SJohn Marino goto truncate_check_qh;
6414a238c70SJohn Marino }
6424a238c70SJohn Marino else /* round down */
6434a238c70SJohn Marino goto sub_one_ulp;
6444a238c70SJohn Marino }
6454a238c70SJohn Marino else /* sticky3=0, round_bit=1 ==> rounding to nearest */
6464a238c70SJohn Marino {
6474a238c70SJohn Marino inex = cmp_s_r;
6484a238c70SJohn Marino goto truncate;
6494a238c70SJohn Marino }
6504a238c70SJohn Marino }
6514a238c70SJohn Marino else /* q1-2 < u/v < q1-1 */
6524a238c70SJohn Marino {
6534a238c70SJohn Marino /* if rnd=MPFR_RNDN, the result is q1 when
6544a238c70SJohn Marino q1-2 >= q1-2^(sh-1), i.e. sh >= 2,
6554a238c70SJohn Marino otherwise (sh=1) it is q1-2 */
6564a238c70SJohn Marino if (rnd_mode == MPFR_RNDN) /* sh > 0 */
6574a238c70SJohn Marino {
6584a238c70SJohn Marino /* Case sh=1: sb=0 always, and q1-rb is exactly
6594a238c70SJohn Marino representable, like q1-rb-2.
6604a238c70SJohn Marino rb action
6614a238c70SJohn Marino 0 subtract two ulps, inex=-1
6624a238c70SJohn Marino 1 truncate, inex=1
6634a238c70SJohn Marino
6644a238c70SJohn Marino Case sh>1: one ulp is 2^(sh-1) >= 2
6654a238c70SJohn Marino rb sb action
6664a238c70SJohn Marino 0 0 truncate, inex=1
6674a238c70SJohn Marino 0 1 truncate, inex=1
6684a238c70SJohn Marino 1 x truncate, inex=-1
6694a238c70SJohn Marino */
6704a238c70SJohn Marino if (sh == 1)
6714a238c70SJohn Marino {
6724a238c70SJohn Marino if (round_bit == MPFR_LIMB_ZERO)
6734a238c70SJohn Marino {
6744a238c70SJohn Marino inex = -1;
6754a238c70SJohn Marino sh = 0;
6764a238c70SJohn Marino goto sub_two_ulp;
6774a238c70SJohn Marino }
6784a238c70SJohn Marino else
6794a238c70SJohn Marino {
6804a238c70SJohn Marino inex = 1;
6814a238c70SJohn Marino goto truncate_check_qh;
6824a238c70SJohn Marino }
6834a238c70SJohn Marino }
6844a238c70SJohn Marino else /* sh > 1 */
6854a238c70SJohn Marino {
6864a238c70SJohn Marino inex = (round_bit == MPFR_LIMB_ZERO) ? 1 : -1;
6874a238c70SJohn Marino goto truncate_check_qh;
6884a238c70SJohn Marino }
6894a238c70SJohn Marino }
6904a238c70SJohn Marino else if (like_rndz)
6914a238c70SJohn Marino {
6924a238c70SJohn Marino /* the result is down(q1-2), i.e. subtract one
6934a238c70SJohn Marino ulp if sh > 0, and two ulps if sh=0 */
6944a238c70SJohn Marino inex = -1;
6954a238c70SJohn Marino if (sh > 0)
6964a238c70SJohn Marino goto sub_one_ulp;
6974a238c70SJohn Marino else
6984a238c70SJohn Marino goto sub_two_ulp;
6994a238c70SJohn Marino }
7004a238c70SJohn Marino /* if round away from zero, the result is up(q1-1),
7014a238c70SJohn Marino which is q1 unless sh = 0, where it is q1-1 */
7024a238c70SJohn Marino else
7034a238c70SJohn Marino {
7044a238c70SJohn Marino inex = 1;
7054a238c70SJohn Marino if (sh > 0)
7064a238c70SJohn Marino goto truncate_check_qh;
7074a238c70SJohn Marino else /* sh = 0 */
7084a238c70SJohn Marino goto sub_one_ulp;
7094a238c70SJohn Marino }
7104a238c70SJohn Marino }
7114a238c70SJohn Marino }
7124a238c70SJohn Marino }
7134a238c70SJohn Marino }
7144a238c70SJohn Marino }
7154a238c70SJohn Marino
7164a238c70SJohn Marino case_1: /* quotient is in [q1, q1+1),
7174a238c70SJohn Marino round_bit is the round_bit (0 for directed rounding),
7184a238c70SJohn Marino sticky the sticky bit */
7194a238c70SJohn Marino if (like_rndz || (round_bit == MPFR_LIMB_ZERO && sticky == MPFR_LIMB_ZERO))
7204a238c70SJohn Marino {
7214a238c70SJohn Marino inex = round_bit == MPFR_LIMB_ZERO && sticky == MPFR_LIMB_ZERO ? 0 : -1;
7224a238c70SJohn Marino goto truncate;
7234a238c70SJohn Marino }
7244a238c70SJohn Marino else if (rnd_mode == MPFR_RNDN) /* sticky <> 0 or round <> 0 */
7254a238c70SJohn Marino {
7264a238c70SJohn Marino if (round_bit == MPFR_LIMB_ZERO) /* necessarily sticky <> 0 */
7274a238c70SJohn Marino {
7284a238c70SJohn Marino inex = -1;
7294a238c70SJohn Marino goto truncate;
7304a238c70SJohn Marino }
7314a238c70SJohn Marino /* round_bit = 1 */
7324a238c70SJohn Marino else if (sticky != MPFR_LIMB_ZERO)
7334a238c70SJohn Marino goto add_one_ulp; /* inex=1 */
7344a238c70SJohn Marino else /* round_bit=1, sticky=0 */
7354a238c70SJohn Marino goto even_rule;
7364a238c70SJohn Marino }
7374a238c70SJohn Marino else /* round away from zero, sticky <> 0 */
7384a238c70SJohn Marino goto add_one_ulp; /* with inex=1 */
7394a238c70SJohn Marino
7404a238c70SJohn Marino sub_two_ulp:
7414a238c70SJohn Marino /* we cannot subtract MPFR_LIMB_MPFR_LIMB_ONE << (sh+1) since this is
7424a238c70SJohn Marino undefined for sh = GMP_NUMB_BITS */
7434a238c70SJohn Marino qh -= mpn_sub_1 (q0p, q0p, q0size, MPFR_LIMB_ONE << sh);
7444a238c70SJohn Marino /* go through */
7454a238c70SJohn Marino
7464a238c70SJohn Marino sub_one_ulp:
7474a238c70SJohn Marino qh -= mpn_sub_1 (q0p, q0p, q0size, MPFR_LIMB_ONE << sh);
7484a238c70SJohn Marino /* go through truncate_check_qh */
7494a238c70SJohn Marino
7504a238c70SJohn Marino truncate_check_qh:
7514a238c70SJohn Marino if (qh)
7524a238c70SJohn Marino {
7534a238c70SJohn Marino qexp ++;
7544a238c70SJohn Marino q0p[q0size - 1] = MPFR_LIMB_HIGHBIT;
7554a238c70SJohn Marino }
7564a238c70SJohn Marino goto truncate;
7574a238c70SJohn Marino
7584a238c70SJohn Marino even_rule: /* has to set inex */
7594a238c70SJohn Marino inex = (q0p[0] & (MPFR_LIMB_ONE << sh)) ? 1 : -1;
7604a238c70SJohn Marino if (inex < 0)
7614a238c70SJohn Marino goto truncate;
7624a238c70SJohn Marino /* else go through add_one_ulp */
7634a238c70SJohn Marino
7644a238c70SJohn Marino add_one_ulp:
7654a238c70SJohn Marino inex = 1; /* always here */
7664a238c70SJohn Marino if (mpn_add_1 (q0p, q0p, q0size, MPFR_LIMB_ONE << sh))
7674a238c70SJohn Marino {
7684a238c70SJohn Marino qexp ++;
7694a238c70SJohn Marino q0p[q0size - 1] = MPFR_LIMB_HIGHBIT;
7704a238c70SJohn Marino }
7714a238c70SJohn Marino
7724a238c70SJohn Marino truncate: /* inex already set */
7734a238c70SJohn Marino
7744a238c70SJohn Marino MPFR_TMP_FREE(marker);
7754a238c70SJohn Marino
7764a238c70SJohn Marino /* check for underflow/overflow */
7774a238c70SJohn Marino if (MPFR_UNLIKELY(qexp > __gmpfr_emax))
7784a238c70SJohn Marino return mpfr_overflow (q, rnd_mode, sign_quotient);
7794a238c70SJohn Marino else if (MPFR_UNLIKELY(qexp < __gmpfr_emin))
7804a238c70SJohn Marino {
7814a238c70SJohn Marino if (rnd_mode == MPFR_RNDN && ((qexp < __gmpfr_emin - 1) ||
7824a238c70SJohn Marino (inex >= 0 && mpfr_powerof2_raw (q))))
7834a238c70SJohn Marino rnd_mode = MPFR_RNDZ;
7844a238c70SJohn Marino return mpfr_underflow (q, rnd_mode, sign_quotient);
7854a238c70SJohn Marino }
7864a238c70SJohn Marino MPFR_SET_EXP(q, qexp);
7874a238c70SJohn Marino
7884a238c70SJohn Marino inex *= sign_quotient;
7894a238c70SJohn Marino MPFR_RET (inex);
7904a238c70SJohn Marino }
791