Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

isnan or isntnan?

6 views
Skip to first unread message

JohnF

unread,
Nov 13, 2010, 11:48:42 AM11/13/10
to
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,
--
John Forkosh ( mailto: j...@f.com where j=john and f=forkosh )

Eric Sosman

unread,
Nov 13, 2010, 4:48:45 PM11/13/10
to
On 11/13/2010 11:48 AM, 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 ...

--
Eric Sosman
eso...@ieee-dot-org.invalid

James Waldby

unread,
Nov 13, 2010, 8:20:46 PM11/13/10
to
On Sat, 13 Nov 2010 16:48:42 +0000, JohnF wrote:

> 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[i].

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.

--
jiw

JohnF

unread,
Nov 14, 2010, 5:06:23 PM11/14/10
to

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.

Alan Curry

unread,
Nov 14, 2010, 5:51:39 PM11/14/10
to
In article <ibmfh9$foe$1...@reader1.panix.com>,

JohnF <jo...@please.see.sig.for.email.com> 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

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.

--
Alan Curry

Tim Prince

unread,
Nov 14, 2010, 8:45:47 PM11/14/10
to
-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.

--
Tim Prince

JohnF

unread,
Nov 14, 2010, 9:39:29 PM11/14/10
to

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.

JohnF

unread,
Nov 14, 2010, 9:48:48 PM11/14/10
to

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.)

Nick Bowler

unread,
Nov 16, 2010, 2:04:00 PM11/16/10
to
On Sat, 13 Nov 2010 16:48:42 +0000, JohnF wrote:
> 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.

jacob navia

unread,
Nov 16, 2010, 2:45:59 PM11/16/10
to
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.

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.

Keith Thompson

unread,
Nov 16, 2010, 4:36:52 PM11/16/10
to

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?

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

jacob navia

unread,
Nov 17, 2010, 3:57:18 AM11/17/10
to
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?


William Hughes

unread,
Nov 17, 2010, 11:36:13 AM11/17/10
to

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


> --
> Keith Thompson (The_Other_Keith) ks...@mib.org  <http://www.ghoti.net/~kst>
> Nokia
> "We must do something.  This is something.  Therefore, we must do this."

>     -- Antony Jay and Jonathan Lynn, "Yes Minister"- Hide quoted text -
>
> - Show quoted text -

Keith Thompson

unread,
Nov 17, 2010, 11:48:32 AM11/17/10
to

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.)

JohnF

unread,
Nov 17, 2010, 1:05:07 PM11/17/10
to
Keith Thompson <ks...@mib.org> wrote:
>
> 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.

Keith Thompson

unread,
Nov 17, 2010, 2:04:37 PM11/17/10
to
William Hughes <wpih...@hotmail.com> writes:
> On Nov 16, 5:36 pm, Keith Thompson <ks...@mib.org> wrote:
[...]

>> 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.

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.)

Nick Bowler

unread,
Nov 17, 2010, 2:29:14 PM11/17/10
to
On Wed, 17 Nov 2010 11:04:37 -0800, Keith Thompson wrote:
[...]

>> On Nov 16, 5:36 pm, Keith Thompson <ks...@mib.org> wrote:
>>> 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?
[...]

> 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).

James Waldby

unread,
Nov 17, 2010, 3:16:14 PM11/17/10
to
On Wed, 17 Nov 2010 11:04:37 -0800, Keith Thompson wrote:
> William Hughes writes:
>> On Nov 16, 5:36 pm, Keith Thompson wrote:
...

>> It may depend on optimization level. If you specify -ffinite-math-only
>> and pass isnan a NAN there is no expected behaviour. At low optimization

>> isnan(x) may in fact determine if x is a NAN, and since the compiler
...

> 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

--
jiw

Keith Thompson

unread,
Nov 17, 2010, 3:44:50 PM11/17/10
to

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

Nobody

unread,
Nov 19, 2010, 1:42:34 PM11/19/10
to
On Tue, 16 Nov 2010 20:45:59 +0100, jacob navia wrote:

> 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?

Nobody

unread,
Nov 19, 2010, 1:45:18 PM11/19/10
to
On Wed, 17 Nov 2010 09:57:18 +0100, jacob navia wrote:

> The option given by the user was
>
> -ffast-math
>
> and THAT option turns on IMPLICITELY finite-math

Sure. What did you expect it to do?

Or is there some law against making one option a superset of another?

-fast-math enables ... fast math, i.e. certain approximations which are
faster but less accurate. Assuming finiteness is one of them. Assuming
e.g. x/y = x*(1/y) is another.

At least you get the choice (Borland C would make the latter optimisation
regardless of switches). If you randomly enable optimisations without
reading the documentation, you deserve whatever you get.

