isnan or isntnan?

J

JohnF

I'm having trouble debugging some apparent nan problem.
Checking with isnan() seems okay, but printf() just prints
nan anyway. I'm running gcc 4.2.4, under linux (slackware 12.2
with default packages/libs/etc), and for debugging purposes
have compiled with -ffast-math. It's the y2 arg that's the
apparent culprit in the following code (which log-linearly
interpolates and returns the y-value at input x, given known
points x1,y1 and x2,y2)...
double loglinterp(x, x1, y1, x2, y2)
double x,x1,y1,x2,y2;
{
double weight;
int nanerror = (isnan(y1)?1:0);
if ( isnan(y2) ) nanerror += 2;
if ( nanerror!=0 || y1<=0.0 || y2<=0.0 )
{ printf("loglinterp> y-arg<=0.0(isnan=%d): x=%8.5f; "
"x1=%8.5f, y1=%8.5f; x2=%8.5f, y2=%8.5f\n",
nanerror,x,x1,y1,x2,y2);
return (-1.0); }
if ( x2 == x1 ) weight = .5;
else weight = (x - x1)/(x2 - x1);
return exp( (1.0 - weight)*log(y1) + weight*log(y2) );
}
And here's some output where it appears to be catching
what it apparently thinks is a y2<=0 (I've manually wrapped
and indented the long lines)...
loglinterp> y-arg<=0.0(isnan=0): x= 0.17131; x1= 0.16615,
y1= 0.59367; x2= 0.17910, y2= nan
loglinterp> y-arg<=0.0(isnan=0): x= 0.16898; x1= 0.16615,
y1= 0.59367; x2= 0.17910, y2= nan
loglinterp> y-arg<=0.0(isnan=0): x= 0.16668; x1= 0.16615,
y1= 0.59367; x2= 0.17910, y2= nan
It seems that isnan(y2) must be false since it prints 0 for
the nanerror variable, but then it prints nan for y2 anyway.
What could be going on, and how do I proceed to debug it?
Thanks,
 
E

Eric Sosman

I'm having trouble debugging some apparent nan problem.
Checking with isnan() seems okay, but printf() just prints
nan anyway. I'm running gcc 4.2.4, under linux (slackware 12.2
with default packages/libs/etc), and for debugging purposes
have compiled with -ffast-math. [...]
What could be going on, and how do I proceed to debug it?

The info for my copy of gcc says that -ffast-math "can
result in incorrect output..." The info doesn't describe the
kinds of incorrectness that might occur, but perhaps if you
dig into the matter you'll find an explanation.

Or you could omit -ffast-math and see what happens ...
 
J

James Waldby

I'm having trouble debugging some apparent nan problem. Checking with
isnan() seems okay, but printf() just prints nan anyway.

