xref: /dragonfly/contrib/mpfr/src/eint.c (revision ab6d115f)
14a238c70SJohn Marino /* mpfr_eint, mpfr_eint1 -- the exponential integral
24a238c70SJohn Marino 
3*ab6d115fSJohn Marino Copyright 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 #define MPFR_NEED_LONGLONG_H
244a238c70SJohn Marino #include "mpfr-impl.h"
254a238c70SJohn Marino 
264a238c70SJohn Marino /* eint1(x) = -gamma - log(x) - sum((-1)^k*z^k/k/k!, k=1..infinity) for x > 0
274a238c70SJohn Marino             = - eint(-x) for x < 0
284a238c70SJohn Marino    where
294a238c70SJohn Marino    eint (x) = gamma + log(x) + sum(z^k/k/k!, k=1..infinity) for x > 0
304a238c70SJohn Marino    eint (x) is undefined for x < 0.
314a238c70SJohn Marino */
324a238c70SJohn Marino 
334a238c70SJohn Marino /* compute in y an approximation of sum(x^k/k/k!, k=1..infinity),
344a238c70SJohn Marino    and return e such that the absolute error is bound by 2^e ulp(y) */
354a238c70SJohn Marino static mpfr_exp_t
mpfr_eint_aux(mpfr_t y,mpfr_srcptr x)364a238c70SJohn Marino mpfr_eint_aux (mpfr_t y, mpfr_srcptr x)
374a238c70SJohn Marino {
384a238c70SJohn Marino   mpfr_t eps; /* dynamic (absolute) error bound on t */
394a238c70SJohn Marino   mpfr_t erru, errs;
404a238c70SJohn Marino   mpz_t m, s, t, u;
414a238c70SJohn Marino   mpfr_exp_t e, sizeinbase;
424a238c70SJohn Marino   mpfr_prec_t w = MPFR_PREC(y);
434a238c70SJohn Marino   unsigned long k;
444a238c70SJohn Marino   MPFR_GROUP_DECL (group);
454a238c70SJohn Marino 
464a238c70SJohn Marino   /* for |x| <= 1, we have S := sum(x^k/k/k!, k=1..infinity) = x + R(x)
474a238c70SJohn Marino      where |R(x)| <= (x/2)^2/(1-x/2) <= 2*(x/2)^2
484a238c70SJohn Marino      thus |R(x)/x| <= |x|/2
494a238c70SJohn Marino      thus if |x| <= 2^(-PREC(y)) we have |S - o(x)| <= ulp(y) */
504a238c70SJohn Marino 
514a238c70SJohn Marino   if (MPFR_GET_EXP(x) <= - (mpfr_exp_t) w)
524a238c70SJohn Marino     {
534a238c70SJohn Marino       mpfr_set (y, x, MPFR_RNDN);
544a238c70SJohn Marino       return 0;
554a238c70SJohn Marino     }
564a238c70SJohn Marino 
574a238c70SJohn Marino   mpz_init (s); /* initializes to 0 */
584a238c70SJohn Marino   mpz_init (t);
594a238c70SJohn Marino   mpz_init (u);
604a238c70SJohn Marino   mpz_init (m);
614a238c70SJohn Marino   MPFR_GROUP_INIT_3 (group, 31, eps, erru, errs);
624a238c70SJohn Marino   e = mpfr_get_z_2exp (m, x); /* x = m * 2^e */
634a238c70SJohn Marino   MPFR_ASSERTD (mpz_sizeinbase (m, 2) == MPFR_PREC (x));
644a238c70SJohn Marino   if (MPFR_PREC (x) > w)
654a238c70SJohn Marino     {
664a238c70SJohn Marino       e += MPFR_PREC (x) - w;
674a238c70SJohn Marino       mpz_tdiv_q_2exp (m, m, MPFR_PREC (x) - w);
684a238c70SJohn Marino     }
694a238c70SJohn Marino   /* remove trailing zeroes from m: this will speed up much cases where
704a238c70SJohn Marino      x is a small integer divided by a power of 2 */
714a238c70SJohn Marino   k = mpz_scan1 (m, 0);
724a238c70SJohn Marino   mpz_tdiv_q_2exp (m, m, k);
734a238c70SJohn Marino   e += k;
744a238c70SJohn Marino   /* initialize t to 2^w */
754a238c70SJohn Marino   mpz_set_ui (t, 1);
764a238c70SJohn Marino   mpz_mul_2exp (t, t, w);
774a238c70SJohn Marino   mpfr_set_ui (eps, 0, MPFR_RNDN); /* eps[0] = 0 */
784a238c70SJohn Marino   mpfr_set_ui (errs, 0, MPFR_RNDN);
794a238c70SJohn Marino   for (k = 1;; k++)
804a238c70SJohn Marino     {
814a238c70SJohn Marino       /* let eps[k] be the absolute error on t[k]:
824a238c70SJohn Marino          since t[k] = trunc(t[k-1]*m*2^e/k), we have
834a238c70SJohn Marino          eps[k+1] <= 1 + eps[k-1]*m*2^e/k + t[k-1]*m*2^(1-w)*2^e/k
844a238c70SJohn Marino                   =  1 + (eps[k-1] + t[k-1]*2^(1-w))*m*2^e/k
854a238c70SJohn Marino                   = 1 + (eps[k-1]*2^(w-1) + t[k-1])*2^(1-w)*m*2^e/k */
864a238c70SJohn Marino       mpfr_mul_2ui (eps, eps, w - 1, MPFR_RNDU);
874a238c70SJohn Marino       mpfr_add_z (eps, eps, t, MPFR_RNDU);
884a238c70SJohn Marino       MPFR_MPZ_SIZEINBASE2 (sizeinbase, m);
894a238c70SJohn Marino       mpfr_mul_2si (eps, eps, sizeinbase - (w - 1) + e, MPFR_RNDU);
904a238c70SJohn Marino       mpfr_div_ui (eps, eps, k, MPFR_RNDU);
914a238c70SJohn Marino       mpfr_add_ui (eps, eps, 1, MPFR_RNDU);
924a238c70SJohn Marino       mpz_mul (t, t, m);
934a238c70SJohn Marino       if (e < 0)
944a238c70SJohn Marino         mpz_tdiv_q_2exp (t, t, -e);
954a238c70SJohn Marino       else
964a238c70SJohn Marino         mpz_mul_2exp (t, t, e);
974a238c70SJohn Marino       mpz_tdiv_q_ui (t, t, k);
984a238c70SJohn Marino       mpz_tdiv_q_ui (u, t, k);
994a238c70SJohn Marino       mpz_add (s, s, u);
1004a238c70SJohn Marino       /* the absolute error on u is <= 1 + eps[k]/k */
1014a238c70SJohn Marino       mpfr_div_ui (erru, eps, k, MPFR_RNDU);
1024a238c70SJohn Marino       mpfr_add_ui (erru, erru, 1, MPFR_RNDU);
1034a238c70SJohn Marino       /* and that on s is the sum of all errors on u */
1044a238c70SJohn Marino       mpfr_add (errs, errs, erru, MPFR_RNDU);
1054a238c70SJohn Marino       /* we are done when t is smaller than errs */
1064a238c70SJohn Marino       if (mpz_sgn (t) == 0)
1074a238c70SJohn Marino         sizeinbase = 0;
1084a238c70SJohn Marino       else
1094a238c70SJohn Marino         MPFR_MPZ_SIZEINBASE2 (sizeinbase, t);
1104a238c70SJohn Marino       if (sizeinbase < MPFR_GET_EXP (errs))
1114a238c70SJohn Marino         break;
1124a238c70SJohn Marino     }
1134a238c70SJohn Marino   /* the truncation error is bounded by (|t|+eps)/k*(|x|/k + |x|^2/k^2 + ...)
1144a238c70SJohn Marino      <= (|t|+eps)/k*|x|/(k-|x|) */
1154a238c70SJohn Marino   mpz_abs (t, t);
1164a238c70SJohn Marino   mpfr_add_z (eps, eps, t, MPFR_RNDU);
1174a238c70SJohn Marino   mpfr_div_ui (eps, eps, k, MPFR_RNDU);
1184a238c70SJohn Marino   mpfr_abs (erru, x, MPFR_RNDU); /* |x| */
1194a238c70SJohn Marino   mpfr_mul (eps, eps, erru, MPFR_RNDU);
1204a238c70SJohn Marino   mpfr_ui_sub (erru, k, erru, MPFR_RNDD);
1214a238c70SJohn Marino   if (MPFR_IS_NEG (erru))
1224a238c70SJohn Marino     {
1234a238c70SJohn Marino       /* the truncated series does not converge, return fail */
1244a238c70SJohn Marino       e = w;
1254a238c70SJohn Marino     }
1264a238c70SJohn Marino   else
1274a238c70SJohn Marino     {
1284a238c70SJohn Marino       mpfr_div (eps, eps, erru, MPFR_RNDU);
1294a238c70SJohn Marino       mpfr_add (errs, errs, eps, MPFR_RNDU);
1304a238c70SJohn Marino       mpfr_set_z (y, s, MPFR_RNDN);
1314a238c70SJohn Marino       mpfr_div_2ui (y, y, w, MPFR_RNDN);
1324a238c70SJohn Marino       /* errs was an absolute error bound on s. We must convert it to an error
1334a238c70SJohn Marino          in terms of ulp(y). Since ulp(y) = 2^(EXP(y)-PREC(y)), we must
1344a238c70SJohn Marino          divide the error by 2^(EXP(y)-PREC(y)), but since we divided also
1354a238c70SJohn Marino          y by 2^w = 2^PREC(y), we must simply divide by 2^EXP(y). */
1364a238c70SJohn Marino       e = MPFR_GET_EXP (errs) - MPFR_GET_EXP (y);
1374a238c70SJohn Marino     }
1384a238c70SJohn Marino   MPFR_GROUP_CLEAR (group);
1394a238c70SJohn Marino   mpz_clear (s);
1404a238c70SJohn Marino   mpz_clear (t);
1414a238c70SJohn Marino   mpz_clear (u);
1424a238c70SJohn Marino   mpz_clear (m);
1434a238c70SJohn Marino   return e;
1444a238c70SJohn Marino }
1454a238c70SJohn Marino 
1464a238c70SJohn Marino /* Return in y an approximation of Ei(x) using the asymptotic expansion:
1474a238c70SJohn Marino    Ei(x) = exp(x)/x * (1 + 1/x + 2/x^2 + ... + k!/x^k + ...)
1484a238c70SJohn Marino    Assumes x >= PREC(y) * log(2).
1494a238c70SJohn Marino    Returns the error bound in terms of ulp(y).
1504a238c70SJohn Marino */
1514a238c70SJohn Marino static mpfr_exp_t
mpfr_eint_asympt(mpfr_ptr y,mpfr_srcptr x)1524a238c70SJohn Marino mpfr_eint_asympt (mpfr_ptr y, mpfr_srcptr x)
1534a238c70SJohn Marino {
1544a238c70SJohn Marino   mpfr_prec_t p = MPFR_PREC(y);
1554a238c70SJohn Marino   mpfr_t invx, t, err;
1564a238c70SJohn Marino   unsigned long k;
1574a238c70SJohn Marino   mpfr_exp_t err_exp;
1584a238c70SJohn Marino 
1594a238c70SJohn Marino   mpfr_init2 (t, p);
1604a238c70SJohn Marino   mpfr_init2 (invx, p);
1614a238c70SJohn Marino   mpfr_init2 (err, 31); /* error in ulps on y */
1624a238c70SJohn Marino   mpfr_ui_div (invx, 1, x, MPFR_RNDN); /* invx = 1/x*(1+u) with |u|<=2^(1-p) */
1634a238c70SJohn Marino   mpfr_set_ui (t, 1, MPFR_RNDN); /* exact */
1644a238c70SJohn Marino   mpfr_set (y, t, MPFR_RNDN);
1654a238c70SJohn Marino   mpfr_set_ui (err, 0, MPFR_RNDN);
1664a238c70SJohn Marino   for (k = 1; MPFR_GET_EXP(t) + (mpfr_exp_t) p > MPFR_GET_EXP(y); k++)
1674a238c70SJohn Marino     {
1684a238c70SJohn Marino       mpfr_mul (t, t, invx, MPFR_RNDN); /* 2 more roundings */
1694a238c70SJohn Marino       mpfr_mul_ui (t, t, k, MPFR_RNDN); /* 1 more rounding: t = k!/x^k*(1+u)^e
1704a238c70SJohn Marino                                           with u=2^{-p} and |e| <= 3*k */
1714a238c70SJohn Marino       /* we use the fact that |(1+u)^n-1| <= 2*|n*u| for |n*u| <= 1, thus
1724a238c70SJohn Marino          the error on t is less than 6*k*2^{-p}*t <= 6*k*ulp(t) */
1734a238c70SJohn Marino       /* err is in terms of ulp(y): transform it in terms of ulp(t) */
1744a238c70SJohn Marino       mpfr_mul_2si (err, err, MPFR_GET_EXP(y) - MPFR_GET_EXP(t), MPFR_RNDU);
1754a238c70SJohn Marino       mpfr_add_ui (err, err, 6 * k, MPFR_RNDU);
1764a238c70SJohn Marino       /* transform back in terms of ulp(y) */
1774a238c70SJohn Marino       mpfr_div_2si (err, err, MPFR_GET_EXP(y) - MPFR_GET_EXP(t), MPFR_RNDU);
1784a238c70SJohn Marino       mpfr_add (y, y, t, MPFR_RNDN);
1794a238c70SJohn Marino     }
1804a238c70SJohn Marino   /* add the truncation error bounded by ulp(y): 1 ulp */
1814a238c70SJohn Marino   mpfr_mul (y, y, invx, MPFR_RNDN); /* err <= 2*err + 3/2 */
1824a238c70SJohn Marino   mpfr_exp (t, x, MPFR_RNDN); /* err(t) <= 1/2*ulp(t) */
1834a238c70SJohn Marino   mpfr_mul (y, y, t, MPFR_RNDN); /* again: err <= 2*err + 3/2 */
1844a238c70SJohn Marino   mpfr_mul_2ui (err, err, 2, MPFR_RNDU);
1854a238c70SJohn Marino   mpfr_add_ui (err, err, 8, MPFR_RNDU);
1864a238c70SJohn Marino   err_exp = MPFR_GET_EXP(err);
1874a238c70SJohn Marino   mpfr_clear (t);
1884a238c70SJohn Marino   mpfr_clear (invx);
1894a238c70SJohn Marino   mpfr_clear (err);
1904a238c70SJohn Marino   return err_exp;
1914a238c70SJohn Marino }
1924a238c70SJohn Marino 
1934a238c70SJohn Marino int
mpfr_eint(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd)1944a238c70SJohn Marino mpfr_eint (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd)
1954a238c70SJohn Marino {
1964a238c70SJohn Marino   int inex;
1974a238c70SJohn Marino   mpfr_t tmp, ump;
1984a238c70SJohn Marino   mpfr_exp_t err, te;
1994a238c70SJohn Marino   mpfr_prec_t prec;
2004a238c70SJohn Marino   MPFR_SAVE_EXPO_DECL (expo);
2014a238c70SJohn Marino   MPFR_ZIV_DECL (loop);
2024a238c70SJohn Marino 
2034a238c70SJohn Marino   MPFR_LOG_FUNC (
2044a238c70SJohn Marino     ("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd),
2054a238c70SJohn Marino     ("y[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (y), mpfr_log_prec, y, inex));
2064a238c70SJohn Marino 
2074a238c70SJohn Marino   if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
2084a238c70SJohn Marino     {
2094a238c70SJohn Marino       /* exp(NaN) = exp(-Inf) = NaN */
2104a238c70SJohn Marino       if (MPFR_IS_NAN (x) || (MPFR_IS_INF (x) && MPFR_IS_NEG(x)))
2114a238c70SJohn Marino         {
2124a238c70SJohn Marino           MPFR_SET_NAN (y);
2134a238c70SJohn Marino           MPFR_RET_NAN;
2144a238c70SJohn Marino         }
2154a238c70SJohn Marino       /* eint(+inf) = +inf */
2164a238c70SJohn Marino       else if (MPFR_IS_INF (x))
2174a238c70SJohn Marino         {
2184a238c70SJohn Marino           MPFR_SET_INF(y);
2194a238c70SJohn Marino           MPFR_SET_POS(y);
2204a238c70SJohn Marino           MPFR_RET(0);
2214a238c70SJohn Marino         }
2224a238c70SJohn Marino       else /* eint(+/-0) = -Inf */
2234a238c70SJohn Marino         {
2244a238c70SJohn Marino           MPFR_SET_INF(y);
2254a238c70SJohn Marino           MPFR_SET_NEG(y);
2264a238c70SJohn Marino           mpfr_set_divby0 ();
2274a238c70SJohn Marino           MPFR_RET(0);
2284a238c70SJohn Marino         }
2294a238c70SJohn Marino     }
2304a238c70SJohn Marino 
2314a238c70SJohn Marino   /* eint(x) = NaN for x < 0 */
2324a238c70SJohn Marino   if (MPFR_IS_NEG(x))
2334a238c70SJohn Marino     {
2344a238c70SJohn Marino       MPFR_SET_NAN (y);
2354a238c70SJohn Marino       MPFR_RET_NAN;
2364a238c70SJohn Marino     }
2374a238c70SJohn Marino 
2384a238c70SJohn Marino   MPFR_SAVE_EXPO_MARK (expo);
2394a238c70SJohn Marino 
2404a238c70SJohn Marino   /* Since eint(x) >= exp(x)/x, we have log2(eint(x)) >= (x-log(x))/log(2).
2414a238c70SJohn Marino      Let's compute k <= (x-log(x))/log(2) in a low precision. If k >= emax,
2424a238c70SJohn Marino      then log2(eint(x)) >= emax, and eint(x) >= 2^emax, i.e. it overflows. */
2434a238c70SJohn Marino   mpfr_init2 (tmp, 64);
2444a238c70SJohn Marino   mpfr_init2 (ump, 64);
2454a238c70SJohn Marino   mpfr_log (tmp, x, MPFR_RNDU);
2464a238c70SJohn Marino   mpfr_sub (ump, x, tmp, MPFR_RNDD);
2474a238c70SJohn Marino   mpfr_const_log2 (tmp, MPFR_RNDU);
2484a238c70SJohn Marino   mpfr_div (ump, ump, tmp, MPFR_RNDD);
2494a238c70SJohn Marino   /* FIXME: We really need mpfr_set_exp_t and mpfr_cmpfr_exp_t functions. */
2504a238c70SJohn Marino   MPFR_ASSERTN (MPFR_EMAX_MAX <= LONG_MAX);
2514a238c70SJohn Marino   if (mpfr_cmp_ui (ump, __gmpfr_emax) >= 0)
2524a238c70SJohn Marino     {
2534a238c70SJohn Marino       mpfr_clear (tmp);
2544a238c70SJohn Marino       mpfr_clear (ump);
2554a238c70SJohn Marino       MPFR_SAVE_EXPO_FREE (expo);
2564a238c70SJohn Marino       return mpfr_overflow (y, rnd, 1);
2574a238c70SJohn Marino     }
2584a238c70SJohn Marino 
2594a238c70SJohn Marino   /* Init stuff */
2604a238c70SJohn Marino   prec = MPFR_PREC (y) + 2 * MPFR_INT_CEIL_LOG2 (MPFR_PREC (y)) + 6;
2614a238c70SJohn Marino 
2624a238c70SJohn Marino   /* eint() has a root 0.37250741078136663446..., so if x is near,
2634a238c70SJohn Marino      already take more bits */
2644a238c70SJohn Marino   /* FIXME: do not use native floating-point here. */
2654a238c70SJohn Marino   if (MPFR_GET_EXP(x) == -1) /* 1/4 <= x < 1/2 */
2664a238c70SJohn Marino     {
2674a238c70SJohn Marino       double d;
2684a238c70SJohn Marino       d = mpfr_get_d (x, MPFR_RNDN) - 0.37250741078136663;
2694a238c70SJohn Marino       d = (d == 0.0) ? -53 : __gmpfr_ceil_log2 (d);
2704a238c70SJohn Marino       prec += -d;
2714a238c70SJohn Marino     }
2724a238c70SJohn Marino 
2734a238c70SJohn Marino   mpfr_set_prec (tmp, prec);
2744a238c70SJohn Marino   mpfr_set_prec (ump, prec);
2754a238c70SJohn Marino 
2764a238c70SJohn Marino   MPFR_ZIV_INIT (loop, prec);            /* Initialize the ZivLoop controler */
2774a238c70SJohn Marino   for (;;)                               /* Infinite loop */
2784a238c70SJohn Marino     {
2794a238c70SJohn Marino       /* We need that the smallest value of k!/x^k is smaller than 2^(-p).
2804a238c70SJohn Marino          The minimum is obtained for x=k, and it is smaller than e*sqrt(x)/e^x
2814a238c70SJohn Marino          for x>=1. */
2824a238c70SJohn Marino       if (MPFR_GET_EXP (x) > 0 && mpfr_cmp_d (x, ((double) prec +
2834a238c70SJohn Marino                             0.5 * (double) MPFR_GET_EXP (x)) * LOG2 + 1.0) > 0)
2844a238c70SJohn Marino         err = mpfr_eint_asympt (tmp, x);
2854a238c70SJohn Marino       else
2864a238c70SJohn Marino         {
2874a238c70SJohn Marino           err = mpfr_eint_aux (tmp, x); /* error <= 2^err ulp(tmp) */
2884a238c70SJohn Marino           te = MPFR_GET_EXP(tmp);
2894a238c70SJohn Marino           mpfr_const_euler (ump, MPFR_RNDN); /* 0.577 -> EXP(ump)=0 */
2904a238c70SJohn Marino           mpfr_add (tmp, tmp, ump, MPFR_RNDN);
2914a238c70SJohn Marino           /* error <= 1/2 + 1/2*2^(EXP(ump)-EXP(tmp)) + 2^(te-EXP(tmp)+err)
2924a238c70SJohn Marino              <= 1/2 + 2^(MAX(EXP(ump), te+err+1) - EXP(tmp))
2934a238c70SJohn Marino              <= 2^(MAX(0, 1 + MAX(EXP(ump), te+err+1) - EXP(tmp))) */
2944a238c70SJohn Marino           err = MAX(1, te + err + 2) - MPFR_GET_EXP(tmp);
2954a238c70SJohn Marino           err = MAX(0, err);
2964a238c70SJohn Marino           te = MPFR_GET_EXP(tmp);
2974a238c70SJohn Marino           mpfr_log (ump, x, MPFR_RNDN);
2984a238c70SJohn Marino           mpfr_add (tmp, tmp, ump, MPFR_RNDN);
2994a238c70SJohn Marino           /* same formula as above, except now EXP(ump) is not 0 */
3004a238c70SJohn Marino           err += te + 1;
3014a238c70SJohn Marino           if (MPFR_LIKELY (!MPFR_IS_ZERO (ump)))
3024a238c70SJohn Marino             err = MAX (MPFR_GET_EXP (ump), err);
3034a238c70SJohn Marino           err = MAX(0, err - MPFR_GET_EXP (tmp));
3044a238c70SJohn Marino         }
3054a238c70SJohn Marino       if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp, prec - err, MPFR_PREC (y), rnd)))
3064a238c70SJohn Marino         break;
3074a238c70SJohn Marino       MPFR_ZIV_NEXT (loop, prec);        /* Increase used precision */
3084a238c70SJohn Marino       mpfr_set_prec (tmp, prec);
3094a238c70SJohn Marino       mpfr_set_prec (ump, prec);
3104a238c70SJohn Marino     }
3114a238c70SJohn Marino   MPFR_ZIV_FREE (loop);                  /* Free the ZivLoop Controler */
3124a238c70SJohn Marino 
3134a238c70SJohn Marino   inex = mpfr_set (y, tmp, rnd);    /* Set y to the computed value */
3144a238c70SJohn Marino   mpfr_clear (tmp);
3154a238c70SJohn Marino   mpfr_clear (ump);
3164a238c70SJohn Marino 
3174a238c70SJohn Marino   MPFR_SAVE_EXPO_FREE (expo);
3184a238c70SJohn Marino   return mpfr_check_range (y, inex, rnd);
3194a238c70SJohn Marino }
320