mirror of
https://github.com/intel/llvm.git
synced 2026-02-07 07:39:11 +08:00
[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
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,24 +24,38 @@ private:
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user