[libc-commits] [libc] [libc][math][c23] implement C23 math function asinpif16 (PR #146226)

Mohamed Emad via libc-commits libc-commits at lists.llvm.org
Sun Jun 29 21:15:05 PDT 2025


https://github.com/hulxv updated https://github.com/llvm/llvm-project/pull/146226

>From 790f1c42e74d1c2daf6133ec04ae542bcc00c2f6 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Fri, 27 Jun 2025 02:58:36 +0300
Subject: [PATCH 01/19] [libc][math][c23] implement C23 math function
 `asinpif16`

---
 libc/config/linux/aarch64/entrypoints.txt |   1 +
 libc/config/linux/x86_64/entrypoints.txt  |   1 +
 libc/docs/headers/math/index.rst          |   2 +-
 libc/include/math.yaml                    |   9 +-
 libc/src/math/asinpif16.h                 |  21 +++
 libc/src/math/generic/CMakeLists.txt      |  16 ++
 libc/src/math/generic/asinpif16.cpp       | 191 ++++++++++++++++++++++
 7 files changed, 239 insertions(+), 2 deletions(-)
 create mode 100644 libc/src/math/asinpif16.h
 create mode 100644 libc/src/math/generic/asinpif16.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index be5f5a66016b5..240d48f5bcdb8 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -651,6 +651,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
     # math.h C23 _Float16 entrypoints
     # libc.src.math.acoshf16
+    libc.src.math.asinpif16
     libc.src.math.canonicalizef16
     libc.src.math.ceilf16
     libc.src.math.copysignf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 73dfeae1a2c94..c9e5b0096099f 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -664,6 +664,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.acoshf16
     libc.src.math.asinf16
     libc.src.math.asinhf16
+    libc.src.math.asinpif16
     libc.src.math.canonicalizef16
     libc.src.math.ceilf16
     libc.src.math.copysignf16
diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst
index 947bd4b60b391..aaacc3ca92832 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -259,7 +259,7 @@ Higher Math Functions
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
 | asinh     | |check|          |                 |                        | |check|              |                        | 7.12.5.2               | F.10.2.2                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
-| asinpi    |                  |                 |                        |                      |                        | 7.12.4.9               | F.10.1.9                   |
+| asinpi    |                  |                 |                        | |check|              |                        | 7.12.4.9               | F.10.1.9                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
 | atan      | |check|          | 1 ULP           |                        |                      |                        | 7.12.4.3               | F.10.1.3                   |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
diff --git a/libc/include/math.yaml b/libc/include/math.yaml
index fef829422244d..b49c17b871a93 100644
--- a/libc/include/math.yaml
+++ b/libc/include/math.yaml
@@ -71,7 +71,14 @@ functions:
       - stdc
     return_type: double
     arguments:
-      - type: double
+      - type: double 
+  - name: asinpif16
+    standards:
+      - stdc
+    return_type: _Float16
+    arguments:
+      - type: _Float16
+    guard: LIBC_TYPES_HAS_FLOAT16
   - name: atan2
     standards:
       - stdc
diff --git a/libc/src/math/asinpif16.h b/libc/src/math/asinpif16.h
new file mode 100644
index 0000000000000..67ccb4ff4ac3d
--- /dev/null
+++ b/libc/src/math/asinpif16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for asinpif16 ---------------------*- 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_ASINFPI16_H
+#define LLVM_LIBC_SRC_MATH_ASINFPI16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float16 asinpif16(float16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_ASINPIF16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index adbed5b2de48c..76accf72058d3 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -4017,6 +4017,22 @@ add_entrypoint_object(
     libc.src.__support.macros.properties.types
 )
 
