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

Co-authored-by: bassiounix <muhammad.m.bassiouni@gmail.com>
This commit is contained in:
Zorojuro 2026-03-31 00:59:55 +05:30 committed by GitHub
parent f10dccd458
commit 15a7c45163
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 355 additions and 8 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+

View File

@ -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"

View File

@ -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

View File

@ -23,7 +23,7 @@ namespace fputil {
// which uses FMA instructions to speed up if available.
template <typename T>
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;
}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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<bfloat16>;
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<bfloat16>(fputil::multiply_add(xf, 0x1.0p-9f, xf));
}
return x;
}
float xp = fputil::cast<float>(inv_trigf_utils_internal::asin_eval(x_sq));
float result = xf * (fputil::multiply_add<float>(x_sq, xp, 1.0f));
return fputil::cast<bfloat16>(result);
}
// Case 2: 0.5 <|x| <= 1
// using reduction: asin(x) = pi/2 - 2*asin(sqrt((1-x)/2))
if (x_abs <= 0x3F80) { // x_abs <= 1
// |x| = {1}
if (LIBC_UNLIKELY(x_abs == 0x3F80)) {
return fputil::cast<bfloat16>(x_sign * PI_2);
}
float t = fputil::multiply_add<float>(xf_abs, -0.5f, 0.5f);
float t_sqrt = fputil::sqrt<float>(t);
float tp = fputil::cast<float>(inv_trigf_utils_internal::asin_eval(t));
float asin_sqrt_t = t_sqrt * (fputil::multiply_add<float>(t, tp, 1.0f));
float result = fputil::multiply_add<float>(-2.0f, asin_sqrt_t, PI_2);
return fputil::cast<bfloat16>(x_sign * result);
}
// 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

View File

@ -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]);

View File

@ -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)

21
libc/src/math/asinbf16.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
)

View File

@ -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) {}

View File

@ -445,6 +445,13 @@ TEST(LlvmLibcSharedMathTest, AllFloat128) {
TEST(LlvmLibcSharedMathTest, AllBFloat16) {
using FPBits = LIBC_NAMESPACE::fputil::FPBits<bfloat16>;
EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::atanbf16(bfloat16(0.0)));
EXPECT_FP_EQ(bfloat16(0.0), LIBC_NAMESPACE::shared::asinbf16(bfloat16(0.0)));
EXPECT_FP_EQ(bfloat16(5.0), LIBC_NAMESPACE::shared::bf16add(2.0, 3.0));
EXPECT_FP_EQ(bfloat16(2.0f), LIBC_NAMESPACE::shared::bf16divf(4.0f, 2.0f));
EXPECT_FP_EQ(bfloat16(2.0), LIBC_NAMESPACE::shared::bf16divl(6.0L, 3.0L));
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);

View File

@ -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

View File

@ -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<bfloat16>;
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
// Range: [0, Inf]
static constexpr uint16_t POS_START = 0x0000U;
static constexpr uint16_t POS_STOP = 0x7f80U;
// Range: [-Inf, 0]
static constexpr uint16_t NEG_START = 0x8000U;
static constexpr uint16_t NEG_STOP = 0xff80U;
TEST_F(LlvmLibcAsinBf16Test, PositiveRange) {
for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
bfloat16 x = FPBits(v).get_val();
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
LIBC_NAMESPACE::asinbf16(x), 0.5);
}
}
TEST_F(LlvmLibcAsinBf16Test, NegativeRange) {
for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
bfloat16 x = FPBits(v).get_val();
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Asin, x,
LIBC_NAMESPACE::asinbf16(x), 0.5);
}
}

View File

@ -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

View File

@ -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(); }

View File

@ -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"],