[snip three lines of code like
double loglinterp(x, x1, y1, x2, y2) double x,x1,y1,x2,y2; {
compiled with gcc 4.2.4 on slackware 12.2 with -ffast-math switch
etc]
if ( isnan(y2) ) nanerror += 2;
if ( nanerror!=0 || y1<=0.0 || y2<=0.0 )
{ printf("loglinterp> y-arg<=0.0(isnan=%d): x=%8.5f; "
"x1=%8.5f, y1=%8.5f; x2=%8.5f, y2=%8.5f\n",
nanerror,x,x1,y1,x2,y2);

[snip other code and some output like next:]
loglinterp> y-arg<=0.0(isnan=0): x= 0.16668; x1= 0.16615,
y1= 0.59367; x2= 0.17910, y2= nan
It seems that isnan(y2) must be false since it prints 0 for the nanerror
variable, but then it prints nan for y2 anyway. What could be going on,
and how do I proceed to debug it? Thanks,

For more discussion of debugging, perhaps try comp.programming,
not c.l.c. (Added c.p to newsgroups and set followups there.)

If Eric Sosman's suggestion re -ffast-math doesn't help, try
printing y2 also in hex, both before calling loglinterp() and
within loglinterp(). Eg, write a function printFX (double y)
and in printFX() declare a union u with double and long or long
long members u.f and u.l; set u.f to y; and printf ("...%f...%0lx...",
u.f, u.l). Use an integer type of the same size as a double.
If you want to print characters as well, have a member u.c
declared with char c[sizeof(double)], and putchar each u.c.

Then, if the hex versions look like characters or like integers,
look for a string copy or array copy spilling out of bounds, or
assignment to an integer alias of y2, etc.
 
J

JohnF

Eric said:
JohnF said:
I'm having trouble debugging some apparent nan problem.
Checking with isnan() seems okay, but printf() just prints
nan anyway. I'm running gcc 4.2.4, under linux (slackware 12.2
with default packages/libs/etc), and for debugging purposes
have compiled with -ffast-math. [...]
What could be going on, and how do I proceed to debug it?

The info for my copy of gcc says that -ffast-math "can
result in incorrect output..." The info doesn't describe the
kinds of incorrectness that might occur, but perhaps if you
dig into the matter you'll find an explanation.
Or you could omit -ffast-math and see what happens ...

Thanks, Eric. Actually, I first compiled it without any
special -switches at all, and got some nan's in the output.
The -ffast-math helped pin down the culprit by exaggerating
the nan problem. Otherwise, it didn't show up in loglinterp()
at all. And anyway, I wouldn't want to "solve" the problem by
hiding it. I'd think a correct program should run correctly
with or without -ffast-math.
 
A

Alan Curry

I'm having trouble debugging some apparent nan problem.
Checking with isnan() seems okay, but printf() just prints
nan anyway. I'm running gcc 4.2.4, under linux (slackware 12.2

This is plausibly a compiler bug, so before digging too deep, you should
first try to reproduce the result with the newest version of the compiler you
can get your hands on.

The first rule of compiler bugs is that if you think you found one, you
probably didn't. The second rule is if you did find one, it's probably
already been found and fixed by someone else.

Besides, gcc-4.2 is no longer a maintained branch, which means that even if
you did find a previously unknown bug, nobody will care unless a newer
version is also affected.
 
T

Tim Prince

Eric said:
JohnF said:
I'm having trouble debugging some apparent nan problem.
Checking with isnan() seems okay, but printf() just prints
nan anyway. I'm running gcc 4.2.4, under linux (slackware 12.2
with default packages/libs/etc), and for debugging purposes
have compiled with -ffast-math. [...]
What could be going on, and how do I proceed to debug it?

The info for my copy of gcc says that -ffast-math "can
result in incorrect output..." The info doesn't describe the
kinds of incorrectness that might occur, but perhaps if you
dig into the matter you'll find an explanation.
Or you could omit -ffast-math and see what happens ...

Thanks, Eric. Actually, I first compiled it without any
special -switches at all, and got some nan's in the output.
The -ffast-math helped pin down the culprit by exaggerating
the nan problem. Otherwise, it didn't show up in loglinterp()
at all. And anyway, I wouldn't want to "solve" the problem by
hiding it. I'd think a correct program should run correctly
with or without -ffast-math.
-ffast-math can easily provoke a NaN from a sequence of operations which
would produce finite results without that option. For example, x/y could
in effect become (1/y) * x; should 1/y overflow, a zero could be
produced "erroneously," then, further arithmetic involving those
results could produce NaN. Also, -ffast-math allows parentheses to be
treated K&R fashion (ignored, according to usual algebraic rules), in
violation of standard C rules.
It's certainly possible that making your code more reliable will allow
it to work with and without -ffast-math.
 
J

JohnF

Tim said:
JohnF said:
Eric said:
JohnF wrote:
I'm having trouble debugging some apparent nan problem.
Checking with isnan() seems okay, but printf() just prints
nan anyway. I'm running gcc 4.2.4, under linux (slackware 12.2
with default packages/libs/etc), and for debugging purposes
have compiled with -ffast-math. [...]
What could be going on, and how do I proceed to debug it?

