[libc-commits] [libc] [libc][math] correct the output of `asinpif` and `acospi` (PR #185544)
Mohamed Emad via libc-commits
libc-commits at lists.llvm.org
Mon Mar 9 19:57:03 PDT 2026
https://github.com/hulxv updated https://github.com/llvm/llvm-project/pull/185544
>From 64fbe4cfb1262e2f94d88ad6a881ab7398b63d10 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Tue, 10 Mar 2026 02:26:45 +0200
Subject: [PATCH] [libc][math] correct the output of `asinpif` and `acospi`
---
libc/src/__support/math/inv_trigf_utils.h | 47 ++++++++++---------
.../test/src/math/exhaustive/asinpif_test.cpp | 6 +--
libc/test/src/math/smoke/acospif_test.cpp | 4 +-
3 files changed, 31 insertions(+), 26 deletions(-)
diff --git a/libc/src/__support/math/inv_trigf_utils.h b/libc/src/__support/math/inv_trigf_utils.h
index 54a94f572cda3..83fe9f7f6201c 100644
--- a/libc/src/__support/math/inv_trigf_utils.h
+++ b/libc/src/__support/math/inv_trigf_utils.h
@@ -188,58 +188,63 @@ LIBC_INLINE double asin_eval(double xsq) {
// > [|D...|], [0, 0.5]);
// > for i from 0 to degree(P) do coeff(P, i);
// > print("Error:", dirtyinfnorm(P - g, [1e-30; 0.25]));
-// Error : 0x1.a53f84eafa3ea69bb81b6c52b3278872083fca2c757bd778acp-54 ~= 2^-54
+// Error : 0x1.6b01ec54170565911f924eb53361de37df00d74e2a10a21d5p-56 ~ 2^−55.496
//
// Non-zero coefficients (even powers only):
-LIBC_INLINE_VAR constexpr double ASINPI_COEFFS[12] = {
- 0x1.45f306dc9c881p-2, // x^0
- 0x1.b2995e7b7e756p-5, // x^2
- 0x1.8723a1d12f828p-6, // x^4
- 0x1.d1a45564b9545p-7, // x^6
- 0x1.3ce4ceaa0e1e9p-7, // x^8
- 0x1.d2c305898ea13p-8, // x^10
- 0x1.692212e27a5f9p-8, // x^12
- 0x1.2b22cc744d25bp-8, // x^14
- 0x1.8427b864479ffp-9, // x^16
- 0x1.815522d7a2bf1p-8, // x^18
- -0x1.f6df98438aef4p-9, // x^20
- 0x1.4b50c2eb13708p-7 // x^22
+constexpr double ASINPI_COEFFS[13] = {
+ 0x1.45f306dc9c883p-2, // x^0
+ 0x1.b2995e7b7af0fp-5, // x^2
+ 0x1.8723a1d61d2e9p-6, // x^4
+ 0x1.d1a4529a30a69p-7, // x^6
+ 0x1.3ce53861f8f1fp-7, // x^8
+ 0x1.d2b076c914efep-8, // x^10
+ 0x1.6a2b36f9aed68p-8, // x^12
+ 0x1.21604ae2879a2p-8, // x^14
+ 0x1.ff0549b4fd0d6p-9, // x^16
+ 0x1.035d343508f72p-9, // x^18
+ 0x1.a7b91f72b1592p-8, // x^20
+ -0x1.6a3fb073e97aep-8, // x^22
+ 0x1.547a51d51664ap-7 // x^24
};
// Evaluates P1(v2) = c1 + c2*v2 + c3*v2^2 + ... + c12*v2^11 (tail of P
// without c0) using Estrin's scheme for instruction-level parallelism.
//
-// The tail polynomial has 12 coefficients ASINPI_COEFFS[1..11] in powers of
-// v2:
-// P1(v2) = c1 + c2*v2 + c3*v2^2 + c4*v2^3 + ... + c11*v2^10
+// The tail polynomial has 12 coefficients (ASINPI_COEFFS[1] through
+// ASINPI_COEFFS[12]) in powers of v2:
+// P1(v2) = c1 + c2*v2 + c3*v2^2 + c4*v2^3 + ... + c12*v2^11
//
// Estrin pairs them bottom-up:
// Level 0 (6 pairs, using v2):
// p0 = c1 + c2*v2 p1 = c3 + c4*v2
// p2 = c5 + c6*v2 p3 = c7 + c8*v2
-// p4 = c9 + c10*v2 p5 = c11
+// p4 = c9 + c10*v2 p5 = c11 + c12*v2
// Level 1 (3 pairs, using v4):
// q0 = p0 + p1*v4 q1 = p2 + p3*v4
// q2 = p4 + p5*v4
// Level 2 (using v8):
// r0 = q0 + q1*v8 r1 = q2
-// result = q0 + q1*v8 + q1*v16
+// Level 3 (using v16):
+// result = r0 + r1*v16
LIBC_INLINE double asinpi_eval(double v2) {
double v4 = v2 * v2;
double v8 = v4 * v4;
+ double v16 = v8 * v8;
double p0 = fputil::multiply_add(v2, ASINPI_COEFFS[2], ASINPI_COEFFS[1]);
double p1 = fputil::multiply_add(v2, ASINPI_COEFFS[4], ASINPI_COEFFS[3]);
double p2 = fputil::multiply_add(v2, ASINPI_COEFFS[6], ASINPI_COEFFS[5]);
double p3 = fputil::multiply_add(v2, ASINPI_COEFFS[8], ASINPI_COEFFS[7]);
double p4 = fputil::multiply_add(v2, ASINPI_COEFFS[10], ASINPI_COEFFS[9]);
- double p5 = ASINPI_COEFFS[11];
+ double p5 = fputil::multiply_add(v2, ASINPI_COEFFS[12], ASINPI_COEFFS[11]);
double q0 = fputil::multiply_add(v4, p1, p0);
double q1 = fputil::multiply_add(v4, p3, p2);
double q2 = fputil::multiply_add(v4, p5, p4);
- return fputil::polyeval(v8, q0, q1, q2);
+ double r0 = fputil::multiply_add(v8, q1, q0);
+
+ return fputil::multiply_add(v16, q2, r0);
}
} // namespace inv_trigf_utils_internal
diff --git a/libc/test/src/math/exhaustive/asinpif_test.cpp b/libc/test/src/math/exhaustive/asinpif_test.cpp
index b327e350a0563..f4688b546da11 100644
--- a/libc/test/src/math/exhaustive/asinpif_test.cpp
+++ b/libc/test/src/math/exhaustive/asinpif_test.cpp
@@ -12,7 +12,7 @@
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
-using LlvmLibcAsinfExhaustiveTest =
+using LlvmLibcAsinpifExhaustiveTest =
LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Asinpi,
LIBC_NAMESPACE::asinpif>;
@@ -20,7 +20,7 @@ using LlvmLibcAsinfExhaustiveTest =
static constexpr uint32_t POS_START = 0x0000'0000U;
static constexpr uint32_t POS_STOP = 0x7f80'0000U;
-TEST_F(LlvmLibcAsinfExhaustiveTest, PostiveRange) {
+TEST_F(LlvmLibcAsinpifExhaustiveTest, PostiveRange) {
test_full_range_all_roundings(POS_START, POS_STOP);
}
@@ -28,6 +28,6 @@ TEST_F(LlvmLibcAsinfExhaustiveTest, PostiveRange) {
static constexpr uint32_t NEG_START = 0xb000'0000U;
static constexpr uint32_t NEG_STOP = 0xff80'0000U;
-TEST_F(LlvmLibcAsinfExhaustiveTest, NegativeRange) {
+TEST_F(LlvmLibcAsinpifExhaustiveTest, NegativeRange) {
test_full_range_all_roundings(NEG_START, NEG_STOP);
}
diff --git a/libc/test/src/math/smoke/acospif_test.cpp b/libc/test/src/math/smoke/acospif_test.cpp
index ccee9a25de5e3..c3795764c6b8d 100644
--- a/libc/test/src/math/smoke/acospif_test.cpp
+++ b/libc/test/src/math/smoke/acospif_test.cpp
@@ -31,10 +31,10 @@ TEST_F(LlvmLibcAcospifTest, SpecialNumbers) {
EXPECT_FP_EQ(0.5f, LIBC_NAMESPACE::acospif(-0.0f));
EXPECT_MATH_ERRNO(0);
// acospif(1) = 0
- EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::acospif(1.0f));
+ EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::acospif(1.0f));
EXPECT_MATH_ERRNO(0);
// acospif(-1) = 1
- EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::acospif(-1.0f));
+ EXPECT_FP_EQ_ALL_ROUNDING(1.0f, LIBC_NAMESPACE::acospif(-1.0f));
EXPECT_MATH_ERRNO(0);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::acospif(inf));
More information about the libc-commits
mailing list