I don't think this works properly.
Test case:
Code: Select all
constexpr bool my_is_nan( T x )noexcept {
using integer_type = std::conditional_t<std::is_same_v<T, float>, std::uint32_t, std::uint64_t>;
constexpr auto qnan = std::bit_cast<integer_type, T>(std::numeric_limits<float>::quiet_NaN());
constexpr auto snan = std::bit_cast<integer_type, T>(std::numeric_limits<float>::signaling_NaN());
const auto bits = std::bit_cast<integer_type, T>(x);
return bits == qnan || bits == snan;
}
int main()
{
union
{
double f;
struct
{
uint64_t mantissa : 52;
uint64_t exponent : 11;
uint64_t sign : 1;
};
} x;
x.f = nan("");
std::cout << "IsNaN: " << isnan( x.f ) << " MyIsNaN: " << my_is_nan( x.f ) << " (sign=" << x.sign << ", exponent=" << x.exponent << ", mantissa=" << x.mantissa << ")" << std::endl;
x.mantissa |= 0xFFFF;
std::cout << "IsNaN: " << isnan( x.f ) << " MyIsNaN: " << my_is_nan( x.f ) << " (sign=" << x.sign << ", exponent=" << x.exponent << ", mantissa=" << x.mantissa << ")" << std::endl;
}
Output:
Code: Select all
IsNaN: 1 MyIsNaN: 1
IsNaN: 1 MyIsNaN: 0
A floating point number has a format that looks something like this:
A NaN is (usually) a number where all the exponent bits are set to 1. Whether it's a quiet or signaling NaN is determined by the highest bit of the mantissa. In a double, that leaves 51 bits (+ sign bit) that could be set to anything while still being considered NaN.
This is also mentioned in the cppreference page for queit_NaN and signaling_NaN: "In IEEE 754, the most common binary representation of floating-point numbers, any value with all bits of the exponent set and at least one bit of the fraction set represents a NaN. It is implementation-defined which values of the fraction represent quiet or signaling NaNs, and whether the sign bit is meaningful."
In fact, this property is used by dynamic languages to pack multiple types into a single double by using those free NaN bits to store data. This is known as NaN boxing, you can read about it here (got images from here too):
https://craftinginterpreters.com/optimization.html