Skip to content

[libc][math] Refactor asinhf16 implementation to header-only in src/__support/math folder. #150849

New issue

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

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

Already on GitHub? Sign in to your account

Conversation

bassiounix
Copy link
Contributor

@bassiounix bassiounix commented Jul 27, 2025

Copy link
Contributor Author

bassiounix commented Jul 27, 2025

@bassiounix bassiounix requested a review from lntue July 27, 2025 19:21
@bassiounix bassiounix added bazel "Peripheral" support tier build system: utils/bazel cmake Build system in general and CMake in particular libc labels Jul 27, 2025 — with Graphite App
@bassiounix bassiounix marked this pull request as ready for review July 27, 2025 19:22
@llvmbot
Copy link
Member

llvmbot commented Jul 27, 2025

@llvm/pr-subscribers-libc

Author: Muhammad Bassiouni (bassiounix)

Changes

Part of #147386

in preparation for: https://discourse.llvm.org/t/rfc-make-clang-builtin-math-functions-constexpr-with-llvm-libc-to-support-c-23-constexpr-math-functions/86450


Full diff: https://github.com/llvm/llvm-project/pull/150849.diff

10 Files Affected:

  • (modified) libc/shared/math.h (+1)
  • (modified) libc/shared/math/asinf16.h (+1-1)
  • (added) libc/shared/math/asinhf16.h (+28)
  • (modified) libc/src/__support/math/CMakeLists.txt (+18)
  • (added) libc/src/__support/math/asinhf16.h (+123)
  • (modified) libc/src/math/generic/CMakeLists.txt (+1-12)
  • (modified) libc/src/math/generic/asinhf16.cpp (+2-94)
  • (modified) libc/test/shared/CMakeLists.txt (+1)
  • (modified) libc/test/shared/shared_math_test.cpp (+1)
  • (modified) utils/bazel/llvm-project-overlay/libc/BUILD.bazel (+25)
diff --git a/libc/shared/math.h b/libc/shared/math.h
index e0f00f52e9dc3..26e33ecd45d73 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -21,6 +21,7 @@
 #include "math/asinf.h"
 #include "math/asinf16.h"
 #include "math/asinhf.h"
+#include "math/asinhf16.h"
 #include "math/erff.h"
 #include "math/exp.h"
 #include "math/exp10.h"
diff --git a/libc/shared/math/asinf16.h b/libc/shared/math/asinf16.h
index d545e269a6402..af5b2ec179233 100644
--- a/libc/shared/math/asinf16.h
+++ b/libc/shared/math/asinf16.h
@@ -25,4 +25,4 @@ using math::asinf16;
 
 #endif // LIBC_TYPES_HAS_FLOAT16
 
-#endif // LLVM_LIBC_SHARED_MATH_ASINF_H
+#endif // LLVM_LIBC_SHARED_MATH_ASINF16_H
diff --git a/libc/shared/math/asinhf16.h b/libc/shared/math/asinhf16.h
new file mode 100644
index 0000000000000..1a0525b6a9b8b
--- /dev/null
+++ b/libc/shared/math/asinhf16.h
@@ -0,0 +1,28 @@
+//===-- Shared asinhf16 function ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SHARED_MATH_ASINHF16_H
+#define LLVM_LIBC_SHARED_MATH_ASINHF16_H
+
+#include "shared/libc_common.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "src/__support/math/asinhf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::asinhf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SHARED_MATH_ASINHF16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 13f46a13fe0d7..be208f946024a 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -154,6 +154,24 @@ add_header_library(
     libc.src.__support.macros.optimization
 )
 