The info for my copy of gcc says that -ffast-math "can
result in incorrect output..." The info doesn't describe the
kinds of incorrectness that might occur, but perhaps if you
dig into the matter you'll find an explanation.
Or you could omit -ffast-math and see what happens ...

Thanks, Eric. Actually, I first compiled it without any
special -switches at all, and got some nan's in the output.
The -ffast-math helped pin down the culprit by exaggerating
the nan problem. Otherwise, it didn't show up in loglinterp()
at all. And anyway, I wouldn't want to "solve" the problem by
hiding it. I'd think a correct program should run correctly
with or without -ffast-math.

-ffast-math can easily provoke a NaN from a sequence of operations which
would produce finite results without that option. For example, x/y could
in effect become (1/y) * x; should 1/y overflow, a zero could be
produced "erroneously," then, further arithmetic involving those
results could produce NaN.

Thanks, Tim. As mentioned to Eric, I first compiled without any
special -switches, and noticed nan's in the output. So that probably
reflects some actual code error on my part, rather than some compiler
artifact from order of execution, or whatever. The -ffast-math did,
in fact, produce a few more nan's than without it, helping me locate
a common "bottleneck" at loglinterp() through which all the bad
numbers seem to pass. Now I can try to trace back from there to the
source (and then hopefully cause) of the bad numbers. And that can
probably now be done with or without -ffast-math in the compile.
Also, -ffast-math allows parentheses to be
treated K&R fashion (ignored, according to usual algebraic rules), in
violation of standard C rules.
It's certainly possible that making your code more reliable will allow
it to work with and without -ffast-math.

I'll be happy to get it working without. I had no particular interest
in the switch until I noticed nan errors in the output and started
trying to debug.
 
J

JohnF

Alan Curry said:
This is plausibly a compiler bug, so before digging too deep, you should
first try to reproduce the result with the newest version of the compiler you
can get your hands on.

The first rule of compiler bugs is that if you think you found one, you
probably didn't. The second rule is if you did find one, it's probably
already been found and fixed by someone else.

Besides, gcc-4.2 is no longer a maintained branch, which means that even if
you did find a previously unknown bug, nobody will care unless a newer
version is also affected.

Thanks, Alan, but I'm not all that concerned about following up
on a (rather benign in this case) putative compiler bug.
It's not affecting (as far as I know) my program, just my
debugging process. So the compiler bug, if that's what it is,
won't affect me at all after the program is debugged.
And James, from the other post, suggested a workaround --
sprintf the number and check the string for "nan".
If printf is printing nan, then that ought to work
regardless of isnan()'s inconsistent return value.
And that'll solve my immediate problem, compiler bug or not.
(Now all I have to do is actually debug the silly program.)
 
N

Nick Bowler

It seems that isnan(y2) must be false since it prints 0 for the nanerror
variable, but then it prints nan for y2 anyway. What could be going on,
and how do I proceed to debug it? Thanks,

Since I didn't see it posted elsewhere in this thread, it should be
noted that GCC's -ffast-math option implies -ffinite-math-only, which
tells the compiler that it may assume all floating point values are
finite. This means that GCC can and will replace all calls to isnan or
isinf with a constant 0.
 
J

jacob navia

Le 16/11/10 20:04, Nick Bowler a écrit :
Since I didn't see it posted elsewhere in this thread, it should be
noted that GCC's -ffast-math option implies -ffinite-math-only, which
tells the compiler that it may assume all floating point values are
finite. This means that GCC can and will replace all calls to isnan or
isinf with a constant 0.


!!!!!!!!!!!!!!!!!!!!!!!!

This is one of the worst bugs of gcc I have ever seen.

Buggy by design!

How can the compiler possibly replace all isnan() by zero?
And by an IMPLICIT RULE. Nowhere in the documentation is mentioned that
calls to isnan() will be ignored. It just says:

-ffinite-math-only
Allow optimizations for floating-point arithmetic that assume that
arguments and results are not NaNs or +-Infs.

