[libc] [llvm] [libc][math][c23] Add asinbf16 math function (PR #184170)

Muhammad Bassiouni via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 30 10:59:59 PDT 2026


https://github.com/bassiounix updated https://github.com/llvm/llvm-project/pull/184170

>From e503b0fc2a2e93c528677eea0794e200e2eccbbd Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Mon, 2 Mar 2026 19:01:06 +0530
Subject: [PATCH 01/14] feat: implementation for asinbf16

---
 libc/src/__support/math/asinbf16.h | 168 +++++++++++++++++++++++++++++
 1 file changed, 168 insertions(+)
 create mode 100644 libc/src/__support/math/asinbf16.h

diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
new file mode 100644
index 0000000000000..681743662729a
--- /dev/null
+++ b/libc/src/__support/math/asinbf16.h
@@ -0,0 +1,168 @@
+//===-- Implementation header for asinbf16 ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ASINBF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_ASINBF16_H
+
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/macros/optimization.h"
+
+/*
+    cases to consider and info
+    sin (x) = opp/hypot
+
+    // odd function -> sin(x) = sign(x) * sign(x)
+    // sin(x + 2pi) = sin (x)
+    // taylor series -> sin x= x - (x^3)/3! + x^5/(5!) - x^7/(7!)....
+
+
+    //
+    sin(pi-x) = sin(x)
+    sin(pi+x) = -sin(x)
+    sin(2*pi - x) = -sin(x)
+    //
+    sin(pi/2) = 1
+    sin(pi/5) = sin(30) = 1/2
+    sin(pi/4) = sin(45) = 1/root(2)
+    sin(n*pi) = 0
+
+
+    y  = asin(x)
+    // Domain E [-1,1]
+    // Range E [-pi/2,pi/2]
+
+    // properties
+        1. asin(x) = sign(x) * sin(x)
+
+
+    // identities
+
+    // taylor
+
+*/
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE constexpr bfloat16 asinf16(bfloat16 x) {
+  // Generated by Sollya using the following command:
+  // > display = hexadecimal;
+  // > round(pi/2, SG, RN);
+  constexpr float PI_2 = 0x1.921fb6p0f;
+
+  using FPBits = fputil::FPBits<bfloat16>;
+  FPBits xbits(x);
+
+  uint16_t x_u = xbits.uintval();
+  uint16_t x_abs = x_u & 0x7fff;
+  float x_sign = (xbits.sign() == Sign::NEG) ? -1 : 1;
+
+  // x-> pi/2  => y -> 1
+  // domain is E [-1,1]
+  // |x| > 1, or NaN or infinity are invalid
+  if (LIBC_UNLIKELY(x_abs > 0x3F80)) {
+    // NaN
+    if (xbits.is_nan()) {
+      if (xbits.is_signaling_nan()) {
+        fputil::raise_except_if_required(FE_INVALID);
+        return FPBits::quiet_nan().get_val();
+      }
+      return x; // quiet NaN
+    }
+
+    fputil::raise_except_if_required(FE_INVALID);
+    fputil::set_errno_if_required(EDOM); // Domain is bounded
+    return FPBits::quiet_nan().get_val();
+  }
+
+  // |x| = {0}
+  if (LIBC_UNLIKELY(x_abs == 0))
+    return x; // with sign
+
+  // for |x| in (0,1] -> sign handles by sign(x) * sin(x)
+  // Taylor series for asin(x)
+  // asin(x) = x + x^3/6 + 3x^5/40 + ...
+  // asin(x) = x * (1 + x^2/6 + 3x^4/40 + ...)
+  // asin(x)/x = 1 + x^2/6 + 3x^4/40 + ...
+  // asin(x)/x = P(x^2) ---------------------------[1]
+
+  // As we approach towards 1 the precision decreases
+  // above 0.89 it goes < 2^-6 error (increase)
+  // So we find a recursive way to handle a range inside the valid range where
+  // its more precise
+  //
+  // y = asin(x)  -> sin(y) = x
+  // x = sin(y) = cos(pi/2 - y)
+  // Double angle formula -> cos(2A) = 1 - 2*sin^2(A)
+  // sin(A) = sqrt((1-cos(2A))/2);
+  // put z = 2A
+  // if (z== (pi/2 - y)) here then we can say x = cos(z)
+  // sin(z/2) = sqrt((1-cos(z))/2)
+  // sin(z/2) = sqrt((1-x)/2)
+  // z = 2 * asin(sqrt((1-x)/2));
+
+  // since derivative of asin(x) = 1/sqrt(1-x^2) the errors increase as we
+  // approach 1 so we use the recursive relation z = pi/2 - y = 2 *
+  // asin(sqrt((1-x)/2)); y = pi/2 * 2 * asin(sqrt((1-x)/2)); since y = asin(x)
+  // asin(x) = pi/2 - 2 * asin(sqrt((1-x)/2)) ; ---------------------------[2]
+
+  //[Note: check for inf rec (i.e should not output the same invalid interval
+  //which could not be calculated precisely by taylor series)];
+  // Here we choose an input interval where the values have less precision and
+  // use the formula to fold into the valid interval where we could generate
+  // precise values from taylor eg :- input (0,5,1] -> gets interval [0,1)
+
+  float xf = x;
+  float xf_abs = (xf < 0 ? -xf : xf);
+  float x_sq = xf_abs * xf_abs;
+
+  // Minimax polynomial for asin(x)/x, returns P(u) as float
+  // Degree 6 polynomial of asin(x) generated using Sollya with command :
+  // > display = hexadecimal
+  // > P = fpminimax(asin(x)/x, [|0,2,4,6|], [|SG,SG,SG,SG|], [0, 0.5]);
+  auto asin_poly = [](float u) {
+    return fputil::polyeval(u, 0x1.ffffcep-1f, 0x1.55b648p-3f, 0x1.24d192p-4f,
+                            0x1.0a788p-4f);
+  };
+
+  // for range: (0,0.5]
+  if (x_abs <= 0x3F00) {
+
+    // Remember:- asin(x)/x = P(x^2) -> (ref from [1])
+    // asin(x) = x * P(x^2)
+    // xf already carries the sign
+    float result = xf * asin_poly(x_sq);
+    return bfloat16(result);
+  }
+
+  // remaining range: (0.5,1)
+
+  // ref from [2]
+  // asin(x) = pi/2 - 2 * asin(sqrt((1-x)/2))
+  // let t = ((1-|x|)/2) = |x|*(-1/2) + 1/2
+  // asin(sqrt(t)) = sqrt(t) * P(t)
+  // asin(x) = sign * (pi/2 - 2 * sqrt(t) * P(t))
+
+  float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
+  float t_sqrt = fputil::sqrt<float>(t);
+  float asin_sqrt_t = t_sqrt * asin_poly(t);
+  float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
+  return bfloat16(x_sign * result);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINF16_H

>From 8f568b2d5bed19cb0ad99a407b52f0c33478b750 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Mon, 2 Mar 2026 19:04:40 +0530
Subject: [PATCH 02/14] chore: entrypoints added

---
 libc/config/baremetal/aarch64/entrypoints.txt | 1 +
 libc/config/baremetal/arm/entrypoints.txt     | 1 +
 libc/config/baremetal/riscv/entrypoints.txt   | 1 +
 libc/config/darwin/aarch64/entrypoints.txt    | 1 +
 libc/config/darwin/x86_64/entrypoints.txt     | 1 +
 libc/config/gpu/amdgpu/entrypoints.txt        | 1 +
 libc/config/gpu/nvptx/entrypoints.txt         | 1 +
 libc/config/linux/aarch64/entrypoints.txt     | 1 +
 libc/config/linux/arm/entrypoints.txt         | 1 +
 libc/config/linux/riscv/entrypoints.txt       | 1 +
 libc/config/linux/x86_64/entrypoints.txt      | 1 +
 libc/config/windows/entrypoints.txt           | 1 +
 12 files changed, 12 insertions(+)

diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index ed84bdff8ce1e..82910c320b48a 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -792,6 +792,7 @@ endif()
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
+  libc.src.math.asinbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 43ba426b8ca09..4cf34764916f7 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -801,6 +801,7 @@ endif()
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
+  libc.src.math.asinbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 79fbd1e4b0de2..c4a11c6f87337 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -798,6 +798,7 @@ endif()
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
+  libc.src.math.asinbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index 71881d23c7a06..0888f4b0d922b 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -611,6 +611,7 @@ endif()
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
+  libc.src.math.asinbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl
diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index cad973f1ac069..046d1b409742f 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -235,6 +235,7 @@ set(TARGET_LIBM_ENTRYPOINTS
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
+  libc.src.math.asinbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl
diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index e327d9ac6f3d3..a80bdeddf8319 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -627,6 +627,7 @@ endif()
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
+  libc.src.math.asinbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index efc784d23e301..5fba41d40c7e6 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -629,6 +629,7 @@ endif()
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
+  libc.src.math.asinbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 4311ba624e6d8..103b259503723 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -874,6 +874,7 @@ endif()
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
+  libc.src.math.asinbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index a10dc0c82e36f..31dcb31c67c7a 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -477,6 +477,7 @@ set(TARGET_LIBM_ENTRYPOINTS
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
+  libc.src.math.asinbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 17efa2e368ede..5782acb727ee2 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -895,6 +895,7 @@ endif()
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
+  libc.src.math.asinbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index eeaccc863dbc3..42176cd5bd3b3 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -950,6 +950,7 @@ endif()
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
+  libc.src.math.asinbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index e594f6bbb1fd5..e8080bc97c59a 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -323,6 +323,7 @@ set(TARGET_LIBM_ENTRYPOINTS
 list(APPEND TARGET_LIBM_ENTRYPOINTS
   # bfloat16 entrypoints
   libc.src.math.atanbf16
+  libc.src.math.asinbf16
   libc.src.math.bf16add
   libc.src.math.bf16addf
   libc.src.math.bf16addl

>From 087b4e930948ea65e964765cd96c0b3a6954129d Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Mon, 2 Mar 2026 19:34:56 +0530
Subject: [PATCH 03/14] feat: added tests

feat:added tests

t1

t2

t3

error

testing multiplier

fix: handled rounding exception

squash
---
 libc/docs/headers/math/index.rst              |  2 +-
 libc/shared/math.h                            |  1 +
 libc/shared/math/asinbf16.h                   | 23 ++++++++
 libc/src/__support/math/CMakeLists.txt        | 16 ++++++
 libc/src/__support/math/asinbf16.h            | 14 ++++-
 libc/src/math/CMakeLists.txt                  |  1 +
 libc/src/math/asinbf16.h                      | 22 ++++++++
 libc/src/math/generic/CMakeLists.txt          | 10 ++++
 libc/src/math/generic/asinbf16.cpp            | 19 +++++++
 libc/test/shared/CMakeLists.txt               |  1 +
 libc/test/shared/shared_math_test.cpp         |  1 +
 libc/test/src/math/CMakeLists.txt             | 14 +++++
 libc/test/src/math/asinbf16_test.cpp          | 54 ++++++++++++++++++
 libc/test/src/math/exhaustive/CMakeLists.txt  | 18 ++++++
 .../src/math/exhaustive/asinbf16_test.cpp     | 56 +++++++++++++++++++
 libc/test/src/math/smoke/CMakeLists.txt       | 25 +++++----
 libc/test/src/math/smoke/asinbf16_test.cpp    | 41 ++++++++++++++
 .../llvm-project-overlay/libc/BUILD.bazel     | 22 ++++++++
 18 files changed, 325 insertions(+), 15 deletions(-)
 create mode 100644 libc/shared/math/asinbf16.h
 create mode 100644 libc/src/math/asinbf16.h
 create mode 100644 libc/src/math/generic/asinbf16.cpp
 create mode 100644 libc/test/src/math/asinbf16_test.cpp
 create mode 100644 libc/test/src/math/exhaustive/asinbf16_test.cpp
 create mode 100644 libc/test/src/math/smoke/asinbf16_test.cpp

diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst
index f9614c6d19d22..14152ac62435d 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -265,7 +265,7 @@ Higher Math Functions
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
 | acospi    |                  |                 |                        | |check|              |                        |                        | 7.12.4.8               | F.10.1.8                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| asin      | |check|          | |check|         |                        | |check|              |                        |                        | 7.12.4.2               | F.10.1.2                   |
+| asin      | |check|          | |check|         |                        | |check|              |                        | |check|                | 7.12.4.2               | F.10.1.2                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
 | asinh     | |check|          |                 |                        | |check|              |                        |                        | 7.12.5.2               | F.10.2.2                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
diff --git a/libc/shared/math.h b/libc/shared/math.h
index 08a4c994283c5..13ed0ba9518a5 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -19,6 +19,7 @@
 #include "math/acospif.h"
 #include "math/acospif16.h"
 #include "math/asin.h"
+#include "math/asinbf16.h"
 #include "math/asinf.h"
 #include "math/asinf16.h"
 #include "math/asinhf.h"
diff --git a/libc/shared/math/asinbf16.h b/libc/shared/math/asinbf16.h
new file mode 100644
index 0000000000000..158547f22d2da
--- /dev/null
+++ b/libc/shared/math/asinbf16.h
@@ -0,0 +1,23 @@
+//===-- Shared asinbf16 function --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SHARED_MATH_ASINBF16_H
+#define LLVM_LIBC_SHARED_MATH_ASINBF16_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/asinbf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::asinbf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_ASINBF16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 10329830a004b..e1409de79e6ca 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -381,6 +381,22 @@ add_header_library(
     libc.src.__support.macros.optimization
 )
 
+
+add_header_library(
+  asinbf16
+  HDRS
+    asinbf16.h
+  DEPENDS
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.polyeval
+    libc.src.__support.FPUtil.cast
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.FPUtil.sqrt
+    libc.src.__support.macros.optimization
+    libc.src.__support.FPUtil.bfloat16
+)
+
 add_header_library(
   atanpif16
   HDRS
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 681743662729a..40fea2c7851d3 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -55,7 +55,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr bfloat16 asinf16(bfloat16 x) {
+LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
   // Generated by Sollya using the following command:
   // > display = hexadecimal;
   // > round(pi/2, SG, RN);
@@ -90,6 +90,16 @@ LIBC_INLINE constexpr bfloat16 asinf16(bfloat16 x) {
   if (LIBC_UNLIKELY(x_abs == 0))
     return x; // with sign
 
+  if (LIBC_UNLIKELY(x_abs <= 0x3D00)) {
+    int rounding = fputil::quick_get_round();
+    if ((xbits.is_pos() && rounding == FE_UPWARD) ||
+        (xbits.is_neg() && rounding == FE_DOWNWARD)) {
+      float xf = x;
+      return bfloat16(fputil::multiply_add(xf, 0x1.0p-13f, xf));
+    }
+    return x;
+  }
+
   // for |x| in (0,1] -> sign handles by sign(x) * sin(x)
   // Taylor series for asin(x)
   // asin(x) = x + x^3/6 + 3x^5/40 + ...
@@ -165,4 +175,4 @@ LIBC_INLINE constexpr bfloat16 asinf16(bfloat16 x) {
 
 } // namespace LIBC_NAMESPACE_DECL
 
-#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINF16_H
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINBF16_H
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index ebba3f04b8d56..b53817e2a1729 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -52,6 +52,7 @@ add_math_entrypoint_object(acospif)
 add_math_entrypoint_object(acospif16)
  
 add_math_entrypoint_object(asin)
+add_math_entrypoint_object(asinbf16)
 add_math_entrypoint_object(asinf)
 add_math_entrypoint_object(asinf16)
 
diff --git a/libc/src/math/asinbf16.h b/libc/src/math/asinbf16.h
new file mode 100644
index 0000000000000..9c2f1fea51e61
--- /dev/null
+++ b/libc/src/math/asinbf16.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for asinbf16 -----------------------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_ASINBF16_H
+#define LLVM_LIBC_SRC_MATH_ASINBF16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+bfloat16 asinbf16(bfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_ASINBF16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 30f33749d165e..899c32216e987 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -4098,6 +4098,16 @@ add_entrypoint_object(
     libc.src.__support.math.atanpif16
 )
 
+add_entrypoint_object(
+  asinbf16
+  SRCS
+    asinbf16.cpp
+  HDRS
+    ../asinbf16.h
+  DEPENDS
+    libc.src.__support.math.asinbf16
+)
+
 add_entrypoint_object(
   asinf
   SRCS
diff --git a/libc/src/math/generic/asinbf16.cpp b/libc/src/math/generic/asinbf16.cpp
new file mode 100644
index 0000000000000..a197e9d300d32
--- /dev/null
+++ b/libc/src/math/generic/asinbf16.cpp
@@ -0,0 +1,19 @@
+//===-- Half-precision asinbf16(x) function -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception.
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/asinbf16.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/math/asinbf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(bfloat16, asinbf16, (bfloat16 x)) {
+  return math::asinbf16(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index c3795d366a588..88b6fc566d1ec 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -16,6 +16,7 @@ add_fp_unittest(
     libc.src.__support.math.acospif
     libc.src.__support.math.acospif16
     libc.src.__support.math.asin
+    libc.src.__support.math.asinbf16
     libc.src.__support.math.asinf
     libc.src.__support.math.asinf16
     libc.src.__support.math.asinhf
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index b52abc6d8e990..a3408eb29a953 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -425,6 +425,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat128) {
 TEST(LlvmLibcSharedMathTest, AllBFloat16) {
   using FPBits = LIBC_NAMESPACE::fputil::FPBits<bfloat16>;
   EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::atanbf16(bfloat16(0.0)));
+  EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::asinbf16(bfloat16(0.0)));
   EXPECT_FP_EQ(bfloat16(5.0), LIBC_NAMESPACE::shared::bf16add(2.0, 3.0));
   EXPECT_FP_EQ(bfloat16(2.0f), LIBC_NAMESPACE::shared::bf16divf(4.0f, 2.0f));
   EXPECT_FP_EQ(bfloat16(2.0), LIBC_NAMESPACE::shared::bf16divl(6.0L, 3.0L));
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 2fd77f964e4d6..8171ce03d3aba 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2512,6 +2512,20 @@ add_fp_unittest(
     libc.src.math.asin
 )
 
+
+add_fp_unittest(
+  asinbf16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    asinbf16_test.cpp
+  DEPENDS
+    libc.src.math.asinbf16  
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.bfloat16
+)
+
 add_fp_unittest(
   asinf16_test
   NEED_MPFR
diff --git a/libc/test/src/math/asinbf16_test.cpp b/libc/test/src/math/asinbf16_test.cpp
new file mode 100644
index 0000000000000..55276883d52ed
--- /dev/null
+++ b/libc/test/src/math/asinbf16_test.cpp
@@ -0,0 +1,54 @@
+//===-- Exhaustive test for asinbf16 --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/math/asinbf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcAsinBf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// Range: [0, Inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// Range: [-Inf, 0]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcAsinBf16Test, PositiveRange) {
+  for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
+    bfloat16 x = FPBits(v).get_val();
+
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
+                                   LIBC_NAMESPACE::asinbf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcAsinBf16Test, NegativeRange) {
+  for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
+    bfloat16 x = FPBits(v).get_val();
+
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
+                                   LIBC_NAMESPACE::asinbf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcAsinBf16Test, SpecialNumbers) {
+  constexpr bfloat16 VALUES[] = {zero,    neg_zero,   inf,
+                                 neg_inf, min_normal, max_normal};
+  for (size_t i = 0; i < 6; ++i) {
+    bfloat16 x = VALUES[i];
+
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
+                                   LIBC_NAMESPACE::asinbf16(x), 0.5);
+  }
+}
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 2d1301d3a1e66..5e5f3f0adf083 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -650,6 +650,24 @@ add_fp_unittest(
     libc.src.__support.math.atanf
 )
 
+
+add_fp_unittest(
+  asinbf16_test
+  NO_RUN_POSTBUILD
+  NEED_MPFR
+  SUITE
+    libc_math_exhaustive_tests
+  SRCS
+    asinbf16_test.cpp
+  DEPENDS
+    .exhaustive_test
+    libc.src.math.asinbf16
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.bfloat16
+  LINK_LIBRARIES
+    -lpthread
+)
+
 add_fp_unittest(
   asinf_test
   NO_RUN_POSTBUILD
diff --git a/libc/test/src/math/exhaustive/asinbf16_test.cpp b/libc/test/src/math/exhaustive/asinbf16_test.cpp
new file mode 100644
index 0000000000000..85f0b811b2c8d
--- /dev/null
+++ b/libc/test/src/math/exhaustive/asinbf16_test.cpp
@@ -0,0 +1,56 @@
+//===-- Exhaustive test for asinbf16 --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/math/asinbf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcAsinBf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// Normal range: [+0, +int]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// Normal range: [-0, -int]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcAsinBf16Test, NormalPositiveRange) {
+  for (uint16_t v1 = POS_START; v1 <= POS_STOP; v1++) {
+
+    bfloat16 x = FPBits(v1).get_val();
+
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
+                                   LIBC_NAMESPACE::asinbf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcAsinBf16Test, NormalNegativeRange) {
+  for (uint16_t v1 = NEG_START; v1 <= NEG_STOP; v1++) {
+
+    bfloat16 x = FPBits(v1).get_val();
+
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
+                                   LIBC_NAMESPACE::asinbf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcAsinBf16Test, SpecialNumbers) {
+  constexpr bfloat16 VALUES[] = {zero,    neg_zero,   inf,
+                                 neg_inf, min_normal, max_normal};
+  for (size_t i = 0; i < 6; ++i) {
+    bfloat16 x = VALUES[i];
+
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
+                                   LIBC_NAMESPACE::asinbf16(x), 0.5);
+  }
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 79f2ea4806377..d02a678fc8702 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4839,6 +4839,19 @@ add_fp_unittest(
     libc.src.math.asin
 )
 
+add_fp_unittest(
+  asinbf16_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    asinbf16_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.src.math.asinbf16
+    libc.hdr.fenv_macros
+    libc.src.__support.FPUtil.bfloat16
+)
+
 add_fp_unittest(
   asinf16_test
   SUITE
@@ -4885,18 +4898,6 @@ add_fp_unittest(
     libc.src.math.acosf16
 )
 
-add_fp_unittest(
-  acospif_test
-  SUITE
-    libc-math-smoke-tests
-  SRCS
-    acospif_test.cpp
-  DEPENDS
-    libc.hdr.errno_macros
-    libc.src.math.acospif
-    libc.src.__support.FPUtil.fp_bits
-)
-
 add_fp_unittest(
   acospif16_test
   SUITE
diff --git a/libc/test/src/math/smoke/asinbf16_test.cpp b/libc/test/src/math/smoke/asinbf16_test.cpp
new file mode 100644
index 0000000000000..d237a194c46fc
--- /dev/null
+++ b/libc/test/src/math/smoke/asinbf16_test.cpp
@@ -0,0 +1,41 @@
+//===-- Unittests for asinbf16 --------------------------------------------===//
+//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception.
+//
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/math/asinbf16.h"
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+class LlvmLibcAsinBf16Test : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+  DECLARE_SPECIAL_CONSTANTS(bfloat16)
+public:
+  void test_special_numbers() {
+    EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::asinbf16(aNaN));
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        aNaN, LIBC_NAMESPACE::asinbf16(sNaN), FE_INVALID);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::asinbf16(zero));
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::asinbf16(neg_zero));
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::asinbf16(inf));
+    EXPECT_MATH_ERRNO(EDOM);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::asinbf16(neg_inf));
+    EXPECT_MATH_ERRNO(EDOM);
+  }
+};
+TEST_F(LlvmLibcAsinBf16Test, SpecialNumbers) { test_special_numbers(); }
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index a69ebcdb63fa7..7fdc6e46305c0 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -3365,6 +3365,21 @@ libc_support_library(
     ],
 )
 
+libc_support_library(
+    name = "__support_math_asinbf16",
+    hdrs = ["src/__support/math/asinbf16.h"],
+    deps = [
+        ":__support_fputil_bfloat16",
+        ":__support_fputil_cast",
+        ":__support_fputil_fenv_impl",
+        ":__support_fputil_fp_bits",
+        ":__support_fputil_multiply_add",
+        ":__support_fputil_polyeval",
+        ":__support_fputil_sqrt",
+        ":__support_macros_optimization",
+    ],
+)
+
 libc_support_library(
     name = "__support_math_asinf",
     hdrs = ["src/__support/math/asinf.h"],
@@ -6561,6 +6576,13 @@ libc_math_function(
     additional_deps = [":__support_math_asin"],
 )
 
+libc_math_function(
+    name = "asinbf16",
+    additional_deps = [
+        ":__support_math_asinbf16",
+    ],
+)
+
 libc_math_function(
     name = "asinf",
     additional_deps = [":__support_math_asinf"],

>From 03b8606e685108bcc56e621007febe44328162d5 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Mon, 2 Mar 2026 23:02:44 +0530
Subject: [PATCH 04/14] chore: clang

---
 libc/src/__support/math/asinbf16.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 40fea2c7851d3..3c8d465ce0181 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -128,7 +128,7 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
   // asin(x) = pi/2 - 2 * asin(sqrt((1-x)/2)) ; ---------------------------[2]
 
   //[Note: check for inf rec (i.e should not output the same invalid interval
-  //which could not be calculated precisely by taylor series)];
+  // which could not be calculated precisely by taylor series)]
   // Here we choose an input interval where the values have less precision and
   // use the formula to fold into the valid interval where we could generate
   // precise values from taylor eg :- input (0,5,1] -> gets interval [0,1)

>From f22fdde2d82ae9f7688e3d0cc3b60331e60e9bf5 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 3 Mar 2026 11:22:36 +0530
Subject: [PATCH 05/14] chore: kept essential comments

chore: nit

chore: kept essential comments only

chore: format
---
 libc/src/__support/math/asinbf16.h      | 99 +++----------------------
 libc/test/src/math/smoke/CMakeLists.txt | 12 +++
 2 files changed, 23 insertions(+), 88 deletions(-)

diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 3c8d465ce0181..64094e59b0859 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -18,39 +18,6 @@
 #include "src/__support/FPUtil/sqrt.h"
 #include "src/__support/macros/optimization.h"
 
-/*
-    cases to consider and info
-    sin (x) = opp/hypot
-
-    // odd function -> sin(x) = sign(x) * sign(x)
-    // sin(x + 2pi) = sin (x)
-    // taylor series -> sin x= x - (x^3)/3! + x^5/(5!) - x^7/(7!)....
-
-
-    //
-    sin(pi-x) = sin(x)
-    sin(pi+x) = -sin(x)
-    sin(2*pi - x) = -sin(x)
-    //
-    sin(pi/2) = 1
-    sin(pi/5) = sin(30) = 1/2
-    sin(pi/4) = sin(45) = 1/root(2)
-    sin(n*pi) = 0
-
-
-    y  = asin(x)
-    // Domain E [-1,1]
-    // Range E [-pi/2,pi/2]
-
-    // properties
-        1. asin(x) = sign(x) * sin(x)
-
-
-    // identities
-
-    // taylor
-
-*/
 namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
@@ -67,11 +34,13 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
   uint16_t x_u = xbits.uintval();
   uint16_t x_abs = x_u & 0x7fff;
   float x_sign = (xbits.sign() == Sign::NEG) ? -1 : 1;
+  float xf = x;
 
-  // x-> pi/2  => y -> 1
-  // domain is E [-1,1]
-  // |x| > 1, or NaN or infinity are invalid
-  if (LIBC_UNLIKELY(x_abs > 0x3F80)) {
+  // case 1: |x|>=1, NaN or Inf
+  if (LIBC_UNLIKELY(x_abs >= 0x3F80)) {
+    if (x_abs == 0x3F80) {
+      return bfloat16(x_sign * PI_2);
+    }
     // NaN
     if (xbits.is_nan()) {
       if (xbits.is_signaling_nan()) {
@@ -80,13 +49,13 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
       }
       return x; // quiet NaN
     }
-
+    // |x|>1 & inf
     fputil::raise_except_if_required(FE_INVALID);
     fputil::set_errno_if_required(EDOM); // Domain is bounded
     return FPBits::quiet_nan().get_val();
   }
 
-  // |x| = {0}
+  // case 2:  |x| = {0}
   if (LIBC_UNLIKELY(x_abs == 0))
     return x; // with sign
 
@@ -94,50 +63,14 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
     int rounding = fputil::quick_get_round();
     if ((xbits.is_pos() && rounding == FE_UPWARD) ||
         (xbits.is_neg() && rounding == FE_DOWNWARD)) {
-      float xf = x;
       return bfloat16(fputil::multiply_add(xf, 0x1.0p-13f, xf));
     }
     return x;
   }
 
-  // for |x| in (0,1] -> sign handles by sign(x) * sin(x)
-  // Taylor series for asin(x)
-  // asin(x) = x + x^3/6 + 3x^5/40 + ...
-  // asin(x) = x * (1 + x^2/6 + 3x^4/40 + ...)
-  // asin(x)/x = 1 + x^2/6 + 3x^4/40 + ...
-  // asin(x)/x = P(x^2) ---------------------------[1]
-
-  // As we approach towards 1 the precision decreases
-  // above 0.89 it goes < 2^-6 error (increase)
-  // So we find a recursive way to handle a range inside the valid range where
-  // its more precise
-  //
-  // y = asin(x)  -> sin(y) = x
-  // x = sin(y) = cos(pi/2 - y)
-  // Double angle formula -> cos(2A) = 1 - 2*sin^2(A)
-  // sin(A) = sqrt((1-cos(2A))/2);
-  // put z = 2A
-  // if (z== (pi/2 - y)) here then we can say x = cos(z)
-  // sin(z/2) = sqrt((1-cos(z))/2)
-  // sin(z/2) = sqrt((1-x)/2)
-  // z = 2 * asin(sqrt((1-x)/2));
-
-  // since derivative of asin(x) = 1/sqrt(1-x^2) the errors increase as we
-  // approach 1 so we use the recursive relation z = pi/2 - y = 2 *
-  // asin(sqrt((1-x)/2)); y = pi/2 * 2 * asin(sqrt((1-x)/2)); since y = asin(x)
-  // asin(x) = pi/2 - 2 * asin(sqrt((1-x)/2)) ; ---------------------------[2]
-
-  //[Note: check for inf rec (i.e should not output the same invalid interval
-  // which could not be calculated precisely by taylor series)]
-  // Here we choose an input interval where the values have less precision and
-  // use the formula to fold into the valid interval where we could generate
-  // precise values from taylor eg :- input (0,5,1] -> gets interval [0,1)
-
-  float xf = x;
   float xf_abs = (xf < 0 ? -xf : xf);
   float x_sq = xf_abs * xf_abs;
 
-  // Minimax polynomial for asin(x)/x, returns P(u) as float
   // Degree 6 polynomial of asin(x) generated using Sollya with command :
   // > display = hexadecimal
   // > P = fpminimax(asin(x)/x, [|0,2,4,6|], [|SG,SG,SG,SG|], [0, 0.5]);
@@ -146,24 +79,14 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
                             0x1.0a788p-4f);
   };
 
-  // for range: (0,0.5]
+  // case 3: (0,0.5]
   if (x_abs <= 0x3F00) {
-
-    // Remember:- asin(x)/x = P(x^2) -> (ref from [1])
-    // asin(x) = x * P(x^2)
-    // xf already carries the sign
     float result = xf * asin_poly(x_sq);
     return bfloat16(result);
   }
 
-  // remaining range: (0.5,1)
-
-  // ref from [2]
-  // asin(x) = pi/2 - 2 * asin(sqrt((1-x)/2))
-  // let t = ((1-|x|)/2) = |x|*(-1/2) + 1/2
-  // asin(sqrt(t)) = sqrt(t) * P(t)
-  // asin(x) = sign * (pi/2 - 2 * sqrt(t) * P(t))
-
+  // case 4: (0.5,1)
+  //  using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
   float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
   float t_sqrt = fputil::sqrt<float>(t);
   float asin_sqrt_t = t_sqrt * asin_poly(t);
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index d02a678fc8702..28b85b1a25bbd 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4898,6 +4898,18 @@ add_fp_unittest(
     libc.src.math.acosf16
 )
 
+add_fp_unittest(
+  acospif_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    acospif_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.src.math.acospif
+    libc.src.__support.FPUtil.fp_bits
+)
+
 add_fp_unittest(
   acospif16_test
   SUITE

>From f70ac29c3d77665690ad9820564942d68b3f4788 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 3 Mar 2026 20:46:51 +0530
Subject: [PATCH 06/14] chore: removed redundant tests and poly calc

---
 libc/src/__support/math/CMakeLists.txt        |  1 +
 libc/src/__support/math/asinbf16.h            | 14 ++---
 libc/test/src/math/asinbf16_test.cpp          | 11 ----
 libc/test/src/math/exhaustive/CMakeLists.txt  | 18 ------
 .../src/math/exhaustive/asinbf16_test.cpp     | 56 -------------------
 5 files changed, 5 insertions(+), 95 deletions(-)
 delete mode 100644 libc/test/src/math/exhaustive/asinbf16_test.cpp

diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index e1409de79e6ca..8d739d4cc4bcf 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -395,6 +395,7 @@ add_header_library(
     libc.src.__support.FPUtil.sqrt
     libc.src.__support.macros.optimization
     libc.src.__support.FPUtil.bfloat16
+    libc.src.__support.math.inv_trigf_utils
 )
 
 add_header_library(
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 64094e59b0859..3281ea7724bab 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -17,6 +17,7 @@
 #include "src/__support/FPUtil/multiply_add.h"
 #include "src/__support/FPUtil/sqrt.h"
 #include "src/__support/macros/optimization.h"
+#include "src/__support/math/inv_trigf_utils.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
@@ -71,17 +72,10 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
   float xf_abs = (xf < 0 ? -xf : xf);
   float x_sq = xf_abs * xf_abs;
 
-  // Degree 6 polynomial of asin(x) generated using Sollya with command :
-  // > display = hexadecimal
-  // > P = fpminimax(asin(x)/x, [|0,2,4,6|], [|SG,SG,SG,SG|], [0, 0.5]);
-  auto asin_poly = [](float u) {
-    return fputil::polyeval(u, 0x1.ffffcep-1f, 0x1.55b648p-3f, 0x1.24d192p-4f,
-                            0x1.0a788p-4f);
-  };
-
   // case 3: (0,0.5]
   if (x_abs <= 0x3F00) {
-    float result = xf * asin_poly(x_sq);
+    // asin_eval returns P(x^2) - 1, where P(x^2) ~ asin(x)/x
+    float result = xf * ( 1.0 + inv_trigf_utils_internal::asin_eval(x_sq));
     return bfloat16(result);
   }
 
@@ -89,7 +83,7 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
   //  using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
   float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
   float t_sqrt = fputil::sqrt<float>(t);
-  float asin_sqrt_t = t_sqrt * asin_poly(t);
+  float asin_sqrt_t = t_sqrt * ( 1.0 + inv_trigf_utils_internal::asin_eval(t));
   float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
   return bfloat16(x_sign * result);
 }
diff --git a/libc/test/src/math/asinbf16_test.cpp b/libc/test/src/math/asinbf16_test.cpp
index 55276883d52ed..0fef18133db2f 100644
--- a/libc/test/src/math/asinbf16_test.cpp
+++ b/libc/test/src/math/asinbf16_test.cpp
@@ -41,14 +41,3 @@ TEST_F(LlvmLibcAsinBf16Test, NegativeRange) {
                                    LIBC_NAMESPACE::asinbf16(x), 0.5);
   }
 }
-
-TEST_F(LlvmLibcAsinBf16Test, SpecialNumbers) {
-  constexpr bfloat16 VALUES[] = {zero,    neg_zero,   inf,
-                                 neg_inf, min_normal, max_normal};
-  for (size_t i = 0; i < 6; ++i) {
-    bfloat16 x = VALUES[i];
-
-    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
-                                   LIBC_NAMESPACE::asinbf16(x), 0.5);
-  }
-}
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 5e5f3f0adf083..2d1301d3a1e66 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -650,24 +650,6 @@ add_fp_unittest(
     libc.src.__support.math.atanf
 )
 
-
-add_fp_unittest(
-  asinbf16_test
-  NO_RUN_POSTBUILD
-  NEED_MPFR
-  SUITE
-    libc_math_exhaustive_tests
-  SRCS
-    asinbf16_test.cpp
-  DEPENDS
-    .exhaustive_test
-    libc.src.math.asinbf16
-    libc.src.__support.FPUtil.fp_bits
-    libc.src.__support.FPUtil.bfloat16
-  LINK_LIBRARIES
-    -lpthread
-)
-
 add_fp_unittest(
   asinf_test
   NO_RUN_POSTBUILD
diff --git a/libc/test/src/math/exhaustive/asinbf16_test.cpp b/libc/test/src/math/exhaustive/asinbf16_test.cpp
deleted file mode 100644
index 85f0b811b2c8d..0000000000000
--- a/libc/test/src/math/exhaustive/asinbf16_test.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-//===-- Exhaustive test for asinbf16 --------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "src/__support/FPUtil/bfloat16.h"
-#include "src/math/asinbf16.h"
-#include "test/UnitTest/FPMatcher.h"
-#include "test/UnitTest/Test.h"
-#include "utils/MPFRWrapper/MPFRUtils.h"
-
-using LlvmLibcAsinBf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
-
-namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
-
-// Normal range: [+0, +int]
-static constexpr uint16_t POS_START = 0x0000U;
-static constexpr uint16_t POS_STOP = 0x7f80U;
-
-// Normal range: [-0, -int]
-static constexpr uint16_t NEG_START = 0x8000U;
-static constexpr uint16_t NEG_STOP = 0xff80U;
-
-TEST_F(LlvmLibcAsinBf16Test, NormalPositiveRange) {
-  for (uint16_t v1 = POS_START; v1 <= POS_STOP; v1++) {
-
-    bfloat16 x = FPBits(v1).get_val();
-
-    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
-                                   LIBC_NAMESPACE::asinbf16(x), 0.5);
-  }
-}
-
-TEST_F(LlvmLibcAsinBf16Test, NormalNegativeRange) {
-  for (uint16_t v1 = NEG_START; v1 <= NEG_STOP; v1++) {
-
-    bfloat16 x = FPBits(v1).get_val();
-
-    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
-                                   LIBC_NAMESPACE::asinbf16(x), 0.5);
-  }
-}
-
-TEST_F(LlvmLibcAsinBf16Test, SpecialNumbers) {
-  constexpr bfloat16 VALUES[] = {zero,    neg_zero,   inf,
-                                 neg_inf, min_normal, max_normal};
-  for (size_t i = 0; i < 6; ++i) {
-    bfloat16 x = VALUES[i];
-
-    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
-                                   LIBC_NAMESPACE::asinbf16(x), 0.5);
-  }
-}

>From 48bce7bbd06a4f1572cffe7245d6963999477c4f Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 3 Mar 2026 20:59:37 +0530
Subject: [PATCH 07/14] chore: removed polyeval and typcasted properly to
 intermediate float

---
 libc/src/__support/math/CMakeLists.txt |  1 -
 libc/src/__support/math/asinbf16.h     | 15 ++++++++-------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 8d739d4cc4bcf..c7a4b49a7fe94 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -389,7 +389,6 @@ add_header_library(
   DEPENDS
     libc.src.__support.FPUtil.fenv_impl
     libc.src.__support.FPUtil.fp_bits
-    libc.src.__support.FPUtil.polyeval
     libc.src.__support.FPUtil.cast
     libc.src.__support.FPUtil.multiply_add
     libc.src.__support.FPUtil.sqrt
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 3281ea7724bab..a7f5f910b40f0 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -11,7 +11,6 @@
 
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
 #include "src/__support/FPUtil/bfloat16.h"
 #include "src/__support/FPUtil/cast.h"
 #include "src/__support/FPUtil/multiply_add.h"
@@ -40,7 +39,7 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
   // case 1: |x|>=1, NaN or Inf
   if (LIBC_UNLIKELY(x_abs >= 0x3F80)) {
     if (x_abs == 0x3F80) {
-      return bfloat16(x_sign * PI_2);
+      return fputil::cast<bfloat16>(x_sign * PI_2);
     }
     // NaN
     if (xbits.is_nan()) {
@@ -64,7 +63,7 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
     int rounding = fputil::quick_get_round();
     if ((xbits.is_pos() && rounding == FE_UPWARD) ||
         (xbits.is_neg() && rounding == FE_DOWNWARD)) {
-      return bfloat16(fputil::multiply_add(xf, 0x1.0p-13f, xf));
+      return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-13f, xf));
     }
     return x;
   }
@@ -75,17 +74,19 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
   // case 3: (0,0.5]
   if (x_abs <= 0x3F00) {
     // asin_eval returns P(x^2) - 1, where P(x^2) ~ asin(x)/x
-    float result = xf * ( 1.0 + inv_trigf_utils_internal::asin_eval(x_sq));
-    return bfloat16(result);
+    float result = xf * static_cast<float>(
+                            1.0 + inv_trigf_utils_internal::asin_eval(x_sq));
+    return fputil::cast<bfloat16>(result);
   }
 
   // case 4: (0.5,1)
   //  using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
   float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
   float t_sqrt = fputil::sqrt<float>(t);
-  float asin_sqrt_t = t_sqrt * ( 1.0 + inv_trigf_utils_internal::asin_eval(t));
+  float asin_sqrt_t =
+      t_sqrt * static_cast<float>(1.0 + inv_trigf_utils_internal::asin_eval(t));
   float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
-  return bfloat16(x_sign * result);
+  return fputil::cast<bfloat16>(x_sign * result);
 }
 
 } // namespace math

