xref: /dflybsd-src/contrib/mpfr/src/pow.c (revision 2786097444a0124b5d33763854de247e230c6629)
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