blob: 75125d789627a2246939b9aec53b1b271d63aca5 [file]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Implementation header for double-precision pow(x, y).
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_POW_H
#define LLVM_LIBC_SRC___SUPPORT_MATH_POW_H
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/double_double.h"
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/FPUtil/nearest_integer.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h"
#include "src/__support/macros/properties/cpu_features.h"
#include "src/__support/math/common_constants.h"
#include "src/__support/math/exp_constants.h"
#include "src/__support/math/pow_utils.h"
#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
#include "src/__support/math/pow_fast.h"
#else
#include "src/__support/math/pow_accurate_128.h"
namespace LIBC_NAMESPACE_DECL {
namespace math {
// Overview of the main part of pow(x, y) = x^y computations.
//
// Let x = 2^(e_x) * m_x > 0. Then:
// x^y = 2^( y * log2(x) )
// = 2^( y * ( e_x + log2(m_x) ) )
// = 2^( e_h + e_l )
// = 2^(e_h) * 2^(e_l)
// where:
// e_h = round(y * log2(x)),
// e_l = {y * log2(x)} = y * log2(x) - e_h.
//
// In particular, e_h is an integer, and |e_l| <= 0.5.
//
// For the final result to be fit in double precision, the exponent field can be
// bounded by:
// -1075 <= e_h <= 1024,
// and anything outside that can be passed to quick overflow/underflow logic.
//
// Since |e_l| <= 0.5:
// 0.5 < 2^(e_l) < 2,
// the relative error of x^y = 2^(e_h) * 2^(e_l) is about
// ~ absolute error of e_l
// ~ absolute error of y * log2(x)
// ~ relative error(log2(x)) * |y|
// ~ relative error(log2(x)) * |e_h|
// < relative error(log2(x)) * 2^11.
//
// Roughly speaking, to compute x^y with relative error < 2^(-n), we will need
// to compute log2(x) with relative error < 2^(-n - 11), approximately.
//
// To compute log2(x), we will perform range reduction for log2(m_x):
// dx = r * m_x - 1.
// Then m_x = (1 + dx) / r, and
// log2(m_x) = log2( (1 + dx) / r )
// = log2(1 + dx) - log2(r),
// where -log2(r) is obtained from look up tables.
// The computation of dx = r * m_x - 1 is exact, and we choose the size of the
// look up table for r's such that:
// -2^-8 <= dx < 2^-7.
// Combining them together, we have that:
// log2(x) = e_x - log2(r) + log2(1 + dx)
// = e_x - log2(r) + log2(e) * (dx - dx^2/2 + dx^3/3 - ...)
// So in the worst case, where e_x = log2(r) = 0, the relative error of log2(x)
// computation will be:
// ~ absolute_error(log2(1 + dx)) / |dx|.
// So if we compute log2(1 + dx) accurately up to dx^n term, and use a
// polynomial approximation for the dx^(n + 1) and higher terms:
// log2(1 + dx) ~ log2(e) * (dx - dx^2/2 + ... + (-1)^(n + 1) dx^n / n) +
// dx^(n + 1) * P(dx)
// such that the absolute error of P(dx) is smaller than double precision ulp,
// then the overall relative error of our log2(1 + dx) approximation is:
// ~ ulp(dx^(n + 1)) / |dx| ~ 2^(-52) * |dx^n|
//
// Let's consider 3 cases:
// - For a fast path of a correctly rounded implementation, we will want the
// relative error of x^y bounded above by:
// ~ 2^(-precision - 10) = 2^(-53 - 10) = 2^(-63)
// so that the Ziv accuracy test passes with probability > 1 - 2^-10 ~ 99.99%.
// And from the above argument, we need to compute log2(1 + dx) with relative
// error ~ 2^(-63 - 11) = 2^(-74).
// So we will need to compute log2(1 + dx) accurately up to dx^n such that:
// 2^(-52) * |dx^n| ~ 2^(-74).
// Or equivalently:
// |dx^n| < 2^(-22).
// With our bounds from range reduction |dx| < 2^(-7), n = 3 will be quite
// close to our desired precision needed.
//
// In summary, for a fast path of correctly rounded implementation, we will
// compute log2(e) * (dx - dx^2/2 + dx^3/3) accurately, and approximate higher
// terms with dx^4 * P(dx), where:
// |(log2(1 + dx) - log2(e) * (dx - dx^2/2 + dx^3/3))/dx^4 - P(dx)| < 2^-53.
//
// - For a strictly < 1 ULP error fast version across the full exponent range
// (as implemented in pow_fast), we will want the relative error of x^y
// bounded above by:
// ~ 2^(-precision) = 2^(-53).
// So the relative error needed to approximate log2(1 + dx) is:
// ~ 2^(-53 - 11) = 2^(-64),
// and we will need to compute log2(1 + dx) accurately up to dx^n such that:
// 2^(-52) * |dx^n| ~ 2^(-64),
// or equivalently:
// |dx^n| < 2^-12.
// With |dx| < 2^(-7), n = 2 satisfies |dx^2| < 2^(-14) < 2^(-12).
// Hence, we compute log2(e) * (dx - dx^2/2) accurately in DoubleDouble, and
// approximate higher terms with dx^3 * P(dx), where:
// |(log2(1 + dx) - log2(e) * (dx - dx^2/2))/dx^3 - P(dx)| < 2^-53.
// This guarantees error < 1 ULP everywhere (empirically bounded by 0.75 ULP).
//
// - If we were to choose n = 1 (computing only log2(e) * dx accurately, and
// approximating higher terms with dx^2 * P(dx)), the relative error of
// log2(1 + dx) is only bounded by:
// ~ 2^(-52) * |dx| < 2^(-52) * 2^(-7) = 2^(-59).
// The resulting relative error of x^y is about:
// ~ 2^(-59) * |e_h|.
// While this achieves < 1 ULP for typical inputs with |e_h| <= 64, near
// extreme exponent boundaries (|e_h| ~ 2^10 and |dx| ~ 2^-7) the error can
// drift up to ~7.8 ULPs (bounded theoretically by ~16 ULPs).
LIBC_INLINE double pow(double x, double y) {
using namespace pow_internal;
using FPBits = fputil::FPBits<double>;
FPBits xbits(x), ybits(y);
uint64_t x_u = xbits.uintval();
uint64_t y_u = ybits.uintval();
uint64_t y_a = ybits.abs().uintval();
if (LIBC_UNLIKELY((x_u & 0x0003'FFFF'FFFF'FFFF) == 0 ||
(y_u & 0x000F'FFFF'FFFF'FFFF) == 0)) {
if (auto r = check_special_inputs(x, y); LIBC_UNLIKELY(r.has_value()))
return r.value();
}
double e_x = static_cast<double>(xbits.get_exponent());
uint64_t x_mant = xbits.get_mantissa();
bool is_neg = false;
double sign_d = 1.0;
if (LIBC_UNLIKELY(y_a <= Y_LOWER_BOUND || y_a >= Y_UPPER_BOUND ||
x_u >= FPBits::inf().uintval() ||
x_u < FPBits::min_normal().uintval())) {
if (auto r = check_exceptional_cases(x, y, e_x, x_mant, is_neg, sign_d);
LIBC_UNLIKELY(r.has_value()))
return r.value();
}
// x^y = 2^( y * log2(x) )
// = 2^( y * ( e_x + log2(m_x) ) )
// First we compute log2(x) = e_x + log2(m_x)
// Extract exponent field of x.
// Use the highest 7 fractional bits of m_x as the index for look up tables.
unsigned idx_x = static_cast<unsigned>(x_mant >> (FPBits::FRACTION_LEN - 7));
// Add the hidden bit to the mantissa.
// 1 <= m_x < 2
FPBits m_x = FPBits(x_mant | 0x3ff0'0000'0000'0000);
// Reduced argument for log2(m_x):
// dx = r * m_x - 1.
// The computation is exact, and -2^-8 <= dx < 2^-7.
// Then m_x = (1 + dx) / r, and
// log2(m_x) = log2( (1 + dx) / r )
// = log2(1 + dx) - log2(r).
// As analyzed in the overview comment above, we evaluate the cubic part
// (dx * C1 + dx^2 * C2 + dx^3 * C3) accurately using DoubleDouble (n = 3)
// and approximate higher terms with dx^4 * P(dx) to ensure relative error
// < 2^-63 for this fast path.
// Degree-5 polynomial approximation for:
// P(dx) ~ (log2(1 + dx) - (dx - dx^2/2 + dx^3/3)/log(2)) / dx^4
// Generated by Sollya with:
// > P = fpminimax((log2(1 + x) - (x - x^2/2 + x^3/3)/log(2))/x^4, 5,
// [|D...|], [-2^-8, 2^-7]);
// > dirtyinfnorm((log2(1 + x) - (x - x^2/2 + x^3/3)/log(2))/x - x^3*P,
// [-2^-8, 2^-7]);
// 0x1.a643c...p-74
// > dirtyinfnorm((log2(1 + x) - (x - x^2/2 + x^3/3)/log(2))/x^4 - P,
// [-2^-8, 2^-7]);
// 0x1.b81c5...p-53
constexpr double COEFFS[] = {-0x1.71547652b82fdp-2, 0x1.2776c50ef8f9bp-2,
-0x1.ec709dc4f0fedp-3, 0x1.a617677f716dep-3,
-0x1.715423d54d5p-3, 0x1.44e6355fc4d03p-3};
// Constants for C_k = (-1)^(k-1) / (k * log(2)) in DoubleDouble:
// C1 = 1 / log(2)
constexpr DoubleDouble C1 = {0x1.777d0ffda0d24p-56, 0x1.71547652b82fep0};
// C2 = -1 / (2 * log(2))
constexpr DoubleDouble C2 = {-0x1.777d0ffda0d24p-57, -0x1.71547652b82fep-1};
// C3 = 1 / (3 * log(2))
constexpr DoubleDouble C3 = {0x1.b749fc15522bcp-50, 0x1.ec709dc3a03e2p-2};
// Perform exact range reduction.
#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
double dx = fputil::multiply_add(RD[idx_x], m_x.get_val(), -1.0); // Exact
#else
double c = FPBits(m_x.uintval() & 0x3fff'e000'0000'0000).get_val();
double dx =
fputil::multiply_add(RD[idx_x], m_x.get_val() - c, CD[idx_x]); // Exact
#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
// Evaluate the cubic part (dx * C1 + dx^2 * C2 + dx^3 * C3) and polynomial
// tail using a parallel Double-Double Estrin scheme.
#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
// Error-free transformation for r = C1.hi + dx * C2.hi:
double r_hi = fputil::multiply_add(dx, C2.hi, C1.hi);
double r_lo = fputil::multiply_add(dx, C2.hi, C1.hi - r_hi); // Exact error
#else
DoubleDouble dx_c2 = fputil::exact_mult(dx, C2.hi);
DoubleDouble r_sum = fputil::exact_add(C1.hi, dx_c2.hi);
double r_hi = r_sum.hi;
double r_lo = r_sum.lo + dx_c2.lo;
#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
// Low parts polynomial evaluated in parallel:
// C1.lo + dx * (C2.lo + dx * C3.lo) + r_lo
double lo_tail = fputil::multiply_add(dx, C3.lo, C2.lo);
double lo_poly = fputil::multiply_add(dx, lo_tail, C1.lo + r_lo);
// Evaluate polynomial tail P(dx) using Estrin's scheme:
double dx2 = dx * dx;
double c0 = fputil::multiply_add(dx, COEFFS[1], COEFFS[0]);
double c1 = fputil::multiply_add(dx, COEFFS[3], COEFFS[2]);
double c2 = fputil::multiply_add(dx, COEFFS[5], COEFFS[4]);
double dx4 = dx2 * dx2;
double d0 = fputil::multiply_add(dx2, c1, c0);
double p = fputil::multiply_add(dx4, c2, d0);
// High part of cubic term: C3.hi + dx * P(dx)
double q = fputil::multiply_add(dx, p, C3.hi);
// Combine dx^2 * q into lo_poly:
lo_poly = fputil::multiply_add(dx2, q, lo_poly);
// Multiply by dx to get log2(1 + dx) in DoubleDouble:
DoubleDouble log2_1p = fputil::exact_mult(dx, r_hi);
log2_1p.lo = fputil::multiply_add(dx, lo_poly, log2_1p.lo);
// Combine with e_x - log2(r):
DoubleDouble log2_x_hi =
fputil::exact_add(e_x + LOG2_R_DD[idx_x].hi, log2_1p.hi);
double log2_x_lo = log2_1p.lo + LOG2_R_DD[idx_x].lo;
DoubleDouble log2_x = fputil::exact_add(log2_x_hi.hi, log2_x_lo);
log2_x.lo += log2_x_hi.lo;
// To compute 2^(y * log2(x)), we break the exponent into 3 parts:
// y * log2(x) = hi + mid + lo, where
// hi is an integer
// mid * 2^6 is an integer
// |lo| <= 2^-7
// Then:
// x^y = 2^(y * log2(x)) = 2^hi * 2^mid * 2^lo,
// In which 2^mid is obtained from a look-up table of size 2^6 = 64 elements,
// and 2^lo ~ 1 + lo * P(lo).
// Thus, we have:
// hi + mid = 2^-6 * round( 2^6 * y * log2(x) )
// If we restrict the output such that |hi| < 512, (hi + mid) uses (9 + 6)
// bits, hence, if we use double precision to perform
// round( 2^6 * y * log2(x))
// the lo part is bounded by 2^-7 + 2^(-(52 - 15)) = 2^-7 + 2^-37
// In the following computations:
// y6 = 2^6 * y
// hm = 2^6 * (hi + mid) = round(2^6 * y * log2(x)) ~ round(y6 * s)
// lo6 = 2^6 * lo = 2^6 * (y - (hi + mid)) = y6 * log2(x) - hm.
constexpr double SCALE = 0x1.0p6;
double y6 = y * SCALE; // Exact.
DoubleDouble y6_log2_x = fputil::exact_mult(y6, log2_x.hi);
y6_log2_x.lo = fputil::multiply_add(y6, log2_x.lo, y6_log2_x.lo);
// Check overflow/underflow.
double scale = 1.0;
bool is_denorm = false;
// |2^(hi + mid) - exp2_hi_mid| <= ulp(exp2_hi_mid) / 2
// The fast computation for 2^hi below requires that:
// |hi| < 512, or equivalently, |hm| < 512 * 2^6.
// This guarantees that the biased exponent:
// exp_biased = (hm_i >> 6) + EXP_BIAS = hi + 1023
// is strictly within the normal double range:
// 1023 - 511 <= exp_biased <= 1023 + 511, or 512 <= exp_biased <= 1534.
// Hence, 2^hi is always a normal, non-zero, finite power of 2, and the
// multiplication upper * exp2_hi is exact and never underflows or overflows.
//
// From the edge case checks above:
// 2^(-54) / 1074 <= |y| <= 1075 * 2^53, and
// |log_2(1 - 2^(-53))| <= |log2(x)| <= 1074.
// So their product is bounded by:
// 2^-117 < |y * log2(x)| < 2^74.
//
// The meaningful range for y * log2(x) in double precision is:
// -1075 <= y * log2(x) <= 1024.
// Any value > 1024 overflows, and any value < -1075 underflows.
//
// When |y * log2(x)| >= 511, we shift the exponent by an offset S:
// y * log2(x) = (y * log2(x) - S) + S
// and multiply by scale = 2^S at the end.
// To ensure the shifted exponent (y * log2(x) - S) stays within [-511, 511]:
// - For positive range [511, 1024]:
// 511 - S > -511 ==> S < 1022
// 1024 - S < 511 ==> S > 513
// - For negative range [-1076, -511]:
// -511 + S < 511 ==> S <= 1022
// -1076 + S > -511 ==> S >= 565
// Combined, the shift must satisfy: 565 <= S <= 1022.
// We choose S = 600, which yields:
// y * log2(x) - 600 in [-89, 424] for the positive range, and
// y * log2(x) + 600 in [-476, 89] for the negative range,
// both fitting well within [-511, 511].
//
// For exponents that are completely out of range:
// y * log2(x) > 1025 or y * log2(x) < -1076,
// the product can be as large as 2^74, so subtracting or adding 600 * 64
// would still overflow a 32-bit int when computing hm_i.
// We return early with overflow or underflow in these cases.
//
// Alternatively, for less branching or in SIMD / vector implementations, one
// could clamp y6_log2_x.hi to:
// - UPPER_EXP_BOUND (511 * 64) for overflow, which when multiplied by
// scale = 2^600 yields 2^1111 and correctly overflows.
// - -500 * 64 for underflow, which when multiplied by scale = 2^-600 yields
// 2^-1100 and correctly underflows.
// However, in this correctly rounded version, such clamping can cause the
// Ziv accuracy test to fail on the clamped exponent, unnecessarily
// triggering the slow accurate paths for overflow or underflow cases.
constexpr double UPPER_EXP_BOUND = 511.0 * SCALE;
if (LIBC_UNLIKELY(FPBits(y6_log2_x.hi).abs().get_val() >= UPPER_EXP_BOUND)) {
if (FPBits(y6_log2_x.hi).sign() == Sign::POS) {
if (y6_log2_x.hi > 1025.0 * SCALE)
return set_overflow(is_neg);
scale = 0x1.0p600;
y6_log2_x.hi -= 600.0 * SCALE;
} else {
if (y6_log2_x.hi <= -1021.0 * SCALE) {
if (y6_log2_x.hi < -1076.0 * SCALE)
return set_underflow(is_neg);
is_denorm = true;
} else {
scale = 0x1.0p-600;
y6_log2_x.hi += 600.0 * SCALE;
}
}
}
double hm = fputil::nearest_integer(y6_log2_x.hi);
// lo6 = 2^6 * lo.
DoubleDouble lo6 = fputil::exact_add(y6_log2_x.hi - hm, y6_log2_x.lo);
int hm_i = static_cast<int>(hm);
unsigned idx_y = static_cast<unsigned>(hm_i) & 0x3f;
// 2^hi
int hi = hm_i >> 6;
double exp2_hi = 1.0;
if (LIBC_LIKELY(!is_denorm)) {
int64_t exp2_hi_i = static_cast<int64_t>(
static_cast<uint64_t>(hi + FPBits::EXP_BIAS) << FPBits::FRACTION_LEN);
exp2_hi = FPBits(static_cast<uint64_t>(exp2_hi_i)).get_val();
}
// 2^mid
DoubleDouble exp2_mid{EXP2_MID1[idx_y].mid * sign_d,
EXP2_MID1[idx_y].hi * sign_d};
// Polynomial expansion for 2^(lo6/64):
// 2^(lo6/64) ~ 1 + lo6 * (log(2)/64) + lo6^2 * P(lo6)
// The linear term is computed in DoubleDouble, and the degree-3 polynomial
// P(lo6) is evaluated with standard double precision.
//
// hi and lo parts of log(2)/64, generated by Sollya with:
// > a = D(log(2)/64);
// > b = D(log(2)/64 - a);
constexpr DoubleDouble LOG_2_OVER_64 = {0x1.abc9e3b39803fp-62,
0x1.62e42fefa39efp-7};
// Degree-3 polynomial approximation for (2^(lo6/64) - 1 - lo6*log(2)/64) /
// lo6^2: Generated by Sollya with:
// > f = (2^(x/64) - 1 - x*log(2)/64) / x^2;
// > P = fpminimax(f, 5, [|D...|], [-0.5, 0.5]);
// > dirtyinfnorm((f - P) * x^2, [-0.5, 0.5]);
// 0x1.1778...p-73
constexpr double EXP2_COEFFS[] = {
0x1.ebfbdff82c58fp-15, 0x1.c6b08d704a0cp-23, 0x1.3b2ab6fb4d08fp-31,
0x1.5d87fe77a735dp-40, 0x1.430d835610044p-49, 0x1.ffe67c38112c3p-59};
DoubleDouble lo_log_2 = fputil::quick_mult(lo6, LOG_2_OVER_64);
DoubleDouble lo_log_2_p1 = fputil::exact_add(1.0, lo_log_2.hi);
lo_log_2_p1.lo += lo_log_2.lo;
double lo6_sq = lo6.hi * lo6.hi;
double e0 = fputil::multiply_add(lo6.hi, EXP2_COEFFS[1], EXP2_COEFFS[0]);
double e1 = fputil::multiply_add(lo6.hi, EXP2_COEFFS[3], EXP2_COEFFS[2]);
double e2 = fputil::multiply_add(lo6.hi, EXP2_COEFFS[5], EXP2_COEFFS[4]);
double lo6_4 = lo6_sq * lo6_sq;
double f0 = fputil::multiply_add(lo6_sq, e0, lo_log_2_p1.lo);
double f1 = fputil::multiply_add(lo6_sq, e2, e1);
lo_log_2_p1.lo = fputil::multiply_add(lo6_4, f1, f0);
DoubleDouble r = fputil::quick_mult(exp2_mid, lo_log_2_p1);
// Absolute error bound for r:
// - Base error from exp2 stage is bounded by 0x1.0p-64.
// - Propagated error from log2(x):
// |y| * err(log2(x)) * (2^mid * log(2)) <= |y| * 2^-73.5
// Dynamic error bound adapting to exponent scale |y|:
#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
double err_r =
fputil::multiply_add(FPBits(y).abs().get_val(), 0x1.8p-73, 0x1.0p-64);
#else // !LIBC_TARGET_CPU_HAS_FMA_DOUBLE
// Without FMA, intermediate roundings increase log2(x) and exp2 errors.
double err_r =
fputil::multiply_add(FPBits(y).abs().get_val(), 0x1.cp-72, 0x1.0p-63);
#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
if (LIBC_UNLIKELY(is_denorm)) {
if (auto r_denorm = ziv_test_denorm(hi, r.hi, r.lo, err_r, is_neg);
LIBC_LIKELY(r_denorm.has_value())) {
double res = r_denorm.value();
// Since is_denorm is triggered when y * log2(x) <= -1021 * 2^6, the
// rounded result can still be a normal number (>= 2^-1022). In that
// case, no underflow has occurred, so return directly.
if (LIBC_UNLIKELY(FPBits(res).is_normal()))
return res;
// When the rounded result is denormal or zero, underflow and ERANGE
// should only be set if the result is inexact. We check for exact
// results:
// 1. If x = 2^e_x (x_mant == 0), then x^y = 2^(e_x * y) is an exact
// power of 2 iff e_x * y is an integer and >= -1074.0 (the smallest
// representable power of 2 in double precision).
if (LIBC_UNLIKELY(x_mant == 0)) {
double ex_y = e_x * y;
if (ex_y >= -1074.0 && pow_internal::is_integer(ex_y))
return res;
} else if (LIBC_UNLIKELY(y > 0.0 && y <= 35.0)) {
// 2. If x is not a power of 2, exact results in double precision can
// only occur for 0 < y <= 35 (Lauter and Lefevre). If it falls on
// an exact boundary, convert via DyadicFloat to ensure that
// underflow and inexact exceptions are not signaled.
uint64_t exact_m = 0;
int exact_exp = 0;
if (pow_internal::is_exact_rounding_boundary(x, y, exact_m,
exact_exp)) {
int l = 64 - cpp::countl_zero(exact_m);
pow_internal::DFloat128 exact_f128(
is_neg ? Sign::NEG : Sign::POS, exact_exp + l - 128,
pow_internal::MantissaType(exact_m) << (128 - l));
exact_f128.normalize();
return static_cast<double>(exact_f128);
}
}
// Otherwise, the denormal or zero result is inexact, so we signal the
// underflow exception and set ERANGE if required.
fputil::set_errno_if_required(ERANGE);
fputil::raise_underflow_except_if_required<double>();
return res;
}
return pow_accurate(x, y, is_neg, static_cast<int>(e_x), idx_x, dx);
}
double upper = r.hi + (r.lo + err_r);
double lower = r.hi + (r.lo - err_r);
if (LIBC_LIKELY(upper == lower)) {
double tmp1 = upper * exp2_hi;
return tmp1 * scale;
}
return pow_accurate(x, y, is_neg, static_cast<int>(e_x), idx_x, dx);
}
} // namespace math
} // namespace LIBC_NAMESPACE_DECL
#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
#endif // LLVM_LIBC_SRC___SUPPORT_MATH_POW_H