diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt index ed84bdff8ce1..82910c320b48 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 43ba426b8ca0..4cf34764916f 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 79fbd1e4b0de..c4a11c6f8733 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 71881d23c7a0..0888f4b0d922 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 cad973f1ac06..046d1b409742 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 e327d9ac6f3d..a80bdeddf831 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 efc784d23e30..5fba41d40c7e 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 4311ba624e6d..103b25950372 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 a10dc0c82e36..31dcb31c67c7 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 17efa2e368ed..5782acb727ee 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 eeaccc863dbc..42176cd5bd3b 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 e594f6bbb1fd..e8080bc97c59 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 diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst index f9614c6d19d2..14152ac62435 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 08a4c994283c..13ed0ba9518a 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 000000000000..158547f22d2d --- /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/FPUtil/multiply_add.h b/libc/src/__support/FPUtil/multiply_add.h index f6c6ee0754ea..f47c6d72342e 100644 --- a/libc/src/__support/FPUtil/multiply_add.h +++ b/libc/src/__support/FPUtil/multiply_add.h @@ -23,7 +23,7 @@ namespace fputil { // which uses FMA instructions to speed up if available. template -LIBC_INLINE cpp::enable_if_t<(sizeof(T) > sizeof(void *)), T> +LIBC_INLINE constexpr cpp::enable_if_t<(sizeof(T) > sizeof(void *)), T> multiply_add(const T &x, const T &y, const T &z) { return x * y + z; } diff --git a/libc/src/__support/FPUtil/sqrt.h b/libc/src/__support/FPUtil/sqrt.h index d4ed744b4010..308de73b0dbc 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/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt index 10329830a004..6d752b06bcd8 100644 --- a/libc/src/__support/math/CMakeLists.txt +++ b/libc/src/__support/math/CMakeLists.txt @@ -321,7 +321,6 @@ add_header_library( libc.src.__support.FPUtil.sqrt libc.src.__support.macros.optimization libc.src.__support.FPUtil.bfloat16 - ) add_header_library( @@ -381,6 +380,21 @@ add_header_library( libc.src.__support.macros.optimization ) +add_header_library( + asinbf16 + HDRS + asinbf16.h + DEPENDS + .inv_trigf_utils + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.bfloat16 + libc.src.__support.FPUtil.cast + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.sqrt + libc.src.__support.macros.optimization +) + add_header_library( atanpif16 HDRS diff --git a/libc/src/__support/math/acoshf_utils.h b/libc/src/__support/math/acoshf_utils.h index 8a8e2caccc76..3d760f983524 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 new file mode 100644 index 000000000000..b291852762d7 --- /dev/null +++ b/libc/src/__support/math/asinbf16.h @@ -0,0 +1,95 @@ +//===-- 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 "inv_trigf_utils.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.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" + +namespace LIBC_NAMESPACE_DECL { +namespace math { + +LIBC_INLINE LIBC_CONSTEXPR bfloat16 asinbf16(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; + FPBits xbits(x); + + uint16_t x_u = xbits.uintval(); + uint16_t x_abs = x_u & 0x7fff; + float x_sign = (x_u >> 15) ? -1 : 1; + float xf = x; + + float xf_abs = (xf < 0 ? -xf : xf); + float x_sq = xf_abs * xf_abs; + + // Case 1: |x| <= 0.5 + if (x_abs <= 0x3F00) { // x_abs <= 0.5 + // |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(fputil::multiply_add(xf, 0x1.0p-9f, xf)); + } + return x; + } + + float xp = fputil::cast(inv_trigf_utils_internal::asin_eval(x_sq)); + float result = xf * (fputil::multiply_add(x_sq, xp, 1.0f)); + return fputil::cast(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 <= 1 + // |x| = {1} + if (LIBC_UNLIKELY(x_abs == 0x3F80)) { + return fputil::cast(x_sign * PI_2); + } + + float t = fputil::multiply_add(xf_abs, -0.5f, 0.5f); + float t_sqrt = fputil::sqrt(t); + float tp = fputil::cast(inv_trigf_utils_internal::asin_eval(t)); + float asin_sqrt_t = t_sqrt * (fputil::multiply_add(t, tp, 1.0f)); + float result = fputil::multiply_add(-2.0f, asin_sqrt_t, PI_2); + return fputil::cast(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 diff --git a/libc/src/__support/math/inv_trigf_utils.h b/libc/src/__support/math/inv_trigf_utils.h index 558d91760f8f..e30eaeb3a3f9 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/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index ebba3f04b8d5..b53817e2a172 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 000000000000..06780cb10101 --- /dev/null +++ b/libc/src/math/asinbf16.h @@ -0,0 +1,21 @@ +//===-- 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 30f33749d165..899c32216e98 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 000000000000..acaeef0c6ef5 --- /dev/null +++ b/libc/src/math/generic/asinbf16.cpp @@ -0,0 +1,18 @@ +//===-- 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. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception. +// +//===----------------------------------------------------------------------===// + +#include "src/math/asinbf16.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 c3795d366a58..8710b0513d23 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 @@ -266,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 11be8c972174..53d416de3069 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 @@ -58,4 +59,7 @@ static_assert(float128(0.0) == LIBC_NAMESPACE::shared::ceilf128(float128(0.0))); // BFloat16 Tests //===----------------------------------------------------------------------===// +static_assert(bfloat16(0.0) == LIBC_NAMESPACE::shared::asinbf16(bfloat16(0.0))); static_assert(bfloat16(0.0) == LIBC_NAMESPACE::shared::ceilbf16(bfloat16(0.0))); + +TEST(LlvmLibcSharedMathTest, ConstantEvaluation) {} diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp index 07be7e9516b6..941d5a167ee8 100644 --- a/libc/test/shared/shared_math_test.cpp +++ b/libc/test/shared/shared_math_test.cpp @@ -445,6 +445,13 @@ TEST(LlvmLibcSharedMathTest, AllFloat128) { TEST(LlvmLibcSharedMathTest, AllBFloat16) { using FPBits = LIBC_NAMESPACE::fputil::FPBits; 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)); + EXPECT_FP_EQ(bfloat16(2.0), LIBC_NAMESPACE::shared::bf16div(4.0, 2.0)); + EXPECT_FP_EQ(bfloat16(10.0), + LIBC_NAMESPACE::shared::bf16fmal(2.0L, 3.0L, 4.0L)); bfloat16 canonicalizebf16_cx = bfloat16(0.0); bfloat16 canonicalizebf16_x = bfloat16(0.0); diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt index 2fd77f964e4d..97ede9b1c9f8 100644 --- a/libc/test/src/math/CMakeLists.txt +++ b/libc/test/src/math/CMakeLists.txt @@ -2512,6 +2512,19 @@ 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 000000000000..0fef18133db2 --- /dev/null +++ b/libc/test/src/math/asinbf16_test.cpp @@ -0,0 +1,43 @@ +//===-- 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; + +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); + } +} diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index 79f2ea480637..28b85b1a25bb 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 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 000000000000..d237a194c46f --- /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 7434e0bbed3c..ecfb00d84171 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -3367,6 +3367,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_sqrt", + ":__support_macros_optimization", + ":__support_math_inv_trigf_utils", + ], +) + libc_support_library( name = "__support_math_asinf", hdrs = ["src/__support/math/asinf.h"], @@ -6563,6 +6578,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"],