xref: /dflybsd-src/contrib/mpfr/src/jn.c (revision 2786097444a0124b5d33763854de247e230c6629)
14a238c70SJohn Marino /* mpfr_j0, mpfr_j1, mpfr_jn -- Bessel functions of 1st kind, integer order.
24a238c70SJohn Marino    http://www.opengroup.org/onlinepubs/009695399/functions/j0.html
34a238c70SJohn Marino 
4*ab6d115fSJohn Marino Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
5*ab6d115fSJohn Marino Contributed by the AriC and Caramel projects, INRIA.
64a238c70SJohn Marino 
74a238c70SJohn Marino This file is part of the GNU MPFR Library.
84a238c70SJohn Marino 
94a238c70SJohn Marino The GNU MPFR Library is free software; you can redistribute it and/or modify
104a238c70SJohn Marino it under the terms of the GNU Lesser General Public License as published by
114a238c70SJohn Marino the Free Software Foundation; either version 3 of the License, or (at your
124a238c70SJohn Marino option) any later version.
134a238c70SJohn Marino 
144a238c70SJohn Marino The GNU MPFR Library is distributed in the hope that it will be useful, but
154a238c70SJohn Marino WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
164a238c70SJohn Marino or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
174a238c70SJohn Marino License for more details.
184a238c70SJohn Marino 
194a238c70SJohn Marino You should have received a copy of the GNU Lesser General Public License
204a238c70SJohn Marino along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
214a238c70SJohn Marino http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
224a238c70SJohn Marino 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
234a238c70SJohn Marino 
244a238c70SJohn Marino #define MPFR_NEED_LONGLONG_H
254a238c70SJohn Marino #include "mpfr-impl.h"
264a238c70SJohn Marino 
274a238c70SJohn Marino /* Relations: j(-n,z) = (-1)^n j(n,z)
284a238c70SJohn Marino               j(n,-z) = (-1)^n j(n,z)
294a238c70SJohn Marino */
304a238c70SJohn Marino 
314a238c70SJohn Marino static int mpfr_jn_asympt (mpfr_ptr, long, mpfr_srcptr, mpfr_rnd_t);
324a238c70SJohn Marino 
334a238c70SJohn Marino int
mpfr_j0(mpfr_ptr res,mpfr_srcptr z,mpfr_rnd_t r)344a238c70SJohn Marino mpfr_j0 (mpfr_ptr res, mpfr_srcptr z, mpfr_rnd_t r)
354a238c70SJohn Marino {
364a238c70SJohn Marino   return mpfr_jn (res, 0, z, r);
374a238c70SJohn Marino }
384a238c70SJohn Marino 
394a238c70SJohn Marino int
mpfr_j1(mpfr_ptr res,mpfr_srcptr z,mpfr_rnd_t r)404a238c70SJohn Marino mpfr_j1 (mpfr_ptr res, mpfr_srcptr z, mpfr_rnd_t r)
414a238c70SJohn Marino {
424a238c70SJohn Marino   return mpfr_jn (res, 1, z, r);
434a238c70SJohn Marino }
444a238c70SJohn Marino 
454a238c70SJohn Marino /* Estimate k1 such that z^2/4 = k1 * (k1 + n)
464a238c70SJohn Marino    i.e., k1 = (sqrt(n^2+z^2)-n)/2 = n/2 * (sqrt(1+(z/n)^2) - 1) if n != 0.
474a238c70SJohn Marino    Return k0 = min(2*k1/log(2), ULONG_MAX).
484a238c70SJohn Marino */
494a238c70SJohn Marino static unsigned long
mpfr_jn_k0(unsigned long n,mpfr_srcptr z)504a238c70SJohn Marino mpfr_jn_k0 (unsigned long n, mpfr_srcptr z)
514a238c70SJohn Marino {
524a238c70SJohn Marino   mpfr_t t, u;
534a238c70SJohn Marino   unsigned long k0;
544a238c70SJohn Marino 
554a238c70SJohn Marino   mpfr_init2 (t, 32);
564a238c70SJohn Marino   mpfr_init2 (u, 32);
574a238c70SJohn Marino   if (n == 0)
584a238c70SJohn Marino     {
594a238c70SJohn Marino       mpfr_abs (t, z, MPFR_RNDN);  /* t = 2*k1 */
604a238c70SJohn Marino     }
614a238c70SJohn Marino   else
624a238c70SJohn Marino     {
634a238c70SJohn Marino       mpfr_div_ui (t, z, n, MPFR_RNDN);
644a238c70SJohn Marino       mpfr_sqr (t, t, MPFR_RNDN);
654a238c70SJohn Marino       mpfr_add_ui (t, t, 1, MPFR_RNDN);
664a238c70SJohn Marino       mpfr_sqrt (t, t, MPFR_RNDN);
674a238c70SJohn Marino       mpfr_sub_ui (t, t, 1, MPFR_RNDN);
684a238c70SJohn Marino       mpfr_mul_ui (t, t, n, MPFR_RNDN);  /* t = 2*k1 */
694a238c70SJohn Marino     }
704a238c70SJohn Marino   /* the following is a 32-bit approximation to nearest to 1/log(2) */
714a238c70SJohn Marino   mpfr_set_str_binary (u, "1.0111000101010100011101100101001");
724a238c70SJohn Marino   mpfr_mul (t, t, u, MPFR_RNDN);
734a238c70SJohn Marino   if (mpfr_fits_ulong_p (t, MPFR_RNDN))
744a238c70SJohn Marino     k0 = mpfr_get_ui (t, MPFR_RNDN);
754a238c70SJohn Marino   else
764a238c70SJohn Marino     k0 = ULONG_MAX;
774a238c70SJohn Marino   mpfr_clear (t);
784a238c70SJohn Marino   mpfr_clear (u);
794a238c70SJohn Marino   return k0;
804a238c70SJohn Marino }
814a238c70SJohn Marino 
824a238c70SJohn Marino int
mpfr_jn(mpfr_ptr res,long n,mpfr_srcptr z,mpfr_rnd_t r)834a238c70SJohn Marino mpfr_jn (mpfr_ptr res, long n, mpfr_srcptr z, mpfr_rnd_t r)
844a238c70SJohn Marino {
854a238c70SJohn Marino   int inex;
864a238c70SJohn Marino   int exception = 0;
874a238c70SJohn Marino   unsigned long absn;
884a238c70SJohn Marino   mpfr_prec_t prec, pbound, err;
894a238c70SJohn Marino   mpfr_uprec_t uprec;
904a238c70SJohn Marino   mpfr_exp_t exps, expT, diffexp;
914a238c70SJohn Marino   mpfr_t y, s, t, absz;
924a238c70SJohn Marino   unsigned long k, zz, k0;
934a238c70SJohn Marino   MPFR_GROUP_DECL(g);
944a238c70SJohn Marino   MPFR_SAVE_EXPO_DECL (expo);
954a238c70SJohn Marino   MPFR_ZIV_DECL (loop);
964a238c70SJohn Marino 
974a238c70SJohn Marino   MPFR_LOG_FUNC
984a238c70SJohn Marino     (("n=%d x[%Pu]=%.*Rg rnd=%d", n, mpfr_get_prec (z), mpfr_log_prec, z, r),
994a238c70SJohn Marino      ("res[%Pu]=%.*Rg inexact=%d",
1004a238c70SJohn Marino       mpfr_get_prec (res), mpfr_log_prec, res, inex));
1014a238c70SJohn Marino 
1024a238c70SJohn Marino   absn = SAFE_ABS (unsigned long, n);
1034a238c70SJohn Marino 
1044a238c70SJohn Marino   if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (z)))
1054a238c70SJohn Marino     {
1064a238c70SJohn Marino       if (MPFR_IS_NAN (z))
1074a238c70SJohn Marino         {
1084a238c70SJohn Marino           MPFR_SET_NAN (res);
1094a238c70SJohn Marino           MPFR_RET_NAN;
1104a238c70SJohn Marino         }
1114a238c70SJohn Marino       /* j(n,z) tends to zero when z goes to +Inf or -Inf, oscillating around
1124a238c70SJohn Marino          0. We choose to return +0 in that case. */
1134a238c70SJohn Marino       else if (MPFR_IS_INF (z)) /* FIXME: according to j(-n,z) = (-1)^n j(n,z)
1144a238c70SJohn Marino                                    we might want to give a sign depending on
1154a238c70SJohn Marino                                    z and n */
1164a238c70SJohn Marino         return mpfr_set_ui (res, 0, r);
1174a238c70SJohn Marino       else /* z=0: j(0,0)=1, j(n odd,+/-0) = +/-0 if n > 0, -/+0 if n < 0,
1184a238c70SJohn Marino               j(n even,+/-0) = +0 */
1194a238c70SJohn Marino         {
1204a238c70SJohn Marino           if (n == 0)
1214a238c70SJohn Marino             return mpfr_set_ui (res, 1, r);
1224a238c70SJohn Marino           else if (absn & 1) /* n odd */
1234a238c70SJohn Marino             return (n > 0) ? mpfr_set (res, z, r) : mpfr_neg (res, z, r);
1244a238c70SJohn Marino           else /* n even */
1254a238c70SJohn Marino             return mpfr_set_ui (res, 0, r);
1264a238c70SJohn Marino         }
1274a238c70SJohn Marino     }
1284a238c70SJohn Marino 
1294a238c70SJohn Marino   MPFR_SAVE_EXPO_MARK (expo);
1304a238c70SJohn Marino 
1314a238c70SJohn Marino   /* check for tiny input for j0: j0(z) = 1 - z^2/4 + ..., more precisely
1324a238c70SJohn Marino      |j0(z) - 1| <= z^2/4 for -1 <= z <= 1. */
1334a238c70SJohn Marino   if (n == 0)
1344a238c70SJohn Marino     MPFR_FAST_COMPUTE_IF_SMALL_INPUT (res, __gmpfr_one, -2 * MPFR_GET_EXP (z),
1354a238c70SJohn Marino                                       2, 0, r, inex = _inexact; goto end);
1364a238c70SJohn Marino 
1374a238c70SJohn Marino   /* idem for j1: j1(z) = z/2 - z^3/16 + ..., more precisely
1384a238c70SJohn Marino      |j1(z) - z/2| <= |z^3|/16 for -1 <= z <= 1, with the sign of j1(z) - z/2
1394a238c70SJohn Marino      being the opposite of that of z. */
1404a238c70SJohn Marino   /* TODO: add a test to trigger an error when
1414a238c70SJohn Marino        inex = _inexact; goto end
1424a238c70SJohn Marino      is forgotten in MPFR_FAST_COMPUTE_IF_SMALL_INPUT below. */
1434a238c70SJohn Marino   if (n == 1)
1444a238c70SJohn Marino     {
1454a238c70SJohn Marino       /* We first compute 2j1(z) = z - z^3/8 + ..., then divide by 2 using
1464a238c70SJohn Marino          the "extra" argument of MPFR_FAST_COMPUTE_IF_SMALL_INPUT. But we
1474a238c70SJohn Marino          must also handle the underflow case (an overflow is not possible
1484a238c70SJohn Marino          for small inputs). If an underflow occurred in mpfr_round_near_x,
1494a238c70SJohn Marino          the rounding was to zero or equivalent, and the result is 0, so
1504a238c70SJohn Marino          that the division by 2 will give the wanted result. Otherwise...
1514a238c70SJohn Marino          The rounded result in unbounded exponent range is res/2. If the
1524a238c70SJohn Marino          division by 2 doesn't underflow, it is exact, and we can return
1534a238c70SJohn Marino          this result. And an underflow in the division is a real underflow.
1544a238c70SJohn Marino          In case of directed rounding mode, the result is correct. But in
1554a238c70SJohn Marino          case of rounding to nearest, there is a double rounding problem,
1564a238c70SJohn Marino          and the result is 0 iff the result before the division is the
1574a238c70SJohn Marino          minimum positive number and _inexact has the same sign as z;
1584a238c70SJohn Marino          but in rounding to nearest, res/2 will yield 0 iff |res| is the
1594a238c70SJohn Marino          minimum positive number, so that we just need to test the result
1604a238c70SJohn Marino          of the division and the sign of _inexact. */
1614a238c70SJohn Marino       mpfr_clear_flags ();
1624a238c70SJohn Marino       MPFR_FAST_COMPUTE_IF_SMALL_INPUT
1634a238c70SJohn Marino         (res, z, -2 * MPFR_GET_EXP (z), 3, 0, r, {
1644a238c70SJohn Marino           int inex2 = mpfr_div_2ui (res, res, 1, r);
1654a238c70SJohn Marino           if (MPFR_UNLIKELY (r == MPFR_RNDN && MPFR_IS_ZERO (res)) &&
1664a238c70SJohn Marino               (MPFR_ASSERTN (inex2 != 0), SIGN (_inexact) != MPFR_SIGN (z)))
1674a238c70SJohn Marino             {
1684a238c70SJohn Marino               mpfr_nexttoinf (res);
1694a238c70SJohn Marino               inex = - inex2;
1704a238c70SJohn Marino             }
1714a238c70SJohn Marino           else
1724a238c70SJohn Marino             inex = inex2 != 0 ? inex2 : _inexact;
1734a238c70SJohn Marino           MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
1744a238c70SJohn Marino           goto end;
1754a238c70SJohn Marino         });
1764a238c70SJohn Marino     }
1774a238c70SJohn Marino 
1784a238c70SJohn Marino   /* we can use the asymptotic expansion as soon as |z| > p log(2)/2,
1794a238c70SJohn Marino      but to get some margin we use it for |z| > p/2 */
1804a238c70SJohn Marino   pbound = MPFR_PREC (res) / 2 + 3;
1814a238c70SJohn Marino   MPFR_ASSERTN (pbound <= ULONG_MAX);
1824a238c70SJohn Marino   MPFR_ALIAS (absz, z, 1, MPFR_EXP (z));
1834a238c70SJohn Marino   if (mpfr_cmp_ui (absz, pbound) > 0)
1844a238c70SJohn Marino     {
1854a238c70SJohn Marino       inex = mpfr_jn_asympt (res, n, z, r);
1864a238c70SJohn Marino       if (inex != 0)
1874a238c70SJohn Marino         goto end;
1884a238c70SJohn Marino     }
1894a238c70SJohn Marino 
1904a238c70SJohn Marino   MPFR_GROUP_INIT_3 (g, 32, y, s, t);
1914a238c70SJohn Marino 
1924a238c70SJohn Marino   /* check underflow case: |j(n,z)| <= 1/sqrt(2 Pi n) (ze/2n)^n
1934a238c70SJohn Marino      (see algorithms.tex) */
1944a238c70SJohn Marino   /* FIXME: the code below doesn't detect all the underflow cases. Either
1954a238c70SJohn Marino      this should be done, or the generic code should detect underflows. */
1964a238c70SJohn Marino   if (absn > 0)
1974a238c70SJohn Marino     {
1984a238c70SJohn Marino       /* the following is an upper 32-bit approximation to exp(1)/2 */
1994a238c70SJohn Marino       mpfr_set_str_binary (y, "1.0101101111110000101010001011001");
2004a238c70SJohn Marino       if (MPFR_SIGN(z) > 0)
2014a238c70SJohn Marino         mpfr_mul (y, y, z, MPFR_RNDU);
2024a238c70SJohn Marino       else
2034a238c70SJohn Marino         {
2044a238c70SJohn Marino           mpfr_mul (y, y, z, MPFR_RNDD);
2054a238c70SJohn Marino           mpfr_neg (y, y, MPFR_RNDU);
2064a238c70SJohn Marino         }
2074a238c70SJohn Marino       mpfr_div_ui (y, y, absn, MPFR_RNDU);
2084a238c70SJohn Marino       /* now y is an upper approximation to |ze/2n|: y < 2^EXP(y),
2094a238c70SJohn Marino          thus |j(n,z)| < 1/2*y^n < 2^(n*EXP(y)-1).
2104a238c70SJohn Marino          If n*EXP(y) < emin then we have an underflow.
2114a238c70SJohn Marino          Note that if emin = MPFR_EMIN_MIN and j = 1, this inequality
2124a238c70SJohn Marino          will never be satisfied.
2134a238c70SJohn Marino          Warning: absn is an unsigned long. */
2144a238c70SJohn Marino       if ((MPFR_GET_EXP (y) < 0 && absn > - expo.saved_emin)
2154a238c70SJohn Marino           || (absn <= - MPFR_EMIN_MIN &&
2164a238c70SJohn Marino               MPFR_GET_EXP (y) < expo.saved_emin / (mpfr_exp_t) absn))
2174a238c70SJohn Marino         {
2184a238c70SJohn Marino           MPFR_GROUP_CLEAR (g);
2194a238c70SJohn Marino           MPFR_SAVE_EXPO_FREE (expo);
2204a238c70SJohn Marino           return mpfr_underflow (res, (r == MPFR_RNDN) ? MPFR_RNDZ : r,
2214a238c70SJohn Marino                          (n % 2) ? ((n > 0) ? MPFR_SIGN(z) : -MPFR_SIGN(z))
2224a238c70SJohn Marino                                  : MPFR_SIGN_POS);
2234a238c70SJohn Marino         }
2244a238c70SJohn Marino     }
2254a238c70SJohn Marino 
2264a238c70SJohn Marino   /* the logarithm of the ratio between the largest term in the series
2274a238c70SJohn Marino      and the first one is roughly bounded by k0, which we add to the
2284a238c70SJohn Marino      working precision to take into account this cancellation */
2294a238c70SJohn Marino   /* The following operations avoid integer overflow and ensure that
2304a238c70SJohn Marino      prec <= MPFR_PREC_MAX (prec = MPFR_PREC_MAX won't prevent an abort,
2314a238c70SJohn Marino      but the failure should be handled cleanly). */
2324a238c70SJohn Marino   k0 = mpfr_jn_k0 (absn, z);
2334a238c70SJohn Marino   MPFR_LOG_MSG (("k0 = %lu\n", k0));
2344a238c70SJohn Marino   uprec = MPFR_PREC_MAX - 2 * MPFR_INT_CEIL_LOG2 (MPFR_PREC_MAX) - 3;
2354a238c70SJohn Marino   if (k0 < uprec)
2364a238c70SJohn Marino     uprec = k0;
2374a238c70SJohn Marino   uprec += MPFR_PREC (res) + 2 * MPFR_INT_CEIL_LOG2 (MPFR_PREC (res)) + 3;
2384a238c70SJohn Marino   prec = uprec < MPFR_PREC_MAX ? (mpfr_prec_t) uprec : MPFR_PREC_MAX;
2394a238c70SJohn Marino 
2404a238c70SJohn Marino   MPFR_ZIV_INIT (loop, prec);
2414a238c70SJohn Marino   for (;;)
2424a238c70SJohn Marino     {
2434a238c70SJohn Marino       MPFR_BLOCK_DECL (flags);
2444a238c70SJohn Marino 
2454a238c70SJohn Marino       MPFR_GROUP_REPREC_3 (g, prec, y, s, t);
2464a238c70SJohn Marino       MPFR_BLOCK (flags, {
2474a238c70SJohn Marino       mpfr_pow_ui (t, z, absn, MPFR_RNDN); /* z^|n| */
2484a238c70SJohn Marino       mpfr_mul (y, z, z, MPFR_RNDN);       /* z^2 */
2494a238c70SJohn Marino       mpfr_clear_erangeflag ();
2504a238c70SJohn Marino       zz = mpfr_get_ui (y, MPFR_RNDU);
2514a238c70SJohn Marino       /* FIXME: The error analysis is incorrect in case of range error. */
2524a238c70SJohn Marino       MPFR_ASSERTN (! mpfr_erangeflag_p ()); /* since mpfr_clear_erangeflag */
2534a238c70SJohn Marino       mpfr_div_2ui (y, y, 2, MPFR_RNDN);   /* z^2/4 */
2544a238c70SJohn Marino       mpfr_fac_ui (s, absn, MPFR_RNDN);    /* |n|! */
2554a238c70SJohn Marino       mpfr_div (t, t, s, MPFR_RNDN);
2564a238c70SJohn Marino       if (absn > 0)
2574a238c70SJohn Marino         mpfr_div_2ui (t, t, absn, MPFR_RNDN);
2584a238c70SJohn Marino       mpfr_set (s, t, MPFR_RNDN);
2594a238c70SJohn Marino       /* note: we assume here that the maximal error bound is proportional to
2604a238c70SJohn Marino          2^exps, which is true also in the case where s=0 */
2614a238c70SJohn Marino       exps = MPFR_IS_ZERO (s) ? MPFR_EMIN_MIN : MPFR_GET_EXP (s);
2624a238c70SJohn Marino       expT = exps;
2634a238c70SJohn Marino       for (k = 1; ; k++)
2644a238c70SJohn Marino         {
2654a238c70SJohn Marino           MPFR_LOG_MSG (("loop on k, k = %lu\n", k));
2664a238c70SJohn Marino           mpfr_mul (t, t, y, MPFR_RNDN);
2674a238c70SJohn Marino           mpfr_neg (t, t, MPFR_RNDN);
2684a238c70SJohn Marino           /* Mathematically: absn <= LONG_MAX + 1 <= (ULONG_MAX + 1) / 2,
2694a238c70SJohn Marino              and in practice, k is not very large, so that one should have
2704a238c70SJohn Marino              k + absn <= ULONG_MAX. */
2714a238c70SJohn Marino           MPFR_ASSERTN (absn <= ULONG_MAX - k);
2724a238c70SJohn Marino           if (k + absn <= ULONG_MAX / k)
2734a238c70SJohn Marino             mpfr_div_ui (t, t, k * (k + absn), MPFR_RNDN);
2744a238c70SJohn Marino           else
2754a238c70SJohn Marino             {
2764a238c70SJohn Marino               mpfr_div_ui (t, t, k, MPFR_RNDN);
2774a238c70SJohn Marino               mpfr_div_ui (t, t, k + absn, MPFR_RNDN);
2784a238c70SJohn Marino             }
2794a238c70SJohn Marino           /* see above note */
2804a238c70SJohn Marino           exps = MPFR_IS_ZERO (s) ? MPFR_EMIN_MIN : MPFR_GET_EXP (t);
2814a238c70SJohn Marino           if (exps > expT)
2824a238c70SJohn Marino             expT = exps;
2834a238c70SJohn Marino           mpfr_add (s, s, t, MPFR_RNDN);
2844a238c70SJohn Marino           exps = MPFR_IS_ZERO (s) ? MPFR_EMIN_MIN : MPFR_GET_EXP (s);
2854a238c70SJohn Marino           if (exps > expT)
2864a238c70SJohn Marino             expT = exps;
2874a238c70SJohn Marino           /* Above it has been checked that k + absn <= ULONG_MAX. */
2884a238c70SJohn Marino           if (MPFR_GET_EXP (t) + (mpfr_exp_t) prec <= exps &&
2894a238c70SJohn Marino               zz / (2 * k) < k + absn)
2904a238c70SJohn Marino             break;
2914a238c70SJohn Marino         }
2924a238c70SJohn Marino       });
2934a238c70SJohn Marino       /* the error is bounded by (4k^2+21/2k+7) ulp(s)*2^(expT-exps)
2944a238c70SJohn Marino          <= (k+2)^2 ulp(s)*2^(2+expT-exps) */
2954a238c70SJohn Marino       diffexp = expT - exps;
2964a238c70SJohn Marino       err = 2 * MPFR_INT_CEIL_LOG2(k + 2) + 2;
2974a238c70SJohn Marino       /* FIXME: Can an overflow occur in the following sum? */
2984a238c70SJohn Marino       MPFR_ASSERTN (diffexp >= 0 && err >= 0 &&
2994a238c70SJohn Marino                     diffexp <= MPFR_PREC_MAX - err);
3004a238c70SJohn Marino       err += diffexp;
3014a238c70SJohn Marino       if (MPFR_LIKELY (MPFR_CAN_ROUND (s, prec - err, MPFR_PREC(res), r)))
3024a238c70SJohn Marino         {
3034a238c70SJohn Marino           if (MPFR_LIKELY (! (MPFR_UNDERFLOW (flags) ||
3044a238c70SJohn Marino                               MPFR_OVERFLOW (flags))))
3054a238c70SJohn Marino             break;
3064a238c70SJohn Marino           /* The error analysis is incorrect in case of exception.
3074a238c70SJohn Marino              If an underflow or overflow occurred, try once more in
3084a238c70SJohn Marino              a larger precision, and if this happens a second time,
3094a238c70SJohn Marino              then abort to avoid a probable infinite loop. This is
3104a238c70SJohn Marino              a problem that must be fixed! */
3114a238c70SJohn Marino           MPFR_ASSERTN (! exception);
3124a238c70SJohn Marino           exception = 1;
3134a238c70SJohn Marino         }
3144a238c70SJohn Marino       MPFR_ZIV_NEXT (loop, prec);
3154a238c70SJohn Marino     }
3164a238c70SJohn Marino   MPFR_ZIV_FREE (loop);
3174a238c70SJohn Marino 
3184a238c70SJohn Marino   inex = ((n >= 0) || ((n & 1) == 0)) ? mpfr_set (res, s, r)
3194a238c70SJohn Marino                                       : mpfr_neg (res, s, r);
3204a238c70SJohn Marino 
3214a238c70SJohn Marino   MPFR_GROUP_CLEAR (g);
3224a238c70SJohn Marino 
3234a238c70SJohn Marino  end:
3244a238c70SJohn Marino   MPFR_SAVE_EXPO_FREE (expo);
3254a238c70SJohn Marino   return mpfr_check_range (res, inex, r);
3264a238c70SJohn Marino }
3274a238c70SJohn Marino 
3284a238c70SJohn Marino #define MPFR_JN
3294a238c70SJohn Marino #include "jyn_asympt.c"
330