xref: /netbsd/external/lgpl3/mpfr/dist/src/gamma_inc.c (revision 606004a0)
1 /* mpfr_gamma_inc -- incomplete gamma function
2 
3 Copyright 2016-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 /* The incomplete gamma function is defined for x >= 0 and a not a negative
27    integer by:
28 
29    gamma_inc(a,x) := Gamma(a,x) = int(t^(a-1) * exp(-t), t=x..infinity)
30 
31                   = Gamma(a) - gamma(a,x) with:
32 
33    gamma(a,x) = int(t^(a-1) * exp(-t), t=0..x).
34 
35    The function gamma(a,x) satisfies the Taylor expansions (we use the second
36    one in the code below):
37 
38    gamma(a,x) = x^a * sum((-x)^k/k!/(a+k), k=0..infinity)
39 
40    gamma(a,x) = x^a * exp(-x) * sum(x^k/(a*(a+1)*...*(a+k)), k=0..infinity)
41 */
42 
43 static int
44 mpfr_gamma_inc_negint (mpfr_ptr y, mpfr_srcptr a, mpfr_srcptr x, mpfr_rnd_t r);
45 
46 int
mpfr_gamma_inc(mpfr_ptr y,mpfr_srcptr a,mpfr_srcptr x,mpfr_rnd_t rnd)47 mpfr_gamma_inc (mpfr_ptr y, mpfr_srcptr a, mpfr_srcptr x, mpfr_rnd_t rnd)
48 {
49   mpfr_prec_t w;
50   mpfr_t s, t, u;
51   int inex;
52   unsigned long k;
53   mpfr_exp_t e0, e1, e2, err;
54   MPFR_GROUP_DECL(group);
55   MPFR_ZIV_DECL(loop);
56   MPFR_SAVE_EXPO_DECL (expo);
57 
58   if (MPFR_ARE_SINGULAR (a, x))
59     {
60       /* if a or x is NaN, return NaN */
61       if (MPFR_IS_NAN (a) || MPFR_IS_NAN (x))
62         {
63           MPFR_SET_NAN (y);
64           MPFR_RET_NAN;
65         }
66 
67       /* Note: for x < 0, gamma_inc (a, x) is a complex number */
68 
69       if (MPFR_IS_INF (a) || MPFR_IS_INF (x))
70         {
71           if (MPFR_IS_INF (a) && MPFR_IS_INF (x))
72             {
73               if ((MPFR_IS_POS (a) && MPFR_IS_POS (x)) || MPFR_IS_NEG (x))
74                 {
75                   /* (a) gamma_inc(+Inf,+Inf) = NaN because
76                          gamma_inc(x,x) tends to +Inf but
77                          gamma_inc(x,x^2) tends to +0.
78                      (b) gamma_inc(+/-Inf,-Inf) = NaN, for example
79                          gamma_inc (a, -a) is a complex number
80                          for a not an integer */
81                   MPFR_SET_NAN (y);
82                   MPFR_RET_NAN;
83                 }
84               else
85                 {
86                   /* gamma_inc(-Inf,+Inf) = +0 */
87                   MPFR_SET_ZERO (y);
88                   MPFR_SET_POS (y);
89                   MPFR_RET (0);  /* exact */
90                 }
91             }
92           else /* only one of a, x is infinite */
93             {
94               if (MPFR_IS_INF (a))
95                 {
96                   MPFR_ASSERTD (MPFR_IS_INF (a) && MPFR_IS_FP (x));
97                   if (MPFR_IS_POS (a))
98                     {
99                       /* gamma_inc(+Inf, x) = +Inf */
100                       MPFR_SET_INF (y);
101                       MPFR_SET_POS (y);
102                       MPFR_RET (0);  /* exact */
103                     }
104                   else /* a = -Inf */
105                     {
106                       /* gamma_inc(-Inf, x) = NaN for x <= 0
107                                               +Inf for 0 < x < 1
108                                               +0 for 1 <= x */
109                       if (mpfr_cmp_ui (x, 0) <= 0)
110                         {
111                           MPFR_SET_NAN (y);
112                           MPFR_RET_NAN;
113                         }
114                       else if (mpfr_cmp_ui (x, 1) < 0)
115                         {
116                           MPFR_SET_INF (y);
117                           MPFR_SET_POS (y);
118                           MPFR_RET (0);  /* exact */
119                         }
120                       else
121                         {
122                           MPFR_SET_ZERO (y);
123                           MPFR_SET_POS (y);
124                           MPFR_RET (0);  /* exact */
125                         }
126                     }
127                 }
128               else
129                 {
130                   MPFR_ASSERTD (MPFR_IS_FP (a) && MPFR_IS_INF (x));
131                   if (MPFR_IS_POS (x))
132                     {
133                       /* x is +Inf: integral tends to zero */
134                       MPFR_SET_ZERO (y);
135                       MPFR_SET_POS (y);
136                       MPFR_RET (0);  /* exact */
137                     }
138                   else /* NaN for x < 0 */
139                     {
140                       MPFR_SET_NAN (y);
141                       MPFR_RET_NAN;
142                     }
143                 }
144             }
145         }
146 
147       if (MPFR_IS_ZERO (a) || MPFR_IS_ZERO (x))
148         {
149           if (MPFR_IS_ZERO (a))
150             {
151               if (mpfr_cmp_ui (x, 0) < 0)
152                 {
153                   /* gamma_inc(a,x) = NaN for x < 0 */
154                   MPFR_SET_NAN (y);
155                   MPFR_RET_NAN;
156                 }
157               else if (MPFR_IS_ZERO (x))
158                 /* gamma_inc(a,0) = gamma(a) */
159                 return mpfr_gamma (y, a, rnd); /* a=+0->+Inf, a=-0->-Inf */
160               else
161                 {
162                   /* gamma_inc (0, x) = int (exp(-t), t=x..infinity) = E1(x) */
163                   mpfr_t minus_x;
164                   MPFR_TMP_INIT_NEG(minus_x, x);
165                   /* mpfr_eint(x) for x < 0 returns -E1(-x) */
166                   inex = mpfr_eint (y, minus_x, MPFR_INVERT_RND(rnd));
167                   MPFR_CHANGE_SIGN(y);
168                   return -inex;
169                 }
170             }
171           else /* x = 0: gamma_inc(a,0) = gamma(a) */
172             return mpfr_gamma (y, a, rnd);
173         }
174     }
175 
176   /* for x < 0 return NaN */
177   if (MPFR_SIGN(x) < 0)
178     {
179       MPFR_SET_NAN (y);
180       MPFR_RET_NAN;
181     }
182 
183   if (mpfr_integer_p (a) && MPFR_SIGN(a) < 0)
184     return mpfr_gamma_inc_negint (y, a, x, rnd);
185 
186   MPFR_SAVE_EXPO_MARK (expo);
187 
188   w = MPFR_PREC(y) + 13; /* working precision */
189 
190   MPFR_GROUP_INIT_2(group, w, s, t);
191   mpfr_init2 (u, 2); /* u is special (see below) */
192   MPFR_ZIV_INIT (loop, w);
193   for (;;)
194     {
195       mpfr_exp_t expu, precu, exps;
196       mpfr_t s_abs;
197       mpfr_exp_t decay = 0;
198       MPFR_BLOCK_DECL (flags);
199 
200       /* Note: in the error analysis below, theta represents any value of
201          absolute value less than 2^(-w) where w is the working precision (two
202          instances of theta may represent different values), cf Higham's book.
203       */
204 
205       /* to ensure that u = a + k is exact, we have three cases:
206          (1) EXP(a) <= 0, then we need PREC(u) >= 1 - EXP(a) + PREC(a)
207          (2) EXP(a) - PREC(a) <= 0 < E(a), then PREC(u) >= PREC(a)
208          (3) 0 < EXP(a) - PREC(a), then PREC(u) >= EXP(a) */
209       precu = MPFR_GET_EXP(a) <= 0 ?
210         MPFR_ADD_PREC (MPFR_PREC(a), 1 - MPFR_EXP(a))
211         : (MPFR_EXP(a) <= MPFR_PREC(a)) ? MPFR_PREC(a) : MPFR_EXP(a);
212       MPFR_ASSERTD (precu + 1 <= MPFR_PREC_MAX);
213       mpfr_set_prec (u, precu + 1);
214       expu = (MPFR_EXP(a) > 0) ? MPFR_EXP(a) : 1;
215 
216       /* estimate Taylor series */
217       mpfr_ui_div (t, 1, a, MPFR_RNDA); /* t = 1/a * (1 + theta) */
218       mpfr_set (s, t, MPFR_RNDA);       /* s = 1/a * (1 + theta) */
219       if (MPFR_IS_NEG(a))
220         {
221           mpfr_init2 (s_abs, 32);
222           mpfr_abs (s_abs, s, MPFR_RNDU);
223         }
224       for (k = 1;; k++)
225         {
226           mpfr_mul (t, t, x, MPFR_RNDU); /* t = x^k/(a * ... * (a+k-1))
227                                           * (1 + theta)^(2k) */
228           inex = mpfr_add_ui (u, a, k, MPFR_RNDZ); /* u = a+k exactly */
229           MPFR_ASSERTD(inex == 0);
230           mpfr_div (t, t, u, MPFR_RNDA); /* t = x^k/(a * ... * (a+k))
231                                           * (1 + theta)^(2k+1) */
232           mpfr_add (s, s, t, MPFR_RNDZ);
233           /* when s is zero, we consider ulp(s) = ulp(t) */
234           exps = (MPFR_IS_ZERO(s)) ? MPFR_GET_EXP(t) : MPFR_GET_EXP(s);
235           if (MPFR_IS_NEG(a))
236             {
237               if (MPFR_IS_POS(t))
238                 mpfr_add (s_abs, s_abs, t, MPFR_RNDU);
239               else
240                 mpfr_sub (s_abs, s_abs, t, MPFR_RNDU);
241             }
242           /* we stop when |t| < ulp(s), u > 0 and |x/u| < 1/2, which ensures
243              that the tail is at most 2*ulp(s) */
244           MPFR_ASSERTD (MPFR_NOTZERO(t));
245           if (MPFR_GET_EXP(t) + w <= exps && MPFR_IS_POS(u) &&
246               MPFR_GET_EXP(x) + 1 < MPFR_GET_EXP(u))
247             break;
248 
249           /* if there was an exponent shift in u, increase the precision of
250              u so that mpfr_add_ui (u, a, k) remains exact */
251           if (MPFR_EXP(u) > expu) /* exponent shift in u */
252             {
253               MPFR_ASSERTD(MPFR_EXP(u) == expu + 1);
254               expu = MPFR_EXP(u);
255               mpfr_set_prec (u, mpfr_get_prec (u) + 1);
256             }
257         }
258       if (MPFR_IS_NEG(a))
259         {
260           decay = MPFR_GET_EXP(s_abs) - MPFR_GET_EXP(s);
261           mpfr_clear (s_abs);
262         }
263       /* For a > 0, since all terms are positive, we have
264          s = S * (1 + theta)^(2k+3) with S being the infinite Taylor series.
265          For a < 0, the error is bounded by that on the sum s_abs of absolute
266          values of the terms, i.e., S_abs * [(1 + theta)^(2k+3) - 1]. Thus we
267          can simply use the same error analysis as for a > 0, adding an error
268          corresponding to the decay of exponent between s_abs and s. */
269 
270       /* multiply by exp(-x) */
271       mpfr_exp (t, x, MPFR_RNDZ);    /* t = exp(x) * (1+theta) */
272       mpfr_div (s, s, t, MPFR_RNDZ); /* s = <exact value> * (1+theta)^(2k+5) */
273 
274       /* multiply by x^a */
275       mpfr_pow (t, x, a, MPFR_RNDZ); /* t = x^a * (1+theta) */
276       mpfr_mul (s, s, t, MPFR_RNDZ); /* s = Gamma(a,x) * (1+theta)^(2k+7) */
277 
278       /* Since |theta| < 2^(-w) using the Taylor expansion of log(1+x)
279          we have log(1+theta) = theta1 with |theta1| < 1.16*2^(-w) for w >= 2,
280          thus (1+theta)^(2k+7) = exp((2k+7)*theta1).
281          Assuming 2k+7 = t*2^w for |t| < 0.5, we have
282          |(2k+7)*theta1| = |t*2^w*theta1| < 0.58.
283          For |u| < 0.58 we have |exp(u)-1| < 1.36*|u|
284          thus |(1+theta)^(2k+7) - 1| < 1.36*0.58*(2k+7)/2^w < 0.79*(2k+7)/2^w.
285          Since one ulp is at worst a relative error of 2^(1-w),
286          the error on s is at most 2^(decay+1)*(2k+7) ulps. */
287 
288       /* subtract from gamma(a) */
289       MPFR_BLOCK (flags, mpfr_gamma (t, a, MPFR_RNDZ));
290       MPFR_ASSERTN (!MPFR_OVERFLOW (flags));  /* FIXME: support overflow */
291       /* t = gamma(a) * (1+theta) */
292       e0 = MPFR_GET_EXP (t);
293       e1 = (MPFR_IS_ZERO(s)) ? __gmpfr_emin : MPFR_GET_EXP (s);
294       mpfr_sub (s, t, s, MPFR_RNDZ);
295       /* if s is zero, we can assume ulp(s) = ulp(t), but anyway we won't
296          be able to round */
297       e2 = (MPFR_IS_ZERO(s)) ? e0 : MPFR_GET_EXP (s);
298       /* the final error is at most 1 ulp (for the final subtraction)
299          + 2^(e0-e2) ulps # for the error in t
300          + 2^(decay+1)*(2k+7) ulps * 2^(e1-e2) # for the error in gamma(a,x) */
301 
302       e1 += decay + 1 + MPFR_INT_CEIL_LOG2 (2*k+7);
303       /* Now the error is <= 1 + 2^(e0-e2) + 2^(e1-e2).
304          Since the formula is symmetric in e0 and e1, we can assume without
305          loss of generality e0 >= e1, then:
306          if e0 = e1: err <= 1 + 2*2^(e0-e2) <= 2^(e0-e2+2)
307          if e0 > e1: err <= 1 + 1.5*2^(e0-e2)
308                          <= 2^(e0-e2+1) if e0 > e2
309                          <= 2^2 otherwise */
310       if (e0 == e1)
311         {
312           /* Check that e0 - e2 + 2 <= MPFR_EXP_MAX */
313           MPFR_ASSERTD (e2 >= 2 || e0 <= (MPFR_EXP_MAX - 2) + e2);
314           /* Check that e0 - e2 + 2 >= MPFR_EXP_MIN */
315           MPFR_ASSERTD (e2 <= 2 || e0 >= MPFR_EXP_MIN + (e2 - 2));
316           err = e0 - e2 + 2;
317         }
318       else
319         {
320           e0 = (e0 > e1) ? e0 : e1; /* max(e0,e1) */
321           MPFR_ASSERTD (e0 <= e2 || e2 >= 1 || e0 <= (MPFR_EXP_MAX - 1) + e2);
322           err = (e0 > e2) ? e0 - e2 + 1 : 2;
323         }
324 
325       if (MPFR_LIKELY (MPFR_CAN_ROUND (s, w - err, MPFR_PREC(y), rnd)))
326         break;
327 
328       MPFR_ZIV_NEXT (loop, w);
329       MPFR_GROUP_REPREC_2(group, w, s, t);
330     }
331   MPFR_ZIV_FREE (loop);
332   mpfr_clear (u);
333 
334   inex = mpfr_set (y, s, rnd);
335   MPFR_GROUP_CLEAR(group);
336 
337   MPFR_SAVE_EXPO_FREE (expo);
338   return mpfr_check_range (y, inex, rnd);
339 }
340 
341 /* For a negative integer, we have (formula 6.5.19):
342 
343    gamma(-n,x) = (-1)^n/n! [E_1(x) - exp(-x) sum((-1)^j*j!/x^(j+1), j=0..n-1)]
344 
345    See also https://arxiv.org/pdf/1407.0349v1.pdf.
346 
347    Assumes 'a' is a negative integer.
348 */
349 static int
mpfr_gamma_inc_negint(mpfr_ptr y,mpfr_srcptr a,mpfr_srcptr x,mpfr_rnd_t rnd)350 mpfr_gamma_inc_negint (mpfr_ptr y, mpfr_srcptr a, mpfr_srcptr x,
351                        mpfr_rnd_t rnd)
352 {
353   mpfr_t s, t, abs_a, neg_x;
354   unsigned long j;
355   mpfr_prec_t w;
356   int inex;
357   mpfr_exp_t exp_s, new_exp_s, exp_t, err_s, logj;
358   MPFR_GROUP_DECL(group);
359   MPFR_ZIV_DECL(loop);
360   MPFR_SAVE_EXPO_DECL (expo);
361 
362   MPFR_ASSERTD(mpfr_integer_p (a));
363   MPFR_ASSERTD(mpfr_cmp_ui (a, 0) < 0);
364 
365   MPFR_TMP_INIT_ABS(abs_a, a);
366 
367   /* below, theta represents any value such that |theta| <= 2^(-w) */
368 
369   w = MPFR_PREC(y) + 10; /* initial working precision */
370 
371   MPFR_SAVE_EXPO_MARK (expo);
372   MPFR_GROUP_INIT_2(group, w, s, t);
373   MPFR_ZIV_INIT (loop, w);
374   for (;;)
375     {
376       /* we require |a| <= 2^(w-3) for the error analysis below */
377       if (MPFR_GET_EXP(a) + 3 > w)
378         w = MPFR_GET_EXP(a) + 3;
379 
380       mpfr_ui_div (t, 1, x, MPFR_RNDN); /* t = 1/x * (1 + theta) */
381       mpfr_set (s, t, MPFR_RNDN);
382       MPFR_ASSERTD (MPFR_NOTZERO(s));
383       exp_t = exp_s = MPFR_GET_EXP(s); /* max. exponent of s/t during loop */
384       new_exp_s = exp_s;
385 
386       for (j = 1; mpfr_cmp_ui (abs_a, j) > 0; j++)
387         {
388           /* invariant: t = (-1)^(j-1)*(j-1)!/x^j * (1 + theta)^(2j-1) */
389           mpfr_mul_ui (t, t, j, MPFR_RNDN);
390           mpfr_neg (t, t, MPFR_RNDN); /* exact */
391           mpfr_div (t, t, x, MPFR_RNDN);
392           /* now t = (-1)^j*j!/x^(j+1) * (1 + theta)^(2j+1).
393              We have (1 + theta)^(2j+1) = exp((2j+1)*log(1+theta)).
394              For |u| <= 1/2, we have |log(1+u)| <= 1.4 |u| thus:
395              |(1+theta)^(2j+1)-1| <= max |exp(1.4*(2j+1)*u)-1| for |u|<=2^(-w).
396              Now for |v| <= 1/2 we have |exp(v)-1| <= 0.7*|v| thus:
397              |(1+theta)^(2j+1) - 1| <= 2*(2j+1)*2^(-w)
398              as long as 1.4*(2j+1)*2^(-w) <= 1/2, which is true when j<2^(w-3).
399              Since j < |a| it suffices that |a| <= 2^(w-3).
400              In that case the rel. error on t is bounded by 2*(2j+1)*2^(-w),
401              thus the error in ulps is bounded by 2*(2j+1) ulp(t). */
402           if (MPFR_IS_ZERO(t)) /* underflow on t */
403             break;
404           if (MPFR_GET_EXP(t) > exp_t)
405             exp_t = MPFR_GET_EXP(t);
406           mpfr_add (s, s, t, MPFR_RNDN);
407           /* if s is zero, we can assume its ulp is that of t */
408           new_exp_s = (MPFR_IS_ZERO(s)) ? MPFR_GET_EXP(t) : MPFR_GET_EXP(s);
409           if (new_exp_s > exp_s)
410             exp_s = new_exp_s;
411         }
412 
413       /* the error on s is bounded by (j-1) * 2^(exp_s - EXP(s)) * 1/2
414          for the mpfr_add roundings, plus
415          sum(2*(2i+1), i=1..j-1) * 2^(exp_t - EXP(s)) for the error on t.
416          The latter sum is (2*j^2-2) * 2^(exp_t - EXP(s)). */
417 
418       logj = MPFR_INT_CEIL_LOG2(j);
419       exp_s += logj - 1;
420       exp_t += 1 + 2 * logj;
421 
422       /* now the error on s is bounded by 2^(exp_s-EXP(s))+2^(exp_t-EXP(s)) */
423 
424       exp_s = (exp_s >= exp_t) ? exp_s + 1 : exp_t + 1;
425       err_s = exp_s - new_exp_s;
426 
427       /* now the error on the sum S := sum((-1)^j*j!/x^(j+1), j=0..n-1)
428          is bounded by 2^err_s ulp(s) */
429 
430       MPFR_TMP_INIT_NEG(neg_x, x);
431 
432       mpfr_exp (t, neg_x, MPFR_RNDN); /* t = exp(-x) * (1 + theta) */
433       mpfr_mul (s, s, t, MPFR_RNDN);
434       if (MPFR_IS_ZERO(s))
435         {
436           MPFR_ASSERTD (MPFR_NOTZERO(t));
437           new_exp_s += MPFR_GET_EXP(t);
438         }
439       /* s = exp(-x) * (S +/- 2^err_s ulp(S)) * (1 + theta)^2.
440          = exp(-x) * (S +/- 2^err_s ulp(S)) * (1 +/- 3 ulp(1))
441          The error on s is bounded by:
442          exp(-x) * [2^err_s*ulp(S) + S*3*ulp(1) + 2^err_s*ulp(S)*3*ulp(1)]
443          <= ulp(s) * [2^(err_s+1) + 6 + 1]
444          <= ulp(s) * 2^(err_s+2) as long as err_s >= 2. */
445 
446       err_s = (err_s >= 2) ? err_s + 2 : 4;
447       /* now the error on s is bounded by 2^err_s ulp(s) */
448 
449       mpfr_eint (t, neg_x, MPFR_RNDN); /* t = -E1(-x) * (1 + theta) */
450       mpfr_neg (t, t, MPFR_RNDN); /* exact */
451 
452       exp_s = (MPFR_IS_ZERO(s)) ? new_exp_s : MPFR_GET_EXP(s);
453       MPFR_ASSERTD (MPFR_NOTZERO(t));
454       exp_t = MPFR_GET_EXP(t);
455       mpfr_sub (s, t, s, MPFR_RNDN); /* E_1(x) - exp(-x) * S */
456       if (MPFR_IS_ZERO(s)) /* cancellation: increase working precision */
457         goto next_w;
458 
459       /* err(s) <= 1/2 * ulp(s) [mpfr_sub]
460          + 2^err_s * 2^(exp_s-EXP(s)) * ulp(s) [previous error on s]
461          + 1/2 * 2^(exp_t-EXP(s)) * ulp(s) [error on t] */
462 
463       exp_s += err_s;
464       exp_t -= 1;
465       exp_s = (exp_s >= exp_t) ? exp_s + 1 : exp_t + 1;
466       MPFR_ASSERTD (MPFR_NOTZERO(s));
467       err_s = exp_s - MPFR_GET_EXP(s);
468       /* err(s) <= 1/2 * ulp(s) + 2^err_s * ulp(s) */
469 
470       /* divide by n! */
471       mpfr_gamma (t, abs_a, MPFR_RNDN); /* t = (n-1)! * (1 + theta) */
472       mpfr_mul (t, t, abs_a, MPFR_RNDN); /* t = n! * (1 + theta)^2 */
473       mpfr_div (s, s, t, MPFR_RNDN);
474       /* since (1 + theta)^2 converts to an error of at most 3 ulps
475          for w >= 2, the final error is at most:
476          2 * (1/2 + 2^err_s) * ulp(s) [error on previous s]
477          + 2 * 3 * ulp(s)           [error on t]
478          + 1 * ulp(s)                 [product of errors]
479          = ulp(s) * (2^(err_s+1) + 8) */
480       err_s = (err_s >= 2) ? err_s + 1 : 4;
481 
482       /* the final error is bounded by 2^err_s * ulp(s) */
483 
484       /* Is there a better way to compute (-1)^n? */
485       mpfr_set_si (t, -1, MPFR_RNDN);
486       mpfr_pow (t, t, abs_a, MPFR_RNDN);
487       if (MPFR_IS_NEG(t))
488         mpfr_neg (s, s, MPFR_RNDN);
489 
490       if (MPFR_LIKELY (MPFR_CAN_ROUND (s, w - err_s, MPFR_PREC(y), rnd)))
491         break;
492 
493     next_w:
494       MPFR_ZIV_NEXT (loop, w);
495       MPFR_GROUP_REPREC_2(group, w, s, t);
496     }
497   MPFR_ZIV_FREE (loop);
498 
499   inex = mpfr_set (y, s, rnd);
500   MPFR_GROUP_CLEAR(group);
501 
502   MPFR_SAVE_EXPO_FREE (expo);
503   return mpfr_check_range (y, inex, rnd);
504 }
505