+add_entrypoint_object(
+  asinpif16
+  SRCS
+    asinpif16.cpp
+  HDRS
+    ../asinpif16.h
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.fenv_macros
+    libc.src.__support.FPUtil.cast
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.macros.optimization
+)
+
 add_entrypoint_object(
   atanhf
   SRCS
diff --git a/libc/src/math/generic/asinpif16.cpp b/libc/src/math/generic/asinpif16.cpp
new file mode 100644
index 0000000000000..7de675211e5d2
--- /dev/null
+++ b/libc/src/math/generic/asinpif16.cpp
@@ -0,0 +1,191 @@
+//===-- Half-precision asinf16(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 "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.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"
+#include "src/math/asinfpi16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+static constexpr float16 ONE_OVER_TWO = 0x3800; // 0.5f16
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+static constexpr size_t N_ASINFPI_EXCEPTS = 9;
+
+static constexpr float16 ONE_OVER_THREE = 0x3555; // 0.333251953125f16
+static constexpr float16 ONE_OVER_FOUR = 0x3400;  // 0.25f16
+static constexpr float16 ONE_OVER_SIX = 0x32ab;   // 0.166748046875f16
+
+static constexpr fputil::ExceptValues<float16, N_ASINFPI_EXCEPTS>
+    ASINFPI_EXCEPTS{{
+        // (input_hex, RZ_output_hex, RU_offset, RD_offset, RN_offset)
+
+        // x = 0.0, asinfpi(0.0) = 0.0
+        {0x0000, 0x0000, 0, 0, 0},
+
+        // x = 1.0, asinfpi(1.0) = 0.5
+        {0x3C00, ONE_OVER_TWO.uintval(), 0, 0, 0},
+
+        // x = -1.0, asinfpi(-1.0) = -0.5
+        {0xBC00, (fputil::FPBits<float16>(-ONE_OVER_TWO)).uintval(), 0, 0, 0},
+
+        // x = 0.5, asinfpi(0.5) = 1/6
+        {0x3800, ONE_OVER_SIX.uintval(), 0, 0, 0},
+
+        // x = -0.5, asinfpi(-0.5) = -1/6
+        {0xB800, (fputil::FPBits<float16>(-ONE_OVER_SIX)).uintval(), 0, 0, 0},
+
+        // x = sqrt(2)/2 ~ 0.70710678, asinfpi(x) = 1/4
+        // 0x3B41 is float16 for ~0.707. 0x3400 is float16 for 0.25
+        {0x3B41, ONE_OVER_FOUR.uintval(), 0, 0, 0},
+
+        // x = -sqrt(2)/2 ~ -0.70710678, asinfpi(x) = -1/4
+        {0xBB41, (fputil::FPBits<float16>(-ONE_OVER_FOUR)).uintval(), 0, 0, 0},
+
+        // x = sqrt(3)/2 ~ 0.8660254, asinfpi(x) = 1/3
+        // 0x3BF2 is float16 for ~0.866. 0x3555 is float16 for 1/3
+        {0x3BF2, ONE_OVER_THREE.uintval(), 0, 0, 0},
+
+        // x = -sqrt(3)/2 ~ -0.8660254, asinfpi(x) = -1/3
+        {0xBBF2, (fputil::FPBits<float16>(-ONE_OVER_THREE)).uintval(), 0, 0, 0},
+    }};
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
+  using FPBits = fputil::FPBits<float16>;
+
+  FPBits xbits(x);
+  uint16_t x_uint = xbits.uintval();
+  uint16_t x_abs = xbits.uintval() & 0x7fffU;
+  uint16_t x_sign = x_uint >> 15;
+
+  if (LIBC_UNLIKELY(x_abs > 0x3c00)) {
+    // aspinf16(NaN) = 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;
+    }
+
+    // 1 < |x| <= +/-inf
+    fputil::raise_except_if_required(FE_INVALID);
+    fputil::set_errno_if_required(EDOM);
+
+    return FPBits::quiet_nan().get_val();
+  }
+
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+  // Handle exceptional values
+  if (auto r = ACOSF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+    return r.value();
+
+#else
+  // Handling zero
+  if (LIBC_UNLIKELY(x_abs == 0x0000)) {
+    return x;
+  }
+
+  // Handling +/-1.0
+  // If x is +/-1.0, return +/-0.5
+  if (LIBC_UNLIKELY(x_abs == 0x3c00)) {
+    return fputil::cast<float16>(x_sign ? -ONE_OVER_TWO : ONE_OVER_TWO);
+  }
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+  // the coefficients for the polynomial approximation of asin(x)/pi in the
+  // range [0, 0.5] extracted using python-sympy
+  //
+  // Python code to generate the coefficients:
+  //   from sympy import *
+  //   import math
+  //   x = symbols('x')
+  //   print(series(asin(x)/math.pi, x, 0, 21))
+  //
+  // OUTPUT:
+  //
+  // 0.318309886183791*x + 0.0530516476972984*x**3 + 0.0238732414637843*x**5 +
+  // 0.0142102627760621*x**7 + 0.00967087327815336*x**9 +
+  // 0.00712127941391293*x**11 + 0.00552355646848375*x**13 +
+  // 0.00444514782463692*x**15 + 0.00367705242846804*x**17 +
+  // 0.00310721681820837*x**19 + O(x**21)
+  //
+  // it's very accurate in the range [0, 0.5] and has a maximum error of
+  // 0.0000000000000001 in the range [0, 0.5].
+  static constexpr float16 POLY_COEFFS[10] = {
+      0.318309886183791f16,   // x^1
+      0.0530516476972984f16,  // x^3
+      0.0238732414637843f16,  // x^5
+      0.0142102627760621f16,  // x^7
+      0.00967087327815336f16, // x^9
+      0.00712127941391293f16, // x^11
+      0.00552355646848375f16, // x^13
+      0.00444514782463692f16, // x^15
+      0.00367705242846804f16, // x^17
+      0.00310721681820837f16  // x^19
+  };
+
+  // polynomial evaluation using horner's method
+  // work only for |x| in [0, 0.5]
+  auto __asinpi_polyeval = [](float16 xsq) -> float16 {
+    return fputil::polyeval(xsq, POLY_COEFFS[0], POLY_COEFFS[1], POLY_COEFFS[2],
+                            POLY_COEFFS[3], POLY_COEFFS[4], POLY_COEFFS[5],
+                            POLY_COEFFS[6], POLY_COEFFS[7], POLY_COEFFS[9],
+                            POLY_COEFFS[9]);
+  };
+
+  // if |x| <= 0.5:
+  if (x_abs <= 0x3800) {
+    // Use polynomial approximation of asin(x)/pi in the range [0, 0.5]
+    float16 xsq = x * x;
+    float16 result = x * __asinpi_polyeval(xsq);
+    return fputil::cast<float16>(result);
+  }
+
+  // If |x| > 0.5, we need to use the range reduction method:
+  //    y = asin(x) => x = sin(y)
+  //      because: sin(a) = cos(pi/2 - a)
+  //      therefore:
+  //    x = cos(pi/2 - y)
+  //      let z = pi/2 - y,
+  //    x = cos(z)
+  //      becuase: cos(2a) = 1 - 2 * sin^2(a), z = 2a, a = z/2
+  //      therefore:
+  //    cos(z) = 1 - 2 * sin^2(z/2)
+  //    sin(z/2) = sqrt((1 - cos(z))/2)
+  //    sin(z/2) = sqrt((1 - x)/2)
+  //      let u = (1 - x)/2
+  //      then:
+  //    sin(z/2) = sqrt(u)
+  //    z/2 = asin(sqrt(u))
+  //    z = 2 * asin(sqrt(u))
+  //    pi/2 - y = 2 * asin(sqrt(u))
+  //    y = pi/2 - 2 * asin(sqrt(u))
+  //    y/pi = 1/2 - 2 * asin(sqrt(u))/pi
+  //
+  // Finally, we can write:
+  //   asinpi(x) = 1/2 - 2 * asinpi(sqrt(u))
+
+  float16 u = fputil::multiply_add(-ONE_OVER_TWO, x, ONE_OVER_TWO);
+
+  float16 asinpi_sqrt_u = __asinpi_polyeval(u);
+
+  float16 result = fputil::multiply_add(-2.0f16, asinpi_sqrt_u, ONE_OVER_TWO);
+
+  return fputil::cast<float16>(result);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

>From 813f341c3efa799fa310d8ff17d0c84323434b57 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Fri, 27 Jun 2025 22:40:29 +0300
Subject: [PATCH 02/19] formatting

---
 libc/src/math/generic/asinpif16.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/libc/src/math/generic/asinpif16.cpp b/libc/src/math/generic/asinpif16.cpp
index 7de675211e5d2..facb06b540644 100644
--- a/libc/src/math/generic/asinpif16.cpp
+++ b/libc/src/math/generic/asinpif16.cpp
@@ -180,9 +180,7 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   //   asinpi(x) = 1/2 - 2 * asinpi(sqrt(u))
 
   float16 u = fputil::multiply_add(-ONE_OVER_TWO, x, ONE_OVER_TWO);
-
   float16 asinpi_sqrt_u = __asinpi_polyeval(u);
-
   float16 result = fputil::multiply_add(-2.0f16, asinpi_sqrt_u, ONE_OVER_TWO);
 
   return fputil::cast<float16>(result);

>From 69e654e4657283b8dd7123b781953909cc14b66c Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Fri, 27 Jun 2025 22:46:14 +0300
Subject: [PATCH 03/19] builld: add missed entrypoint

---
 libc/src/math/CMakeLists.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index d177ff79141c0..e7ccb3726c54c 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -56,6 +56,8 @@ add_math_entrypoint_object(asinh)
 add_math_entrypoint_object(asinhf)
 add_math_entrypoint_object(asinhf16)
 
+add_math_entrypoint_object(asinpif16)
+
 add_math_entrypoint_object(atan)
 add_math_entrypoint_object(atanf)
 

>From 453cf1850b70c49b297dab33548677e5fea1e20c Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Fri, 27 Jun 2025 22:46:33 +0300
Subject: [PATCH 04/19] test: add unit tests for `asinpif16`

---
 libc/test/src/math/CMakeLists.txt     |  11 ++
 libc/test/src/math/asinpif16_test.cpp | 140 ++++++++++++++++++++++++++
 2 files changed, 151 insertions(+)
 create mode 100644 libc/test/src/math/asinpif16_test.cpp

diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 7ee8b86135557..e6786a706eec9 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2245,6 +2245,17 @@ add_fp_unittest(
     libc.src.math.asinf16  
 )
 
+add_fp_unittest(
+  asinfpi16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    asinpif16_test.cpp
+  DEPENDS
+    libc.src.math.asinpif16  
+)
+
 add_fp_unittest(
   acosf_test
   NEED_MPFR
diff --git a/libc/test/src/math/asinpif16_test.cpp b/libc/test/src/math/asinpif16_test.cpp
new file mode 100644
index 0000000000000..ba01bc0119f0c
--- /dev/null
+++ b/libc/test/src/math/asinpif16_test.cpp
@@ -0,0 +1,140 @@
+//===-- Unittests for asinpif16 -------------------------------------------===//
+//
+// 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/errno/libc_errno.h"
+#include "src/math/asinpif16.h"
+#include "test/UnitTest/FPMatcher.h"
+
+#include <errno.h>
+#include <stdint.h>
+
+using LlvmLibcAsinpif16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
+
+TEST_F(LlvmLibcAsinpif16Test, SpecialNumbers) {
+  using FPBits = LIBC_NAMESPACE::fputil::FPBits<float16>;
+
+  // Test zero
+  EXPECT_FP_EQ(FPBits::zero(), LIBC_NAMESPACE::asinpif16(FPBits::zero()));
+  EXPECT_FP_EQ(FPBits::neg_zero(),
+               LIBC_NAMESPACE::asinpif16(FPBits::neg_zero()));
+
+  // Test +/-1
+  EXPECT_FP_EQ(float16(0.5), LIBC_NAMESPACE::asinpif16(float16(1.0)));
+  EXPECT_FP_EQ(float16(-0.5), LIBC_NAMESPACE::asinpif16(float16(-1.0)));
+
+  // Test NaN inputs
+  EXPECT_FP_EQ(FPBits::quiet_nan(),
+               LIBC_NAMESPACE::asinpif16(FPBits::quiet_nan()));
+  EXPECT_FP_EQ(FPBits::quiet_nan(),
+               LIBC_NAMESPACE::asinpif16(FPBits::signaling_nan()));
+
+  // Test infinity inputs - should return NaN and set errno
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan(), LIBC_NAMESPACE::asinpif16(FPBits::inf()));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan(),
+               LIBC_NAMESPACE::asinpif16(FPBits::neg_inf()));
+  EXPECT_MATH_ERRNO(EDOM);
+}
+
+TEST_F(LlvmLibcAsinpif16Test, OutOfRange) {
+  using FPBits = LIBC_NAMESPACE::fputil::FPBits<float16>;
+
+  // Test values > 1
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan(), LIBC_NAMESPACE::asinpif16(float16(1.5)));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan(), LIBC_NAMESPACE::asinpif16(float16(2.0)));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  // Test values < -1
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan(), LIBC_NAMESPACE::asinpif16(float16(-1.5)));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan(), LIBC_NAMESPACE::asinpif16(float16(-2.0)));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  // Test maximum normal value (should be > 1 for float16)
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan(),
+               LIBC_NAMESPACE::asinpif16(FPBits::max_normal()));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan(),
+               LIBC_NAMESPACE::asinpif16(FPBits::max_normal().get_sign()));
+  EXPECT_MATH_ERRNO(EDOM);
+}
+
+TEST_F(LlvmLibcAsinpif16Test, SmallValues) {
+  using FPBits = LIBC_NAMESPACE::fputil::FPBits<float16>;
+
+  // Test very small values - should be close to x/π
+  constexpr float16 small_vals[] = {
+      0x1.0p-10,  // Small positive
+      -0x1.0p-10, // Small negative
+      0x1.0p-14,  // Very small positive
+      -0x1.0p-14, // Very small negative
+  };
+
+  for (float16 x : small_vals) {
+    float16 result = LIBC_NAMESPACE::asinpif16(x);
+    // For small x, asinpi(x) ≈ x/π ≈ 0.318309886 * x
+    // We expect the result to be close to x/π but not exactly due to polynomial
+    // approximation
+    EXPECT_TRUE(LIBC_NAMESPACE::fputil::abs(result) <=
+                LIBC_NAMESPACE::fputil::abs(x));
+  }
+
+  // Test minimum subnormal values
+  EXPECT_FP_EQ_ALL_ROUNDING(FPBits::min_subnormal(),
+                            LIBC_NAMESPACE::asinpif16(FPBits::min_subnormal()));
+  EXPECT_FP_EQ_ALL_ROUNDING(
+      FPBits::min_subnormal().get_sign(),
+      LIBC_NAMESPACE::asinpif16(FPBits::min_subnormal().get_sign()));
+}
+
+
+TEST_F(LlvmLibcAsinpif16Test, SymmetryProperty) {
+  // Test that asinpi(-x) = -asinpi(x)
+  constexpr float16 test_vals[] = {0.1, 0.25, 0.5, 0.75, 0.9, 0.99, 1.0};
+
+  for (float16 x : test_vals) {
+    if (x <= 1.0) { // Only test valid domain
+      float16 pos_result = LIBC_NAMESPACE::asinpif16(x);
+      float16 neg_result = LIBC_NAMESPACE::asinpif16(-x);
+
+      EXPECT_FP_EQ(pos_result, -neg_result);
+    }
+  }
+}
+
+TEST_F(LlvmLibcAsinpif16Test, RangeValidation) {
+  // Test that output is always in [-0.5, 0.5] for valid inputs
+  constexpr int num_tests = 1000;
+
+  for (int i = 0; i <= num_tests; ++i) {
+    // Generate test value in [-1, 1]
+    float t = -1.0f + (2.0f * i) / num_tests;
+    float16 x = static_cast<float16>(t);
+
+    if (LIBC_NAMESPACE::fputil::abs(x) <= 1.0) {
+      float16 result = LIBC_NAMESPACE::asinpif16(x);
+
+      // Result should be in [-0.5, 0.5]
+      EXPECT_TRUE(result >= -0.5);
+      EXPECT_TRUE(result <= 0.5);
+    }
+  }
+}
\ No newline at end of file

