xref: /freebsd-src/contrib/arm-optimized-routines/math/pow.c (revision f3087bef11543b42e0d69b708f367097a4118d24)
131914882SAlex Richardson /*
231914882SAlex Richardson  * Double-precision x^y function.
331914882SAlex Richardson  *
4*f3087befSAndrew Turner  * Copyright (c) 2018-2024, Arm Limited.
5072a4ba8SAndrew Turner  * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
631914882SAlex Richardson  */
731914882SAlex Richardson 
831914882SAlex Richardson #include <float.h>
931914882SAlex Richardson #include <math.h>
1031914882SAlex Richardson #include <stdint.h>
1131914882SAlex Richardson #include "math_config.h"
12*f3087befSAndrew Turner #include "test_defs.h"
1331914882SAlex Richardson 
1431914882SAlex Richardson /*
1531914882SAlex Richardson Worst-case error: 0.54 ULP (~= ulperr_exp + 1024*Ln2*relerr_log*2^53)
1631914882SAlex Richardson relerr_log: 1.3 * 2^-68 (Relative error of log, 1.5 * 2^-68 without fma)
1731914882SAlex Richardson ulperr_exp: 0.509 ULP (ULP error of exp, 0.511 ULP without fma)
1831914882SAlex Richardson */
1931914882SAlex Richardson 
2031914882SAlex Richardson #define T __pow_log_data.tab
2131914882SAlex Richardson #define A __pow_log_data.poly
2231914882SAlex Richardson #define Ln2hi __pow_log_data.ln2hi
2331914882SAlex Richardson #define Ln2lo __pow_log_data.ln2lo
2431914882SAlex Richardson #define N (1 << POW_LOG_TABLE_BITS)
2531914882SAlex Richardson #define OFF 0x3fe6955500000000
2631914882SAlex Richardson 
2731914882SAlex Richardson /* Top 12 bits of a double (sign and exponent bits).  */
2831914882SAlex Richardson static inline uint32_t
2931914882SAlex Richardson top12 (double x)
3031914882SAlex Richardson {
3131914882SAlex Richardson   return asuint64 (x) >> 52;
3231914882SAlex Richardson }
3331914882SAlex Richardson 
3431914882SAlex Richardson /* Compute y+TAIL = log(x) where the rounded result is y and TAIL has about
3531914882SAlex Richardson    additional 15 bits precision.  IX is the bit representation of x, but
3631914882SAlex Richardson    normalized in the subnormal range using the sign bit for the exponent.  */
3731914882SAlex Richardson static inline double_t
3831914882SAlex Richardson log_inline (uint64_t ix, double_t *tail)
3931914882SAlex Richardson {
4031914882SAlex Richardson   /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
4131914882SAlex Richardson   double_t z, r, y, invc, logc, logctail, kd, hi, t1, t2, lo, lo1, lo2, p;
4231914882SAlex Richardson   uint64_t iz, tmp;
4331914882SAlex Richardson   int k, i;
4431914882SAlex Richardson 
4531914882SAlex Richardson   /* x = 2^k z; where z is in range [OFF,2*OFF) and exact.
4631914882SAlex Richardson      The range is split into N subintervals.
4731914882SAlex Richardson      The ith subinterval contains z and c is near its center.  */
4831914882SAlex Richardson   tmp = ix - OFF;
4931914882SAlex Richardson   i = (tmp >> (52 - POW_LOG_TABLE_BITS)) % N;
5031914882SAlex Richardson   k = (int64_t) tmp >> 52; /* arithmetic shift */
5131914882SAlex Richardson   iz = ix - (tmp & 0xfffULL << 52);
5231914882SAlex Richardson   z = asdouble (iz);
5331914882SAlex Richardson   kd = (double_t) k;
5431914882SAlex Richardson 
5531914882SAlex Richardson   /* log(x) = k*Ln2 + log(c) + log1p(z/c-1).  */
5631914882SAlex Richardson   invc = T[i].invc;
5731914882SAlex Richardson   logc = T[i].logc;
5831914882SAlex Richardson   logctail = T[i].logctail;
5931914882SAlex Richardson 
6031914882SAlex Richardson   /* Note: 1/c is j/N or j/N/2 where j is an integer in [N,2N) and
6131914882SAlex Richardson      |z/c - 1| < 1/N, so r = z/c - 1 is exactly representible.  */
6231914882SAlex Richardson #if HAVE_FAST_FMA
6331914882SAlex Richardson   r = fma (z, invc, -1.0);
6431914882SAlex Richardson #else
6531914882SAlex Richardson   /* Split z such that rhi, rlo and rhi*rhi are exact and |rlo| <= |r|.  */
6631914882SAlex Richardson   double_t zhi = asdouble ((iz + (1ULL << 31)) & (-1ULL << 32));
6731914882SAlex Richardson   double_t zlo = z - zhi;
6831914882SAlex Richardson   double_t rhi = zhi * invc - 1.0;
6931914882SAlex Richardson   double_t rlo = zlo * invc;
7031914882SAlex Richardson   r = rhi + rlo;
7131914882SAlex Richardson #endif
7231914882SAlex Richardson 
7331914882SAlex Richardson   /* k*Ln2 + log(c) + r.  */
7431914882SAlex Richardson   t1 = kd * Ln2hi + logc;
7531914882SAlex Richardson   t2 = t1 + r;
7631914882SAlex Richardson   lo1 = kd * Ln2lo + logctail;
7731914882SAlex Richardson   lo2 = t1 - t2 + r;
7831914882SAlex Richardson 
7931914882SAlex Richardson   /* Evaluation is optimized assuming superscalar pipelined execution.  */
8031914882SAlex Richardson   double_t ar, ar2, ar3, lo3, lo4;
8131914882SAlex Richardson   ar = A[0] * r; /* A[0] = -0.5.  */
8231914882SAlex Richardson   ar2 = r * ar;
8331914882SAlex Richardson   ar3 = r * ar2;
8431914882SAlex Richardson   /* k*Ln2 + log(c) + r + A[0]*r*r.  */
8531914882SAlex Richardson #if HAVE_FAST_FMA
8631914882SAlex Richardson   hi = t2 + ar2;
8731914882SAlex Richardson   lo3 = fma (ar, r, -ar2);
8831914882SAlex Richardson   lo4 = t2 - hi + ar2;
8931914882SAlex Richardson #else
9031914882SAlex Richardson   double_t arhi = A[0] * rhi;
9131914882SAlex Richardson   double_t arhi2 = rhi * arhi;
9231914882SAlex Richardson   hi = t2 + arhi2;
9331914882SAlex Richardson   lo3 = rlo * (ar + arhi);
9431914882SAlex Richardson   lo4 = t2 - hi + arhi2;
9531914882SAlex Richardson #endif
9631914882SAlex Richardson   /* p = log1p(r) - r - A[0]*r*r.  */
9731914882SAlex Richardson #if POW_LOG_POLY_ORDER == 8
9831914882SAlex Richardson   p = (ar3
9931914882SAlex Richardson        * (A[1] + r * A[2] + ar2 * (A[3] + r * A[4] + ar2 * (A[5] + r * A[6]))));
10031914882SAlex Richardson #endif
10131914882SAlex Richardson   lo = lo1 + lo2 + lo3 + lo4 + p;
10231914882SAlex Richardson   y = hi + lo;
10331914882SAlex Richardson   *tail = hi - y + lo;
10431914882SAlex Richardson   return y;
10531914882SAlex Richardson }
10631914882SAlex Richardson 
10731914882SAlex Richardson #undef N
10831914882SAlex Richardson #undef T
10931914882SAlex Richardson #define N (1 << EXP_TABLE_BITS)
11031914882SAlex Richardson #define InvLn2N __exp_data.invln2N
11131914882SAlex Richardson #define NegLn2hiN __exp_data.negln2hiN
11231914882SAlex Richardson #define NegLn2loN __exp_data.negln2loN
11331914882SAlex Richardson #define Shift __exp_data.shift
11431914882SAlex Richardson #define T __exp_data.tab
11531914882SAlex Richardson #define C2 __exp_data.poly[5 - EXP_POLY_ORDER]
11631914882SAlex Richardson #define C3 __exp_data.poly[6 - EXP_POLY_ORDER]
11731914882SAlex Richardson #define C4 __exp_data.poly[7 - EXP_POLY_ORDER]
11831914882SAlex Richardson #define C5 __exp_data.poly[8 - EXP_POLY_ORDER]
11931914882SAlex Richardson #define C6 __exp_data.poly[9 - EXP_POLY_ORDER]
12031914882SAlex Richardson 
12131914882SAlex Richardson /* Handle cases that may overflow or underflow when computing the result that
12231914882SAlex Richardson    is scale*(1+TMP) without intermediate rounding.  The bit representation of
12331914882SAlex Richardson    scale is in SBITS, however it has a computed exponent that may have
12431914882SAlex Richardson    overflown into the sign bit so that needs to be adjusted before using it as
12531914882SAlex Richardson    a double.  (int32_t)KI is the k used in the argument reduction and exponent
12631914882SAlex Richardson    adjustment of scale, positive k here means the result may overflow and
12731914882SAlex Richardson    negative k means the result may underflow.  */
12831914882SAlex Richardson static inline double
12931914882SAlex Richardson specialcase (double_t tmp, uint64_t sbits, uint64_t ki)
13031914882SAlex Richardson {
13131914882SAlex Richardson   double_t scale, y;
13231914882SAlex Richardson 
13331914882SAlex Richardson   if ((ki & 0x80000000) == 0)
13431914882SAlex Richardson     {
13531914882SAlex Richardson       /* k > 0, the exponent of scale might have overflowed by <= 460.  */
13631914882SAlex Richardson       sbits -= 1009ull << 52;
13731914882SAlex Richardson       scale = asdouble (sbits);
13831914882SAlex Richardson       y = 0x1p1009 * (scale + scale * tmp);
13931914882SAlex Richardson       return check_oflow (eval_as_double (y));
14031914882SAlex Richardson     }
14131914882SAlex Richardson   /* k < 0, need special care in the subnormal range.  */
14231914882SAlex Richardson   sbits += 1022ull << 52;
14331914882SAlex Richardson   /* Note: sbits is signed scale.  */
14431914882SAlex Richardson   scale = asdouble (sbits);
14531914882SAlex Richardson   y = scale + scale * tmp;
14631914882SAlex Richardson   if (fabs (y) < 1.0)
14731914882SAlex Richardson     {
14831914882SAlex Richardson       /* Round y to the right precision before scaling it into the subnormal
14931914882SAlex Richardson 	 range to avoid double rounding that can cause 0.5+E/2 ulp error where
15031914882SAlex Richardson 	 E is the worst-case ulp error outside the subnormal range.  So this
15131914882SAlex Richardson 	 is only useful if the goal is better than 1 ulp worst-case error.  */
15231914882SAlex Richardson       double_t hi, lo, one = 1.0;
15331914882SAlex Richardson       if (y < 0.0)
15431914882SAlex Richardson 	one = -1.0;
15531914882SAlex Richardson       lo = scale - y + scale * tmp;
15631914882SAlex Richardson       hi = one + y;
15731914882SAlex Richardson       lo = one - hi + y + lo;
15831914882SAlex Richardson       y = eval_as_double (hi + lo) - one;
15931914882SAlex Richardson       /* Fix the sign of 0.  */
16031914882SAlex Richardson       if (y == 0.0)
16131914882SAlex Richardson 	y = asdouble (sbits & 0x8000000000000000);
16231914882SAlex Richardson       /* The underflow exception needs to be signaled explicitly.  */
16331914882SAlex Richardson       force_eval_double (opt_barrier_double (0x1p-1022) * 0x1p-1022);
16431914882SAlex Richardson     }
16531914882SAlex Richardson   y = 0x1p-1022 * y;
16631914882SAlex Richardson   return check_uflow (eval_as_double (y));
16731914882SAlex Richardson }
16831914882SAlex Richardson 
16931914882SAlex Richardson #define SIGN_BIAS (0x800 << EXP_TABLE_BITS)
17031914882SAlex Richardson 
17131914882SAlex Richardson /* Computes sign*exp(x+xtail) where |xtail| < 2^-8/N and |xtail| <= |x|.
17231914882SAlex Richardson    The sign_bias argument is SIGN_BIAS or 0 and sets the sign to -1 or 1.  */
17331914882SAlex Richardson static inline double
17431914882SAlex Richardson exp_inline (double_t x, double_t xtail, uint32_t sign_bias)
17531914882SAlex Richardson {
17631914882SAlex Richardson   uint32_t abstop;
17731914882SAlex Richardson   uint64_t ki, idx, top, sbits;
17831914882SAlex Richardson   /* double_t for better performance on targets with FLT_EVAL_METHOD==2.  */
17931914882SAlex Richardson   double_t kd, z, r, r2, scale, tail, tmp;
18031914882SAlex Richardson 
18131914882SAlex Richardson   abstop = top12 (x) & 0x7ff;
18231914882SAlex Richardson   if (unlikely (abstop - top12 (0x1p-54) >= top12 (512.0) - top12 (0x1p-54)))
18331914882SAlex Richardson     {
18431914882SAlex Richardson       if (abstop - top12 (0x1p-54) >= 0x80000000)
18531914882SAlex Richardson 	{
18631914882SAlex Richardson 	  /* Avoid spurious underflow for tiny x.  */
18731914882SAlex Richardson 	  /* Note: 0 is common input.  */
18831914882SAlex Richardson 	  double_t one = WANT_ROUNDING ? 1.0 + x : 1.0;
18931914882SAlex Richardson 	  return sign_bias ? -one : one;
19031914882SAlex Richardson 	}
19131914882SAlex Richardson       if (abstop >= top12 (1024.0))
19231914882SAlex Richardson 	{
19331914882SAlex Richardson 	  /* Note: inf and nan are already handled.  */
19431914882SAlex Richardson 	  if (asuint64 (x) >> 63)
19531914882SAlex Richardson 	    return __math_uflow (sign_bias);
19631914882SAlex Richardson 	  else
19731914882SAlex Richardson 	    return __math_oflow (sign_bias);
19831914882SAlex Richardson 	}
19931914882SAlex Richardson       /* Large x is special cased below.  */
20031914882SAlex Richardson       abstop = 0;
20131914882SAlex Richardson     }
20231914882SAlex Richardson 
20331914882SAlex Richardson   /* exp(x) = 2^(k/N) * exp(r), with exp(r) in [2^(-1/2N),2^(1/2N)].  */
20431914882SAlex Richardson   /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N].  */
20531914882SAlex Richardson   z = InvLn2N * x;
20631914882SAlex Richardson #if TOINT_INTRINSICS
20731914882SAlex Richardson   kd = roundtoint (z);
20831914882SAlex Richardson   ki = converttoint (z);
20931914882SAlex Richardson #elif EXP_USE_TOINT_NARROW
21031914882SAlex Richardson   /* z - kd is in [-0.5-2^-16, 0.5] in all rounding modes.  */
21131914882SAlex Richardson   kd = eval_as_double (z + Shift);
21231914882SAlex Richardson   ki = asuint64 (kd) >> 16;
21331914882SAlex Richardson   kd = (double_t) (int32_t) ki;
21431914882SAlex Richardson #else
21531914882SAlex Richardson   /* z - kd is in [-1, 1] in non-nearest rounding modes.  */
21631914882SAlex Richardson   kd = eval_as_double (z + Shift);
21731914882SAlex Richardson   ki = asuint64 (kd);
21831914882SAlex Richardson   kd -= Shift;
21931914882SAlex Richardson #endif
22031914882SAlex Richardson   r = x + kd * NegLn2hiN + kd * NegLn2loN;
22131914882SAlex Richardson   /* The code assumes 2^-200 < |xtail| < 2^-8/N.  */
22231914882SAlex Richardson   r += xtail;
22331914882SAlex Richardson   /* 2^(k/N) ~= scale * (1 + tail).  */
22431914882SAlex Richardson   idx = 2 * (ki % N);
22531914882SAlex Richardson   top = (ki + sign_bias) << (52 - EXP_TABLE_BITS);
22631914882SAlex Richardson   tail = asdouble (T[idx]);
22731914882SAlex Richardson   /* This is only a valid scale when -1023*N < k < 1024*N.  */
22831914882SAlex Richardson   sbits = T[idx + 1] + top;
22931914882SAlex Richardson   /* exp(x) = 2^(k/N) * exp(r) ~= scale + scale * (tail + exp(r) - 1).  */
23031914882SAlex Richardson   /* Evaluation is optimized assuming superscalar pipelined execution.  */
23131914882SAlex Richardson   r2 = r * r;
23231914882SAlex Richardson   /* Without fma the worst case error is 0.25/N ulp larger.  */
23331914882SAlex Richardson   /* Worst case error is less than 0.5+1.11/N+(abs poly error * 2^53) ulp.  */
23431914882SAlex Richardson #if EXP_POLY_ORDER == 4
23531914882SAlex Richardson   tmp = tail + r + r2 * C2 + r * r2 * (C3 + r * C4);
23631914882SAlex Richardson #elif EXP_POLY_ORDER == 5
23731914882SAlex Richardson   tmp = tail + r + r2 * (C2 + r * C3) + r2 * r2 * (C4 + r * C5);
23831914882SAlex Richardson #elif EXP_POLY_ORDER == 6
23931914882SAlex Richardson   tmp = tail + r + r2 * (0.5 + r * C3) + r2 * r2 * (C4 + r * C5 + r2 * C6);
24031914882SAlex Richardson #endif
24131914882SAlex Richardson   if (unlikely (abstop == 0))
24231914882SAlex Richardson     return specialcase (tmp, sbits, ki);
24331914882SAlex Richardson   scale = asdouble (sbits);
24431914882SAlex Richardson   /* Note: tmp == 0 or |tmp| > 2^-200 and scale > 2^-739, so there
24531914882SAlex Richardson      is no spurious underflow here even without fma.  */
24631914882SAlex Richardson   return eval_as_double (scale + scale * tmp);
24731914882SAlex Richardson }
24831914882SAlex Richardson 
24931914882SAlex Richardson /* Returns 0 if not int, 1 if odd int, 2 if even int.  The argument is
25031914882SAlex Richardson    the bit representation of a non-zero finite floating-point value.  */
25131914882SAlex Richardson static inline int
25231914882SAlex Richardson checkint (uint64_t iy)
25331914882SAlex Richardson {
25431914882SAlex Richardson   int e = iy >> 52 & 0x7ff;
25531914882SAlex Richardson   if (e < 0x3ff)
25631914882SAlex Richardson     return 0;
25731914882SAlex Richardson   if (e > 0x3ff + 52)
25831914882SAlex Richardson     return 2;
25931914882SAlex Richardson   if (iy & ((1ULL << (0x3ff + 52 - e)) - 1))
26031914882SAlex Richardson     return 0;
26131914882SAlex Richardson   if (iy & (1ULL << (0x3ff + 52 - e)))
26231914882SAlex Richardson     return 1;
26331914882SAlex Richardson   return 2;
26431914882SAlex Richardson }
26531914882SAlex Richardson 
26631914882SAlex Richardson /* Returns 1 if input is the bit representation of 0, infinity or nan.  */
26731914882SAlex Richardson static inline int
26831914882SAlex Richardson zeroinfnan (uint64_t i)
26931914882SAlex Richardson {
27031914882SAlex Richardson   return 2 * i - 1 >= 2 * asuint64 (INFINITY) - 1;
27131914882SAlex Richardson }
27231914882SAlex Richardson 
27331914882SAlex Richardson double
27431914882SAlex Richardson pow (double x, double y)
27531914882SAlex Richardson {
27631914882SAlex Richardson   uint32_t sign_bias = 0;
27731914882SAlex Richardson   uint64_t ix, iy;
27831914882SAlex Richardson   uint32_t topx, topy;
27931914882SAlex Richardson 
28031914882SAlex Richardson   ix = asuint64 (x);
28131914882SAlex Richardson   iy = asuint64 (y);
28231914882SAlex Richardson   topx = top12 (x);
28331914882SAlex Richardson   topy = top12 (y);
28431914882SAlex Richardson   if (unlikely (topx - 0x001 >= 0x7ff - 0x001
28531914882SAlex Richardson 		|| (topy & 0x7ff) - 0x3be >= 0x43e - 0x3be))
28631914882SAlex Richardson     {
28731914882SAlex Richardson       /* Note: if |y| > 1075 * ln2 * 2^53 ~= 0x1.749p62 then pow(x,y) = inf/0
28831914882SAlex Richardson 	 and if |y| < 2^-54 / 1075 ~= 0x1.e7b6p-65 then pow(x,y) = +-1.  */
28931914882SAlex Richardson       /* Special cases: (x < 0x1p-126 or inf or nan) or
29031914882SAlex Richardson 	 (|y| < 0x1p-65 or |y| >= 0x1p63 or nan).  */
29131914882SAlex Richardson       if (unlikely (zeroinfnan (iy)))
29231914882SAlex Richardson 	{
29331914882SAlex Richardson 	  if (2 * iy == 0)
29431914882SAlex Richardson 	    return issignaling_inline (x) ? x + y : 1.0;
29531914882SAlex Richardson 	  if (ix == asuint64 (1.0))
29631914882SAlex Richardson 	    return issignaling_inline (y) ? x + y : 1.0;
29731914882SAlex Richardson 	  if (2 * ix > 2 * asuint64 (INFINITY)
29831914882SAlex Richardson 	      || 2 * iy > 2 * asuint64 (INFINITY))
29931914882SAlex Richardson 	    return x + y;
30031914882SAlex Richardson 	  if (2 * ix == 2 * asuint64 (1.0))
30131914882SAlex Richardson 	    return 1.0;
30231914882SAlex Richardson 	  if ((2 * ix < 2 * asuint64 (1.0)) == !(iy >> 63))
30331914882SAlex Richardson 	    return 0.0; /* |x|<1 && y==inf or |x|>1 && y==-inf.  */
30431914882SAlex Richardson 	  return y * y;
30531914882SAlex Richardson 	}
30631914882SAlex Richardson       if (unlikely (zeroinfnan (ix)))
30731914882SAlex Richardson 	{
30831914882SAlex Richardson 	  double_t x2 = x * x;
30931914882SAlex Richardson 	  if (ix >> 63 && checkint (iy) == 1)
31031914882SAlex Richardson 	    {
31131914882SAlex Richardson 	      x2 = -x2;
31231914882SAlex Richardson 	      sign_bias = 1;
31331914882SAlex Richardson 	    }
31431914882SAlex Richardson 	  if (WANT_ERRNO && 2 * ix == 0 && iy >> 63)
31531914882SAlex Richardson 	    return __math_divzero (sign_bias);
31631914882SAlex Richardson 	  /* Without the barrier some versions of clang hoist the 1/x2 and
31731914882SAlex Richardson 	     thus division by zero exception can be signaled spuriously.  */
31831914882SAlex Richardson 	  return iy >> 63 ? opt_barrier_double (1 / x2) : x2;
31931914882SAlex Richardson 	}
32031914882SAlex Richardson       /* Here x and y are non-zero finite.  */
32131914882SAlex Richardson       if (ix >> 63)
32231914882SAlex Richardson 	{
32331914882SAlex Richardson 	  /* Finite x < 0.  */
32431914882SAlex Richardson 	  int yint = checkint (iy);
32531914882SAlex Richardson 	  if (yint == 0)
32631914882SAlex Richardson 	    return __math_invalid (x);
32731914882SAlex Richardson 	  if (yint == 1)
32831914882SAlex Richardson 	    sign_bias = SIGN_BIAS;
32931914882SAlex Richardson 	  ix &= 0x7fffffffffffffff;
33031914882SAlex Richardson 	  topx &= 0x7ff;
33131914882SAlex Richardson 	}
33231914882SAlex Richardson       if ((topy & 0x7ff) - 0x3be >= 0x43e - 0x3be)
33331914882SAlex Richardson 	{
33431914882SAlex Richardson 	  /* Note: sign_bias == 0 here because y is not odd.  */
33531914882SAlex Richardson 	  if (ix == asuint64 (1.0))
33631914882SAlex Richardson 	    return 1.0;
33731914882SAlex Richardson 	  if ((topy & 0x7ff) < 0x3be)
33831914882SAlex Richardson 	    {
33931914882SAlex Richardson 	      /* |y| < 2^-65, x^y ~= 1 + y*log(x).  */
34031914882SAlex Richardson 	      if (WANT_ROUNDING)
34131914882SAlex Richardson 		return ix > asuint64 (1.0) ? 1.0 + y : 1.0 - y;
34231914882SAlex Richardson 	      else
34331914882SAlex Richardson 		return 1.0;
34431914882SAlex Richardson 	    }
34531914882SAlex Richardson 	  return (ix > asuint64 (1.0)) == (topy < 0x800) ? __math_oflow (0)
34631914882SAlex Richardson 							 : __math_uflow (0);
34731914882SAlex Richardson 	}
34831914882SAlex Richardson       if (topx == 0)
34931914882SAlex Richardson 	{
35031914882SAlex Richardson 	  /* Normalize subnormal x so exponent becomes negative.  */
35131914882SAlex Richardson 	  /* Without the barrier some versions of clang evalutate the mul
35231914882SAlex Richardson 	     unconditionally causing spurious overflow exceptions.  */
35331914882SAlex Richardson 	  ix = asuint64 (opt_barrier_double (x) * 0x1p52);
35431914882SAlex Richardson 	  ix &= 0x7fffffffffffffff;
35531914882SAlex Richardson 	  ix -= 52ULL << 52;
35631914882SAlex Richardson 	}
35731914882SAlex Richardson     }
35831914882SAlex Richardson 
35931914882SAlex Richardson   double_t lo;
36031914882SAlex Richardson   double_t hi = log_inline (ix, &lo);
36131914882SAlex Richardson   double_t ehi, elo;
36231914882SAlex Richardson #if HAVE_FAST_FMA
36331914882SAlex Richardson   ehi = y * hi;
36431914882SAlex Richardson   elo = y * lo + fma (y, hi, -ehi);
36531914882SAlex Richardson #else
36631914882SAlex Richardson   double_t yhi = asdouble (iy & -1ULL << 27);
36731914882SAlex Richardson   double_t ylo = y - yhi;
36831914882SAlex Richardson   double_t lhi = asdouble (asuint64 (hi) & -1ULL << 27);
36931914882SAlex Richardson   double_t llo = hi - lhi + lo;
37031914882SAlex Richardson   ehi = yhi * lhi;
37131914882SAlex Richardson   elo = ylo * lhi + y * llo; /* |elo| < |ehi| * 2^-25.  */
37231914882SAlex Richardson #endif
37331914882SAlex Richardson   return exp_inline (ehi, elo, sign_bias);
37431914882SAlex Richardson }
37531914882SAlex Richardson #if USE_GLIBC_ABI
37631914882SAlex Richardson strong_alias (pow, __pow_finite)
37731914882SAlex Richardson hidden_alias (pow, __ieee754_pow)
37831914882SAlex Richardson # if LDBL_MANT_DIG == 53
37931914882SAlex Richardson long double powl (long double x, long double y) { return pow (x, y); }
38031914882SAlex Richardson # endif
38131914882SAlex Richardson #endif
382*f3087befSAndrew Turner 
383*f3087befSAndrew Turner TEST_ULP (pow, 0.05)
384*f3087befSAndrew Turner TEST_ULP_NONNEAREST (pow, 0.5)
385*f3087befSAndrew Turner TEST_INTERVAL2 (pow, 0.5, 2.0, 0, inf, 20000)
386*f3087befSAndrew Turner TEST_INTERVAL2 (pow, -0.5, -2.0, 0, inf, 20000)
387*f3087befSAndrew Turner TEST_INTERVAL2 (pow, 0.5, 2.0, -0, -inf, 20000)
388*f3087befSAndrew Turner TEST_INTERVAL2 (pow, -0.5, -2.0, -0, -inf, 20000)
389*f3087befSAndrew Turner TEST_INTERVAL2 (pow, 0.5, 2.0, 0x1p-10, 0x1p10, 40000)
390*f3087befSAndrew Turner TEST_INTERVAL2 (pow, 0.5, 2.0, -0x1p-10, -0x1p10, 40000)
391*f3087befSAndrew Turner TEST_INTERVAL2 (pow, 0, inf, 0.5, 2.0, 80000)
392*f3087befSAndrew Turner TEST_INTERVAL2 (pow, 0, inf, -0.5, -2.0, 80000)
393*f3087befSAndrew Turner TEST_INTERVAL2 (pow, 0x1.fp-1, 0x1.08p0, 0x1p8, 0x1p17, 80000)
394*f3087befSAndrew Turner TEST_INTERVAL2 (pow, 0x1.fp-1, 0x1.08p0, -0x1p8, -0x1p17, 80000)
395*f3087befSAndrew Turner TEST_INTERVAL2 (pow, 0, 0x1p-1000, 0, 1.0, 50000)
396*f3087befSAndrew Turner TEST_INTERVAL2 (pow, 0x1p1000, inf, 0, 1.0, 50000)
397*f3087befSAndrew Turner TEST_INTERVAL2 (pow, 0x1.ffffffffffff0p-1, 0x1.0000000000008p0, 0x1p60, 0x1p68,
398*f3087befSAndrew Turner 		50000)
399*f3087befSAndrew Turner TEST_INTERVAL2 (pow, 0x1.ffffffffff000p-1, 0x1p0, 0x1p50, 0x1p52, 50000)
400*f3087befSAndrew Turner TEST_INTERVAL2 (pow, -0x1.ffffffffff000p-1, -0x1p0, 0x1p50, 0x1p52, 50000)
401