[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