>From 1897e003b564b6fbe6010719156bd11f5a536975 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 28 Jun 2025 18:43:51 +0300
Subject: [PATCH 05/19] fix the typo in unittest build entry

---
 libc/test/src/math/CMakeLists.txt | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index e6786a706eec9..bd62b76817ceb 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2246,14 +2246,16 @@ add_fp_unittest(
 )
 
 add_fp_unittest(
-  asinfpi16_test
+  asinpif16_test
   NEED_MPFR
   SUITE
     libc-math-unittests
   SRCS
     asinpif16_test.cpp
   DEPENDS
-    libc.src.math.asinpif16  
+  libc.src.math.fabs
+  libc.src.math.asinpif16  
+  libc.src.__support.FPUtil.fp_bits
 )
 
 add_fp_unittest(

>From a8122b77119ad5fa812ba884f525c21c98e16006 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 28 Jun 2025 19:07:34 +0300
Subject: [PATCH 06/19] fix bugs

---
 libc/src/math/generic/asinpif16.cpp | 98 +++++++++++++----------------
 1 file changed, 43 insertions(+), 55 deletions(-)

diff --git a/libc/src/math/generic/asinpif16.cpp b/libc/src/math/generic/asinpif16.cpp
index facb06b540644..34b0b7e7779fc 100644
--- a/libc/src/math/generic/asinpif16.cpp
+++ b/libc/src/math/generic/asinpif16.cpp
@@ -6,60 +6,40 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/math/asinpif16.h"
 #include "hdr/errno_macros.h"
 #include "hdr/fenv_macros.h"
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/PolyEval.h"
 #include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/except_value_utils.h"
 #include "src/__support/FPUtil/multiply_add.h"
 #include "src/__support/FPUtil/sqrt.h"
 #include "src/__support/macros/optimization.h"
-#include "src/math/asinfpi16.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
-static constexpr float16 ONE_OVER_TWO = 0x3800; // 0.5f16
+static constexpr float16 ONE_OVER_TWO = 0.5f16;
 
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-static constexpr size_t N_ASINFPI_EXCEPTS = 9;
-
-static constexpr float16 ONE_OVER_THREE = 0x3555; // 0.333251953125f16
-static constexpr float16 ONE_OVER_FOUR = 0x3400;  // 0.25f16
-static constexpr float16 ONE_OVER_SIX = 0x32ab;   // 0.166748046875f16
+static constexpr size_t N_ASINFPI_EXCEPTS = 3;
+static constexpr float16 ONE_OVER_SIX = 0.166748046875f16;
 
 static constexpr fputil::ExceptValues<float16, N_ASINFPI_EXCEPTS>
     ASINFPI_EXCEPTS{{
         // (input_hex, RZ_output_hex, RU_offset, RD_offset, RN_offset)
-
         // x = 0.0, asinfpi(0.0) = 0.0
         {0x0000, 0x0000, 0, 0, 0},
 
         // x = 1.0, asinfpi(1.0) = 0.5
-        {0x3C00, ONE_OVER_TWO.uintval(), 0, 0, 0},
-
-        // x = -1.0, asinfpi(-1.0) = -0.5
-        {0xBC00, (fputil::FPBits<float16>(-ONE_OVER_TWO)).uintval(), 0, 0, 0},
+        {(fputil::FPBits<float16>(1.0f16)).uintval(),
+         (fputil::FPBits<float16>(ONE_OVER_TWO)).uintval(), 0, 0, 0},
 
         // x = 0.5, asinfpi(0.5) = 1/6
-        {0x3800, ONE_OVER_SIX.uintval(), 0, 0, 0},
-
-        // x = -0.5, asinfpi(-0.5) = -1/6
-        {0xB800, (fputil::FPBits<float16>(-ONE_OVER_SIX)).uintval(), 0, 0, 0},
-
-        // x = sqrt(2)/2 ~ 0.70710678, asinfpi(x) = 1/4
-        // 0x3B41 is float16 for ~0.707. 0x3400 is float16 for 0.25
-        {0x3B41, ONE_OVER_FOUR.uintval(), 0, 0, 0},
-
-        // x = -sqrt(2)/2 ~ -0.70710678, asinfpi(x) = -1/4
-        {0xBB41, (fputil::FPBits<float16>(-ONE_OVER_FOUR)).uintval(), 0, 0, 0},
-
-        // x = sqrt(3)/2 ~ 0.8660254, asinfpi(x) = 1/3
-        // 0x3BF2 is float16 for ~0.866. 0x3555 is float16 for 1/3
-        {0x3BF2, ONE_OVER_THREE.uintval(), 0, 0, 0},
+        {(fputil::FPBits<float16>(0.5f16)).uintval(),
+         (fputil::FPBits<float16>(ONE_OVER_SIX)).uintval(), 0, 0, 0},
 
-        // x = -sqrt(3)/2 ~ -0.8660254, asinfpi(x) = -1/3
-        {0xBBF2, (fputil::FPBits<float16>(-ONE_OVER_THREE)).uintval(), 0, 0, 0},
     }};
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
@@ -68,10 +48,14 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
 
   FPBits xbits(x);
   uint16_t x_uint = xbits.uintval();
-  uint16_t x_abs = xbits.uintval() & 0x7fffU;
-  uint16_t x_sign = x_uint >> 15;
+  bool is_neg = static_cast<bool>(x_uint >> 15);
+  float16 x_abs = is_neg ? -x : x;
 
-  if (LIBC_UNLIKELY(x_abs > 0x3c00)) {
+  auto __signed_result = [is_neg](float16 r) -> float16 {
+    return is_neg ? -r : r;
+  };
+
+  if (LIBC_UNLIKELY(x_abs > 1.0f16)) {
     // aspinf16(NaN) = NaN
     if (xbits.is_nan()) {
       if (xbits.is_signaling_nan()) {
@@ -89,31 +73,31 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   }
 
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-  // Handle exceptional values
-  if (auto r = ACOSF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
-    return r.value();
-
-#else
-  // Handling zero
-  if (LIBC_UNLIKELY(x_abs == 0x0000)) {
-    return x;
+  // exceptional values
+  if (auto r = ASINFPI_EXCEPTS.lookup(x_uint); LIBC_UNLIKELY(r.has_value())) {
+    return (r.value());
+  }
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+  // zero
+  if (LIBC_UNLIKELY(x_abs == 0.0f16)) {
+    return 0.0f16;
   }
 
-  // Handling +/-1.0
-  // If x is +/-1.0, return +/-0.5
-  if (LIBC_UNLIKELY(x_abs == 0x3c00)) {
-    return fputil::cast<float16>(x_sign ? -ONE_OVER_TWO : ONE_OVER_TWO);
+  // +/-1.0
+  // if x is +/-1.0, return +/-0.5
+  if (LIBC_UNLIKELY(x_abs == 1.0f16)) {
+    return fputil::cast<float16>(__signed_result(ONE_OVER_TWO));
   }
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
   // the coefficients for the polynomial approximation of asin(x)/pi in the
   // range [0, 0.5] extracted using python-sympy
   //
   // Python code to generate the coefficients:
-  //   from sympy import *
-  //   import math
-  //   x = symbols('x')
-  //   print(series(asin(x)/math.pi, x, 0, 21))
+  //  > from sympy import *
+  //  > import math
+  //  > x = symbols('x')
+  //  > print(series(asin(x)/math.pi, x, 0, 21))
   //
   // OUTPUT:
   //
@@ -143,16 +127,16 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   auto __asinpi_polyeval = [](float16 xsq) -> float16 {
     return fputil::polyeval(xsq, POLY_COEFFS[0], POLY_COEFFS[1], POLY_COEFFS[2],
                             POLY_COEFFS[3], POLY_COEFFS[4], POLY_COEFFS[5],
-                            POLY_COEFFS[6], POLY_COEFFS[7], POLY_COEFFS[9],
+                            POLY_COEFFS[6], POLY_COEFFS[7], POLY_COEFFS[8],
                             POLY_COEFFS[9]);
   };
 
   // if |x| <= 0.5:
-  if (x_abs <= 0x3800) {
+  if (LIBC_UNLIKELY(x_abs <= ONE_OVER_TWO)) {
     // Use polynomial approximation of asin(x)/pi in the range [0, 0.5]
     float16 xsq = x * x;
     float16 result = x * __asinpi_polyeval(xsq);
-    return fputil::cast<float16>(result);
+    return fputil::cast<float16>(__signed_result(result));
   }
 
   // If |x| > 0.5, we need to use the range reduction method:
@@ -178,12 +162,16 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   //
   // Finally, we can write:
   //   asinpi(x) = 1/2 - 2 * asinpi(sqrt(u))
+  //     where u = (1 - x) /2
+  //             = 0.5 - 0.5 * x
+  //             = multiply_add(-0.5, x, 0.5)
 
-  float16 u = fputil::multiply_add(-ONE_OVER_TWO, x, ONE_OVER_TWO);
-  float16 asinpi_sqrt_u = __asinpi_polyeval(u);
+  float16 u = fputil::multiply_add(-ONE_OVER_TWO, x_abs, ONE_OVER_TWO);
+  float16 u_sqrt = fputil::sqrt<float16>(u);
+  float16 asinpi_sqrt_u = u_sqrt * __asinpi_polyeval(u);
   float16 result = fputil::multiply_add(-2.0f16, asinpi_sqrt_u, ONE_OVER_TWO);
 
-  return fputil::cast<float16>(result);
+  return fputil::cast<float16>(__signed_result(result));
 }
 
 } // namespace LIBC_NAMESPACE_DECL

>From 50f9029c0945379a2e788135a184639cd0d66d83 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 28 Jun 2025 19:07:45 +0300
Subject: [PATCH 07/19] fix the test

---
 libc/test/src/math/asinpif16_test.cpp | 102 +++++++++-----------------
 1 file changed, 36 insertions(+), 66 deletions(-)

diff --git a/libc/test/src/math/asinpif16_test.cpp b/libc/test/src/math/asinpif16_test.cpp
index ba01bc0119f0c..6d8f76568902e 100644
--- a/libc/test/src/math/asinpif16_test.cpp
+++ b/libc/test/src/math/asinpif16_test.cpp
@@ -8,6 +8,7 @@
 
 #include "src/errno/libc_errno.h"
 #include "src/math/asinpif16.h"
+#include "src/math/fabs.h"
 #include "test/UnitTest/FPMatcher.h"
 
 #include <errno.h>
@@ -18,29 +19,28 @@ using LlvmLibcAsinpif16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
 TEST_F(LlvmLibcAsinpif16Test, SpecialNumbers) {
   using FPBits = LIBC_NAMESPACE::fputil::FPBits<float16>;
 
-  // Test zero
-  EXPECT_FP_EQ(FPBits::zero(), LIBC_NAMESPACE::asinpif16(FPBits::zero()));
-  EXPECT_FP_EQ(FPBits::neg_zero(),
-               LIBC_NAMESPACE::asinpif16(FPBits::neg_zero()));
+  // zero
+  EXPECT_FP_EQ(0.0f16, LIBC_NAMESPACE::asinpif16(0.0f16));
 
-  // Test +/-1
+  // +/-1
   EXPECT_FP_EQ(float16(0.5), LIBC_NAMESPACE::asinpif16(float16(1.0)));
   EXPECT_FP_EQ(float16(-0.5), LIBC_NAMESPACE::asinpif16(float16(-1.0)));
 
-  // Test NaN inputs
-  EXPECT_FP_EQ(FPBits::quiet_nan(),
-               LIBC_NAMESPACE::asinpif16(FPBits::quiet_nan()));
-  EXPECT_FP_EQ(FPBits::quiet_nan(),
-               LIBC_NAMESPACE::asinpif16(FPBits::signaling_nan()));
+  // NaN inputs
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(FPBits::quiet_nan().get_val()));
 
-  // Test infinity inputs - should return NaN and set errno
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(FPBits::signaling_nan().get_val()));
+
+  // infinity inputs -> should return NaN
   errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan(), LIBC_NAMESPACE::asinpif16(FPBits::inf()));
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(), LIBC_NAMESPACE::asinpif16(inf));
   EXPECT_MATH_ERRNO(EDOM);
 
   errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan(),
-               LIBC_NAMESPACE::asinpif16(FPBits::neg_inf()));
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(neg_inf));
   EXPECT_MATH_ERRNO(EDOM);
 }
 
