[libc] [llvm] [libc][math][c23] Add asinbf16 math function (PR #184170)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 2 21:53:19 PST 2026
https://github.com/Sukumarsawant updated https://github.com/llvm/llvm-project/pull/184170
>From 8cc4eac864f96bbbc30e023c93c02651e2188216 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Mon, 2 Mar 2026 19:01:06 +0530
Subject: [PATCH 1/5] 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 a378ad65a7c40b210de929fc85aad131a46a1075 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Mon, 2 Mar 2026 19:04:40 +0530
Subject: [PATCH 2/5] 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 1c04ee2b6d040..1d6cebda8e9f6 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -776,6 +776,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
+ 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 ad6b6d922b57a..25fb20228cf60 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -779,6 +779,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
+ 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 29be47dfbfd53..437ab69f32778 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -777,6 +777,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
+ 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 b4a1ee70764cb..265703974ef91 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -593,6 +593,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
+ 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 e899bf97ea3f6..21dc4c84d97a8 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -233,6 +233,7 @@ set(TARGET_LIBM_ENTRYPOINTS
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
+ 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 a65b6f0274fd8..c81c9c3ef716d 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -618,6 +618,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
+ 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 fee0038c88cc0..49bb420c12a37 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -620,6 +620,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
+ 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 960958b7cf90a..d0513961fdbc3 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -849,6 +849,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
+ 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 e76bf81670ce5..8ed89ff0e4522 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -462,6 +462,7 @@ set(TARGET_LIBM_ENTRYPOINTS
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
+ 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 a69d1a1b0a642..f94878d769cc7 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -870,6 +870,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
+ 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 bb4973628d588..1846793d1b475 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -917,6 +917,7 @@ endif()
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
+ 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 f777fc6c94bc2..81469db6c23b0 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -308,6 +308,7 @@ set(TARGET_LIBM_ENTRYPOINTS
list(APPEND TARGET_LIBM_ENTRYPOINTS
# bfloat16 entrypoints
+ libc.src.math.asinbf16
libc.src.math.bf16add
libc.src.math.bf16addf
libc.src.math.bf16addl
>From bf30f87da7dbf808df044d7f951b45f9a1de4bd1 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Mon, 2 Mar 2026 19:34:56 +0530
Subject: [PATCH 3/5] 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 7ea54fb4d8263..e7a2c808b0fad 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -269,7 +269,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 a7d735ffa1746..33deb7d22d570 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 3bb8e76a54bfb..e9787b2ba0ceb 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -331,6 +331,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(
asinf
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 e617950368994..94a9b8df05f00 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 f8ec25be61d12..d28aa8cd687c4 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -4053,6 +4053,16 @@ add_entrypoint_object(
libc.src.__support.macros.properties.types
)
+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 a04a15cdabcb7..4bf22acafa72e 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 460449e4fcb2e..65c18746bf3ff 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -406,6 +406,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat128) {
TEST(LlvmLibcSharedMathTest, AllBFloat16) {
using FPBits = LIBC_NAMESPACE::fputil::FPBits<bfloat16>;
+ 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 73b5ebf5a856e..b839e8f53841a 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2465,6 +2465,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 a21e208312c56..6ec56e43c1658 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -597,6 +597,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 3d52873c40bb8..4f8da5b78fcbf 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4773,6 +4773,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
@@ -4819,18 +4832,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 c6ed630ab02a8..37b57945e914c 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -2976,6 +2976,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"],
@@ -5915,6 +5930,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 dd0b7b0a1440976f743dd244b7e5e398f279e9f3 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Mon, 2 Mar 2026 23:02:44 +0530
Subject: [PATCH 4/5] 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 39f63c2829e84fc5ba6f1be14d9b40c4ba98ef14 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 3 Mar 2026 11:22:36 +0530
Subject: [PATCH 5/5] chore: nit
---
libc/test/src/math/smoke/CMakeLists.txt | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 4f8da5b78fcbf..c1cc04453aa80 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4832,6 +4832,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
More information about the llvm-commits
mailing list