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 @@ -10,6 +10,7 @@ #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_HYPOT_H #include "BasicOperations.h" +#include "FEnvImpl.h" #include "FPBits.h" #include "src/__support/CPP/TypeTraits.h" @@ -143,11 +144,18 @@ if ((x_bits.get_unbiased_exponent() >= y_bits.get_unbiased_exponent() + MantissaWidth::VALUE + 2) || (y == 0)) { + if ((y != 0) && (get_round() == FE_UPWARD)) { + UIntType out_bits = FPBits_t(abs(x)).uintval(); + return T(FPBits_t(++out_bits)); + } return abs(x); } else if ((y_bits.get_unbiased_exponent() >= x_bits.get_unbiased_exponent() + MantissaWidth::VALUE + 2) || (x == 0)) { - y_bits.set_sign(0); + if ((x != 0) && (get_round() == FE_UPWARD)) { + UIntType out_bits = FPBits_t(abs(y)).uintval(); + return T(FPBits_t(++out_bits)); + } return abs(y); } @@ -250,8 +258,16 @@ y_new >>= 1; // Round to the nearest, tie to even. - if (round_bit && (lsb || sticky_bits || (r != 0))) { - ++y_new; + switch (get_round()) { + case FE_TONEAREST: + // Round to nearest, ties to even + if (round_bit && (lsb || sticky_bits || (r != 0))) + ++y_new; + break; + case FE_UPWARD: + if (round_bit || sticky_bits || (r != 0)) + ++y_new; + break; } if (y_new >= (ONE >> 1)) { 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 @@ -62,9 +62,9 @@ y = -y; } - T result = func(x, y); mpfr::BinaryInput input{x, y}; - ASSERT_MPFR_MATCH(mpfr::Operation::Hypot, input, result, 0.5); + ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Hypot, input, + func(x, y), 0.5); } } } @@ -85,9 +85,9 @@ y = -y; } - T result = func(x, y); mpfr::BinaryInput input{x, y}; - ASSERT_MPFR_MATCH(mpfr::Operation::Hypot, input, result, 0.5); + ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Hypot, input, + func(x, y), 0.5); } } }