diff --git a/libc/src/math/generic/acosf.cpp b/libc/src/math/generic/acosf.cpp --- a/libc/src/math/generic/acosf.cpp +++ b/libc/src/math/generic/acosf.cpp @@ -73,8 +73,13 @@ return static_cast(fputil::multiply_add(-x3, r, M_MATH_PI_2 - xd)); } - // |x| > 1, return NaNs. - if (LIBC_UNLIKELY(x_abs > 0x3f80'0000U)) { + // |x| >= 1, return 0, 2pi, or NaNs. + if (LIBC_UNLIKELY(x_abs >= 0x3f80'0000U)) { + if (x_abs == 0x3f80'0000U) + return x_sign ? /* x == -1.0f */ fputil::round_result_slightly_down( + 0x1.921fb6p+1f) + : /* x == 1.0f */ 0.0f; + if (x_abs <= 0x7f80'0000U) { fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); @@ -82,7 +87,7 @@ return x + FPBits::build_quiet_nan(0); } - // When 0.5 < |x| <= 1, we perform range reduction as follow: + // When 0.5 < |x| < 1, we perform range reduction as follow: // // Assume further that 0.5 < x <= 1, and let: // y = acos(x) @@ -100,7 +105,7 @@ // |x| <= 0.5: // acos(x) ~ 2 * sqrt(u) * P(u). // - // When -1 <= x <= -0.5, we use the identity: + // When -1 < x <= -0.5, we use the identity: // acos(x) = pi - acos(-x) // which is reduced to the postive case. diff --git a/libc/src/math/generic/acoshf.cpp b/libc/src/math/generic/acoshf.cpp --- a/libc/src/math/generic/acoshf.cpp +++ b/libc/src/math/generic/acoshf.cpp @@ -23,7 +23,9 @@ FPBits_t xbits(x); uint32_t x_u = xbits.uintval(); - if (LIBC_UNLIKELY(x < 1.0f)) { + if (LIBC_UNLIKELY(x <= 1.0f)) { + if (x == 1.0f) + return 0.0f; // x < 1. fputil::set_errno_if_required(EDOM); fputil::raise_except_if_required(FE_INVALID); diff --git a/libc/src/math/generic/atanf.cpp b/libc/src/math/generic/atanf.cpp --- a/libc/src/math/generic/atanf.cpp +++ b/libc/src/math/generic/atanf.cpp @@ -17,6 +17,11 @@ LLVM_LIBC_FUNCTION(float, atanf, (float x)) { using FPBits = typename fputil::FPBits; + + // x == 0.0 + if (LIBC_UNLIKELY(x == 0.0f)) + return x; + FPBits xbits(x); bool sign = xbits.get_sign(); xbits.set_sign(false); diff --git a/libc/test/src/math/acosf_test.cpp b/libc/test/src/math/acosf_test.cpp --- a/libc/test/src/math/acosf_test.cpp +++ b/libc/test/src/math/acosf_test.cpp @@ -26,13 +26,22 @@ TEST(LlvmLibcAcosfTest, SpecialNumbers) { libc_errno = 0; - EXPECT_FP_EQ(aNaN, __llvm_libc::acosf(aNaN)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acosf(aNaN)); EXPECT_MATH_ERRNO(0); - EXPECT_FP_EQ(aNaN, __llvm_libc::acosf(inf)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acosf(inf)); EXPECT_MATH_ERRNO(EDOM); - EXPECT_FP_EQ(aNaN, __llvm_libc::acosf(neg_inf)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acosf(neg_inf)); + EXPECT_MATH_ERRNO(EDOM); + + EXPECT_FP_EQ_ALL_ROUNDING(zero, __llvm_libc::acosf(1.0f)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acosf(2.0f)); + EXPECT_MATH_ERRNO(EDOM); + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acosf(-2.0f)); EXPECT_MATH_ERRNO(EDOM); } diff --git a/libc/test/src/math/acoshf_test.cpp b/libc/test/src/math/acoshf_test.cpp --- a/libc/test/src/math/acoshf_test.cpp +++ b/libc/test/src/math/acoshf_test.cpp @@ -26,19 +26,19 @@ TEST(LlvmLibcAcoshfTest, SpecialNumbers) { libc_errno = 0; - EXPECT_FP_EQ(aNaN, __llvm_libc::acoshf(aNaN)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acoshf(aNaN)); EXPECT_MATH_ERRNO(0); - EXPECT_FP_EQ(aNaN, __llvm_libc::acoshf(0.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acoshf(0.0f)); EXPECT_MATH_ERRNO(EDOM); - EXPECT_FP_EQ(0.0f, __llvm_libc::acoshf(1.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(0.0f, __llvm_libc::acoshf(1.0f)); EXPECT_MATH_ERRNO(0); - EXPECT_FP_EQ(inf, __llvm_libc::acoshf(inf)); + EXPECT_FP_EQ_ALL_ROUNDING(inf, __llvm_libc::acoshf(inf)); EXPECT_MATH_ERRNO(0); - EXPECT_FP_EQ(aNaN, __llvm_libc::acoshf(neg_inf)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::acoshf(neg_inf)); EXPECT_MATH_ERRNO(EDOM); } diff --git a/libc/test/src/math/asinf_test.cpp b/libc/test/src/math/asinf_test.cpp --- a/libc/test/src/math/asinf_test.cpp +++ b/libc/test/src/math/asinf_test.cpp @@ -27,19 +27,19 @@ TEST(LlvmLibcAsinfTest, SpecialNumbers) { libc_errno = 0; - EXPECT_FP_EQ(aNaN, __llvm_libc::asinf(aNaN)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::asinf(aNaN)); EXPECT_MATH_ERRNO(0); - EXPECT_FP_EQ(0.0f, __llvm_libc::asinf(0.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(0.0f, __llvm_libc::asinf(0.0f)); EXPECT_MATH_ERRNO(0); - EXPECT_FP_EQ(-0.0f, __llvm_libc::asinf(-0.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, __llvm_libc::asinf(-0.0f)); EXPECT_MATH_ERRNO(0); - EXPECT_FP_EQ(aNaN, __llvm_libc::asinf(inf)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::asinf(inf)); EXPECT_MATH_ERRNO(EDOM); - EXPECT_FP_EQ(aNaN, __llvm_libc::asinf(neg_inf)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::asinf(neg_inf)); EXPECT_MATH_ERRNO(EDOM); } diff --git a/libc/test/src/math/asinhf_test.cpp b/libc/test/src/math/asinhf_test.cpp --- a/libc/test/src/math/asinhf_test.cpp +++ b/libc/test/src/math/asinhf_test.cpp @@ -26,19 +26,19 @@ TEST(LlvmLibcAsinhfTest, SpecialNumbers) { libc_errno = 0; - EXPECT_FP_EQ(aNaN, __llvm_libc::asinhf(aNaN)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::asinhf(aNaN)); EXPECT_MATH_ERRNO(0); - EXPECT_FP_EQ(0.0f, __llvm_libc::asinhf(0.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(0.0f, __llvm_libc::asinhf(0.0f)); EXPECT_MATH_ERRNO(0); - EXPECT_FP_EQ(-0.0f, __llvm_libc::asinhf(-0.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, __llvm_libc::asinhf(-0.0f)); EXPECT_MATH_ERRNO(0); - EXPECT_FP_EQ(inf, __llvm_libc::asinhf(inf)); + EXPECT_FP_EQ_ALL_ROUNDING(inf, __llvm_libc::asinhf(inf)); EXPECT_MATH_ERRNO(0); - EXPECT_FP_EQ(neg_inf, __llvm_libc::asinhf(neg_inf)); + EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, __llvm_libc::asinhf(neg_inf)); EXPECT_MATH_ERRNO(0); } diff --git a/libc/test/src/math/atanf_test.cpp b/libc/test/src/math/atanf_test.cpp --- a/libc/test/src/math/atanf_test.cpp +++ b/libc/test/src/math/atanf_test.cpp @@ -28,17 +28,17 @@ TEST(LlvmLibcAtanfTest, SpecialNumbers) { libc_errno = 0; __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); - EXPECT_FP_EQ(aNaN, __llvm_libc::atanf(aNaN)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::atanf(aNaN)); EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); - EXPECT_FP_EQ(0.0f, __llvm_libc::atanf(0.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(0.0f, __llvm_libc::atanf(0.0f)); EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); - EXPECT_FP_EQ(-0.0f, __llvm_libc::atanf(-0.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, __llvm_libc::atanf(-0.0f)); EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); } diff --git a/libc/test/src/math/atanhf_test.cpp b/libc/test/src/math/atanhf_test.cpp --- a/libc/test/src/math/atanhf_test.cpp +++ b/libc/test/src/math/atanhf_test.cpp @@ -26,27 +26,27 @@ TEST(LlvmLibcAtanhfTest, SpecialNumbers) { libc_errno = 0; __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); - EXPECT_FP_EQ(aNaN, __llvm_libc::atanhf(aNaN)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::atanhf(aNaN)); EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); - EXPECT_FP_EQ(0.0f, __llvm_libc::atanhf(0.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(0.0f, __llvm_libc::atanhf(0.0f)); EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); - EXPECT_FP_EQ(-0.0f, __llvm_libc::atanhf(-0.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, __llvm_libc::atanhf(-0.0f)); EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); - EXPECT_FP_EQ(inf, __llvm_libc::atanhf(1.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(inf, __llvm_libc::atanhf(1.0f)); EXPECT_FP_EXCEPTION(FE_DIVBYZERO); EXPECT_MATH_ERRNO(ERANGE); __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); - EXPECT_FP_EQ(neg_inf, __llvm_libc::atanhf(-1.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, __llvm_libc::atanhf(-1.0f)); EXPECT_FP_EXCEPTION(FE_DIVBYZERO); EXPECT_MATH_ERRNO(ERANGE); @@ -54,33 +54,33 @@ bt.bits += 1; __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); - EXPECT_FP_EQ(aNaN, __llvm_libc::atanhf(bt.get_val())); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::atanhf(bt.get_val())); EXPECT_FP_EXCEPTION(FE_INVALID); EXPECT_MATH_ERRNO(EDOM); __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); bt.set_sign(true); - EXPECT_FP_EQ(aNaN, __llvm_libc::atanhf(bt.get_val())); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::atanhf(bt.get_val())); EXPECT_FP_EXCEPTION(FE_INVALID); EXPECT_MATH_ERRNO(EDOM); __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); - EXPECT_FP_EQ(aNaN, __llvm_libc::atanhf(2.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::atanhf(2.0f)); EXPECT_FP_EXCEPTION(FE_INVALID); EXPECT_MATH_ERRNO(EDOM); __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); - EXPECT_FP_EQ(aNaN, __llvm_libc::atanhf(-2.0f)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::atanhf(-2.0f)); EXPECT_FP_EXCEPTION(FE_INVALID); EXPECT_MATH_ERRNO(EDOM); __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT); - EXPECT_FP_EQ(aNaN, __llvm_libc::atanhf(inf)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::atanhf(inf)); EXPECT_FP_EXCEPTION(FE_INVALID); EXPECT_MATH_ERRNO(EDOM); bt.set_sign(true); - EXPECT_FP_EQ(aNaN, __llvm_libc::atanhf(neg_inf)); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, __llvm_libc::atanhf(neg_inf)); EXPECT_FP_EXCEPTION(FE_INVALID); EXPECT_MATH_ERRNO(EDOM); }