jacob navia

unread,
Nov 21, 2010, 2:55:02 PM11/21/10
to
Le 19/11/10 19:42, Nobody a écrit :

> On Tue, 16 Nov 2010 20:45:59 +0100, jacob navia wrote:
>
>> 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.
>

The idea of not using gnu stuff doesn'y even cross your mind.

It is a very good alternative really. Just say NO.

> If the compiler assumes that values are never NaN, it can optimise isnan()
> to constant zero.

The fact that isnan() is called should tell anyone with a small brain
that that assumption is NOT shared by the guy who wrote the program,
that considers that a NAN could really happen there.

But WHO CARES about correct results?

Important is only that results are delivered FAST.


< The usual point of making assumptions is to enable such
> optimisations.
>

I could conceive that making those assumptions about data manipulated by
the compiler could be (maybe) OK. But just "pessimizing" away a call
to a function?

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

Sure. If I would have read the fine print I wouldn't have bought that
dammed appliance. Obviously it was my fault.

Well, I decided never to come to that store again.

Here is the same. Just say NO to GNU.

:-)


Nobody

unread,
Nov 21, 2010, 3:56:32 PM11/21/10
to
On Sun, 21 Nov 2010 20:55:02 +0100, jacob navia wrote:

>> If the compiler assumes that values are never NaN, it can optimise isnan()
>> to constant zero.
>
> The fact that isnan() is called should tell anyone with a small brain
> that that assumption is NOT shared by the guy who wrote the program,
> that considers that a NAN could really happen there.
>
> But WHO CARES about correct results?

Not someone who uses -ffast-math or similar.

> Important is only that results are delivered FAST.

If that was true, -fast-math would be enabled by default. It isn't. It
isn't even enabled by any level of -O.

If you ask for speed over correctness, you get it. If you don't want it,
don't ask for it.

> < The usual point of making assumptions is to enable such
>> optimisations.
>>
>
> I could conceive that making those assumptions about data manipulated by
> the compiler could be (maybe) OK. But just "pessimizing" away a call
> to a function?

You're assuming that it's a call. I would assume that it's either a
macro or a built-in, and it gets optimised away because the code which
implements it is subject to the same assumptions of finiteness as any
other code (when -finite-math-only is used). By the time that it gets
optimised away, the compiler may not even know that the code originated
from isnan().

Even if the compiler left the call in, there's no guarantee that the
argument would actually be NaN when it ordinarily should be.

It's similar to the situation where if you do:
void foo(int *p)
...
int x = *p;
if (p) bar();

the compiler may optimise "if (p) bar();" to simply "bar();". If p happens
to be null, the code has invoked undefined behaviour by dereferencing it,
so the compiler is free to choose to execute bar() as its preferred
form of undefined behaviour.

>> If isnan() actually did something, the compiler *wouldn't* be assuming
>> that values are never NaN, would it?
>
> Sure. If I would have read the fine print I wouldn't have bought that
> dammed appliance. Obviously it was my fault.

Well, it does very much look as if you're trying to blame the compiler for
your own shortcomings. Most modern compilers have similar options; I guess
that they're all broken too? IMHO, a compiler which /didn't/ provide such
an option would be defective.

On some architectures, non-finite floating-point can be quite expensive
E.g. the Alpha's FPU doesn't support NaN or infinity; on this
architecture, you have to use -mieee-fp if you want the compiler to insert
software support for infinity and NaN. Note: the C standard doesn't
actually require an implementation to support inifinity or NaN.

Even on architectures which support NaN in hardware, foregoing
optimisations which are valid for all finite values may adversely
affect performance, and often for no good reason. NaN is often just as
much a "wrong answer" as any other value (it typically arises from
numerically unstable calculations).

Nick

unread,
Nov 21, 2010, 4:21:09 PM11/21/10
to
jacob navia <ja...@spamsink.net> writes:

> Sure. If I would have read the fine print I wouldn't have bought that
> dammed appliance. Obviously it was my fault.
>
> Well, I decided never to come to that store again.

You seem to be arguing that if, instead of buying a device that could
work on a variety of voltages, you instead specifically asked to have
one imported from the US, and then complained that it blew up on
the European mains.

> Here is the same. Just say NO to GNU.
>
> :-)

I know you write your own compiler. And half the time you talk sense
about it. But the other half you come across a completely bonkers - did
you know that?
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk

Seebs

unread,
Nov 21, 2010, 6:22:58 PM11/21/10
to
On 2010-11-21, jacob navia <ja...@spamsink.net> wrote:
> The idea of not using gnu stuff doesn'y even cross your mind.

