[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:
parent
fb6b470cae
commit
62cfe1659e
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
23
libc/shared/math/acospif.h
Normal file
23
libc/shared/math/acospif.h
Normal 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
|
||||
@ -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
|
||||
)
|
||||
|
||||
100
libc/src/__support/math/acospif.h
Normal file
100
libc/src/__support/math/acospif.h
Normal 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
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
20
libc/src/math/acospif.h
Normal 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
|
||||
@ -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
|
||||
|
||||
16
libc/src/math/generic/acospif.cpp
Normal file
16
libc/src/math/generic/acospif.cpp
Normal 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
|
||||
@ -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
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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
|
||||
|
||||
29
libc/test/src/math/acospif_test.cpp
Normal file
29
libc/test/src/math/acospif_test.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
33
libc/test/src/math/exhaustive/acospif_test.cpp
Normal file
33
libc/test/src/math/exhaustive/acospif_test.cpp
Normal 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);
|
||||
}
|
||||
@ -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
|
||||
|
||||
51
libc/test/src/math/smoke/acospif_test.cpp
Normal file
51
libc/test/src/math/smoke/acospif_test.cpp
Normal 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);
|
||||
}
|
||||
@ -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 = [
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user