Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

NaN*0.0 != NaN

Eric_Tittley
Beginner
550 Views
A piece of code sent to me had the following test for NaN:

if ( c * 0.0 != 0.0) { ... }

If c == NaN, the test is evaluated as follows
icc False
gcc True
xlc True

Similar code evaluates true in Matlab and IDL.

Now, I know that if ( c * 0.0 != 0.0) { ... } is not the best test, but was wondering what the difference is.

Seemingly, it is that NaN*0.0 == NaN in all compilers/environments except the Intel Compiler Suite. With icc, NaN*0.0 = 0.

Using: icc (ICC) 11.1 20090511 / gcc 4.4.0 / xlc ?

Results were independent of optimisation.

Anyone know what IEEE standard says NaN*0.0 should evaluate to? Is that even the correct question to ask?
0 Kudos
4 Replies
TimP
Honored Contributor III
550 Views
If you are trying to support platforms which don't implement isnan(), you will have extreme difficulty accomplishing the task. There have been plenty of problems in the open source library implementations, even under the restriction to compilation by gcc, and you will see configure tests in gnu software which look for ways to accomplish it.
The test will work on IEEE compliant hardware, with a compiler which compiles it literally. Your statement about "independent of optimisation" is too cryptic. Are you certain that gcc -ffast-math doesn't break it? Did you try icc -fp-model source -fno-inline-functions or other likely choices? I shudder to think how many combinations of options you would require to back up that statement.
Your NaN*0.0 == NaN literally speaking is impossible, as any comparison against NaN produces !=.
0 Kudos
Eric_Tittley
Beginner
550 Views
Thanks, tim18, for the response.

You are correct to point out that my original post was vague at points. gcc's -ffast-math does indeed change the result.

And I stupidly wrote "NaN*0.0 == NaN in all compilers/environments except the Intel Compiler Suite" when I meant to say "NaN*0.0 evaluates to NaN in all compilers/environments except the Intel Compiler Suite, where it evaluates to 0." But then, as the test above with gcc's -ffast-math shows, that statement is not strictly true, either.

May I distill the question to the (seemingly) simple question:
What does IEEE have to say about what NaN*0.0 should evaluate to?

The answer may be "nothing", which is an important answer, in itself.


0 Kudos
TimP
Honored Contributor III
550 Views
IEEE hardware produces a NaN result for any operation with a NaN operand. The specific variety of NaN may change. A comparison of NaN values, even if they are identical, produces non-equality. The greater problem you have is that compilers tend to ignore the possibilities of NaN and Inf operands when optimizing code. There aren't convenient means for changing this behavior, other than adoption of current C and Fortran standard intrinsics such as isnan().
0 Kudos
jimdempseyatthecove
Honored Contributor III
550 Views

You not only have the problem of the compiler seeing X*0.0 and replacing it with 0.0 (i.e. not perform NaN*0.0) but you also have the (potential) problem with the compiler seeing float==float and generating __int32==__int32 to compare bit values for equality. IEEE requires that even if two NaN's have same bit values, NaN1 - NaN2produces NaN. The __int32==__int32 comparison can return true when the NaN's happen to contain the same bit pattern (NaN's often do not have the same bit pattern)

Use isnan(x), its portable and depending on compiler it is likely intrinsic, inline and fast.

Jim Dempsey
0 Kudos
Reply