diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -90,8 +90,13 @@ static_assert(sizeof(T) == sizeof(UIntType), "Data type and integral representation have different sizes."); - static constexpr int EXPONENT_BIAS = (1 << (ExponentWidth::VALUE - 1)) - 1; - static constexpr int MAX_EXPONENT = (1 << ExponentWidth::VALUE) - 1; + static constexpr int EXPONENT_BIAS = + (UIntType(1) << (ExponentWidth::VALUE - 1)) - 1; + static constexpr int MAX_EXPONENT = + (UIntType(1) << ExponentWidth::VALUE) - 1; + + static constexpr UIntType QUIET_BIT = + (UIntType(1) << (MantissaWidth::VALUE - 1)); static constexpr UIntType MIN_SUBNORMAL = UIntType(1); static constexpr UIntType MAX_SUBNORMAL = @@ -164,9 +169,17 @@ return bits; } + // Always generate quiet NaNs to avoid transformation of signaling NaNs: + // C17 F10.9.2: "if just one argument is a NaN, the [fmin/fmax] functions + // return the other argument" + // IEEE 754-2019 6.2, 9.6: "if either operand is a signaling NaN, an invalid + // operation exception is signaled... under default exception handling, any + // operation signaling an invalid operation exception and for which a + // floating-point result is to be delivered, except as stated otherwise, + // shall deliver a quiet NaN." static constexpr T build_nan(UIntType v) { FPBits bits = inf(); - bits.set_mantissa(v); + bits.set_mantissa(QUIET_BIT | v); return T(bits); } diff --git a/libc/test/src/math/RoundToIntegerTest.h b/libc/test/src/math/RoundToIntegerTest.h --- a/libc/test/src/math/RoundToIntegerTest.h +++ b/libc/test/src/math/RoundToIntegerTest.h @@ -84,7 +84,10 @@ void do_infinity_and_na_n_test(RoundToIntegerFunc func) { test_one_input(func, inf, INTEGER_MAX, true); test_one_input(func, neg_inf, INTEGER_MIN, true); +#ifndef LLVM_LIBC_NO_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR + // Result is not well-defined, we always returns INTEGER_MAX test_one_input(func, nan, INTEGER_MAX, true); +#endif } void testInfinityAndNaN(RoundToIntegerFunc func) {