(root)/
mpfr-4.2.1/
src/
gamma_inc.c
       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
      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
     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  }