xref: /dflybsd-src/contrib/mpfr/src/li2.c (revision 2786097444a0124b5d33763854de247e230c6629)
14a238c70SJohn Marino /* mpfr_li2 -- Dilogarithm.
24a238c70SJohn Marino 
3*ab6d115fSJohn Marino Copyright 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 /* Compute the alternating series
274a238c70SJohn Marino    s = S(z) = \sum_{k=0}^infty B_{2k} (z))^{2k+1} / (2k+1)!
284a238c70SJohn Marino    with 0 < z <= log(2) to the precision of s rounded in the direction
294a238c70SJohn Marino    rnd_mode.
304a238c70SJohn Marino    Return the maximum index of the truncature which is useful
314a238c70SJohn Marino    for determinating the relative error.
324a238c70SJohn Marino */
334a238c70SJohn Marino static int
li2_series(mpfr_t sum,mpfr_srcptr z,mpfr_rnd_t rnd_mode)344a238c70SJohn Marino li2_series (mpfr_t sum, mpfr_srcptr z, mpfr_rnd_t rnd_mode)
354a238c70SJohn Marino {
364a238c70SJohn Marino   int i, Bm, Bmax;
374a238c70SJohn Marino   mpfr_t s, u, v, w;
384a238c70SJohn Marino   mpfr_prec_t sump, p;
394a238c70SJohn Marino   mpfr_exp_t se, err;
404a238c70SJohn Marino   mpz_t *B;
414a238c70SJohn Marino   MPFR_ZIV_DECL (loop);
424a238c70SJohn Marino 
434a238c70SJohn Marino   /* The series converges for |z| < 2 pi, but in mpfr_li2 the argument is
444a238c70SJohn Marino      reduced so that 0 < z <= log(2). Here is additionnal check that z is
454a238c70SJohn Marino      (nearly) correct */
464a238c70SJohn Marino   MPFR_ASSERTD (MPFR_IS_STRICTPOS (z));
474a238c70SJohn Marino   MPFR_ASSERTD (mpfr_cmp_d (z, 0.6953125) <= 0);
484a238c70SJohn Marino 
494a238c70SJohn Marino   sump = MPFR_PREC (sum);       /* target precision */
504a238c70SJohn Marino   p = sump + MPFR_INT_CEIL_LOG2 (sump) + 4;     /* the working precision */
514a238c70SJohn Marino   mpfr_init2 (s, p);
524a238c70SJohn Marino   mpfr_init2 (u, p);
534a238c70SJohn Marino   mpfr_init2 (v, p);
544a238c70SJohn Marino   mpfr_init2 (w, p);
554a238c70SJohn Marino 
564a238c70SJohn Marino   B = mpfr_bernoulli_internal ((mpz_t *) 0, 0);
574a238c70SJohn Marino   Bm = Bmax = 1;
584a238c70SJohn Marino 
594a238c70SJohn Marino   MPFR_ZIV_INIT (loop, p);
604a238c70SJohn Marino   for (;;)
614a238c70SJohn Marino     {
624a238c70SJohn Marino       mpfr_sqr (u, z, MPFR_RNDU);
634a238c70SJohn Marino       mpfr_set (v, z, MPFR_RNDU);
644a238c70SJohn Marino       mpfr_set (s, z, MPFR_RNDU);
654a238c70SJohn Marino       se = MPFR_GET_EXP (s);
664a238c70SJohn Marino       err = 0;
674a238c70SJohn Marino 
684a238c70SJohn Marino       for (i = 1;; i++)
694a238c70SJohn Marino         {
704a238c70SJohn Marino           if (i >= Bmax)
714a238c70SJohn Marino             B = mpfr_bernoulli_internal (B, Bmax++); /* B_2i*(2i+1)!, exact */
724a238c70SJohn Marino 
734a238c70SJohn Marino           mpfr_mul (v, u, v, MPFR_RNDU);
744a238c70SJohn Marino           mpfr_div_ui (v, v, 2 * i, MPFR_RNDU);
754a238c70SJohn Marino           mpfr_div_ui (v, v, 2 * i, MPFR_RNDU);
764a238c70SJohn Marino           mpfr_div_ui (v, v, 2 * i + 1, MPFR_RNDU);
774a238c70SJohn Marino           mpfr_div_ui (v, v, 2 * i + 1, MPFR_RNDU);
784a238c70SJohn Marino           /* here, v_2i = v_{2i-2} / (2i * (2i+1))^2 */
794a238c70SJohn Marino 
804a238c70SJohn Marino           mpfr_mul_z (w, v, B[i], MPFR_RNDN);
814a238c70SJohn Marino           /* here, w_2i = v_2i * B_2i * (2i+1)! with
824a238c70SJohn Marino              error(w_2i) < 2^(5 * i + 8) ulp(w_2i) (see algorithms.tex) */
834a238c70SJohn Marino 
844a238c70SJohn Marino           mpfr_add (s, s, w, MPFR_RNDN);
854a238c70SJohn Marino 
864a238c70SJohn Marino           err = MAX (err + se, 5 * i + 8 + MPFR_GET_EXP (w))
874a238c70SJohn Marino             - MPFR_GET_EXP (s);
884a238c70SJohn Marino           err = 2 + MAX (-1, err);
894a238c70SJohn Marino           se = MPFR_GET_EXP (s);
904a238c70SJohn Marino           if (MPFR_GET_EXP (w) <= se - (mpfr_exp_t) p)
914a238c70SJohn Marino             break;
924a238c70SJohn Marino         }
934a238c70SJohn Marino 
944a238c70SJohn Marino       /* the previous value of err is the rounding error,
954a238c70SJohn Marino          the truncation error is less than EXP(z) - 6 * i - 5
964a238c70SJohn Marino          (see algorithms.tex) */
974a238c70SJohn Marino       err = MAX (err, MPFR_GET_EXP (z) - 6 * i - 5) + 1;
984a238c70SJohn Marino       if (MPFR_CAN_ROUND (s, (mpfr_exp_t) p - err, sump, rnd_mode))
994a238c70SJohn Marino         break;
1004a238c70SJohn Marino 
1014a238c70SJohn Marino       MPFR_ZIV_NEXT (loop, p);
1024a238c70SJohn Marino       mpfr_set_prec (s, p);
1034a238c70SJohn Marino       mpfr_set_prec (u, p);
1044a238c70SJohn Marino       mpfr_set_prec (v, p);
1054a238c70SJohn Marino       mpfr_set_prec (w, p);
1064a238c70SJohn Marino     }
1074a238c70SJohn Marino   MPFR_ZIV_FREE (loop);
1084a238c70SJohn Marino   mpfr_set (sum, s, rnd_mode);
1094a238c70SJohn Marino 
1104a238c70SJohn Marino   Bm = Bmax;
1114a238c70SJohn Marino   while (Bm--)
1124a238c70SJohn Marino     mpz_clear (B[Bm]);
1134a238c70SJohn Marino   (*__gmp_free_func) (B, Bmax * sizeof (mpz_t));
1144a238c70SJohn Marino   mpfr_clears (s, u, v, w, (mpfr_ptr) 0);
1154a238c70SJohn Marino 
1164a238c70SJohn Marino   /* Let K be the returned value.
1174a238c70SJohn Marino      1. As we compute an alternating series, the truncation error has the same
1184a238c70SJohn Marino      sign as the next term w_{K+2} which is positive iff K%4 == 0.
1194a238c70SJohn Marino      2. Assume that error(z) <= (1+t) z', where z' is the actual value, then
1204a238c70SJohn Marino      error(s) <= 2 * (K+1) * t (see algorithms.tex).
1214a238c70SJohn Marino    */
1224a238c70SJohn Marino   return 2 * i;
1234a238c70SJohn Marino }
1244a238c70SJohn Marino 
1254a238c70SJohn Marino /* try asymptotic expansion when x is large and positive:
1264a238c70SJohn Marino    Li2(x) = -log(x)^2/2 + Pi^2/3 - 1/x + O(1/x^2).
1274a238c70SJohn Marino    More precisely for x >= 2 we have for g(x) = -log(x)^2/2 + Pi^2/3:
1284a238c70SJohn Marino    -2 <= x * (Li2(x) - g(x)) <= -1
1294a238c70SJohn Marino    thus |Li2(x) - g(x)| <= 2/x.
1304a238c70SJohn Marino    Assumes x >= 38, which ensures log(x)^2/2 >= 2*Pi^2/3, and g(x) <= -3.3.
1314a238c70SJohn Marino    Return 0 if asymptotic expansion failed (unable to round), otherwise
1324a238c70SJohn Marino    returns correct ternary value.
1334a238c70SJohn Marino */
1344a238c70SJohn Marino static int
mpfr_li2_asympt_pos(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd_mode)1354a238c70SJohn Marino mpfr_li2_asympt_pos (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
1364a238c70SJohn Marino {
1374a238c70SJohn Marino   mpfr_t g, h;
1384a238c70SJohn Marino   mpfr_prec_t w = MPFR_PREC (y) + 20;
1394a238c70SJohn Marino   int inex = 0;
1404a238c70SJohn Marino 
1414a238c70SJohn Marino   MPFR_ASSERTN (mpfr_cmp_ui (x, 38) >= 0);
1424a238c70SJohn Marino 
1434a238c70SJohn Marino   mpfr_init2 (g, w);
1444a238c70SJohn Marino   mpfr_init2 (h, w);
1454a238c70SJohn Marino   mpfr_log (g, x, MPFR_RNDN);    /* rel. error <= |(1 + theta) - 1| */
1464a238c70SJohn Marino   mpfr_sqr (g, g, MPFR_RNDN);    /* rel. error <= |(1 + theta)^3 - 1| <= 2^(2-w) */
1474a238c70SJohn Marino   mpfr_div_2ui (g, g, 1, MPFR_RNDN);     /* rel. error <= 2^(2-w) */
1484a238c70SJohn Marino   mpfr_const_pi (h, MPFR_RNDN);  /* error <= 2^(1-w) */
1494a238c70SJohn Marino   mpfr_sqr (h, h, MPFR_RNDN);    /* rel. error <= 2^(2-w) */
1504a238c70SJohn Marino   mpfr_div_ui (h, h, 3, MPFR_RNDN);      /* rel. error <= |(1 + theta)^4 - 1|
1514a238c70SJohn Marino                                            <= 5 * 2^(-w) */
1524a238c70SJohn Marino   /* since x is chosen such that log(x)^2/2 >= 2 * (Pi^2/3), we should have
1534a238c70SJohn Marino      g >= 2*h, thus |g-h| >= |h|, and the relative error on g is at most
1544a238c70SJohn Marino      multiplied by 2 in the difference, and that by h is unchanged. */
1554a238c70SJohn Marino   MPFR_ASSERTN (MPFR_EXP (g) > MPFR_EXP (h));
1564a238c70SJohn Marino   mpfr_sub (g, h, g, MPFR_RNDN); /* err <= ulp(g)/2 + g*2^(3-w) + g*5*2^(-w)
1574a238c70SJohn Marino                                    <= ulp(g) * (1/2 + 8 + 5) < 14 ulp(g).
1584a238c70SJohn Marino 
1594a238c70SJohn Marino                                    If in addition 2/x <= 2 ulp(g), i.e.,
1604a238c70SJohn Marino                                    1/x <= ulp(g), then the total error is
1614a238c70SJohn Marino                                    bounded by 16 ulp(g). */
1624a238c70SJohn Marino   if ((MPFR_EXP (x) >= (mpfr_exp_t) w - MPFR_EXP (g)) &&
1634a238c70SJohn Marino       MPFR_CAN_ROUND (g, w - 4, MPFR_PREC (y), rnd_mode))
1644a238c70SJohn Marino     inex = mpfr_set (y, g, rnd_mode);
1654a238c70SJohn Marino 
1664a238c70SJohn Marino   mpfr_clear (g);
1674a238c70SJohn Marino   mpfr_clear (h);
1684a238c70SJohn Marino 
1694a238c70SJohn Marino   return inex;
1704a238c70SJohn Marino }
1714a238c70SJohn Marino 
1724a238c70SJohn Marino /* try asymptotic expansion when x is large and negative:
1734a238c70SJohn Marino    Li2(x) = -log(-x)^2/2 - Pi^2/6 - 1/x + O(1/x^2).
1744a238c70SJohn Marino    More precisely for x <= -2 we have for g(x) = -log(-x)^2/2 - Pi^2/6:
1754a238c70SJohn Marino    |Li2(x) - g(x)| <= 1/|x|.
1764a238c70SJohn Marino    Assumes x <= -7, which ensures |log(-x)^2/2| >= Pi^2/6, and g(x) <= -3.5.
1774a238c70SJohn Marino    Return 0 if asymptotic expansion failed (unable to round), otherwise
1784a238c70SJohn Marino    returns correct ternary value.
1794a238c70SJohn Marino */
1804a238c70SJohn Marino static int
mpfr_li2_asympt_neg(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd_mode)1814a238c70SJohn Marino mpfr_li2_asympt_neg (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
1824a238c70SJohn Marino {
1834a238c70SJohn Marino   mpfr_t g, h;
1844a238c70SJohn Marino   mpfr_prec_t w = MPFR_PREC (y) + 20;
1854a238c70SJohn Marino   int inex = 0;
1864a238c70SJohn Marino 
1874a238c70SJohn Marino   MPFR_ASSERTN (mpfr_cmp_si (x, -7) <= 0);
1884a238c70SJohn Marino 
1894a238c70SJohn Marino   mpfr_init2 (g, w);
1904a238c70SJohn Marino   mpfr_init2 (h, w);
1914a238c70SJohn Marino   mpfr_neg (g, x, MPFR_RNDN);
1924a238c70SJohn Marino   mpfr_log (g, g, MPFR_RNDN);    /* rel. error <= |(1 + theta) - 1| */
1934a238c70SJohn Marino   mpfr_sqr (g, g, MPFR_RNDN);    /* rel. error <= |(1 + theta)^3 - 1| <= 2^(2-w) */
1944a238c70SJohn Marino   mpfr_div_2ui (g, g, 1, MPFR_RNDN);     /* rel. error <= 2^(2-w) */
1954a238c70SJohn Marino   mpfr_const_pi (h, MPFR_RNDN);  /* error <= 2^(1-w) */
1964a238c70SJohn Marino   mpfr_sqr (h, h, MPFR_RNDN);    /* rel. error <= 2^(2-w) */
1974a238c70SJohn Marino   mpfr_div_ui (h, h, 6, MPFR_RNDN);      /* rel. error <= |(1 + theta)^4 - 1|
1984a238c70SJohn Marino                                            <= 5 * 2^(-w) */
1994a238c70SJohn Marino   MPFR_ASSERTN (MPFR_EXP (g) >= MPFR_EXP (h));
2004a238c70SJohn Marino   mpfr_add (g, g, h, MPFR_RNDN); /* err <= ulp(g)/2 + g*2^(2-w) + g*5*2^(-w)
2014a238c70SJohn Marino                                    <= ulp(g) * (1/2 + 4 + 5) < 10 ulp(g).
2024a238c70SJohn Marino 
2034a238c70SJohn Marino                                    If in addition |1/x| <= 4 ulp(g), then the
2044a238c70SJohn Marino                                    total error is bounded by 16 ulp(g). */
2054a238c70SJohn Marino   if ((MPFR_EXP (x) >= (mpfr_exp_t) (w - 2) - MPFR_EXP (g)) &&
2064a238c70SJohn Marino       MPFR_CAN_ROUND (g, w - 4, MPFR_PREC (y), rnd_mode))
2074a238c70SJohn Marino     inex = mpfr_neg (y, g, rnd_mode);
2084a238c70SJohn Marino 
2094a238c70SJohn Marino   mpfr_clear (g);
2104a238c70SJohn Marino   mpfr_clear (h);
2114a238c70SJohn Marino 
2124a238c70SJohn Marino   return inex;
2134a238c70SJohn Marino }
2144a238c70SJohn Marino 
2154a238c70SJohn Marino /* Compute the real part of the dilogarithm defined by
2164a238c70SJohn Marino    Li2(x) = -\Int_{t=0}^x log(1-t)/t dt */
2174a238c70SJohn Marino int
mpfr_li2(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd_mode)2184a238c70SJohn Marino mpfr_li2 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
2194a238c70SJohn Marino {
2204a238c70SJohn Marino   int inexact;
2214a238c70SJohn Marino   mpfr_exp_t err;
2224a238c70SJohn Marino   mpfr_prec_t yp, m;
2234a238c70SJohn Marino   MPFR_ZIV_DECL (loop);
2244a238c70SJohn Marino   MPFR_SAVE_EXPO_DECL (expo);
2254a238c70SJohn Marino 
2264a238c70SJohn Marino   MPFR_LOG_FUNC
2274a238c70SJohn Marino     (("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode),
2284a238c70SJohn Marino      ("y[%Pu]=%.*Rg inexact=%d",
2294a238c70SJohn Marino       mpfr_get_prec (y), mpfr_log_prec, y, inexact));
2304a238c70SJohn Marino 
2314a238c70SJohn Marino   if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
2324a238c70SJohn Marino     {
2334a238c70SJohn Marino       if (MPFR_IS_NAN (x))
2344a238c70SJohn Marino         {
2354a238c70SJohn Marino           MPFR_SET_NAN (y);
2364a238c70SJohn Marino           MPFR_RET_NAN;
2374a238c70SJohn Marino         }
2384a238c70SJohn Marino       else if (MPFR_IS_INF (x))
2394a238c70SJohn Marino         {
2404a238c70SJohn Marino           MPFR_SET_NEG (y);
2414a238c70SJohn Marino           MPFR_SET_INF (y);
2424a238c70SJohn Marino           MPFR_RET (0);
2434a238c70SJohn Marino         }
2444a238c70SJohn Marino       else                      /* x is zero */
2454a238c70SJohn Marino         {
2464a238c70SJohn Marino           MPFR_ASSERTD (MPFR_IS_ZERO (x));
2474a238c70SJohn Marino           MPFR_SET_SAME_SIGN (y, x);
2484a238c70SJohn Marino           MPFR_SET_ZERO (y);
2494a238c70SJohn Marino           MPFR_RET (0);
2504a238c70SJohn Marino         }
2514a238c70SJohn Marino     }
2524a238c70SJohn Marino 
2534a238c70SJohn Marino   /* Li2(x) = x + x^2/4 + x^3/9 + ..., more precisely for 0 < x <= 1/2
2544a238c70SJohn Marino      we have |Li2(x) - x| < x^2/2 <= 2^(2EXP(x)-1) and for -1/2 <= x < 0
2554a238c70SJohn Marino      we have |Li2(x) - x| < x^2/4 <= 2^(2EXP(x)-2) */
2564a238c70SJohn Marino   if (MPFR_IS_POS (x))
2574a238c70SJohn Marino     MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, -MPFR_GET_EXP (x), 1, 1, rnd_mode,
2584a238c70SJohn Marino                                       {});
2594a238c70SJohn Marino   else
2604a238c70SJohn Marino     MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, -MPFR_GET_EXP (x), 2, 0, rnd_mode,
2614a238c70SJohn Marino                                       {});
2624a238c70SJohn Marino 
2634a238c70SJohn Marino   MPFR_SAVE_EXPO_MARK (expo);
2644a238c70SJohn Marino   yp = MPFR_PREC (y);
2654a238c70SJohn Marino   m = yp + MPFR_INT_CEIL_LOG2 (yp) + 13;
2664a238c70SJohn Marino 
2674a238c70SJohn Marino   if (MPFR_LIKELY ((mpfr_cmp_ui (x, 0) > 0) && (mpfr_cmp_d (x, 0.5) <= 0)))
2684a238c70SJohn Marino     /* 0 < x <= 1/2: Li2(x) = S(-log(1-x))-log^2(1-x)/4 */
2694a238c70SJohn Marino     {
2704a238c70SJohn Marino       mpfr_t s, u;
2714a238c70SJohn Marino       mpfr_exp_t expo_l;
2724a238c70SJohn Marino       int k;
2734a238c70SJohn Marino 
2744a238c70SJohn Marino       mpfr_init2 (u, m);
2754a238c70SJohn Marino       mpfr_init2 (s, m);
2764a238c70SJohn Marino 
2774a238c70SJohn Marino       MPFR_ZIV_INIT (loop, m);
2784a238c70SJohn Marino       for (;;)
2794a238c70SJohn Marino         {
2804a238c70SJohn Marino           mpfr_ui_sub (u, 1, x, MPFR_RNDN);
2814a238c70SJohn Marino           mpfr_log (u, u, MPFR_RNDU);
2824a238c70SJohn Marino           if (MPFR_IS_ZERO(u))
2834a238c70SJohn Marino             goto next_m;
2844a238c70SJohn Marino           mpfr_neg (u, u, MPFR_RNDN);    /* u = -log(1-x) */
2854a238c70SJohn Marino           expo_l = MPFR_GET_EXP (u);
2864a238c70SJohn Marino           k = li2_series (s, u, MPFR_RNDU);
2874a238c70SJohn Marino           err = 1 + MPFR_INT_CEIL_LOG2 (k + 1);
2884a238c70SJohn Marino 
2894a238c70SJohn Marino           mpfr_sqr (u, u, MPFR_RNDU);
2904a238c70SJohn Marino           mpfr_div_2ui (u, u, 2, MPFR_RNDU);     /* u = log^2(1-x) / 4 */
2914a238c70SJohn Marino           mpfr_sub (s, s, u, MPFR_RNDN);
2924a238c70SJohn Marino 
2934a238c70SJohn Marino           /* error(s) <= (0.5 + 2^(d-EXP(s))
2944a238c70SJohn Marino              + 2^(3 + MAX(1, - expo_l) - EXP(s))) ulp(s) */
2954a238c70SJohn Marino           err = MAX (err, MAX (1, - expo_l) - 1) - MPFR_GET_EXP (s);
2964a238c70SJohn Marino           err = 2 + MAX (-1, err);
2974a238c70SJohn Marino           if (MPFR_CAN_ROUND (s, (mpfr_exp_t) m - err, yp, rnd_mode))
2984a238c70SJohn Marino             break;
2994a238c70SJohn Marino 
3004a238c70SJohn Marino         next_m:
3014a238c70SJohn Marino           MPFR_ZIV_NEXT (loop, m);
3024a238c70SJohn Marino           mpfr_set_prec (u, m);
3034a238c70SJohn Marino           mpfr_set_prec (s, m);
3044a238c70SJohn Marino         }
3054a238c70SJohn Marino       MPFR_ZIV_FREE (loop);
3064a238c70SJohn Marino       inexact = mpfr_set (y, s, rnd_mode);
3074a238c70SJohn Marino 
3084a238c70SJohn Marino       mpfr_clear (u);
3094a238c70SJohn Marino       mpfr_clear (s);
3104a238c70SJohn Marino       MPFR_SAVE_EXPO_FREE (expo);
3114a238c70SJohn Marino       return mpfr_check_range (y, inexact, rnd_mode);
3124a238c70SJohn Marino     }
3134a238c70SJohn Marino   else if (!mpfr_cmp_ui (x, 1))
3144a238c70SJohn Marino     /* Li2(1)= pi^2 / 6 */
3154a238c70SJohn Marino     {
3164a238c70SJohn Marino       mpfr_t u;
3174a238c70SJohn Marino       mpfr_init2 (u, m);
3184a238c70SJohn Marino 
3194a238c70SJohn Marino       MPFR_ZIV_INIT (loop, m);
3204a238c70SJohn Marino       for (;;)
3214a238c70SJohn Marino         {
3224a238c70SJohn Marino           mpfr_const_pi (u, MPFR_RNDU);
3234a238c70SJohn Marino           mpfr_sqr (u, u, MPFR_RNDN);
3244a238c70SJohn Marino           mpfr_div_ui (u, u, 6, MPFR_RNDN);
3254a238c70SJohn Marino 
3264a238c70SJohn Marino           err = m - 4;          /* error(u) <= 19/2 ulp(u) */
3274a238c70SJohn Marino           if (MPFR_CAN_ROUND (u, err, yp, rnd_mode))
3284a238c70SJohn Marino             break;
3294a238c70SJohn Marino 
3304a238c70SJohn Marino           MPFR_ZIV_NEXT (loop, m);
3314a238c70SJohn Marino           mpfr_set_prec (u, m);
3324a238c70SJohn Marino         }
3334a238c70SJohn Marino       MPFR_ZIV_FREE (loop);
3344a238c70SJohn Marino       inexact = mpfr_set (y, u, rnd_mode);
3354a238c70SJohn Marino 
3364a238c70SJohn Marino       mpfr_clear (u);
3374a238c70SJohn Marino       MPFR_SAVE_EXPO_FREE (expo);
3384a238c70SJohn Marino       return mpfr_check_range (y, inexact, rnd_mode);
3394a238c70SJohn Marino     }
3404a238c70SJohn Marino   else if (mpfr_cmp_ui (x, 2) >= 0)
3414a238c70SJohn Marino     /* x >= 2: Li2(x) = -S(-log(1-1/x))-log^2(x)/2+log^2(1-1/x)/4+pi^2/3 */
3424a238c70SJohn Marino     {
3434a238c70SJohn Marino       int k;
3444a238c70SJohn Marino       mpfr_exp_t expo_l;
3454a238c70SJohn Marino       mpfr_t s, u, xx;
3464a238c70SJohn Marino 
3474a238c70SJohn Marino       if (mpfr_cmp_ui (x, 38) >= 0)
3484a238c70SJohn Marino         {
3494a238c70SJohn Marino           inexact = mpfr_li2_asympt_pos (y, x, rnd_mode);
3504a238c70SJohn Marino           if (inexact != 0)
3514a238c70SJohn Marino             goto end_of_case_gt2;
3524a238c70SJohn Marino         }
3534a238c70SJohn Marino 
3544a238c70SJohn Marino       mpfr_init2 (u, m);
3554a238c70SJohn Marino       mpfr_init2 (s, m);
3564a238c70SJohn Marino       mpfr_init2 (xx, m);
3574a238c70SJohn Marino 
3584a238c70SJohn Marino       MPFR_ZIV_INIT (loop, m);
3594a238c70SJohn Marino       for (;;)
3604a238c70SJohn Marino         {
3614a238c70SJohn Marino           mpfr_ui_div (xx, 1, x, MPFR_RNDN);
3624a238c70SJohn Marino           mpfr_neg (xx, xx, MPFR_RNDN);
3634a238c70SJohn Marino           mpfr_log1p (u, xx, MPFR_RNDD);
3644a238c70SJohn Marino           mpfr_neg (u, u, MPFR_RNDU);    /* u = -log(1-1/x) */
3654a238c70SJohn Marino           expo_l = MPFR_GET_EXP (u);
3664a238c70SJohn Marino           k = li2_series (s, u, MPFR_RNDN);
3674a238c70SJohn Marino           mpfr_neg (s, s, MPFR_RNDN);
3684a238c70SJohn Marino           err = MPFR_INT_CEIL_LOG2 (k + 1) + 1; /* error(s) <= 2^err ulp(s) */
3694a238c70SJohn Marino 
3704a238c70SJohn Marino           mpfr_sqr (u, u, MPFR_RNDN);
3714a238c70SJohn Marino           mpfr_div_2ui (u, u, 2, MPFR_RNDN);     /* u= log^2(1-1/x)/4 */
3724a238c70SJohn Marino           mpfr_add (s, s, u, MPFR_RNDN);
3734a238c70SJohn Marino           err =
3744a238c70SJohn Marino             MAX (err,
3754a238c70SJohn Marino                  3 + MAX (1, -expo_l) + MPFR_GET_EXP (u)) - MPFR_GET_EXP (s);
3764a238c70SJohn Marino           err = 2 + MAX (-1, err);      /* error(s) <= 2^err ulp(s) */
3774a238c70SJohn Marino           err += MPFR_GET_EXP (s);
3784a238c70SJohn Marino 
3794a238c70SJohn Marino           mpfr_log (u, x, MPFR_RNDU);
3804a238c70SJohn Marino           mpfr_sqr (u, u, MPFR_RNDN);
3814a238c70SJohn Marino           mpfr_div_2ui (u, u, 1, MPFR_RNDN);     /* u = log^2(x)/2 */
3824a238c70SJohn Marino           mpfr_sub (s, s, u, MPFR_RNDN);
3834a238c70SJohn Marino           err = MAX (err, 3 + MPFR_GET_EXP (u)) - MPFR_GET_EXP (s);
3844a238c70SJohn Marino           err = 2 + MAX (-1, err);      /* error(s) <= 2^err ulp(s) */
3854a238c70SJohn Marino           err += MPFR_GET_EXP (s);
3864a238c70SJohn Marino 
3874a238c70SJohn Marino           mpfr_const_pi (u, MPFR_RNDU);
3884a238c70SJohn Marino           mpfr_sqr (u, u, MPFR_RNDN);
3894a238c70SJohn Marino           mpfr_div_ui (u, u, 3, MPFR_RNDN);      /* u = pi^2/3 */
3904a238c70SJohn Marino           mpfr_add (s, s, u, MPFR_RNDN);
3914a238c70SJohn Marino           err = MAX (err, 2) - MPFR_GET_EXP (s);
3924a238c70SJohn Marino           err = 2 + MAX (-1, err);      /* error(s) <= 2^err ulp(s) */
3934a238c70SJohn Marino           if (MPFR_CAN_ROUND (s, (mpfr_exp_t) m - err, yp, rnd_mode))
3944a238c70SJohn Marino             break;
3954a238c70SJohn Marino 
3964a238c70SJohn Marino           MPFR_ZIV_NEXT (loop, m);
3974a238c70SJohn Marino           mpfr_set_prec (u, m);
3984a238c70SJohn Marino           mpfr_set_prec (s, m);
3994a238c70SJohn Marino           mpfr_set_prec (xx, m);
4004a238c70SJohn Marino         }
4014a238c70SJohn Marino       MPFR_ZIV_FREE (loop);
4024a238c70SJohn Marino       inexact = mpfr_set (y, s, rnd_mode);
4034a238c70SJohn Marino       mpfr_clears (s, u, xx, (mpfr_ptr) 0);
4044a238c70SJohn Marino 
4054a238c70SJohn Marino     end_of_case_gt2:
4064a238c70SJohn Marino       MPFR_SAVE_EXPO_FREE (expo);
4074a238c70SJohn Marino       return mpfr_check_range (y, inexact, rnd_mode);
4084a238c70SJohn Marino     }
4094a238c70SJohn Marino   else if (mpfr_cmp_ui (x, 1) > 0)
4104a238c70SJohn Marino     /* 2 > x > 1: Li2(x) = S(log(x))+log^2(x)/4-log(x)log(x-1)+pi^2/6 */
4114a238c70SJohn Marino     {
4124a238c70SJohn Marino       int k;
4134a238c70SJohn Marino       mpfr_exp_t e1, e2;
4144a238c70SJohn Marino       mpfr_t s, u, v, xx;
4154a238c70SJohn Marino       mpfr_init2 (s, m);
4164a238c70SJohn Marino       mpfr_init2 (u, m);
4174a238c70SJohn Marino       mpfr_init2 (v, m);
4184a238c70SJohn Marino       mpfr_init2 (xx, m);
4194a238c70SJohn Marino 
4204a238c70SJohn Marino       MPFR_ZIV_INIT (loop, m);
4214a238c70SJohn Marino       for (;;)
4224a238c70SJohn Marino         {
4234a238c70SJohn Marino           mpfr_log (v, x, MPFR_RNDU);
4244a238c70SJohn Marino           k = li2_series (s, v, MPFR_RNDN);
4254a238c70SJohn Marino           e1 = MPFR_GET_EXP (s);
4264a238c70SJohn Marino 
4274a238c70SJohn Marino           mpfr_sqr (u, v, MPFR_RNDN);
4284a238c70SJohn Marino           mpfr_div_2ui (u, u, 2, MPFR_RNDN);     /* u = log^2(x)/4 */
4294a238c70SJohn Marino           mpfr_add (s, s, u, MPFR_RNDN);
4304a238c70SJohn Marino 
4314a238c70SJohn Marino           mpfr_sub_ui (xx, x, 1, MPFR_RNDN);
4324a238c70SJohn Marino           mpfr_log (u, xx, MPFR_RNDU);
4334a238c70SJohn Marino           e2 = MPFR_GET_EXP (u);
4344a238c70SJohn Marino           mpfr_mul (u, v, u, MPFR_RNDN); /* u = log(x) * log(x-1) */
4354a238c70SJohn Marino           mpfr_sub (s, s, u, MPFR_RNDN);
4364a238c70SJohn Marino 
4374a238c70SJohn Marino           mpfr_const_pi (u, MPFR_RNDU);
4384a238c70SJohn Marino           mpfr_sqr (u, u, MPFR_RNDN);
4394a238c70SJohn Marino           mpfr_div_ui (u, u, 6, MPFR_RNDN);      /* u = pi^2/6 */
4404a238c70SJohn Marino           mpfr_add (s, s, u, MPFR_RNDN);
4414a238c70SJohn Marino           /* error(s) <= (31 + (k+1) * 2^(1-e1) + 2^(1-e2)) ulp(s)
4424a238c70SJohn Marino              see algorithms.tex */
4434a238c70SJohn Marino           err = MAX (MPFR_INT_CEIL_LOG2 (k + 1) + 1 - e1, 1 - e2);
4444a238c70SJohn Marino           err = 2 + MAX (5, err);
4454a238c70SJohn Marino           if (MPFR_CAN_ROUND (s, (mpfr_exp_t) m - err, yp, rnd_mode))
4464a238c70SJohn Marino             break;
4474a238c70SJohn Marino 
4484a238c70SJohn Marino           MPFR_ZIV_NEXT (loop, m);
4494a238c70SJohn Marino           mpfr_set_prec (s, m);
4504a238c70SJohn Marino           mpfr_set_prec (u, m);
4514a238c70SJohn Marino           mpfr_set_prec (v, m);
4524a238c70SJohn Marino           mpfr_set_prec (xx, m);
4534a238c70SJohn Marino         }
4544a238c70SJohn Marino       MPFR_ZIV_FREE (loop);
4554a238c70SJohn Marino       inexact = mpfr_set (y, s, rnd_mode);
4564a238c70SJohn Marino 
4574a238c70SJohn Marino       mpfr_clears (s, u, v, xx, (mpfr_ptr) 0);
4584a238c70SJohn Marino       MPFR_SAVE_EXPO_FREE (expo);
4594a238c70SJohn Marino       return mpfr_check_range (y, inexact, rnd_mode);
4604a238c70SJohn Marino     }
4614a238c70SJohn Marino   else if (mpfr_cmp_ui_2exp (x, 1, -1) > 0) /*  1/2 < x < 1 */
4624a238c70SJohn Marino     /* 1 > x > 1/2: Li2(x) = -S(-log(x))+log^2(x)/4-log(x)log(1-x)+pi^2/6 */
4634a238c70SJohn Marino     {
4644a238c70SJohn Marino       int k;
4654a238c70SJohn Marino       mpfr_t s, u, v, xx;
4664a238c70SJohn Marino       mpfr_init2 (s, m);
4674a238c70SJohn Marino       mpfr_init2 (u, m);
4684a238c70SJohn Marino       mpfr_init2 (v, m);
4694a238c70SJohn Marino       mpfr_init2 (xx, m);
4704a238c70SJohn Marino 
4714a238c70SJohn Marino 
4724a238c70SJohn Marino       MPFR_ZIV_INIT (loop, m);
4734a238c70SJohn Marino       for (;;)
4744a238c70SJohn Marino         {
4754a238c70SJohn Marino           mpfr_log (u, x, MPFR_RNDD);
4764a238c70SJohn Marino           mpfr_neg (u, u, MPFR_RNDN);
4774a238c70SJohn Marino           k = li2_series (s, u, MPFR_RNDN);
4784a238c70SJohn Marino           mpfr_neg (s, s, MPFR_RNDN);
4794a238c70SJohn Marino           err = 1 + MPFR_INT_CEIL_LOG2 (k + 1) - MPFR_GET_EXP (s);
4804a238c70SJohn Marino 
4814a238c70SJohn Marino           mpfr_ui_sub (xx, 1, x, MPFR_RNDN);
4824a238c70SJohn Marino           mpfr_log (v, xx, MPFR_RNDU);
4834a238c70SJohn Marino           mpfr_mul (v, v, u, MPFR_RNDN); /* v = - log(x) * log(1-x) */
4844a238c70SJohn Marino           mpfr_add (s, s, v, MPFR_RNDN);
4854a238c70SJohn Marino           err = MAX (err, 1 - MPFR_GET_EXP (v));
4864a238c70SJohn Marino           err = 2 + MAX (3, err) - MPFR_GET_EXP (s);
4874a238c70SJohn Marino 
4884a238c70SJohn Marino           mpfr_sqr (u, u, MPFR_RNDN);
4894a238c70SJohn Marino           mpfr_div_2ui (u, u, 2, MPFR_RNDN);     /* u = log^2(x)/4 */
4904a238c70SJohn Marino           mpfr_add (s, s, u, MPFR_RNDN);
4914a238c70SJohn Marino           err = MAX (err, 2 + MPFR_GET_EXP (u)) - MPFR_GET_EXP (s);
4924a238c70SJohn Marino           err = 2 + MAX (-1, err) + MPFR_GET_EXP (s);
4934a238c70SJohn Marino 
4944a238c70SJohn Marino           mpfr_const_pi (u, MPFR_RNDU);
4954a238c70SJohn Marino           mpfr_sqr (u, u, MPFR_RNDN);
4964a238c70SJohn Marino           mpfr_div_ui (u, u, 6, MPFR_RNDN);      /* u = pi^2/6 */
4974a238c70SJohn Marino           mpfr_add (s, s, u, MPFR_RNDN);
4984a238c70SJohn Marino           err = MAX (err, 3) - MPFR_GET_EXP (s);
4994a238c70SJohn Marino           err = 2 + MAX (-1, err);
5004a238c70SJohn Marino 
5014a238c70SJohn Marino           if (MPFR_CAN_ROUND (s, (mpfr_exp_t) m - err, yp, rnd_mode))
5024a238c70SJohn Marino             break;
5034a238c70SJohn Marino 
5044a238c70SJohn Marino           MPFR_ZIV_NEXT (loop, m);
5054a238c70SJohn Marino           mpfr_set_prec (s, m);
5064a238c70SJohn Marino           mpfr_set_prec (u, m);
5074a238c70SJohn Marino           mpfr_set_prec (v, m);
5084a238c70SJohn Marino           mpfr_set_prec (xx, m);
5094a238c70SJohn Marino         }
5104a238c70SJohn Marino       MPFR_ZIV_FREE (loop);
5114a238c70SJohn Marino       inexact = mpfr_set (y, s, rnd_mode);
5124a238c70SJohn Marino 
5134a238c70SJohn Marino       mpfr_clears (s, u, v, xx, (mpfr_ptr) 0);
5144a238c70SJohn Marino       MPFR_SAVE_EXPO_FREE (expo);
5154a238c70SJohn Marino       return mpfr_check_range (y, inexact, rnd_mode);
5164a238c70SJohn Marino     }
5174a238c70SJohn Marino   else if (mpfr_cmp_si (x, -1) >= 0)
5184a238c70SJohn Marino     /* 0 > x >= -1: Li2(x) = -S(log(1-x))-log^2(1-x)/4 */
5194a238c70SJohn Marino     {
5204a238c70SJohn Marino       int k;
5214a238c70SJohn Marino       mpfr_exp_t expo_l;
5224a238c70SJohn Marino       mpfr_t s, u, xx;
5234a238c70SJohn Marino       mpfr_init2 (s, m);
5244a238c70SJohn Marino       mpfr_init2 (u, m);
5254a238c70SJohn Marino       mpfr_init2 (xx, m);
5264a238c70SJohn Marino 
5274a238c70SJohn Marino       MPFR_ZIV_INIT (loop, m);
5284a238c70SJohn Marino       for (;;)
5294a238c70SJohn Marino         {
5304a238c70SJohn Marino           mpfr_neg (xx, x, MPFR_RNDN);
5314a238c70SJohn Marino           mpfr_log1p (u, xx, MPFR_RNDN);
5324a238c70SJohn Marino           k = li2_series (s, u, MPFR_RNDN);
5334a238c70SJohn Marino           mpfr_neg (s, s, MPFR_RNDN);
5344a238c70SJohn Marino           expo_l = MPFR_GET_EXP (u);
5354a238c70SJohn Marino           err = 1 + MPFR_INT_CEIL_LOG2 (k + 1) - MPFR_GET_EXP (s);
5364a238c70SJohn Marino 
5374a238c70SJohn Marino           mpfr_sqr (u, u, MPFR_RNDN);
5384a238c70SJohn Marino           mpfr_div_2ui (u, u, 2, MPFR_RNDN);     /* u = log^2(1-x)/4 */
5394a238c70SJohn Marino           mpfr_sub (s, s, u, MPFR_RNDN);
5404a238c70SJohn Marino           err = MAX (err, - expo_l);
5414a238c70SJohn Marino           err = 2 + MAX (err, 3);
5424a238c70SJohn Marino           if (MPFR_CAN_ROUND (s, (mpfr_exp_t) m - err, yp, rnd_mode))
5434a238c70SJohn Marino             break;
5444a238c70SJohn Marino 
5454a238c70SJohn Marino           MPFR_ZIV_NEXT (loop, m);
5464a238c70SJohn Marino           mpfr_set_prec (s, m);
5474a238c70SJohn Marino           mpfr_set_prec (u, m);
5484a238c70SJohn Marino           mpfr_set_prec (xx, m);
5494a238c70SJohn Marino         }
5504a238c70SJohn Marino       MPFR_ZIV_FREE (loop);
5514a238c70SJohn Marino       inexact = mpfr_set (y, s, rnd_mode);
5524a238c70SJohn Marino 
5534a238c70SJohn Marino       mpfr_clears (s, u, xx, (mpfr_ptr) 0);
5544a238c70SJohn Marino       MPFR_SAVE_EXPO_FREE (expo);
5554a238c70SJohn Marino       return mpfr_check_range (y, inexact, rnd_mode);
5564a238c70SJohn Marino     }
5574a238c70SJohn Marino   else
5584a238c70SJohn Marino     /* x < -1: Li2(x)
5594a238c70SJohn Marino        = S(log(1-1/x))-log^2(-x)/4-log(1-x)log(-x)/2+log^2(1-x)/4-pi^2/6 */
5604a238c70SJohn Marino     {
5614a238c70SJohn Marino       int k;
5624a238c70SJohn Marino       mpfr_t s, u, v, w, xx;
5634a238c70SJohn Marino 
5644a238c70SJohn Marino       if (mpfr_cmp_si (x, -7) <= 0)
5654a238c70SJohn Marino         {
5664a238c70SJohn Marino           inexact = mpfr_li2_asympt_neg (y, x, rnd_mode);
5674a238c70SJohn Marino           if (inexact != 0)
5684a238c70SJohn Marino             goto end_of_case_ltm1;
5694a238c70SJohn Marino         }
5704a238c70SJohn Marino 
5714a238c70SJohn Marino       mpfr_init2 (s, m);
5724a238c70SJohn Marino       mpfr_init2 (u, m);
5734a238c70SJohn Marino       mpfr_init2 (v, m);
5744a238c70SJohn Marino       mpfr_init2 (w, m);
5754a238c70SJohn Marino       mpfr_init2 (xx, m);
5764a238c70SJohn Marino 
5774a238c70SJohn Marino       MPFR_ZIV_INIT (loop, m);
5784a238c70SJohn Marino       for (;;)
5794a238c70SJohn Marino         {
5804a238c70SJohn Marino           mpfr_ui_div (xx, 1, x, MPFR_RNDN);
5814a238c70SJohn Marino           mpfr_neg (xx, xx, MPFR_RNDN);
5824a238c70SJohn Marino           mpfr_log1p (u, xx, MPFR_RNDN);
5834a238c70SJohn Marino           k = li2_series (s, u, MPFR_RNDN);
5844a238c70SJohn Marino 
5854a238c70SJohn Marino           mpfr_ui_sub (xx, 1, x, MPFR_RNDN);
5864a238c70SJohn Marino           mpfr_log (u, xx, MPFR_RNDU);
5874a238c70SJohn Marino           mpfr_neg (xx, x, MPFR_RNDN);
5884a238c70SJohn Marino           mpfr_log (v, xx, MPFR_RNDU);
5894a238c70SJohn Marino           mpfr_mul (w, v, u, MPFR_RNDN);
5904a238c70SJohn Marino           mpfr_div_2ui (w, w, 1, MPFR_RNDN);  /* w = log(-x) * log(1-x) / 2 */
5914a238c70SJohn Marino           mpfr_sub (s, s, w, MPFR_RNDN);
5924a238c70SJohn Marino           err = 1 + MAX (3, MPFR_INT_CEIL_LOG2 (k+1) + 1  - MPFR_GET_EXP (s))
5934a238c70SJohn Marino             + MPFR_GET_EXP (s);
5944a238c70SJohn Marino 
5954a238c70SJohn Marino           mpfr_sqr (w, v, MPFR_RNDN);
5964a238c70SJohn Marino           mpfr_div_2ui (w, w, 2, MPFR_RNDN);  /* w = log^2(-x) / 4 */
5974a238c70SJohn Marino           mpfr_sub (s, s, w, MPFR_RNDN);
5984a238c70SJohn Marino           err = MAX (err, 3 + MPFR_GET_EXP(w)) - MPFR_GET_EXP (s);
5994a238c70SJohn Marino           err = 2 + MAX (-1, err) + MPFR_GET_EXP (s);
6004a238c70SJohn Marino 
6014a238c70SJohn Marino           mpfr_sqr (w, u, MPFR_RNDN);
6024a238c70SJohn Marino           mpfr_div_2ui (w, w, 2, MPFR_RNDN);     /* w = log^2(1-x) / 4 */
6034a238c70SJohn Marino           mpfr_add (s, s, w, MPFR_RNDN);
6044a238c70SJohn Marino           err = MAX (err, 3 + MPFR_GET_EXP (w)) - MPFR_GET_EXP (s);
6054a238c70SJohn Marino           err = 2 + MAX (-1, err) + MPFR_GET_EXP (s);
6064a238c70SJohn Marino 
6074a238c70SJohn Marino           mpfr_const_pi (w, MPFR_RNDU);
6084a238c70SJohn Marino           mpfr_sqr (w, w, MPFR_RNDN);
6094a238c70SJohn Marino           mpfr_div_ui (w, w, 6, MPFR_RNDN);      /* w = pi^2 / 6 */
6104a238c70SJohn Marino           mpfr_sub (s, s, w, MPFR_RNDN);
6114a238c70SJohn Marino           err = MAX (err, 3) - MPFR_GET_EXP (s);
6124a238c70SJohn Marino           err = 2 + MAX (-1, err) + MPFR_GET_EXP (s);
6134a238c70SJohn Marino 
6144a238c70SJohn Marino           if (MPFR_CAN_ROUND (s, (mpfr_exp_t) m - err, yp, rnd_mode))
6154a238c70SJohn Marino             break;
6164a238c70SJohn Marino 
6174a238c70SJohn Marino           MPFR_ZIV_NEXT (loop, m);
6184a238c70SJohn Marino           mpfr_set_prec (s, m);
6194a238c70SJohn Marino           mpfr_set_prec (u, m);
6204a238c70SJohn Marino           mpfr_set_prec (v, m);
6214a238c70SJohn Marino           mpfr_set_prec (w, m);
6224a238c70SJohn Marino           mpfr_set_prec (xx, m);
6234a238c70SJohn Marino         }
6244a238c70SJohn Marino       MPFR_ZIV_FREE (loop);
6254a238c70SJohn Marino       inexact = mpfr_set (y, s, rnd_mode);
6264a238c70SJohn Marino       mpfr_clears (s, u, v, w, xx, (mpfr_ptr) 0);
6274a238c70SJohn Marino 
6284a238c70SJohn Marino     end_of_case_ltm1:
6294a238c70SJohn Marino       MPFR_SAVE_EXPO_FREE (expo);
6304a238c70SJohn Marino       return mpfr_check_range (y, inexact, rnd_mode);
6314a238c70SJohn Marino     }
6324a238c70SJohn Marino 
6334a238c70SJohn Marino   MPFR_ASSERTN (0);             /* should never reach this point */
6344a238c70SJohn Marino }
635