@@ -49,73 +49,44 @@ TEST_F(LlvmLibcAsinpif16Test, OutOfRange) {
 
   // Test values > 1
   errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan(), LIBC_NAMESPACE::asinpif16(float16(1.5)));
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(float16(1.5)));
   EXPECT_MATH_ERRNO(EDOM);
 
   errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan(), LIBC_NAMESPACE::asinpif16(float16(2.0)));
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(float16(2.0)));
   EXPECT_MATH_ERRNO(EDOM);
 
   // Test values < -1
   errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan(), LIBC_NAMESPACE::asinpif16(float16(-1.5)));
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(float16(-1.5)));
   EXPECT_MATH_ERRNO(EDOM);
 
   errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan(), LIBC_NAMESPACE::asinpif16(float16(-2.0)));
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(float16(-2.0)));
   EXPECT_MATH_ERRNO(EDOM);
 
   // Test maximum normal value (should be > 1 for float16)
   errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan(),
-               LIBC_NAMESPACE::asinpif16(FPBits::max_normal()));
-  EXPECT_MATH_ERRNO(EDOM);
-
-  errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan(),
-               LIBC_NAMESPACE::asinpif16(FPBits::max_normal().get_sign()));
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(FPBits::max_normal().get_val()));
   EXPECT_MATH_ERRNO(EDOM);
 }
 
