14a238c70SJohn Marino /* mpfr_pow -- power function x^y
24a238c70SJohn Marino
3*ab6d115fSJohn Marino Copyright 2001, 2002, 2003, 2004, 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 /* return non zero iff x^y is exact.
274a238c70SJohn Marino Assumes x and y are ordinary numbers,
284a238c70SJohn Marino y is not an integer, x is not a power of 2 and x is positive
294a238c70SJohn Marino
304a238c70SJohn Marino If x^y is exact, it computes it and sets *inexact.
314a238c70SJohn Marino */
324a238c70SJohn Marino static int
mpfr_pow_is_exact(mpfr_ptr z,mpfr_srcptr x,mpfr_srcptr y,mpfr_rnd_t rnd_mode,int * inexact)334a238c70SJohn Marino mpfr_pow_is_exact (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y,
344a238c70SJohn Marino mpfr_rnd_t rnd_mode, int *inexact)
354a238c70SJohn Marino {
364a238c70SJohn Marino mpz_t a, c;
374a238c70SJohn Marino mpfr_exp_t d, b;
384a238c70SJohn Marino unsigned long i;
394a238c70SJohn Marino int res;
404a238c70SJohn Marino
414a238c70SJohn Marino MPFR_ASSERTD (!MPFR_IS_SINGULAR (y));
424a238c70SJohn Marino MPFR_ASSERTD (!MPFR_IS_SINGULAR (x));
434a238c70SJohn Marino MPFR_ASSERTD (!mpfr_integer_p (y));
444a238c70SJohn Marino MPFR_ASSERTD (mpfr_cmp_si_2exp (x, MPFR_INT_SIGN (x),
454a238c70SJohn Marino MPFR_GET_EXP (x) - 1) != 0);
464a238c70SJohn Marino MPFR_ASSERTD (MPFR_IS_POS (x));
474a238c70SJohn Marino
484a238c70SJohn Marino if (MPFR_IS_NEG (y))
494a238c70SJohn Marino return 0; /* x is not a power of two => x^-y is not exact */
504a238c70SJohn Marino
514a238c70SJohn Marino /* compute d such that y = c*2^d with c odd integer */
524a238c70SJohn Marino mpz_init (c);
534a238c70SJohn Marino d = mpfr_get_z_2exp (c, y);
544a238c70SJohn Marino i = mpz_scan1 (c, 0);
554a238c70SJohn Marino mpz_fdiv_q_2exp (c, c, i);
564a238c70SJohn Marino d += i;
574a238c70SJohn Marino /* now y=c*2^d with c odd */
584a238c70SJohn Marino /* Since y is not an integer, d is necessarily < 0 */
594a238c70SJohn Marino MPFR_ASSERTD (d < 0);
604a238c70SJohn Marino
614a238c70SJohn Marino /* Compute a,b such that x=a*2^b */
624a238c70SJohn Marino mpz_init (a);
634a238c70SJohn Marino b = mpfr_get_z_2exp (a, x);
644a238c70SJohn Marino i = mpz_scan1 (a, 0);
654a238c70SJohn Marino mpz_fdiv_q_2exp (a, a, i);
664a238c70SJohn Marino b += i;
674a238c70SJohn Marino /* now x=a*2^b with a is odd */
684a238c70SJohn Marino
694a238c70SJohn Marino for (res = 1 ; d != 0 ; d++)
704a238c70SJohn Marino {
714a238c70SJohn Marino /* a*2^b is a square iff
724a238c70SJohn Marino (i) a is a square when b is even
734a238c70SJohn Marino (ii) 2*a is a square when b is odd */
744a238c70SJohn Marino if (b % 2 != 0)
754a238c70SJohn Marino {
764a238c70SJohn Marino mpz_mul_2exp (a, a, 1); /* 2*a */
774a238c70SJohn Marino b --;
784a238c70SJohn Marino }
794a238c70SJohn Marino MPFR_ASSERTD ((b % 2) == 0);
804a238c70SJohn Marino if (!mpz_perfect_square_p (a))
814a238c70SJohn Marino {
824a238c70SJohn Marino res = 0;
834a238c70SJohn Marino goto end;
844a238c70SJohn Marino }
854a238c70SJohn Marino mpz_sqrt (a, a);
864a238c70SJohn Marino b = b / 2;
874a238c70SJohn Marino }
884a238c70SJohn Marino /* Now x = (a'*2^b')^(2^-d) with d < 0
894a238c70SJohn Marino so x^y = ((a'*2^b')^(2^-d))^(c*2^d)
904a238c70SJohn Marino = ((a'*2^b')^c with c odd integer */
914a238c70SJohn Marino {
924a238c70SJohn Marino mpfr_t tmp;
934a238c70SJohn Marino mpfr_prec_t p;
944a238c70SJohn Marino MPFR_MPZ_SIZEINBASE2 (p, a);
954a238c70SJohn Marino mpfr_init2 (tmp, p); /* prec = 1 should not be possible */
964a238c70SJohn Marino res = mpfr_set_z (tmp, a, MPFR_RNDN);
974a238c70SJohn Marino MPFR_ASSERTD (res == 0);
984a238c70SJohn Marino res = mpfr_mul_2si (tmp, tmp, b, MPFR_RNDN);
994a238c70SJohn Marino MPFR_ASSERTD (res == 0);
1004a238c70SJohn Marino *inexact = mpfr_pow_z (z, tmp, c, rnd_mode);
1014a238c70SJohn Marino mpfr_clear (tmp);
1024a238c70SJohn Marino res = 1;
1034a238c70SJohn Marino }
1044a238c70SJohn Marino end:
1054a238c70SJohn Marino mpz_clear (a);
1064a238c70SJohn Marino mpz_clear (c);
1074a238c70SJohn Marino return res;
1084a238c70SJohn Marino }
1094a238c70SJohn Marino
1104a238c70SJohn Marino /* Return 1 if y is an odd integer, 0 otherwise. */
1114a238c70SJohn Marino static int
is_odd(mpfr_srcptr y)1124a238c70SJohn Marino is_odd (mpfr_srcptr y)
1134a238c70SJohn Marino {
1144a238c70SJohn Marino mpfr_exp_t expo;
1154a238c70SJohn Marino mpfr_prec_t prec;
1164a238c70SJohn Marino mp_size_t yn;
1174a238c70SJohn Marino mp_limb_t *yp;
1184a238c70SJohn Marino
1194a238c70SJohn Marino /* NAN, INF or ZERO are not allowed */
1204a238c70SJohn Marino MPFR_ASSERTD (!MPFR_IS_SINGULAR (y));
1214a238c70SJohn Marino
1224a238c70SJohn Marino expo = MPFR_GET_EXP (y);
1234a238c70SJohn Marino if (expo <= 0)
1244a238c70SJohn Marino return 0; /* |y| < 1 and not 0 */
1254a238c70SJohn Marino
1264a238c70SJohn Marino prec = MPFR_PREC(y);
1274a238c70SJohn Marino if ((mpfr_prec_t) expo > prec)
1284a238c70SJohn Marino return 0; /* y is a multiple of 2^(expo-prec), thus not odd */
1294a238c70SJohn Marino
1304a238c70SJohn Marino /* 0 < expo <= prec:
1314a238c70SJohn Marino y = 1xxxxxxxxxt.zzzzzzzzzzzzzzzzzz[000]
1324a238c70SJohn Marino expo bits (prec-expo) bits
1334a238c70SJohn Marino
1344a238c70SJohn Marino We have to check that:
1354a238c70SJohn Marino (a) the bit 't' is set
1364a238c70SJohn Marino (b) all the 'z' bits are zero
1374a238c70SJohn Marino */
1384a238c70SJohn Marino
139*ab6d115fSJohn Marino prec = MPFR_PREC2LIMBS (prec) * GMP_NUMB_BITS - expo;
1404a238c70SJohn Marino /* number of z+0 bits */
1414a238c70SJohn Marino
1424a238c70SJohn Marino yn = prec / GMP_NUMB_BITS;
1434a238c70SJohn Marino MPFR_ASSERTN(yn >= 0);
1444a238c70SJohn Marino /* yn is the index of limb containing the 't' bit */
1454a238c70SJohn Marino
1464a238c70SJohn Marino yp = MPFR_MANT(y);
1474a238c70SJohn Marino /* if expo is a multiple of GMP_NUMB_BITS, t is bit 0 */
1484a238c70SJohn Marino if (expo % GMP_NUMB_BITS == 0 ? (yp[yn] & 1) == 0
1494a238c70SJohn Marino : yp[yn] << ((expo % GMP_NUMB_BITS) - 1) != MPFR_LIMB_HIGHBIT)
1504a238c70SJohn Marino return 0;
1514a238c70SJohn Marino while (--yn >= 0)
1524a238c70SJohn Marino if (yp[yn] != 0)
1534a238c70SJohn Marino return 0;
1544a238c70SJohn Marino return 1;
1554a238c70SJohn Marino }
1564a238c70SJohn Marino
1574a238c70SJohn Marino /* Assumes that the exponent range has already been extended and if y is
1584a238c70SJohn Marino an integer, then the result is not exact in unbounded exponent range. */
1594a238c70SJohn Marino int
mpfr_pow_general(mpfr_ptr z,mpfr_srcptr x,mpfr_srcptr y,mpfr_rnd_t rnd_mode,int y_is_integer,mpfr_save_expo_t * expo)1604a238c70SJohn Marino mpfr_pow_general (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y,
1614a238c70SJohn Marino mpfr_rnd_t rnd_mode, int y_is_integer, mpfr_save_expo_t *expo)
1624a238c70SJohn Marino {
1634a238c70SJohn Marino mpfr_t t, u, k, absx;
1644a238c70SJohn Marino int neg_result = 0;
1654a238c70SJohn Marino int k_non_zero = 0;
1664a238c70SJohn Marino int check_exact_case = 0;
1674a238c70SJohn Marino int inexact;
1684a238c70SJohn Marino /* Declaration of the size variable */
1694a238c70SJohn Marino mpfr_prec_t Nz = MPFR_PREC(z); /* target precision */
1704a238c70SJohn Marino mpfr_prec_t Nt; /* working precision */
1714a238c70SJohn Marino mpfr_exp_t err; /* error */
1724a238c70SJohn Marino MPFR_ZIV_DECL (ziv_loop);
1734a238c70SJohn Marino
1744a238c70SJohn Marino
1754a238c70SJohn Marino MPFR_LOG_FUNC
1764a238c70SJohn Marino (("x[%Pu]=%.*Rg y[%Pu]=%.*Rg rnd=%d",
1774a238c70SJohn Marino mpfr_get_prec (x), mpfr_log_prec, x,
1784a238c70SJohn Marino mpfr_get_prec (y), mpfr_log_prec, y, rnd_mode),
1794a238c70SJohn Marino ("z[%Pu]=%.*Rg inexact=%d",
1804a238c70SJohn Marino mpfr_get_prec (z), mpfr_log_prec, z, inexact));
1814a238c70SJohn Marino
1824a238c70SJohn Marino /* We put the absolute value of x in absx, pointing to the significand
1834a238c70SJohn Marino of x to avoid allocating memory for the significand of absx. */
1844a238c70SJohn Marino MPFR_ALIAS(absx, x, /*sign=*/ 1, /*EXP=*/ MPFR_EXP(x));
1854a238c70SJohn Marino
1864a238c70SJohn Marino /* We will compute the absolute value of the result. So, let's
1874a238c70SJohn Marino invert the rounding mode if the result is negative. */
1884a238c70SJohn Marino if (MPFR_IS_NEG (x) && is_odd (y))
1894a238c70SJohn Marino {
1904a238c70SJohn Marino neg_result = 1;
1914a238c70SJohn Marino rnd_mode = MPFR_INVERT_RND (rnd_mode);
1924a238c70SJohn Marino }
1934a238c70SJohn Marino
1944a238c70SJohn Marino /* compute the precision of intermediary variable */
1954a238c70SJohn Marino /* the optimal number of bits : see algorithms.tex */
1964a238c70SJohn Marino Nt = Nz + 5 + MPFR_INT_CEIL_LOG2 (Nz);
1974a238c70SJohn Marino
1984a238c70SJohn Marino /* initialise of intermediary variable */
1994a238c70SJohn Marino mpfr_init2 (t, Nt);
2004a238c70SJohn Marino
2014a238c70SJohn Marino MPFR_ZIV_INIT (ziv_loop, Nt);
2024a238c70SJohn Marino for (;;)
2034a238c70SJohn Marino {
2044a238c70SJohn Marino MPFR_BLOCK_DECL (flags1);
2054a238c70SJohn Marino
2064a238c70SJohn Marino /* compute exp(y*ln|x|), using MPFR_RNDU to get an upper bound, so
2074a238c70SJohn Marino that we can detect underflows. */
2084a238c70SJohn Marino mpfr_log (t, absx, MPFR_IS_NEG (y) ? MPFR_RNDD : MPFR_RNDU); /* ln|x| */
2094a238c70SJohn Marino mpfr_mul (t, y, t, MPFR_RNDU); /* y*ln|x| */
2104a238c70SJohn Marino if (k_non_zero)
2114a238c70SJohn Marino {
2124a238c70SJohn Marino MPFR_LOG_MSG (("subtract k * ln(2)\n", 0));
2134a238c70SJohn Marino mpfr_const_log2 (u, MPFR_RNDD);
2144a238c70SJohn Marino mpfr_mul (u, u, k, MPFR_RNDD);
2154a238c70SJohn Marino /* Error on u = k * log(2): < k * 2^(-Nt) < 1. */
2164a238c70SJohn Marino mpfr_sub (t, t, u, MPFR_RNDU);
2174a238c70SJohn Marino MPFR_LOG_MSG (("t = y * ln|x| - k * ln(2)\n", 0));
2184a238c70SJohn Marino MPFR_LOG_VAR (t);
2194a238c70SJohn Marino }
2204a238c70SJohn Marino /* estimate of the error -- see pow function in algorithms.tex.
2214a238c70SJohn Marino The error on t is at most 1/2 + 3*2^(EXP(t)+1) ulps, which is
2224a238c70SJohn Marino <= 2^(EXP(t)+3) for EXP(t) >= -1, and <= 2 ulps for EXP(t) <= -2.
2234a238c70SJohn Marino Additional error if k_no_zero: treal = t * errk, with
2244a238c70SJohn Marino 1 - |k| * 2^(-Nt) <= exp(-|k| * 2^(-Nt)) <= errk <= 1,
2254a238c70SJohn Marino i.e., additional absolute error <= 2^(EXP(k)+EXP(t)-Nt).
2264a238c70SJohn Marino Total error <= 2^err1 + 2^err2 <= 2^(max(err1,err2)+1). */
2274a238c70SJohn Marino err = MPFR_NOTZERO (t) && MPFR_GET_EXP (t) >= -1 ?
2284a238c70SJohn Marino MPFR_GET_EXP (t) + 3 : 1;
2294a238c70SJohn Marino if (k_non_zero)
2304a238c70SJohn Marino {
2314a238c70SJohn Marino if (MPFR_GET_EXP (k) > err)
2324a238c70SJohn Marino err = MPFR_GET_EXP (k);
2334a238c70SJohn Marino err++;
2344a238c70SJohn Marino }
2354a238c70SJohn Marino MPFR_BLOCK (flags1, mpfr_exp (t, t, MPFR_RNDN)); /* exp(y*ln|x|)*/
2364a238c70SJohn Marino /* We need to test */
2374a238c70SJohn Marino if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (t) || MPFR_UNDERFLOW (flags1)))
2384a238c70SJohn Marino {
2394a238c70SJohn Marino mpfr_prec_t Ntmin;
2404a238c70SJohn Marino MPFR_BLOCK_DECL (flags2);
2414a238c70SJohn Marino
2424a238c70SJohn Marino MPFR_ASSERTN (!k_non_zero);
2434a238c70SJohn Marino MPFR_ASSERTN (!MPFR_IS_NAN (t));
2444a238c70SJohn Marino
2454a238c70SJohn Marino /* Real underflow? */
2464a238c70SJohn Marino if (MPFR_IS_ZERO (t))
2474a238c70SJohn Marino {
2484a238c70SJohn Marino /* Underflow. We computed rndn(exp(t)), where t >= y*ln|x|.
2494a238c70SJohn Marino Therefore rndn(|x|^y) = 0, and we have a real underflow on
2504a238c70SJohn Marino |x|^y. */
2514a238c70SJohn Marino inexact = mpfr_underflow (z, rnd_mode == MPFR_RNDN ? MPFR_RNDZ
2524a238c70SJohn Marino : rnd_mode, MPFR_SIGN_POS);
2534a238c70SJohn Marino if (expo != NULL)
2544a238c70SJohn Marino MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, MPFR_FLAGS_INEXACT
2554a238c70SJohn Marino | MPFR_FLAGS_UNDERFLOW);
2564a238c70SJohn Marino break;
2574a238c70SJohn Marino }
2584a238c70SJohn Marino
2594a238c70SJohn Marino /* Real overflow? */
2604a238c70SJohn Marino if (MPFR_IS_INF (t))
2614a238c70SJohn Marino {
2624a238c70SJohn Marino /* Note: we can probably use a low precision for this test. */
2634a238c70SJohn Marino mpfr_log (t, absx, MPFR_IS_NEG (y) ? MPFR_RNDU : MPFR_RNDD);
2644a238c70SJohn Marino mpfr_mul (t, y, t, MPFR_RNDD); /* y * ln|x| */
2654a238c70SJohn Marino MPFR_BLOCK (flags2, mpfr_exp (t, t, MPFR_RNDD));
2664a238c70SJohn Marino /* t = lower bound on exp(y * ln|x|) */
2674a238c70SJohn Marino if (MPFR_OVERFLOW (flags2))
2684a238c70SJohn Marino {
2694a238c70SJohn Marino /* We have computed a lower bound on |x|^y, and it
2704a238c70SJohn Marino overflowed. Therefore we have a real overflow
2714a238c70SJohn Marino on |x|^y. */
2724a238c70SJohn Marino inexact = mpfr_overflow (z, rnd_mode, MPFR_SIGN_POS);
2734a238c70SJohn Marino if (expo != NULL)
2744a238c70SJohn Marino MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, MPFR_FLAGS_INEXACT
2754a238c70SJohn Marino | MPFR_FLAGS_OVERFLOW);
2764a238c70SJohn Marino break;
2774a238c70SJohn Marino }
2784a238c70SJohn Marino }
2794a238c70SJohn Marino
2804a238c70SJohn Marino k_non_zero = 1;
2814a238c70SJohn Marino Ntmin = sizeof(mpfr_exp_t) * CHAR_BIT;
2824a238c70SJohn Marino if (Ntmin > Nt)
2834a238c70SJohn Marino {
2844a238c70SJohn Marino Nt = Ntmin;
2854a238c70SJohn Marino mpfr_set_prec (t, Nt);
2864a238c70SJohn Marino }
2874a238c70SJohn Marino mpfr_init2 (u, Nt);
2884a238c70SJohn Marino mpfr_init2 (k, Ntmin);
2894a238c70SJohn Marino mpfr_log2 (k, absx, MPFR_RNDN);
2904a238c70SJohn Marino mpfr_mul (k, y, k, MPFR_RNDN);
2914a238c70SJohn Marino mpfr_round (k, k);
2924a238c70SJohn Marino MPFR_LOG_VAR (k);
2934a238c70SJohn Marino /* |y| < 2^Ntmin, therefore |k| < 2^Nt. */
2944a238c70SJohn Marino continue;
2954a238c70SJohn Marino }
2964a238c70SJohn Marino if (MPFR_LIKELY (MPFR_CAN_ROUND (t, Nt - err, Nz, rnd_mode)))
2974a238c70SJohn Marino {
2984a238c70SJohn Marino inexact = mpfr_set (z, t, rnd_mode);
2994a238c70SJohn Marino break;
3004a238c70SJohn Marino }
3014a238c70SJohn Marino
3024a238c70SJohn Marino /* check exact power, except when y is an integer (since the
3034a238c70SJohn Marino exact cases for y integer have already been filtered out) */
3044a238c70SJohn Marino if (check_exact_case == 0 && ! y_is_integer)
3054a238c70SJohn Marino {
3064a238c70SJohn Marino if (mpfr_pow_is_exact (z, absx, y, rnd_mode, &inexact))
3074a238c70SJohn Marino break;
3084a238c70SJohn Marino check_exact_case = 1;
3094a238c70SJohn Marino }
3104a238c70SJohn Marino
3114a238c70SJohn Marino /* reactualisation of the precision */
3124a238c70SJohn Marino MPFR_ZIV_NEXT (ziv_loop, Nt);
3134a238c70SJohn Marino mpfr_set_prec (t, Nt);
3144a238c70SJohn Marino if (k_non_zero)
3154a238c70SJohn Marino mpfr_set_prec (u, Nt);
3164a238c70SJohn Marino }
3174a238c70SJohn Marino MPFR_ZIV_FREE (ziv_loop);
3184a238c70SJohn Marino
3194a238c70SJohn Marino if (k_non_zero)
3204a238c70SJohn Marino {
3214a238c70SJohn Marino int inex2;
3224a238c70SJohn Marino long lk;
3234a238c70SJohn Marino
3244a238c70SJohn Marino /* The rounded result in an unbounded exponent range is z * 2^k. As
3254a238c70SJohn Marino * MPFR chooses underflow after rounding, the mpfr_mul_2si below will
3264a238c70SJohn Marino * correctly detect underflows and overflows. However, in rounding to
3274a238c70SJohn Marino * nearest, if z * 2^k = 2^(emin - 2), then the double rounding may
3284a238c70SJohn Marino * affect the result. We need to cope with that before overwriting z.
3294a238c70SJohn Marino * This can occur only if k < 0 (this test is necessary to avoid a
3304a238c70SJohn Marino * potential integer overflow).
3314a238c70SJohn Marino * If inexact >= 0, then the real result is <= 2^(emin - 2), so that
3324a238c70SJohn Marino * o(2^(emin - 2)) = +0 is correct. If inexact < 0, then the real
3334a238c70SJohn Marino * result is > 2^(emin - 2) and we need to round to 2^(emin - 1).
3344a238c70SJohn Marino */
3354a238c70SJohn Marino MPFR_ASSERTN (MPFR_EXP_MAX <= LONG_MAX);
3364a238c70SJohn Marino lk = mpfr_get_si (k, MPFR_RNDN);
3374a238c70SJohn Marino /* Due to early overflow detection, |k| should not be much larger than
3384a238c70SJohn Marino * MPFR_EMAX_MAX, and as MPFR_EMAX_MAX <= MPFR_EXP_MAX/2 <= LONG_MAX/2,
3394a238c70SJohn Marino * an overflow should not be possible in mpfr_get_si (and lk is exact).
3404a238c70SJohn Marino * And one even has the following assertion. TODO: complete proof.
3414a238c70SJohn Marino */
3424a238c70SJohn Marino MPFR_ASSERTD (lk > LONG_MIN && lk < LONG_MAX);
3434a238c70SJohn Marino /* Note: even in case of overflow (lk inexact), the code is correct.
3444a238c70SJohn Marino * Indeed, for the 3 occurrences of lk:
3454a238c70SJohn Marino * - The test lk < 0 is correct as sign(lk) = sign(k).
3464a238c70SJohn Marino * - In the test MPFR_GET_EXP (z) == __gmpfr_emin - 1 - lk,
3474a238c70SJohn Marino * if lk is inexact, then lk = LONG_MIN <= MPFR_EXP_MIN
3484a238c70SJohn Marino * (the minimum value of the mpfr_exp_t type), and
3494a238c70SJohn Marino * __gmpfr_emin - 1 - lk >= MPFR_EMIN_MIN - 1 - 2 * MPFR_EMIN_MIN
3504a238c70SJohn Marino * >= - MPFR_EMIN_MIN - 1 = MPFR_EMAX_MAX - 1. However, from the
3514a238c70SJohn Marino * choice of k, z has been chosen to be around 1, so that the
3524a238c70SJohn Marino * result of the test is false, as if lk were exact.
3534a238c70SJohn Marino * - In the mpfr_mul_2si (z, z, lk, rnd_mode), if lk is inexact,
3544a238c70SJohn Marino * then |lk| >= LONG_MAX >= MPFR_EXP_MAX, and as z is around 1,
3554a238c70SJohn Marino * mpfr_mul_2si underflows or overflows in the same way as if
3564a238c70SJohn Marino * lk were exact.
3574a238c70SJohn Marino * TODO: give a bound on |t|, then on |EXP(z)|.
3584a238c70SJohn Marino */
3594a238c70SJohn Marino if (rnd_mode == MPFR_RNDN && inexact < 0 && lk < 0 &&
3604a238c70SJohn Marino MPFR_GET_EXP (z) == __gmpfr_emin - 1 - lk && mpfr_powerof2_raw (z))
3614a238c70SJohn Marino {
3624a238c70SJohn Marino /* Rounding to nearest, real result > z * 2^k = 2^(emin - 2),
3634a238c70SJohn Marino * underflow case: as the minimum precision is > 1, we will
3644a238c70SJohn Marino * obtain the correct result and exceptions by replacing z by
3654a238c70SJohn Marino * nextabove(z).
3664a238c70SJohn Marino */
3674a238c70SJohn Marino MPFR_ASSERTN (MPFR_PREC_MIN > 1);
3684a238c70SJohn Marino mpfr_nextabove (z);
3694a238c70SJohn Marino }
3704a238c70SJohn Marino mpfr_clear_flags ();
3714a238c70SJohn Marino inex2 = mpfr_mul_2si (z, z, lk, rnd_mode);
3724a238c70SJohn Marino if (inex2) /* underflow or overflow */
3734a238c70SJohn Marino {
3744a238c70SJohn Marino inexact = inex2;
3754a238c70SJohn Marino if (expo != NULL)
3764a238c70SJohn Marino MPFR_SAVE_EXPO_UPDATE_FLAGS (*expo, __gmpfr_flags);
3774a238c70SJohn Marino }
3784a238c70SJohn Marino mpfr_clears (u, k, (mpfr_ptr) 0);
3794a238c70SJohn Marino }
3804a238c70SJohn Marino mpfr_clear (t);
3814a238c70SJohn Marino
3824a238c70SJohn Marino /* update the sign of the result if x was negative */
3834a238c70SJohn Marino if (neg_result)
3844a238c70SJohn Marino {
3854a238c70SJohn Marino MPFR_SET_NEG(z);
3864a238c70SJohn Marino inexact = -inexact;
3874a238c70SJohn Marino }
3884a238c70SJohn Marino
3894a238c70SJohn Marino return inexact;
3904a238c70SJohn Marino }
3914a238c70SJohn Marino
3924a238c70SJohn Marino /* The computation of z = pow(x,y) is done by
3934a238c70SJohn Marino z = exp(y * log(x)) = x^y
3944a238c70SJohn Marino For the special cases, see Section F.9.4.4 of the C standard:
3954a238c70SJohn Marino _ pow(±0, y) = ±inf for y an odd integer < 0.
3964a238c70SJohn Marino _ pow(±0, y) = +inf for y < 0 and not an odd integer.
3974a238c70SJohn Marino _ pow(±0, y) = ±0 for y an odd integer > 0.
3984a238c70SJohn Marino _ pow(±0, y) = +0 for y > 0 and not an odd integer.
3994a238c70SJohn Marino _ pow(-1, ±inf) = 1.
4004a238c70SJohn Marino _ pow(+1, y) = 1 for any y, even a NaN.
4014a238c70SJohn Marino _ pow(x, ±0) = 1 for any x, even a NaN.
4024a238c70SJohn Marino _ pow(x, y) = NaN for finite x < 0 and finite non-integer y.
4034a238c70SJohn Marino _ pow(x, -inf) = +inf for |x| < 1.
4044a238c70SJohn Marino _ pow(x, -inf) = +0 for |x| > 1.
4054a238c70SJohn Marino _ pow(x, +inf) = +0 for |x| < 1.
4064a238c70SJohn Marino _ pow(x, +inf) = +inf for |x| > 1.
4074a238c70SJohn Marino _ pow(-inf, y) = -0 for y an odd integer < 0.
4084a238c70SJohn Marino _ pow(-inf, y) = +0 for y < 0 and not an odd integer.
4094a238c70SJohn Marino _ pow(-inf, y) = -inf for y an odd integer > 0.
4104a238c70SJohn Marino _ pow(-inf, y) = +inf for y > 0 and not an odd integer.
4114a238c70SJohn Marino _ pow(+inf, y) = +0 for y < 0.
4124a238c70SJohn Marino _ pow(+inf, y) = +inf for y > 0. */
4134a238c70SJohn Marino int
mpfr_pow(mpfr_ptr z,mpfr_srcptr x,mpfr_srcptr y,mpfr_rnd_t rnd_mode)4144a238c70SJohn Marino mpfr_pow (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode)
4154a238c70SJohn Marino {
4164a238c70SJohn Marino int inexact;
4174a238c70SJohn Marino int cmp_x_1;
4184a238c70SJohn Marino int y_is_integer;
4194a238c70SJohn Marino MPFR_SAVE_EXPO_DECL (expo);
4204a238c70SJohn Marino
4214a238c70SJohn Marino MPFR_LOG_FUNC
4224a238c70SJohn Marino (("x[%Pu]=%.*Rg y[%Pu]=%.*Rg rnd=%d",
4234a238c70SJohn Marino mpfr_get_prec (x), mpfr_log_prec, x,
4244a238c70SJohn Marino mpfr_get_prec (y), mpfr_log_prec, y, rnd_mode),
4254a238c70SJohn Marino ("z[%Pu]=%.*Rg inexact=%d",
4264a238c70SJohn Marino mpfr_get_prec (z), mpfr_log_prec, z, inexact));
4274a238c70SJohn Marino
4284a238c70SJohn Marino if (MPFR_ARE_SINGULAR (x, y))
4294a238c70SJohn Marino {
4304a238c70SJohn Marino /* pow(x, 0) returns 1 for any x, even a NaN. */
4314a238c70SJohn Marino if (MPFR_UNLIKELY (MPFR_IS_ZERO (y)))
4324a238c70SJohn Marino return mpfr_set_ui (z, 1, rnd_mode);
4334a238c70SJohn Marino else if (MPFR_IS_NAN (x))
4344a238c70SJohn Marino {
4354a238c70SJohn Marino MPFR_SET_NAN (z);
4364a238c70SJohn Marino MPFR_RET_NAN;
4374a238c70SJohn Marino }
4384a238c70SJohn Marino else if (MPFR_IS_NAN (y))
4394a238c70SJohn Marino {
4404a238c70SJohn Marino /* pow(+1, NaN) returns 1. */
4414a238c70SJohn Marino if (mpfr_cmp_ui (x, 1) == 0)
4424a238c70SJohn Marino return mpfr_set_ui (z, 1, rnd_mode);
4434a238c70SJohn Marino MPFR_SET_NAN (z);
4444a238c70SJohn Marino MPFR_RET_NAN;
4454a238c70SJohn Marino }
4464a238c70SJohn Marino else if (MPFR_IS_INF (y))
4474a238c70SJohn Marino {
4484a238c70SJohn Marino if (MPFR_IS_INF (x))
4494a238c70SJohn Marino {
4504a238c70SJohn Marino if (MPFR_IS_POS (y))
4514a238c70SJohn Marino MPFR_SET_INF (z);
4524a238c70SJohn Marino else
4534a238c70SJohn Marino MPFR_SET_ZERO (z);
4544a238c70SJohn Marino MPFR_SET_POS (z);
4554a238c70SJohn Marino MPFR_RET (0);
4564a238c70SJohn Marino }
4574a238c70SJohn Marino else
4584a238c70SJohn Marino {
4594a238c70SJohn Marino int cmp;
4604a238c70SJohn Marino cmp = mpfr_cmpabs (x, __gmpfr_one) * MPFR_INT_SIGN (y);
4614a238c70SJohn Marino MPFR_SET_POS (z);
4624a238c70SJohn Marino if (cmp > 0)
4634a238c70SJohn Marino {
4644a238c70SJohn Marino /* Return +inf. */
4654a238c70SJohn Marino MPFR_SET_INF (z);
4664a238c70SJohn Marino MPFR_RET (0);
4674a238c70SJohn Marino }
4684a238c70SJohn Marino else if (cmp < 0)
4694a238c70SJohn Marino {
4704a238c70SJohn Marino /* Return +0. */
4714a238c70SJohn Marino MPFR_SET_ZERO (z);
4724a238c70SJohn Marino MPFR_RET (0);
4734a238c70SJohn Marino }
4744a238c70SJohn Marino else
4754a238c70SJohn Marino {
4764a238c70SJohn Marino /* Return 1. */
4774a238c70SJohn Marino return mpfr_set_ui (z, 1, rnd_mode);
4784a238c70SJohn Marino }
4794a238c70SJohn Marino }
4804a238c70SJohn Marino }
4814a238c70SJohn Marino else if (MPFR_IS_INF (x))
4824a238c70SJohn Marino {
4834a238c70SJohn Marino int negative;
4844a238c70SJohn Marino /* Determine the sign now, in case y and z are the same object */
4854a238c70SJohn Marino negative = MPFR_IS_NEG (x) && is_odd (y);
4864a238c70SJohn Marino if (MPFR_IS_POS (y))
4874a238c70SJohn Marino MPFR_SET_INF (z);
4884a238c70SJohn Marino else
4894a238c70SJohn Marino MPFR_SET_ZERO (z);
4904a238c70SJohn Marino if (negative)
4914a238c70SJohn Marino MPFR_SET_NEG (z);
4924a238c70SJohn Marino else
4934a238c70SJohn Marino MPFR_SET_POS (z);
4944a238c70SJohn Marino MPFR_RET (0);
4954a238c70SJohn Marino }
4964a238c70SJohn Marino else
4974a238c70SJohn Marino {
4984a238c70SJohn Marino int negative;
4994a238c70SJohn Marino MPFR_ASSERTD (MPFR_IS_ZERO (x));
5004a238c70SJohn Marino /* Determine the sign now, in case y and z are the same object */
5014a238c70SJohn Marino negative = MPFR_IS_NEG(x) && is_odd (y);
5024a238c70SJohn Marino if (MPFR_IS_NEG (y))
5034a238c70SJohn Marino {
5044a238c70SJohn Marino MPFR_ASSERTD (! MPFR_IS_INF (y));
5054a238c70SJohn Marino MPFR_SET_INF (z);
5064a238c70SJohn Marino mpfr_set_divby0 ();
5074a238c70SJohn Marino }
5084a238c70SJohn Marino else
5094a238c70SJohn Marino MPFR_SET_ZERO (z);
5104a238c70SJohn Marino if (negative)
5114a238c70SJohn Marino MPFR_SET_NEG (z);
5124a238c70SJohn Marino else
5134a238c70SJohn Marino MPFR_SET_POS (z);
5144a238c70SJohn Marino MPFR_RET (0);
5154a238c70SJohn Marino }
5164a238c70SJohn Marino }
5174a238c70SJohn Marino
5184a238c70SJohn Marino /* x^y for x < 0 and y not an integer is not defined */
5194a238c70SJohn Marino y_is_integer = mpfr_integer_p (y);
5204a238c70SJohn Marino if (MPFR_IS_NEG (x) && ! y_is_integer)
5214a238c70SJohn Marino {
5224a238c70SJohn Marino MPFR_SET_NAN (z);
5234a238c70SJohn Marino MPFR_RET_NAN;
5244a238c70SJohn Marino }
5254a238c70SJohn Marino
5264a238c70SJohn Marino /* now the result cannot be NaN:
5274a238c70SJohn Marino (1) either x > 0
5284a238c70SJohn Marino (2) or x < 0 and y is an integer */
5294a238c70SJohn Marino
5304a238c70SJohn Marino cmp_x_1 = mpfr_cmpabs (x, __gmpfr_one);
5314a238c70SJohn Marino if (cmp_x_1 == 0)
5324a238c70SJohn Marino return mpfr_set_si (z, MPFR_IS_NEG (x) && is_odd (y) ? -1 : 1, rnd_mode);
5334a238c70SJohn Marino
5344a238c70SJohn Marino /* now we have:
5354a238c70SJohn Marino (1) either x > 0
5364a238c70SJohn Marino (2) or x < 0 and y is an integer
5374a238c70SJohn Marino and in addition |x| <> 1.
5384a238c70SJohn Marino */
5394a238c70SJohn Marino
5404a238c70SJohn Marino /* detect overflow: an overflow is possible if
5414a238c70SJohn Marino (a) |x| > 1 and y > 0
5424a238c70SJohn Marino (b) |x| < 1 and y < 0.
5434a238c70SJohn Marino FIXME: this assumes 1 is always representable.
5444a238c70SJohn Marino
5454a238c70SJohn Marino FIXME2: maybe we can test overflow and underflow simultaneously.
5464a238c70SJohn Marino The idea is the following: first compute an approximation to
5474a238c70SJohn Marino y * log2|x|, using rounding to nearest. If |x| is not too near from 1,
5484a238c70SJohn Marino this approximation should be accurate enough, and in most cases enable
5494a238c70SJohn Marino one to prove that there is no underflow nor overflow.
5504a238c70SJohn Marino Otherwise, it should enable one to check only underflow or overflow,
5514a238c70SJohn Marino instead of both cases as in the present case.
5524a238c70SJohn Marino */
5534a238c70SJohn Marino if (cmp_x_1 * MPFR_SIGN (y) > 0)
5544a238c70SJohn Marino {
5554a238c70SJohn Marino mpfr_t t;
5564a238c70SJohn Marino int negative, overflow;
5574a238c70SJohn Marino
5584a238c70SJohn Marino MPFR_SAVE_EXPO_MARK (expo);
5594a238c70SJohn Marino mpfr_init2 (t, 53);
5604a238c70SJohn Marino /* we want a lower bound on y*log2|x|:
5614a238c70SJohn Marino (i) if x > 0, it suffices to round log2(x) toward zero, and
5624a238c70SJohn Marino to round y*o(log2(x)) toward zero too;
5634a238c70SJohn Marino (ii) if x < 0, we first compute t = o(-x), with rounding toward 1,
5644a238c70SJohn Marino and then follow as in case (1). */
5654a238c70SJohn Marino if (MPFR_SIGN (x) > 0)
5664a238c70SJohn Marino mpfr_log2 (t, x, MPFR_RNDZ);
5674a238c70SJohn Marino else
5684a238c70SJohn Marino {
5694a238c70SJohn Marino mpfr_neg (t, x, (cmp_x_1 > 0) ? MPFR_RNDZ : MPFR_RNDU);
5704a238c70SJohn Marino mpfr_log2 (t, t, MPFR_RNDZ);
5714a238c70SJohn Marino }
5724a238c70SJohn Marino mpfr_mul (t, t, y, MPFR_RNDZ);
5734a238c70SJohn Marino overflow = mpfr_cmp_si (t, __gmpfr_emax) > 0;
5744a238c70SJohn Marino mpfr_clear (t);
5754a238c70SJohn Marino MPFR_SAVE_EXPO_FREE (expo);
5764a238c70SJohn Marino if (overflow)
5774a238c70SJohn Marino {
5784a238c70SJohn Marino MPFR_LOG_MSG (("early overflow detection\n", 0));
5794a238c70SJohn Marino negative = MPFR_SIGN(x) < 0 && is_odd (y);
5804a238c70SJohn Marino return mpfr_overflow (z, rnd_mode, negative ? -1 : 1);
5814a238c70SJohn Marino }
5824a238c70SJohn Marino }
5834a238c70SJohn Marino
5844a238c70SJohn Marino /* Basic underflow checking. One has:
5854a238c70SJohn Marino * - if y > 0, |x^y| < 2^(EXP(x) * y);
5864a238c70SJohn Marino * - if y < 0, |x^y| <= 2^((EXP(x) - 1) * y);
5874a238c70SJohn Marino * so that one can compute a value ebound such that |x^y| < 2^ebound.
5884a238c70SJohn Marino * If we have ebound <= emin - 2 (emin - 1 in directed rounding modes),
5894a238c70SJohn Marino * then there is an underflow and we can decide the return value.
5904a238c70SJohn Marino */
5914a238c70SJohn Marino if (MPFR_IS_NEG (y) ? (MPFR_GET_EXP (x) > 1) : (MPFR_GET_EXP (x) < 0))
5924a238c70SJohn Marino {
5934a238c70SJohn Marino mpfr_t tmp;
5944a238c70SJohn Marino mpfr_eexp_t ebound;
5954a238c70SJohn Marino int inex2;
5964a238c70SJohn Marino
5974a238c70SJohn Marino /* We must restore the flags. */
5984a238c70SJohn Marino MPFR_SAVE_EXPO_MARK (expo);
5994a238c70SJohn Marino mpfr_init2 (tmp, sizeof (mpfr_exp_t) * CHAR_BIT);
6004a238c70SJohn Marino inex2 = mpfr_set_exp_t (tmp, MPFR_GET_EXP (x), MPFR_RNDN);
6014a238c70SJohn Marino MPFR_ASSERTN (inex2 == 0);
6024a238c70SJohn Marino if (MPFR_IS_NEG (y))
6034a238c70SJohn Marino {
6044a238c70SJohn Marino inex2 = mpfr_sub_ui (tmp, tmp, 1, MPFR_RNDN);
6054a238c70SJohn Marino MPFR_ASSERTN (inex2 == 0);
6064a238c70SJohn Marino }
6074a238c70SJohn Marino mpfr_mul (tmp, tmp, y, MPFR_RNDU);
6084a238c70SJohn Marino if (MPFR_IS_NEG (y))
6094a238c70SJohn Marino mpfr_nextabove (tmp);
6104a238c70SJohn Marino /* tmp doesn't necessarily fit in ebound, but that doesn't matter
6114a238c70SJohn Marino since we get the minimum value in such a case. */
6124a238c70SJohn Marino ebound = mpfr_get_exp_t (tmp, MPFR_RNDU);
6134a238c70SJohn Marino mpfr_clear (tmp);
6144a238c70SJohn Marino MPFR_SAVE_EXPO_FREE (expo);
6154a238c70SJohn Marino if (MPFR_UNLIKELY (ebound <=
6164a238c70SJohn Marino __gmpfr_emin - (rnd_mode == MPFR_RNDN ? 2 : 1)))
6174a238c70SJohn Marino {
6184a238c70SJohn Marino /* warning: mpfr_underflow rounds away from 0 for MPFR_RNDN */
6194a238c70SJohn Marino MPFR_LOG_MSG (("early underflow detection\n", 0));
6204a238c70SJohn Marino return mpfr_underflow (z,
6214a238c70SJohn Marino rnd_mode == MPFR_RNDN ? MPFR_RNDZ : rnd_mode,
6224a238c70SJohn Marino MPFR_SIGN (x) < 0 && is_odd (y) ? -1 : 1);
6234a238c70SJohn Marino }
6244a238c70SJohn Marino }
6254a238c70SJohn Marino
6264a238c70SJohn Marino /* If y is an integer, we can use mpfr_pow_z (based on multiplications),
6274a238c70SJohn Marino but if y is very large (I'm not sure about the best threshold -- VL),
6284a238c70SJohn Marino we shouldn't use it, as it can be very slow and take a lot of memory
6294a238c70SJohn Marino (and even crash or make other programs crash, as several hundred of
6304a238c70SJohn Marino MBs may be necessary). Note that in such a case, either x = +/-2^b
6314a238c70SJohn Marino (this case is handled below) or x^y cannot be represented exactly in
6324a238c70SJohn Marino any precision supported by MPFR (the general case uses this property).
6334a238c70SJohn Marino */
6344a238c70SJohn Marino if (y_is_integer && (MPFR_GET_EXP (y) <= 256))
6354a238c70SJohn Marino {
6364a238c70SJohn Marino mpz_t zi;
6374a238c70SJohn Marino
6384a238c70SJohn Marino MPFR_LOG_MSG (("special code for y not too large integer\n", 0));
6394a238c70SJohn Marino mpz_init (zi);
6404a238c70SJohn Marino mpfr_get_z (zi, y, MPFR_RNDN);
6414a238c70SJohn Marino inexact = mpfr_pow_z (z, x, zi, rnd_mode);
6424a238c70SJohn Marino mpz_clear (zi);
6434a238c70SJohn Marino return inexact;
6444a238c70SJohn Marino }
6454a238c70SJohn Marino
6464a238c70SJohn Marino /* Special case (+/-2^b)^Y which could be exact. If x is negative, then
6474a238c70SJohn Marino necessarily y is a large integer. */
6484a238c70SJohn Marino {
6494a238c70SJohn Marino mpfr_exp_t b = MPFR_GET_EXP (x) - 1;
6504a238c70SJohn Marino
6514a238c70SJohn Marino MPFR_ASSERTN (b >= LONG_MIN && b <= LONG_MAX); /* FIXME... */
6524a238c70SJohn Marino if (mpfr_cmp_si_2exp (x, MPFR_SIGN(x), b) == 0)
6534a238c70SJohn Marino {
6544a238c70SJohn Marino mpfr_t tmp;
6554a238c70SJohn Marino int sgnx = MPFR_SIGN (x);
6564a238c70SJohn Marino
6574a238c70SJohn Marino MPFR_LOG_MSG (("special case (+/-2^b)^Y\n", 0));
6584a238c70SJohn Marino /* now x = +/-2^b, so x^y = (+/-1)^y*2^(b*y) is exact whenever b*y is
6594a238c70SJohn Marino an integer */
6604a238c70SJohn Marino MPFR_SAVE_EXPO_MARK (expo);
6614a238c70SJohn Marino mpfr_init2 (tmp, MPFR_PREC (y) + sizeof (long) * CHAR_BIT);
6624a238c70SJohn Marino inexact = mpfr_mul_si (tmp, y, b, MPFR_RNDN); /* exact */
6634a238c70SJohn Marino MPFR_ASSERTN (inexact == 0);
6644a238c70SJohn Marino /* Note: as the exponent range has been extended, an overflow is not
6654a238c70SJohn Marino possible (due to basic overflow and underflow checking above, as
6664a238c70SJohn Marino the result is ~ 2^tmp), and an underflow is not possible either
6674a238c70SJohn Marino because b is an integer (thus either 0 or >= 1). */
6684a238c70SJohn Marino mpfr_clear_flags ();
6694a238c70SJohn Marino inexact = mpfr_exp2 (z, tmp, rnd_mode);
6704a238c70SJohn Marino mpfr_clear (tmp);
6714a238c70SJohn Marino if (sgnx < 0 && is_odd (y))
6724a238c70SJohn Marino {
6734a238c70SJohn Marino mpfr_neg (z, z, rnd_mode);
6744a238c70SJohn Marino inexact = -inexact;
6754a238c70SJohn Marino }
6764a238c70SJohn Marino /* Without the following, the overflows3 test in tpow.c fails. */
6774a238c70SJohn Marino MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);
6784a238c70SJohn Marino MPFR_SAVE_EXPO_FREE (expo);
6794a238c70SJohn Marino return mpfr_check_range (z, inexact, rnd_mode);
6804a238c70SJohn Marino }
6814a238c70SJohn Marino }
6824a238c70SJohn Marino
6834a238c70SJohn Marino MPFR_SAVE_EXPO_MARK (expo);
6844a238c70SJohn Marino
6854a238c70SJohn Marino /* Case where |y * log(x)| is very small. Warning: x can be negative, in
6864a238c70SJohn Marino that case y is a large integer. */
6874a238c70SJohn Marino {
6884a238c70SJohn Marino mpfr_t t;
6894a238c70SJohn Marino mpfr_exp_t err;
6904a238c70SJohn Marino
6914a238c70SJohn Marino /* We need an upper bound on the exponent of y * log(x). */
6924a238c70SJohn Marino mpfr_init2 (t, 16);
6934a238c70SJohn Marino if (MPFR_IS_POS(x))
6944a238c70SJohn Marino mpfr_log (t, x, cmp_x_1 < 0 ? MPFR_RNDD : MPFR_RNDU); /* away from 0 */
6954a238c70SJohn Marino else
6964a238c70SJohn Marino {
6974a238c70SJohn Marino /* if x < -1, round to +Inf, else round to zero */
6984a238c70SJohn Marino mpfr_neg (t, x, (mpfr_cmp_si (x, -1) < 0) ? MPFR_RNDU : MPFR_RNDD);
6994a238c70SJohn Marino mpfr_log (t, t, (mpfr_cmp_ui (t, 1) < 0) ? MPFR_RNDD : MPFR_RNDU);
7004a238c70SJohn Marino }
7014a238c70SJohn Marino MPFR_ASSERTN (MPFR_IS_PURE_FP (t));
7024a238c70SJohn Marino err = MPFR_GET_EXP (y) + MPFR_GET_EXP (t);
7034a238c70SJohn Marino mpfr_clear (t);
7044a238c70SJohn Marino mpfr_clear_flags ();
7054a238c70SJohn Marino MPFR_SMALL_INPUT_AFTER_SAVE_EXPO (z, __gmpfr_one, - err, 0,
7064a238c70SJohn Marino (MPFR_SIGN (y) > 0) ^ (cmp_x_1 < 0),
7074a238c70SJohn Marino rnd_mode, expo, {});
7084a238c70SJohn Marino }
7094a238c70SJohn Marino
7104a238c70SJohn Marino /* General case */
7114a238c70SJohn Marino inexact = mpfr_pow_general (z, x, y, rnd_mode, y_is_integer, &expo);
7124a238c70SJohn Marino
7134a238c70SJohn Marino MPFR_SAVE_EXPO_FREE (expo);
7144a238c70SJohn Marino return mpfr_check_range (z, inexact, rnd_mode);
7154a238c70SJohn Marino }
716