[libc-commits] [libc] bb6966a - [libc] Return correct values for hypot when overflowed.
Tue Ly via libc-commits
libc-commits at lists.llvm.org
Wed Sep 7 16:23:35 PDT 2022
Author: Tue Ly
Date: 2022-09-07T19:23:11-04:00
New Revision: bb6966aa5340609dc5144b9f496f548bc53f7e60
URL: https://github.com/llvm/llvm-project/commit/bb6966aa5340609dc5144b9f496f548bc53f7e60
DIFF: https://github.com/llvm/llvm-project/commit/bb6966aa5340609dc5144b9f496f548bc53f7e60.diff
LOG: [libc] Return correct values for hypot when overflowed.
Hypot incorrectly returns +Inf when overflowed with FE_DOWNWARD and
FE_TOWARDZERO rounding modes.
Reviewed By: sivachandra, zimmermann6
Differential Revision: https://reviews.llvm.org/D133370
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 077e8db20b03c..de22691f7de79 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -189,7 +189,10 @@ static inline T hypot(T x, T y) {
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 @@ static inline T hypot(T x, T y) {
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 @@ static inline T hypot(T x, T y) {
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));
}
}
diff --git a/libc/test/src/math/HypotTest.h b/libc/test/src/math/HypotTest.h
index b7a7ffdf5312a..57abef8b62342 100644
--- a/libc/test/src/math/HypotTest.h
+++ b/libc/test/src/math/HypotTest.h
@@ -24,24 +24,38 @@ class HypotTestTemplate : public __llvm_libc::testing::Test {
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) {
More information about the libc-commits
mailing list