>From c7f83660562659511b81fad272f164e14d96c9ab Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Tue, 3 Mar 2026 21:33:20 +0530
Subject: [PATCH 08/14] fix: proper usage of asin_eval

---
 libc/src/__support/math/asinbf16.h | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index a7f5f910b40f0..2ea9d61b874b7 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -33,7 +33,7 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
 
   uint16_t x_u = xbits.uintval();
   uint16_t x_abs = x_u & 0x7fff;
-  float x_sign = (xbits.sign() == Sign::NEG) ? -1 : 1;
+  float x_sign = (x_u >> 15) ? -1 : 1;
   float xf = x;
 
   // case 1: |x|>=1, NaN or Inf
@@ -73,9 +73,9 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
 
   // case 3: (0,0.5]
   if (x_abs <= 0x3F00) {
-    // asin_eval returns P(x^2) - 1, where P(x^2) ~ asin(x)/x
-    float result = xf * static_cast<float>(
-                            1.0 + inv_trigf_utils_internal::asin_eval(x_sq));
+    double xp = inv_trigf_utils_internal::asin_eval(x_sq);
+    float result =
+        xf * static_cast<float>(fputil::multiply_add<double>(x_sq, xp, 1.0));
     return fputil::cast<bfloat16>(result);
   }
 
@@ -83,8 +83,9 @@ LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
   //  using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
   float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
   float t_sqrt = fputil::sqrt<float>(t);
