[libc-commits] [libc] f0d05bb - [libc][math] Fix signed zeros for acosf, acoshf, and atanf in FE_DOWNWARD mode.

Tue Ly via libc-commits libc-commits at lists.llvm.org
Thu Sep 7 08:21:49 PDT 2023


Author: Tue Ly
Date: 2023-09-07T15:21:33Z
New Revision: f0d05bb69947174c38b13f735af507c43379a553

URL: https://github.com/llvm/llvm-project/commit/f0d05bb69947174c38b13f735af507c43379a553
DIFF: https://github.com/llvm/llvm-project/commit/f0d05bb69947174c38b13f735af507c43379a553.diff

LOG: [libc][math] Fix signed zeros for acosf, acoshf, and atanf in FE_DOWNWARD mode.

Fix signed zeros for acosf, acoshf, and atanf in FE_DOWNWARD mode.

Reviewed By: sivachandra

Differential Revision: https://reviews.llvm.org/D159476

Added: 
    

Modified: 
    libc/src/math/generic/acosf.cpp
    libc/src/math/generic/acoshf.cpp
    libc/src/math/generic/atanf.cpp
    libc/test/src/math/acosf_test.cpp
    libc/test/src/math/acoshf_test.cpp
    libc/test/src/math/asinf_test.cpp
    libc/test/src/math/asinhf_test.cpp
    libc/test/src/math/atanf_test.cpp
    libc/test/src/math/atanhf_test.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/math/generic/acosf.cpp b/libc/src/math/generic/acosf.cpp
index 41152e06ff1f5d..ab13467b4a0a5f 100644
--- a/libc/src/math/generic/acosf.cpp
+++ b/libc/src/math/generic/acosf.cpp
@@ -73,8 +73,13 @@ LLVM_LIBC_FUNCTION(float, acosf, (float x)) {
     return static_cast<float>(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 @@ LLVM_LIBC_FUNCTION(float, acosf, (float x)) {
     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 @@ LLVM_LIBC_FUNCTION(float, acosf, (float x)) {
   // |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
index f8e5a90a4d056c..ce352764fbbc19 100644
--- a/libc/src/math/generic/acoshf.cpp
+++ b/libc/src/math/generic/acoshf.cpp
@@ -23,7 +23,9 @@ LLVM_LIBC_FUNCTION(float, acoshf, (float x)) {
   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
index 9b0c11996a5b2b..5037806d37a1b1 100644
--- a/libc/src/math/generic/atanf.cpp
+++ b/libc/src/math/generic/atanf.cpp
@@ -17,6 +17,11 @@ namespace __llvm_libc {
 
 LLVM_LIBC_FUNCTION(float, atanf, (float x)) {
   using FPBits = typename fputil::FPBits<float>;
+
+  // 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
index 1d4000c10eb837..63895ec3e30aef 100644
--- a/libc/test/src/math/acosf_test.cpp
+++ b/libc/test/src/math/acosf_test.cpp
@@ -26,13 +26,22 @@ DECLARE_SPECIAL_CONSTANTS(float)
 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
index 148813ce28495b..895503c6bc73cd 100644
--- a/libc/test/src/math/acoshf_test.cpp
+++ b/libc/test/src/math/acoshf_test.cpp
@@ -26,19 +26,19 @@ DECLARE_SPECIAL_CONSTANTS(float)
 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
index cd1431ae739390..cc99e5b7b6cac8 100644
--- a/libc/test/src/math/asinf_test.cpp
+++ b/libc/test/src/math/asinf_test.cpp
@@ -27,19 +27,19 @@ DECLARE_SPECIAL_CONSTANTS(float)
 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
index f7ba2eae4b7fe9..cadb9572c372e8 100644
--- a/libc/test/src/math/asinhf_test.cpp
+++ b/libc/test/src/math/asinhf_test.cpp
@@ -26,19 +26,19 @@ DECLARE_SPECIAL_CONSTANTS(float)
 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
index 208104cc26dd97..cd60b8d8a775e6 100644
--- a/libc/test/src/math/atanf_test.cpp
+++ b/libc/test/src/math/atanf_test.cpp
@@ -28,17 +28,17 @@ DECLARE_SPECIAL_CONSTANTS(float)
 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
index 7dce915714844d..021a3f177b821e 100644
--- a/libc/test/src/math/atanhf_test.cpp
+++ b/libc/test/src/math/atanhf_test.cpp
@@ -26,27 +26,27 @@ DECLARE_SPECIAL_CONSTANTS(float)
 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 @@ TEST(LlvmLibcAtanhfTest, SpecialNumbers) {
   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);
 }


        


More information about the libc-commits mailing list