This option should never be turned on by any -O option since it can
result in incorrect output for programs which depend on an exact
implementation of IEEE or ISO rules/specifications.

The default is -fno-finite-math-only.

Reading this, I understand that the compiler "assumes that arguments and
results are not NANs. Nowhere is said that a function call to isnan()
will be IGNORED.

Well...

THERE IS NO WARRANTY FOR THE PROGRAM, THE ENTIRE RISK AS TO THE QUALITY
AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.
 
K

Keith Thompson

jacob navia said:
Le 16/11/10 20:04, Nick Bowler a écrit :

!!!!!!!!!!!!!!!!!!!!!!!!

This is one of the worst bugs of gcc I have ever seen.

Buggy by design!

How can the compiler possibly replace all isnan() by zero?
And by an IMPLICIT RULE. Nowhere in the documentation is mentioned that
calls to isnan() will be ignored. It just says:

-ffinite-math-only
Allow optimizations for floating-point arithmetic that assume that
arguments and results are not NaNs or +-Infs.

This option should never be turned on by any -O option since it can
result in incorrect output for programs which depend on an exact
implementation of IEEE or ISO rules/specifications.

The default is -fno-finite-math-only.

Reading this, I understand that the compiler "assumes that arguments and
results are not NANs. Nowhere is said that a function call to isnan()
will be IGNORED.

The option is not enabled by default, and the documentation, which
you've just quoted, says what it does. It's obviously intended
for use with programs that are known not to generate anything other
than finite real numbers (no NaNs, no infinities, etc.).

If your program is calling isnan(), you obviously care about
whether some value in your program is a NaN -- and you obviously
shouldn't be using -ffinite-math-only to compile it. That option
doesn't prevent the generation of NaNs and infinities, it permits
the compiler to assume that *your program* doesn't generate them.

You're complaining that an option that, according to its
documentation, "can result in incorrect output" can result in
incorrect output.

Note that isnan() is provided by glibc, not by gcc, though gcc
might optimize calls to it in some cases.

And you're assuming that Nick's statement about gcc's behavior is
correct. It's not an unreasonable inference from the documentation,
but a quick experiment doesn't support his statement; in a small test
program compiled with -ffinite-math-only, isnan() returns 1. Nick,
do you know something about this beyond what gcc's documentation
states?
 
J

jacob navia

Le 16/11/10 22:36, Keith Thompson a écrit :
You are confusing

The option given by the user was

-ffast-math

and THAT option turns on IMPLICITELY finite-math

But obviously, you are right.

