Ron Blaschke wrote on 01/08/2006 08:17:

I am wondering if this NaN != NaN property could be used for the isnan
and finite tests, like so:

int
Parrot_math_isnan(double x)
{
    return x != x;
}

int
Parrot_math_finite(double x)
{
    return (!Parrot_math_isnan(x - x));
}

That is, if "x != x" it's a NaN.  If x is finite, "x - x" should yield
something close to 0.  Otherwise, "Inf - Inf" or "NaN - NaN", it's NaN.

'x - x' should always yield precisely 0 - http://docs.sun.com/source/806-3568/ncg_goldberg.html#929 says "The IEEE standard uses denormalized numbers, which guarantee [...] x = y <=> x - y = 0", and later states "x - x = +0 for all x [...] Unless the rounding mode is round toward -Inf, in which case x - x = -0". (Except when x is +/-Inf or NaN, when it should give NaN.)

Is this not portable enough?  Is it better to look at the bits directly?

It doesn't work nicely with optimisers (or at least with MSVC's). Parrot_math_isnan seems to be handled correctly, but Parrot_math_finite has problems:

Using VS2003 /O1, it does compile into a call to Parrot_math_isnan, but with the argument 0.0 (via 'fldz') rather than calculating x-x.

Using VS2003 /O2, it does:
    ?Parrot_math_finite@@[EMAIL PROTECTED] PROC NEAR
        mov eax, 1
        ret 0
    ?Parrot_math_finite@@[EMAIL PROTECTED] ENDP

Using VS2003 /O2 plus /Op ("improve floating-pt consistency") it does get the correct answer.

Using VS2005 /O0 to /O2, it does get the correct answer by default. But adding /fp:fast makes it the same as the VS2003 behaviour. (The documentation says /fp:precise enables behaviour where "Expression optimizations that are invalid for special values (NaN, +infinity, -infinity, +0, -0) will not be allowed. The optimizations x-x => 0, x*0 => 0, x-0 => x, x+0 => x, and 0-x => -x are all invalid for various reasons (see IEEE 754 and the C99 standard)", but those optimisations are allowed under /fp:fast because most people care about speed more than predictable/correct output.)

It seems like the only way to stay safe is to work around the optimiser, presumably by testing bits or using library functions or writing assembly code (e.g. with 'fxam' on x86).


Ron


--
Philip Taylor
[EMAIL PROTECTED]

Reply via email to