Skip to content

[libc][math] Skip checking for exceptional values when LIBC_MATH_SKIP_ACCURATE_PASS is set. #130811

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions libc/src/math/generic/acosf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

namespace LIBC_NAMESPACE_DECL {

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr size_t N_EXCEPTS = 4;

// Exceptional values when |x| <= 0.5
Expand All @@ -34,6 +35,7 @@ static constexpr fputil::ExceptValues<float, N_EXCEPTS> ACOSF_EXCEPTS = {{
// x = -0x1.04c444p-12, acosf(x) = 0x1.923p0 (RZ)
{0xb9826222, 0x3fc91800, 1, 0, 1},
}};
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

LLVM_LIBC_FUNCTION(float, acosf, (float x)) {
using FPBits = typename fputil::FPBits<float>;
Expand All @@ -51,9 +53,11 @@ LLVM_LIBC_FUNCTION(float, acosf, (float x)) {
// acos(x) = pi/2 - asin(x)
// ~ pi/2 - x - x^3 / 6

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Check for exceptional values
if (auto r = ACOSF_EXCEPTS.lookup(x_uint); LIBC_UNLIKELY(r.has_value()))
return r.value();
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

double xd = static_cast<double>(x);
return static_cast<float>(fputil::multiply_add(
Expand Down
4 changes: 4 additions & 0 deletions libc/src/math/generic/acosf16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ namespace LIBC_NAMESPACE_DECL {
static constexpr float PI_OVER_2 = 0x1.921fb6p0f;
static constexpr float PI = 0x1.921fb6p1f;

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr size_t N_EXCEPTS = 2;

static constexpr fputil::ExceptValues<float16, N_EXCEPTS> ACOSF16_EXCEPTS{{
// (input, RZ output, RU offset, RD offset, RN offset)
{0xacaf, 0x3e93, 1, 0, 0},
{0xb874, 0x4052, 1, 0, 1},
}};
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

LLVM_LIBC_FUNCTION(float16, acosf16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
Expand Down Expand Up @@ -64,9 +66,11 @@ LLVM_LIBC_FUNCTION(float16, acosf16, (float16 x)) {

float xf = x;

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Handle exceptional values
if (auto r = ACOSF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

// |x| == 0x1p0, x is 1 or -1
// if x is (-)1, return pi, else
Expand Down
7 changes: 6 additions & 1 deletion libc/src/math/generic/acoshf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float, acoshf, (float x)) {
using FPBits_t = typename fputil::FPBits<float>;
FPBits_t xbits(x);
uint32_t x_u = xbits.uintval();

if (LIBC_UNLIKELY(x <= 1.0f)) {
if (x == 1.0f)
Expand All @@ -33,6 +32,8 @@ LLVM_LIBC_FUNCTION(float, acoshf, (float x)) {
return FPBits_t::quiet_nan().get_val();
}

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
uint32_t x_u = xbits.uintval();
if (LIBC_UNLIKELY(x_u >= 0x4f8ffb03)) {
if (LIBC_UNLIKELY(xbits.is_inf_or_nan()))
return x;
Expand Down Expand Up @@ -64,6 +65,10 @@ LLVM_LIBC_FUNCTION(float, acoshf, (float x)) {
return round_result_slightly_up(0x1.451436p6f);
}
}
#else
if (LIBC_UNLIKELY(xbits.is_inf_or_nan()))
return x;
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

double x_d = static_cast<double>(x);
// acosh(x) = log(x + sqrt(x^2 - 1))
Expand Down
6 changes: 6 additions & 0 deletions libc/src/math/generic/asinf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

namespace LIBC_NAMESPACE_DECL {

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr size_t N_EXCEPTS = 2;

// Exceptional values when |x| <= 0.5
Expand All @@ -40,6 +41,7 @@ static constexpr fputil::ExceptValues<float, N_EXCEPTS> ASINF_EXCEPTS_HI = {{
// x = 0x1.ee836cp-1, asinf(x) = 0x1.4f0654p0 (RZ)
{0x3f7741b6, 0x3fa7832a, 1, 0, 0},
}};
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

LLVM_LIBC_FUNCTION(float, asinf, (float x)) {
using FPBits = typename fputil::FPBits<float>;
Expand Down Expand Up @@ -82,10 +84,12 @@ LLVM_LIBC_FUNCTION(float, asinf, (float x)) {
#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
}

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Check for exceptional values
if (auto r = ASINF_EXCEPTS_LO.lookup_odd(x_abs, x_sign);
LIBC_UNLIKELY(r.has_value()))
return r.value();
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

// For |x| <= 0.5, we approximate asinf(x) by:
// asin(x) = x * P(x^2)
Expand All @@ -111,10 +115,12 @@ LLVM_LIBC_FUNCTION(float, asinf, (float x)) {
return FPBits::quiet_nan().get_val();
}

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Check for exceptional values
if (auto r = ASINF_EXCEPTS_HI.lookup_odd(x_abs, x_sign);
LIBC_UNLIKELY(r.has_value()))
return r.value();
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

// When |x| > 0.5, we perform range reduction as follow:
//
Expand Down
5 changes: 5 additions & 0 deletions libc/src/math/generic/asinhf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ LLVM_LIBC_FUNCTION(float, asinhf, (float x)) {
double x_sign = SIGN[x_u >> 31];
double x_d = x;

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Helper functions to set results for exceptional cases.
auto round_result_slightly_down = [x_sign](float r) -> float {
return fputil::multiply_add(static_cast<float>(x_sign), r,
Expand Down Expand Up @@ -95,6 +96,10 @@ LLVM_LIBC_FUNCTION(float, asinhf, (float x)) {
return round_result_slightly_down(0x1.e1b92p3f);
}
}
#else
if (LIBC_UNLIKELY(xbits.is_inf_or_nan()))
return x;
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

// asinh(x) = log(x + sqrt(x^2 + 1))
return static_cast<float>(
Expand Down
4 changes: 4 additions & 0 deletions libc/src/math/generic/cosf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

namespace LIBC_NAMESPACE_DECL {

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Exceptional cases for cosf.
static constexpr size_t N_EXCEPTS = 6;

Expand All @@ -38,6 +39,7 @@ static constexpr fputil::ExceptValues<float, N_EXCEPTS> COSF_EXCEPTS{{
// x = 0x1.ddebdep120, cos(x) = 0x1.114438p-1 (RZ)
{0x7beef5ef, 0x3f08a21c, 1, 0, 0},
}};
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

LLVM_LIBC_FUNCTION(float, cosf, (float x)) {
using FPBits = typename fputil::FPBits<float>;
Expand Down Expand Up @@ -108,8 +110,10 @@ LLVM_LIBC_FUNCTION(float, cosf, (float x)) {
#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
}

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = COSF_EXCEPTS.lookup(x_abs); LIBC_UNLIKELY(r.has_value()))
return r.value();
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

// x is inf or nan.
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
Expand Down
4 changes: 4 additions & 0 deletions libc/src/math/generic/cosf16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

namespace LIBC_NAMESPACE_DECL {

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
constexpr size_t N_EXCEPTS = 4;

constexpr fputil::ExceptValues<float16, N_EXCEPTS> COSF16_EXCEPTS{{
Expand All @@ -28,6 +29,7 @@ constexpr fputil::ExceptValues<float16, N_EXCEPTS> COSF16_EXCEPTS{{
{0x5c49, 0xb8c6, 0, 1, 0},
{0x7acc, 0xa474, 0, 1, 0},
}};
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

LLVM_LIBC_FUNCTION(float16, cosf16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
Expand All @@ -53,9 +55,11 @@ LLVM_LIBC_FUNCTION(float16, cosf16, (float16 x)) {
// = cos(k * pi/32) * cos(y * pi/32) -
// sin(k * pi/32) * sin(y * pi/32)

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Handle exceptional values
if (auto r = COSF16_EXCEPTS.lookup(x_abs); LIBC_UNLIKELY(r.has_value()))
return r.value();
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

// cos(+/-0) = 1
if (LIBC_UNLIKELY(x_abs == 0U))
Expand Down
4 changes: 4 additions & 0 deletions libc/src/math/generic/coshf16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

namespace LIBC_NAMESPACE_DECL {

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr fputil::ExceptValues<float16, 9> COSHF16_EXCEPTS_POS = {{
// x = 0x1.6ap-5, coshf16(x) = 0x1p+0 (RZ)
{0x29a8U, 0x3c00U, 1U, 0U, 1U},
Expand Down Expand Up @@ -51,6 +52,7 @@ static constexpr fputil::ExceptValues<float16, 4> COSHF16_EXCEPTS_NEG = {{
// x = -0x1.5fp+3, coshf16(x) = 0x1.c54p+14 (RZ)
{0xc97cU, 0x7715U, 1U, 0U, 1U},
}};
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

LLVM_LIBC_FUNCTION(float16, coshf16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
Expand Down Expand Up @@ -89,13 +91,15 @@ LLVM_LIBC_FUNCTION(float16, coshf16, (float16 x)) {
}
}

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (x_bits.is_pos()) {
if (auto r = COSHF16_EXCEPTS_POS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
} else {
if (auto r = COSHF16_EXCEPTS_NEG.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
}
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

return eval_sinh_or_cosh</*IsSinh=*/false>(x);
}
Expand Down
2 changes: 2 additions & 0 deletions libc/src/math/generic/erff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ LLVM_LIBC_FUNCTION(float, erff, (float x)) {
return ONE[sign] + SMALL[sign];
}

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Exceptional mask = common 0 bits of 2 exceptional values.
constexpr uint32_t EXCEPT_MASK = 0x809a'6184U;

Expand All @@ -155,6 +156,7 @@ LLVM_LIBC_FUNCTION(float, erff, (float x)) {
if (x_abs == 0U)
return x;
}
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

// Polynomial approximation:
// erf(x) ~ x * (c0 + c1 * x^2 + c2 * x^4 + ... + c7 * x^14)
Expand Down
4 changes: 4 additions & 0 deletions libc/src/math/generic/exp10f16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

namespace LIBC_NAMESPACE_DECL {

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
static constexpr size_t N_EXP10F16_EXCEPTS = 5;
#else
Expand Down Expand Up @@ -53,6 +54,7 @@ static constexpr fputil::ExceptValues<float16, N_EXP10F16_EXCEPTS>
{0x446eU, 0x7690U, 1U, 0U, 1U},
#endif
}};
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
Expand Down Expand Up @@ -119,8 +121,10 @@ LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) {
}
}

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXP10F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

// 10^x = 2^((hi + mid) * log2(10)) * 10^lo
auto [exp2_hi_mid, exp10_lo] = exp10_range_reduction(x);
Expand Down
6 changes: 6 additions & 0 deletions libc/src/math/generic/exp10m1f.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

namespace LIBC_NAMESPACE_DECL {

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr size_t N_EXCEPTS_LO = 11;

static constexpr fputil::ExceptValues<float, N_EXCEPTS_LO> EXP10M1F_EXCEPTS_LO =
Expand Down Expand Up @@ -94,6 +95,7 @@ static constexpr fputil::ExceptValues<float, N_EXCEPTS_HI> EXP10M1F_EXCEPTS_HI =
// x = -0x1.ca4322p-5, exp10m1f(x) = -0x1.ef073p-4 (RZ)
{0xbd65'2191U, 0xbdf7'8398U, 0U, 1U, 1U},
}};
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

LLVM_LIBC_FUNCTION(float, exp10m1f, (float x)) {
using FPBits = fputil::FPBits<float>;
Expand All @@ -119,8 +121,10 @@ LLVM_LIBC_FUNCTION(float, exp10m1f, (float x)) {

// When |x| <= log10(2) * 2^(-6)
if (LIBC_UNLIKELY(x_abs <= 0x3b9a'209bU)) {
#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXP10M1F_EXCEPTS_LO.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

double dx = x;
double dx_sq = dx * dx;
Expand Down Expand Up @@ -192,8 +196,10 @@ LLVM_LIBC_FUNCTION(float, exp10m1f, (float x)) {
}
}

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXP10M1F_EXCEPTS_HI.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

// Range reduction: 10^x = 2^(mid + hi) * 10^lo
// rr = (2^(mid + hi), lo)
Expand Down
6 changes: 6 additions & 0 deletions libc/src/math/generic/exp10m1f16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

namespace LIBC_NAMESPACE_DECL {

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr fputil::ExceptValues<float16, 3> EXP10M1F16_EXCEPTS_LO = {{
// (input, RZ output, RU offset, RD offset, RN offset)
// x = 0x1.5c4p-4, exp10m1f16(x) = 0x1.bacp-3 (RZ)
Expand Down Expand Up @@ -58,6 +59,7 @@ static constexpr fputil::ExceptValues<float16, N_EXP10M1F16_EXCEPTS_HI>
{0x44bdU, 0x7aaeU, 1U, 0U, 1U},
#endif
}};
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

LLVM_LIBC_FUNCTION(float16, exp10m1f16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
Expand Down Expand Up @@ -122,9 +124,11 @@ LLVM_LIBC_FUNCTION(float16, exp10m1f16, (float16 x)) {
if (LIBC_UNLIKELY(x_abs == 0))
return x;

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXP10M1F16_EXCEPTS_LO.lookup(x_u);
LIBC_UNLIKELY(r.has_value()))
return r.value();
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

float xf = x;
// Degree-5 minimax polynomial generated by Sollya with the following
Expand Down Expand Up @@ -153,8 +157,10 @@ LLVM_LIBC_FUNCTION(float16, exp10m1f16, (float16 x)) {
}
}

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXP10M1F16_EXCEPTS_HI.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

// exp10(x) = exp2((hi + mid) * log2(10)) * exp10(lo)
auto [exp2_hi_mid, exp10_lo] = exp10_range_reduction(x);
Expand Down
4 changes: 4 additions & 0 deletions libc/src/math/generic/exp2f16.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

namespace LIBC_NAMESPACE_DECL {

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr fputil::ExceptValues<float16, 3> EXP2F16_EXCEPTS = {{
// (input, RZ output, RU offset, RD offset, RN offset)
// x = 0x1.714p-11, exp2f16(x) = 0x1p+0 (RZ)
Expand All @@ -30,6 +31,7 @@ static constexpr fputil::ExceptValues<float16, 3> EXP2F16_EXCEPTS = {{
// x = -0x1.d5cp-4, exp2f16(x) = 0x1.d8cp-1 (RZ)
{0xaf57U, 0x3b63U, 1U, 0U, 0U},
}};
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

LLVM_LIBC_FUNCTION(float16, exp2f16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
Expand Down Expand Up @@ -82,8 +84,10 @@ LLVM_LIBC_FUNCTION(float16, exp2f16, (float16 x)) {
}
}

#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXP2F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS

// exp2(x) = exp2(hi + mid) * exp2(lo)
auto [exp2_hi_mid, exp2_lo] = exp2_range_reduction(x);
Expand Down
Loading
Loading