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]