diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h --- a/libc/src/__support/FPUtil/Hypot.h +++ b/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)); } } diff --git a/libc/test/src/math/HypotTest.h b/libc/test/src/math/HypotTest.h --- a/libc/test/src/math/HypotTest.h +++ b/libc/test/src/math/HypotTest.h @@ -24,24 +24,38 @@ using Func = T (*)(T, T); using FPBits = __llvm_libc::fputil::FPBits; using UIntType = typename FPBits::UIntType; - const T nan = T(__llvm_libc::fputil::FPBits::build_nan(1)); - const T inf = T(__llvm_libc::fputil::FPBits::inf()); - const T neg_inf = T(__llvm_libc::fputil::FPBits::neg_inf()); - const T zero = T(__llvm_libc::fputil::FPBits::zero()); - const T neg_zero = T(__llvm_libc::fputil::FPBits::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 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) {