xref: /netbsd-src/external/lgpl3/mpfr/dist/src/li2.c (revision ec6772edaf0cdcb5f52a48f4aca5e33a8fb8ecfd)
1 /* mpfr_li2 -- Dilogarithm.
2 
3 Copyright 2007-2023 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
5 
6 This file is part of the GNU MPFR Library.
7 
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16 License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22 
23 #define MPFR_NEED_LONGLONG_H
24 #include "mpfr-impl.h"
25 
26 /* Compute the alternating series
27    s = S(z) = \sum_{k=0}^infty B_{2k} (z))^{2k+1} / (2k+1)!
28    with 0 < z <= log(2) to the precision of s rounded in the direction
29    rnd_mode.
30    Return the maximum index of the truncature which is useful
31    for determinating the relative error.
32 */
33 static int
li2_series(mpfr_ptr sum,mpfr_srcptr z,mpfr_rnd_t rnd_mode)34 li2_series (mpfr_ptr sum, mpfr_srcptr z, mpfr_rnd_t rnd_mode)
35 {
36   int i;
37   mpfr_t s, u, v, w;
38   mpfr_prec_t sump, p;
39   mpfr_exp_t se, err;
40   MPFR_ZIV_DECL (loop);
41 
42   /* The series converges for |z| < 2 pi, but in mpfr_li2 the argument is
43      reduced so that 0 < z <= log(2). Here is an additional check that z
44      is (nearly) correct. */
45   MPFR_ASSERTD (MPFR_IS_STRICTPOS (z));
46   MPFR_ASSERTD (mpfr_cmp_ui_2exp (z, 89, -7) <= 0); /* z <= 0.6953125 */
47 
48   sump = MPFR_PREC (sum);       /* target precision */
49   p = sump + MPFR_INT_CEIL_LOG2 (sump) + 4;     /* the working precision */
50   mpfr_init2 (s, p);
51   mpfr_init2 (u, p);
52   mpfr_init2 (v, p);
53   mpfr_init2 (w, p);
54 
55   MPFR_ZIV_INIT (loop, p);
56   for (;;)
57     {
58       mpfr_sqr (u, z, MPFR_RNDU);
59       mpfr_set (v, z, MPFR_RNDU);
60       mpfr_set (s, z, MPFR_RNDU);
61       se = MPFR_GET_EXP (s);
62       err = 0;
63 
64       for (i = 1;; i++)
65         {
66           mpfr_mul (v, u, v, MPFR_RNDU);
67           mpfr_div_ui (v, v, 2 * i, MPFR_RNDU);
68           mpfr_div_ui (v, v, 2 * i, MPFR_RNDU);
69           mpfr_div_ui (v, v, 2 * i + 1, MPFR_RNDU);
70           mpfr_div_ui (v, v, 2 * i + 1, MPFR_RNDU);
71           /* here, v_2i = v_{2i-2} / (2i * (2i+1))^2 */
72 
73           mpfr_mul_z (w, v, mpfr_bernoulli_cache(i), MPFR_RNDN);
74           /* here, w_2i = v_2i * B_2i * (2i+1)! with
75              error(w_2i) < 2^(5 * i + 8) ulp(w_2i) (see algorithms.tex) */
76 
77           mpfr_add (s, s, w, MPFR_RNDN);
78 
79           err = MAX (err + se, 5 * i + 8 + MPFR_GET_EXP (w))
80             - MPFR_GET_EXP (s);
81           err = 2 + MAX (-1, err);
82           se = MPFR_GET_EXP (s);
83           if (MPFR_GET_EXP (w) <= se - (mpfr_exp_t) p)
84             break;
85         }
86 
87       /* the previous value of err is the rounding error,
88          the truncation error is less than EXP(z) - 6 * i - 5
89          (see algorithms.tex) */
90       err = MAX (err, MPFR_GET_EXP (z) - 6 * i - 5) + 1;
91       if (MPFR_CAN_ROUND (s, (mpfr_exp_t) p - err, sump, rnd_mode))
92         break;
93 
94       MPFR_ZIV_NEXT (loop, p);
95       mpfr_set_prec (s, p);
96       mpfr_set_prec (u, p);
97       mpfr_set_prec (v, p);
98       mpfr_set_prec (w, p);
99     }
100   MPFR_ZIV_FREE (loop);
101   mpfr_set (sum, s, rnd_mode);
102 
103   mpfr_clears (s, u, v, w, (mpfr_ptr) 0);
104 
105   /* Let K be the returned value.
106      1. As we compute an alternating series, the truncation error has the same
107      sign as the next term w_{K+2} which is positive iff K%4 == 0.
108      2. Assume that error(z) <= (1+t) z', where z' is the actual value, then
109      error(s) <= 2 * (K+1) * t (see algorithms.tex).
110    */
111   return 2 * i;
112 }
113 
114 /* try asymptotic expansion when x is large and positive:
115    Li2(x) = -log(x)^2/2 + Pi^2/3 - 1/x + O(1/x^2).
116    More precisely for x >= 2 we have for g(x) = -log(x)^2/2 + Pi^2/3:
117    -2 <= x * (Li2(x) - g(x)) <= -1
118    thus |Li2(x) - g(x)| <= 2/x.
119    Assumes x >= 38, which ensures log(x)^2/2 >= 2*Pi^2/3, and g(x) <= -3.3.
120    Return 0 if asymptotic expansion failed (unable to round), otherwise
121    returns 1 for RNDF, and correct ternary value otherwise.
122 */
123 static int
mpfr_li2_asympt_pos(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd_mode)124 mpfr_li2_asympt_pos (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
125 {
126   mpfr_t g, h;
127   mpfr_prec_t w = MPFR_PREC (y) + 20;
128   int inex = 0;
129 
130   MPFR_ASSERTN (mpfr_cmp_ui (x, 38) >= 0);
131 
132   mpfr_init2 (g, w);
133   mpfr_init2 (h, w);
134   mpfr_log (g, x, MPFR_RNDN);    /* rel. error <= |(1 + theta) - 1| */
135   mpfr_sqr (g, g, MPFR_RNDN);    /* rel. error <= |(1 + theta)^3 - 1| <= 2^(2-w) */
136   mpfr_div_2ui (g, g, 1, MPFR_RNDN);     /* rel. error <= 2^(2-w) */
137   mpfr_const_pi (h, MPFR_RNDN);  /* error <= 2^(1-w) */
138   mpfr_sqr (h, h, MPFR_RNDN);    /* rel. error <= 2^(2-w) */
139   mpfr_div_ui (h, h, 3, MPFR_RNDN);      /* rel. error <= |(1 + theta)^4 - 1|
140                                            <= 5 * 2^(-w) */
141   /* since x is chosen such that log(x)^2/2 >= 2 * (Pi^2/3), we should have
142      g >= 2*h, thus |g-h| >= |h|, and the relative error on g is at most
143      multiplied by 2 in the difference, and that by h is unchanged. */
144   MPFR_ASSERTN (MPFR_EXP (g) > MPFR_EXP (h));
145   mpfr_sub (g, h, g, MPFR_RNDN); /* err <= ulp(g)/2 + g*2^(3-w) + g*5*2^(-w)
146                                    <= ulp(g) * (1/2 + 8 + 5) < 14 ulp(g).
147 
148                                    If in addition 2/x <= 2 ulp(g), i.e.,
149                                    1/x <= ulp(g), then the total error is
150                                    bounded by 16 ulp(g). */
151   if ((MPFR_EXP (x) >= (mpfr_exp_t) w - MPFR_EXP (g)) &&
152       MPFR_CAN_ROUND (g, w - 4, MPFR_PREC (y), rnd_mode))
153     {
154       inex = mpfr_set (y, g, rnd_mode);
155       if (rnd_mode == MPFR_RNDF)
156         inex = 1;
157     }
158 
159   mpfr_clear (g);
160   mpfr_clear (h);
161 
162   return inex;
163 }
164 
165 /* try asymptotic expansion when x is large and negative:
166    Li2(x) = -log(-x)^2/2 - Pi^2/6 - 1/x + O(1/x^2).
167    More precisely for x <= -2 we have for g(x) = -log(-x)^2/2 - Pi^2/6:
168    |Li2(x) - g(x)| <= 1/|x|.
169    Assumes x <= -7, which ensures |log(-x)^2/2| >= Pi^2/6, and g(x) <= -3.5.
170    Return 0 if asymptotic expansion failed (unable to round), otherwise
171    returns 1 for RNDF, and correct ternary value otherwise.
172 */
173 static int
mpfr_li2_asympt_neg(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd_mode)174 mpfr_li2_asympt_neg (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
175 {
176   mpfr_t g, h;
177   mpfr_prec_t w = MPFR_PREC (y) + 20;
178   int inex = 0;
179 
180   MPFR_ASSERTN (mpfr_cmp_si (x, -7) <= 0);
181 
182   mpfr_init2 (g, w);
183   mpfr_init2 (h, w);
184   mpfr_neg (g, x, MPFR_RNDN);
185   mpfr_log (g, g, MPFR_RNDN);    /* rel. error <= |(1 + theta) - 1| */
186   mpfr_sqr (g, g, MPFR_RNDN);    /* rel. error <= |(1 + theta)^3 - 1| <= 2^(2-w) */
187   mpfr_div_2ui (g, g, 1, MPFR_RNDN);     /* rel. error <= 2^(2-w) */
188   mpfr_const_pi (h, MPFR_RNDN);  /* error <= 2^(1-w) */
189   mpfr_sqr (h, h, MPFR_RNDN);    /* rel. error <= 2^(2-w) */
190   mpfr_div_ui (h, h, 6, MPFR_RNDN);      /* rel. error <= |(1 + theta)^4 - 1|
191                                            <= 5 * 2^(-w) */
192   MPFR_ASSERTN (MPFR_EXP (g) >= MPFR_EXP (h));
193   mpfr_add (g, g, h, MPFR_RNDN); /* err <= ulp(g)/2 + g*2^(2-w) + g*5*2^(-w)
194                                    <= ulp(g) * (1/2 + 4 + 5) < 10 ulp(g).
195 
196                                    If in addition |1/x| <= 4 ulp(g), then the
197                                    total error is bounded by 16 ulp(g). */
198   if ((MPFR_EXP (x) >= (mpfr_exp_t) (w - 2) - MPFR_EXP (g)) &&
199       MPFR_CAN_ROUND (g, w - 4, MPFR_PREC (y), rnd_mode))
200     {
201       inex = mpfr_neg (y, g, rnd_mode);
202       if (rnd_mode == MPFR_RNDF)
203         inex = 1;
204     }
205 
206   mpfr_clear (g);
207   mpfr_clear (h);
208 
209   return inex;
210 }
211 
212 /* Compute the real part of the dilogarithm defined by
213    Li2(x) = -\Int_{t=0}^x log(1-t)/t dt */
214 int
mpfr_li2(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd_mode)215 mpfr_li2 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
216 {
217   int inexact;
218   mpfr_exp_t err;
219   mpfr_prec_t yp, m;
220   MPFR_ZIV_DECL (loop);
221   MPFR_SAVE_EXPO_DECL (expo);
222 
223   MPFR_LOG_FUNC
224     (("x[%Pd]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode),
225      ("y[%Pd]=%.*Rg inexact=%d",
226       mpfr_get_prec (y), mpfr_log_prec, y, inexact));
227 
228   if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
229     {
230       if (MPFR_IS_NAN (x))
231         {
232           MPFR_SET_NAN (y);
233           MPFR_RET_NAN;
234         }
235       else if (MPFR_IS_INF (x))
236         {
237           MPFR_SET_NEG (y);
238           MPFR_SET_INF (y);
239           MPFR_RET (0);
240         }
241       else                      /* x is zero */
242         {
243           MPFR_ASSERTD (MPFR_IS_ZERO (x));
244           MPFR_SET_SAME_SIGN (y, x);
245           MPFR_SET_ZERO (y);
246           MPFR_RET (0);
247         }
248     }
249 
250   /* Li2(x) = x + x^2/4 + x^3/9 + ..., more precisely for 0 < x <= 1/2
251      we have |Li2(x) - x| < x^2/2 <= 2^(2EXP(x)-1) and for -1/2 <= x < 0
252      we have |Li2(x) - x| < x^2/4 <= 2^(2EXP(x)-2) */
253   if (MPFR_IS_POS (x))
254     MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, -MPFR_GET_EXP (x), 1, 1, rnd_mode,
255                                       {});
256   else
257     MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, -MPFR_GET_EXP (x), 2, 0, rnd_mode,
258                                       {});
259 
260   MPFR_SAVE_EXPO_MARK (expo);
261   yp = MPFR_PREC (y);
262   m = yp + MPFR_INT_CEIL_LOG2 (yp) + 13;
263 
264   if (MPFR_LIKELY ((mpfr_cmp_ui (x, 0) > 0) && (mpfr_cmp_ui_2exp (x, 1, -1) <= 0)))
265     /* 0 < x <= 1/2: Li2(x) = S(-log(1-x))-log^2(1-x)/4 */
266     {
267       mpfr_t s, u;
268       mpfr_exp_t expo_l;
269       int k;
270 
271       mpfr_init2 (u, m);
272       mpfr_init2 (s, m);
273 
274       MPFR_ZIV_INIT (loop, m);
275       for (;;)
276         {
277           mpfr_ui_sub (u, 1, x, MPFR_RNDN);
278           mpfr_log (u, u, MPFR_RNDU);
279           if (MPFR_IS_ZERO(u))
280             goto next_m;
281           mpfr_neg (u, u, MPFR_RNDN);    /* u = -log(1-x) */
282           expo_l = MPFR_GET_EXP (u);
283           k = li2_series (s, u, MPFR_RNDU);
284           err = 1 + MPFR_INT_CEIL_LOG2 (k + 1);
285 
286           mpfr_sqr (u, u, MPFR_RNDU);
287           mpfr_div_2ui (u, u, 2, MPFR_RNDU);     /* u = log^2(1-x) / 4 */
288           mpfr_sub (s, s, u, MPFR_RNDN);
289 
290           /* error(s) <= (0.5 + 2^(d-EXP(s))
291              + 2^(3 + MAX(1, - expo_l) - EXP(s))) ulp(s) */
292           err = MAX (err, MAX (1, - expo_l) - 1) - MPFR_GET_EXP (s);
293           err = 2 + MAX (-1, err);
294           if (MPFR_CAN_ROUND (s, (mpfr_exp_t) m - err, yp, rnd_mode))
295             break;
296 
297         next_m:
298           MPFR_ZIV_NEXT (loop, m);
299           mpfr_set_prec (u, m);
300           mpfr_set_prec (s, m);
301         }
302       MPFR_ZIV_FREE (loop);
303       inexact = mpfr_set (y, s, rnd_mode);
304 
305       mpfr_clear (u);
306       mpfr_clear (s);
307       MPFR_SAVE_EXPO_FREE (expo);
308       return mpfr_check_range (y, inexact, rnd_mode);
309     }
310   else if (!mpfr_cmp_ui (x, 1))
311     /* Li2(1)= pi^2 / 6 */
312     {
313       mpfr_t u;
314       mpfr_init2 (u, m);
315 
316       MPFR_ZIV_INIT (loop, m);
317       for (;;)
318         {
319           mpfr_const_pi (u, MPFR_RNDU);
320           mpfr_sqr (u, u, MPFR_RNDN);
321           mpfr_div_ui (u, u, 6, MPFR_RNDN);
322 
323           err = m - 4;          /* error(u) <= 19/2 ulp(u) */
324           if (MPFR_CAN_ROUND (u, err, yp, rnd_mode))
325             break;
326 
327           MPFR_ZIV_NEXT (loop, m);
328           mpfr_set_prec (u, m);
329         }
330       MPFR_ZIV_FREE (loop);
331       inexact = mpfr_set (y, u, rnd_mode);
332 
333       mpfr_clear (u);
334       MPFR_SAVE_EXPO_FREE (expo);
335       return mpfr_check_range (y, inexact, rnd_mode);
336     }
337   else if (mpfr_cmp_ui (x, 2) >= 0)
338     /* x >= 2: Li2(x) = -S(-log(1-1/x))-log^2(x)/2+log^2(1-1/x)/4+pi^2/3 */
339     {
340       int k;
341       mpfr_exp_t expo_l;
342       mpfr_t s, u, xx;
343 
344       if (mpfr_cmp_ui (x, 38) >= 0)
345         {
346           inexact = mpfr_li2_asympt_pos (y, x, rnd_mode);
347           if (inexact != 0)
348             goto end_of_case_gt2;
349         }
350 
351       mpfr_init2 (u, m);
352       mpfr_init2 (s, m);
353       mpfr_init2 (xx, m);
354 
355       MPFR_ZIV_INIT (loop, m);
356       for (;;)
357         {
358           mpfr_ui_div (xx, 1, x, MPFR_RNDN);
359           mpfr_neg (xx, xx, MPFR_RNDN);
360           mpfr_log1p (u, xx, MPFR_RNDD);
361           mpfr_neg (u, u, MPFR_RNDU);    /* u = -log(1-1/x) */
362           expo_l = MPFR_GET_EXP (u);
363           k = li2_series (s, u, MPFR_RNDN);
364           mpfr_neg (s, s, MPFR_RNDN);
365           err = MPFR_INT_CEIL_LOG2 (k + 1) + 1; /* error(s) <= 2^err ulp(s) */
366 
367           mpfr_sqr (u, u, MPFR_RNDN);
368           mpfr_div_2ui (u, u, 2, MPFR_RNDN);     /* u= log^2(1-1/x)/4 */
369           mpfr_add (s, s, u, MPFR_RNDN);
370           err =
371             MAX (err,
372                  3 + MAX (1, -expo_l) + MPFR_GET_EXP (u)) - MPFR_GET_EXP (s);
373           err = 2 + MAX (-1, err);      /* error(s) <= 2^err ulp(s) */
374           err += MPFR_GET_EXP (s);
375 
376           mpfr_log (u, x, MPFR_RNDU);
377           mpfr_sqr (u, u, MPFR_RNDN);
378           mpfr_div_2ui (u, u, 1, MPFR_RNDN);     /* u = log^2(x)/2 */
379           mpfr_sub (s, s, u, MPFR_RNDN);
380           err = MAX (err, 3 + MPFR_GET_EXP (u)) - MPFR_GET_EXP (s);
381           err = 2 + MAX (-1, err);      /* error(s) <= 2^err ulp(s) */
382           err += MPFR_GET_EXP (s);
383 
384           mpfr_const_pi (u, MPFR_RNDU);
385           mpfr_sqr (u, u, MPFR_RNDN);
386           mpfr_div_ui (u, u, 3, MPFR_RNDN);      /* u = pi^2/3 */
387           mpfr_add (s, s, u, MPFR_RNDN);
388           err = MAX (err, 2) - MPFR_GET_EXP (s);
389           err = 2 + MAX (-1, err);      /* error(s) <= 2^err ulp(s) */
390           if (MPFR_CAN_ROUND (s, (mpfr_exp_t) m - err, yp, rnd_mode))
391             break;
392 
393           MPFR_ZIV_NEXT (loop, m);
394           mpfr_set_prec (u, m);
395           mpfr_set_prec (s, m);
396           mpfr_set_prec (xx, m);
397         }
398       MPFR_ZIV_FREE (loop);
399       inexact = mpfr_set (y, s, rnd_mode);
400       mpfr_clears (s, u, xx, (mpfr_ptr) 0);
401 
402     end_of_case_gt2:
403       MPFR_SAVE_EXPO_FREE (expo);
404       return mpfr_check_range (y, inexact, rnd_mode);
405     }
406   else if (mpfr_cmp_ui (x, 1) > 0)
407     /* 2 > x > 1: Li2(x) = S(log(x))+log^2(x)/4-log(x)log(x-1)+pi^2/6 */
408     {
409       int k;
410       mpfr_exp_t e1, e2;
411       mpfr_t s, u, v, xx;
412       mpfr_init2 (s, m);
413       mpfr_init2 (u, m);
414       mpfr_init2 (v, m);
415       mpfr_init2 (xx, m);
416 
417       MPFR_ZIV_INIT (loop, m);
418       for (;;)
419         {
420           mpfr_log (v, x, MPFR_RNDU);
421           k = li2_series (s, v, MPFR_RNDN);
422           e1 = MPFR_GET_EXP (s);
423 
424           mpfr_sqr (u, v, MPFR_RNDN);
425           mpfr_div_2ui (u, u, 2, MPFR_RNDN);     /* u = log^2(x)/4 */
426           mpfr_add (s, s, u, MPFR_RNDN);
427 
428           mpfr_sub_ui (xx, x, 1, MPFR_RNDN);
429           mpfr_log (u, xx, MPFR_RNDU);
430           e2 = MPFR_GET_EXP (u);
431           mpfr_mul (u, v, u, MPFR_RNDN); /* u = log(x) * log(x-1) */
432           mpfr_sub (s, s, u, MPFR_RNDN);
433 
434           mpfr_const_pi (u, MPFR_RNDU);
435           mpfr_sqr (u, u, MPFR_RNDN);
436           mpfr_div_ui (u, u, 6, MPFR_RNDN);      /* u = pi^2/6 */
437           mpfr_add (s, s, u, MPFR_RNDN);
438           /* error(s) <= (31 + (k+1) * 2^(1-e1) + 2^(1-e2)) ulp(s)
439              see algorithms.tex */
440           err = MAX (MPFR_INT_CEIL_LOG2 (k + 1) + 1 - e1, 1 - e2);
441           err = 2 + MAX (5, err);
442           if (MPFR_CAN_ROUND (s, (mpfr_exp_t) m - err, yp, rnd_mode))
443             break;
444 
445           MPFR_ZIV_NEXT (loop, m);
446           mpfr_set_prec (s, m);
447           mpfr_set_prec (u, m);
448           mpfr_set_prec (v, m);
449           mpfr_set_prec (xx, m);
450         }
451       MPFR_ZIV_FREE (loop);
452       inexact = mpfr_set (y, s, rnd_mode);
453 
454       mpfr_clears (s, u, v, xx, (mpfr_ptr) 0);
455       MPFR_SAVE_EXPO_FREE (expo);
456       return mpfr_check_range (y, inexact, rnd_mode);
457     }
458   else if (mpfr_cmp_ui_2exp (x, 1, -1) > 0) /*  1/2 < x < 1 */
459     /* 1 > x > 1/2: Li2(x) = -S(-log(x))+log^2(x)/4-log(x)log(1-x)+pi^2/6 */
460     {
461       int k;
462       mpfr_t s, u, v, xx;
463       mpfr_init2 (s, m);
464       mpfr_init2 (u, m);
465       mpfr_init2 (v, m);
466       mpfr_init2 (xx, m);
467 
468 
469       MPFR_ZIV_INIT (loop, m);
470       for (;;)
471         {
472           mpfr_log (u, x, MPFR_RNDD);
473           mpfr_neg (u, u, MPFR_RNDN);
474           k = li2_series (s, u, MPFR_RNDN);
475           mpfr_neg (s, s, MPFR_RNDN);
476           err = 1 + MPFR_INT_CEIL_LOG2 (k + 1) - MPFR_GET_EXP (s);
477 
478           mpfr_ui_sub (xx, 1, x, MPFR_RNDN);
479           mpfr_log (v, xx, MPFR_RNDU);
480           mpfr_mul (v, v, u, MPFR_RNDN); /* v = - log(x) * log(1-x) */
481           mpfr_add (s, s, v, MPFR_RNDN);
482           err = MAX (err, 1 - MPFR_GET_EXP (v));
483           err = 2 + MAX (3, err) - MPFR_GET_EXP (s);
484 
485           mpfr_sqr (u, u, MPFR_RNDN);
486           mpfr_div_2ui (u, u, 2, MPFR_RNDN);     /* u = log^2(x)/4 */
487           mpfr_add (s, s, u, MPFR_RNDN);
488           err = MAX (err, 2 + MPFR_GET_EXP (u)) - MPFR_GET_EXP (s);
489           err = 2 + MAX (-1, err) + MPFR_GET_EXP (s);
490 
491           mpfr_const_pi (u, MPFR_RNDU);
492           mpfr_sqr (u, u, MPFR_RNDN);
493           mpfr_div_ui (u, u, 6, MPFR_RNDN);      /* u = pi^2/6 */
494           mpfr_add (s, s, u, MPFR_RNDN);
495           err = MAX (err, 3) - MPFR_GET_EXP (s);
496           err = 2 + MAX (-1, err);
497 
498           if (MPFR_CAN_ROUND (s, (mpfr_exp_t) m - err, yp, rnd_mode))
499             break;
500 
501           MPFR_ZIV_NEXT (loop, m);
502           mpfr_set_prec (s, m);
503           mpfr_set_prec (u, m);
504           mpfr_set_prec (v, m);
505           mpfr_set_prec (xx, m);
506         }
507       MPFR_ZIV_FREE (loop);
508       inexact = mpfr_set (y, s, rnd_mode);
509 
510       mpfr_clears (s, u, v, xx, (mpfr_ptr) 0);
511       MPFR_SAVE_EXPO_FREE (expo);
512       return mpfr_check_range (y, inexact, rnd_mode);
513     }
514   else if (mpfr_cmp_si (x, -1) >= 0)
515     /* 0 > x >= -1: Li2(x) = -S(log(1-x))-log^2(1-x)/4 */
516     {
517       int k;
518       mpfr_exp_t expo_l;
519       mpfr_t s, u, xx;
520       mpfr_init2 (s, m);
521       mpfr_init2 (u, m);
522       mpfr_init2 (xx, m);
523 
524       MPFR_ZIV_INIT (loop, m);
525       for (;;)
526         {
527           mpfr_neg (xx, x, MPFR_RNDN);
528           mpfr_log1p (u, xx, MPFR_RNDN);
529           k = li2_series (s, u, MPFR_RNDN);
530           mpfr_neg (s, s, MPFR_RNDN);
531           expo_l = MPFR_GET_EXP (u);
532           err = 1 + MPFR_INT_CEIL_LOG2 (k + 1) - MPFR_GET_EXP (s);
533 
534           mpfr_sqr (u, u, MPFR_RNDN);
535           mpfr_div_2ui (u, u, 2, MPFR_RNDN);     /* u = log^2(1-x)/4 */
536           mpfr_sub (s, s, u, MPFR_RNDN);
537           err = MAX (err, - expo_l);
538           err = 2 + MAX (err, 3);
539           if (MPFR_CAN_ROUND (s, (mpfr_exp_t) m - err, yp, rnd_mode))
540             break;
541 
542           MPFR_ZIV_NEXT (loop, m);
543           mpfr_set_prec (s, m);
544           mpfr_set_prec (u, m);
545           mpfr_set_prec (xx, m);
546         }
547       MPFR_ZIV_FREE (loop);
548       inexact = mpfr_set (y, s, rnd_mode);
549 
550       mpfr_clears (s, u, xx, (mpfr_ptr) 0);
551       MPFR_SAVE_EXPO_FREE (expo);
552       return mpfr_check_range (y, inexact, rnd_mode);
553     }
554   else
555     /* x < -1: Li2(x)
556        = S(log(1-1/x))-log^2(-x)/4-log(1-x)log(-x)/2+log^2(1-x)/4-pi^2/6 */
557     {
558       int k;
559       mpfr_t s, u, v, w, xx;
560 
561       if (mpfr_cmp_si (x, -7) <= 0)
562         {
563           inexact = mpfr_li2_asympt_neg (y, x, rnd_mode);
564           if (inexact != 0)
565             goto end_of_case_ltm1;
566         }
567 
568       mpfr_init2 (s, m);
569       mpfr_init2 (u, m);
570       mpfr_init2 (v, m);
571       mpfr_init2 (w, m);
572       mpfr_init2 (xx, m);
573 
574       MPFR_ZIV_INIT (loop, m);
575       for (;;)
576         {
577           mpfr_ui_div (xx, 1, x, MPFR_RNDN);
578           mpfr_neg (xx, xx, MPFR_RNDN);
579           mpfr_log1p (u, xx, MPFR_RNDN);
580           k = li2_series (s, u, MPFR_RNDN);
581 
582           mpfr_ui_sub (xx, 1, x, MPFR_RNDN);
583           mpfr_log (u, xx, MPFR_RNDU);
584           mpfr_neg (xx, x, MPFR_RNDN);
585           mpfr_log (v, xx, MPFR_RNDU);
586           mpfr_mul (w, v, u, MPFR_RNDN);
587           mpfr_div_2ui (w, w, 1, MPFR_RNDN);  /* w = log(-x) * log(1-x) / 2 */
588           mpfr_sub (s, s, w, MPFR_RNDN);
589           err = 1 + MAX (3, MPFR_INT_CEIL_LOG2 (k+1) + 1  - MPFR_GET_EXP (s))
590             + MPFR_GET_EXP (s);
591 
592           mpfr_sqr (w, v, MPFR_RNDN);
593           mpfr_div_2ui (w, w, 2, MPFR_RNDN);  /* w = log^2(-x) / 4 */
594           mpfr_sub (s, s, w, MPFR_RNDN);
595           err = MAX (err, 3 + MPFR_GET_EXP(w)) - MPFR_GET_EXP (s);
596           err = 2 + MAX (-1, err) + MPFR_GET_EXP (s);
597 
598           mpfr_sqr (w, u, MPFR_RNDN);
599           mpfr_div_2ui (w, w, 2, MPFR_RNDN);     /* w = log^2(1-x) / 4 */
600           mpfr_add (s, s, w, MPFR_RNDN);
601           err = MAX (err, 3 + MPFR_GET_EXP (w)) - MPFR_GET_EXP (s);
602           err = 2 + MAX (-1, err) + MPFR_GET_EXP (s);
603 
604           mpfr_const_pi (w, MPFR_RNDU);
605           mpfr_sqr (w, w, MPFR_RNDN);
606           mpfr_div_ui (w, w, 6, MPFR_RNDN);      /* w = pi^2 / 6 */
607           mpfr_sub (s, s, w, MPFR_RNDN);
608           err = MAX (err, 3) - MPFR_GET_EXP (s);
609           err = 2 + MAX (-1, err) + MPFR_GET_EXP (s);
610 
611           if (MPFR_CAN_ROUND (s, (mpfr_exp_t) m - err, yp, rnd_mode))
612             break;
613 
614           MPFR_ZIV_NEXT (loop, m);
615           mpfr_set_prec (s, m);
616           mpfr_set_prec (u, m);
617           mpfr_set_prec (v, m);
618           mpfr_set_prec (w, m);
619           mpfr_set_prec (xx, m);
620         }
621       MPFR_ZIV_FREE (loop);
622       inexact = mpfr_set (y, s, rnd_mode);
623       mpfr_clears (s, u, v, w, xx, (mpfr_ptr) 0);
624 
625     end_of_case_ltm1:
626       MPFR_SAVE_EXPO_FREE (expo);
627       return mpfr_check_range (y, inexact, rnd_mode);
628     }
629 
630   MPFR_RET_NEVER_GO_HERE ();
631 }
632