[libc][math][c23] implement C23 acospif math function (#183661)

Implementing C23 `acospi` math function for single-precision with the
header-only approach that is followed since #147386
This commit is contained in:
Mohamed Emad 2026-02-28 04:32:45 +02:00 committed by GitHub
parent fb6b470cae
commit 62cfe1659e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 429 additions and 61 deletions

View File

@ -336,6 +336,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
libc.src.math.acospif
libc.src.math.asin
libc.src.math.asinf
libc.src.math.asinhf

View File

@ -339,6 +339,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
libc.src.math.acospif
libc.src.math.asin
libc.src.math.asinf
libc.src.math.asinhf

View File

@ -338,6 +338,7 @@ set(TARGET_LIBM_ENTRYPOINTS
# math.h entrypoints
libc.src.math.acosf
libc.src.math.acoshf
libc.src.math.acospif
libc.src.math.asinf
libc.src.math.asinhf
libc.src.math.asinpif

View File

@ -153,6 +153,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
libc.src.math.acospif
libc.src.math.asin
libc.src.math.asinf
libc.src.math.asinhf

View File

@ -283,6 +283,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
libc.src.math.acospif
libc.src.math.asin
libc.src.math.asinf
libc.src.math.asinhf

View File

@ -283,6 +283,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
libc.src.math.acospif
libc.src.math.asin
libc.src.math.asinf
libc.src.math.asinhf

View File

@ -423,6 +423,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
libc.src.math.acospif
libc.src.math.asin
libc.src.math.asinf
libc.src.math.asinhf

View File

@ -253,6 +253,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
libc.src.math.acospif
libc.src.math.asin
libc.src.math.asinf
libc.src.math.asinhf

View File

@ -427,6 +427,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
libc.src.math.acospif
libc.src.math.asin
libc.src.math.asinf
libc.src.math.asinhf

View File

@ -469,6 +469,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
libc.src.math.acospif
libc.src.math.asin
libc.src.math.asinf
libc.src.math.asinhf

View File

@ -133,9 +133,9 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
libc.src.math.acospif
libc.src.math.asin
libc.src.math.asinf
libc.src.math.asinpif
libc.src.math.asinhf
libc.src.math.asinpif
libc.src.math.atan2

View File

@ -16,6 +16,7 @@
#include "math/acosf16.h"
#include "math/acoshf.h"
#include "math/acoshf16.h"
#include "math/acospif.h"
#include "math/acospif16.h"
#include "math/asin.h"
#include "math/asinf.h"

View File

@ -0,0 +1,23 @@
//===-- Shared acospif 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_ACOSPIF_H
#define LLVM_LIBC_SHARED_MATH_ACOSPIF_H
#include "shared/libc_common.h"
#include "src/__support/math/acospif.h"
namespace LIBC_NAMESPACE_DECL {
namespace shared {
using math::acospif;
} // namespace shared
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SHARED_MATH_ACOSPIF_H

View File

@ -94,6 +94,21 @@ add_header_library(
libc.src.__support.macros.optimization
)
add_header_library(
acospif
HDRS
acospif.h
DEPENDS
.inv_trigf_utils
libc.src.__support.FPUtil.fenv_implt
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.polyeval
libc.src.__support.FPUtil.cast
libc.src.__support.FPUtil.multiply_add
libc.src.__support.FPUtil.sqrt
libc.src.__support.macros.optimization
)
add_header_library(
acospif16
HDRS
@ -177,12 +192,11 @@ add_header_library(
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
.inv_trigf_utils
libc.src.__support.FPUtil.except_value_utils
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
)

View File

@ -0,0 +1,100 @@
//===-- Implementation header for acospif -----------------------*- 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_ACOSPIF_H
#define LLVM_LIBC_SRC___SUPPORT_MATH_ACOSPIF_H
#include "inv_trigf_utils.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"
namespace LIBC_NAMESPACE_DECL {
namespace math {
LIBC_INLINE float acospif(float x) {
using FPBits = fputil::FPBits<float>;
FPBits xbits(x);
bool is_neg = xbits.is_neg();
double x_abs = fputil::cast<double>(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();
}
// acospif(x) = 1/2 - asinpif(x)
//
// if |x| <= 0.5:
// acospif(x) = 0.5 - x * (c0 + x^2 * P1(x^2))
if (LIBC_UNLIKELY(x_abs <= 0.5)) {
double x_d = fputil::cast<double>(x);
double v2 = x_d * x_d;
double result = x_d * fputil::multiply_add(
v2, inv_trigf_utils_internal::asinpi_eval(v2),
inv_trigf_utils_internal::ASINPI_COEFFS[0]);
return fputil::cast<float>(0.5 - result);
}
// If |x| > 0.5, we use the identity:
// asinpif(x) = sign(x) * (0.5 - 2 * sqrt(u) * P(u))
// where u = (1 - |x|) / 2, P(u) ~ asin(sqrt(u)) / (pi * sqrt(u))
//
// Then:
// acospif(x) = 0.5 - asinpif(x)
//
// For x > 0.5:
// acospif(x) = 0.5 - (0.5 - 2*sqrt(u)*P(u)) = 2*sqrt(u)*P(u)
//
// For x < -0.5:
// acospif(x) = 0.5 - (-(0.5 - 2*sqrt(u)*P(u))) = 1 - 2*sqrt(u)*P(u)
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 =
(inv_trigf_utils_internal::ASINPI_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<double>(u);
double neg2_sqrt_u = -2.0 * sqrt_u;
// tail = (c0 - 1/pi) + u * P1(u)
double tail = fputil::multiply_add(
u, inv_trigf_utils_internal::asinpi_eval(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);
// For x > 0.5: acospif(x) = 2*sqrt(u)*P(u)
// For x < -0.5: acospif(x) = 1 - 2*sqrt(u)*P(u)
return fputil::cast<float>(0.5 - signed_result(result));
}
} // namespace math
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_MATH_ACOSPIF_H

View File

@ -9,6 +9,7 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_ASINPIF_H
#define LLVM_LIBC_SRC___SUPPORT_MATH_ASINPIF_H
#include "inv_trigf_utils.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/PolyEval.h"
@ -66,50 +67,14 @@ LIBC_INLINE float asinpif(float x) {
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<double>(x);
double v2 = x_d * x_d;
double result = x_d * fputil::multiply_add(v2, asinpi_polyeval(v2),
ASINPI_POLY_COEFFS[0]);
double result = x_d * fputil::multiply_add(
v2, inv_trigf_utils_internal::asinpi_eval(v2),
inv_trigf_utils_internal::ASINPI_COEFFS[0]);
return fputil::cast<float>(result);
}
@ -131,14 +96,16 @@ LIBC_INLINE float asinpif(float x) {
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;
(inv_trigf_utils_internal::ASINPI_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<double>(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 tail = fputil::multiply_add(
u, inv_trigf_utils_internal::asinpi_eval(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);

View File

@ -177,6 +177,43 @@ LIBC_INLINE double asin_eval(double xsq) {
return fputil::multiply_add(xsq, r2, r1);
}
// 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):
LIBC_INLINE_VAR constexpr double ASINPI_COEFFS[13] = {
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)
LIBC_INLINE double asinpi_eval(double v2) {
return fputil::polyeval(
v2, ASINPI_COEFFS[1], ASINPI_COEFFS[2], ASINPI_COEFFS[3],
ASINPI_COEFFS[4], ASINPI_COEFFS[5], ASINPI_COEFFS[6], ASINPI_COEFFS[7],
ASINPI_COEFFS[8], ASINPI_COEFFS[9], ASINPI_COEFFS[10], ASINPI_COEFFS[11]);
}
} // namespace inv_trigf_utils_internal
} // namespace LIBC_NAMESPACE_DECL

View File

@ -48,6 +48,7 @@ add_math_entrypoint_object(acosh)
add_math_entrypoint_object(acoshf)
add_math_entrypoint_object(acoshf16)
add_math_entrypoint_object(acospif)
add_math_entrypoint_object(acospif16)
add_math_entrypoint_object(asin)

20
libc/src/math/acospif.h Normal file
View File

@ -0,0 +1,20 @@
//===-- Implementation header for acospif -----------------------*- 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_ACOSPIF_H
#define LLVM_LIBC_SRC_MATH_ACOSPIF_H
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
float acospif(float x);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_MATH_ACOSPIF_H

View File

@ -3963,6 +3963,16 @@ add_entrypoint_object(
libc.src.errno.errno
)
add_entrypoint_object(
acospif
SRCS
acospif.cpp
HDRS
../acospif.h
DEPENDS
libc.src.__support.math.acospif
)
add_entrypoint_object(
asinhf
SRCS

View File

@ -0,0 +1,16 @@
//===-- Single-precision acospif(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/acospif.h"
#include "src/__support/math/acospif.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(float, acospif, (float x)) { return math::acospif(x); }
} // namespace LIBC_NAMESPACE_DECL

View File

@ -13,6 +13,7 @@ add_fp_unittest(
libc.src.__support.math.acosf16
libc.src.__support.math.acoshf
libc.src.__support.math.acoshf16
libc.src.__support.math.acospif
libc.src.__support.math.acospif16
libc.src.__support.math.asin
libc.src.__support.math.asinf

View File

@ -148,6 +148,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat) {
EXPECT_FP_EQ(0x1.921fb6p+0, LIBC_NAMESPACE::shared::acosf(0.0f));
EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::acoshf(1.0f));
EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::acospif(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));

View File

@ -2533,6 +2533,17 @@ add_fp_unittest(
libc.src.math.acosf16
)
add_fp_unittest(
acospif_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
acospif_test.cpp
DEPENDS
libc.src.math.acospif
)
add_fp_unittest(
acospif16_test
NEED_MPFR

View File

@ -0,0 +1,29 @@
//===-- Unittests for acospif (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/acospif.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include "utils/MPFRWrapper/MPFRUtils.h"
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
using LlvmLibcAcospifTest = LIBC_NAMESPACE::testing::FPTest<float>;
TEST_F(LlvmLibcAcospifTest, 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 (uint32_t i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
float x = FPBits(v).get_val();
ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Acospi, x,
LIBC_NAMESPACE::acospif(x), 0.5);
ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Acospi, -x,
LIBC_NAMESPACE::acospif(-x), 0.5);
}
}

View File

@ -15,24 +15,15 @@ namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
using LlvmLibcAsinpifTest = LIBC_NAMESPACE::testing::FPTest<float>;
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);
}
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);
}
}

View File

@ -502,6 +502,22 @@ add_fp_unittest(
-lpthread
)
add_fp_unittest(
acospif_test
NO_RUN_POSTBUILD
NEED_MPFR
SUITE
libc_math_exhaustive_tests
SRCS
acospif_test.cpp
DEPENDS
.exhaustive_test
libc.src.math.acospif
libc.src.__support.FPUtil.fp_bits
LINK_LIBRARIES
-lpthread
)
add_fp_unittest(
asinhf_test
NO_RUN_POSTBUILD

View File

@ -0,0 +1,33 @@
//===-- Exhaustive test for acospif ---------------------------------------===//
//
// 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/acospif.h"
#include "utils/MPFRWrapper/MPFRUtils.h"
namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
using LlvmLibcAsinfExhaustiveTest =
LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Acospi,
LIBC_NAMESPACE::acospif>;
// 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);
}

View File

@ -4819,6 +4819,18 @@ add_fp_unittest(
libc.src.math.acosf16
)
add_fp_unittest(
acospif_test
SUITE
libc-math-smoke-tests
SRCS
acospif_test.cpp
DEPENDS
libc.hdr.errno_macros
libc.src.math.acospif
libc.src.__support.FPUtil.fp_bits
)
add_fp_unittest(
acospif16_test
SUITE

View File

@ -0,0 +1,51 @@
//===-- Unittests for acospif ---------------------------------------------===//
//
// 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/acospif.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include "hdr/stdint_proxy.h"
using LlvmLibcAcospifTest = LIBC_NAMESPACE::testing::FPTest<float>;
TEST_F(LlvmLibcAcospifTest, SpecialNumbers) {
EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::acospif(sNaN), FE_INVALID);
EXPECT_MATH_ERRNO(0);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::acospif(aNaN));
EXPECT_MATH_ERRNO(0);
// acospif(0) = 0.5
EXPECT_FP_EQ(0.5f, LIBC_NAMESPACE::acospif(0.0f));
EXPECT_MATH_ERRNO(0);
// acospif(-0) = 0.5
EXPECT_FP_EQ(0.5f, LIBC_NAMESPACE::acospif(-0.0f));
EXPECT_MATH_ERRNO(0);
// acospif(1) = 0
EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::acospif(1.0f));
EXPECT_MATH_ERRNO(0);
// acospif(-1) = 1
EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::acospif(-1.0f));
EXPECT_MATH_ERRNO(0);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::acospif(inf));
EXPECT_MATH_ERRNO(EDOM);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::acospif(neg_inf));
EXPECT_MATH_ERRNO(EDOM);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::acospif(2.0f));
EXPECT_MATH_ERRNO(EDOM);
EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::acospif(-2.0f));
EXPECT_MATH_ERRNO(EDOM);
}

View File

@ -2597,6 +2597,22 @@ libc_support_library(
],
)
libc_support_library(
name = "__support_math_acospif",
hdrs = ["src/__support/math/acospif.h"],
deps = [
":__support_fputil_cast",
":__support_fputil_fenv_impl",
":__support_fputil_fp_bits",
":__support_fputil_multiply_add",
":__support_fputil_polyeval",
":__support_fputil_sqrt",
":__support_macros_config",
":__support_macros_optimization",
":__support_math_inv_trigf_utils",
],
)
libc_support_library(
name = "__support_math_acospif16",
hdrs = ["src/__support/math/acospif16.h"],
@ -2847,6 +2863,7 @@ libc_support_library(
":__support_fputil_sqrt",
":__support_macros_config",
":__support_macros_optimization",
":__support_math_inv_trigf_utils",
],
)
@ -5878,6 +5895,13 @@ libc_math_function(
],
)
libc_math_function(
name = "acospif",
additional_deps = [
":__support_math_acospif",
],
)
libc_math_function(
name = "acospif16",
additional_deps = [