[libc-commits] [libc] [libc][math] Skip checking for exceptional values when LIBC_MATH_SKIP_ACCURATE_PASS is set. (PR #130811)
via libc-commits
libc-commits at lists.llvm.org
Tue Mar 11 11:22:20 PDT 2025
https://github.com/lntue created https://github.com/llvm/llvm-project/pull/130811
None
>From f0ce7125a9631e0b876060cd0d1788f0181e2e47 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Tue, 11 Mar 2025 18:16:15 +0000
Subject: [PATCH] [libc][math] Skip checking for exceptional values when
LIBC_MATH_SKIP_ACCURATE_PASS is set.
---
libc/src/math/generic/acosf.cpp | 4 ++++
libc/src/math/generic/acosf16.cpp | 4 ++++
libc/src/math/generic/acoshf.cpp | 7 ++++++-
libc/src/math/generic/asinf.cpp | 6 ++++++
libc/src/math/generic/asinhf.cpp | 5 +++++
libc/src/math/generic/cosf.cpp | 4 ++++
libc/src/math/generic/cosf16.cpp | 4 ++++
libc/src/math/generic/coshf16.cpp | 4 ++++
libc/src/math/generic/erff.cpp | 2 ++
libc/src/math/generic/exp10f16.cpp | 4 ++++
libc/src/math/generic/exp10m1f.cpp | 6 ++++++
libc/src/math/generic/exp10m1f16.cpp | 6 ++++++
libc/src/math/generic/exp2f16.cpp | 4 ++++
libc/src/math/generic/exp2f_impl.h | 10 ++++++----
libc/src/math/generic/exp2m1f.cpp | 6 ++++++
libc/src/math/generic/exp2m1f16.cpp | 6 ++++++
libc/src/math/generic/expf.cpp | 2 ++
libc/src/math/generic/expf16.cpp | 6 ++++++
libc/src/math/generic/expm1f16.cpp | 7 +++++++
libc/src/math/generic/log10f.cpp | 2 ++
libc/src/math/generic/log10f16.cpp | 4 ++++
libc/src/math/generic/log1pf.cpp | 10 ++++++++++
libc/src/math/generic/log2f16.cpp | 4 ++++
libc/src/math/generic/logf.cpp | 4 ++++
libc/src/math/generic/logf16.cpp | 4 ++++
libc/src/math/generic/sincosf.cpp | 4 ++++
libc/src/math/generic/sinf.cpp | 2 ++
libc/src/math/generic/sinf16.cpp | 5 +++++
libc/src/math/generic/sinhf.cpp | 2 ++
libc/src/math/generic/sinhf16.cpp | 4 ++++
libc/src/math/generic/tanf.cpp | 8 +++++++-
libc/src/math/generic/tanf16.cpp | 6 +++++-
libc/src/math/generic/tanhf16.cpp | 4 ++++
libc/src/math/generic/tanpif16.cpp | 5 +++++
34 files changed, 158 insertions(+), 7 deletions(-)
diff --git a/libc/src/math/generic/acosf.cpp b/libc/src/math/generic/acosf.cpp
index 3c097a7871380..509a5ebc4973e 100644
--- a/libc/src/math/generic/acosf.cpp
+++ b/libc/src/math/generic/acosf.cpp
@@ -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
@@ -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>;
@@ -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(
diff --git a/libc/src/math/generic/acosf16.cpp b/libc/src/math/generic/acosf16.cpp
index 858da3bfaa918..202a950fbb5dd 100644
--- a/libc/src/math/generic/acosf16.cpp
+++ b/libc/src/math/generic/acosf16.cpp
@@ -27,6 +27,7 @@ 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{{
@@ -34,6 +35,7 @@ static constexpr fputil::ExceptValues<float16, N_EXCEPTS> ACOSF16_EXCEPTS{{
{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>;
@@ -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
diff --git a/libc/src/math/generic/acoshf.cpp b/libc/src/math/generic/acoshf.cpp
index 6158063d30521..c4927fa27a84b 100644
--- a/libc/src/math/generic/acoshf.cpp
+++ b/libc/src/math/generic/acoshf.cpp
@@ -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)
@@ -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;
@@ -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))
diff --git a/libc/src/math/generic/asinf.cpp b/libc/src/math/generic/asinf.cpp
index b54a9e7b2b00b..da854417e85fe 100644
--- a/libc/src/math/generic/asinf.cpp
+++ b/libc/src/math/generic/asinf.cpp
@@ -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
@@ -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>;
@@ -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)
@@ -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:
//
diff --git a/libc/src/math/generic/asinhf.cpp b/libc/src/math/generic/asinhf.cpp
index 1d68ac9ea13bc..9cdb7b8394e9d 100644
--- a/libc/src/math/generic/asinhf.cpp
+++ b/libc/src/math/generic/asinhf.cpp
@@ -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,
@@ -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>(
diff --git a/libc/src/math/generic/cosf.cpp b/libc/src/math/generic/cosf.cpp
index 23e3db067e669..6ea24f9ccd3fa 100644
--- a/libc/src/math/generic/cosf.cpp
+++ b/libc/src/math/generic/cosf.cpp
@@ -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;
@@ -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>;
@@ -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)) {
diff --git a/libc/src/math/generic/cosf16.cpp b/libc/src/math/generic/cosf16.cpp
index 534e07854474e..4d42db981ce71 100644
--- a/libc/src/math/generic/cosf16.cpp
+++ b/libc/src/math/generic/cosf16.cpp
@@ -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{{
@@ -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>;
@@ -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))
diff --git a/libc/src/math/generic/coshf16.cpp b/libc/src/math/generic/coshf16.cpp
index cca7581c70e0e..6668e77000f0c 100644
--- a/libc/src/math/generic/coshf16.cpp
+++ b/libc/src/math/generic/coshf16.cpp
@@ -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},
@@ -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>;
@@ -89,6 +91,7 @@ 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();
@@ -96,6 +99,7 @@ LLVM_LIBC_FUNCTION(float16, coshf16, (float16 x)) {
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);
}
diff --git a/libc/src/math/generic/erff.cpp b/libc/src/math/generic/erff.cpp
index 15357452759ea..016afe4a68140 100644
--- a/libc/src/math/generic/erff.cpp
+++ b/libc/src/math/generic/erff.cpp
@@ -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;
@@ -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)
diff --git a/libc/src/math/generic/exp10f16.cpp b/libc/src/math/generic/exp10f16.cpp
index f2002e9f146c0..31abf3b4f89b2 100644
--- a/libc/src/math/generic/exp10f16.cpp
+++ b/libc/src/math/generic/exp10f16.cpp
@@ -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
@@ -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>;
@@ -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);
diff --git a/libc/src/math/generic/exp10m1f.cpp b/libc/src/math/generic/exp10m1f.cpp
index c0e302eea7b08..e973b2921c2e4 100644
--- a/libc/src/math/generic/exp10m1f.cpp
+++ b/libc/src/math/generic/exp10m1f.cpp
@@ -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 =
@@ -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>;
@@ -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;
@@ -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)
diff --git a/libc/src/math/generic/exp10m1f16.cpp b/libc/src/math/generic/exp10m1f16.cpp
index 41e2c2bb14b04..545c479694811 100644
--- a/libc/src/math/generic/exp10m1f16.cpp
+++ b/libc/src/math/generic/exp10m1f16.cpp
@@ -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)
@@ -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>;
@@ -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
@@ -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);
diff --git a/libc/src/math/generic/exp2f16.cpp b/libc/src/math/generic/exp2f16.cpp
index 858053fe2bccb..5c039c59df1af 100644
--- a/libc/src/math/generic/exp2f16.cpp
+++ b/libc/src/math/generic/exp2f16.cpp
@@ -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)
@@ -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>;
@@ -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);
diff --git a/libc/src/math/generic/exp2f_impl.h b/libc/src/math/generic/exp2f_impl.h
index ae2d0628c1205..5c6c2bd415188 100644
--- a/libc/src/math/generic/exp2f_impl.h
+++ b/libc/src/math/generic/exp2f_impl.h
@@ -27,10 +27,6 @@ namespace LIBC_NAMESPACE_DECL {
namespace generic {
LIBC_INLINE float exp2f(float x) {
- constexpr uint32_t EXVAL1 = 0x3b42'9d37U;
- constexpr uint32_t EXVAL2 = 0xbcf3'a937U;
- constexpr uint32_t EXVAL_MASK = EXVAL1 & EXVAL2;
-
using FPBits = typename fputil::FPBits<float>;
FPBits xbits(x);
@@ -46,6 +42,11 @@ LIBC_INLINE float exp2f(float x) {
return 1.0f + x;
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ constexpr uint32_t EXVAL1 = 0x3b42'9d37U;
+ constexpr uint32_t EXVAL2 = 0xbcf3'a937U;
+ constexpr uint32_t EXVAL_MASK = EXVAL1 & EXVAL2;
+
// Check exceptional values.
if (LIBC_UNLIKELY((x_u & EXVAL_MASK) == EXVAL_MASK)) {
if (LIBC_UNLIKELY(x_u == EXVAL1)) { // x = 0x1.853a6ep-9f
@@ -54,6 +55,7 @@ LIBC_INLINE float exp2f(float x) {
return fputil::round_result_slightly_down(0x1.f58d62p-1f);
}
}
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Minimax polynomial generated by Sollya with:
// > P = fpminimax((2^x - 1)/x, 5, [|D...|], [-2^-5, 2^-5]);
diff --git a/libc/src/math/generic/exp2m1f.cpp b/libc/src/math/generic/exp2m1f.cpp
index 2060dc34cc9bf..4913a5e4277e4 100644
--- a/libc/src/math/generic/exp2m1f.cpp
+++ b/libc/src/math/generic/exp2m1f.cpp
@@ -23,6 +23,7 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr size_t N_EXCEPTS_LO = 8;
static constexpr fputil::ExceptValues<float, N_EXCEPTS_LO> EXP2M1F_EXCEPTS_LO =
@@ -58,6 +59,7 @@ static constexpr fputil::ExceptValues<float, N_EXCEPTS_HI> EXP2M1F_EXCEPTS_HI =
// x = -0x1.de7b9cp-5, exp2m1f(x) = -0x1.4508f4p-5 (RZ)
{0xbd6f'3dceU, 0xbd22'847aU, 0U, 1U, 1U},
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float, exp2m1f, (float x)) {
using FPBits = fputil::FPBits<float>;
@@ -70,8 +72,10 @@ LLVM_LIBC_FUNCTION(float, exp2m1f, (float x)) {
if (LIBC_UNLIKELY(x_abs >= 0x4300'0000U || x_abs <= 0x3d00'0000U)) {
// |x| <= 2^-5
if (x_abs <= 0x3d00'0000U) {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXP2M1F_EXCEPTS_LO.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Minimax polynomial generated by Sollya with:
// > display = hexadecimal;
@@ -121,8 +125,10 @@ LLVM_LIBC_FUNCTION(float, exp2m1f, (float x)) {
return -1.0f;
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXP2M1F_EXCEPTS_HI.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// For -25 < x < 128, to compute 2^x, we perform the following range
// reduction: find hi, mid, lo such that:
diff --git a/libc/src/math/generic/exp2m1f16.cpp b/libc/src/math/generic/exp2m1f16.cpp
index eceb76f1893e2..61633cd2cfcfb 100644
--- a/libc/src/math/generic/exp2m1f16.cpp
+++ b/libc/src/math/generic/exp2m1f16.cpp
@@ -24,6 +24,7 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr fputil::ExceptValues<float16, 6> EXP2M1F16_EXCEPTS_LO = {{
// (input, RZ output, RU offset, RD offset, RN offset)
// x = 0x1.cf4p-13, exp2m1f16(x) = 0x1.41p-13 (RZ)
@@ -72,6 +73,7 @@ static constexpr fputil::ExceptValues<float16, N_EXP2M1F16_EXCEPTS_HI>
{0xba8dU, 0xb6edU, 0U, 1U, 1U},
#endif
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float16, exp2m1f16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
@@ -132,9 +134,11 @@ LLVM_LIBC_FUNCTION(float16, exp2m1f16, (float16 x)) {
// When |x| <= 2^(-3).
if (x_abs <= 0x3000U) {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXP2M1F16_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
@@ -149,8 +153,10 @@ LLVM_LIBC_FUNCTION(float16, exp2m1f16, (float16 x)) {
}
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXP2M1F16_EXCEPTS_HI.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);
diff --git a/libc/src/math/generic/expf.cpp b/libc/src/math/generic/expf.cpp
index ee5c2a32b6c6b..fa507d4d9322c 100644
--- a/libc/src/math/generic/expf.cpp
+++ b/libc/src/math/generic/expf.cpp
@@ -28,10 +28,12 @@ LLVM_LIBC_FUNCTION(float, expf, (float x)) {
uint32_t x_u = xbits.uintval();
uint32_t x_abs = x_u & 0x7fff'ffffU;
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Exceptional values
if (LIBC_UNLIKELY(x_u == 0xc236'bd8cU)) { // x = -0x1.6d7b18p+5f
return 0x1.108a58p-66f - x * 0x1.0p-95f;
}
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// When |x| >= 89, |x| < 2^-25, or x is nan
if (LIBC_UNLIKELY(x_abs >= 0x42b2'0000U || x_abs <= 0x3280'0000U)) {
diff --git a/libc/src/math/generic/expf16.cpp b/libc/src/math/generic/expf16.cpp
index 0548ef3932ae9..1af9b3ec9ad6e 100644
--- a/libc/src/math/generic/expf16.cpp
+++ b/libc/src/math/generic/expf16.cpp
@@ -22,6 +22,7 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr fputil::ExceptValues<float16, 2> EXPF16_EXCEPTS_LO = {{
// (input, RZ output, RU offset, RD offset, RN offset)
// x = 0x1.de4p-8, expf16(x) = 0x1.01cp+0 (RZ)
@@ -39,6 +40,7 @@ static constexpr fputil::ExceptValues<float16, 3> EXPF16_EXCEPTS_HI = {{
// x = -0x1.55p-5, expf16(x) = 0x1.ebp-1 (RZ)
{0xa954U, 0x3bacU, 1U, 0U, 0U},
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float16, expf16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
@@ -95,8 +97,10 @@ LLVM_LIBC_FUNCTION(float16, expf16, (float16 x)) {
// When 0 < |x| <= 2^(-5).
if (x_abs <= 0x2800U && !x_bits.is_zero()) {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXPF16_EXCEPTS_LO.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
float xf = x;
// Degree-3 minimax polynomial generated by Sollya with the following
@@ -109,8 +113,10 @@ LLVM_LIBC_FUNCTION(float16, expf16, (float16 x)) {
}
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXPF16_EXCEPTS_HI.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// exp(x) = exp(hi + mid) * exp(lo)
auto [exp_hi_mid, exp_lo] = exp_range_reduction(x);
diff --git a/libc/src/math/generic/expm1f16.cpp b/libc/src/math/generic/expm1f16.cpp
index bfd263eaa9cb0..2188dfbda8ef9 100644
--- a/libc/src/math/generic/expm1f16.cpp
+++ b/libc/src/math/generic/expm1f16.cpp
@@ -23,6 +23,7 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr fputil::ExceptValues<float16, 1> EXPM1F16_EXCEPTS_LO = {{
// (input, RZ output, RU offset, RD offset, RN offset)
// x = 0x1.564p-5, expm1f16(x) = 0x1.5d4p-5 (RZ)
@@ -47,6 +48,7 @@ static constexpr fputil::ExceptValues<float16, N_EXPM1F16_EXCEPTS_HI>
{0x3282U, 0x3337U, 1U, 0U, 0U},
#endif
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float16, expm1f16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
@@ -105,9 +107,12 @@ LLVM_LIBC_FUNCTION(float16, expm1f16, (float16 x)) {
// When 0 < |x| <= 2^(-3).
if (x_abs <= 0x3000U && !x_bits.is_zero()) {
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXPM1F16_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
@@ -121,8 +126,10 @@ LLVM_LIBC_FUNCTION(float16, expm1f16, (float16 x)) {
}
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = EXPM1F16_EXCEPTS_HI.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// exp(x) = exp(hi + mid) * exp(lo)
auto [exp_hi_mid, exp_lo] = exp_range_reduction(x);
diff --git a/libc/src/math/generic/log10f.cpp b/libc/src/math/generic/log10f.cpp
index 73ca26374e4a3..81e7cdbcfe5a1 100644
--- a/libc/src/math/generic/log10f.cpp
+++ b/libc/src/math/generic/log10f.cpp
@@ -139,6 +139,7 @@ LLVM_LIBC_FUNCTION(float, log10f, (float x)) {
return 9.0f;
case 0x5015'02f9U: // x = 10,000,000,000
return 10.0f;
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
case 0x0efe'ee7aU: // x = 0x1.fddcf4p-98f
return fputil::round_result_slightly_up(-0x1.d33a46p+4f);
case 0x3f5f'de1bU: // x = 0x1.bfbc36p-1f
@@ -157,6 +158,7 @@ LLVM_LIBC_FUNCTION(float, log10f, (float x)) {
case 0x7956'ba5eU: // x = 69683218960000541503257137270226944.0
return fputil::round_result_slightly_up(0x1.16bebap+5f);
#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
}
}
diff --git a/libc/src/math/generic/log10f16.cpp b/libc/src/math/generic/log10f16.cpp
index c7cb99e1d4691..2626af4ddda15 100644
--- a/libc/src/math/generic/log10f16.cpp
+++ b/libc/src/math/generic/log10f16.cpp
@@ -23,6 +23,7 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
static constexpr size_t N_LOG10F16_EXCEPTS = 11;
#else
@@ -71,6 +72,7 @@ static constexpr fputil::ExceptValues<float16, N_LOG10F16_EXCEPTS>
// x = 0x1.674p+13, log10f16(x) = 0x1.03cp+2 (RZ)
{0x719dU, 0x440fU, 1U, 0U, 0U},
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float16, log10f16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
@@ -110,8 +112,10 @@ LLVM_LIBC_FUNCTION(float16, log10f16, (float16 x)) {
return FPBits::inf().get_val();
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = LOG10F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// To compute log10(x), we perform the following range reduction:
// x = 2^m * 1.mant,
diff --git a/libc/src/math/generic/log1pf.cpp b/libc/src/math/generic/log1pf.cpp
index 442b00144104b..7f614293029de 100644
--- a/libc/src/math/generic/log1pf.cpp
+++ b/libc/src/math/generic/log1pf.cpp
@@ -90,6 +90,7 @@ LLVM_LIBC_FUNCTION(float, log1pf, (float x)) {
// Use log1p(x) = log(1 + x) for |x| > 2^-6;
if (x_a > 0x3c80'0000U) {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Hard-to-round cases.
switch (x_u) {
case 0x41078febU: // x = 0x1.0f1fd6p3
@@ -119,11 +120,19 @@ LLVM_LIBC_FUNCTION(float, log1pf, (float x)) {
return fputil::round_result_slightly_up(0x1.43ff6ep+6f);
#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
}
+#else
+ if (x == -1.0f) {
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_DIVBYZERO);
+ return FPBits::inf(Sign::NEG).get_val();
+ }
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
return internal::log(xd + 1.0);
}
// |x| <= 2^-6.
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Hard-to round cases.
switch (x_u) {
case 0x35400003U: // x = 0x1.800006p-21f
@@ -137,6 +146,7 @@ LLVM_LIBC_FUNCTION(float, log1pf, (float x)) {
case 0xbb0ec8c4U: // x = -0x1.1d9188p-9
return fputil::round_result_slightly_up(-0x1.1de14ap-9f);
}
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Polymial generated by Sollya with:
// > fpminimax(log(1 + x)/x, 7, [|D...|], [-2^-6; 2^-6]);
diff --git a/libc/src/math/generic/log2f16.cpp b/libc/src/math/generic/log2f16.cpp
index 70d592c1976d7..34be780388f2c 100644
--- a/libc/src/math/generic/log2f16.cpp
+++ b/libc/src/math/generic/log2f16.cpp
@@ -23,6 +23,7 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
static constexpr size_t N_LOG2F16_EXCEPTS = 2;
#else
@@ -57,6 +58,7 @@ static constexpr fputil::ExceptValues<float16, N_LOG2F16_EXCEPTS>
{0x3c89U, 0x31cbU, 1U, 0U, 1U},
#endif
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float16, log2f16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
@@ -96,8 +98,10 @@ LLVM_LIBC_FUNCTION(float16, log2f16, (float16 x)) {
return FPBits::inf().get_val();
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = LOG2F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// To compute log2(x), we perform the following range reduction:
// x = 2^m * 1.mant,
diff --git a/libc/src/math/generic/logf.cpp b/libc/src/math/generic/logf.cpp
index 9ed44cdc04226..032d658a941be 100644
--- a/libc/src/math/generic/logf.cpp
+++ b/libc/src/math/generic/logf.cpp
@@ -66,6 +66,7 @@ LLVM_LIBC_FUNCTION(float, logf, (float x)) {
// Small inputs
if (x_u < 0x4c5d65a5U) {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Hard-to-round cases.
switch (x_u) {
case 0x3f7f4d6fU: // x = 0x1.fe9adep-1f
@@ -80,6 +81,7 @@ LLVM_LIBC_FUNCTION(float, logf, (float x)) {
return round_result_slightly_up(-0x1.6d7b18p+5f);
#endif // LIBC_TARGET_CPU_HAS_FMA
}
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Subnormal inputs.
if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval())) {
if (x == 0.0f) {
@@ -94,6 +96,7 @@ LLVM_LIBC_FUNCTION(float, logf, (float x)) {
x_u = xbits.uintval();
}
} else {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Hard-to-round cases.
switch (x_u) {
case 0x4c5d65a5U: // x = 0x1.bacb4ap+25f
@@ -113,6 +116,7 @@ LLVM_LIBC_FUNCTION(float, logf, (float x)) {
return round_result_slightly_up(0x1.5c9442p+5f);
#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
}
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Exceptional inputs.
if (LIBC_UNLIKELY(x_u > FPBits::max_normal().uintval())) {
if (x_u == 0x8000'0000U) {
diff --git a/libc/src/math/generic/logf16.cpp b/libc/src/math/generic/logf16.cpp
index dd08e34270eef..8e0d7d8f226cb 100644
--- a/libc/src/math/generic/logf16.cpp
+++ b/libc/src/math/generic/logf16.cpp
@@ -23,6 +23,7 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
static constexpr size_t N_LOGF16_EXCEPTS = 5;
#else
@@ -64,6 +65,7 @@ static constexpr fputil::ExceptValues<float16, N_LOGF16_EXCEPTS>
{0x6354U, 0x46d7U, 1U, 0U, 1U},
#endif
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float16, logf16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
@@ -103,8 +105,10 @@ LLVM_LIBC_FUNCTION(float16, logf16, (float16 x)) {
return FPBits::inf().get_val();
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = LOGF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// To compute log(x), we perform the following range reduction:
// x = 2^m * 1.mant,
diff --git a/libc/src/math/generic/sincosf.cpp b/libc/src/math/generic/sincosf.cpp
index 898c8bd0f0ae9..623ef636afb1e 100644
--- a/libc/src/math/generic/sincosf.cpp
+++ b/libc/src/math/generic/sincosf.cpp
@@ -19,6 +19,7 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Exceptional values
static constexpr int N_EXCEPTS = 6;
@@ -48,6 +49,7 @@ static constexpr uint32_t EXCEPT_OUTPUTS_COS[N_EXCEPTS][4] = {
{0x3f78142e, 1, 0, 1}, // x = 0x1.2b9622p67, cos(x) = 0x1.f0285cp-1 (RZ)
{0x3f08a21c, 1, 0, 0}, // x = 0x1.ddebdep120, cos(x) = 0x1.114438p-1 (RZ)
};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(void, sincosf, (float x, float *sinp, float *cosp)) {
using FPBits = typename fputil::FPBits<float>;
@@ -152,6 +154,7 @@ LLVM_LIBC_FUNCTION(void, sincosf, (float x, float *sinp, float *cosp)) {
return;
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Check exceptional values.
for (int i = 0; i < N_EXCEPTS; ++i) {
if (LIBC_UNLIKELY(x_abs == EXCEPT_INPUTS[i])) {
@@ -178,6 +181,7 @@ LLVM_LIBC_FUNCTION(void, sincosf, (float x, float *sinp, float *cosp)) {
return;
}
}
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Combine the results with the sine and cosine of sum formulas:
// sin(x) = sin((k + y)*pi/32)
diff --git a/libc/src/math/generic/sinf.cpp b/libc/src/math/generic/sinf.cpp
index da188e5df557e..d27ce843a2c92 100644
--- a/libc/src/math/generic/sinf.cpp
+++ b/libc/src/math/generic/sinf.cpp
@@ -124,6 +124,7 @@ LLVM_LIBC_FUNCTION(float, sinf, (float x)) {
return static_cast<float>(xd * result);
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (LIBC_UNLIKELY(x_abs == 0x4619'9998U)) { // x = 0x1.33333p13
float r = -0x1.63f4bap-2f;
int rounding = fputil::quick_get_round();
@@ -132,6 +133,7 @@ LLVM_LIBC_FUNCTION(float, sinf, (float x)) {
r = -0x1.63f4bcp-2f;
return xbits.is_neg() ? -r : r;
}
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (LIBC_UNLIKELY(x_abs >= 0x7f80'0000U)) {
if (x_abs == 0x7f80'0000U) {
diff --git a/libc/src/math/generic/sinf16.cpp b/libc/src/math/generic/sinf16.cpp
index 7c15951cccecf..85e55a614588a 100644
--- a/libc/src/math/generic/sinf16.cpp
+++ b/libc/src/math/generic/sinf16.cpp
@@ -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> SINF16_EXCEPTS{{
@@ -28,6 +29,7 @@ constexpr fputil::ExceptValues<float16, N_EXCEPTS> SINF16_EXCEPTS{{
{0x5cb0, 0xbbff, 0, 1, 0},
{0x51f5, 0xb80f, 0, 1, 0},
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float16, sinf16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
@@ -53,11 +55,14 @@ LLVM_LIBC_FUNCTION(float16, sinf16, (float16 x)) {
// = sin(k * pi/32) * cos(y * pi/32) +
// sin(y * pi/32) * cos(k * pi/32)
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Handle exceptional values
bool x_sign = x_u >> 15;
+
if (auto r = SINF16_EXCEPTS.lookup_odd(x_abs, x_sign);
LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
int rounding = fputil::quick_get_round();
diff --git a/libc/src/math/generic/sinhf.cpp b/libc/src/math/generic/sinhf.cpp
index 371dd6e67e66e..d6158fd302536 100644
--- a/libc/src/math/generic/sinhf.cpp
+++ b/libc/src/math/generic/sinhf.cpp
@@ -24,11 +24,13 @@ LLVM_LIBC_FUNCTION(float, sinhf, (float x)) {
if (LIBC_UNLIKELY(x_abs >= 0x42b4'0000U || x_abs <= 0x3da0'0000U)) {
// |x| <= 0.078125
if (x_abs <= 0x3da0'0000U) {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// |x| = 0.0005589424981735646724700927734375
if (LIBC_UNLIKELY(x_abs == 0x3a12'85ffU)) {
if (fputil::fenv_is_round_to_nearest())
return x;
}
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// |x| <= 2^-26
if (LIBC_UNLIKELY(x_abs <= 0x3280'0000U)) {
diff --git a/libc/src/math/generic/sinhf16.cpp b/libc/src/math/generic/sinhf16.cpp
index e2dd009dc72c6..680e1cc49a1d8 100644
--- a/libc/src/math/generic/sinhf16.cpp
+++ b/libc/src/math/generic/sinhf16.cpp
@@ -20,6 +20,7 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr fputil::ExceptValues<float16, 16> SINHF16_EXCEPTS_POS = {{
// x = 0x1.714p-5, sinhf16(x) = 0x1.714p-5 (RZ)
{0x29c5U, 0x29c5U, 1U, 0U, 1U},
@@ -81,6 +82,7 @@ static constexpr fputil::ExceptValues<float16, 12> SINHF16_EXCEPTS_NEG = {{
// x = -0x1.5fp+3, sinhf16(x) = -0x1.c54p+14 (RZ)
{0xc97cU, 0xf715U, 0U, 1U, 1U},
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float16, sinhf16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
@@ -130,6 +132,7 @@ LLVM_LIBC_FUNCTION(float16, sinhf16, (float16 x)) {
return FPBits(static_cast<uint16_t>(x_u)).get_val();
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (x_bits.is_pos()) {
if (auto r = SINHF16_EXCEPTS_POS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
@@ -137,6 +140,7 @@ LLVM_LIBC_FUNCTION(float16, sinhf16, (float16 x)) {
if (auto r = SINHF16_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=*/true>(x);
}
diff --git a/libc/src/math/generic/tanf.cpp b/libc/src/math/generic/tanf.cpp
index f4f7e08838d81..a15aa9796cbd8 100644
--- a/libc/src/math/generic/tanf.cpp
+++ b/libc/src/math/generic/tanf.cpp
@@ -21,6 +21,7 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Exceptional cases for tanf.
constexpr size_t N_EXCEPTS = 6;
@@ -39,11 +40,11 @@ constexpr fputil::ExceptValues<float, N_EXCEPTS> TANF_EXCEPTS{{
// x = 0x1.a6ce12p86, tan(x) = -0x1.c5612ep-1 (RZ)
{0x6ad36709, 0xbf62b097, 0, 1, 0},
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float, tanf, (float x)) {
using FPBits = typename fputil::FPBits<float>;
FPBits xbits(x);
- bool x_sign = xbits.uintval() >> 31;
uint32_t x_abs = xbits.uintval() & 0x7fff'ffffU;
// |x| < pi/32
@@ -92,6 +93,8 @@ LLVM_LIBC_FUNCTION(float, tanf, (float x)) {
return static_cast<float>(xd * result);
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ bool x_sign = xbits.uintval() >> 31;
// Check for exceptional values
if (LIBC_UNLIKELY(x_abs == 0x3f8a1f62U)) {
// |x| = 0x1.143ec4p0
@@ -104,6 +107,7 @@ LLVM_LIBC_FUNCTION(float, tanf, (float x)) {
return tmp;
}
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// |x| > 0x1.ada6a8p+27f
if (LIBC_UNLIKELY(x_abs > 0x4d56'd354U)) {
@@ -115,10 +119,12 @@ LLVM_LIBC_FUNCTION(float, tanf, (float x)) {
}
return x + FPBits::quiet_nan().get_val();
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// Other large exceptional values
if (auto r = TANF_EXCEPTS.lookup_odd(x_abs, x_sign);
LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
}
// For |x| >= pi/32, we use the definition of tan(x) function:
diff --git a/libc/src/math/generic/tanf16.cpp b/libc/src/math/generic/tanf16.cpp
index 48aa51e456a8a..97d201b65bbe6 100644
--- a/libc/src/math/generic/tanf16.cpp
+++ b/libc/src/math/generic/tanf16.cpp
@@ -19,6 +19,7 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
constexpr size_t N_EXCEPTS = 9;
constexpr fputil::ExceptValues<float16, N_EXCEPTS> TANF16_EXCEPTS{{
@@ -33,6 +34,7 @@ constexpr fputil::ExceptValues<float16, N_EXCEPTS> TANF16_EXCEPTS{{
{0x6f4d, 0xbe19, 0, 1, 1},
{0x7330, 0xcb62, 0, 1, 0},
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float16, tanf16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
@@ -40,13 +42,15 @@ LLVM_LIBC_FUNCTION(float16, tanf16, (float16 x)) {
uint16_t x_u = xbits.uintval();
uint16_t x_abs = x_u & 0x7fff;
- bool x_sign = x_u >> 15;
float xf = x;
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+ bool x_sign = x_u >> 15;
// Handle exceptional values
if (auto r = TANF16_EXCEPTS.lookup_odd(x_abs, x_sign);
LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// |x| <= 0x1.d1p-5
if (LIBC_UNLIKELY(x_abs <= 0x2b44)) {
diff --git a/libc/src/math/generic/tanhf16.cpp b/libc/src/math/generic/tanhf16.cpp
index 0266b5cfc2df1..4c43cfd29153f 100644
--- a/libc/src/math/generic/tanhf16.cpp
+++ b/libc/src/math/generic/tanhf16.cpp
@@ -24,12 +24,14 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
static constexpr fputil::ExceptValues<float16, 2> TANHF16_EXCEPTS = {{
// x = 0x1.f54p+0, tanhf16(x) = 0x1.ecp-1 (RZ)
{0x3fd5U, 0x3bb0U, 1U, 0U, 0U},
// x = -0x1.f54p+0, tanhf16(x) = -0x1.ecp-1 (RZ)
{0xbfd5U, 0xbbb0U, 0U, 1U, 0U},
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float16, tanhf16, (float16 x)) {
using FPBits = fputil::FPBits<float16>;
@@ -98,8 +100,10 @@ LLVM_LIBC_FUNCTION(float16, tanhf16, (float16 x)) {
return fputil::cast<float16>(-0x1.ffcp-1);
}
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
if (auto r = TANHF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
// For atanh(-1 + 2^(-11)) < x < atanh(1 - 2^(-11)), to compute tanh(x), we
// perform the following range reduction: find hi, mid, lo, such that:
diff --git a/libc/src/math/generic/tanpif16.cpp b/libc/src/math/generic/tanpif16.cpp
index cf4f9917d4537..71cf25c9741a1 100644
--- a/libc/src/math/generic/tanpif16.cpp
+++ b/libc/src/math/generic/tanpif16.cpp
@@ -19,6 +19,7 @@
namespace LIBC_NAMESPACE_DECL {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
constexpr size_t N_EXCEPTS = 21;
constexpr fputil::ExceptValues<float16, N_EXCEPTS> TANPIF16_EXCEPTS{{
@@ -35,6 +36,7 @@ constexpr fputil::ExceptValues<float16, N_EXCEPTS> TANPIF16_EXCEPTS{{
{0x4135, 0xc1ee, 0, 1, 0}, {0x42cb, 0x41ee, 1, 0, 0},
{0x4335, 0xc1ee, 0, 1, 0},
}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
LLVM_LIBC_FUNCTION(float16, tanpif16, (float16 x)) {
using FPBits = typename fputil::FPBits<float16>;
@@ -48,10 +50,13 @@ LLVM_LIBC_FUNCTION(float16, tanpif16, (float16 x)) {
if (LIBC_UNLIKELY(x_abs == 0U))
return x;
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
bool x_sign = x_u >> 15;
+
if (auto r = TANPIF16_EXCEPTS.lookup_odd(x_abs, x_sign);
LIBC_UNLIKELY(r.has_value()))
return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
}
// Numbers greater or equal to 2^10 are integers, or infinity, or NaN
More information about the libc-commits
mailing list