It's not an option for me, and hasn't been for years. Furthermore,
fundamentally, I don't see anything wrong with the GNU stuff in this case;
they offer a documented way to do a particular thing, and it works as
documented.

>> If the compiler assumes that values are never NaN, it can optimise isnan()
>> to constant zero.

> The fact that isnan() is called should tell anyone with a small brain
> that that assumption is NOT shared by the guy who wrote the program,
> that considers that a NAN could really happen there.

> But WHO CARES about correct results?

Not someone who specifically requests that the compiler generate faster code
which optimizes out some tests.

> Important is only that results are delivered FAST.

That is, indeed, what was communicated by the choice of compiler options.

> I could conceive that making those assumptions about data manipulated by
> the compiler could be (maybe) OK. But just "pessimizing" away a call
> to a function?

Uh, yeah. Happens all the time. Do you honestly think that most compilers
generate a function call for strlen("foo")?

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

Keith Thompson

unread,
Nov 22, 2010, 2:20:06 AM11/22/10
to
jacob navia <ja...@spamsink.net> writes:
> Le 19/11/10 19:42, Nobody a écrit :
>> On Tue, 16 Nov 2010 20:45:59 +0100, jacob navia wrote:
>>> 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.
>>
>
> The idea of not using gnu stuff doesn'y even cross your mind.

In this case, the idea of not using -ffast-math or -ffinite-math-only
accomplishes exactly the same thing.

> It is a very good alternative really. Just say NO.
>
>> If the compiler assumes that values are never NaN, it can optimise isnan()
>> to constant zero.
>
> The fact that isnan() is called should tell anyone with a small brain
> that that assumption is NOT shared by the guy who wrote the program,
> that considers that a NAN could really happen there.

Then the program shouldn't have been compiled with -ffast-math
or -ffinite-math-only.

> But WHO CARES about correct results?
>
> Important is only that results are delivered FAST.

gcc offers you an *option* to obtain fast results at the expense
of correctness in some cases. For some code, that might be a good
tradeoff. You don't have to take advantage of that option if you
don't want to. It isn't enabled by default. Would gcc be a better
compiler if the option were removed? Fine, then write a wrapper
that discards any occurrence of -ffast-math or -ffinite-math-only
on the command line. Problem solved.

> < The usual point of making assumptions is to enable such
>> optimisations.
>>
>
> I could conceive that making those assumptions about data manipulated by
> the compiler could be (maybe) OK. But just "pessimizing" away a call
> to a function?
>
>> If isnan() actually did something, the compiler *wouldn't* be assuming
>> that values are never NaN, would it?
>>
>
> Sure. If I would have read the fine print I wouldn't have bought that
> dammed appliance. Obviously it was my fault.

If you didn't read the fine print, you wouldn't know about those
options, would you?

[...]

jacob navia

unread,
Nov 22, 2010, 3:56:02 AM11/22/10
to
Le 22/11/10 00:22, Seebs a �crit :

>> I could conceive that making those assumptions about data manipulated by
>> the compiler could be (maybe) OK. But just "pessimizing" away a call
>> to a function?
>
> Uh, yeah. Happens all the time. Do you honestly think that most compilers
> generate a function call for strlen("foo")?
>

So WHAT?

strlen("foo") can give only ONE result. isnan() surely NOT, unless
you apply bad specs to the limit of nonsense.

Finite math can be assumed. Optimizing away a call to isnan is another
thing.

Noob

unread,
Nov 22, 2010, 8:46:55 AM11/22/10
to
Jacob Navia wrote:

> The idea of not using gnu stuff doesn't even cross your mind.


> It is a very good alternative really. Just say NO.

Your contempt for GCC is entertaining, in a weird way.

Perhaps you should contribute to LLVM? (Scratch that. It's written in C++)

William Hughes

unread,
Nov 22, 2010, 9:43:27 AM11/22/10
to
On Nov 22, 4:56 am, jacob navia <ja...@spamsink.net> wrote:

> Finite math can be assumed. Optimizing away a call to isnan is another
> thing.

Why. You told the compiler what the answer to isnan(x) should be.
It used that answer. Remember "if you lie to the compiler it will get
it's revenge". And I can think of a case where depending on where I
got
the data, I might or might not be sure that the program will not
get a nan. If so, I might want to have a version of the program
compiled with -ffinite-math-only which would only be safe to use on
certain
data sets. So compiling code that contains isnan with -ffinite-math-
only
can be quite reasonable.

As a general principle, choosing speed over safety is a bad idea.
However, in some cases it can be justified.

- William Hughes

Seebs

unread,
Nov 22, 2010, 2:21:53 PM11/22/10
to
On 2010-11-22, jacob navia <ja...@spamsink.net> wrote:
>> Uh, yeah. Happens all the time. Do you honestly think that most compilers
>> generate a function call for strlen("foo")?

> So WHAT?

So we've established that compilers are allowed to optimize away calls
that they know produce a specific value.

> strlen("foo") can give only ONE result.

Actually, it can in fact give more than one, for some reasonably common
cases of undefined behavior. (Consider a string-constant-folding compiler,
and someone concatenating onto the "foo" constant.)

But! Here's the thing: If the compiler is allowed to assume that
there are no NaNs, then isnan(x) can give only ONE result -- 0. Because
x is not a NaN, *by definition*.

> Finite math can be assumed. Optimizing away a call to isnan is another
> thing.

No. If you are assuming finite math, isnan() must always return 0, and
failure to do so means the assumption was violated.

Another way to look at it: -ffinite-math declares any operation which
can produce an infinity or NaN to be undefined behavior. :)