+add_header_library(
+  asinhf16
+  HDRS
+    asinhf16.h
+DEPENDS
+    .acoshf_utils
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.polyeval
+    libc.src.__support.FPUtil.cast
+    libc.src.__support.FPUtil.except_value_utils
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.FPUtil.rounding_mode
+    libc.src.__support.FPUtil.sqrt
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_header_library(
   asinf
   HDRS
diff --git a/libc/src/__support/math/asinhf16.h b/libc/src/__support/math/asinhf16.h
new file mode 100644
index 0000000000000..81657b8db97b0
--- /dev/null
+++ b/libc/src/__support/math/asinhf16.h
@@ -0,0 +1,123 @@
+//===-- Implementation header for asinhf16 ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ASINHF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ASINHF16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "acoshf_utils.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE static constexpr float16 asinhf16(float16 x) {
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+  constexpr size_t N_EXCEPTS = 8;
+
+  constexpr fputil::ExceptValues<float16, N_EXCEPTS> ASINHF16_EXCEPTS{{
+    // (input, RZ output, RU offset, RD offset, RN offset)
+
+    // x = 0x1.da4p-2, asinhf16(x) = 0x1.ca8p-2 (RZ)
+    {0x3769, 0x372a, 1, 0, 1},
+    // x = 0x1.d6cp-1, asinhf16(x) = 0x1.a58p-1 (RZ)
+    {0x3b5b, 0x3a96, 1, 0, 0},
+    // x = 0x1.c7cp+3, asinhf16(x) = 0x1.accp+1 (RZ)
+    {0x4b1f, 0x42b3, 1, 0, 0},
+    // x = 0x1.26cp+4, asinhf16(x) = 0x1.cd8p+1 (RZ)
+    {0x4c9b, 0x4336, 1, 0, 1},
+    // x = -0x1.da4p-2, asinhf16(x) = -0x1.ca8p-2 (RZ)
+    {0xb769, 0xb72a, 0, 1, 1},
+    // x = -0x1.d6cp-1, asinhf16(x) = -0x1.a58p-1 (RZ)
+    {0xbb5b, 0xba96, 0, 1, 0},
+    // x = -0x1.c7cp+3, asinhf16(x) = -0x1.accp+1 (RZ)
+    {0xcb1f, 0xc2b3, 0, 1, 0},
+    // x = -0x1.26cp+4, asinhf16(x) = -0x1.cd8p+1 (RZ)
+    {0xcc9b, 0xc336, 0, 1, 1},
+}};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+  using namespace acoshf_internal;
+  using FPBits = fputil::FPBits<float16>;
+  FPBits xbits(x);
+
+  uint16_t x_u = xbits.uintval();
+  uint16_t x_abs = x_u & 0x7fff;
+
+  if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) {
+    if (xbits.is_signaling_nan()) {
+      fputil::raise_except_if_required(FE_INVALID);
+      return FPBits::quiet_nan().get_val();
+    }
+
+    return x;
+  }
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+  // Handle exceptional values
+  if (auto r = ASINHF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+    return r.value();
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+  float xf = x;
+  const float SIGN[2] = {1.0f, -1.0f};
+  float x_sign = SIGN[x_u >> 15];
+
+  // |x| <= 0.25
+  if (LIBC_UNLIKELY(x_abs <= 0x3400)) {
+    // when |x| < 0x1.718p-5, asinhf16(x) = x. Adjust by 1 ULP for certain
+    // rounding types.
+    if (LIBC_UNLIKELY(x_abs < 0x29c6)) {
+      int rounding = fputil::quick_get_round();
+      if ((rounding == FE_UPWARD || rounding == FE_TOWARDZERO) && xf < 0)
+        return fputil::cast<float16>(xf + 0x1p-24f);
+      if ((rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) && xf > 0)
+        return fputil::cast<float16>(xf - 0x1p-24f);
+      return fputil::cast<float16>(xf);
+    }
+
+    float x_sq = xf * xf;
+    // Generated by Sollya with:
+    // > P = fpminimax(asinh(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 2^-2]);
+    // The last coefficient 0x1.bd114ep-6f has been changed to 0x1.bd114ep-5f
+    // for better accuracy.
+    float p = fputil::polyeval(x_sq, 1.0f, -0x1.555552p-3f, 0x1.332f6ap-4f,
+                               -0x1.6c53dep-5f, 0x1.bd114ep-5f);
+
+    return fputil::cast<float16>(xf * p);
+  }
+
+  // General case: asinh(x) = ln(x + sqrt(x^2 + 1))
+  float sqrt_term = fputil::sqrt<float>(fputil::multiply_add(xf, xf, 1.0f));
+  return fputil::cast<float16>(
+      x_sign * log_eval(fputil::multiply_add(xf, x_sign, sqrt_term)));
+
+
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINHF16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index f91feacbff54d..025b0290bfe70 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -3899,18 +3899,7 @@ add_entrypoint_object(
   HDRS
     ../asinhf16.h
   DEPENDS
-    .explogxf
-    libc.hdr.fenv_macros
-    libc.src.__support.FPUtil.cast
-    libc.src.__support.FPUtil.except_value_utils
-    libc.src.__support.FPUtil.fenv_impl
-    libc.src.__support.FPUtil.fp_bits
-    libc.src.__support.FPUtil.multiply_add
-    libc.src.__support.FPUtil.polyeval
-    libc.src.__support.FPUtil.rounding_mode
-    libc.src.__support.FPUtil.sqrt
-    libc.src.__support.macros.optimization
-    libc.src.__support.macros.properties.types
+    libc.src.__support.math.asinhf16
 )
 
 add_entrypoint_object(
diff --git a/libc/src/math/generic/asinhf16.cpp b/libc/src/math/generic/asinhf16.cpp
index 0a0b471d87ecc..d517e633f7bea 100644
--- a/libc/src/math/generic/asinhf16.cpp
+++ b/libc/src/math/generic/asinhf16.cpp
@@ -7,102 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/math/asinhf16.h"
-#include "explogxf.h"
-#include "hdr/fenv_macros.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/cast.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/FPUtil/rounding_mode.h"
-#include "src/__support/FPUtil/sqrt.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h"
+#include "src/__support/math/asinhf16.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-static constexpr size_t N_EXCEPTS = 8;
-
-static constexpr fputil::ExceptValues<float16, N_EXCEPTS> ASINHF16_EXCEPTS{{
-    // (input, RZ output, RU offset, RD offset, RN offset)
-
-    // x = 0x1.da4p-2, asinhf16(x) = 0x1.ca8p-2 (RZ)
-    {0x3769, 0x372a, 1, 0, 1},
-    // x = 0x1.d6cp-1, asinhf16(x) = 0x1.a58p-1 (RZ)
-    {0x3b5b, 0x3a96, 1, 0, 0},
-    // x = 0x1.c7cp+3, asinhf16(x) = 0x1.accp+1 (RZ)
-    {0x4b1f, 0x42b3, 1, 0, 0},
-    // x = 0x1.26cp+4, asinhf16(x) = 0x1.cd8p+1 (RZ)
-    {0x4c9b, 0x4336, 1, 0, 1},
-    // x = -0x1.da4p-2, asinhf16(x) = -0x1.ca8p-2 (RZ)
-    {0xb769, 0xb72a, 0, 1, 1},
-    // x = -0x1.d6cp-1, asinhf16(x) = -0x1.a58p-1 (RZ)
-    {0xbb5b, 0xba96, 0, 1, 0},
-    // x = -0x1.c7cp+3, asinhf16(x) = -0x1.accp+1 (RZ)
-    {0xcb1f, 0xc2b3, 0, 1, 0},
-    // x = -0x1.26cp+4, asinhf16(x) = -0x1.cd8p+1 (RZ)
-    {0xcc9b, 0xc336, 0, 1, 1},
-}};
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-LLVM_LIBC_FUNCTION(float16, asinhf16, (float16 x)) {
-  using namespace acoshf_internal;
-  using FPBits = fputil::FPBits<float16>;
-  FPBits xbits(x);
-
-  uint16_t x_u = xbits.uintval();
-  uint16_t x_abs = x_u & 0x7fff;
-
-  if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) {
-    if (xbits.is_signaling_nan()) {
-      fputil::raise_except_if_required(FE_INVALID);
-      return FPBits::quiet_nan().get_val();
-    }
-
-    return x;
-  }
-
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-  // Handle exceptional values
-  if (auto r = ASINHF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
-    return r.value();
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-
-  float xf = x;
-  const float SIGN[2] = {1.0f, -1.0f};
-  float x_sign = SIGN[x_u >> 15];
-
-  // |x| <= 0.25
-  if (LIBC_UNLIKELY(x_abs <= 0x3400)) {
-    // when |x| < 0x1.718p-5, asinhf16(x) = x. Adjust by 1 ULP for certain
-    // rounding types.
-    if (LIBC_UNLIKELY(x_abs < 0x29c6)) {
-      int rounding = fputil::quick_get_round();
-      if ((rounding == FE_UPWARD || rounding == FE_TOWARDZERO) && xf < 0)
-        return fputil::cast<float16>(xf + 0x1p-24f);
-      if ((rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO) && xf > 0)
-        return fputil::cast<float16>(xf - 0x1p-24f);
-      return fputil::cast<float16>(xf);
-    }
-
-    float x_sq = xf * xf;
-    // Generated by Sollya with:
-    // > P = fpminimax(asinh(x)/x, [|0, 2, 4, 6, 8|], [|SG...|], [0, 2^-2]);
-    // The last coefficient 0x1.bd114ep-6f has been changed to 0x1.bd114ep-5f
-    // for better accuracy.
-    float p = fputil::polyeval(x_sq, 1.0f, -0x1.555552p-3f, 0x1.332f6ap-4f,
-                               -0x1.6c53dep-5f, 0x1.bd114ep-5f);
-
-    return fputil::cast<float16>(xf * p);
-  }
-
-  // General case: asinh(x) = ln(x + sqrt(x^2 + 1))
-  float sqrt_term = fputil::sqrt<float>(fputil::multiply_add(xf, xf, 1.0f));
-  return fputil::cast<float16>(
-      x_sign * log_eval(fputil::multiply_add(xf, x_sign, sqrt_term)));
-}
+LLVM_LIBC_FUNCTION(float16, asinhf16, (float16 x)) { return math::asinhf16(x); }
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 77f3617841293..7ddf26c1d091c 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -17,6 +17,7 @@ add_fp_unittest(
     libc.src.__support.math.asinf
     libc.src.__support.math.asinf16
     libc.src.__support.math.asinhf
+    libc.src.__support.math.asinhf16
     libc.src.__support.math.erff
     libc.src.__support.math.exp
     libc.src.__support.math.exp10
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 2e4450a9b40e8..3ddea7a6a4aa5 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -18,6 +18,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat16) {
   EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::acoshf16(1.0f16));
   EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::acospif16(1.0f16));
   EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::asinf16(0.0f16));
+  EXPECT_FP_EQ(0x0p+0f16, LIBC_NAMESPACE::shared::asinhf16(0.0f16));
 
   EXPECT_FP_EQ(0x1p+0f16, LIBC_NAMESPACE::shared::exp10f16(0.0f16));
 
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 0e40d92cb5c97..31334e324e705 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -2245,6 +2245,24 @@ libc_support_library(
     ],
 )
 
