[libc-commits] [PATCH] D133370: [libc] Return correct values for hypot when overflowed.

Tue Ly via Phabricator via libc-commits libc-commits at lists.llvm.org
Tue Sep 6 11:44:10 PDT 2022


lntue created this revision.
lntue added reviewers: sivachandra, zimmermann6.
Herald added subscribers: ecnelises, tschuett.
Herald added projects: libc-project, All.
lntue requested review of this revision.

Hypot incorrectly returns +Inf when overflowed with FE_DOWNWARD and
FE_TOWARDZERO rounding modes.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D133370

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


Index: libc/test/src/math/HypotTest.h
===================================================================
--- libc/test/src/math/HypotTest.h
+++ libc/test/src/math/HypotTest.h
@@ -24,24 +24,38 @@
   using Func = T (*)(T, T);
   using FPBits = __llvm_libc::fputil::FPBits<T>;
   using UIntType = typename FPBits::UIntType;
-  const T nan = T(__llvm_libc::fputil::FPBits<T>::build_nan(1));
-  const T inf = T(__llvm_libc::fputil::FPBits<T>::inf());
-  const T neg_inf = T(__llvm_libc::fputil::FPBits<T>::neg_inf());
-  const T zero = T(__llvm_libc::fputil::FPBits<T>::zero());
-  const T neg_zero = T(__llvm_libc::fputil::FPBits<T>::neg_zero());
+  const T nan = T(FPBits::build_nan(1));
+  const T inf = T(FPBits::inf());
+  const T neg_inf = T(FPBits::neg_inf());
+  const T zero = T(FPBits::zero());
+  const T neg_zero = T(FPBits::neg_zero());
+  const T max_normal = T(FPBits(FPBits::MAX_NORMAL));
+  const T min_normal = T(FPBits(FPBits::MIN_NORMAL));
+  const T max_subnormal = T(FPBits(FPBits::MAX_SUBNORMAL));
+  const T min_subnormal = T(FPBits(FPBits::MIN_SUBNORMAL));
 
 public:
   void test_special_numbers(Func func) {
+    constexpr int N = 13;
+    const T SpecialInputs[N] = {inf,           neg_inf,        zero,
+                                neg_zero,      max_normal,     min_normal,
+                                max_subnormal, min_subnormal,  -max_normal,
+                                -min_normal,   -max_subnormal, -min_subnormal};
+
     EXPECT_FP_EQ(func(inf, nan), inf);
     EXPECT_FP_EQ(func(nan, neg_inf), inf);
-    EXPECT_FP_EQ(func(zero, inf), inf);
-    EXPECT_FP_EQ(func(neg_inf, neg_zero), inf);
-
     EXPECT_FP_EQ(func(nan, nan), nan);
     EXPECT_FP_EQ(func(nan, zero), nan);
     EXPECT_FP_EQ(func(neg_zero, nan), nan);
 
-    EXPECT_FP_EQ(func(neg_zero, zero), zero);
+    for (int i = 0; i < N; ++i) {
+      for (int j = 0; j < N; ++j) {
+        mpfr::BinaryInput<T> input{SpecialInputs[i], SpecialInputs[j]};
+        EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Hypot, input,
+                                       func(SpecialInputs[i], SpecialInputs[j]),
+                                       0.5);
+      }
+    }
   }
 
   void test_subnormal_range(Func func) {
Index: libc/src/__support/FPUtil/Hypot.h
===================================================================
--- libc/src/__support/FPUtil/Hypot.h
+++ libc/src/__support/FPUtil/Hypot.h
@@ -189,7 +189,10 @@
       sum >>= 2;
       ++out_exp;
       if (out_exp >= FPBits_t::MAX_EXPONENT) {
-        return T(FPBits_t::inf());
+        if (int round_mode = get_round();
+            round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
+          return T(FPBits_t::inf());
+        return T(FPBits_t(FPBits_t::MAX_NORMAL));
       }
     } else {
       // For denormal result, we simply move the leading bit of the result to
@@ -227,7 +230,8 @@
   y_new >>= 1;
 
   // Round to the nearest, tie to even.
-  switch (get_round()) {
+  int round_mode = get_round();
+  switch (round_mode) {
   case FE_TONEAREST:
     // Round to nearest, ties to even
     if (round_bit && (lsb || sticky_bits || (r != 0)))
@@ -243,7 +247,9 @@
     y_new -= ONE >> 1;
     ++out_exp;
     if (out_exp >= FPBits_t::MAX_EXPONENT) {
-      return T(FPBits_t::inf());
+      if (round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
+        return T(FPBits_t::inf());
+      return T(FPBits_t(FPBits_t::MAX_NORMAL));
     }
   }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D133370.458236.patch
Type: text/x-patch
Size: 3437 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libc-commits/attachments/20220906/a0dc60c9/attachment.bin>


More information about the libc-commits mailing list