+  double tp = inv_trigf_utils_internal::asin_eval(t);
   float asin_sqrt_t =
-      t_sqrt * static_cast<float>(1.0 + inv_trigf_utils_internal::asin_eval(t));
+      t_sqrt * static_cast<float>(fputil::multiply_add<double>(t, tp, 1.0));
   float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
   return fputil::cast<bfloat16>(x_sign * result);
 }

>From 497f3e5f67036bb16c7c5b4cb720af570a8aa091 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Wed, 4 Mar 2026 21:44:54 +0530
Subject: [PATCH 09/14] chore: nit

---
 libc/src/math/asinbf16.h                          | 3 +--
 libc/src/math/generic/asinbf16.cpp                | 2 +-
 libc/test/src/math/CMakeLists.txt                 | 2 +-
 utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 2 +-
 4 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/libc/src/math/asinbf16.h b/libc/src/math/asinbf16.h
index 9c2f1fea51e61..06780cb101018 100644
--- a/libc/src/math/asinbf16.h
+++ b/libc/src/math/asinbf16.h
@@ -1,5 +1,4 @@
-//===-- Implementation header for asinbf16 -----------------------*- C++
-//-*-===//
+//===-- Implementation header for asinbf16 ----------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/src/math/generic/asinbf16.cpp b/libc/src/math/generic/asinbf16.cpp
index a197e9d300d32..876d3bbe646ed 100644
--- a/libc/src/math/generic/asinbf16.cpp
+++ b/libc/src/math/generic/asinbf16.cpp
@@ -1,4 +1,4 @@
-//===-- Half-precision asinbf16(x) function -------------------------------===//
+//===-- Implementation for asinbf16(x) function ---------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 8171ce03d3aba..5fcd8ac49fea3 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2521,7 +2521,7 @@ add_fp_unittest(
   SRCS
     asinbf16_test.cpp
   DEPENDS
