www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1994/11/08/00:46:44

Date: Tue, 08 Nov 1994 11:34:16 +1100
From: Bill Metzenthen <BILLM AT vaxc DOT cc DOT monash DOT edu DOT au>
Subject: Re: 2.4/3-2.4/3!=0
To: djgpp AT sun DOT soe DOT clarkson DOT edu

From:	IN%"cspt AT ludens DOT elte DOT hu"  "Peter Csizmadia"  8-NOV-1994 00:51:42.17
To:	IN%"djgpp AT sun DOT soe DOT clarkson DOT edu"
CC:	
Subj:	RE: 2.4/3-2.4/3!=0

Date: Mon, 07 Nov 1994 11:42:24 +0100
Subject: Re: 2.4/3-2.4/3!=0

Peter Csizmadia "cspt AT ludens DOT elte DOT hu" writes:

> 	I just received Bill Metzenthen's and Eli Zaretskii's messages.
> Their explanation for the first bug is acceptable. Bill partly explained the 
> anomalous behaviour of the second program, but the bug is still unexplained.
> I simpified the program:
>
> #include <stdlib.h>
> main(int argc, char* argv[]) {
>    double a = atof(argv[1]);
>    double x = a/sqrt(1+a*a);
>    printf("1-x=%le\n", 1.0-x);
>    printf("x%s1\n", (x==1.0)? "==":"!="); !!! simple comparision !!!
>    printf("1-x=%le\n", 1.0-x);
> }
>
> gcc g.c -o g -O1
> go32 g 10
> 1-x=4.96280979001086e-03
> x!=1
> 1-x=4.96280979001096e-03  !!! IT CHANGED !!!
[stuff deleted]
> 	So my question is:
> Is it possible to compile this program with -O1 (and -ffloat-store), but 
> without this bug? 
> If it is, which optimization flag must I switch off after -O1?

Ok, it wasn't clear to me that this particular point (the apparent
influence of the comparison) was worrying you. I suppose that it might
not be obvious, but the behaviour here is really quite simple and not
due to any bug in gcc.

You need to recall that a C compiler is allowed to keep stuff in
registers.  On an 80x86 machine, floating point registers have 64 bit
precision.  In the program above, the variables x and a can be kept in
registers until the printf() is called.  With the 80x86 version of
gcc, functions assume that all floating point registers are available
for local use.  This means that whenever a function is called, it must
be assumed that any stuff which is in floating point registers might
get clobbered.  In particular, in the above program the variable 'x'
must be saved in some other location before the first printf() is
called.  gcc does this by placing 'x' in a 53 bit precision location
in RAM.

I hope that it is clear now that the first printf() is asked to print
the results of a 64 bit precision computation (remember that the FPU
is set by go32 to produce 64 bit precision results), where 'x' has
been computed to 64 bit precision, while the third printf() is asked
to print the results of a computation where all quantities have 53 bit
precision.  The comparison will of course also be dealing with a 53
bit precision value for 'x'.

The bug is really with your program.  It comes back to that golden
rule of floating point computations - (almost) never write code which
relies upon exact or "near exact" matches.  There are just too many
ways in which things can break, these postings have not covered all
of the possibilities...

There may be some way to get gcc to work around your bug, but it
really would be better to re-write your code.

I hope this helps.


--Bill

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019