Tim Rentsch

unread,
Nov 22, 2010, 6:26:24 PM11/22/10
to
jacob navia <ja...@spamsink.net> writes:

> Le 16/11/10 20:04, Nick Bowler a @C3{A9}crit :


>> On Sat, 13 Nov 2010 16:48:42 +0000, JohnF wrote:
>>> 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.
>>
>
>
> !!!!!!!!!!!!!!!!!!!!!!!!
>
> This is one of the worst bugs of gcc I have ever seen.

> [snip elaboration]

Why does it bother you so much that gcc has an option
supporting a non-conforming extension? Doesn't lccwin
have options that support non-conforming extensions?

Nobody

unread,
Nov 22, 2010, 8:24:16 PM11/22/10
to
On Mon, 22 Nov 2010 09:56:02 +0100, jacob navia wrote:

> Finite math can be assumed. Optimizing away a call to isnan is another
> thing.

No. It. Isn't.

For a start, the standard explicitly states that isnan() is a macro. Once
the preprocessor has done its business, the compiler may not even
know that there *was* a call to isnan().

Beyond that, once a compiler starts optimising, there's a good chance that
the expression which was being passed to isnan() doesn't actually exist in
any shape or form.

Have you ever tried debugging optimised code? If you do, you'll find that
lots of variables no longer exist, entire statements no longer exist.
Because the compiler basically treats the original code as a specification
and then generates entirely different code whose only resemblance to the
original is that it produces the same result.

If the compiler was obliged to call the same functions in the same
sequence, there wouldn't be much point in enabling optimisation in the
first place.

Keith Thompson

unread,
Nov 22, 2010, 9:54:32 PM11/22/10
to

Here's a better analogy.

You buy a coffee machine. When used in the normal manner, it makes
good coffee and works in a reasonably intuitive way.

Somewhere in the coffee machine's manual, there's a paragraph that
says that, if you really want to, you can remove three screws on the
base, open up a panel, and flip a switch to change the setting on
the heater. By doing so, you can make your coffee 10% faster, but
you risk starting a fire if you don't have just the required ratio
of coffee beans and water. (If you don't flip the switch, a safety
feature turns off the heater before that can happen, but it can't
act quickly enough at the higher setting.) And the ratio is such
that you can't make really strong coffee with the switch flipped.

Flipping the switch gives you better speed at the expense of reduced
functionality and greater risk of malfunction. It's just the thing
for those coffee brewing speed competitions all the kids are into
these days.

There is no reasonable way you'd even know about the switch if you
didn't read the manual, you couldn't flip it accidentally if you
didn't know about it, and if you did read the manual you'd know about
the risks. You'd also know that the bean/water ratio requirement
means you can't make really strong coffee if the switch is enabled,
and you happen to like your coffee really string. (No cream, no sugar,
just a sprinkling of NaNs.)

What you seem to be doing is buying this coffee maker with the
intention of making really strong coffee, and complaining that
it's defective because it doesn't work the way you want it to if
you flip the switch.

Except that you didn't actually buy the coffee maker (even though
it's free); you're just complaining about it because somebody else
(who had no problem with it) described the switch's behavior.
(I won't assume that this has anything to do with the fact that
you manufacture a competitive coffee maker.)

What exactly was your problem again?

Tom St Denis

unread,
Nov 24, 2010, 1:39:20 PM11/24/10
to

Why not just not pass -ffast-math if you don't want this behaviour?

-ffast-math is an OPTIMIZATION not a requisite to compile code.

Tom

Noob

unread,
Nov 25, 2010, 3:51:36 AM11/25/10
to
Tom St Denis wrote:

> Why not just not pass -ffast-math if you don't want this behaviour?
>
> -ffast-math is an OPTIMIZATION not a requisite to compile code.

You see, the problem is, if he were to do that, he'd have to give up
a perfectly "good" excuse to diss GCC.

0 new messages