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,22 @@ if ((x_bits.get_unbiased_exponent() >= y_bits.get_unbiased_exponent() + MantissaWidth::VALUE + 2) || (y == 0)) { + // Check if the rounding mode is FE_UPWARD, will need -frounding-math so + // that the compiler does not optimize it away. + if ((y != 0) && (0x1p0f + 0x1p-24f != 0x1p0f)) { + 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); + // Check if the rounding mode is FE_UPWARD, will need -frounding-math so + // that the compiler does not optimize it away. + if ((x != 0) && (0x1p0f + 0x1p-24f != 0x1p0f)) { + UIntType out_bits = FPBits_t(abs(y)).uintval(); + return T(FPBits_t(++out_bits)); + } return abs(y); } @@ -250,8 +262,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/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -954,7 +954,9 @@ DEPENDS libc.src.__support.FPUtil.fputil COMPILE_OPTIONS - -O2 + -O3 + -frounding-math + -Wno-c++17-extensions ) add_entrypoint_object( @@ -1002,7 +1004,9 @@ DEPENDS libc.src.__support.FPUtil.fputil COMPILE_OPTIONS - -O2 + -O3 + -frounding-math + -Wno-c++17-extensions ) add_entrypoint_object( diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt --- a/libc/test/src/math/CMakeLists.txt +++ b/libc/test/src/math/CMakeLists.txt @@ -1060,6 +1060,8 @@ libc.include.math libc.src.math.hypotf libc.src.__support.FPUtil.fputil + COMPILE_OPTIONS + -Wno-c++17-extensions ) add_fp_unittest( @@ -1073,6 +1075,8 @@ libc.include.math libc.src.math.hypot libc.src.__support.FPUtil.fputil + COMPILE_OPTIONS + -Wno-c++17-extensions ) add_fp_unittest( 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 @@ -10,7 +10,6 @@ #define LLVM_LIBC_TEST_SRC_MATH_HYPOTTEST_H #include "src/__support/FPUtil/FPBits.h" -#include "src/__support/FPUtil/Hypot.h" #include "utils/MPFRWrapper/MPFRUtils.h" #include "utils/UnitTest/FPMatcher.h" #include "utils/UnitTest/Test.h" @@ -43,6 +42,17 @@ EXPECT_FP_EQ(func(neg_zero, nan), nan); EXPECT_FP_EQ(func(neg_zero, zero), zero); + + T x = 0x1.ffffecp-1f; + T y = 0x1.000002p+27; + mpfr::BinaryInput input{x, y}; + ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Hypot, input, func(x, y), + 0.5); + x = 0x1.ccbbbcfef3c02p-523; + y = 0x1.924bf639c1a94p+500; + input = mpfr::BinaryInput{x, y}; + ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Hypot, input, func(x, y), + 0.5); } void test_subnormal_range(Func func) { @@ -62,9 +72,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 +95,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); } } } diff --git a/libc/test/src/math/differential_testing/CMakeLists.txt b/libc/test/src/math/differential_testing/CMakeLists.txt --- a/libc/test/src/math/differential_testing/CMakeLists.txt +++ b/libc/test/src/math/differential_testing/CMakeLists.txt @@ -406,6 +406,7 @@ libc.src.math.hypotf COMPILE_OPTIONS -fno-builtin + -Wno-c++17-extensions ) add_diff_binary( @@ -417,4 +418,5 @@ libc.src.math.hypot COMPILE_OPTIONS -fno-builtin + -Wno-c++17-extensions )