-    libc.src.math.asinbf16  
+    libc.src.math.asinbf16
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.bfloat16
 )
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 7fdc6e46305c0..3819d39a329b7 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -3374,9 +3374,9 @@ libc_support_library(
         ":__support_fputil_fenv_impl",
         ":__support_fputil_fp_bits",
         ":__support_fputil_multiply_add",
-        ":__support_fputil_polyeval",
         ":__support_fputil_sqrt",
         ":__support_macros_optimization",
+        ":__support_math_inv_trigf_utils",
     ],
 )
 

>From 656dbe6eaf982d1c646fcbaf43f5f7f23403648a Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 14 Mar 2026 09:19:12 +0530
Subject: [PATCH 10/14] removed constexpr

---
 libc/src/__support/math/CMakeLists.txt | 1 -
 libc/src/__support/math/asinbf16.h     | 2 +-
 libc/src/math/generic/asinbf16.cpp     | 1 -
 3 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index c7a4b49a7fe94..c13d182303850 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -381,7 +381,6 @@ add_header_library(
     libc.src.__support.macros.optimization
 )
 
-
 add_header_library(
   asinbf16
   HDRS
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 2ea9d61b874b7..81f6433b02759 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -22,7 +22,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 namespace math {
 
-LIBC_INLINE constexpr bfloat16 asinbf16(bfloat16 x) {
+LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
   // Generated by Sollya using the following command:
   // > display = hexadecimal;
   // > round(pi/2, SG, RN);
diff --git a/libc/src/math/generic/asinbf16.cpp b/libc/src/math/generic/asinbf16.cpp
index 876d3bbe646ed..acaeef0c6ef55 100644
--- a/libc/src/math/generic/asinbf16.cpp
+++ b/libc/src/math/generic/asinbf16.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/math/asinbf16.h"
-#include "src/__support/FPUtil/bfloat16.h"
 #include "src/__support/math/asinbf16.h"
 
 namespace LIBC_NAMESPACE_DECL {

>From 403e1407b827fe43fe40d72f5a12c31cb3d92703 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 28 Mar 2026 11:58:15 +0530
Subject: [PATCH 11/14] nit

---
 libc/test/src/math/CMakeLists.txt | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 5fcd8ac49fea3..97ede9b1c9f8d 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2512,7 +2512,6 @@ add_fp_unittest(
     libc.src.math.asin
 )
 
-
 add_fp_unittest(
   asinbf16_test
   NEED_MPFR

>From cf13e4313def4d4a900d8958ec5eae0a96f96a7f Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 28 Mar 2026 21:35:24 +0530
Subject: [PATCH 12/14] chore: branches and (float)

---
 libc/src/__support/math/asinbf16.h | 90 +++++++++++++++---------------
 1 file changed, 45 insertions(+), 45 deletions(-)

diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index 81f6433b02759..ed327cea101c6 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -19,7 +19,6 @@
 #include "src/__support/math/inv_trigf_utils.h"
 
 namespace LIBC_NAMESPACE_DECL {
-
 namespace math {
 
 LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
@@ -36,62 +35,63 @@ LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
   float x_sign = (x_u >> 15) ? -1 : 1;
   float xf = x;
 
-  // case 1: |x|>=1, NaN or Inf
-  if (LIBC_UNLIKELY(x_abs >= 0x3F80)) {
-    if (x_abs == 0x3F80) {
-      return fputil::cast<bfloat16>(x_sign * PI_2);
-    }
-    // NaN
-    if (xbits.is_nan()) {
-      if (xbits.is_signaling_nan()) {
-        fputil::raise_except_if_required(FE_INVALID);
-        return FPBits::quiet_nan().get_val();
-      }
-      return x; // quiet NaN
-    }
-    // |x|>1 & inf
-    fputil::raise_except_if_required(FE_INVALID);
-    fputil::set_errno_if_required(EDOM); // Domain is bounded
-    return FPBits::quiet_nan().get_val();
-  }
-
-  // case 2:  |x| = {0}
-  if (LIBC_UNLIKELY(x_abs == 0))
-    return x; // with sign
-
-  if (LIBC_UNLIKELY(x_abs <= 0x3D00)) {
-    int rounding = fputil::quick_get_round();
-    if ((xbits.is_pos() && rounding == FE_UPWARD) ||
-        (xbits.is_neg() && rounding == FE_DOWNWARD)) {
-      return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-13f, xf));
-    }
-    return x;
-  }
-
   float xf_abs = (xf < 0 ? -xf : xf);
   float x_sq = xf_abs * xf_abs;
 
-  // case 3: (0,0.5]
+  // Case 1: |x| <= 0.5
   if (x_abs <= 0x3F00) {
-    double xp = inv_trigf_utils_internal::asin_eval(x_sq);
+    // |x| = {0}
+    if (LIBC_UNLIKELY(x_abs == 0))
+      return x; // with sign
+
+    if (LIBC_UNLIKELY(x_abs <= 0x3D00)) {
+      int rounding = fputil::quick_get_round();
+      if ((xbits.is_pos() && rounding == FE_UPWARD) ||
+          (xbits.is_neg() && rounding == FE_DOWNWARD)) {
+        return fputil::cast<bfloat16>(fputil::multiply_add(xf, 0x1.0p-9f, xf));
+      }
+      return x;
+    }
+
+    float xp = fputil::cast<float>(inv_trigf_utils_internal::asin_eval(x_sq));
     float result =
-        xf * static_cast<float>(fputil::multiply_add<double>(x_sq, xp, 1.0));
+        xf * static_cast<float>(fputil::multiply_add<float>(x_sq, xp, 1.0));
     return fputil::cast<bfloat16>(result);
   }
 
-  // case 4: (0.5,1)
+  // Case 2: 0.5 <|x| <= 1
   //  using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
-  float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
-  float t_sqrt = fputil::sqrt<float>(t);
-  double tp = inv_trigf_utils_internal::asin_eval(t);
-  float asin_sqrt_t =
-      t_sqrt * static_cast<float>(fputil::multiply_add<double>(t, tp, 1.0));
-  float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
-  return fputil::cast<bfloat16>(x_sign * result);
+  if (x_abs <= 0x3F80 && x_abs > 0x3F00) {
+    // |x| = {1}
+    if (LIBC_UNLIKELY(x_abs == 0x3F80)) {
+      return fputil::cast<bfloat16>(x_sign * PI_2);
+    }
+
+    float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
+    float t_sqrt = fputil::sqrt<float>(t);
+    float tp = fputil::cast<float>(inv_trigf_utils_internal::asin_eval(t));
+    float asin_sqrt_t =
+        t_sqrt * static_cast<float>(fputil::multiply_add<float>(t, tp, 1.0));
+    float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
+    return fputil::cast<bfloat16>(x_sign * result);
+  }
+
+  // Case 3: NaN and Inf
+  // NaN
+  if (xbits.is_nan()) {
+    if (xbits.is_signaling_nan()) {
+      fputil::raise_except_if_required(FE_INVALID);
+      return FPBits::quiet_nan().get_val();
+    }
+    return x; // quiet NaN
+  }
+  // |x|>1 & inf
+  fputil::raise_except_if_required(FE_INVALID);
+  fputil::set_errno_if_required(EDOM); // Domain is bounded
+  return FPBits::quiet_nan().get_val();
 }
 
 } // namespace math
-
 } // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINBF16_H

>From 06fc7d54eb4aa09607295fe0c5d7eb94781f4715 Mon Sep 17 00:00:00 2001
From: Sukumarsawant <sawantsukumar at gmail.com>
Date: Sat, 28 Mar 2026 21:52:22 +0530
Subject: [PATCH 13/14] nits

---
 libc/src/__support/math/asinbf16.h | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index ed327cea101c6..d6935f0d6bada 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -39,7 +39,7 @@ LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
   float x_sq = xf_abs * xf_abs;
 
   // Case 1: |x| <= 0.5
-  if (x_abs <= 0x3F00) {
+  if (x_abs <= 0x3F00) { // x_abs <= 0.5
     // |x| = {0}
     if (LIBC_UNLIKELY(x_abs == 0))
       return x; // with sign
@@ -54,14 +54,13 @@ LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
     }
 
     float xp = fputil::cast<float>(inv_trigf_utils_internal::asin_eval(x_sq));
-    float result =
-        xf * static_cast<float>(fputil::multiply_add<float>(x_sq, xp, 1.0));
+    float result = xf * (fputil::multiply_add<float>(x_sq, xp, 1.0f));
     return fputil::cast<bfloat16>(result);
   }
 
   // Case 2: 0.5 <|x| <= 1
   //  using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
-  if (x_abs <= 0x3F80 && x_abs > 0x3F00) {
+  if (x_abs <= 0x3F80) { // x_abs <= 1
     // |x| = {1}
     if (LIBC_UNLIKELY(x_abs == 0x3F80)) {
       return fputil::cast<bfloat16>(x_sign * PI_2);
@@ -70,8 +69,7 @@ LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
     float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
     float t_sqrt = fputil::sqrt<float>(t);
     float tp = fputil::cast<float>(inv_trigf_utils_internal::asin_eval(t));
-    float asin_sqrt_t =
-        t_sqrt * static_cast<float>(fputil::multiply_add<float>(t, tp, 1.0));
+    float asin_sqrt_t = t_sqrt * (fputil::multiply_add<float>(t, tp, 1.0f));
     float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
     return fputil::cast<bfloat16>(x_sign * result);
   }

>From 6eda2aa1a1c46f202c2d25a5680c64692f0178ca Mon Sep 17 00:00:00 2001
From: bassiounix <muhammad.m.bassiouni at gmail.com>
Date: Mon, 30 Mar 2026 19:59:36 +0200
Subject: [PATCH 14/14] enable constant evaluation support

---
 libc/src/__support/FPUtil/sqrt.h                | 5 +++--
 libc/src/__support/math/acoshf_utils.h          | 2 +-
 libc/src/__support/math/asinbf16.h              | 2 +-
 libc/src/__support/math/inv_trigf_utils.h       | 2 +-
 libc/test/shared/CMakeLists.txt                 | 9 ++++++++-
 libc/test/shared/shared_math_constexpr_test.cpp | 4 ++++
 6 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/libc/src/__support/FPUtil/sqrt.h b/libc/src/__support/FPUtil/sqrt.h
index d4ed744b4010d..308de73b0dbcd 100644
--- a/libc/src/__support/FPUtil/sqrt.h
+++ b/libc/src/__support/FPUtil/sqrt.h
@@ -15,8 +15,9 @@
 #include "src/__support/FPUtil/generic/sqrt.h"
 
 // Generic instruction specializations with __builtin_elementwise_sqrt.
-#if defined(LIBC_TARGET_CPU_HAS_FPU_FLOAT) ||                                  \
-    defined(LIBC_TARGET_CPU_HAS_FPU_DOUBLE)
+#if !defined(LIBC_HAS_CONSTANT_EVALUATION) &&                                  \
+    (defined(LIBC_TARGET_CPU_HAS_FPU_FLOAT) ||                                 \
+     defined(LIBC_TARGET_CPU_HAS_FPU_DOUBLE))
 
 #if __has_builtin(__builtin_elementwise_sqrt)
 
diff --git a/libc/src/__support/math/acoshf_utils.h b/libc/src/__support/math/acoshf_utils.h
index 8a8e2caccc765..3d760f9835249 100644
--- a/libc/src/__support/math/acoshf_utils.h
+++ b/libc/src/__support/math/acoshf_utils.h
@@ -99,7 +99,7 @@ LIBC_INLINE LIBC_CONSTEXPR double log_eval(double x) {
   uint64_t x_m = (x_u & FPBits::FRACTION_MASK) | FPBits::one().uintval();
   double m = FPBits(x_m).get_val();
 
-  double dx;
+  double dx = 0.0;
 
   // Perform exact range reduction
 #ifdef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
diff --git a/libc/src/__support/math/asinbf16.h b/libc/src/__support/math/asinbf16.h
index d6935f0d6bada..52c4da3e5a1dc 100644
--- a/libc/src/__support/math/asinbf16.h
+++ b/libc/src/__support/math/asinbf16.h
@@ -21,7 +21,7 @@
 namespace LIBC_NAMESPACE_DECL {
 namespace math {
 
-LIBC_INLINE bfloat16 asinbf16(bfloat16 x) {
+LIBC_INLINE LIBC_CONSTEXPR bfloat16 asinbf16(bfloat16 x) {
   // Generated by Sollya using the following command:
   // > display = hexadecimal;
   // > round(pi/2, SG, RN);
diff --git a/libc/src/__support/math/inv_trigf_utils.h b/libc/src/__support/math/inv_trigf_utils.h
index 558d91760f8f9..e30eaeb3a3f9a 100644
--- a/libc/src/__support/math/inv_trigf_utils.h
+++ b/libc/src/__support/math/inv_trigf_utils.h
@@ -171,7 +171,7 @@ LIBC_INLINE_VAR constexpr double ASIN_COEFFS[12] = {
 };
 
 // Evaluate P(x^2) - 1, where P(x^2) ~ asin(x)/x
-LIBC_INLINE double asin_eval(double xsq) {
+LIBC_INLINE LIBC_CONSTEXPR double asin_eval(double xsq) {
   double x4 = xsq * xsq;
   double c0 = fputil::multiply_add(xsq, ASIN_COEFFS[1], ASIN_COEFFS[0]);
   double c1 = fputil::multiply_add(xsq, ASIN_COEFFS[3], ASIN_COEFFS[2]);
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 88b6fc566d1ec..8710b0513d23b 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -267,5 +267,12 @@ add_fp_unittest(
   SRCS
     shared_math_constexpr_test.cpp
   DEPENDS
-    .shared_math_test
+    libc.src.__support.math.asinbf16
+    libc.src.__support.math.ceil
+    libc.src.__support.math.ceilbf16
+    libc.src.__support.math.ceilf
+    libc.src.__support.math.ceilf128
+    libc.src.__support.math.ceilf16
+    libc.src.__support.math.ceill
+    libc.src.__support.math.log
 )
diff --git a/libc/test/shared/shared_math_constexpr_test.cpp b/libc/test/shared/shared_math_constexpr_test.cpp
index 69ff3ec46e8b3..e5e233fae3e13 100644
--- a/libc/test/shared/shared_math_constexpr_test.cpp
+++ b/libc/test/shared/shared_math_constexpr_test.cpp
@@ -9,6 +9,7 @@
 #define LIBC_ENABLE_CONSTEXPR 1
 
 #include "shared/math.h"
+#include "test/UnitTest/Test.h"
 
 //===----------------------------------------------------------------------===//
 //                       Double Tests
@@ -59,5 +60,8 @@ static_assert(float128(0x0p+0) ==
 //                       BFloat16 Tests
 //===----------------------------------------------------------------------===//
 
+static_assert(bfloat16(0.0) == LIBC_NAMESPACE::shared::asinbf16(bfloat16(0.0)));
 static_assert(bfloat16(0x0p+0) ==
               LIBC_NAMESPACE::shared::ceilbf16(bfloat16(0.0)));
+
+TEST(LlvmLibcSharedMathTest, ConstantEvaluation) {}



More information about the llvm-commits mailing list