[libc-commits] [libc] [libc][math] Reduce memory usage for single precision inverse hyperbolic functions for LIBC_MATH_HAS_SMALL_TABLES option. (PR #188110)

via libc-commits libc-commits at lists.llvm.org
Mon Mar 23 12:53:41 PDT 2026


https://github.com/lntue created https://github.com/llvm/llvm-project/pull/188110

None

>From 9ff7708c79c062de76f936a49a219b1042d58542 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Mon, 23 Mar 2026 19:46:51 +0000
Subject: [PATCH] [libc][math] Reduce memory usage for single precision inverse
 hyperbolic functions for LIBC_MATH_HAS_SMALL_TABLES option.

---
 libc/src/__support/math/acoshf_utils.h | 51 +++++++++++++++++++++++++-
 libc/test/src/math/acoshf_test.cpp     |  2 +-
 libc/test/src/math/asinhf_test.cpp     |  4 +-
 libc/test/src/math/atanhf_test.cpp     | 11 +++++-
 4 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/libc/src/__support/math/acoshf_utils.h b/libc/src/__support/math/acoshf_utils.h
index a0002f404a19f..dc6fd9af8218e 100644
--- a/libc/src/__support/math/acoshf_utils.h
+++ b/libc/src/__support/math/acoshf_utils.h
@@ -13,12 +13,59 @@
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/PolyEval.h"
 #include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/macros/optimization.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
 namespace acoshf_internal {
 
-// x should be positive, normal finite value
+// Compute log(|x|), use for float functions, so the error requirements are not
+// as strict as for double precision, and x is assumed to be normal.
+
+#if defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS) &&                               \
+    defined(LIBC_MATH_HAS_SMALL_TABLES)
+
+LIBC_INLINE double log_eval(double x) {
+  using FPBits = fputil::FPBits<double>;
+  FPBits x_bits(x);
+  uint64_t x_u = x_bits.uintval();
+  // Extract exponent and remove sign bit.
+  double ex = static_cast<double>(
+      (static_cast<int>(x_u >> FPBits::FRACTION_LEN) & 0x7ff) -
+      FPBits::EXP_BIAS);
+  // Reduce to 1.m
+  double x_r =
+      FPBits((x_u & FPBits::FRACTION_MASK) | FPBits::one().uintval()).get_val();
+  // x_r = 1 + dx
+  double dx = x_r - 1.0;
+  // Minimax polynomial of log(1 + x) generated by Sollya with:
+  // > P = fpminimax(log(1 + x)/x, 8, [|1, D...|], [0, 1]);
+  // > dirtyinfnorm((log(1 + x) - x*P)/log(1 + x), [0, 1]);
+  // 0x1.2d5f0a5f66124e3afefa7a66251d1530e07301ed8p-25
+  constexpr double COEFFS[8] = {
+      -0x1.ffff09a15a555p-2, 0x1.55350257eb492p-2, -0x1.fd0649c8116b3p-3,
+      0x1.8814186a6a587p-3,  -0x1.194a9c269ae3p-3, 0x1.4389c5fa07e93p-4,
+      -0x1.ea7bb4f18dbccp-6, 0x1.5d864e41667eep-8,
+  };
+  constexpr double LOG_2 = 0x1.62e42fefa39efp-1;
+
+  double dx2 = dx * dx;
+  double c0 = fputil::multiply_add(dx, COEFFS[1], COEFFS[0]);
+  double c1 = fputil::multiply_add(dx, COEFFS[3], COEFFS[2]);
+  double c2 = fputil::multiply_add(dx, COEFFS[5], COEFFS[4]);
+  double c3 = fputil::multiply_add(dx, COEFFS[7], COEFFS[6]);
+  double dx4 = dx2 * dx2;
+  double d0 = fputil::multiply_add(dx2, c1, c0);
+  double d1 = fputil::multiply_add(dx2, c3, c2);
+  double p = fputil::multiply_add(dx4, d1, d0);
+
+  double r_hi = fputil::multiply_add(ex, LOG_2, dx);
+  double r = fputil::multiply_add(dx2, p, r_hi);
+  return r;
+}
+
+#else // Accurate evaluation.
+
 LIBC_INLINE double log_eval(double x) {
   // For x = 2^ex * (1 + mx)
   //   log(x) = ex * log(2) + log(1 + mx)
@@ -53,6 +100,8 @@ LIBC_INLINE double log_eval(double x) {
   return result;
 }
 
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS && LIBC_MATH_HAS_SMALL_TABLES
+
 } // namespace acoshf_internal
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/math/acoshf_test.cpp b/libc/test/src/math/acoshf_test.cpp
index a0e9b390b58de..d846e484a3d6e 100644
--- a/libc/test/src/math/acoshf_test.cpp
+++ b/libc/test/src/math/acoshf_test.cpp
@@ -51,7 +51,7 @@ TEST_F(LlvmLibcAcoshfTest, InFloatRange) {
     if (FPBits(v).is_nan() || FPBits(v).is_inf())
       continue;
     ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Acosh, x,
-                                   LIBC_NAMESPACE::acoshf(x), 0.5);
+                                   LIBC_NAMESPACE::acoshf(x), TOLERANCE + 0.5);
   }
 }
 
diff --git a/libc/test/src/math/asinhf_test.cpp b/libc/test/src/math/asinhf_test.cpp
index 9d9c042208d28..c3c43eb931c0c 100644
--- a/libc/test/src/math/asinhf_test.cpp
+++ b/libc/test/src/math/asinhf_test.cpp
@@ -50,9 +50,9 @@ TEST_F(LlvmLibcAsinhfTest, InFloatRange) {
     if (FPBits(v).is_nan() || FPBits(v).is_inf())
       continue;
     ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asinh, x,
-                                   LIBC_NAMESPACE::asinhf(x), 0.5);
+                                   LIBC_NAMESPACE::asinhf(x), TOLERANCE + 0.5);
     ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asinh, -x,
-                                   LIBC_NAMESPACE::asinhf(-x), 0.5);
+                                   LIBC_NAMESPACE::asinhf(-x), TOLERANCE + 0.5);
   }
 }
 
diff --git a/libc/test/src/math/atanhf_test.cpp b/libc/test/src/math/atanhf_test.cpp
index 43bde8c5cb0a8..87391383752be 100644
--- a/libc/test/src/math/atanhf_test.cpp
+++ b/libc/test/src/math/atanhf_test.cpp
@@ -10,11 +10,18 @@
 #include "hdr/math_macros.h"
 #include "hdr/stdint_proxy.h"
 #include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/macros/optimization.h"
 #include "src/math/atanhf.h"
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 #include "utils/MPFRWrapper/MPFRUtils.h"
 
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+#define TOLERANCE 1
+#else
+#define TOLERANCE 0
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
 using LlvmLibcAtanhfTest = LIBC_NAMESPACE::testing::FPTest<float>;
 using LIBC_NAMESPACE::Sign;
 
@@ -99,9 +106,9 @@ TEST_F(LlvmLibcAtanhfTest, InFloatRange) {
   for (uint32_t i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
     float x = FPBits(v).get_val();
     ASSERT_MPFR_MATCH(mpfr::Operation::Atanh, x, LIBC_NAMESPACE::atanhf(x),
-                      0.5);
+                      TOLERANCE + 0.5);
     ASSERT_MPFR_MATCH(mpfr::Operation::Atanh, -x, LIBC_NAMESPACE::atanhf(-x),
-                      0.5);
+                      TOLERANCE + 0.5);
   }
 }
 



More information about the libc-commits mailing list