I was trying around with signalling nans and how they are handled by the cpu. But when i used the builtin signaling nan from the standard numeric_limits class, it didn't work, at least in Visual Studio. No exceptions or flags were raised, when I've done operations on them. But when i manually put the bit sequence for an snan, it worked.
My c++ code:
#include <iostream>
#include <string.h> // memcpy
#include <bitset>
#include <limits>
#include <immintrin.h>
int main() {
if (std::numeric_limits<float>::has_signaling_NaN) {
float snan = std::numeric_limits<float>::signaling_NaN();
int bits = 0;
memcpy(&bits, &snan, sizeof(float));
std::cout << std::bitset<32>(bits) << "\n";
//check if fp-flags are being raised
volatile float temp = snan;
_mm_setcsr(_mm_getcsr() & ~_MM_EXCEPT_MASK);//clear flags
temp = temp + 1.0f;
std::cout << "Invalid Flag: " << ((_mm_getcsr() & _MM_EXCEPT_INVALID) > 0) << "\n";
}
else {
std::cout << "No signaling NaN" << std::endl;
}
return 0;
}
Sign
| Exponent
| | Fraction
| | |
0 11111111 10000000000000000000001 VS MSVC v19.34 /Od and /O2 -No Flags Raised
0 11111111 00000000000000000000001 VS Clang (6.0 ?) Addon /Od and /O2 -Invalid Flags Raised for Both
0 11111111 01000000000000000000000 Clang 14.0.6 Mingw64 -O2 and -O0 -Invalid Flags Raised for Both
0 11111111 01000000000000000000000 GCC 12.2.0 Mingw64 -O2 and -O0 -Invalid Flags Raised for Both
I understand that there are differences in the snan format, as the standard only defines that the first bit should be zero, but not which bit should then differentiate the bit Value from INFINTY. So the result of MSVC is obviously wrong as of my understanding, or am I missing something.
I tried running it on different settings, other c++ versions, but nothing changed.