-TEST_F(LlvmLibcAsinpif16Test, SmallValues) {
-  using FPBits = LIBC_NAMESPACE::fputil::FPBits<float16>;
-
-  // Test very small values - should be close to x/π
-  constexpr float16 small_vals[] = {
-      0x1.0p-10,  // Small positive
-      -0x1.0p-10, // Small negative
-      0x1.0p-14,  // Very small positive
-      -0x1.0p-14, // Very small negative
-  };
-
-  for (float16 x : small_vals) {
-    float16 result = LIBC_NAMESPACE::asinpif16(x);
-    // For small x, asinpi(x) ≈ x/π ≈ 0.318309886 * x
-    // We expect the result to be close to x/π but not exactly due to polynomial
-    // approximation
-    EXPECT_TRUE(LIBC_NAMESPACE::fputil::abs(result) <=
-                LIBC_NAMESPACE::fputil::abs(x));
-  }
-
-  // Test minimum subnormal values
-  EXPECT_FP_EQ_ALL_ROUNDING(FPBits::min_subnormal(),
-                            LIBC_NAMESPACE::asinpif16(FPBits::min_subnormal()));
-  EXPECT_FP_EQ_ALL_ROUNDING(
-      FPBits::min_subnormal().get_sign(),
-      LIBC_NAMESPACE::asinpif16(FPBits::min_subnormal().get_sign()));
-}
-
-
 TEST_F(LlvmLibcAsinpif16Test, SymmetryProperty) {
   // Test that asinpi(-x) = -asinpi(x)
-  constexpr float16 test_vals[] = {0.1, 0.25, 0.5, 0.75, 0.9, 0.99, 1.0};
+  constexpr float16 test_vals[] = {0.1f16, 0.25f16, 0.5f16, 0.75f16,
+                                   0.9f16, 0.99f16, 1.0f16};
 
   for (float16 x : test_vals) {
-    if (x <= 1.0) { // Only test valid domain
+    if (x <= 1.0) {
       float16 pos_result = LIBC_NAMESPACE::asinpif16(x);
       float16 neg_result = LIBC_NAMESPACE::asinpif16(-x);
 
-      EXPECT_FP_EQ(pos_result, -neg_result);
+      EXPECT_FP_EQ(pos_result, LIBC_NAMESPACE::fabs(neg_result));
     }
   }
 }
@@ -125,16 +96,15 @@ TEST_F(LlvmLibcAsinpif16Test, RangeValidation) {
   constexpr int num_tests = 1000;
 
   for (int i = 0; i <= num_tests; ++i) {
-    // Generate test value in [-1, 1]
-    float t = -1.0f + (2.0f * i) / num_tests;
-    float16 x = static_cast<float16>(t);
+    float16 t = -1.0f16 + (2.0f16 * static_cast<float16>(i)) /
+                              static_cast<float16>(num_tests);
 
-    if (LIBC_NAMESPACE::fputil::abs(x) <= 1.0) {
-      float16 result = LIBC_NAMESPACE::asinpif16(x);
+    if (LIBC_NAMESPACE::fabs(t) <= 1.0) {
+      float16 result = LIBC_NAMESPACE::asinpif16(t);
 
-      // Result should be in [-0.5, 0.5]
-      EXPECT_TRUE(result >= -0.5);
-      EXPECT_TRUE(result <= 0.5);
+      // should be in [-0.5, 0.5]
+      EXPECT_TRUE(result >= -0.5f16);
+      EXPECT_TRUE(result <= 0.5f16);
     }
   }
-}
\ No newline at end of file
+}

>From 930f5be76abced4cf2762a32d23a99fdd105780e Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 28 Jun 2025 19:41:29 +0300
Subject: [PATCH 08/19] remove unesseccery code

---
 libc/src/math/generic/asinpif16.cpp | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/libc/src/math/generic/asinpif16.cpp b/libc/src/math/generic/asinpif16.cpp
index 34b0b7e7779fc..b66327c536f5f 100644
--- a/libc/src/math/generic/asinpif16.cpp
+++ b/libc/src/math/generic/asinpif16.cpp
@@ -79,17 +79,6 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   }
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
-  // zero
-  if (LIBC_UNLIKELY(x_abs == 0.0f16)) {
-    return 0.0f16;
-  }
-
-  // +/-1.0
-  // if x is +/-1.0, return +/-0.5
-  if (LIBC_UNLIKELY(x_abs == 1.0f16)) {
-    return fputil::cast<float16>(__signed_result(ONE_OVER_TWO));
-  }
-
   // the coefficients for the polynomial approximation of asin(x)/pi in the
   // range [0, 0.5] extracted using python-sympy
   //
@@ -101,6 +90,7 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   //
   // OUTPUT:
   //
+  // 
   // 0.318309886183791*x + 0.0530516476972984*x**3 + 0.0238732414637843*x**5 +
   // 0.0142102627760621*x**7 + 0.00967087327815336*x**9 +
   // 0.00712127941391293*x**11 + 0.00552355646848375*x**13 +

>From 3db1b0dcbd0fd2890d9ad12ea4842de6092dc867 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 28 Jun 2025 20:06:35 +0300
Subject: [PATCH 09/19] add negatives for expected values

---
 libc/src/math/generic/asinpif16.cpp | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/libc/src/math/generic/asinpif16.cpp b/libc/src/math/generic/asinpif16.cpp
index b66327c536f5f..fdcf8f78bb8d0 100644
--- a/libc/src/math/generic/asinpif16.cpp
+++ b/libc/src/math/generic/asinpif16.cpp
@@ -23,7 +23,7 @@ namespace LIBC_NAMESPACE_DECL {
 static constexpr float16 ONE_OVER_TWO = 0.5f16;
 
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-static constexpr size_t N_ASINFPI_EXCEPTS = 3;
+static constexpr size_t N_ASINFPI_EXCEPTS = 5;
 static constexpr float16 ONE_OVER_SIX = 0.166748046875f16;
 
 static constexpr fputil::ExceptValues<float16, N_ASINFPI_EXCEPTS>
@@ -32,14 +32,22 @@ static constexpr fputil::ExceptValues<float16, N_ASINFPI_EXCEPTS>
         // x = 0.0, asinfpi(0.0) = 0.0
         {0x0000, 0x0000, 0, 0, 0},
 
-        // x = 1.0, asinfpi(1.0) = 0.5
-        {(fputil::FPBits<float16>(1.0f16)).uintval(),
-         (fputil::FPBits<float16>(ONE_OVER_TWO)).uintval(), 0, 0, 0},
+        // x = 1.0, asinfpi(1) = 1/2
+        {(fputil::FPBits<float16>(-1.0f16)).uintval(),
+         (fputil::FPBits<float16>(-ONE_OVER_TWO)).uintval(), 0, 0, 0},
+
+        // x = -1.0, asinfpi(-1.0) = -1/2
+        {(fputil::FPBits<float16>(-1.0f16)).uintval(),
+         (fputil::FPBits<float16>(-ONE_OVER_TWO)).uintval(), 0, 0, 0},
 
         // x = 0.5, asinfpi(0.5) = 1/6
         {(fputil::FPBits<float16>(0.5f16)).uintval(),
          (fputil::FPBits<float16>(ONE_OVER_SIX)).uintval(), 0, 0, 0},
 
+        // x = -0.5, asinfpi(0.5) = -1/6
+        {(fputil::FPBits<float16>(-0.5f16)).uintval(),
+         (fputil::FPBits<float16>(-ONE_OVER_SIX)).uintval(), 0, 0, 0},
+
     }};
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
@@ -75,7 +83,7 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
   // exceptional values
   if (auto r = ASINFPI_EXCEPTS.lookup(x_uint); LIBC_UNLIKELY(r.has_value())) {
-    return (r.value());
+    return r.value();
   }
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
@@ -90,7 +98,7 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   //
   // OUTPUT:
   //
-  // 
+  //
   // 0.318309886183791*x + 0.0530516476972984*x**3 + 0.0238732414637843*x**5 +
   // 0.0142102627760621*x**7 + 0.00967087327815336*x**9 +
   // 0.00712127941391293*x**11 + 0.00552355646848375*x**13 +

>From 1097815848c58f49c6523a252d62eabcac23128c Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 28 Jun 2025 20:06:52 +0300
Subject: [PATCH 10/19] remove unused headers

