14a238c70SJohn Marino /* mpfr_pow_z -- power function x^z with z a MPZ
24a238c70SJohn Marino
3*ab6d115fSJohn Marino Copyright 2005, 2006, 2007, 2008, 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 #define MPFR_NEED_LONGLONG_H
244a238c70SJohn Marino #include "mpfr-impl.h"
254a238c70SJohn Marino
264a238c70SJohn Marino /* y <- x^|z| with z != 0
274a238c70SJohn Marino if cr=1: ensures correct rounding of y
284a238c70SJohn Marino if cr=0: does not ensure correct rounding, but avoid spurious overflow
294a238c70SJohn Marino or underflow, and uses the precision of y as working precision (warning,
304a238c70SJohn Marino y and x might be the same variable). */
314a238c70SJohn Marino static int
mpfr_pow_pos_z(mpfr_ptr y,mpfr_srcptr x,mpz_srcptr z,mpfr_rnd_t rnd,int cr)324a238c70SJohn Marino mpfr_pow_pos_z (mpfr_ptr y, mpfr_srcptr x, mpz_srcptr z, mpfr_rnd_t rnd, int cr)
334a238c70SJohn Marino {
344a238c70SJohn Marino mpfr_t res;
354a238c70SJohn Marino mpfr_prec_t prec, err;
364a238c70SJohn Marino int inexact;
374a238c70SJohn Marino mpfr_rnd_t rnd1, rnd2;
384a238c70SJohn Marino mpz_t absz;
394a238c70SJohn Marino mp_size_t size_z;
404a238c70SJohn Marino MPFR_ZIV_DECL (loop);
414a238c70SJohn Marino MPFR_BLOCK_DECL (flags);
424a238c70SJohn Marino
434a238c70SJohn Marino MPFR_LOG_FUNC
444a238c70SJohn Marino (("x[%Pu]=%.*Rg z=%Zd rnd=%d cr=%d",
454a238c70SJohn Marino mpfr_get_prec (x), mpfr_log_prec, x, z, rnd, cr),
464a238c70SJohn Marino ("y[%Pu]=%.*Rg inexact=%d",
474a238c70SJohn Marino mpfr_get_prec (y), mpfr_log_prec, y, inexact));
484a238c70SJohn Marino
494a238c70SJohn Marino MPFR_ASSERTD (mpz_sgn (z) != 0);
504a238c70SJohn Marino
514a238c70SJohn Marino if (MPFR_UNLIKELY (mpz_cmpabs_ui (z, 1) == 0))
524a238c70SJohn Marino return mpfr_set (y, x, rnd);
534a238c70SJohn Marino
544a238c70SJohn Marino absz[0] = z[0];
554a238c70SJohn Marino SIZ (absz) = ABS(SIZ(absz)); /* Hack to get abs(z) */
564a238c70SJohn Marino MPFR_MPZ_SIZEINBASE2 (size_z, z);
574a238c70SJohn Marino
584a238c70SJohn Marino /* round toward 1 (or -1) to avoid spurious overflow or underflow,
594a238c70SJohn Marino i.e. if an overflow or underflow occurs, it is a real exception
604a238c70SJohn Marino and is not just due to the rounding error. */
614a238c70SJohn Marino rnd1 = (MPFR_EXP(x) >= 1) ? MPFR_RNDZ
624a238c70SJohn Marino : (MPFR_IS_POS(x) ? MPFR_RNDU : MPFR_RNDD);
634a238c70SJohn Marino rnd2 = (MPFR_EXP(x) >= 1) ? MPFR_RNDD : MPFR_RNDU;
644a238c70SJohn Marino
654a238c70SJohn Marino if (cr != 0)
664a238c70SJohn Marino prec = MPFR_PREC (y) + 3 + size_z + MPFR_INT_CEIL_LOG2 (MPFR_PREC (y));
674a238c70SJohn Marino else
684a238c70SJohn Marino prec = MPFR_PREC (y);
694a238c70SJohn Marino mpfr_init2 (res, prec);
704a238c70SJohn Marino
714a238c70SJohn Marino MPFR_ZIV_INIT (loop, prec);
724a238c70SJohn Marino for (;;)
734a238c70SJohn Marino {
744a238c70SJohn Marino unsigned int inexmul; /* will be non-zero if res may be inexact */
754a238c70SJohn Marino mp_size_t i = size_z;
764a238c70SJohn Marino
774a238c70SJohn Marino /* now 2^(i-1) <= z < 2^i */
784a238c70SJohn Marino /* see below (case z < 0) for the error analysis, which is identical,
794a238c70SJohn Marino except if z=n, the maximal relative error is here 2(n-1)2^(-prec)
804a238c70SJohn Marino instead of 2(2n-1)2^(-prec) for z<0. */
814a238c70SJohn Marino MPFR_ASSERTD (prec > (mpfr_prec_t) i);
824a238c70SJohn Marino err = prec - 1 - (mpfr_prec_t) i;
834a238c70SJohn Marino
844a238c70SJohn Marino MPFR_BLOCK (flags,
854a238c70SJohn Marino inexmul = mpfr_mul (res, x, x, rnd2);
864a238c70SJohn Marino MPFR_ASSERTD (i >= 2);
874a238c70SJohn Marino if (mpz_tstbit (absz, i - 2))
884a238c70SJohn Marino inexmul |= mpfr_mul (res, res, x, rnd1);
894a238c70SJohn Marino for (i -= 3; i >= 0 && !MPFR_BLOCK_EXCEP; i--)
904a238c70SJohn Marino {
914a238c70SJohn Marino inexmul |= mpfr_mul (res, res, res, rnd2);
924a238c70SJohn Marino if (mpz_tstbit (absz, i))
934a238c70SJohn Marino inexmul |= mpfr_mul (res, res, x, rnd1);
944a238c70SJohn Marino });
954a238c70SJohn Marino if (MPFR_LIKELY (inexmul == 0 || cr == 0
964a238c70SJohn Marino || MPFR_OVERFLOW (flags) || MPFR_UNDERFLOW (flags)
974a238c70SJohn Marino || MPFR_CAN_ROUND (res, err, MPFR_PREC (y), rnd)))
984a238c70SJohn Marino break;
994a238c70SJohn Marino /* Can't decide correct rounding, increase the precision */
1004a238c70SJohn Marino MPFR_ZIV_NEXT (loop, prec);
1014a238c70SJohn Marino mpfr_set_prec (res, prec);
1024a238c70SJohn Marino }
1034a238c70SJohn Marino MPFR_ZIV_FREE (loop);
1044a238c70SJohn Marino
1054a238c70SJohn Marino /* Check Overflow */
1064a238c70SJohn Marino if (MPFR_OVERFLOW (flags))
1074a238c70SJohn Marino {
1084a238c70SJohn Marino MPFR_LOG_MSG (("overflow\n", 0));
1094a238c70SJohn Marino inexact = mpfr_overflow (y, rnd, mpz_odd_p (absz) ?
1104a238c70SJohn Marino MPFR_SIGN (x) : MPFR_SIGN_POS);
1114a238c70SJohn Marino }
1124a238c70SJohn Marino /* Check Underflow */
1134a238c70SJohn Marino else if (MPFR_UNDERFLOW (flags))
1144a238c70SJohn Marino {
1154a238c70SJohn Marino MPFR_LOG_MSG (("underflow\n", 0));
1164a238c70SJohn Marino if (rnd == MPFR_RNDN)
1174a238c70SJohn Marino {
1184a238c70SJohn Marino mpfr_t y2, zz;
1194a238c70SJohn Marino
1204a238c70SJohn Marino /* We cannot decide now whether the result should be rounded
1214a238c70SJohn Marino toward zero or +Inf. So, let's use the general case of
1224a238c70SJohn Marino mpfr_pow, which can do that. But the problem is that the
1234a238c70SJohn Marino result can be exact! However, it is sufficient to try to
1244a238c70SJohn Marino round on 2 bits (the precision does not matter in case of
1254a238c70SJohn Marino underflow, since MPFR does not have subnormals), in which
1264a238c70SJohn Marino case, the result cannot be exact due to previous filtering
1274a238c70SJohn Marino of trivial cases. */
1284a238c70SJohn Marino MPFR_ASSERTD (mpfr_cmp_si_2exp (x, MPFR_SIGN (x),
1294a238c70SJohn Marino MPFR_EXP (x) - 1) != 0);
1304a238c70SJohn Marino mpfr_init2 (y2, 2);
1314a238c70SJohn Marino mpfr_init2 (zz, ABS (SIZ (z)) * GMP_NUMB_BITS);
1324a238c70SJohn Marino inexact = mpfr_set_z (zz, z, MPFR_RNDN);
1334a238c70SJohn Marino MPFR_ASSERTN (inexact == 0);
1344a238c70SJohn Marino inexact = mpfr_pow_general (y2, x, zz, rnd, 1,
1354a238c70SJohn Marino (mpfr_save_expo_t *) NULL);
1364a238c70SJohn Marino mpfr_clear (zz);
1374a238c70SJohn Marino mpfr_set (y, y2, MPFR_RNDN);
1384a238c70SJohn Marino mpfr_clear (y2);
1394a238c70SJohn Marino __gmpfr_flags = MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW;
1404a238c70SJohn Marino }
1414a238c70SJohn Marino else
1424a238c70SJohn Marino {
1434a238c70SJohn Marino inexact = mpfr_underflow (y, rnd, mpz_odd_p (absz) ?
1444a238c70SJohn Marino MPFR_SIGN (x) : MPFR_SIGN_POS);
1454a238c70SJohn Marino }
1464a238c70SJohn Marino }
1474a238c70SJohn Marino else
1484a238c70SJohn Marino inexact = mpfr_set (y, res, rnd);
1494a238c70SJohn Marino
1504a238c70SJohn Marino mpfr_clear (res);
1514a238c70SJohn Marino return inexact;
1524a238c70SJohn Marino }
1534a238c70SJohn Marino
1544a238c70SJohn Marino /* The computation of y = pow(x,z) is done by
1554a238c70SJohn Marino * y = set_ui(1) if z = 0
1564a238c70SJohn Marino * y = pow_ui(x,z) if z > 0
1574a238c70SJohn Marino * y = pow_ui(1/x,-z) if z < 0
1584a238c70SJohn Marino *
1594a238c70SJohn Marino * Note: in case z < 0, we could also compute 1/pow_ui(x,-z). However, in
1604a238c70SJohn Marino * case MAX < 1/MIN, where MAX is the largest positive value, i.e.,
1614a238c70SJohn Marino * MAX = nextbelow(+Inf), and MIN is the smallest positive value, i.e.,
1624a238c70SJohn Marino * MIN = nextabove(+0), then x^(-z) might produce an overflow, whereas
1634a238c70SJohn Marino * x^z is representable.
1644a238c70SJohn Marino */
1654a238c70SJohn Marino
1664a238c70SJohn Marino int
mpfr_pow_z(mpfr_ptr y,mpfr_srcptr x,mpz_srcptr z,mpfr_rnd_t rnd)1674a238c70SJohn Marino mpfr_pow_z (mpfr_ptr y, mpfr_srcptr x, mpz_srcptr z, mpfr_rnd_t rnd)
1684a238c70SJohn Marino {
1694a238c70SJohn Marino int inexact;
1704a238c70SJohn Marino mpz_t tmp;
1714a238c70SJohn Marino MPFR_SAVE_EXPO_DECL (expo);
1724a238c70SJohn Marino
1734a238c70SJohn Marino MPFR_LOG_FUNC
1744a238c70SJohn Marino (("x[%Pu]=%.*Rg z=%Zd rnd=%d",
1754a238c70SJohn Marino mpfr_get_prec (x), mpfr_log_prec, x, z, rnd),
1764a238c70SJohn Marino ("y[%Pu]=%.*Rg inexact=%d",
1774a238c70SJohn Marino mpfr_get_prec (y), mpfr_log_prec, y, inexact));
1784a238c70SJohn Marino
1794a238c70SJohn Marino /* x^0 = 1 for any x, even a NaN */
1804a238c70SJohn Marino if (MPFR_UNLIKELY (mpz_sgn (z) == 0))
1814a238c70SJohn Marino return mpfr_set_ui (y, 1, rnd);
1824a238c70SJohn Marino
1834a238c70SJohn Marino if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
1844a238c70SJohn Marino {
1854a238c70SJohn Marino if (MPFR_IS_NAN (x))
1864a238c70SJohn Marino {
1874a238c70SJohn Marino MPFR_SET_NAN (y);
1884a238c70SJohn Marino MPFR_RET_NAN;
1894a238c70SJohn Marino }
1904a238c70SJohn Marino else if (MPFR_IS_INF (x))
1914a238c70SJohn Marino {
1924a238c70SJohn Marino /* Inf^n = Inf, (-Inf)^n = Inf for n even, -Inf for n odd */
1934a238c70SJohn Marino /* Inf ^(-n) = 0, sign = + if x>0 or z even */
1944a238c70SJohn Marino if (mpz_sgn (z) > 0)
1954a238c70SJohn Marino MPFR_SET_INF (y);
1964a238c70SJohn Marino else
1974a238c70SJohn Marino MPFR_SET_ZERO (y);
1984a238c70SJohn Marino if (MPFR_UNLIKELY (MPFR_IS_NEG (x) && mpz_odd_p (z)))
1994a238c70SJohn Marino MPFR_SET_NEG (y);
2004a238c70SJohn Marino else
2014a238c70SJohn Marino MPFR_SET_POS (y);
2024a238c70SJohn Marino MPFR_RET (0);
2034a238c70SJohn Marino }
2044a238c70SJohn Marino else /* x is zero */
2054a238c70SJohn Marino {
2064a238c70SJohn Marino MPFR_ASSERTD (MPFR_IS_ZERO(x));
2074a238c70SJohn Marino if (mpz_sgn (z) > 0)
2084a238c70SJohn Marino /* 0^n = +/-0 for any n */
2094a238c70SJohn Marino MPFR_SET_ZERO (y);
2104a238c70SJohn Marino else
2114a238c70SJohn Marino {
2124a238c70SJohn Marino /* 0^(-n) if +/- INF */
2134a238c70SJohn Marino MPFR_SET_INF (y);
2144a238c70SJohn Marino mpfr_set_divby0 ();
2154a238c70SJohn Marino }
2164a238c70SJohn Marino if (MPFR_LIKELY (MPFR_IS_POS (x) || mpz_even_p (z)))
2174a238c70SJohn Marino MPFR_SET_POS (y);
2184a238c70SJohn Marino else
2194a238c70SJohn Marino MPFR_SET_NEG (y);
2204a238c70SJohn Marino MPFR_RET(0);
2214a238c70SJohn Marino }
2224a238c70SJohn Marino }
2234a238c70SJohn Marino
2244a238c70SJohn Marino MPFR_SAVE_EXPO_MARK (expo);
2254a238c70SJohn Marino
2264a238c70SJohn Marino /* detect exact powers: x^-n is exact iff x is a power of 2
2274a238c70SJohn Marino Do it if n > 0 too as this is faster and this filtering is
2284a238c70SJohn Marino needed in case of underflow. */
2294a238c70SJohn Marino if (MPFR_UNLIKELY (mpfr_cmp_si_2exp (x, MPFR_SIGN (x),
2304a238c70SJohn Marino MPFR_EXP (x) - 1) == 0))
2314a238c70SJohn Marino {
2324a238c70SJohn Marino mpfr_exp_t expx = MPFR_EXP (x); /* warning: x and y may be the same
2334a238c70SJohn Marino variable */
2344a238c70SJohn Marino
2354a238c70SJohn Marino MPFR_LOG_MSG (("x^n with x power of two\n", 0));
2364a238c70SJohn Marino mpfr_set_si (y, mpz_odd_p (z) ? MPFR_INT_SIGN(x) : 1, rnd);
2374a238c70SJohn Marino MPFR_ASSERTD (MPFR_IS_FP (y));
2384a238c70SJohn Marino mpz_init (tmp);
2394a238c70SJohn Marino mpz_mul_si (tmp, z, expx - 1);
2404a238c70SJohn Marino MPFR_ASSERTD (MPFR_GET_EXP (y) == 1);
2414a238c70SJohn Marino mpz_add_ui (tmp, tmp, 1);
2424a238c70SJohn Marino inexact = 0;
2434a238c70SJohn Marino if (MPFR_UNLIKELY (mpz_cmp_si (tmp, __gmpfr_emin) < 0))
2444a238c70SJohn Marino {
2454a238c70SJohn Marino MPFR_LOG_MSG (("underflow\n", 0));
2464a238c70SJohn Marino /* |y| is a power of two, thus |y| <= 2^(emin-2), and in
2474a238c70SJohn Marino rounding to nearest, the value must be rounded to 0. */
2484a238c70SJohn Marino if (rnd == MPFR_RNDN)
2494a238c70SJohn Marino rnd = MPFR_RNDZ;
2504a238c70SJohn Marino inexact = mpfr_underflow (y, rnd, MPFR_SIGN (y));
2514a238c70SJohn Marino }
2524a238c70SJohn Marino else if (MPFR_UNLIKELY (mpz_cmp_si (tmp, __gmpfr_emax) > 0))
2534a238c70SJohn Marino {
2544a238c70SJohn Marino MPFR_LOG_MSG (("overflow\n", 0));
2554a238c70SJohn Marino inexact = mpfr_overflow (y, rnd, MPFR_SIGN (y));
2564a238c70SJohn Marino }
2574a238c70SJohn Marino else
2584a238c70SJohn Marino MPFR_SET_EXP (y, mpz_get_si (tmp));
2594a238c70SJohn Marino mpz_clear (tmp);
2604a238c70SJohn Marino MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
2614a238c70SJohn Marino }
2624a238c70SJohn Marino else if (mpz_sgn (z) > 0)
2634a238c70SJohn Marino {
2644a238c70SJohn Marino inexact = mpfr_pow_pos_z (y, x, z, rnd, 1);
2654a238c70SJohn Marino MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
2664a238c70SJohn Marino }
2674a238c70SJohn Marino else
2684a238c70SJohn Marino {
2694a238c70SJohn Marino /* Declaration of the intermediary variable */
2704a238c70SJohn Marino mpfr_t t;
2714a238c70SJohn Marino mpfr_prec_t Nt; /* Precision of the intermediary variable */
2724a238c70SJohn Marino mpfr_rnd_t rnd1;
2734a238c70SJohn Marino mp_size_t size_z;
2744a238c70SJohn Marino MPFR_ZIV_DECL (loop);
2754a238c70SJohn Marino
2764a238c70SJohn Marino MPFR_MPZ_SIZEINBASE2 (size_z, z);
2774a238c70SJohn Marino
2784a238c70SJohn Marino /* initial working precision */
2794a238c70SJohn Marino Nt = MPFR_PREC (y);
2804a238c70SJohn Marino Nt = Nt + size_z + 3 + MPFR_INT_CEIL_LOG2 (Nt);
2814a238c70SJohn Marino /* ensures Nt >= bits(z)+2 */
2824a238c70SJohn Marino
2834a238c70SJohn Marino /* initialise of intermediary variable */
2844a238c70SJohn Marino mpfr_init2 (t, Nt);
2854a238c70SJohn Marino
2864a238c70SJohn Marino /* We will compute rnd(rnd1(1/x) ^ (-z)), where rnd1 is the rounding
2874a238c70SJohn Marino toward sign(x), to avoid spurious overflow or underflow. */
2884a238c70SJohn Marino rnd1 = MPFR_EXP (x) < 1 ? MPFR_RNDZ :
2894a238c70SJohn Marino (MPFR_SIGN (x) > 0 ? MPFR_RNDU : MPFR_RNDD);
2904a238c70SJohn Marino
2914a238c70SJohn Marino MPFR_ZIV_INIT (loop, Nt);
2924a238c70SJohn Marino for (;;)
2934a238c70SJohn Marino {
2944a238c70SJohn Marino MPFR_BLOCK_DECL (flags);
2954a238c70SJohn Marino
2964a238c70SJohn Marino /* compute (1/x)^(-z), -z>0 */
2974a238c70SJohn Marino /* As emin = -emax, an underflow cannot occur in the division.
2984a238c70SJohn Marino And if an overflow occurs, then this means that x^z overflows
2994a238c70SJohn Marino too (since we have rounded toward 1 or -1). */
3004a238c70SJohn Marino MPFR_BLOCK (flags, mpfr_ui_div (t, 1, x, rnd1));
3014a238c70SJohn Marino MPFR_ASSERTD (! MPFR_UNDERFLOW (flags));
3024a238c70SJohn Marino /* t = (1/x)*(1+theta) where |theta| <= 2^(-Nt) */
3034a238c70SJohn Marino if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags)))
3044a238c70SJohn Marino goto overflow;
3054a238c70SJohn Marino MPFR_BLOCK (flags, mpfr_pow_pos_z (t, t, z, rnd, 0));
3064a238c70SJohn Marino /* Now if z=-n, t = x^z*(1+theta)^(2n-1) where |theta| <= 2^(-Nt),
3074a238c70SJohn Marino with theta maybe different from above. If (2n-1)*2^(-Nt) <= 1/2,
3084a238c70SJohn Marino which is satisfied as soon as Nt >= bits(z)+2, then we can use
3094a238c70SJohn Marino Lemma \ref{lemma_graillat} from algorithms.tex, which yields
3104a238c70SJohn Marino t = x^z*(1+theta) with |theta| <= 2(2n-1)*2^(-Nt), thus the
3114a238c70SJohn Marino error is bounded by 2(2n-1) ulps <= 2^(bits(z)+2) ulps. */
3124a238c70SJohn Marino if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags)))
3134a238c70SJohn Marino {
3144a238c70SJohn Marino overflow:
3154a238c70SJohn Marino MPFR_ZIV_FREE (loop);
3164a238c70SJohn Marino mpfr_clear (t);
3174a238c70SJohn Marino MPFR_SAVE_EXPO_FREE (expo);
3184a238c70SJohn Marino MPFR_LOG_MSG (("overflow\n", 0));
3194a238c70SJohn Marino return mpfr_overflow (y, rnd,
3204a238c70SJohn Marino mpz_odd_p (z) ? MPFR_SIGN (x) :
3214a238c70SJohn Marino MPFR_SIGN_POS);
3224a238c70SJohn Marino }
3234a238c70SJohn Marino if (MPFR_UNLIKELY (MPFR_UNDERFLOW (flags)))
3244a238c70SJohn Marino {
3254a238c70SJohn Marino MPFR_ZIV_FREE (loop);
3264a238c70SJohn Marino mpfr_clear (t);
3274a238c70SJohn Marino MPFR_LOG_MSG (("underflow\n", 0));
3284a238c70SJohn Marino if (rnd == MPFR_RNDN)
3294a238c70SJohn Marino {
3304a238c70SJohn Marino mpfr_t y2, zz;
3314a238c70SJohn Marino
3324a238c70SJohn Marino /* We cannot decide now whether the result should be
3334a238c70SJohn Marino rounded toward zero or away from zero. So, like
3344a238c70SJohn Marino in mpfr_pow_pos_z, let's use the general case of
3354a238c70SJohn Marino mpfr_pow in precision 2. */
3364a238c70SJohn Marino MPFR_ASSERTD (mpfr_cmp_si_2exp (x, MPFR_SIGN (x),
3374a238c70SJohn Marino MPFR_EXP (x) - 1) != 0);
3384a238c70SJohn Marino mpfr_init2 (y2, 2);
3394a238c70SJohn Marino mpfr_init2 (zz, ABS (SIZ (z)) * GMP_NUMB_BITS);
3404a238c70SJohn Marino inexact = mpfr_set_z (zz, z, MPFR_RNDN);
3414a238c70SJohn Marino MPFR_ASSERTN (inexact == 0);
3424a238c70SJohn Marino inexact = mpfr_pow_general (y2, x, zz, rnd, 1,
3434a238c70SJohn Marino (mpfr_save_expo_t *) NULL);
3444a238c70SJohn Marino mpfr_clear (zz);
3454a238c70SJohn Marino mpfr_set (y, y2, MPFR_RNDN);
3464a238c70SJohn Marino mpfr_clear (y2);
3474a238c70SJohn Marino MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_UNDERFLOW);
3484a238c70SJohn Marino goto end;
3494a238c70SJohn Marino }
3504a238c70SJohn Marino else
3514a238c70SJohn Marino {
3524a238c70SJohn Marino MPFR_SAVE_EXPO_FREE (expo);
3534a238c70SJohn Marino return mpfr_underflow (y, rnd, mpz_odd_p (z) ?
3544a238c70SJohn Marino MPFR_SIGN (x) : MPFR_SIGN_POS);
3554a238c70SJohn Marino }
3564a238c70SJohn Marino }
3574a238c70SJohn Marino if (MPFR_LIKELY (MPFR_CAN_ROUND (t, Nt - size_z - 2, MPFR_PREC (y),
3584a238c70SJohn Marino rnd)))
3594a238c70SJohn Marino break;
3604a238c70SJohn Marino /* actualisation of the precision */
3614a238c70SJohn Marino MPFR_ZIV_NEXT (loop, Nt);
3624a238c70SJohn Marino mpfr_set_prec (t, Nt);
3634a238c70SJohn Marino }
3644a238c70SJohn Marino MPFR_ZIV_FREE (loop);
3654a238c70SJohn Marino
3664a238c70SJohn Marino inexact = mpfr_set (y, t, rnd);
3674a238c70SJohn Marino mpfr_clear (t);
3684a238c70SJohn Marino }
3694a238c70SJohn Marino
3704a238c70SJohn Marino end:
3714a238c70SJohn Marino MPFR_SAVE_EXPO_FREE (expo);
3724a238c70SJohn Marino return mpfr_check_range (y, inexact, rnd);
3734a238c70SJohn Marino }
374