| |
| |
| |
| |
| |
| |
| |
|
|
| #include "src/math/asinf.h" |
| #include "src/__support/FPUtil/FEnvImpl.h" |
| #include "src/__support/FPUtil/FPBits.h" |
| #include "src/__support/FPUtil/PolyEval.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/config.h" |
| #include "src/__support/macros/optimization.h" |
| #include "src/__support/macros/properties/cpu_features.h" |
|
|
| #include "inv_trigf_utils.h" |
|
|
| namespace LIBC_NAMESPACE_DECL { |
|
|
| #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS |
| static constexpr size_t N_EXCEPTS = 2; |
|
|
| |
| static constexpr fputil::ExceptValues<float, N_EXCEPTS> ASINF_EXCEPTS_LO = {{ |
| |
| |
| {0x3d09bf86, 0x3d09c62c, 1, 0, 1}, |
| |
| {0x3de5fa1e, 0x3de6768e, 1, 0, 0}, |
| }}; |
|
|
| |
| static constexpr fputil::ExceptValues<float, N_EXCEPTS> ASINF_EXCEPTS_HI = {{ |
| |
| |
| {0x3f083a1a, 0x3f0fa5b2, 1, 0, 0}, |
| |
| {0x3f7741b6, 0x3fa7832a, 1, 0, 0}, |
| }}; |
| #endif |
|
|
| LLVM_LIBC_FUNCTION(float, asinf, (float x)) { |
| using FPBits = typename fputil::FPBits<float>; |
|
|
| FPBits xbits(x); |
| uint32_t x_uint = xbits.uintval(); |
| uint32_t x_abs = xbits.uintval() & 0x7fff'ffffU; |
| constexpr double SIGN[2] = {1.0, -1.0}; |
| uint32_t x_sign = x_uint >> 31; |
|
|
| |
| if (x_abs < 0x3f04'471dU) { |
| |
| if (LIBC_UNLIKELY(x_abs < 0x39e8'9768U)) { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #if defined(LIBC_TARGET_CPU_HAS_FMA_FLOAT) |
| return fputil::multiply_add(x, 0x1.0p-25f, x); |
| #else |
| double xd = static_cast<double>(x); |
| return static_cast<float>(fputil::multiply_add(xd, 0x1.0p-25, xd)); |
| #endif |
| } |
|
|
| #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS |
| |
| if (auto r = ASINF_EXCEPTS_LO.lookup_odd(x_abs, x_sign); |
| LIBC_UNLIKELY(r.has_value())) |
| return r.value(); |
| #endif |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| double xd = static_cast<double>(x); |
| double xsq = xd * xd; |
| double x3 = xd * xsq; |
| double r = asin_eval(xsq); |
| return static_cast<float>(fputil::multiply_add(x3, r, xd)); |
| } |
|
|
| |
| if (LIBC_UNLIKELY(x_abs > 0x3f80'0000U)) { |
| if (xbits.is_signaling_nan()) { |
| fputil::raise_except_if_required(FE_INVALID); |
| return FPBits::quiet_nan().get_val(); |
| } |
|
|
| if (x_abs <= 0x7f80'0000U) { |
| fputil::set_errno_if_required(EDOM); |
| fputil::raise_except_if_required(FE_INVALID); |
| } |
|
|
| return FPBits::quiet_nan().get_val(); |
| } |
|
|
| #ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS |
| |
| if (auto r = ASINF_EXCEPTS_HI.lookup_odd(x_abs, x_sign); |
| LIBC_UNLIKELY(r.has_value())) |
| return r.value(); |
| #endif |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| xbits.set_sign(Sign::POS); |
| double sign = SIGN[x_sign]; |
| double xd = static_cast<double>(xbits.get_val()); |
| double u = fputil::multiply_add(-0.5, xd, 0.5); |
| double c1 = sign * (-2 * fputil::sqrt<double>(u)); |
| double c2 = fputil::multiply_add(sign, M_MATH_PI_2, c1); |
| double c3 = c1 * u; |
|
|
| double r = asin_eval(u); |
| return static_cast<float>(fputil::multiply_add(c3, r, c2)); |
| } |
|
|
| } |
|
|