---
 libc/test/src/math/asinpif16_test.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/libc/test/src/math/asinpif16_test.cpp b/libc/test/src/math/asinpif16_test.cpp
index 6d8f76568902e..7dad1b8fff3ed 100644
--- a/libc/test/src/math/asinpif16_test.cpp
+++ b/libc/test/src/math/asinpif16_test.cpp
@@ -6,14 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "src/errno/libc_errno.h"
 #include "src/math/asinpif16.h"
 #include "src/math/fabs.h"
 #include "test/UnitTest/FPMatcher.h"
 
-#include <errno.h>
-#include <stdint.h>
-
 using LlvmLibcAsinpif16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
 
 TEST_F(LlvmLibcAsinpif16Test, SpecialNumbers) {

>From efa3207b799456c32b4971a628b6f167d824b0f2 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 28 Jun 2025 20:09:13 +0300
Subject: [PATCH 11/19] fix formatting

---
 libc/src/math/generic/asinpif16.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libc/src/math/generic/asinpif16.cpp b/libc/src/math/generic/asinpif16.cpp
index fdcf8f78bb8d0..fdfb4484c9dfe 100644
--- a/libc/src/math/generic/asinpif16.cpp
+++ b/libc/src/math/generic/asinpif16.cpp
@@ -98,7 +98,6 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   //
   // OUTPUT:
   //
-  //
   // 0.318309886183791*x + 0.0530516476972984*x**3 + 0.0238732414637843*x**5 +
   // 0.0142102627760621*x**7 + 0.00967087327815336*x**9 +
   // 0.00712127941391293*x**11 + 0.00552355646848375*x**13 +

>From fae817a88fb287066b133b7d00cbef1673dbb4d8 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 28 Jun 2025 23:42:30 +0300
Subject: [PATCH 12/19] revert the trailing space

---
 libc/include/math.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/include/math.yaml b/libc/include/math.yaml
index d508c8bcdd7ed..07f6a46af5cae 100644
--- a/libc/include/math.yaml
+++ b/libc/include/math.yaml
@@ -84,7 +84,7 @@ functions:
       - stdc
     return_type: double
     arguments:
-      - type: double 
+      - type: double
   - name: asinpif16
     standards:
       - stdc

>From 58903b024a2c877b86ffab7f1775f637346ebb70 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 28 Jun 2025 23:43:06 +0300
Subject: [PATCH 13/19] fix typos

---
 libc/src/math/asinpif16.h           | 4 ++--
 libc/src/math/generic/asinpif16.cpp | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/libc/src/math/asinpif16.h b/libc/src/math/asinpif16.h
index 67ccb4ff4ac3d..b97166af63f5d 100644
--- a/libc/src/math/asinpif16.h
+++ b/libc/src/math/asinpif16.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIBC_SRC_MATH_ASINFPI16_H
-#define LLVM_LIBC_SRC_MATH_ASINFPI16_H
+#ifndef LLVM_LIBC_SRC_MATH_ASINPIF16_H
+#define LLVM_LIBC_SRC_MATH_ASINPIF16_H
 
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/properties/types.h"
diff --git a/libc/src/math/generic/asinpif16.cpp b/libc/src/math/generic/asinpif16.cpp
index fdfb4484c9dfe..b6cd49e58a140 100644
--- a/libc/src/math/generic/asinpif16.cpp
+++ b/libc/src/math/generic/asinpif16.cpp
@@ -1,4 +1,4 @@
-//===-- Half-precision asinf16(x) function --------------------------------===//
+//===-- Half-precision asinpif16(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.

>From 7a2b4afd9af6056a476b8422d70ffa9f9e13ab97 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 28 Jun 2025 23:43:21 +0300
Subject: [PATCH 14/19] renaming lambdas

---
 libc/src/math/generic/asinpif16.cpp | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/libc/src/math/generic/asinpif16.cpp b/libc/src/math/generic/asinpif16.cpp
index b6cd49e58a140..a3c3fe8c3f9e0 100644
--- a/libc/src/math/generic/asinpif16.cpp
+++ b/libc/src/math/generic/asinpif16.cpp
@@ -59,7 +59,7 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   bool is_neg = static_cast<bool>(x_uint >> 15);
   float16 x_abs = is_neg ? -x : x;
 
-  auto __signed_result = [is_neg](float16 r) -> float16 {
+  auto signed_result = [is_neg](float16 r) -> float16 {
     return is_neg ? -r : r;
   };
 
@@ -82,9 +82,8 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
 
 #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
   // exceptional values
-  if (auto r = ASINFPI_EXCEPTS.lookup(x_uint); LIBC_UNLIKELY(r.has_value())) {
+  if (auto r = ASINFPI_EXCEPTS.lookup(x_uint); LIBC_UNLIKELY(r.has_value()))
     return r.value();
-  }
 #endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
 
   // the coefficients for the polynomial approximation of asin(x)/pi in the
@@ -121,7 +120,7 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
 
   // polynomial evaluation using horner's method
   // work only for |x| in [0, 0.5]
-  auto __asinpi_polyeval = [](float16 xsq) -> float16 {
+  auto asinpi_polyeval = [](float16 xsq) -> float16 {
     return fputil::polyeval(xsq, POLY_COEFFS[0], POLY_COEFFS[1], POLY_COEFFS[2],
                             POLY_COEFFS[3], POLY_COEFFS[4], POLY_COEFFS[5],
                             POLY_COEFFS[6], POLY_COEFFS[7], POLY_COEFFS[8],
@@ -132,8 +131,8 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   if (LIBC_UNLIKELY(x_abs <= ONE_OVER_TWO)) {
     // Use polynomial approximation of asin(x)/pi in the range [0, 0.5]
     float16 xsq = x * x;
-    float16 result = x * __asinpi_polyeval(xsq);
-    return fputil::cast<float16>(__signed_result(result));
+    float16 result = x * asinpi_polyeval(xsq);
+    return fputil::cast<float16>(signed_result(result));
   }
 
   // If |x| > 0.5, we need to use the range reduction method:
@@ -165,10 +164,10 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
 
   float16 u = fputil::multiply_add(-ONE_OVER_TWO, x_abs, ONE_OVER_TWO);
   float16 u_sqrt = fputil::sqrt<float16>(u);
-  float16 asinpi_sqrt_u = u_sqrt * __asinpi_polyeval(u);
+  float16 asinpi_sqrt_u = u_sqrt * asinpi_polyeval(u);
   float16 result = fputil::multiply_add(-2.0f16, asinpi_sqrt_u, ONE_OVER_TWO);
 
-  return fputil::cast<float16>(__signed_result(result));
+  return fputil::cast<float16>(signed_result(result));
 }
 
 } // namespace LIBC_NAMESPACE_DECL

>From 30e4cc0d91cef7bdcdfff3b6009cbf90232e9346 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 28 Jun 2025 23:43:42 +0300
Subject: [PATCH 15/19] missed build dependencies

---
 libc/src/math/generic/CMakeLists.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 1525c0fa032bf..ab72c8a47e811 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -4011,9 +4011,12 @@ add_entrypoint_object(
     libc.hdr.errno_macros
     libc.hdr.fenv_macros
     libc.src.__support.FPUtil.cast
+    libc.src.__support.FPUtil.except_value_utils
     libc.src.__support.FPUtil.fenv_impl
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.FPUtil.polyeval
+    libc.src.__support.FPUtil.sqrt
     libc.src.__support.macros.optimization
 )
 

>From c20d7b162a7b9c7035c5114fe96f2db4c1db1c4b Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 28 Jun 2025 23:53:28 +0300
Subject: [PATCH 16/19] fix warnings come fromm
 `LlvmLibcAsinpif16Test.SymmetryProperty` test

---
 libc/test/src/math/asinpif16_test.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libc/test/src/math/asinpif16_test.cpp b/libc/test/src/math/asinpif16_test.cpp
index 7dad1b8fff3ed..cfeff3640875c 100644
--- a/libc/test/src/math/asinpif16_test.cpp
+++ b/libc/test/src/math/asinpif16_test.cpp
@@ -82,7 +82,8 @@ TEST_F(LlvmLibcAsinpif16Test, SymmetryProperty) {
       float16 pos_result = LIBC_NAMESPACE::asinpif16(x);
       float16 neg_result = LIBC_NAMESPACE::asinpif16(-x);
 
-      EXPECT_FP_EQ(pos_result, LIBC_NAMESPACE::fabs(neg_result));
+      EXPECT_FP_EQ(pos_result,
+                   static_cast<float16>(LIBC_NAMESPACE::fabs(neg_result)));
     }
   }
 }

>From 521296d14157f70186fd5d45a64d4e0209202ba3 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sun, 29 Jun 2025 01:55:07 +0300
Subject: [PATCH 17/19] use higher-precision type for poly coeffs

---
 libc/src/math/generic/asinpif16.cpp | 39 ++++++++++++++---------------
 1 file changed, 19 insertions(+), 20 deletions(-)

diff --git a/libc/src/math/generic/asinpif16.cpp b/libc/src/math/generic/asinpif16.cpp
index a3c3fe8c3f9e0..644210e993d71 100644
--- a/libc/src/math/generic/asinpif16.cpp
+++ b/libc/src/math/generic/asinpif16.cpp
@@ -59,9 +59,7 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   bool is_neg = static_cast<bool>(x_uint >> 15);
   float16 x_abs = is_neg ? -x : x;
 
-  auto signed_result = [is_neg](float16 r) -> float16 {
-    return is_neg ? -r : r;
-  };
+  auto signed_result = [is_neg](auto r) -> auto { return is_neg ? -r : r; };
 
   if (LIBC_UNLIKELY(x_abs > 1.0f16)) {
     // aspinf16(NaN) = NaN
@@ -105,22 +103,22 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   //
   // it's very accurate in the range [0, 0.5] and has a maximum error of
   // 0.0000000000000001 in the range [0, 0.5].
-  static constexpr float16 POLY_COEFFS[10] = {
-      0.318309886183791f16,   // x^1
-      0.0530516476972984f16,  // x^3
-      0.0238732414637843f16,  // x^5
-      0.0142102627760621f16,  // x^7
-      0.00967087327815336f16, // x^9
-      0.00712127941391293f16, // x^11
-      0.00552355646848375f16, // x^13
-      0.00444514782463692f16, // x^15
-      0.00367705242846804f16, // x^17
-      0.00310721681820837f16  // x^19
+  static constexpr float POLY_COEFFS[10] = {
+      0.318309886183791f,   // x^1
+      0.0530516476972984f,  // x^3
+      0.0238732414637843f,  // x^5
+      0.0142102627760621f,  // x^7
+      0.00967087327815336f, // x^9
+      0.00712127941391293f, // x^11
+      0.00552355646848375f, // x^13
+      0.00444514782463692f, // x^15
+      0.00367705242846804f, // x^17
+      0.00310721681820837f  // x^19
   };
 
   // polynomial evaluation using horner's method
   // work only for |x| in [0, 0.5]
-  auto asinpi_polyeval = [](float16 xsq) -> float16 {
+  auto asinpi_polyeval = [](float xsq) -> float {
     return fputil::polyeval(xsq, POLY_COEFFS[0], POLY_COEFFS[1], POLY_COEFFS[2],
                             POLY_COEFFS[3], POLY_COEFFS[4], POLY_COEFFS[5],
                             POLY_COEFFS[6], POLY_COEFFS[7], POLY_COEFFS[8],
@@ -131,7 +129,7 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   if (LIBC_UNLIKELY(x_abs <= ONE_OVER_TWO)) {
     // Use polynomial approximation of asin(x)/pi in the range [0, 0.5]
     float16 xsq = x * x;
-    float16 result = x * asinpi_polyeval(xsq);
+    float result = x * asinpi_polyeval(xsq);
     return fputil::cast<float16>(signed_result(result));
   }
 
@@ -162,10 +160,11 @@ LLVM_LIBC_FUNCTION(float16, asinpif16, (float16 x)) {
   //             = 0.5 - 0.5 * x
   //             = multiply_add(-0.5, x, 0.5)
 
-  float16 u = fputil::multiply_add(-ONE_OVER_TWO, x_abs, ONE_OVER_TWO);
-  float16 u_sqrt = fputil::sqrt<float16>(u);
-  float16 asinpi_sqrt_u = u_sqrt * asinpi_polyeval(u);
-  float16 result = fputil::multiply_add(-2.0f16, asinpi_sqrt_u, ONE_OVER_TWO);
+  float u = static_cast<float>(
+      fputil::multiply_add(-ONE_OVER_TWO, x_abs, ONE_OVER_TWO));
+  float u_sqrt = fputil::sqrt<float>(static_cast<float>(u));
+  float asinpi_sqrt_u = u_sqrt * asinpi_polyeval(u);
+  float result = fputil::multiply_add(-2.0f16, asinpi_sqrt_u, ONE_OVER_TWO);
 
   return fputil::cast<float16>(signed_result(result));
 }

>From bf172b185d56a080e948fccac0d0fa3245528e94 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Mon, 30 Jun 2025 07:14:29 +0300
Subject: [PATCH 18/19] make an exhaustive test for `asinpif16`

---
 libc/test/src/math/CMakeLists.txt     |   2 -
 libc/test/src/math/asinpif16_test.cpp | 111 ++++++--------------------
 libc/utils/MPFRWrapper/MPCommon.cpp   |   6 ++
 libc/utils/MPFRWrapper/MPCommon.h     |   1 +
 libc/utils/MPFRWrapper/MPFRUtils.cpp  |   2 +
 libc/utils/MPFRWrapper/MPFRUtils.h    |   1 +
 6 files changed, 34 insertions(+), 89 deletions(-)

diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 3b95d7bc8c035..2a35243d63ab0 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2275,9 +2275,7 @@ add_fp_unittest(
   SRCS
     asinpif16_test.cpp
   DEPENDS
-  libc.src.math.fabs
   libc.src.math.asinpif16  
-  libc.src.__support.FPUtil.fp_bits
 )
 
 add_fp_unittest(
diff --git a/libc/test/src/math/asinpif16_test.cpp b/libc/test/src/math/asinpif16_test.cpp
index cfeff3640875c..8da9f45d5535b 100644
--- a/libc/test/src/math/asinpif16_test.cpp
+++ b/libc/test/src/math/asinpif16_test.cpp
@@ -1,4 +1,4 @@
-//===-- Unittests for asinpif16 -------------------------------------------===//
+//===-- Exhaustive test for asinpif16 -------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,101 +7,38 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/math/asinpif16.h"
-#include "src/math/fabs.h"
 #include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
 
 using LlvmLibcAsinpif16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
 
-TEST_F(LlvmLibcAsinpif16Test, SpecialNumbers) {
-  using FPBits = LIBC_NAMESPACE::fputil::FPBits<float16>;
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
 
-  // zero
-  EXPECT_FP_EQ(0.0f16, LIBC_NAMESPACE::asinpif16(0.0f16));
+// Range: [0, Inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7c00U;
 
-  // +/-1
-  EXPECT_FP_EQ(float16(0.5), LIBC_NAMESPACE::asinpif16(float16(1.0)));
-  EXPECT_FP_EQ(float16(-0.5), LIBC_NAMESPACE::asinpif16(float16(-1.0)));
+// Range: [-Inf, 0]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xfc00U;
 
-  // NaN inputs
-  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
-               LIBC_NAMESPACE::asinpif16(FPBits::quiet_nan().get_val()));
-
-  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
-               LIBC_NAMESPACE::asinpif16(FPBits::signaling_nan().get_val()));
-
-  // infinity inputs -> should return NaN
-  errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(), LIBC_NAMESPACE::asinpif16(inf));
-  EXPECT_MATH_ERRNO(EDOM);
-
-  errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
-               LIBC_NAMESPACE::asinpif16(neg_inf));
-  EXPECT_MATH_ERRNO(EDOM);
-}
-
-TEST_F(LlvmLibcAsinpif16Test, OutOfRange) {
-  using FPBits = LIBC_NAMESPACE::fputil::FPBits<float16>;
-
-  // Test values > 1
-  errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
-               LIBC_NAMESPACE::asinpif16(float16(1.5)));
-  EXPECT_MATH_ERRNO(EDOM);
-
-  errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
-               LIBC_NAMESPACE::asinpif16(float16(2.0)));
-  EXPECT_MATH_ERRNO(EDOM);
-
-  // Test values < -1
-  errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
-               LIBC_NAMESPACE::asinpif16(float16(-1.5)));
-  EXPECT_MATH_ERRNO(EDOM);
-
-  errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
-               LIBC_NAMESPACE::asinpif16(float16(-2.0)));
-  EXPECT_MATH_ERRNO(EDOM);
-
-  // Test maximum normal value (should be > 1 for float16)
-  errno = 0;
-  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
-               LIBC_NAMESPACE::asinpif16(FPBits::max_normal().get_val()));
-  EXPECT_MATH_ERRNO(EDOM);
-}
-
-TEST_F(LlvmLibcAsinpif16Test, SymmetryProperty) {
-  // Test that asinpi(-x) = -asinpi(x)
-  constexpr float16 test_vals[] = {0.1f16, 0.25f16, 0.5f16, 0.75f16,
-                                   0.9f16, 0.99f16, 1.0f16};
-
-  for (float16 x : test_vals) {
-    if (x <= 1.0) {
-      float16 pos_result = LIBC_NAMESPACE::asinpif16(x);
-      float16 neg_result = LIBC_NAMESPACE::asinpif16(-x);
-
-      EXPECT_FP_EQ(pos_result,
-                   static_cast<float16>(LIBC_NAMESPACE::fabs(neg_result)));
-    }
+TEST_F(LlvmLibcAsinpif16Test, PositiveRange) {
+  for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
+    float16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asinpi, x,
+                                   LIBC_NAMESPACE::asinpif16(x), 0.5);
+    break;
   }
 }
 
-TEST_F(LlvmLibcAsinpif16Test, RangeValidation) {
-  // Test that output is always in [-0.5, 0.5] for valid inputs
-  constexpr int num_tests = 1000;
-
-  for (int i = 0; i <= num_tests; ++i) {
-    float16 t = -1.0f16 + (2.0f16 * static_cast<float16>(i)) /
-                              static_cast<float16>(num_tests);
-
-    if (LIBC_NAMESPACE::fabs(t) <= 1.0) {
-      float16 result = LIBC_NAMESPACE::asinpif16(t);
-
-      // should be in [-0.5, 0.5]
-      EXPECT_TRUE(result >= -0.5f16);
-      EXPECT_TRUE(result <= 0.5f16);
-    }
+TEST_F(LlvmLibcAsinpif16Test, NegativeRange) {
+  int i = 0;
+  for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
+    float16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asinpi, -x,
+                                   LIBC_NAMESPACE::asinpif16(-x), 0.5);
+    if (i++ == 10)
+      break;
   }
 }
diff --git a/libc/utils/MPFRWrapper/MPCommon.cpp b/libc/utils/MPFRWrapper/MPCommon.cpp
index ccd4d2d01a4e2..7dde0d09e6ff6 100644
--- a/libc/utils/MPFRWrapper/MPCommon.cpp
+++ b/libc/utils/MPFRWrapper/MPCommon.cpp
@@ -105,6 +105,12 @@ MPFRNumber MPFRNumber::asinh() const {
   return result;
 }
 
