From 8f3dd82a0a1fd3395e903c8b44e2e5f9f2118ff5 Mon Sep 17 00:00:00 2001 From: Mohamed Emad Date: Thu, 26 Feb 2026 05:05:49 +0200 Subject: [PATCH] [libc][math][c23] implement `asinpif` function (#181511) Implementing `asinpi` for single-precision. it continues what is done in #152690 that implemented `asinpif16` with header-only approach that is followed since #147386 --- 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/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 | 2 + libc/docs/headers/math/index.rst | 2 +- libc/shared/math.h | 1 + libc/shared/math/asinpif.h | 23 +++ libc/src/__support/math/CMakeLists.txt | 15 ++ libc/src/__support/math/asinpif.h | 152 ++++++++++++++++++ libc/src/math/CMakeLists.txt | 1 + libc/src/math/asinpif.h | 20 +++ libc/src/math/generic/CMakeLists.txt | 10 ++ libc/src/math/generic/asinpif.cpp | 16 ++ libc/test/shared/CMakeLists.txt | 1 + libc/test/shared/shared_math_test.cpp | 1 + libc/test/src/math/CMakeLists.txt | 11 ++ libc/test/src/math/asinpif_test.cpp | 38 +++++ libc/test/src/math/exhaustive/CMakeLists.txt | 16 ++ .../test/src/math/exhaustive/asinpif_test.cpp | 33 ++++ libc/test/src/math/smoke/CMakeLists.txt | 12 ++ libc/test/src/math/smoke/asinpif_test.cpp | 44 +++++ .../llvm-project-overlay/libc/BUILD.bazel | 24 +++ 29 files changed, 431 insertions(+), 1 deletion(-) create mode 100644 libc/shared/math/asinpif.h create mode 100644 libc/src/__support/math/asinpif.h create mode 100644 libc/src/math/asinpif.h create mode 100644 libc/src/math/generic/asinpif.cpp create mode 100644 libc/test/src/math/asinpif_test.cpp create mode 100644 libc/test/src/math/exhaustive/asinpif_test.cpp create mode 100644 libc/test/src/math/smoke/asinpif_test.cpp diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt index 742d96761c41..582e7c52726f 100644 --- a/libc/config/baremetal/aarch64/entrypoints.txt +++ b/libc/config/baremetal/aarch64/entrypoints.txt @@ -339,6 +339,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.asin libc.src.math.asinf libc.src.math.asinhf + libc.src.math.asinpif libc.src.math.atan2 libc.src.math.atan2f # libc.src.math.atan2l diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt index 95cb0dea8e49..98374e6cede7 100644 --- a/libc/config/baremetal/arm/entrypoints.txt +++ b/libc/config/baremetal/arm/entrypoints.txt @@ -342,6 +342,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.asin libc.src.math.asinf libc.src.math.asinhf + libc.src.math.asinpif libc.src.math.atan2 libc.src.math.atan2f libc.src.math.atan2l diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt index 3fc71280f516..b45b388ec963 100644 --- a/libc/config/baremetal/riscv/entrypoints.txt +++ b/libc/config/baremetal/riscv/entrypoints.txt @@ -340,6 +340,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.acoshf libc.src.math.asinf libc.src.math.asinhf + libc.src.math.asinpif libc.src.math.atan2 libc.src.math.atan2f # libc.src.math.atan2l diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt index 3909417f9730..5488bf1d0c7d 100644 --- a/libc/config/darwin/aarch64/entrypoints.txt +++ b/libc/config/darwin/aarch64/entrypoints.txt @@ -156,6 +156,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.asin libc.src.math.asinf libc.src.math.asinhf + libc.src.math.asinpif libc.src.math.atan2 libc.src.math.atan2f libc.src.math.atan diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt index 0dda7d5c683e..856bf1d55f3b 100644 --- a/libc/config/gpu/amdgpu/entrypoints.txt +++ b/libc/config/gpu/amdgpu/entrypoints.txt @@ -286,6 +286,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.asin libc.src.math.asinf libc.src.math.asinhf + libc.src.math.asinpif libc.src.math.atan libc.src.math.atan2 libc.src.math.atan2f diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt index 6070fb5b17b3..8765cf189f32 100644 --- a/libc/config/gpu/nvptx/entrypoints.txt +++ b/libc/config/gpu/nvptx/entrypoints.txt @@ -286,6 +286,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.asin libc.src.math.asinf libc.src.math.asinhf + libc.src.math.asinpif libc.src.math.atan libc.src.math.atan2 libc.src.math.atan2f diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 0d99a2d63d24..d27dabaff5c1 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -426,6 +426,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.asin libc.src.math.asinf libc.src.math.asinhf + libc.src.math.asinpif libc.src.math.atan2 libc.src.math.atan2f libc.src.math.atan diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index f04ac40145d3..714bd024dad1 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -256,6 +256,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.asin libc.src.math.asinf libc.src.math.asinhf + libc.src.math.asinpif libc.src.math.atan2 libc.src.math.atan2f libc.src.math.atan diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 7baf4de9d8a5..b823e1b25e6c 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -430,6 +430,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.asin libc.src.math.asinf libc.src.math.asinhf + libc.src.math.asinpif libc.src.math.atan2 libc.src.math.atan2f libc.src.math.atan diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 6485c24f5736..f1b3e90cfd03 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -472,6 +472,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.asin libc.src.math.asinf libc.src.math.asinhf + libc.src.math.asinpif libc.src.math.atan2 libc.src.math.atan2f libc.src.math.atan diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index 3a76595b258e..d88a49c9850e 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -135,7 +135,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.acoshf libc.src.math.asin libc.src.math.asinf + libc.src.math.asinpif libc.src.math.asinhf + libc.src.math.asinpif libc.src.math.atan2 libc.src.math.atan2f libc.src.math.atan diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst index 4b443e3e49dd..7ea54fb4d826 100644 --- a/libc/docs/headers/math/index.rst +++ b/libc/docs/headers/math/index.rst @@ -273,7 +273,7 @@ Higher Math Functions +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+ | asinh | |check| | | | |check| | | | 7.12.5.2 | F.10.2.2 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+ -| asinpi | | | | |check| | | | 7.12.4.9 | F.10.1.9 | +| asinpi | |check| | | | |check| | | | 7.12.4.9 | F.10.1.9 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+ | atan | |check| | 1 ULP | | |check| | | | 7.12.4.3 | F.10.1.3 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+ diff --git a/libc/shared/math.h b/libc/shared/math.h index 81f1d120fa7b..4ab336989f79 100644 --- a/libc/shared/math.h +++ b/libc/shared/math.h @@ -22,6 +22,7 @@ #include "math/asinf16.h" #include "math/asinhf.h" #include "math/asinhf16.h" +#include "math/asinpif.h" #include "math/asinpif16.h" #include "math/atan.h" #include "math/atan2.h" diff --git a/libc/shared/math/asinpif.h b/libc/shared/math/asinpif.h new file mode 100644 index 000000000000..f0baece26d2e --- /dev/null +++ b/libc/shared/math/asinpif.h @@ -0,0 +1,23 @@ +//===-- Shared asinpif header -----------------------------------*- 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_ASINPIF_H +#define LLVM_LIBC_SHARED_MATH_ASINPIF_H + +#include "shared/libc_common.h" +#include "src/__support/math/asinpif.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using math::asinpif; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_MATH_ASINPIF_H diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt index dfb35227949f..4e7abd280bc4 100644 --- a/libc/src/__support/math/CMakeLists.txt +++ b/libc/src/__support/math/CMakeLists.txt @@ -172,6 +172,21 @@ add_header_library( libc.src.__support.macros.optimization ) +add_header_library( + asinpif + HDRS + asinpif.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.except_value_utils + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.sqrt + libc.src.__support.macros.optimization +) + add_header_library( atan_utils HDRS diff --git a/libc/src/__support/math/asinpif.h b/libc/src/__support/math/asinpif.h new file mode 100644 index 000000000000..398d64b4f131 --- /dev/null +++ b/libc/src/__support/math/asinpif.h @@ -0,0 +1,152 @@ +//===-- Implementation header for asinpif -----------------------*- 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_ASINPIF_H +#define LLVM_LIBC_SRC___SUPPORT_MATH_ASINPIF_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" + +namespace LIBC_NAMESPACE_DECL { +namespace math { + +LIBC_INLINE float asinpif(float x) { +#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS + constexpr size_t N_EXCEPTS = 5; + constexpr fputil::ExceptValues ASINPIF_EXCEPTS = { + {// (inputs, RZ output, RU offset, RD offset, RN offset) + // x = 0x1.e768f6p-122, asinpif(x) = 0x1.364b7ap-123 (RZ) + {0x02F3B47B, 0x021B25BD, 1, 0, 0}, + // x = 0x1.e768f6p-24, asinpif(x) = 0x1.364b7ap-25 (RZ) + {0x33F3B47B, 0x331B25BD, 1, 0, 1}, + // x = 0x1.dddb4ep-19, asinpif(x) = 0x1.303686p-20 (RZ) + {0x366EEDA7, 0x35981B43, 1, 0, 1}, + // x = -0x1.dddb4ep-19, asinpif(x) = -0x1.303686p-20 (RZ) + {0xB66EEDA7, 0xB5981B43, 0, 1, 1}, + // x = -0x1.e768f6p-24, asinpif(x) = -0x1.364b7ap-25 (RZ) + {0xB3F3B47B, 0xB31B25BD, 0, 1, 1}}}; +#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS + + using FPBits = fputil::FPBits; + + FPBits xbits(x); + bool is_neg = xbits.is_neg(); + double x_abs = fputil::cast(xbits.abs().get_val()); + + auto signed_result = [is_neg](auto r) -> auto { return is_neg ? -r : r; }; + + if (LIBC_UNLIKELY(x_abs > 1.0)) { + if (xbits.is_nan()) { + if (xbits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + return x; + } + + 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 + auto r = ASINPIF_EXCEPTS.lookup(xbits.uintval()); + if (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*x) in the + // range [0, 0.5] extracted using Sollya. + // + // Sollya code: + // > prec = 200; + // > display = hexadecimal; + // > g = asin(x) / (pi * x); + // > P = fpminimax(g, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20|], + // > [|D...|], [0, 0.5]); + // > for i from 0 to degree(P) do coeff(P, i); + // > print("Error:", dirtyinfnorm(P - g, [1e-30; 0.25])); + // Error: 0x1.45c281e1cf9b58p-50 ~= 2^−49.652 + // + // Non-zero coefficients (even powers only): + constexpr double ASINPI_POLY_COEFFS[] = { + 0x1.45f306dc9c881p-2, // x^0 + 0x1.b2995e7b7e756p-5, // x^2 + 0x1.8723a1d12f828p-6, // x^4 + 0x1.d1a45564b9545p-7, // x^6 + 0x1.3ce4ceaa0e1e9p-7, // x^8 + 0x1.d2c305898ea13p-8, // x^10 + 0x1.692212e27a5f9p-8, // x^12 + 0x1.2b22cc744d25bp-8, // x^14 + 0x1.8427b864479ffp-9, // x^16 + 0x1.815522d7a2bf1p-8, // x^18 + -0x1.f6df98438aef4p-9, // x^20 + 0x1.4b50c2eb13708p-7 // x^22 + }; + // Evaluates P1(v2) = c1 + c2*v2 + c3*v2^2 + ... (tail of P without c0) + auto asinpi_polyeval = [&](double v2) -> double { + return fputil::polyeval( + v2, ASINPI_POLY_COEFFS[1], ASINPI_POLY_COEFFS[2], ASINPI_POLY_COEFFS[3], + ASINPI_POLY_COEFFS[4], ASINPI_POLY_COEFFS[5], ASINPI_POLY_COEFFS[6], + ASINPI_POLY_COEFFS[7], ASINPI_POLY_COEFFS[8], ASINPI_POLY_COEFFS[9], + ASINPI_POLY_COEFFS[10], ASINPI_POLY_COEFFS[11]); + }; + + // if |x| <= 0.5: + // asinpi(x) = x * (c0 + x^2 * P1(x^2)) + if (LIBC_UNLIKELY(x_abs <= 0.5)) { + double x_d = fputil::cast(x); + double v2 = x_d * x_d; + double result = x_d * fputil::multiply_add(v2, asinpi_polyeval(v2), + ASINPI_POLY_COEFFS[0]); + return fputil::cast(result); + } + + // If |x| > 0.5: + // asinpi(x) = 0.5 - 2 * sqrt(u) * P(u) + // = 0.5 - 2 * sqrt(u) * (c0 + u * P1(u)) + // = (0.5 - 2*sqrt(u)*ONE_OVER_PI_HI) + // - 2*sqrt(u) * (ONE_OVER_PI_LO + DELTA_C0 + u * P1(u)) + // + // where u = (1 - |x|) / 2, and + // ONE_OVER_PI_HI + ONE_OVER_PI_LO = 1/pi to ~106 bits + // DELTA_C0 = c0 - ONE_OVER_PI_HI + // + // ONE_OVER_PI_LO + DELTA_C0 is a single precomputed constant: + // = ONE_OVER_PI_LO + (c0 - ONE_OVER_PI_HI) + // = c0 - (ONE_OVER_PI_HI - ONE_OVER_PI_LO) + // = c0 - 1/pi (to ~106 bits) + constexpr double ONE_OVER_PI_HI = 0x1.45f306dc9c883p-2; + constexpr double ONE_OVER_PI_LO = -0x1.6b01ec5417056p-56; + // C0_MINUS_1OVERPI = c0 - 1/pi = DELTA_C0 + ONE_OVER_PI_LO + constexpr double C0_MINUS_1OVERPI = + (ASINPI_POLY_COEFFS[0] - ONE_OVER_PI_HI) + ONE_OVER_PI_LO; + + double u = fputil::multiply_add(-0.5, x_abs, 0.5); + double sqrt_u = fputil::sqrt(u); + double neg2_sqrt_u = -2.0 * sqrt_u; + + // tail = (c0 - 1/pi) + u * P1(u) + double tail = fputil::multiply_add(u, asinpi_polyeval(u), C0_MINUS_1OVERPI); + + double result_hi = fputil::multiply_add(neg2_sqrt_u, ONE_OVER_PI_HI, 0.5); + double result = fputil::multiply_add(tail, neg2_sqrt_u, result_hi); + + return fputil::cast(signed_result(result)); +} + +} // namespace math +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ASINPIF_H diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index e37e22fdb58e..7a9370fe487e 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -58,6 +58,7 @@ add_math_entrypoint_object(asinh) add_math_entrypoint_object(asinhf) add_math_entrypoint_object(asinhf16) +add_math_entrypoint_object(asinpif) add_math_entrypoint_object(asinpif16) add_math_entrypoint_object(atan) diff --git a/libc/src/math/asinpif.h b/libc/src/math/asinpif.h new file mode 100644 index 000000000000..b66bdcb16e4c --- /dev/null +++ b/libc/src/math/asinpif.h @@ -0,0 +1,20 @@ +//===-- Implementation header for asinpif -----------------------*- 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_ASINPIF_H +#define LLVM_LIBC_SRC_MATH_ASINPIF_H + +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +float asinpif(float x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_ASINPIF_H diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index ab2411a37d81..bb2c6f673f08 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -4013,6 +4013,16 @@ add_entrypoint_object( libc.src.__support.math.asinhf16 ) +add_entrypoint_object( + asinpif + SRCS + asinpif.cpp + HDRS + ../asinpif.h + DEPENDS + libc.src.__support.math.asinpif +) + add_entrypoint_object( asinpif16 SRCS diff --git a/libc/src/math/generic/asinpif.cpp b/libc/src/math/generic/asinpif.cpp new file mode 100644 index 000000000000..f302ecf4e286 --- /dev/null +++ b/libc/src/math/generic/asinpif.cpp @@ -0,0 +1,16 @@ +//===-- Single-precision asinpif(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/asinpif.h" +#include "src/__support/math/asinpif.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(float, asinpif, (float x)) { return math::asinpif(x); } + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt index 6ef13d36344d..424e4180fc93 100644 --- a/libc/test/shared/CMakeLists.txt +++ b/libc/test/shared/CMakeLists.txt @@ -19,6 +19,7 @@ add_fp_unittest( libc.src.__support.math.asinf16 libc.src.__support.math.asinhf libc.src.__support.math.asinhf16 + libc.src.__support.math.asinpif libc.src.__support.math.asinpif16 libc.src.__support.math.atan libc.src.__support.math.atan2 diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp index 25d39c22faae..2758e3749910 100644 --- a/libc/test/shared/shared_math_test.cpp +++ b/libc/test/shared/shared_math_test.cpp @@ -140,6 +140,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat) { EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::acoshf(1.0f)); EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::asinf(0.0f)); EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::asinhf(0.0f)); + EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::asinpif(0.0f)); EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::atan2f(0.0f, 0.0f)); EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::atanf(0.0f)); EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::atanhf(0.0f)); diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt index 83cf506968b9..47c05c650c70 100644 --- a/libc/test/src/math/CMakeLists.txt +++ b/libc/test/src/math/CMakeLists.txt @@ -2476,6 +2476,17 @@ add_fp_unittest( libc.src.math.asinf16 ) +add_fp_unittest( + asinpif_test + NEED_MPFR + SUITE + libc-math-unittests + SRCS + asinpif_test.cpp + DEPENDS + libc.src.math.asinpif +) + add_fp_unittest( asinpif16_test NEED_MPFR diff --git a/libc/test/src/math/asinpif_test.cpp b/libc/test/src/math/asinpif_test.cpp new file mode 100644 index 000000000000..073d11bc53f2 --- /dev/null +++ b/libc/test/src/math/asinpif_test.cpp @@ -0,0 +1,38 @@ +//===-- Unittests for asinpif (MPFR) --------------------------------------===// +// +// 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/asinpif.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" +#include "utils/MPFRWrapper/MPFRUtils.h" + +namespace mpfr = LIBC_NAMESPACE::testing::mpfr; + +using LlvmLibcAsinpifTest = LIBC_NAMESPACE::testing::FPTest; + +static constexpr mpfr::RoundingMode ROUNDING_MODES[] = { + mpfr::RoundingMode::Nearest, + mpfr::RoundingMode::Upward, + mpfr::RoundingMode::Downward, + mpfr::RoundingMode::TowardZero, +}; + +TEST_F(LlvmLibcAsinpifTest, InFloatRange) { + constexpr uint32_t COUNT = 100'000; + // Test in [-1, 1] + const uint32_t STEP = 0x3F800000 / COUNT; // step through [0, 1.0f] in bits + for (mpfr::RoundingMode rm : ROUNDING_MODES) { + for (uint32_t i = 0, v = 0; i <= COUNT; ++i, v += STEP) { + float x = FPBits(v).get_val(); + ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asinpi, x, + LIBC_NAMESPACE::asinpif(x), 0.5); + ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asinpi, -x, + LIBC_NAMESPACE::asinpif(-x), 0.5); + } + } +} diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt index 9ca4f93e6c41..877d653a2629 100644 --- a/libc/test/src/math/exhaustive/CMakeLists.txt +++ b/libc/test/src/math/exhaustive/CMakeLists.txt @@ -518,6 +518,22 @@ add_fp_unittest( -lpthread ) +add_fp_unittest( + asinpif_test + NO_RUN_POSTBUILD + NEED_MPFR + SUITE + libc_math_exhaustive_tests + SRCS + asinpif_test.cpp + DEPENDS + .exhaustive_test + libc.src.math.asinpif + libc.src.__support.FPUtil.fp_bits + LINK_LIBRARIES + -lpthread +) + add_fp_unittest( atanhf_test NO_RUN_POSTBUILD diff --git a/libc/test/src/math/exhaustive/asinpif_test.cpp b/libc/test/src/math/exhaustive/asinpif_test.cpp new file mode 100644 index 000000000000..b327e350a056 --- /dev/null +++ b/libc/test/src/math/exhaustive/asinpif_test.cpp @@ -0,0 +1,33 @@ +//===-- Exhaustive test for asinpif ---------------------------------------===// +// +// 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 "exhaustive_test.h" +#include "src/math/asinpif.h" +#include "utils/MPFRWrapper/MPFRUtils.h" + +namespace mpfr = LIBC_NAMESPACE::testing::mpfr; + +using LlvmLibcAsinfExhaustiveTest = + LlvmLibcUnaryOpExhaustiveMathTest; + +// Range: [0, Inf]; +static constexpr uint32_t POS_START = 0x0000'0000U; +static constexpr uint32_t POS_STOP = 0x7f80'0000U; + +TEST_F(LlvmLibcAsinfExhaustiveTest, PostiveRange) { + test_full_range_all_roundings(POS_START, POS_STOP); +} + +// Range: [-Inf, 0]; +static constexpr uint32_t NEG_START = 0xb000'0000U; +static constexpr uint32_t NEG_STOP = 0xff80'0000U; + +TEST_F(LlvmLibcAsinfExhaustiveTest, NegativeRange) { + test_full_range_all_roundings(NEG_START, NEG_STOP); +} diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index b58eeda67814..88028d90d2d5 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -4703,6 +4703,18 @@ add_fp_unittest( libc.src.math.asinhf16 ) +add_fp_unittest( + asinpif_test + SUITE + libc-math-smoke-tests + SRCS + asinpif_test.cpp + DEPENDS + libc.hdr.errno_macros + libc.src.math.asinpif + libc.src.__support.FPUtil.fp_bits +) + add_fp_unittest( asinpif16_test NEED_MPFR diff --git a/libc/test/src/math/smoke/asinpif_test.cpp b/libc/test/src/math/smoke/asinpif_test.cpp new file mode 100644 index 000000000000..87ea7259f630 --- /dev/null +++ b/libc/test/src/math/smoke/asinpif_test.cpp @@ -0,0 +1,44 @@ +//===-- Unittests for asinpif ---------------------------------------------===// +// +// 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/math_macros.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/math/asinpif.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +#include "hdr/stdint_proxy.h" + +using LlvmLibcAsinpifTest = LIBC_NAMESPACE::testing::FPTest; + +TEST_F(LlvmLibcAsinpifTest, SpecialNumbers) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::asinpif(sNaN), FE_INVALID); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::asinpif(aNaN)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::asinpif(0.0f)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::asinpif(-0.0f)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::asinpif(inf)); + EXPECT_MATH_ERRNO(EDOM); + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::asinpif(neg_inf)); + EXPECT_MATH_ERRNO(EDOM); + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::asinpif(2.0f)); + EXPECT_MATH_ERRNO(EDOM); + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::asinpif(-2.0f)); + EXPECT_MATH_ERRNO(EDOM); +} diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 3c85350827c6..9f10754cddd9 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -2821,6 +2821,23 @@ libc_support_library( ], ) +libc_support_library( + name = "__support_math_asinpif", + hdrs = ["src/__support/math/asinpif.h"], + deps = [ + ":__support_fputil_cast", + ":__support_fputil_except_value_utils", + ":__support_fputil_fenv_impl", + ":__support_fputil_fp_bits", + ":__support_fputil_multiply_add", + ":__support_fputil_polyeval", + ":__support_fputil_rounding_mode", + ":__support_fputil_sqrt", + ":__support_macros_config", + ":__support_macros_optimization", + ], +) + libc_support_library( name = "__support_math_atan_utils", hdrs = ["src/__support/math/atan_utils.h"], @@ -5723,6 +5740,13 @@ libc_math_function( ], ) +libc_math_function( + name = "asinpif", + additional_deps = [ + ":__support_math_asinpif", + ], +) + libc_math_function( name = "atanf", additional_deps = [":__support_math_atanf"],