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 @@ -150,7 +150,7 @@ return abs(y); } - if (x >= y) { + if (abs(x) >= abs(y)) { a_exp = x_bits.getUnbiasedExponent(); a_mant = x_bits.getMantissa(); b_exp = y_bits.getUnbiasedExponent(); @@ -178,10 +178,13 @@ y_mant_width = MantissaWidth::value + 1; } else { leading_one = internal::findLeadingOne(a_mant, y_mant_width); + a_exp = 1; } if (b_exp != 0) { b_mant |= one; + } else { + b_exp = 1; } a_mant_sq = static_cast(a_mant) * a_mant; 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 @@ -47,28 +47,47 @@ void testSubnormalRange(Func func) { constexpr UIntType count = 1000001; - constexpr UIntType step = - (FPBits::maxSubnormal - FPBits::minSubnormal) / count; - for (UIntType v = FPBits::minSubnormal, w = FPBits::maxSubnormal; - v <= FPBits::maxSubnormal && w >= FPBits::minSubnormal; - v += step, w -= step) { - T x = T(FPBits(v)), y = T(FPBits(w)); - T result = func(x, y); - mpfr::BinaryInput input{x, y}; - ASSERT_MPFR_MATCH(mpfr::Operation::Hypot, input, result, 0.5); + for (unsigned scale = 0; scale < 4; ++scale) { + UIntType maxValue = FPBits::maxSubnormal << scale; + UIntType step = (maxValue - FPBits::minSubnormal) / count; + for (int signs = 0; signs < 4; ++signs) { + for (UIntType v = FPBits::minSubnormal, w = maxValue; + v <= maxValue && w >= FPBits::minSubnormal; v += step, w -= step) { + T x = T(FPBits(v)), y = T(FPBits(w)); + if (signs % 2 == 1) { + x = -x; + } + if (signs >= 2) { + y = -y; + } + + T result = func(x, y); + mpfr::BinaryInput input{x, y}; + ASSERT_MPFR_MATCH(mpfr::Operation::Hypot, input, result, 0.5); + } + } } } void testNormalRange(Func func) { constexpr UIntType count = 1000001; constexpr UIntType step = (FPBits::maxNormal - FPBits::minNormal) / count; - for (UIntType v = FPBits::minNormal, w = FPBits::maxNormal; - v <= FPBits::maxNormal && w >= FPBits::minNormal; - v += step, w -= step) { - T x = T(FPBits(v)), y = T(FPBits(w)); - T result = func(x, y); - mpfr::BinaryInput input{x, y}; - ASSERT_MPFR_MATCH(mpfr::Operation::Hypot, input, result, 0.5); + for (int signs = 0; signs < 4; ++signs) { + for (UIntType v = FPBits::minNormal, w = FPBits::maxNormal; + v <= FPBits::maxNormal && w >= FPBits::minNormal; + v += step, w -= step) { + T x = T(FPBits(v)), y = T(FPBits(w)); + if (signs % 2 == 1) { + x = -x; + } + if (signs >= 2) { + y = -y; + } + + T result = func(x, y); + mpfr::BinaryInput input{x, y}; + ASSERT_MPFR_MATCH(mpfr::Operation::Hypot, input, result, 0.5); + } } } };