Movement against float.init being nan
Ali Çehreli
acehreli at yahoo.com
Thu Aug 25 19:21:08 UTC 2022
On 8/25/22 11:05, Bastiaan Veelo wrote:
> On Monday, 22 August 2022 at 22:11:23 UTC, jmh530 wrote:
>> On Monday, 22 August 2022 at 20:29:57 UTC, Bastiaan Veelo wrote:
>>> I had some fun with `isNaN` the other day. We used it to check for
>>> initialisation in an access function to cache an expensive
>>> computation. This worked brilliantly until we noticed a malfunction
>>> in the release version. It took a while until I realised that I had
>>> given the LDC `fastmath` option to the release build, which assumes
>>> NaN does not occur, which makes `isNaN` misbehave.
>>>
>>
>> Is there a simple example of this behavior?
>
> Yes:
> ```d
> import std;
> void main()
> {
> assert(isNaN(double.nan));
> }
> ```
>
> Compile with LDC and options `--ffast-math -O`.
>
> -- Bastiaan.
I found documentation on --fast-math here:
https://clang.llvm.org/docs/UsersManual.html
It includes "compiler make[s] [...] assumptions [...] Operands to
floating-point operations are not equal to NaN and Inf"
This is contrary to Walter's understanding, which I understand as
"operations on NaN stay NaN". LLVM (at least Clang) seems to have a
different take on NaN.
And here is Phobos' isNaN implementation in math/traits.d:
bool isNaN(X)(X x) @nogc @trusted pure nothrow
if (isFloatingPoint!(X))
{
version (all)
{
return x != x;
}
else
{
/*
Code kept for historical context. At least on Intel, the simple
test
x != x uses one dedicated instruction (ucomiss/ucomisd) that
runs in one
cycle. Code for 80- and 128-bits is larger but still smaller
than the
integrals-based solutions below. Future revisions may enable
the code
below conditionally depending on hardware.
*/
// ... Removed by Ali
}
}
LLVM must be thinking x != x is not a valid operation on NaN. Could we
use a bit pattern check instead? Or write it as an asm block?
Ali
More information about the Digitalmars-d
mailing list