When I buy a coffee machine "guaranted 3 months",
I can't fix it in the store because in a very small paragraph
of the thick contract (that was less than gcc's doc about options)
was written in small print that "I have to pay the transport to
the workshop"... that costs more than the machine

Clever isn't it?
 
W

William Hughes

The option is not enabled by default, and the documentation, which
you've just quoted, says what it does.  It's obviously intended
for use with programs that are known not to generate anything other
than finite real numbers (no NaNs, no infinities, etc.).

If your program is calling isnan(), you obviously care about
whether some value in your program is a NaN -- and you obviously
shouldn't be using -ffinite-math-only to compile it.  That option
doesn't prevent the generation of NaNs and infinities, it permits
the compiler to assume that *your program* doesn't generate them.

You're complaining that an option that, according to its
documentation, "can result in incorrect output" can result in
incorrect output.

Note that isnan() is provided by glibc, not by gcc, though gcc
might optimize calls to it in some cases.

And you're assuming that Nick's statement about gcc's behavior is
correct.  It's not an unreasonable inference from the documentation,
but a quick experiment doesn't support his statement; in a small test
program compiled with -ffinite-math-only, isnan() returns 1.  Nick,
do you know something about this beyond what gcc's documentation
states?



It may depend on optimization level. If you specify
-ffinite-math-only and pass isnan a NAN there is no
expected behaviour. At low opimzation isnan(x) may
in fact determine if x is a NAN, and since the compiler
thinks it knows that x is not a NAN the compiler thinks
this is a slow way of getting 0. At higher optimizations
the compiler may choose a fast way of getting 0.

- William Hughes
 
K

Keith Thompson

jacob navia said:
Le 16/11/10 22:36, Keith Thompson a écrit :
You are confusing

The option given by the user was

-ffast-math

and THAT option turns on IMPLICITELY finite-math

But obviously, you are right.

When I buy a coffee machine "guaranted 3 months",
I can't fix it in the store because in a very small paragraph
of the thick contract (that was less than gcc's doc about options)
was written in small print that "I have to pay the transport to
the workshop"... that costs more than the machine

Clever isn't it?

You are misrepresenting the situation.

Surely you wouldn't consider using -ffast-math without reading the
documentation. If you did so, you would know that it can result in
incorrect output, because the documentation says so in so many words.
And if you hadn't read the documentation, you probably wouldn't know
that -ffast-math exists, and you'd be safe.

This is not fine print.

(Nor is it really about C.)
 
J

JohnF

Keith Thompson said:
If your program is calling isnan(), you obviously care about
whether some value in your program is a NaN -- and you obviously
shouldn't be using -ffinite-math-only to compile it. That option
doesn't prevent the generation of NaNs and infinities, it permits
the compiler to assume that *your program* doesn't generate them.

You're complaining that an option that, according to its
documentation, "can result in incorrect output" can result in
incorrect output.

I'm sorry for starting this sequence of posts. Note that I've
already twice explained above how I wasn't too clear in my
original post. Here's what happened...
o I resurrected some old code from 1991-1992, which was
exhaustively tested (by groups in both New York, which
included me, and in Tampa) and it all worked fine then.
That archived code includes test suites of data and
their output.
o Made a few changes, e.g., our function valloc() subsequently
became part of gcc, so I #define'd it away to a non-colliding
name.
o Got it to all compile/link fine, but execution now generates
occasional nan's in the output. 24 nan's in the usual output.
o So I scattered some isnan()'s where I thought they'd do the
most good, along with some extra output if signalled by a nan.
For example,
Coarse Price Tree
---------nan---------nan---------nan---------nan---------nan-------
(37) (38) (39) (40) (41)
nan (0)
nan
nan 0.48621625 (1)
nan 0.50008069
nan 0.51509498 0.51001222 (2)
0.53033953 0.52437862
0.54581746 0.53987707 0.53454707 (3)
0.55560027 0.54939660
0.57155027 0.56535715 0.55977253 (4)
0.58153494 0.57508219
0.59793103 0.59147873 0.58563206 (5)
That's very helpful and suggestive, but deeper checks still didn't
isolate the "obvious" (or so I thought) problem.
o ***ONLY THEN*** did I look at man gcc for some debugging
ideas, and gave -ffast-math a try, just to see what might
happen. I was kind of hoping program might just segfault
somewhere useful, but no such luck.
o My original post didn't explain all that correctly.
o Nevertheless, James Walby suggested a good trick --
write my own isnan macro that first uses isnan, and
if that's zero then sprintf the number and strstr() the
buffer for "nan". That'll work even with -ffast-math.
o Still haven't found the problem, and haven't bothered
with -ffast-math any more, either, since it provides
no additional information, anyway.

So -ffast-math seems to behave as documented, suppressing the
isnan() signal. That's no problem with James' workaround,
but it unfortunately still didn't provide any additional helpful
debugging info to me for my particular situation.
 
K

Keith Thompson

William Hughes said:
It may depend on optimization level. If you specify
-ffinite-math-only and pass isnan a NAN there is no
expected behaviour. At low opimzation isnan(x) may
in fact determine if x is a NAN, and since the compiler
thinks it knows that x is not a NAN the compiler thinks
this is a slow way of getting 0. At higher optimizations
the compiler may choose a fast way of getting 0.

Using higher optimization levels doesn't guarantee that isnan() returns
0, but it can do so, even when the program logic otherwise implies that
the argument is a NaN.

Consider this program:

#include <stdio.h>
#include <math.h>
#include <time.h>
int main (void)
{
double x = 0.0;
if (time(NULL) > 1290000000) {
puts("setting x to NaN");
x = nan("");
}
printf("x = %g, isnan(x) = %d\n", x, isnan(x));
return 0;
}

The time() test is intended to cause the assignment to occur
without letting the optimizer know that it's certain to happen.
(time_t)1290000000 was a few hours ago. I'm making a non-portable
assumption about how time_t represents times. I could have made
it more portable using mktime(), but I didn't bother.

With "gcc -O0 -ffast-math -std=c99 c.c -lm -o c", the output is:

setting x to NaN
x = nan, isnan(x) = 1

With "gcc -O1 -ffast-math -std=c99 c.c -lm -o c", the output is:

setting x to NaN
x = 0, isnan(x) = 0

Using -ffinite-math-only rather than -ffast-math produces the same
results.

So these options *are behaving as their documentation describes
them*. The program depends on IEEE and/or ISO rules for math
functions, and the options result in incorrect output. The solution
is simple: don't use "-ffast-math" or "-ffinite-math-only" for
this program; use them only for programs that don't depend on
correct behavior for infinities and NaNs, and for which the speed
improvement is worth the loss of standard conformance. (I haven't
measured it, but I'd guess that they can be quite useful for some
programs that are numerically well-behaved.)
 
N

Nick Bowler

]
[...]
Using higher optimization levels doesn't guarantee that isnan() returns
0, but it can do so, even when the program logic otherwise implies that
the argument is a NaN.

Sorry, I didn't mean to imply that isnan was *guaranteed* to be replaced
with a constant zero (my use of the word "all" was not a good one). I
was intending to suggest that the compiler is well within its rights to
optimize the calls away, and that it will do so in some cases.

As a side note, one can elicit more reliable behaviour (I still have no
idea if we can *guarantee* a particular result) from GCC by calling its
builtins directly instead of using the macros provided by the C library
(which may or may not be implemented using GCC's builtins).
 
J

James Waldby

....
Using higher optimization levels doesn't guarantee that isnan() returns
0, but it can do so, even when the program logic otherwise implies that
the argument is a NaN. ....
#include <stdio.h>
#include <math.h>
#include <time.h>
int main (void)
{
double x = 0.0;
if (time(NULL) > 1290000000) {
puts("setting x to NaN");
x = nan("");
}
printf("x = %g, isnan(x) = %d\n", x, isnan(x)); return 0;
}

The time() test is intended to cause the assignment to occur without ....
With "gcc -O0 -ffast-math -std=c99 c.c -lm -o c", the output is:

setting x to NaN
x = nan, isnan(x) = 1

With "gcc -O1 -ffast-math -std=c99 c.c -lm -o c", the output is:

setting x to NaN
x = 0, isnan(x) = 0
[snip conclusions]

On my linux (old fedora) system with gcc 4.1.2 I was unable to replicate
your second result, ie got "x = nan, isnan(x) = 1" for both cases.

Although you didn't explicitly conclude that isnan(x) got optimized away,
that seemed to be the drift of your thoughts. Conceivably nan() got
optimized away instead of (or as well as) isnan(). Replacing the middle
lines of your code with something like following could check if so:

union {double x; long unsigned int y; } u = { 1.0 };
printf("sizeof x = %ld sizeof y = %ld\n", sizeof u.x, sizeof u.y);
printf("x = %8g = %16lx, isnan(x) = %d\n", u.x, u.y, isnan(u.x));
if (time(NULL) > 1290000000) {
puts("setting x to NaN");
u.x = nan("");
}
printf("x = %8g = %16lx, isnan(x) = %d\n", u.x, u.y, isnan(u.x));

On my system, output in both compile cases is:

sizeof x = 8 sizeof y = 8
x = 1 = 3ff0000000000000, isnan(x) = 0
setting x to NaN
x = nan = 7ff8000000000000, isnan(x) = 1
 
K

Keith Thompson

James Waldby said:
...
Using higher optimization levels doesn't guarantee that isnan() returns
0, but it can do so, even when the program logic otherwise implies that
the argument is a NaN. ...
#include <stdio.h>
#include <math.h>
#include <time.h>
int main (void)
{
double x = 0.0;
if (time(NULL) > 1290000000) {
puts("setting x to NaN");
x = nan("");
}
printf("x = %g, isnan(x) = %d\n", x, isnan(x)); return 0;
}

The time() test is intended to cause the assignment to occur without ...
With "gcc -O0 -ffast-math -std=c99 c.c -lm -o c", the output is:

setting x to NaN
x = nan, isnan(x) = 1

With "gcc -O1 -ffast-math -std=c99 c.c -lm -o c", the output is:

setting x to NaN
x = 0, isnan(x) = 0
[snip conclusions]

On my linux (old fedora) system with gcc 4.1.2 I was unable to replicate
your second result, ie got "x = nan, isnan(x) = 1" for both cases.

Although you didn't explicitly conclude that isnan(x) got optimized away,
that seemed to be the drift of your thoughts. Conceivably nan() got
optimized away instead of (or as well as) isnan(). Replacing the middle
lines of your code with something like following could check if so:

union {double x; long unsigned int y; } u = { 1.0 };
printf("sizeof x = %ld sizeof y = %ld\n", sizeof u.x, sizeof u.y);
printf("x = %8g = %16lx, isnan(x) = %d\n", u.x, u.y, isnan(u.x));
if (time(NULL) > 1290000000) {
puts("setting x to NaN");
u.x = nan("");
}
printf("x = %8g = %16lx, isnan(x) = %d\n", u.x, u.y, isnan(u.x));

On my system, output in both compile cases is:

sizeof x = 8 sizeof y = 8
x = 1 = 3ff0000000000000, isnan(x) = 0
setting x to NaN
x = nan = 7ff8000000000000, isnan(x) = 1

Here's the program with your suggested changes. (I used unsigned long
long rather than unsigned long, which is only 32 bits on my system; I
also fixed a couple of other things):

#include <stdio.h>
#include <math.h>
#include <time.h>
int main (void)
{
union { double x; long long unsigned int y; } u = { 1.0 };
printf("sizeof u.x = %zu sizeof u.y = %zu\n",
sizeof u.x, sizeof u.y);
printf("u.x = %8g, u.y = %16llx, isnan(u.x) = %d\n",
u.x, u.y, isnan(u.x));
if (time(NULL) > 1290000000) {
puts("setting u.x to NaN");
u.x = nan("");
}
printf("u.x = %8g, u.y = %16llx, isnan(u.x) = %d\n",
u.x, u.y, isnan(u.x));

return 0;
}

With "-O0 -ffinite-math-only" and "-O1 -ffinite-math-only", the output is:

sizeof u.x = 8 sizeof u.y = 8
u.x = 1, u.y = 3ff0000000000000, isnan(u.x) = 0
setting u.x to NaN
u.x = nan, u.y = 7ff8000000000000, isnan(u.x) = 1

With "-O2 -ffinite-math-only" and "-O3 -ffinite-math-only", the output is:

sizeof u.x = 8 sizeof u.y = 8
u.x = 1, u.y = 3ff0000000000000, isnan(u.x) = 0
setting u.x to NaN
u.x = 1, u.y = 7ff8000000000000, isnan(u.x) = 0
 
N

Nobody

Reading this, I understand that the compiler "assumes that arguments and
results are not NANs. Nowhere is said that a function call to isnan()
will be IGNORED.

Which amounts to the same thing. If you don't understand this, you should
choose a different field of endeavour.

If the compiler assumes that values are never NaN, it can optimise isnan()
to constant zero. The usual point of making assumptions is to enable such
optimisations.

If isnan() actually did something, the compiler *wouldn't* be assuming
that values are never NaN, would it?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top