+libc_support_library(
+    name = "__support_math_asinhf16",
+    hdrs = ["src/__support/math/asinhf16.h"],
+    deps = [
+        ":__support_math_acoshf_utils",
+        ":__support_fputil_fenv_impl",
+        ":__support_fputil_fp_bits",
+        ":__support_fputil_polyeval",
+        ":__support_fputil_cast",
+        ":__support_fputil_except_value_utils",
+        ":__support_fputil_multiply_add",
+        ":__support_fputil_rounding_mode",
+        ":__support_fputil_sqrt",
+        ":__support_macros_config",
+        ":__support_macros_optimization",
+    ],
+)
+
 libc_support_library(
     name = "__support_math_asinf",
     hdrs = ["src/__support/math/asinf.h"],
@@ -2847,6 +2865,13 @@ libc_math_function(
     ],
 )
 
+libc_math_function(
+    name = "asinhf16",
+    additional_deps = [
+        ":__support_math_asinhf16",
+    ],
+)
+
 libc_math_function(
     name = "atanf",
     additional_deps = [

Copy link

github-actions bot commented Jul 27, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@bassiounix bassiounix force-pushed the users/bassiounix/spr/refactor-math-functions-to-header-only-asinhf16 branch from 408c7a4 to ef0a9ce Compare July 27, 2025 21:04
Base automatically changed from users/bassiounix/spr/refactor-math-functions-to-header-only to main July 28, 2025 15:14
@bassiounix bassiounix force-pushed the users/bassiounix/spr/refactor-math-functions-to-header-only-asinhf16 branch 2 times, most recently from cae5d05 to 0138846 Compare July 28, 2025 16:45
@bassiounix bassiounix force-pushed the users/bassiounix/spr/refactor-math-functions-to-header-only-asinhf16 branch from 0138846 to 66a1b22 Compare July 28, 2025 17:33
@bassiounix bassiounix force-pushed the users/bassiounix/spr/refactor-math-functions-to-header-only-asinhf16 branch from 66a1b22 to 2aac58c Compare July 28, 2025 18:21
Copy link
Contributor Author

bassiounix commented Jul 29, 2025

Merge activity

  • Jul 29, 5:08 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 29, 5:11 PM UTC: Graphite rebased this pull request as part of a merge.
  • Jul 29, 5:19 PM UTC: @bassiounix merged this pull request with Graphite.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bazel "Peripheral" support tier build system: utils/bazel cmake Build system in general and CMake in particular libc
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants