From f0ce7125a9631e0b876060cd0d1788f0181e2e47 Mon Sep 17 00:00:00 2001 From: Tue Ly 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 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; @@ -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(x); return static_cast(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 ACOSF16_EXCEPTS{{ @@ -34,6 +35,7 @@ static constexpr fputil::ExceptValues 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; @@ -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; 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(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 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; @@ -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(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( 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 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; @@ -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 COSF16_EXCEPTS{{ @@ -28,6 +29,7 @@ constexpr fputil::ExceptValues 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; @@ -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 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 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; @@ -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(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 {0x446eU, 0x7690U, 1U, 0U, 1U}, #endif }}; +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS LLVM_LIBC_FUNCTION(float16, exp10f16, (float16 x)) { using FPBits = fputil::FPBits; @@ -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 EXP10M1F_EXCEPTS_LO = @@ -94,6 +95,7 @@ static constexpr fputil::ExceptValues 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; @@ -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 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 {0x44bdU, 0x7aaeU, 1U, 0U, 1U}, #endif }}; +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS LLVM_LIBC_FUNCTION(float16, exp10m1f16, (float16 x)) { using FPBits = fputil::FPBits; @@ -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 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 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; @@ -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; 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 EXP2M1F_EXCEPTS_LO = @@ -58,6 +59,7 @@ static constexpr fputil::ExceptValues 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; @@ -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 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 {0xba8dU, 0xb6edU, 0U, 1U, 1U}, #endif }}; +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS LLVM_LIBC_FUNCTION(float16, exp2m1f16, (float16 x)) { using FPBits = fputil::FPBits; @@ -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 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 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; @@ -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 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 {0x3282U, 0x3337U, 1U, 0U, 0U}, #endif }}; +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS LLVM_LIBC_FUNCTION(float16, expm1f16, (float16 x)) { using FPBits = fputil::FPBits; @@ -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 // 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; @@ -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 {0x3c89U, 0x31cbU, 1U, 0U, 1U}, #endif }}; +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS LLVM_LIBC_FUNCTION(float16, log2f16, (float16 x)) { using FPBits = fputil::FPBits; @@ -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 {0x6354U, 0x46d7U, 1U, 0U, 1U}, #endif }}; +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS LLVM_LIBC_FUNCTION(float16, logf16, (float16 x)) { using FPBits = fputil::FPBits; @@ -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; @@ -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(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 SINF16_EXCEPTS{{ @@ -28,6 +29,7 @@ constexpr fputil::ExceptValues 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; @@ -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 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 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; @@ -130,6 +132,7 @@ LLVM_LIBC_FUNCTION(float16, sinhf16, (float16 x)) { return FPBits(static_cast(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(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 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; 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(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 TANF16_EXCEPTS{{ @@ -33,6 +34,7 @@ constexpr fputil::ExceptValues 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; @@ -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 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; @@ -98,8 +100,10 @@ LLVM_LIBC_FUNCTION(float16, tanhf16, (float16 x)) { return fputil::cast(-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 TANPIF16_EXCEPTS{{ @@ -35,6 +36,7 @@ constexpr fputil::ExceptValues 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; @@ -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