Bug 10417

Summary: Inconsistent results in floating point comparison.
Product: gcc Reporter: csk
Component: otherAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: normal CC: csk, ebotcazou, gcc-bugs, timothyprince
Priority: P3    
Version: 3.2.1   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description csk 2003-04-15 19:06:01 UTC
Witness the following short program:

---------------------
#include <stdio.h>
#include <stdlib.h>

int main( int argc, char ** argv )
{
    double x = atof( argv[1] );
    double d = x*x;

    printf( "%d\n", (x*x<d) );
    return 0;
}
-----------------------

Ideally, this program should always print 0, since a number shouldn't be strictly less than itself.  When compiled without optimization, the program will print 0 or 1 depending on the input (I get 0.3 --> 0, 0.4 --> 1, for instance).

Now I understand that floating point numbers are far from ideal, and that this behaviour might not be a bug.  Still, I would love to be able to characterize for which numbers the program will print 0 or 1.  Any thoughts?

Moreover, the program always prints a 0 when compiled with optimization.  This inconsistency relative to the unoptimized version might indeed constitute a bug.

Anyway, it's not totally clear to me that this is a bug.  But either way, I'd love for someone in GCC land to explain to me what's going on.  Thanks.

p.s. The bug remains if you switch from doubles to floats.   
     And I have a slightly larger program that exhibits the inconsistent behaviour when optimization is turned _on_.

Release:
3.2.1, 2.95.4

Environment:
Debian Woody, Pentium IV
Comment 1 timothyprince 2003-04-15 20:36:32 UTC
From: Tim Prince <timothyprince@sbcglobal.net>
To: csk@mud.cgl.uwaterloo.ca, gcc-gnats@gcc.gnu.org
Cc:  
Subject: Re: other/10417: Inconsistent results in floating point comparison.
Date: Tue, 15 Apr 2003 20:36:32 -0700

 On Tuesday 15 April 2003 12:01, csk@mud.cgl.uwaterloo.ca wrote:
 > >Number:         10417
 > >Category:       other
 > >Synopsis:       Inconsistent results in floating point comparison.
 
 > >Environment:
 >
 > Debian Woody, Pentium IV
 >
 > >Description:
 >
 > Witness the following short program:
 >
 > ---------------------
 > #include <stdio.h>
 > #include <stdlib.h>
 >
 > int main( int argc, char ** argv )
 > {
 >     double x = atof( argv[1] );
 >     double d = x*x;
 >
 >     printf( "%d\n", (x*x<d) );
 >     return 0;
 > }
 > -----------------------
 >
 > Ideally, this program should always print 0, since a number shouldn't be
 > strictly less than itself.  When compiled without optimization, the program
 > will print 0 or 1 depending on the input (I get 0.3 --> 0, 0.4 --> 1, for
 > instance).
 >
 > Now I understand that floating point numbers are far from ideal, and that
 > this behaviour might not be a bug.  Still, I would love to be able to
 > characterize for which numbers the program will print 0 or 1.  Any
 > thoughts?
 If you ask the compiler to generate x87 code (the probable default for your 
 configuration), it could interpret the expression as
 (long double)x*x < d;
 so the expression would be 1 every time d has been rounded up.
 If you use the command
 gcc -march=pentium4 -mfpmath=sse *.c
 as you might normally do for a P4, I doubt you could get the results you 
 mention. 
 >
 > Moreover, the program always prints a 0 when compiled with optimization. 
 > This inconsistency relative to the unoptimized version might indeed
 > constitute a bug.
 I can't reproduce this, unless I tell the compiler to generate x87 code. As I 
 don't "always" do that, I am not reproducing your claim. 
 >
 >
 -- 
 Tim Prince
 
Comment 2 Eric Botcazou 2003-04-16 07:30:46 UTC
State-Changed-From-To: open->closed
State-Changed-Why: Not a bug. On x86, when optimizing, floating point values
    may be kept in FP registers when doing comparisons with
    others stored in memory. Now x86 FP registers have
    extra-precision over a 'double', which may invalid
    a comparison. Compile your code with '-ffloat-store'
    if it relies on exact IEEE floating-point semantics.
Comment 3 csk 2003-04-16 10:40:02 UTC
From: "Craig S. Kaplan" <csk@cgl.uwaterloo.ca>
To: tprince@computer.org
Cc: gcc-gnats@gcc.gnu.org
Subject: Re: other/10417: Inconsistent results in floating point comparison.
Date: Wed, 16 Apr 2003 10:40:02 -0400 (EDT)

 Tim,
 
 Thanks for the insights.  If you've got the time, I have some
 additional comments below.
 
 > > ---------------------
 > > #include <stdio.h>
 > > #include <stdlib.h>
 > >
 > > int main( int argc, char ** argv )
 > > {
 > >     double x = atof( argv[1] );
 > >     double d = x*x;
 > >
 > >     printf( "%d\n", (x*x<d) );
 > >     return 0;
 > > }
 > > -----------------------
 > >
 > > Ideally, this program should always print 0, since a number shouldn't be
 > > strictly less than itself.  When compiled without optimization, the program
 > > will print 0 or 1 depending on the input (I get 0.3 --> 0, 0.4 --> 1, for
 > > instance).
 > >
 > > Now I understand that floating point numbers are far from ideal, and that
 > > this behaviour might not be a bug.  Still, I would love to be able to
 > > characterize for which numbers the program will print 0 or 1.  Any
 > > thoughts?
 > If you ask the compiler to generate x87 code (the probable default for your
 > configuration), it could interpret the expression as
 > (long double)x*x < d;
 > so the expression would be 1 every time d has been rounded up.
 > If you use the command
 > gcc -march=pentium4 -mfpmath=sse *.c
 > as you might normally do for a P4, I doubt you could get the results you
 > mention.
 
 Surprisingly, I _do_ still get the strange behaviour with those
 switches.
 
 But I am beginning to understand where the behaviour may be coming
 from, based on your comments and the comments of another maintainer
 who emailed me (ebotcazou).  When d is stored in a variable, some
 extra bits of precision that existed in the FPU are discarded.  Now,
 you seem to suggest that the way the FPU does this is to _round_ d
 (rather than just truncating).  My simple program seems to generate
 random output for different floats, but actually I'm just seeing the
 FPU's rounding semantics -- its decision whether to round up or down.
 Does that sound believable to you?
 
 Of course, if this is the case, we shouldn't expect -mfpmath=sse
 to solve the 'problem' -- we're still rounding x*x to store the
 answer in d.  The other maintainer suggested that I needed
 '-ffloat-store' to guarantee strict IEEE semantics.  I tried that
 switch, and it seemed to make the behaviour a little more consistent.
 It does remove the randomness from the large program I'm working
 on, but amazingly it doesn't fix my toy example.  Using gcc 3.2.1,
 the only way I can make the short program above output 0 consistently
 is to compile it -O2.  The -ffloat-store, -march=pentium4, and
 -mfpmath=sse switches don't seem to do anything.  Any thoughts on
 why I'm not seeing a difference here?
 
 Thanks again.
 
 -- 
 Craig S. Kaplan                     ``Evolution drives a steamroller,
 School of Computer Science          disguised as a stationary bike.''
 University of Waterloo              http://www.cgl.uwaterloo.ca/~csk/
Comment 4 Andrew Pinski 2003-07-01 18:46:30 UTC
Reopening bug to mark bug as a dup of bug 323 so ...
Comment 5 Andrew Pinski 2003-07-01 18:46:51 UTC
that the number of dup goes up.

*** This bug has been marked as a duplicate of 323 ***