4 ms·
> Well half of NaNs are quiet, so that's easy to deal with Which half varies by architecture (I'm looking at you, MIPS - and apparently RISC-V at one point was
by MaulingMonkey 4y ago
> Well half of NaNs are quiet, so that's easy to deal with
Which half varies by architecture (I'm looking at you, MIPS - and apparently RISC-V at one point was going to go the MIPS route with an all-1s payload for canonical qnans?) - so platform specific spaghet and requirements testing is in the mix.
> And the fast optimization flags are themselves violating the standard so those don't count.
Some jerk will enable them, standards-violating or not. While it's valid for the solution to disable the optimization, in practice you will need to debug and write defensive code when this happens. I know of at least one platform which enables such optimizations by default for it's "release" builds, and while I'm angry at them for doing so, I'm unfortunately relegated to existing in the same reality as them.
Perhaps you're lucky enough to exist in a different reality?
> I suggested memcpy because it's the safe way.
More generally, yes, but in the specific context of preserving a NaN payload I would not trust the optimizer to keep my NaN payloads untouched when stored as a floating point value. LLVM developers appear to agree that NaN payload preservation is not guaranteed - I guess you can quote me on my earlier "optimizers can butcher your NaN payloads", presumably even without fast math optimizations:
https://lists.llvm.org/pipermail/llvm-dev/2018-November/127670.html https://lists.llvm.org/pipermail/llvm-dev/2018-November/1276...
Which causes a good bit of awkwardness for Rust:
https://github.com/rust-lang/rust/issues/73328 https://github.com/rust-lang/rust/issues/73328
The solution is to not attempt to store payload-laden NaN as any kind of floating point value, even via memcpy. A union is acceptable in the sense that at least, then, you're supposedly storing an integer, and the bit pattern of that would be preserved. A memcpy to a temporary float immediately before NaN testing / floating point usage - and never back to integer in a naieve attempt to extract the possibly discarded payload - would work, but is a hell of a caveat to omit when saying "memcpy from bytes to a NaN should work fine", especially when mentioning `nan` with it's payload argument, which is unextractable without doing the naieve "back to integer" extraction which, if the above is to be believed, is unreliable at best.
- Dylan16807 4y ago> Perhaps you're lucky enough to exist in a different reality? Any code I've touched that was going to deal with boxing had enough control over the build system to avoid that. > More generally, yes, but in the specific context of preserving a NaN payload I would not trust the optimizer to keep my NaN payloads untouched when stored as a floating point value. LLVM developers appear to agree that NaN payload preservation is not guaranteed - I guess you can quote me on my earlier "optimizers can butcher your NaN payloads", presumably even without fast math optimizations: That looks like it only butchers the NaN if you do math on it or try to have compile-time NaNs, which shouldn't be an issue here? Are there other factors making it worse that I'm missing in a quick read? > A union is acceptable in the sense that at least, then, you're supposedly storing an integer, and the bit pattern of that would be preserved. Oh, you're suggesting a union as permanent storage, not just to perform the cast. That makes sense.