[libc] [llvm] [libc][math][c23] Add asinbf16 math function (PR #184170)
Muhammad Bassiouni via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 30 10:59:59 PDT 2026
https://github.com/bassiounix updated https://github.com/llvm/llvm-project/pull/184170
>From e503b0fc2a2e93c528677eea0794e200e2eccbbd Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Mon, 2 Mar 2026 19:01:06 +0530
Subject: [PATCH 01/14] feat: implementation for asinbf16
---
libc/src/__support/math/asinbf16.h | 168 +++++++++++++++++++++++++++++
1 file changed, 168 insertions(+)
create mode 100644 libc/src/__support/math/asinbf16.h
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
new file mode 100644
index 0000000000000..681743662729a
--- /dev/null
+++ b/libc/src/__support/math/asinbf16.h
@@ -0,0 +1,168 @@
+//===-- Implementation header for asinbf16 ----------------------*- 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_ASINBF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ASINBF16_H
+
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/macros/optimization.h"
+
+/*
+ cases to consider and info
+ sin (x) = opp/hypot
+
+ // odd function -> sin(x) = sign(x) * sign(x)
+ // sin(x + 2pi) = sin (x)
+ // taylor series -> sin x= x - (x^3)/3! + x^5/(5!) - x^7/(7!)....
+
+
+ //
+ sin(pi-x) = sin(x)
+ sin(pi+x) = -sin(x)
+ sin(2*pi - x) = -sin(x)
+ //
+ sin(pi/2) = 1
+ sin(pi/5) = sin(30) = 1/2
+ sin(pi/4) = sin(45) = 1/root(2)
+ sin(n*pi) = 0
+
+
+ y = asin(x)
+ // Domain E [-1,1]
+ // Range E [-pi/2,pi/2]
+
+ // properties
+ 1. asin(x) = sign(x) * sin(x)
+
+
+ // identities
+
+ // taylor
+
+*/
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE constexpr bfloat16 asinf16(bfloat16 x) {
+ // Generated by Sollya using the following command:
+ // > display = hexadecimal;
+ // > round(pi/2, SG, RN);
+ constexpr float PI_2 = 0x1.921fb6p0f;
+
+ using FPBits = fputil::FPBits<bfloat16>;
+ FPBits xbits(x);
+
+ uint16_t x_u = xbits.uintval();
+ uint16_t x_abs = x_u & 0x7fff;
+ float x_sign = (xbits.sign() == Sign::NEG) ? -1 : 1;
+
+ // x-> pi/2 => y -> 1
+ // domain is E [-1,1]
+ // |x| > 1, or NaN or infinity are invalid
+ if (LIBC_UNLIKELY(x_abs > 0x3F80)) {
+ // NaN
+ if (xbits.is_nan()) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ return x; // quiet NaN
+ }
+
+ fputil::raise_except_if_required(FE_INVALID);
+ fputil::set_errno_if_required(EDOM); // Domain is bounded
+ return FPBits::quiet_nan().get_val();
+ }
+
+ // |x| = {0}
+ if (LIBC_UNLIKELY(x_abs == 0))
+ return x; // with sign
+
+ // for |x| in (0,1] -> sign handles by sign(x) * sin(x)
+ // Taylor series for asin(x)
+ // asin(x) = x + x^3/6 + 3x^5/40 + ...
+ // asin(x) = x * (1 + x^2/6 + 3x^4/40 + ...)
+ // asin(x)/x = 1 + x^2/6 + 3x^4/40 + ...
+ // asin(x)/x = P(x^2) ---------------------------[1]
+
+ // As we approach towards 1 the precision decreases
+ // above 0.89 it goes < 2^-6 error (increase)
+ // So we find a recursive way to handle a range inside the valid range where
+ // its more precise
+ //
+ // y = asin(x) -> sin(y) = x
+ // x = sin(y) = cos(pi/2 - y)
+ // Double angle formula -> cos(2A) = 1 - 2*sin^2(A)
+ // sin(A) = sqrt((1-cos(2A))/2);
+ // put z = 2A
+ // if (z== (pi/2 - y)) here then we can say x = cos(z)
+ // sin(z/2) = sqrt((1-cos(z))/2)
+ // sin(z/2) = sqrt((1-x)/2)
+ // z = 2 * asin(sqrt((1-x)/2));
+
+ // since derivative of asin(x) = 1/sqrt(1-x^2) the errors increase as we
+ // approach 1 so we use the recursive relation z = pi/2 - y = 2 *
+ // asin(sqrt((1-x)/2)); y = pi/2 * 2 * asin(sqrt((1-x)/2)); since y = asin(x)
+ // asin(x) = pi/2 - 2 * asin(sqrt((1-x)/2)) ; ---------------------------[2]
+
+ //[Note: check for inf rec (i.e should not output the same invalid interval
+ //which could not be calculated precisely by taylor series)];
+ // Here we choose an input interval where the values have less precision and
+ // use the formula to fold into the valid interval where we could generate
+ // precise values from taylor eg :- input (0,5,1] -> gets interval [0,1)
+
+ float xf = x;
+ float xf_abs = (xf < 0 ? -xf : xf);
+ float x_sq = xf_abs * xf_abs;
+
+ // Minimax polynomial for asin(x)/x, returns P(u) as float
+ // Degree 6 polynomial of asin(x) generated using Sollya with command :
+ // > display = hexadecimal
+ // > P = fpminimax(asin(x)/x, [|0,2,4,6|], [|SG,SG,SG,SG|], [0, 0.5]);
+ auto asin_poly = [](float u) {
+ return fputil::polyeval(u, 0x1.ffffcep-1f, 0x1.55b648p-3f, 0x1.24d192p-4f,
+ 0x1.0a788p-4f);
+ };
+
+ // for range: (0,0.5]
+ if (x_abs <= 0x3F00) {
+
+ // Remember:- asin(x)/x = P(x^2) -> (ref from [1])
+ // asin(x) = x * P(x^2)
+ // xf already carries the sign
+ float result = xf * asin_poly(x_sq);
+ return bfloat16(result);
+ }
+
+ // remaining range: (0.5,1)
+
+ // ref from [2]
+ // asin(x) = pi/2 - 2 * asin(sqrt((1-x)/2))
+ // let t = ((1-|x|)/2) = |x|*(-1/2) + 1/2
+ // asin(sqrt(t)) = sqrt(t) * P(t)
+ // asin(x) = sign * (pi/2 - 2 * sqrt(t) * P(t))
+
+ float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
+ float t_sqrt = fputil::sqrt<float>(t);
+ float asin_sqrt_t = t_sqrt * asin_poly(t);
+ float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
+ return bfloat16(x_sign * result);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINF16_H
>From 8f568b2d5bed19cb0ad99a407b52f0c33478b750 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Mon, 2 Mar 2026 19:04:40 +0530
Subject: [PATCH 02/14] chore: entrypoints added
---
libc/config/baremetal/aarch64/entrypoints.txt | 1 +
libc/config/baremetal/arm/entrypoints.txt | 1 +
libc/config/baremetal/riscv/entrypoints.txt | 1 +
libc/config/darwin/aarch64/entrypoints.txt | 1 +
libc/config/darwin/x86_64/entrypoints.txt | 1 +
libc/config/gpu/amdgpu/entrypoints.txt | 1 +
libc/config/gpu/nvptx/entrypoints.txt | 1 +
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/arm/entrypoints.txt | 1 +
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/config/windows/entrypoints.txt | 1 +
12 files changed, 12 insertions(+)
diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index ed84bdff8ce1e..82910c320b48a 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -792,6 +792,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 43ba426b8ca09..4cf34764916f7 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -801,6 +801,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 79fbd1e4b0de2..c4a11c6f87337 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -798,6 +798,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index 71881d23c7a06..0888f4b0d922b 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -611,6 +611,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index cad973f1ac069..046d1b409742f 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -235,6 +235,7 @@ set(TARGET_LIBM_ENTRYPOINTS
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index e327d9ac6f3d3..a80bdeddf8319 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -627,6 +627,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index efc784d23e301..5fba41d40c7e6 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -629,6 +629,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 4311ba624e6d8..103b259503723 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -874,6 +874,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index a10dc0c82e36f..31dcb31c67c7a 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -477,6 +477,7 @@ set(TARGET_LIBM_ENTRYPOINTS
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 17efa2e368ede..5782acb727ee2 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -895,6 +895,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index eeaccc863dbc3..42176cd5bd3b3 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -950,6 +950,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index e594f6bbb1fd5..e8080bc97c59a 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -323,6 +323,7 @@ set(TARGET_LIBM_ENTRYPOINTS
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
libc.src.math.atanbf16
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
>From 087b4e930948ea65e964765cd96c0b3a6954129d Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Mon, 2 Mar 2026 19:34:56 +0530
Subject: [PATCH 03/14] feat: added tests
feat:added tests
t1
t2
t3
error
testing multiplier
fix: handled rounding exception
squash
---
libc/docs/headers/math/index.rst | 2 +-
libc/shared/math.h | 1 +
libc/shared/math/asinbf16.h | 23 ++++++++
libc/src/__support/math/CMakeLists.txt | 16 ++++++
libc/src/__support/math/asinbf16.h | 14 ++++-
libc/src/math/CMakeLists.txt | 1 +
libc/src/math/asinbf16.h | 22 ++++++++
libc/src/math/generic/CMakeLists.txt | 10 ++++
libc/src/math/generic/asinbf16.cpp | 19 +++++++
libc/test/shared/CMakeLists.txt | 1 +
libc/test/shared/shared_math_test.cpp | 1 +
libc/test/src/math/CMakeLists.txt | 14 +++++
libc/test/src/math/asinbf16_test.cpp | 54 ++++++++++++++++++
libc/test/src/math/exhaustive/CMakeLists.txt | 18 ++++++
.../src/math/exhaustive/asinbf16_test.cpp | 56 +++++++++++++++++++
libc/test/src/math/smoke/CMakeLists.txt | 25 +++++----
libc/test/src/math/smoke/asinbf16_test.cpp | 41 ++++++++++++++
.../llvm-project-overlay/libc/BUILD.bazel | 22 ++++++++
18 files changed, 325 insertions(+), 15 deletions(-)
create mode 100644 libc/shared/math/asinbf16.h
create mode 100644 libc/src/math/asinbf16.h
create mode 100644 libc/src/math/generic/asinbf16.cpp
create mode 100644 libc/test/src/math/asinbf16_test.cpp
create mode 100644 libc/test/src/math/exhaustive/asinbf16_test.cpp
create mode 100644 libc/test/src/math/smoke/asinbf16_test.cpp
diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst
index f9614c6d19d22..14152ac62435d 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -265,7 +265,7 @@ Higher Math Functions
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| acospi | | | | |check| | | | 7.12.4.8 | F.10.1.8 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| asin | |check| | |check| | | |check| | | | 7.12.4.2 | F.10.1.2 |
+| asin | |check| | |check| | | |check| | | |check| | 7.12.4.2 | F.10.1.2 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
| asinh | |check| | | | |check| | | | 7.12.5.2 | F.10.2.2 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
diff --git a/libc/shared/math.h b/libc/shared/math.h
index 08a4c994283c5..13ed0ba9518a5 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -19,6 +19,7 @@
#include "math/acospif.h"
#include "math/acospif16.h"
#include "math/asin.h"
+#include "math/asinbf16.h"
#include "math/asinf.h"
#include "math/asinf16.h"
#include "math/asinhf.h"
diff --git a/libc/shared/math/asinbf16.h b/libc/shared/math/asinbf16.h
new file mode 100644
index 0000000000000..158547f22d2da
--- /dev/null
+++ b/libc/shared/math/asinbf16.h
@@ -0,0 +1,23 @@
+//===-- Shared asinbf16 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_ASINBF16_H
+#define LLVM_LIBC_SHARED_MATH_ASINBF16_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/asinbf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::asinbf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_ASINBF16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 10329830a004b..e1409de79e6ca 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -381,6 +381,22 @@ add_header_library(
libc.src.__support.macros.optimization
)
+
+add_header_library(
+ asinbf16
+ HDRS
+ asinbf16.h
+ DEPENDS
+ 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.multiply_add
+ libc.src.__support.FPUtil.sqrt
+ libc.src.__support.macros.optimization
+ libc.src.__support.FPUtil.bfloat16
+)
+
add_header_library(
atanpif16
HDRS
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 681743662729a..40fea2c7851d3 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -55,7 +55,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr bfloat16 asinf16(bfloat16 x) {
+LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
// Generated by Sollya using the following command:
// > display = hexadecimal;
// > round(pi/2, SG, RN);
@@ -90,6 +90,16 @@ LIBC_INLINE constexpr bfloat16 asinf16(bfloat16 x) {
if (LIBC_UNLIKELY(x_abs == 0))
return x; // with sign
+ if (LIBC_UNLIKELY(x_abs <= 0x3D00)) {
+ int rounding = fputil::quick_get_round();
+ if ((xbits.is_pos() && rounding == FE_UPWARD) ||
+ (xbits.is_neg() && rounding == FE_DOWNWARD)) {
+ float xf = x;
+ return bfloat16(fputil::multiply_add(xf, 0x1.0p-13f, xf));
+ }
+ return x;
+ }
+
// for |x| in (0,1] -> sign handles by sign(x) * sin(x)
// Taylor series for asin(x)
// asin(x) = x + x^3/6 + 3x^5/40 + ...
@@ -165,4 +175,4 @@ LIBC_INLINE constexpr bfloat16 asinf16(bfloat16 x) {
} // namespace LIBC_NAMESPACE_DECL
-#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINF16_H
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINBF16_H
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index ebba3f04b8d56..b53817e2a1729 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -52,6 +52,7 @@ add_math_entrypoint_object(acospif)
add_math_entrypoint_object(acospif16)
add_math_entrypoint_object(asin)
+add_math_entrypoint_object(asinbf16)
add_math_entrypoint_object(asinf)
add_math_entrypoint_object(asinf16)
diff --git a/libc/src/math/asinbf16.h b/libc/src/math/asinbf16.h
new file mode 100644
index 0000000000000..9c2f1fea51e61
--- /dev/null
+++ b/libc/src/math/asinbf16.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for asinbf16 -----------------------*- 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_MATH_ASINBF16_H
+#define LLVM_LIBC_SRC_MATH_ASINBF16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+bfloat16 asinbf16(bfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_ASINBF16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 30f33749d165e..899c32216e987 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -4098,6 +4098,16 @@ add_entrypoint_object(
libc.src.__support.math.atanpif16
)
+add_entrypoint_object(
+ asinbf16
+ SRCS
+ asinbf16.cpp
+ HDRS
+ ../asinbf16.h
+ DEPENDS
+ libc.src.__support.math.asinbf16
+)
+
add_entrypoint_object(
asinf
SRCS
diff --git a/libc/src/math/generic/asinbf16.cpp b/libc/src/math/generic/asinbf16.cpp
new file mode 100644
index 0000000000000..a197e9d300d32
--- /dev/null
+++ b/libc/src/math/generic/asinbf16.cpp
@@ -0,0 +1,19 @@
+//===-- Half-precision asinbf16(x) function -------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/asinbf16.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/math/asinbf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(bfloat16, asinbf16, (bfloat16 x)) {
+ return math::asinbf16(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index c3795d366a588..88b6fc566d1ec 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -16,6 +16,7 @@ add_fp_unittest(
libc.src.__support.math.acospif
libc.src.__support.math.acospif16
libc.src.__support.math.asin
+ libc.src.__support.math.asinbf16
libc.src.__support.math.asinf
libc.src.__support.math.asinf16
libc.src.__support.math.asinhf
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index b52abc6d8e990..a3408eb29a953 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -425,6 +425,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat128) {
TEST(LlvmLibcSharedMathTest, AllBFloat16) {
using FPBits = LIBC_NAMESPACE::fputil::FPBits<bfloat16>;
EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::atanbf16(bfloat16(0.0)));
+ EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::asinbf16(bfloat16(0.0)));
EXPECT_FP_EQ(bfloat16(5.0), LIBC_NAMESPACE::shared::bf16add(2.0, 3.0));
EXPECT_FP_EQ(bfloat16(2.0f), LIBC_NAMESPACE::shared::bf16divf(4.0f, 2.0f));
EXPECT_FP_EQ(bfloat16(2.0), LIBC_NAMESPACE::shared::bf16divl(6.0L, 3.0L));
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 2fd77f964e4d6..8171ce03d3aba 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2512,6 +2512,20 @@ add_fp_unittest(
libc.src.math.asin
)
+
+add_fp_unittest(
+ asinbf16_test
+ NEED_MPFR
+ SUITE
+ libc-math-unittests
+ SRCS
+ asinbf16_test.cpp
+ DEPENDS
+ libc.src.math.asinbf16
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.bfloat16
+)
+
add_fp_unittest(
asinf16_test
NEED_MPFR
diff --git a/libc/test/src/math/asinbf16_test.cpp b/libc/test/src/math/asinbf16_test.cpp
new file mode 100644
index 0000000000000..55276883d52ed
--- /dev/null
+++ b/libc/test/src/math/asinbf16_test.cpp
@@ -0,0 +1,54 @@
+//===-- Exhaustive test for asinbf16 --------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/math/asinbf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcAsinBf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// Range: [0, Inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// Range: [-Inf, 0]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcAsinBf16Test, PositiveRange) {
+ for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
+ bfloat16 x = FPBits(v).get_val();
+
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
+ LIBC_NAMESPACE::asinbf16(x), 0.5);
+ }
+}
+
+TEST_F(LlvmLibcAsinBf16Test, NegativeRange) {
+ for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
+ bfloat16 x = FPBits(v).get_val();
+
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
+ LIBC_NAMESPACE::asinbf16(x), 0.5);
+ }
+}
+
+TEST_F(LlvmLibcAsinBf16Test, SpecialNumbers) {
+ constexpr bfloat16 VALUES[] = {zero, neg_zero, inf,
+ neg_inf, min_normal, max_normal};
+ for (size_t i = 0; i < 6; ++i) {
+ bfloat16 x = VALUES[i];
+
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
+ LIBC_NAMESPACE::asinbf16(x), 0.5);
+ }
+}
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 2d1301d3a1e66..5e5f3f0adf083 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -650,6 +650,24 @@ add_fp_unittest(
libc.src.__support.math.atanf
)
+
+add_fp_unittest(
+ asinbf16_test
+ NO_RUN_POSTBUILD
+ NEED_MPFR
+ SUITE
+ libc_math_exhaustive_tests
+ SRCS
+ asinbf16_test.cpp
+ DEPENDS
+ .exhaustive_test
+ libc.src.math.asinbf16
+ libc.src.__support.FPUtil.fp_bits
+ libc.src.__support.FPUtil.bfloat16
+ LINK_LIBRARIES
+ -lpthread
+)
+
add_fp_unittest(
asinf_test
NO_RUN_POSTBUILD
diff --git a/libc/test/src/math/exhaustive/asinbf16_test.cpp b/libc/test/src/math/exhaustive/asinbf16_test.cpp
new file mode 100644
index 0000000000000..85f0b811b2c8d
--- /dev/null
+++ b/libc/test/src/math/exhaustive/asinbf16_test.cpp
@@ -0,0 +1,56 @@
+//===-- Exhaustive test for asinbf16 --------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/math/asinbf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcAsinBf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// Normal range: [+0, +int]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// Normal range: [-0, -int]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcAsinBf16Test, NormalPositiveRange) {
+ for (uint16_t v1 = POS_START; v1 <= POS_STOP; v1++) {
+
+ bfloat16 x = FPBits(v1).get_val();
+
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
+ LIBC_NAMESPACE::asinbf16(x), 0.5);
+ }
+}
+
+TEST_F(LlvmLibcAsinBf16Test, NormalNegativeRange) {
+ for (uint16_t v1 = NEG_START; v1 <= NEG_STOP; v1++) {
+
+ bfloat16 x = FPBits(v1).get_val();
+
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
+ LIBC_NAMESPACE::asinbf16(x), 0.5);
+ }
+}
+
+TEST_F(LlvmLibcAsinBf16Test, SpecialNumbers) {
+ constexpr bfloat16 VALUES[] = {zero, neg_zero, inf,
+ neg_inf, min_normal, max_normal};
+ for (size_t i = 0; i < 6; ++i) {
+ bfloat16 x = VALUES[i];
+
+ EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
+ LIBC_NAMESPACE::asinbf16(x), 0.5);
+ }
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 79f2ea4806377..d02a678fc8702 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4839,6 +4839,19 @@ add_fp_unittest(
libc.src.math.asin
)
+add_fp_unittest(
+ asinbf16_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ asinbf16_test.cpp
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.src.math.asinbf16
+ libc.hdr.fenv_macros
+ libc.src.__support.FPUtil.bfloat16
+)
+
add_fp_unittest(
asinf16_test
SUITE
@@ -4885,18 +4898,6 @@ add_fp_unittest(
libc.src.math.acosf16
)
-add_fp_unittest(
- acospif_test
- SUITE
- libc-math-smoke-tests
- SRCS
- acospif_test.cpp
- DEPENDS
- libc.hdr.errno_macros
- libc.src.math.acospif
- libc.src.__support.FPUtil.fp_bits
-)
-
add_fp_unittest(
acospif16_test
SUITE
diff --git a/libc/test/src/math/smoke/asinbf16_test.cpp b/libc/test/src/math/smoke/asinbf16_test.cpp
new file mode 100644
index 0000000000000..d237a194c46fc
--- /dev/null
+++ b/libc/test/src/math/smoke/asinbf16_test.cpp
@@ -0,0 +1,41 @@
+//===-- Unittests for asinbf16 --------------------------------------------===//
+//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/math/asinbf16.h"
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+class LlvmLibcAsinBf16Test : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+ DECLARE_SPECIAL_CONSTANTS(bfloat16)
+public:
+ void test_special_numbers() {
+ EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::asinbf16(aNaN));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+ aNaN, LIBC_NAMESPACE::asinbf16(sNaN), FE_INVALID);
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::asinbf16(zero));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::asinbf16(neg_zero));
+ EXPECT_MATH_ERRNO(0);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::asinbf16(inf));
+ EXPECT_MATH_ERRNO(EDOM);
+
+ EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::asinbf16(neg_inf));
+ EXPECT_MATH_ERRNO(EDOM);
+ }
+};
+TEST_F(LlvmLibcAsinBf16Test, SpecialNumbers) { test_special_numbers(); }
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index a69ebcdb63fa7..7fdc6e46305c0 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -3365,6 +3365,21 @@ libc_support_library(
],
)
+libc_support_library(
+ name = "__support_math_asinbf16",
+ hdrs = ["src/__support/math/asinbf16.h"],
+ deps = [
+ ":__support_fputil_bfloat16",
+ ":__support_fputil_cast",
+ ":__support_fputil_fenv_impl",
+ ":__support_fputil_fp_bits",
+ ":__support_fputil_multiply_add",
+ ":__support_fputil_polyeval",
+ ":__support_fputil_sqrt",
+ ":__support_macros_optimization",
+ ],
+)
+
libc_support_library(
name = "__support_math_asinf",
hdrs = ["src/__support/math/asinf.h"],
@@ -6561,6 +6576,13 @@ libc_math_function(
additional_deps = [":__support_math_asin"],
)
+libc_math_function(
+ name = "asinbf16",
+ additional_deps = [
+ ":__support_math_asinbf16",
+ ],
+)
+
libc_math_function(
name = "asinf",
additional_deps = [":__support_math_asinf"],
>From 03b8606e685108bcc56e621007febe44328162d5 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Mon, 2 Mar 2026 23:02:44 +0530
Subject: [PATCH 04/14] chore: clang
---
libc/src/__support/math/asinbf16.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 40fea2c7851d3..3c8d465ce0181 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -128,7 +128,7 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
// asin(x) = pi/2 - 2 * asin(sqrt((1-x)/2)) ; ---------------------------[2]
//[Note: check for inf rec (i.e should not output the same invalid interval
- //which could not be calculated precisely by taylor series)];
+ // which could not be calculated precisely by taylor series)]
// Here we choose an input interval where the values have less precision and
// use the formula to fold into the valid interval where we could generate
// precise values from taylor eg :- input (0,5,1] -> gets interval [0,1)
>From f22fdde2d82ae9f7688e3d0cc3b60331e60e9bf5 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 3 Mar 2026 11:22:36 +0530
Subject: [PATCH 05/14] chore: kept essential comments
chore: nit
chore: kept essential comments only
chore: format
---
libc/src/__support/math/asinbf16.h | 99 +++----------------------
libc/test/src/math/smoke/CMakeLists.txt | 12 +++
2 files changed, 23 insertions(+), 88 deletions(-)
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 3c8d465ce0181..64094e59b0859 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -18,39 +18,6 @@
#include "src/__support/FPUtil/sqrt.h"
#include "src/__support/macros/optimization.h"
-/*
- cases to consider and info
- sin (x) = opp/hypot
-
- // odd function -> sin(x) = sign(x) * sign(x)
- // sin(x + 2pi) = sin (x)
- // taylor series -> sin x= x - (x^3)/3! + x^5/(5!) - x^7/(7!)....
-
-
- //
- sin(pi-x) = sin(x)
- sin(pi+x) = -sin(x)
- sin(2*pi - x) = -sin(x)
- //
- sin(pi/2) = 1
- sin(pi/5) = sin(30) = 1/2
- sin(pi/4) = sin(45) = 1/root(2)
- sin(n*pi) = 0
-
-
- y = asin(x)
- // Domain E [-1,1]
- // Range E [-pi/2,pi/2]
-
- // properties
- 1. asin(x) = sign(x) * sin(x)
-
-
- // identities
-
- // taylor
-
-*/
namespace LIBC_NAMESPACE_DECL {
namespace math {
@@ -67,11 +34,13 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
uint16_t x_u = xbits.uintval();
uint16_t x_abs = x_u & 0x7fff;
float x_sign = (xbits.sign() == Sign::NEG) ? -1 : 1;
+ float xf = x;
- // x-> pi/2 => y -> 1
- // domain is E [-1,1]
- // |x| > 1, or NaN or infinity are invalid
- if (LIBC_UNLIKELY(x_abs > 0x3F80)) {
+ // case 1: |x|>=1, NaN or Inf
+ if (LIBC_UNLIKELY(x_abs >= 0x3F80)) {
+ if (x_abs == 0x3F80) {
+ return bfloat16(x_sign * PI_2);
+ }
// NaN
if (xbits.is_nan()) {
if (xbits.is_signaling_nan()) {
@@ -80,13 +49,13 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
}
return x; // quiet NaN
}
-
+ // |x|>1 & inf
fputil::raise_except_if_required(FE_INVALID);
fputil::set_errno_if_required(EDOM); // Domain is bounded
return FPBits::quiet_nan().get_val();
}
- // |x| = {0}
+ // case 2: |x| = {0}
if (LIBC_UNLIKELY(x_abs == 0))
return x; // with sign
@@ -94,50 +63,14 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
int rounding = fputil::quick_get_round();
if ((xbits.is_pos() && rounding == FE_UPWARD) ||
(xbits.is_neg() && rounding == FE_DOWNWARD)) {
- float xf = x;
return bfloat16(fputil::multiply_add(xf, 0x1.0p-13f, xf));
}
return x;
}
- // for |x| in (0,1] -> sign handles by sign(x) * sin(x)
- // Taylor series for asin(x)
- // asin(x) = x + x^3/6 + 3x^5/40 + ...
- // asin(x) = x * (1 + x^2/6 + 3x^4/40 + ...)
- // asin(x)/x = 1 + x^2/6 + 3x^4/40 + ...
- // asin(x)/x = P(x^2) ---------------------------[1]
-
- // As we approach towards 1 the precision decreases
- // above 0.89 it goes < 2^-6 error (increase)
- // So we find a recursive way to handle a range inside the valid range where
- // its more precise
- //
- // y = asin(x) -> sin(y) = x
- // x = sin(y) = cos(pi/2 - y)
- // Double angle formula -> cos(2A) = 1 - 2*sin^2(A)
- // sin(A) = sqrt((1-cos(2A))/2);
- // put z = 2A
- // if (z== (pi/2 - y)) here then we can say x = cos(z)
- // sin(z/2) = sqrt((1-cos(z))/2)
- // sin(z/2) = sqrt((1-x)/2)
- // z = 2 * asin(sqrt((1-x)/2));
-
- // since derivative of asin(x) = 1/sqrt(1-x^2) the errors increase as we
- // approach 1 so we use the recursive relation z = pi/2 - y = 2 *
- // asin(sqrt((1-x)/2)); y = pi/2 * 2 * asin(sqrt((1-x)/2)); since y = asin(x)
- // asin(x) = pi/2 - 2 * asin(sqrt((1-x)/2)) ; ---------------------------[2]
-
- //[Note: check for inf rec (i.e should not output the same invalid interval
- // which could not be calculated precisely by taylor series)]
- // Here we choose an input interval where the values have less precision and
- // use the formula to fold into the valid interval where we could generate
- // precise values from taylor eg :- input (0,5,1] -> gets interval [0,1)
-
- float xf = x;
float xf_abs = (xf < 0 ? -xf : xf);
float x_sq = xf_abs * xf_abs;
- // Minimax polynomial for asin(x)/x, returns P(u) as float
// Degree 6 polynomial of asin(x) generated using Sollya with command :
// > display = hexadecimal
// > P = fpminimax(asin(x)/x, [|0,2,4,6|], [|SG,SG,SG,SG|], [0, 0.5]);
@@ -146,24 +79,14 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
0x1.0a788p-4f);
};
- // for range: (0,0.5]
+ // case 3: (0,0.5]
if (x_abs <= 0x3F00) {
-
- // Remember:- asin(x)/x = P(x^2) -> (ref from [1])
- // asin(x) = x * P(x^2)
- // xf already carries the sign
float result = xf * asin_poly(x_sq);
return bfloat16(result);
}
- // remaining range: (0.5,1)
-
- // ref from [2]
- // asin(x) = pi/2 - 2 * asin(sqrt((1-x)/2))
- // let t = ((1-|x|)/2) = |x|*(-1/2) + 1/2
- // asin(sqrt(t)) = sqrt(t) * P(t)
- // asin(x) = sign * (pi/2 - 2 * sqrt(t) * P(t))
-
+ // case 4: (0.5,1)
+ // using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
float t_sqrt = fputil::sqrt<float>(t);
float asin_sqrt_t = t_sqrt * asin_poly(t);
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index d02a678fc8702..28b85b1a25bbd 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4898,6 +4898,18 @@ add_fp_unittest(
libc.src.math.acosf16
)
+add_fp_unittest(
+ acospif_test
+ SUITE
+ libc-math-smoke-tests
+ SRCS
+ acospif_test.cpp
+ DEPENDS
+ libc.hdr.errno_macros
+ libc.src.math.acospif
+ libc.src.__support.FPUtil.fp_bits
+)
+
add_fp_unittest(
acospif16_test
SUITE
>From f70ac29c3d77665690ad9820564942d68b3f4788 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 3 Mar 2026 20:46:51 +0530
Subject: [PATCH 06/14] chore: removed redundant tests and poly calc
---
libc/src/__support/math/CMakeLists.txt | 1 +
libc/src/__support/math/asinbf16.h | 14 ++---
libc/test/src/math/asinbf16_test.cpp | 11 ----
libc/test/src/math/exhaustive/CMakeLists.txt | 18 ------
.../src/math/exhaustive/asinbf16_test.cpp | 56 -------------------
5 files changed, 5 insertions(+), 95 deletions(-)
delete mode 100644 libc/test/src/math/exhaustive/asinbf16_test.cpp
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index e1409de79e6ca..8d739d4cc4bcf 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -395,6 +395,7 @@ add_header_library(
libc.src.__support.FPUtil.sqrt
libc.src.__support.macros.optimization
libc.src.__support.FPUtil.bfloat16
+ libc.src.__support.math.inv_trigf_utils
)
add_header_library(
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 64094e59b0859..3281ea7724bab 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -17,6 +17,7 @@
#include "src/__support/FPUtil/multiply_add.h"
#include "src/__support/FPUtil/sqrt.h"
#include "src/__support/macros/optimization.h"
+#include "src/__support/math/inv_trigf_utils.h"
namespace LIBC_NAMESPACE_DECL {
@@ -71,17 +72,10 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
float xf_abs = (xf < 0 ? -xf : xf);
float x_sq = xf_abs * xf_abs;
- // Degree 6 polynomial of asin(x) generated using Sollya with command :
- // > display = hexadecimal
- // > P = fpminimax(asin(x)/x, [|0,2,4,6|], [|SG,SG,SG,SG|], [0, 0.5]);
- auto asin_poly = [](float u) {
- return fputil::polyeval(u, 0x1.ffffcep-1f, 0x1.55b648p-3f, 0x1.24d192p-4f,
- 0x1.0a788p-4f);
- };
-
// case 3: (0,0.5]
if (x_abs <= 0x3F00) {
- float result = xf * asin_poly(x_sq);
+ // asin_eval returns P(x^2) - 1, where P(x^2) ~ asin(x)/x
+ float result = xf * ( 1.0 + inv_trigf_utils_internal::asin_eval(x_sq));
return bfloat16(result);
}
@@ -89,7 +83,7 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
// using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
float t_sqrt = fputil::sqrt<float>(t);
- float asin_sqrt_t = t_sqrt * asin_poly(t);
+ float asin_sqrt_t = t_sqrt * ( 1.0 + inv_trigf_utils_internal::asin_eval(t));
float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
return bfloat16(x_sign * result);
}
diff --git a/libc/test/src/math/asinbf16_test.cpp b/libc/test/src/math/asinbf16_test.cpp
index 55276883d52ed..0fef18133db2f 100644
--- a/libc/test/src/math/asinbf16_test.cpp
+++ b/libc/test/src/math/asinbf16_test.cpp
@@ -41,14 +41,3 @@ TEST_F(LlvmLibcAsinBf16Test, NegativeRange) {
LIBC_NAMESPACE::asinbf16(x), 0.5);
}
}
-
-TEST_F(LlvmLibcAsinBf16Test, SpecialNumbers) {
- constexpr bfloat16 VALUES[] = {zero, neg_zero, inf,
- neg_inf, min_normal, max_normal};
- for (size_t i = 0; i < 6; ++i) {
- bfloat16 x = VALUES[i];
-
- EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
- LIBC_NAMESPACE::asinbf16(x), 0.5);
- }
-}
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 5e5f3f0adf083..2d1301d3a1e66 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -650,24 +650,6 @@ add_fp_unittest(
libc.src.__support.math.atanf
)
-
-add_fp_unittest(
- asinbf16_test
- NO_RUN_POSTBUILD
- NEED_MPFR
- SUITE
- libc_math_exhaustive_tests
- SRCS
- asinbf16_test.cpp
- DEPENDS
- .exhaustive_test
- libc.src.math.asinbf16
- libc.src.__support.FPUtil.fp_bits
- libc.src.__support.FPUtil.bfloat16
- LINK_LIBRARIES
- -lpthread
-)
-
add_fp_unittest(
asinf_test
NO_RUN_POSTBUILD
diff --git a/libc/test/src/math/exhaustive/asinbf16_test.cpp b/libc/test/src/math/exhaustive/asinbf16_test.cpp
deleted file mode 100644
index 85f0b811b2c8d..0000000000000
--- a/libc/test/src/math/exhaustive/asinbf16_test.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-//===-- Exhaustive test for asinbf16 --------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "src/__support/FPUtil/bfloat16.h"
-#include "src/math/asinbf16.h"
-#include "test/UnitTest/FPMatcher.h"
-#include "test/UnitTest/Test.h"
-#include "utils/MPFRWrapper/MPFRUtils.h"
-
-using LlvmLibcAsinBf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
-
-namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
-
-// Normal range: [+0, +int]
-static constexpr uint16_t POS_START = 0x0000U;
-static constexpr uint16_t POS_STOP = 0x7f80U;
-
-// Normal range: [-0, -int]
-static constexpr uint16_t NEG_START = 0x8000U;
-static constexpr uint16_t NEG_STOP = 0xff80U;
-
-TEST_F(LlvmLibcAsinBf16Test, NormalPositiveRange) {
- for (uint16_t v1 = POS_START; v1 <= POS_STOP; v1++) {
-
- bfloat16 x = FPBits(v1).get_val();
-
- EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
- LIBC_NAMESPACE::asinbf16(x), 0.5);
- }
-}
-
-TEST_F(LlvmLibcAsinBf16Test, NormalNegativeRange) {
- for (uint16_t v1 = NEG_START; v1 <= NEG_STOP; v1++) {
-
- bfloat16 x = FPBits(v1).get_val();
-
- EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
- LIBC_NAMESPACE::asinbf16(x), 0.5);
- }
-}
-
-TEST_F(LlvmLibcAsinBf16Test, SpecialNumbers) {
- constexpr bfloat16 VALUES[] = {zero, neg_zero, inf,
- neg_inf, min_normal, max_normal};
- for (size_t i = 0; i < 6; ++i) {
- bfloat16 x = VALUES[i];
-
- EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
- LIBC_NAMESPACE::asinbf16(x), 0.5);
- }
-}
>From 48bce7bbd06a4f1572cffe7245d6963999477c4f Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 3 Mar 2026 20:59:37 +0530
Subject: [PATCH 07/14] chore: removed polyeval and typcasted properly to
intermediate float
---
libc/src/__support/math/CMakeLists.txt | 1 -
libc/src/__support/math/asinbf16.h | 15 ++++++++-------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 8d739d4cc4bcf..c7a4b49a7fe94 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -389,7 +389,6 @@ add_header_library(
DEPENDS
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.multiply_add
libc.src.__support.FPUtil.sqrt
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 3281ea7724bab..a7f5f910b40f0 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -11,7 +11,6 @@
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
#include "src/__support/FPUtil/bfloat16.h"
#include "src/__support/FPUtil/cast.h"
#include "src/__support/FPUtil/multiply_add.h"
@@ -40,7 +39,7 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
// case 1: |x|>=1, NaN or Inf
if (LIBC_UNLIKELY(x_abs >= 0x3F80)) {
if (x_abs == 0x3F80) {
- return bfloat16(x_sign * PI_2);
+ return fputil::cast<bfloat16>(x_sign * PI_2);
}
// NaN
if (xbits.is_nan()) {
@@ -64,7 +63,7 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
int rounding = fputil::quick_get_round();
if ((xbits.is_pos() && rounding == FE_UPWARD) ||
(xbits.is_neg() && rounding == FE_DOWNWARD)) {
- return bfloat16(fputil::multiply_add(xf, 0x1.0p-13f, xf));
+ return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-13f, xf));
}
return x;
}
@@ -75,17 +74,19 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
// case 3: (0,0.5]
if (x_abs <= 0x3F00) {
// asin_eval returns P(x^2) - 1, where P(x^2) ~ asin(x)/x
- float result = xf * ( 1.0 + inv_trigf_utils_internal::asin_eval(x_sq));
- return bfloat16(result);
+ float result = xf * static_cast<float>(
+ 1.0 + inv_trigf_utils_internal::asin_eval(x_sq));
+ return fputil::cast<bfloat16>(result);
}
// case 4: (0.5,1)
// using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
float t_sqrt = fputil::sqrt<float>(t);
- float asin_sqrt_t = t_sqrt * ( 1.0 + inv_trigf_utils_internal::asin_eval(t));
+ float asin_sqrt_t =
+ t_sqrt * static_cast<float>(1.0 + inv_trigf_utils_internal::asin_eval(t));
float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
- return bfloat16(x_sign * result);
+ return fputil::cast<bfloat16>(x_sign * result);
}
} // namespace math
>From c7f83660562659511b81fad272f164e14d96c9ab Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 3 Mar 2026 21:33:20 +0530
Subject: [PATCH 08/14] fix: proper usage of asin_eval
---
libc/src/__support/math/asinbf16.h | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index a7f5f910b40f0..2ea9d61b874b7 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -33,7 +33,7 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
uint16_t x_u = xbits.uintval();
uint16_t x_abs = x_u & 0x7fff;
- float x_sign = (xbits.sign() == Sign::NEG) ? -1 : 1;
+ float x_sign = (x_u >> 15) ? -1 : 1;
float xf = x;
// case 1: |x|>=1, NaN or Inf
@@ -73,9 +73,9 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
// case 3: (0,0.5]
if (x_abs <= 0x3F00) {
- // asin_eval returns P(x^2) - 1, where P(x^2) ~ asin(x)/x
- float result = xf * static_cast<float>(
- 1.0 + inv_trigf_utils_internal::asin_eval(x_sq));
+ double xp = inv_trigf_utils_internal::asin_eval(x_sq);
+ float result =
+ xf * static_cast<float>(fputil::multiply_add<double>(x_sq, xp, 1.0));
return fputil::cast<bfloat16>(result);
}
@@ -83,8 +83,9 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
// using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
float t_sqrt = fputil::sqrt<float>(t);
+ double tp = inv_trigf_utils_internal::asin_eval(t);
float asin_sqrt_t =
- t_sqrt * static_cast<float>(1.0 + inv_trigf_utils_internal::asin_eval(t));
+ t_sqrt * static_cast<float>(fputil::multiply_add<double>(t, tp, 1.0));
float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
return fputil::cast<bfloat16>(x_sign * result);
}
>From 497f3e5f67036bb16c7c5b4cb720af570a8aa091 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Wed, 4 Mar 2026 21:44:54 +0530
Subject: [PATCH 09/14] chore: nit
---
libc/src/math/asinbf16.h | 3 +--
libc/src/math/generic/asinbf16.cpp | 2 +-
libc/test/src/math/CMakeLists.txt | 2 +-
utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 2 +-
4 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/libc/src/math/asinbf16.h b/libc/src/math/asinbf16.h
index 9c2f1fea51e61..06780cb101018 100644
--- a/libc/src/math/asinbf16.h
+++ b/libc/src/math/asinbf16.h
@@ -1,5 +1,4 @@
-//===-- Implementation header for asinbf16 -----------------------*- C++
-//-*-===//
+//===-- Implementation header for asinbf16 ----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/src/math/generic/asinbf16.cpp b/libc/src/math/generic/asinbf16.cpp
index a197e9d300d32..876d3bbe646ed 100644
--- a/libc/src/math/generic/asinbf16.cpp
+++ b/libc/src/math/generic/asinbf16.cpp
@@ -1,4 +1,4 @@
-//===-- Half-precision asinbf16(x) function -------------------------------===//
+//===-- Implementation for asinbf16(x) function ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 8171ce03d3aba..5fcd8ac49fea3 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2521,7 +2521,7 @@ add_fp_unittest(
SRCS
asinbf16_test.cpp
DEPENDS
- libc.src.math.asinbf16
+ libc.src.math.asinbf16
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.bfloat16
)
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 7fdc6e46305c0..3819d39a329b7 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -3374,9 +3374,9 @@ libc_support_library(
":__support_fputil_fenv_impl",
":__support_fputil_fp_bits",
":__support_fputil_multiply_add",
- ":__support_fputil_polyeval",
":__support_fputil_sqrt",
":__support_macros_optimization",
+ ":__support_math_inv_trigf_utils",
],
)
>From 656dbe6eaf982d1c646fcbaf43f5f7f23403648a Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 14 Mar 2026 09:19:12 +0530
Subject: [PATCH 10/14] removed constexpr
---
libc/src/__support/math/CMakeLists.txt | 1 -
libc/src/__support/math/asinbf16.h | 2 +-
libc/src/math/generic/asinbf16.cpp | 1 -
3 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index c7a4b49a7fe94..c13d182303850 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -381,7 +381,6 @@ add_header_library(
libc.src.__support.macros.optimization
)
-
add_header_library(
asinbf16
HDRS
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 2ea9d61b874b7..81f6433b02759 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -22,7 +22,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
+LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
// Generated by Sollya using the following command:
// > display = hexadecimal;
// > round(pi/2, SG, RN);
diff --git a/libc/src/math/generic/asinbf16.cpp b/libc/src/math/generic/asinbf16.cpp
index 876d3bbe646ed..acaeef0c6ef55 100644
--- a/libc/src/math/generic/asinbf16.cpp
+++ b/libc/src/math/generic/asinbf16.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "src/math/asinbf16.h"
-#include "src/__support/FPUtil/bfloat16.h"
#include "src/__support/math/asinbf16.h"
namespace LIBC_NAMESPACE_DECL {
>From 403e1407b827fe43fe40d72f5a12c31cb3d92703 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 28 Mar 2026 11:58:15 +0530
Subject: [PATCH 11/14] nit
---
libc/test/src/math/CMakeLists.txt | 1 -
1 file changed, 1 deletion(-)
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 5fcd8ac49fea3..97ede9b1c9f8d 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2512,7 +2512,6 @@ add_fp_unittest(
libc.src.math.asin
)
-
add_fp_unittest(
asinbf16_test
NEED_MPFR
>From cf13e4313def4d4a900d8958ec5eae0a96f96a7f Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 28 Mar 2026 21:35:24 +0530
Subject: [PATCH 12/14] chore: branches and (float)
---
libc/src/__support/math/asinbf16.h | 90 +++++++++++++++---------------
1 file changed, 45 insertions(+), 45 deletions(-)
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 81f6433b02759..ed327cea101c6 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -19,7 +19,6 @@
#include "src/__support/math/inv_trigf_utils.h"
namespace LIBC_NAMESPACE_DECL {
-
namespace math {
LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
@@ -36,62 +35,63 @@ LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
float x_sign = (x_u >> 15) ? -1 : 1;
float xf = x;
- // case 1: |x|>=1, NaN or Inf
- if (LIBC_UNLIKELY(x_abs >= 0x3F80)) {
- if (x_abs == 0x3F80) {
- return fputil::cast<bfloat16>(x_sign * PI_2);
- }
- // NaN
- if (xbits.is_nan()) {
- if (xbits.is_signaling_nan()) {
- fputil::raise_except_if_required(FE_INVALID);
- return FPBits::quiet_nan().get_val();
- }
- return x; // quiet NaN
- }
- // |x|>1 & inf
- fputil::raise_except_if_required(FE_INVALID);
- fputil::set_errno_if_required(EDOM); // Domain is bounded
- return FPBits::quiet_nan().get_val();
- }
-
- // case 2: |x| = {0}
- if (LIBC_UNLIKELY(x_abs == 0))
- return x; // with sign
-
- if (LIBC_UNLIKELY(x_abs <= 0x3D00)) {
- int rounding = fputil::quick_get_round();
- if ((xbits.is_pos() && rounding == FE_UPWARD) ||
- (xbits.is_neg() && rounding == FE_DOWNWARD)) {
- return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-13f, xf));
- }
- return x;
- }
-
float xf_abs = (xf < 0 ? -xf : xf);
float x_sq = xf_abs * xf_abs;
- // case 3: (0,0.5]
+ // Case 1: |x| <= 0.5
if (x_abs <= 0x3F00) {
- double xp = inv_trigf_utils_internal::asin_eval(x_sq);
+ // |x| = {0}
+ if (LIBC_UNLIKELY(x_abs == 0))
+ return x; // with sign
+
+ if (LIBC_UNLIKELY(x_abs <= 0x3D00)) {
+ int rounding = fputil::quick_get_round();
+ if ((xbits.is_pos() && rounding == FE_UPWARD) ||
+ (xbits.is_neg() && rounding == FE_DOWNWARD)) {
+ return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-9f, xf));
+ }
+ return x;
+ }
+
+ float xp = fputil::cast<float>(inv_trigf_utils_internal::asin_eval(x_sq));
float result =
- xf * static_cast<float>(fputil::multiply_add<double>(x_sq, xp, 1.0));
+ xf * static_cast<float>(fputil::multiply_add<float>(x_sq, xp, 1.0));
return fputil::cast<bfloat16>(result);
}
- // case 4: (0.5,1)
+ // Case 2: 0.5 <|x| <= 1
// using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
- float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
- float t_sqrt = fputil::sqrt<float>(t);
- double tp = inv_trigf_utils_internal::asin_eval(t);
- float asin_sqrt_t =
- t_sqrt * static_cast<float>(fputil::multiply_add<double>(t, tp, 1.0));
- float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
- return fputil::cast<bfloat16>(x_sign * result);
+ if (x_abs <= 0x3F80 && x_abs > 0x3F00) {
+ // |x| = {1}
+ if (LIBC_UNLIKELY(x_abs == 0x3F80)) {
+ return fputil::cast<bfloat16>(x_sign * PI_2);
+ }
+
+ float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
+ float t_sqrt = fputil::sqrt<float>(t);
+ float tp = fputil::cast<float>(inv_trigf_utils_internal::asin_eval(t));
+ float asin_sqrt_t =
+ t_sqrt * static_cast<float>(fputil::multiply_add<float>(t, tp, 1.0));
+ float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
+ return fputil::cast<bfloat16>(x_sign * result);
+ }
+
+ // Case 3: NaN and Inf
+ // NaN
+ if (xbits.is_nan()) {
+ if (xbits.is_signaling_nan()) {
+ fputil::raise_except_if_required(FE_INVALID);
+ return FPBits::quiet_nan().get_val();
+ }
+ return x; // quiet NaN
+ }
+ // |x|>1 & inf
+ fputil::raise_except_if_required(FE_INVALID);
+ fputil::set_errno_if_required(EDOM); // Domain is bounded
+ return FPBits::quiet_nan().get_val();
}
} // namespace math
-
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINBF16_H
>From 06fc7d54eb4aa09607295fe0c5d7eb94781f4715 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 28 Mar 2026 21:52:22 +0530
Subject: [PATCH 13/14] nits
---
libc/src/__support/math/asinbf16.h | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index ed327cea101c6..d6935f0d6bada 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -39,7 +39,7 @@ LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
float x_sq = xf_abs * xf_abs;
// Case 1: |x| <= 0.5
- if (x_abs <= 0x3F00) {
+ if (x_abs <= 0x3F00) { // x_abs <= 0.5
// |x| = {0}
if (LIBC_UNLIKELY(x_abs == 0))
return x; // with sign
@@ -54,14 +54,13 @@ LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
}
float xp = fputil::cast<float>(inv_trigf_utils_internal::asin_eval(x_sq));
- float result =
- xf * static_cast<float>(fputil::multiply_add<float>(x_sq, xp, 1.0));
+ float result = xf * (fputil::multiply_add<float>(x_sq, xp, 1.0f));
return fputil::cast<bfloat16>(result);
}
// Case 2: 0.5 <|x| <= 1
// using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
- if (x_abs <= 0x3F80 && x_abs > 0x3F00) {
+ if (x_abs <= 0x3F80) { // x_abs <= 1
// |x| = {1}
if (LIBC_UNLIKELY(x_abs == 0x3F80)) {
return fputil::cast<bfloat16>(x_sign * PI_2);
@@ -70,8 +69,7 @@ LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
float t_sqrt = fputil::sqrt<float>(t);
float tp = fputil::cast<float>(inv_trigf_utils_internal::asin_eval(t));
- float asin_sqrt_t =
- t_sqrt * static_cast<float>(fputil::multiply_add<float>(t, tp, 1.0));
+ float asin_sqrt_t = t_sqrt * (fputil::multiply_add<float>(t, tp, 1.0f));
float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
return fputil::cast<bfloat16>(x_sign * result);
}
>From 6eda2aa1a1c46f202c2d25a5680c64692f0178ca Mon Sep 17 00:00:00 2001
From: bassiounix <muhammad.m.bassiouni at gmail.com>
Date: Mon, 30 Mar 2026 19:59:36 +0200
Subject: [PATCH 14/14] enable constant evaluation support
---
libc/src/__support/FPUtil/sqrt.h | 5 +++--
libc/src/__support/math/acoshf_utils.h | 2 +-
libc/src/__support/math/asinbf16.h | 2 +-
libc/src/__support/math/inv_trigf_utils.h | 2 +-
libc/test/shared/CMakeLists.txt | 9 ++++++++-
libc/test/shared/shared_math_constexpr_test.cpp | 4 ++++
6 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/libc/src/__support/FPUtil/sqrt.h b/libc/src/__support/FPUtil/sqrt.h
index d4ed744b4010d..308de73b0dbcd 100644
--- a/libc/src/__support/FPUtil/sqrt.h
+++ b/libc/src/__support/FPUtil/sqrt.h
@@ -15,8 +15,9 @@
#include "src/__support/FPUtil/generic/sqrt.h"
// Generic instruction specializations with __builtin_elementwise_sqrt.
-#if defined(LIBC_TARGET_CPU_HAS_FPU_FLOAT) || \
- defined(LIBC_TARGET_CPU_HAS_FPU_DOUBLE)
+#if !defined(LIBC_HAS_CONSTANT_EVALUATION) && \
+ (defined(LIBC_TARGET_CPU_HAS_FPU_FLOAT) || \
+ defined(LIBC_TARGET_CPU_HAS_FPU_DOUBLE))
#if __has_builtin(__builtin_elementwise_sqrt)
diff --git a/libc/src/__support/math/acoshf_utils.h b/libc/src/__support/math/acoshf_utils.h
index 8a8e2caccc765..3d760f9835249 100644
--- a/libc/src/__support/math/acoshf_utils.h
+++ b/libc/src/__support/math/acoshf_utils.h
@@ -99,7 +99,7 @@ LIBC_INLINE LIBC_CONSTEXPR double log_eval(double x) {
uint64_t x_m = (x_u & FPBits::FRACTION_MASK) | FPBits::one().uintval();
double m = FPBits(x_m).get_val();
- double dx;
+ double dx = 0.0;
// Perform exact range reduction
#ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index d6935f0d6bada..52c4da3e5a1dc 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -21,7 +21,7 @@
namespace LIBC_NAMESPACE_DECL {
namespace math {
-LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
+LIBC_INLINE LIBC_CONSTEXPR bfloat16 asinbf16(bfloat16 x) {
// Generated by Sollya using the following command:
// > display = hexadecimal;
// > round(pi/2, SG, RN);
diff --git a/libc/src/__support/math/inv_trigf_utils.h b/libc/src/__support/math/inv_trigf_utils.h
index 558d91760f8f9..e30eaeb3a3f9a 100644
--- a/libc/src/__support/math/inv_trigf_utils.h
+++ b/libc/src/__support/math/inv_trigf_utils.h
@@ -171,7 +171,7 @@ LIBC_INLINE_VAR constexpr double ASIN_COEFFS[12] = {
};
// Evaluate P(x^2) - 1, where P(x^2) ~ asin(x)/x
-LIBC_INLINE double asin_eval(double xsq) {
+LIBC_INLINE LIBC_CONSTEXPR double asin_eval(double xsq) {
double x4 = xsq * xsq;
double c0 = fputil::multiply_add(xsq, ASIN_COEFFS[1], ASIN_COEFFS[0]);
double c1 = fputil::multiply_add(xsq, ASIN_COEFFS[3], ASIN_COEFFS[2]);
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 88b6fc566d1ec..8710b0513d23b 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -267,5 +267,12 @@ add_fp_unittest(
SRCS
shared_math_constexpr_test.cpp
DEPENDS
- .shared_math_test
+ libc.src.__support.math.asinbf16
+ libc.src.__support.math.ceil
+ libc.src.__support.math.ceilbf16
+ libc.src.__support.math.ceilf
+ libc.src.__support.math.ceilf128
+ libc.src.__support.math.ceilf16
+ libc.src.__support.math.ceill
+ libc.src.__support.math.log
)
diff --git a/libc/test/shared/shared_math_constexpr_test.cpp b/libc/test/shared/shared_math_constexpr_test.cpp
index 69ff3ec46e8b3..e5e233fae3e13 100644
--- a/libc/test/shared/shared_math_constexpr_test.cpp
+++ b/libc/test/shared/shared_math_constexpr_test.cpp
@@ -9,6 +9,7 @@
#define LIBC_ENABLE_CONSTEXPR 1
#include "shared/math.h"
+#include "test/UnitTest/Test.h"
//===----------------------------------------------------------------------===//
// Double Tests
@@ -59,5 +60,8 @@ static_assert(float128(0x0p+0) ==
// BFloat16 Tests
//===----------------------------------------------------------------------===//
+static_assert(bfloat16(0.0) == LIBC_NAMESPACE::shared::asinbf16(bfloat16(0.0)));
static_assert(bfloat16(0x0p+0) ==
LIBC_NAMESPACE::shared::ceilbf16(bfloat16(0.0)));
+
+TEST(LlvmLibcSharedMathTest, ConstantEvaluation) {}
More information about the llvm-commits
mailing list