Skip to content

[libc][NFC] Simplify logic in sqrt #80426

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 2, 2024
Merged

Conversation

gchatelet
Copy link
Contributor

No description provided.

@gchatelet gchatelet requested a review from lntue February 2, 2024 12:43
@llvmbot llvmbot added the libc label Feb 2, 2024
@llvmbot
Copy link
Member

llvmbot commented Feb 2, 2024

@llvm/pr-subscribers-libc

Author: Guillaume Chatelet (gchatelet)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/80426.diff

2 Files Affected:

  • (modified) libc/src/__support/FPUtil/generic/sqrt.h (+5-11)
  • (modified) libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h (+5-11)
diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index 702de3f04a9bf..15ac1d3545e95 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -78,20 +78,14 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
 
     FPBits_t bits(x);
 
-    if (bits.is_inf_or_nan()) {
-      if (bits.is_neg() && (bits.get_mantissa() == 0)) {
-        // sqrt(-Inf) = NaN
-        return FLT_NAN;
-      } else {
-        // sqrt(NaN) = NaN
-        // sqrt(+Inf) = +Inf
-        return x;
-      }
-    } else if (bits.is_zero()) {
+    if (bits == FPBits_t::inf(Sign::POS) || bits.is_zero()) {
+      // sqrt(+Inf) = +Inf
       // sqrt(+0) = +0
       // sqrt(-0) = -0
       return x;
-    } else if (bits.is_neg()) {
+    } else if (bits.is_inf_or_nan() || bits.is_neg()) {
+      // sqrt(-Inf) = NaN
+      // sqrt(NaN) = NaN
       // sqrt( negative numbers ) = NaN
       return FLT_NAN;
     } else {
diff --git a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
index 74a536c04817c..2146019011986 100644
--- a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
+++ b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
@@ -43,20 +43,14 @@ LIBC_INLINE long double sqrt(long double x) {
 
   LDBits bits(x);
 
-  if (bits.is_inf_or_nan()) {
-    if (bits.is_neg() && (bits.get_mantissa() == 0)) {
-      // sqrt(-Inf) = NaN
-      return LDNAN;
-    } else {
-      // sqrt(NaN) = NaN
-      // sqrt(+Inf) = +Inf
-      return x;
-    }
-  } else if (bits.is_zero()) {
+  if (bits == LDBits::inf(Sign::POS) || bits.is_zero()) {
+    // sqrt(+Inf) = +Inf
     // sqrt(+0) = +0
     // sqrt(-0) = -0
     return x;
-  } else if (bits.is_neg()) {
+  } else if (bits.is_inf_or_nan() || bits.is_neg()) {
+    // sqrt(-Inf) = NaN
+    // sqrt(NaN) = NaN
     // sqrt( negative numbers ) = NaN
     return LDNAN;
   } else {

// sqrt(+0) = +0
// sqrt(-0) = -0
return x;
} else if (bits.is_neg()) {
} else if (bits.is_inf_or_nan() || bits.is_neg()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will change the NaN payload when x is NaN. When x is NaN we should return it as-is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this required by the standard?
It is not explicit from the cppreference article.

Copy link
Contributor Author

@gchatelet gchatelet Feb 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The C standard (ISO/IEC 9899:201x) says
5.2.4.2.2
A quiet NaN propagates through almost every arithmetic operation without raising a floating-point exception; a signaling NaN generally raises a floating-point exception when occurring as an arithmetic operand.

I'm still unclear about the exact semantics as it doesn't tell whether it should be the exact same NaN or just NaN read as "the floating point class of NaN values".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyways, I think returning the same NaN makes more sense so I've changed the code accordingly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, returning NaN as-is helps with the signaling / quiet NaN semantic, and also it follows the IEEE 754's recommendation:

To facilitate propagation of diagnostic information contained in NaNs,
as much of that information as possible should be preserved in NaN 
results of operations.

@gchatelet gchatelet merged commit b629414 into llvm:main Feb 2, 2024
@gchatelet gchatelet deleted the simplify_sqrt branch February 2, 2024 16:21
agozillon pushed a commit to agozillon/llvm-project that referenced this pull request Feb 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants