14a238c70SJohn Marino /* mpfr_digamma -- digamma function of a floating-point number
24a238c70SJohn Marino
3*ab6d115fSJohn Marino Copyright 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 #include "mpfr-impl.h"
244a238c70SJohn Marino
254a238c70SJohn Marino /* Put in s an approximation of digamma(x).
264a238c70SJohn Marino Assumes x >= 2.
274a238c70SJohn Marino Assumes s does not overlap with x.
284a238c70SJohn Marino Returns an integer e such that the error is bounded by 2^e ulps
294a238c70SJohn Marino of the result s.
304a238c70SJohn Marino */
314a238c70SJohn Marino static mpfr_exp_t
mpfr_digamma_approx(mpfr_ptr s,mpfr_srcptr x)324a238c70SJohn Marino mpfr_digamma_approx (mpfr_ptr s, mpfr_srcptr x)
334a238c70SJohn Marino {
344a238c70SJohn Marino mpfr_prec_t p = MPFR_PREC (s);
354a238c70SJohn Marino mpfr_t t, u, invxx;
364a238c70SJohn Marino mpfr_exp_t e, exps, f, expu;
374a238c70SJohn Marino mpz_t *INITIALIZED(B); /* variable B declared as initialized */
384a238c70SJohn Marino unsigned long n0, n; /* number of allocated B[] */
394a238c70SJohn Marino
404a238c70SJohn Marino MPFR_ASSERTN(MPFR_IS_POS(x) && (MPFR_EXP(x) >= 2));
414a238c70SJohn Marino
424a238c70SJohn Marino mpfr_init2 (t, p);
434a238c70SJohn Marino mpfr_init2 (u, p);
444a238c70SJohn Marino mpfr_init2 (invxx, p);
454a238c70SJohn Marino
464a238c70SJohn Marino mpfr_log (s, x, MPFR_RNDN); /* error <= 1/2 ulp */
474a238c70SJohn Marino mpfr_ui_div (t, 1, x, MPFR_RNDN); /* error <= 1/2 ulp */
484a238c70SJohn Marino mpfr_div_2exp (t, t, 1, MPFR_RNDN); /* exact */
494a238c70SJohn Marino mpfr_sub (s, s, t, MPFR_RNDN);
504a238c70SJohn Marino /* error <= 1/2 + 1/2*2^(EXP(olds)-EXP(s)) + 1/2*2^(EXP(t)-EXP(s)).
514a238c70SJohn Marino For x >= 2, log(x) >= 2*(1/(2x)), thus olds >= 2t, and olds - t >= olds/2,
524a238c70SJohn Marino thus 0 <= EXP(olds)-EXP(s) <= 1, and EXP(t)-EXP(s) <= 0, thus
534a238c70SJohn Marino error <= 1/2 + 1/2*2 + 1/2 <= 2 ulps. */
544a238c70SJohn Marino e = 2; /* initial error */
554a238c70SJohn Marino mpfr_mul (invxx, x, x, MPFR_RNDZ); /* invxx = x^2 * (1 + theta)
564a238c70SJohn Marino for |theta| <= 2^(-p) */
574a238c70SJohn Marino mpfr_ui_div (invxx, 1, invxx, MPFR_RNDU); /* invxx = 1/x^2 * (1 + theta)^2 */
584a238c70SJohn Marino
594a238c70SJohn Marino /* in the following we note err=xxx when the ratio between the approximation
604a238c70SJohn Marino and the exact result can be written (1 + theta)^xxx for |theta| <= 2^(-p),
614a238c70SJohn Marino following Higham's method */
624a238c70SJohn Marino B = mpfr_bernoulli_internal ((mpz_t *) 0, 0);
634a238c70SJohn Marino mpfr_set_ui (t, 1, MPFR_RNDN); /* err = 0 */
644a238c70SJohn Marino for (n = 1;; n++)
654a238c70SJohn Marino {
664a238c70SJohn Marino /* compute next Bernoulli number */
674a238c70SJohn Marino B = mpfr_bernoulli_internal (B, n);
684a238c70SJohn Marino /* The main term is Bernoulli[2n]/(2n)/x^(2n) = B[n]/(2n+1)!(2n)/x^(2n)
694a238c70SJohn Marino = B[n]*t[n]/(2n) where t[n]/t[n-1] = 1/(2n)/(2n+1)/x^2. */
704a238c70SJohn Marino mpfr_mul (t, t, invxx, MPFR_RNDU); /* err = err + 3 */
714a238c70SJohn Marino mpfr_div_ui (t, t, 2 * n, MPFR_RNDU); /* err = err + 1 */
724a238c70SJohn Marino mpfr_div_ui (t, t, 2 * n + 1, MPFR_RNDU); /* err = err + 1 */
734a238c70SJohn Marino /* we thus have err = 5n here */
744a238c70SJohn Marino mpfr_div_ui (u, t, 2 * n, MPFR_RNDU); /* err = 5n+1 */
754a238c70SJohn Marino mpfr_mul_z (u, u, B[n], MPFR_RNDU); /* err = 5n+2, and the
764a238c70SJohn Marino absolute error is bounded
774a238c70SJohn Marino by 10n+4 ulp(u) [Rule 11] */
784a238c70SJohn Marino /* if the terms 'u' are decreasing by a factor two at least,
794a238c70SJohn Marino then the error coming from those is bounded by
804a238c70SJohn Marino sum((10n+4)/2^n, n=1..infinity) = 24 */
814a238c70SJohn Marino exps = mpfr_get_exp (s);
824a238c70SJohn Marino expu = mpfr_get_exp (u);
834a238c70SJohn Marino if (expu < exps - (mpfr_exp_t) p)
844a238c70SJohn Marino break;
854a238c70SJohn Marino mpfr_sub (s, s, u, MPFR_RNDN); /* error <= 24 + n/2 */
864a238c70SJohn Marino if (mpfr_get_exp (s) < exps)
874a238c70SJohn Marino e <<= exps - mpfr_get_exp (s);
884a238c70SJohn Marino e ++; /* error in mpfr_sub */
894a238c70SJohn Marino f = 10 * n + 4;
904a238c70SJohn Marino while (expu < exps)
914a238c70SJohn Marino {
924a238c70SJohn Marino f = (1 + f) / 2;
934a238c70SJohn Marino expu ++;
944a238c70SJohn Marino }
954a238c70SJohn Marino e += f; /* total rouding error coming from 'u' term */
964a238c70SJohn Marino }
974a238c70SJohn Marino
984a238c70SJohn Marino n0 = ++n;
994a238c70SJohn Marino while (n--)
1004a238c70SJohn Marino mpz_clear (B[n]);
1014a238c70SJohn Marino (*__gmp_free_func) (B, n0 * sizeof (mpz_t));
1024a238c70SJohn Marino
1034a238c70SJohn Marino mpfr_clear (t);
1044a238c70SJohn Marino mpfr_clear (u);
1054a238c70SJohn Marino mpfr_clear (invxx);
1064a238c70SJohn Marino
1074a238c70SJohn Marino f = 0;
1084a238c70SJohn Marino while (e > 1)
1094a238c70SJohn Marino {
1104a238c70SJohn Marino f++;
1114a238c70SJohn Marino e = (e + 1) / 2;
1124a238c70SJohn Marino /* Invariant: 2^f * e does not decrease */
1134a238c70SJohn Marino }
1144a238c70SJohn Marino return f;
1154a238c70SJohn Marino }
1164a238c70SJohn Marino
1174a238c70SJohn Marino /* Use the reflection formula Digamma(1-x) = Digamma(x) + Pi * cot(Pi*x),
1184a238c70SJohn Marino i.e., Digamma(x) = Digamma(1-x) - Pi * cot(Pi*x).
1194a238c70SJohn Marino Assume x < 1/2. */
1204a238c70SJohn Marino static int
mpfr_digamma_reflection(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd_mode)1214a238c70SJohn Marino mpfr_digamma_reflection (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
1224a238c70SJohn Marino {
1234a238c70SJohn Marino mpfr_prec_t p = MPFR_PREC(y) + 10, q;
1244a238c70SJohn Marino mpfr_t t, u, v;
1254a238c70SJohn Marino mpfr_exp_t e1, expv;
1264a238c70SJohn Marino int inex;
1274a238c70SJohn Marino MPFR_ZIV_DECL (loop);
1284a238c70SJohn Marino
1294a238c70SJohn Marino /* we want that 1-x is exact with precision q: if 0 < x < 1/2, then
1304a238c70SJohn Marino q = PREC(x)-EXP(x) is ok, otherwise if -1 <= x < 0, q = PREC(x)-EXP(x)
1314a238c70SJohn Marino is ok, otherwise for x < -1, PREC(x) is ok if EXP(x) <= PREC(x),
1324a238c70SJohn Marino otherwise we need EXP(x) */
1334a238c70SJohn Marino if (MPFR_EXP(x) < 0)
1344a238c70SJohn Marino q = MPFR_PREC(x) + 1 - MPFR_EXP(x);
1354a238c70SJohn Marino else if (MPFR_EXP(x) <= MPFR_PREC(x))
1364a238c70SJohn Marino q = MPFR_PREC(x) + 1;
1374a238c70SJohn Marino else
1384a238c70SJohn Marino q = MPFR_EXP(x);
1394a238c70SJohn Marino mpfr_init2 (u, q);
1404a238c70SJohn Marino MPFR_ASSERTN(mpfr_ui_sub (u, 1, x, MPFR_RNDN) == 0);
1414a238c70SJohn Marino
1424a238c70SJohn Marino /* if x is half an integer, cot(Pi*x) = 0, thus Digamma(x) = Digamma(1-x) */
1434a238c70SJohn Marino mpfr_mul_2exp (u, u, 1, MPFR_RNDN);
1444a238c70SJohn Marino inex = mpfr_integer_p (u);
1454a238c70SJohn Marino mpfr_div_2exp (u, u, 1, MPFR_RNDN);
1464a238c70SJohn Marino if (inex)
1474a238c70SJohn Marino {
1484a238c70SJohn Marino inex = mpfr_digamma (y, u, rnd_mode);
1494a238c70SJohn Marino goto end;
1504a238c70SJohn Marino }
1514a238c70SJohn Marino
1524a238c70SJohn Marino mpfr_init2 (t, p);
1534a238c70SJohn Marino mpfr_init2 (v, p);
1544a238c70SJohn Marino
1554a238c70SJohn Marino MPFR_ZIV_INIT (loop, p);
1564a238c70SJohn Marino for (;;)
1574a238c70SJohn Marino {
1584a238c70SJohn Marino mpfr_const_pi (v, MPFR_RNDN); /* v = Pi*(1+theta) for |theta|<=2^(-p) */
1594a238c70SJohn Marino mpfr_mul (t, v, x, MPFR_RNDN); /* (1+theta)^2 */
1604a238c70SJohn Marino e1 = MPFR_EXP(t) - (mpfr_exp_t) p + 1; /* bound for t: err(t) <= 2^e1 */
1614a238c70SJohn Marino mpfr_cot (t, t, MPFR_RNDN);
1624a238c70SJohn Marino /* cot(t * (1+h)) = cot(t) - theta * (1 + cot(t)^2) with |theta|<=t*h */
1634a238c70SJohn Marino if (MPFR_EXP(t) > 0)
1644a238c70SJohn Marino e1 = e1 + 2 * MPFR_EXP(t) + 1;
1654a238c70SJohn Marino else
1664a238c70SJohn Marino e1 = e1 + 1;
1674a238c70SJohn Marino /* now theta * (1 + cot(t)^2) <= 2^e1 */
1684a238c70SJohn Marino e1 += (mpfr_exp_t) p - MPFR_EXP(t); /* error is now 2^e1 ulps */
1694a238c70SJohn Marino mpfr_mul (t, t, v, MPFR_RNDN);
1704a238c70SJohn Marino e1 ++;
1714a238c70SJohn Marino mpfr_digamma (v, u, MPFR_RNDN); /* error <= 1/2 ulp */
1724a238c70SJohn Marino expv = MPFR_EXP(v);
1734a238c70SJohn Marino mpfr_sub (v, v, t, MPFR_RNDN);
1744a238c70SJohn Marino if (MPFR_EXP(v) < MPFR_EXP(t))
1754a238c70SJohn Marino e1 += MPFR_EXP(t) - MPFR_EXP(v); /* scale error for t wrt new v */
1764a238c70SJohn Marino /* now take into account the 1/2 ulp error for v */
1774a238c70SJohn Marino if (expv - MPFR_EXP(v) - 1 > e1)
1784a238c70SJohn Marino e1 = expv - MPFR_EXP(v) - 1;
1794a238c70SJohn Marino else
1804a238c70SJohn Marino e1 ++;
1814a238c70SJohn Marino e1 ++; /* rounding error for mpfr_sub */
1824a238c70SJohn Marino if (MPFR_CAN_ROUND (v, p - e1, MPFR_PREC(y), rnd_mode))
1834a238c70SJohn Marino break;
1844a238c70SJohn Marino MPFR_ZIV_NEXT (loop, p);
1854a238c70SJohn Marino mpfr_set_prec (t, p);
1864a238c70SJohn Marino mpfr_set_prec (v, p);
1874a238c70SJohn Marino }
1884a238c70SJohn Marino MPFR_ZIV_FREE (loop);
1894a238c70SJohn Marino
1904a238c70SJohn Marino inex = mpfr_set (y, v, rnd_mode);
1914a238c70SJohn Marino
1924a238c70SJohn Marino mpfr_clear (t);
1934a238c70SJohn Marino mpfr_clear (v);
1944a238c70SJohn Marino end:
1954a238c70SJohn Marino mpfr_clear (u);
1964a238c70SJohn Marino
1974a238c70SJohn Marino return inex;
1984a238c70SJohn Marino }
1994a238c70SJohn Marino
2004a238c70SJohn Marino /* we have x >= 1/2 here */
2014a238c70SJohn Marino static int
mpfr_digamma_positive(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd_mode)2024a238c70SJohn Marino mpfr_digamma_positive (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
2034a238c70SJohn Marino {
2044a238c70SJohn Marino mpfr_prec_t p = MPFR_PREC(y) + 10, q;
2054a238c70SJohn Marino mpfr_t t, u, x_plus_j;
2064a238c70SJohn Marino int inex;
2074a238c70SJohn Marino mpfr_exp_t errt, erru, expt;
2084a238c70SJohn Marino unsigned long j = 0, min;
2094a238c70SJohn Marino MPFR_ZIV_DECL (loop);
2104a238c70SJohn Marino
2114a238c70SJohn Marino /* compute a precision q such that x+1 is exact */
2124a238c70SJohn Marino if (MPFR_PREC(x) < MPFR_EXP(x))
2134a238c70SJohn Marino q = MPFR_EXP(x);
2144a238c70SJohn Marino else
2154a238c70SJohn Marino q = MPFR_PREC(x) + 1;
2164a238c70SJohn Marino mpfr_init2 (x_plus_j, q);
2174a238c70SJohn Marino
2184a238c70SJohn Marino mpfr_init2 (t, p);
2194a238c70SJohn Marino mpfr_init2 (u, p);
2204a238c70SJohn Marino MPFR_ZIV_INIT (loop, p);
2214a238c70SJohn Marino for(;;)
2224a238c70SJohn Marino {
2234a238c70SJohn Marino /* Lower bound for x+j in mpfr_digamma_approx call: since the smallest
2244a238c70SJohn Marino term of the divergent series for Digamma(x) is about exp(-2*Pi*x), and
2254a238c70SJohn Marino we want it to be less than 2^(-p), this gives x > p*log(2)/(2*Pi)
2264a238c70SJohn Marino i.e., x >= 0.1103 p.
2274a238c70SJohn Marino To be safe, we ensure x >= 0.25 * p.
2284a238c70SJohn Marino */
2294a238c70SJohn Marino min = (p + 3) / 4;
2304a238c70SJohn Marino if (min < 2)
2314a238c70SJohn Marino min = 2;
2324a238c70SJohn Marino
2334a238c70SJohn Marino mpfr_set (x_plus_j, x, MPFR_RNDN);
2344a238c70SJohn Marino mpfr_set_ui (u, 0, MPFR_RNDN);
2354a238c70SJohn Marino j = 0;
2364a238c70SJohn Marino while (mpfr_cmp_ui (x_plus_j, min) < 0)
2374a238c70SJohn Marino {
2384a238c70SJohn Marino j ++;
2394a238c70SJohn Marino mpfr_ui_div (t, 1, x_plus_j, MPFR_RNDN); /* err <= 1/2 ulp */
2404a238c70SJohn Marino mpfr_add (u, u, t, MPFR_RNDN);
2414a238c70SJohn Marino inex = mpfr_add_ui (x_plus_j, x_plus_j, 1, MPFR_RNDZ);
2424a238c70SJohn Marino if (inex != 0) /* we lost one bit */
2434a238c70SJohn Marino {
2444a238c70SJohn Marino q ++;
2454a238c70SJohn Marino mpfr_prec_round (x_plus_j, q, MPFR_RNDZ);
2464a238c70SJohn Marino mpfr_nextabove (x_plus_j);
2474a238c70SJohn Marino }
2484a238c70SJohn Marino /* since all terms are positive, the error is bounded by j ulps */
2494a238c70SJohn Marino }
2504a238c70SJohn Marino for (erru = 0; j > 1; erru++, j = (j + 1) / 2);
2514a238c70SJohn Marino errt = mpfr_digamma_approx (t, x_plus_j);
2524a238c70SJohn Marino expt = MPFR_EXP(t);
2534a238c70SJohn Marino mpfr_sub (t, t, u, MPFR_RNDN);
2544a238c70SJohn Marino if (MPFR_EXP(t) < expt)
2554a238c70SJohn Marino errt += expt - MPFR_EXP(t);
2564a238c70SJohn Marino if (MPFR_EXP(t) < MPFR_EXP(u))
2574a238c70SJohn Marino erru += MPFR_EXP(u) - MPFR_EXP(t);
2584a238c70SJohn Marino if (errt > erru)
2594a238c70SJohn Marino errt = errt + 1;
2604a238c70SJohn Marino else if (errt == erru)
2614a238c70SJohn Marino errt = errt + 2;
2624a238c70SJohn Marino else
2634a238c70SJohn Marino errt = erru + 1;
2644a238c70SJohn Marino if (MPFR_CAN_ROUND (t, p - errt, MPFR_PREC(y), rnd_mode))
2654a238c70SJohn Marino break;
2664a238c70SJohn Marino MPFR_ZIV_NEXT (loop, p);
2674a238c70SJohn Marino mpfr_set_prec (t, p);
2684a238c70SJohn Marino mpfr_set_prec (u, p);
2694a238c70SJohn Marino }
2704a238c70SJohn Marino MPFR_ZIV_FREE (loop);
2714a238c70SJohn Marino inex = mpfr_set (y, t, rnd_mode);
2724a238c70SJohn Marino mpfr_clear (t);
2734a238c70SJohn Marino mpfr_clear (u);
2744a238c70SJohn Marino mpfr_clear (x_plus_j);
2754a238c70SJohn Marino return inex;
2764a238c70SJohn Marino }
2774a238c70SJohn Marino
2784a238c70SJohn Marino int
mpfr_digamma(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd_mode)2794a238c70SJohn Marino mpfr_digamma (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
2804a238c70SJohn Marino {
2814a238c70SJohn Marino int inex;
2824a238c70SJohn Marino MPFR_SAVE_EXPO_DECL (expo);
2834a238c70SJohn Marino
2844a238c70SJohn Marino MPFR_LOG_FUNC
2854a238c70SJohn Marino (("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec(x), mpfr_log_prec, x, rnd_mode),
2864a238c70SJohn Marino ("y[%Pu]=%.*Rg inexact=%d", mpfr_get_prec(y), mpfr_log_prec, y, inex));
2874a238c70SJohn Marino
2884a238c70SJohn Marino
2894a238c70SJohn Marino if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(x)))
2904a238c70SJohn Marino {
2914a238c70SJohn Marino if (MPFR_IS_NAN(x))
2924a238c70SJohn Marino {
2934a238c70SJohn Marino MPFR_SET_NAN(y);
2944a238c70SJohn Marino MPFR_RET_NAN;
2954a238c70SJohn Marino }
2964a238c70SJohn Marino else if (MPFR_IS_INF(x))
2974a238c70SJohn Marino {
2984a238c70SJohn Marino if (MPFR_IS_POS(x)) /* Digamma(+Inf) = +Inf */
2994a238c70SJohn Marino {
3004a238c70SJohn Marino MPFR_SET_SAME_SIGN(y, x);
3014a238c70SJohn Marino MPFR_SET_INF(y);
3024a238c70SJohn Marino MPFR_RET(0);
3034a238c70SJohn Marino }
3044a238c70SJohn Marino else /* Digamma(-Inf) = NaN */
3054a238c70SJohn Marino {
3064a238c70SJohn Marino MPFR_SET_NAN(y);
3074a238c70SJohn Marino MPFR_RET_NAN;
3084a238c70SJohn Marino }
3094a238c70SJohn Marino }
3104a238c70SJohn Marino else /* Zero case */
3114a238c70SJohn Marino {
3124a238c70SJohn Marino /* the following works also in case of overlap */
3134a238c70SJohn Marino MPFR_SET_INF(y);
3144a238c70SJohn Marino MPFR_SET_OPPOSITE_SIGN(y, x);
3154a238c70SJohn Marino mpfr_set_divby0 ();
3164a238c70SJohn Marino MPFR_RET(0);
3174a238c70SJohn Marino }
3184a238c70SJohn Marino }
3194a238c70SJohn Marino
3204a238c70SJohn Marino /* Digamma is undefined for negative integers */
3214a238c70SJohn Marino if (MPFR_IS_NEG(x) && mpfr_integer_p (x))
3224a238c70SJohn Marino {
3234a238c70SJohn Marino MPFR_SET_NAN(y);
3244a238c70SJohn Marino MPFR_RET_NAN;
3254a238c70SJohn Marino }
3264a238c70SJohn Marino
3274a238c70SJohn Marino /* now x is a normal number */
3284a238c70SJohn Marino
3294a238c70SJohn Marino MPFR_SAVE_EXPO_MARK (expo);
3304a238c70SJohn Marino /* for x very small, we have Digamma(x) = -1/x - gamma + O(x), more precisely
3314a238c70SJohn Marino -1 < Digamma(x) + 1/x < 0 for -0.2 < x < 0.2, thus:
3324a238c70SJohn Marino (i) either x is a power of two, then 1/x is exactly representable, and
3334a238c70SJohn Marino as long as 1/2*ulp(1/x) > 1, we can conclude;
3344a238c70SJohn Marino (ii) otherwise assume x has <= n bits, and y has <= n+1 bits, then
3354a238c70SJohn Marino |y + 1/x| >= 2^(-2n) ufp(y), where ufp means unit in first place.
3364a238c70SJohn Marino Since |Digamma(x) + 1/x| <= 1, if 2^(-2n) ufp(y) >= 2, then
3374a238c70SJohn Marino |y - Digamma(x)| >= 2^(-2n-1)ufp(y), and rounding -1/x gives the correct result.
3384a238c70SJohn Marino If x < 2^E, then y > 2^(-E), thus ufp(y) > 2^(-E-1).
3394a238c70SJohn Marino A sufficient condition is thus EXP(x) <= -2 MAX(PREC(x),PREC(Y)). */
3404a238c70SJohn Marino if (MPFR_EXP(x) < -2)
3414a238c70SJohn Marino {
3424a238c70SJohn Marino if (MPFR_EXP(x) <= -2 * (mpfr_exp_t) MAX(MPFR_PREC(x), MPFR_PREC(y)))
3434a238c70SJohn Marino {
3444a238c70SJohn Marino int signx = MPFR_SIGN(x);
3454a238c70SJohn Marino inex = mpfr_si_div (y, -1, x, rnd_mode);
3464a238c70SJohn Marino if (inex == 0) /* x is a power of two */
3474a238c70SJohn Marino { /* result always -1/x, except when rounding down */
3484a238c70SJohn Marino if (rnd_mode == MPFR_RNDA)
3494a238c70SJohn Marino rnd_mode = (signx > 0) ? MPFR_RNDD : MPFR_RNDU;
3504a238c70SJohn Marino if (rnd_mode == MPFR_RNDZ)
3514a238c70SJohn Marino rnd_mode = (signx > 0) ? MPFR_RNDU : MPFR_RNDD;
3524a238c70SJohn Marino if (rnd_mode == MPFR_RNDU)
3534a238c70SJohn Marino inex = 1;
3544a238c70SJohn Marino else if (rnd_mode == MPFR_RNDD)
3554a238c70SJohn Marino {
3564a238c70SJohn Marino mpfr_nextbelow (y);
3574a238c70SJohn Marino inex = -1;
3584a238c70SJohn Marino }
3594a238c70SJohn Marino else /* nearest */
3604a238c70SJohn Marino inex = 1;
3614a238c70SJohn Marino }
3624a238c70SJohn Marino MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
3634a238c70SJohn Marino goto end;
3644a238c70SJohn Marino }
3654a238c70SJohn Marino }
3664a238c70SJohn Marino
3674a238c70SJohn Marino if (MPFR_IS_NEG(x))
3684a238c70SJohn Marino inex = mpfr_digamma_reflection (y, x, rnd_mode);
3694a238c70SJohn Marino /* if x < 1/2 we use the reflection formula */
3704a238c70SJohn Marino else if (MPFR_EXP(x) < 0)
3714a238c70SJohn Marino inex = mpfr_digamma_reflection (y, x, rnd_mode);
3724a238c70SJohn Marino else
3734a238c70SJohn Marino inex = mpfr_digamma_positive (y, x, rnd_mode);
3744a238c70SJohn Marino
3754a238c70SJohn Marino end:
3764a238c70SJohn Marino MPFR_SAVE_EXPO_FREE (expo);
3774a238c70SJohn Marino return mpfr_check_range (y, inex, rnd_mode);
3784a238c70SJohn Marino }
379