| |
| |
| |
| |
| |
| |
| |
|
|
| #include "src/math/atan2f128.h" |
| #include "atan_utils.h" |
| #include "src/__support/FPUtil/FPBits.h" |
| #include "src/__support/FPUtil/dyadic_float.h" |
| #include "src/__support/FPUtil/multiply_add.h" |
| #include "src/__support/FPUtil/nearest_integer.h" |
| #include "src/__support/integer_literals.h" |
| #include "src/__support/macros/config.h" |
| #include "src/__support/macros/optimization.h" |
| #include "src/__support/macros/properties/types.h" |
| #include "src/__support/uint128.h" |
|
|
| namespace LIBC_NAMESPACE_DECL { |
|
|
| namespace { |
|
|
| using Float128 = fputil::DyadicFloat<128>; |
|
|
| static constexpr Float128 ZERO = {Sign::POS, 0, 0_u128}; |
| static constexpr Float128 MZERO = {Sign::NEG, 0, 0_u128}; |
| static constexpr Float128 PI = {Sign::POS, -126, |
| 0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128}; |
| static constexpr Float128 MPI = {Sign::NEG, -126, |
| 0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128}; |
| static constexpr Float128 PI_OVER_2 = { |
| Sign::POS, -127, 0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128}; |
| static constexpr Float128 MPI_OVER_2 = { |
| Sign::NEG, -127, 0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128}; |
| static constexpr Float128 PI_OVER_4 = { |
| Sign::POS, -128, 0xc90fdaa2'2168c234'c4c6628b'80dc1cd1_u128}; |
| static constexpr Float128 THREE_PI_OVER_4 = { |
| Sign::POS, -128, 0x96cbe3f9'990e91a7'9394c9e8'a0a5159d_u128}; |
|
|
| |
| |
| static constexpr Float128 CONST_ADJ[2][2][2] = { |
| {{ZERO, MPI_OVER_2}, {MZERO, MPI_OVER_2}}, |
| {{MPI, PI_OVER_2}, {MPI, PI_OVER_2}}}; |
|
|
| } |
|
|
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| LLVM_LIBC_FUNCTION(float128, atan2f128, (float128 y, float128 x)) { |
| using FPBits = fputil::FPBits<float128>; |
| using Float128 = fputil::DyadicFloat<128>; |
|
|
| FPBits x_bits(x), y_bits(y); |
| bool x_sign = x_bits.sign().is_neg(); |
| bool y_sign = y_bits.sign().is_neg(); |
| x_bits = x_bits.abs(); |
| y_bits = y_bits.abs(); |
| UInt128 x_abs = x_bits.uintval(); |
| UInt128 y_abs = y_bits.uintval(); |
| bool recip = x_abs < y_abs; |
| UInt128 min_abs = recip ? x_abs : y_abs; |
| UInt128 max_abs = !recip ? x_abs : y_abs; |
| unsigned min_exp = static_cast<unsigned>(min_abs >> FPBits::FRACTION_LEN); |
| unsigned max_exp = static_cast<unsigned>(max_abs >> FPBits::FRACTION_LEN); |
|
|
| Float128 num(FPBits(min_abs).get_val()); |
| Float128 den(FPBits(max_abs).get_val()); |
|
|
| |
| |
| if (LIBC_UNLIKELY(max_exp >= 0x7fffU || min_exp == 0U)) { |
| if (x_bits.is_nan() || y_bits.is_nan()) |
| return FPBits::quiet_nan().get_val(); |
| unsigned x_except = x == 0 ? 0 : (FPBits(x_abs).is_inf() ? 2 : 1); |
| unsigned y_except = y == 0 ? 0 : (FPBits(y_abs).is_inf() ? 2 : 1); |
|
|
| |
| |
| |
| |
| |
| |
| constexpr Float128 EXCEPTS[3][3][2] = { |
| {{ZERO, PI}, {ZERO, PI}, {ZERO, PI}}, |
| {{PI_OVER_2, PI_OVER_2}, {ZERO, ZERO}, {ZERO, PI}}, |
| {{PI_OVER_2, PI_OVER_2}, |
| {PI_OVER_2, PI_OVER_2}, |
| {PI_OVER_4, THREE_PI_OVER_4}}, |
| }; |
|
|
| if ((x_except != 1) || (y_except != 1)) { |
| Float128 r = EXCEPTS[y_except][x_except][x_sign]; |
| if (y_sign) |
| r.sign = r.sign.negate(); |
| return static_cast<float128>(r); |
| } |
| } |
|
|
| bool final_sign = ((x_sign != y_sign) != recip); |
| Float128 const_term = CONST_ADJ[x_sign][y_sign][recip]; |
| int exp_diff = den.exponent - num.exponent; |
| |
| |
| if (LIBC_UNLIKELY(exp_diff > FPBits::FRACTION_LEN + 2)) { |
| if (final_sign) |
| const_term.sign = const_term.sign.negate(); |
| return static_cast<float128>(const_term); |
| } |
|
|
| |
| |
| |
| float num_f = |
| cpp::bit_cast<float>(static_cast<uint32_t>(num.mantissa >> 104) + |
| (6U << fputil::FPBits<float>::FRACTION_LEN)); |
| float den_f = cpp::bit_cast<float>( |
| static_cast<uint32_t>(den.mantissa >> 104) + |
| (static_cast<uint32_t>(exp_diff) << fputil::FPBits<float>::FRACTION_LEN)); |
|
|
| float k = fputil::nearest_integer(num_f / den_f); |
| unsigned idx = static_cast<unsigned>(k); |
|
|
| |
| Float128 k_f128(Sign::POS, -6, Float128::MantissaType(idx)); |
|
|
| |
| |
| |
| |
| Float128 num_f128 = fputil::multiply_add(den, -k_f128, num); |
| |
| Float128 den_f128 = fputil::multiply_add(num, k_f128, den); |
|
|
| |
| Float128 q = fputil::quick_mul(num_f128, fputil::approx_reciprocal(den_f128)); |
| |
| Float128 p = atan_eval(q); |
|
|
| Float128 r = |
| fputil::quick_add(const_term, fputil::quick_add(ATAN_I_F128[idx], p)); |
| if (final_sign) |
| r.sign = r.sign.negate(); |
|
|
| return static_cast<float128>(r); |
| } |
|
|
| } |
|
|