+MPFRNumber MPFRNumber::asinpi() const {
+  MPFRNumber result(*this);
+  mpfr_asinpi(result.value, value, mpfr_rounding);
+  return result;
+}
+
 MPFRNumber MPFRNumber::atan() const {
   MPFRNumber result(*this);
   mpfr_atan(result.value, value, mpfr_rounding);
diff --git a/libc/utils/MPFRWrapper/MPCommon.h b/libc/utils/MPFRWrapper/MPCommon.h
index 99cb7ec66a2ca..51c971215cf8f 100644
--- a/libc/utils/MPFRWrapper/MPCommon.h
+++ b/libc/utils/MPFRWrapper/MPCommon.h
@@ -185,6 +185,7 @@ class MPFRNumber {
   MPFRNumber add(const MPFRNumber &b) const;
   MPFRNumber asin() const;
   MPFRNumber asinh() const;
+  MPFRNumber asinpi() const;
   MPFRNumber atan() const;
   MPFRNumber atan2(const MPFRNumber &b);
   MPFRNumber atanh() const;
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index 8853f96ef8f92..c58aae75cc700 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -38,6 +38,8 @@ unary_operation(Operation op, InputType input, unsigned int precision,
     return mpfrInput.asin();
   case Operation::Asinh:
     return mpfrInput.asinh();
+  case Operation::Asinpi:
+    return mpfrInput.asinpi();
   case Operation::Atan:
     return mpfrInput.atan();
   case Operation::Atanh:
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h
index c77a6aa3adeae..3b2d010473f7b 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.h
+++ b/libc/utils/MPFRWrapper/MPFRUtils.h
@@ -31,6 +31,7 @@ enum class Operation : int {
   Acospi,
   Asin,
   Asinh,
+  Asinpi,
   Atan,
   Atanh,
   Cbrt,

>From 6b9534f5e0d453c39ff0f152917d7eea2e08d5a6 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Mon, 30 Jun 2025 07:14:43 +0300
Subject: [PATCH 19/19] move old test to smoke

---
 libc/test/src/math/smoke/CMakeLists.txt     | 13 +++
 libc/test/src/math/smoke/asinpif16_test.cpp | 89 +++++++++++++++++++++
 2 files changed, 102 insertions(+)
 create mode 100644 libc/test/src/math/smoke/asinpif16_test.cpp

diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 599939cbec4b5..51aaf0b0d9f0d 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -3982,6 +3982,19 @@ add_fp_unittest(
     libc.src.math.asinhf16
 )
 
+add_fp_unittest(
+  asinpif16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    asinpif16_test.cpp
+  DEPENDS
+  libc.src.math.fabs
+  libc.src.math.asinpif16  
+  libc.src.__support.FPUtil.fp_bits
+)
+
 add_fp_unittest(
   acoshf_test
   SUITE
diff --git a/libc/test/src/math/smoke/asinpif16_test.cpp b/libc/test/src/math/smoke/asinpif16_test.cpp
new file mode 100644
index 0000000000000..4bf630168864e
--- /dev/null
+++ b/libc/test/src/math/smoke/asinpif16_test.cpp
@@ -0,0 +1,89 @@
+//===-- Unittests for asinpif16 -------------------------------------------===//
+//
+// 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/asinpif16.h"
+#include "src/math/fabs.h"
+#include "test/UnitTest/FPMatcher.h"
+
+using LlvmLibcAsinpif16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
+
+TEST_F(LlvmLibcAsinpif16Test, SpecialNumbers) {
+  using FPBits = LIBC_NAMESPACE::fputil::FPBits<float16>;
+
+  // zero
+  EXPECT_FP_EQ(0.0f16, LIBC_NAMESPACE::asinpif16(0.0f16));
+
+  // +/-1
+  EXPECT_FP_EQ(float16(0.5), LIBC_NAMESPACE::asinpif16(float16(1.0)));
+  EXPECT_FP_EQ(float16(-0.5), LIBC_NAMESPACE::asinpif16(float16(-1.0)));
+
+  // NaN inputs
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(FPBits::quiet_nan().get_val()));
+
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(FPBits::signaling_nan().get_val()));
+
+  // infinity inputs -> should return NaN
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(), LIBC_NAMESPACE::asinpif16(inf));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(neg_inf));
+  EXPECT_MATH_ERRNO(EDOM);
+}
+
+TEST_F(LlvmLibcAsinpif16Test, OutOfRange) {
+  using FPBits = LIBC_NAMESPACE::fputil::FPBits<float16>;
+
+  // Test values > 1
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(float16(1.5)));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(float16(2.0)));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  // Test values < -1
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(float16(-1.5)));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(float16(-2.0)));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  // Test maximum normal value (should be > 1 for float16)
+  errno = 0;
+  EXPECT_FP_EQ(FPBits::quiet_nan().get_val(),
+               LIBC_NAMESPACE::asinpif16(FPBits::max_normal().get_val()));
+  EXPECT_MATH_ERRNO(EDOM);
+}
+
+TEST_F(LlvmLibcAsinpif16Test, SymmetryProperty) {
+  // Test that asinpi(-x) = -asinpi(x)
+  constexpr float16 test_vals[] = {0.1f16, 0.25f16, 0.5f16, 0.75f16,
+                                   0.9f16, 0.99f16, 1.0f16};
+
+  for (float16 x : test_vals) {
+    if (x <= 1.0) {
+      float16 pos_result = LIBC_NAMESPACE::asinpif16(x);
+      float16 neg_result = LIBC_NAMESPACE::asinpif16(-x);
+
+      EXPECT_FP_EQ(pos_result,
+                   static_cast<float16>(LIBC_NAMESPACE::fabs(neg_result)));
+    }
+  }
+}



More information about the libc-commits mailing list