Bug 6900

Summary: Floating point behaviour of gcc on pentium
Product: gcc Reporter: 36876
Component: cAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: normal CC: ehrhardt, gcc-bugs
Priority: P3 Keywords: wrong-code
Version: 3.1   
Target Milestone: ---   
Host: i386-linux Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description 36876 2002-06-01 14:06:00 UTC
[ Reported to the Debian BTS as report #36876.
  Please CC 36876@bugs.debian.org on replies.
  Log of report can be found at http://bugs.debian.org/36876 ]
	

The following program gives erratic/correct answers under different
conditions. The program is self explanatory.

The expected behaviour is to get the value of the variable 'q' to equal the
value of the variable 'shift' . Erratic behaviour refers to deviation from
this equality. The deviation can be controlled by increasing/decreasing the
value of 'factor' . The variable take GENERIC values.

The expected behaviour is seen on SGI and SPARC machines with their native
compilers and also with gcc (2.7x), with or without optimization.

On pentium with gcc/egcs the following happens:

Without optimization:	only those x which are powers of 2 give q = shift.
With optimization:	all give q = shift.

The deviations are NOT an artifact of printf formats. If subsequents
iterations are done with further code, these deviations actually get
amplified, and thus are genuine. In a non trivial code, this uncontrolled
error accumulation is a disaster.

While it is true that beyond 15 decimal places, one has garbage bits in the
internal representation, a suitable round-off/truncation etc should discard
these bits correctly and consistantly for generic values. (Other platforms
mentioned above seem to take care of this so also optimization on pentium
platform.)

In another context, with a somewhat different program, the expected behaviour
resulted WITH-OUT optimization but WITH optimization, the behaviour was
erratic.

--------------------------------------------------------
PLEASE ADVISE.
	-G. Date (shyam@imsc.ernet.in)
--------------------------------------------------------

/*---------------------------------------------------------------------*/
# include <stdio.h>

main(argc, argv)
int argc;
char **argv ;

{
	double q, q0, x, factor, shift;

	factor = 100000000.000001L ; 	/* Choose any typical fraction */
	shift = 0.0L ;

	for(x = 0.0L; x < 257.0L; x = x + 1.0L )	{
		q0 = (factor)*x ;
		q =  q0 - factor*x + shift ;
		if( q == shift )
			printf(" TRUE:\t%20.8E%20.8E%20.8E\n", x, q0, q);
		else		
			printf("FALSE:\t%20.8E%20.8E%20.8E\n", x, q0, q);
	}
}

/*---------------------------------------------------------------------*/

Tim Prince commented:

report [case where an assignment sometimes rounds off to declared 
precision, sometimes not, according to chosen level of optimization]

               q0 = (factor)*x ;
                q =  q0 - factor*x + shift ;


Both egcs-2.96 and gcc-2.95.2 exhibit the reported behavior, where q0 is 
rounded to double when not optimized, so that q0 - factor*x is non-zero.  
When optimized, the same expression turns up zero.  From my personal point of 
view, I might expect the small change

                q =  q0 - (double)(factor*x) + shift ;

to make a difference, but it does not.

BTW, it is even more difficult to predict the result of this when running on 
machines without normal extended precision but with a multiply-accumulate 
instruction which does not round off between multiplication and subtraction.  
I assume that the C9X draft shows the committee's consensus that should be 
modified with the new math library functions if one wishes to produce 
predictable results in future versions of C in such a case.  

Tim
tprince@computer.org

Release:
3.1 (Debian) (Debian unstable)

Environment:
System: Debian GNU/Linux (unstable)
Architecture: i686
	
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed
|/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
||/ Name           Version        Description
+++-==============-==============-============================================
ii  gcc-3.1        3.1-2          The GNU C compiler.
ii  binutils       2.12.90.0.7-1  The GNU assembler, linker and binary utiliti
ii  libc6          2.2.5-6        GNU C Library: Shared libraries and Timezone
host: i386-linux
configured with: /mnt/data/gcc-3.1/gcc-3.1-3.1ds2/src/configure -v --enable-languages=c,c++,java,f77,proto,objc,ada --prefix=/usr --mandir=$\(prefix\)/share/man --infodir=$\(prefix\)/share/info --with-gxx-include-dir=$\(prefix\)/include/g++-v3-3.1 --enable-shared --with-system-zlib --enable-long-long --enable-nls --without-included-gettext --enable-clocale=gnu --enable-threads=posix --enable-java-gc=boehm --enable-objc-gc i386-linux
Comment 1 Wolfgang Bangerth 2002-12-04 07:01:59 UTC
State-Changed-From-To: open->closed
State-Changed-Why: Christian explained why.
Comment 2 Christian Ehrhardt 2002-12-04 15:51:45 UTC
From: "Christian Ehrhardt" <ehrhardt@mathematik.uni-ulm.de>
To: gcc-gnats@gcc.gnu.org, gcc-prs@gcc.gnu.org, tprince@computer.org,
  sure@imsc.ernet.in, gcc-bugs@gcc.gnu.org, nobody@gcc.gnu.org,
  36876@bugs.debian.org, shyam@imsc.ernet.in
Cc:  
Subject: Re: c/6900: Floating point behaviour of gcc on pentium
Date: Wed, 4 Dec 2002 15:51:45 +0100

 Hi,
 
 This is not a bug. Comparing floating point numbers with == may yield
 unexpected results due to rounding errors. Someone please close this PR.
 
    regards  Christian
 
 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=6900
 
Comment 3 Andrew Pinski 2003-07-01 18:45:42 UTC
Reopening bug to mark bug as a dup of bug 323 so ...
Comment 4 Andrew Pinski 2003-07-01 18:46:05 UTC
that the number of dups goes up.

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