[libc-commits] [libc] dbed678 - [libc] Fix bugs with negative and mixed normal/denormal inputs in hypot implementation.

Tue Ly via libc-commits libc-commits at lists.llvm.org
Fri Dec 3 07:14:44 PST 2021


Author: Tue Ly
Date: 2021-12-03T10:14:04-05:00
New Revision: dbed678f4be29107d9848c3716f54bca3ec266bc

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

LOG: [libc] Fix bugs with negative and mixed normal/denormal inputs in hypot implementation.

Fix a bug with negative and mixed normal/denormal inputs in hypot implementation.

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

Added: 
    

Modified: 
    libc/src/__support/FPUtil/Hypot.h
    libc/test/src/math/HypotTest.h

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h
index 448dc1c36ea6d..aa8b720e9f40d 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -150,7 +150,7 @@ static inline T hypot(T x, T y) {
     return abs(y);
   }
 
-  if (x >= y) {
+  if (abs(x) >= abs(y)) {
     a_exp = x_bits.getUnbiasedExponent();
     a_mant = x_bits.getMantissa();
     b_exp = y_bits.getUnbiasedExponent();
@@ -178,10 +178,13 @@ static inline T hypot(T x, T y) {
     y_mant_width = MantissaWidth<T>::value + 1;
   } else {
     leading_one = internal::findLeadingOne(a_mant, y_mant_width);
+    a_exp = 1;
   }
 
   if (b_exp != 0) {
     b_mant |= one;
+  } else {
+    b_exp = 1;
   }
 
   a_mant_sq = static_cast<DUIntType>(a_mant) * a_mant;

diff  --git a/libc/test/src/math/HypotTest.h b/libc/test/src/math/HypotTest.h
index 11adc2f5191aa..86326db75cbc8 100644
--- a/libc/test/src/math/HypotTest.h
+++ b/libc/test/src/math/HypotTest.h
@@ -47,28 +47,47 @@ class HypotTestTemplate : public __llvm_libc::testing::Test {
 
   void testSubnormalRange(Func func) {
     constexpr UIntType count = 1000001;
-    constexpr UIntType step =
-        (FPBits::maxSubnormal - FPBits::minSubnormal) / count;
-    for (UIntType v = FPBits::minSubnormal, w = FPBits::maxSubnormal;
-         v <= FPBits::maxSubnormal && w >= FPBits::minSubnormal;
-         v += step, w -= step) {
-      T x = T(FPBits(v)), y = T(FPBits(w));
-      T result = func(x, y);
-      mpfr::BinaryInput<T> input{x, y};
-      ASSERT_MPFR_MATCH(mpfr::Operation::Hypot, input, result, 0.5);
+    for (unsigned scale = 0; scale < 4; ++scale) {
+      UIntType maxValue = FPBits::maxSubnormal << scale;
+      UIntType step = (maxValue - FPBits::minSubnormal) / count;
+      for (int signs = 0; signs < 4; ++signs) {
+        for (UIntType v = FPBits::minSubnormal, w = maxValue;
+             v <= maxValue && w >= FPBits::minSubnormal; v += step, w -= step) {
+          T x = T(FPBits(v)), y = T(FPBits(w));
+          if (signs % 2 == 1) {
+            x = -x;
+          }
+          if (signs >= 2) {
+            y = -y;
+          }
+
+          T result = func(x, y);
+          mpfr::BinaryInput<T> input{x, y};
+          ASSERT_MPFR_MATCH(mpfr::Operation::Hypot, input, result, 0.5);
+        }
+      }
     }
   }
 
   void testNormalRange(Func func) {
     constexpr UIntType count = 1000001;
     constexpr UIntType step = (FPBits::maxNormal - FPBits::minNormal) / count;
-    for (UIntType v = FPBits::minNormal, w = FPBits::maxNormal;
-         v <= FPBits::maxNormal && w >= FPBits::minNormal;
-         v += step, w -= step) {
-      T x = T(FPBits(v)), y = T(FPBits(w));
-      T result = func(x, y);
-      mpfr::BinaryInput<T> input{x, y};
-      ASSERT_MPFR_MATCH(mpfr::Operation::Hypot, input, result, 0.5);
+    for (int signs = 0; signs < 4; ++signs) {
+      for (UIntType v = FPBits::minNormal, w = FPBits::maxNormal;
+           v <= FPBits::maxNormal && w >= FPBits::minNormal;
+           v += step, w -= step) {
+        T x = T(FPBits(v)), y = T(FPBits(w));
+        if (signs % 2 == 1) {
+          x = -x;
+        }
+        if (signs >= 2) {
+          y = -y;
+        }
+
+        T result = func(x, y);
+        mpfr::BinaryInput<T> input{x, y};
+        ASSERT_MPFR_MATCH(mpfr::Operation::Hypot, input, result, 0.5);
+      }
     }
   }
 };


        


More information about the libc-commits mailing list