[libc-commits] [libc] [llvm] [libc][math][c23] Add asinbf16 math function (PR #184170)
via libc-commits
libc-commits at lists.llvm.org
Sat Mar 21 08:25:34 PDT 2026
https://github.com/Sukumarsawant updated https://github.com/llvm/llvm-project/pull/184170
>From b1fd8686440af80d5ed4103aac6ca6fafab6027c 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/10] 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 30ffd3f0f874039571991c32f2e3b3f8e0c1813a 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/10] 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 84600efc5e0d1..05d25c95df32f 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -790,6 +790,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 902f6ed44179b..a4114c5894492 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -800,6 +800,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 30f9bccd22214..2d71b58c9f836 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -796,6 +796,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 4d27e994323fd..bb72ab3094bce 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -609,6 +609,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 7aaf3470dceab..059bb0c4253cd 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -624,6 +624,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 96c0902d729dc..6492f04e26968 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -626,6 +626,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 d6569e59a3e5f..07aefe21df143 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -870,6 +870,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 9fd45329ad0f9..b37f59e38b3d2 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -476,6 +476,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 fdfce36b824f0..75470de6b8ae0 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -891,6 +891,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 8cceaccc314dc..d286549c61103 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -946,6 +946,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 ee8072a3465e5..ebbbefdedfa94 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -322,6 +322,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 66f87d3367f29c24830f84709c82635f92198f24 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/10] 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 202ef034b8ace..e8ece1ba5951c 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 3d81216f1bcfb..63e8c28cd288e 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 6266b26b81ba8..7ef77563c83f6 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -362,6 +362,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 5bdb8d99eedeb..b6dffda8b31c8 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 fdc3fa777d1fa..a31579e684058 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -4072,6 +4072,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 36262012ad0f0..27bda41749e21 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 341b35a7b7e0f..66960284f070d 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -423,6 +423,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 ceed946e2386e..fab01a18ada87 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2501,6 +2501,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 9d97c90cfaeb9..b54b38f83810d 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4814,6 +4814,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
@@ -4860,18 +4873,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 491e846cbe49a..1f26a47fc11bc 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -3143,6 +3143,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"],
@@ -6312,6 +6327,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 bcf7075c7de2e0be9cdf3ab39a1d23796ecbb70e 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/10] 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 21372910bdfcf6550d6df266761bcaa1265fd404 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/10] 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 b54b38f83810d..bb85ffc78fa00 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4873,6 +4873,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 15b7cd770b04784568760276158901ef2a462869 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/10] 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 7ef77563c83f6..f468c72d389ee 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -376,6 +376,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 8219353768728a38fd7d6b4787ff4c61ee15377a 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/10] 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 f468c72d389ee..8b611c6a418cc 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -370,7 +370,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 289480088795987084f5feaec8d5f899c4f8968c 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/10] 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 876c1606538585917baf89d218a563c325a89889 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/10] 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 fab01a18ada87..a905aae345411 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2510,7 +2510,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 1f26a47fc11bc..ca25251ab2c2c 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -3152,9 +3152,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 f614cd8ecce04b4507d0871a6cc5f74f6d6f7576 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/10] 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 8b611c6a418cc..620222be8110f 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -362,7 +362,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 {
More information about the libc-commits
mailing list