optimization/9654: extra-precision fp comparisons are less accurate

richard@wetafx.co.nz richard@wetafx.co.nz
Tue Feb 11 04:06:00 GMT 2003


>Number:         9654
>Category:       optimization
>Synopsis:       extra-precision fp comparisons are less accurate
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          wrong-code
>Submitter-Id:   net
>Arrival-Date:   Tue Feb 11 04:06:01 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     richard@wetafx.co.nz
>Release:        g++3 (GCC) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)
>Organization:
>Environment:
Linux 2.4.18-xfssmp #1 SMP i686
>Description:
//////////bug.cc:
#include <math.h>

double s(double t) throw()
{
  double d = 0.75+t;
  double o = d < 1.0 ? acos(d) : 1.0/67108864.0;
  return sin(o*0.5)/sin(o);
}

int main(void)
{
  return isnan(s(0.25-1.0/18014398509481984.0));
}
//////////GNUmakefile:
bug: bug.cc; g++3 -O1 -o bug bug.cc -lm 
>How-To-Repeat:
With the two specified files, use gmake to build.

With optimization turned on, the comparison between
d and 1.0 on line 6 succeeds when it should fail.

Essentially, the value that is computed for d is
still in an fp register (with extra precision)
when it is compared with 1.0.  That value is less
then 1.0, but by the time it is actually converted
to a double, it gets rounded to 1.0.  Thus, the
situation that the comparison is trying to trap
does not get trapped.

Corresponding problems also appear with floats.

This problem also shows up with:

gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
gcc version 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.2)
>Fix:
There are various ways to work around this.  Obviously,
the code can be changed slightly so that the intended
effect is correct.  However, other similar problems may
be far more subtle than generating a NaN.

The problem can be avoid using the -ffloat-store option,
but that has detrimental effects on performance.

It would be great if floating point comparisons (float
or double) were guaranteed to be on values at the
precision specified by the source code, and not on
values with extra precision.

If this cannot be the default, perhaps there should
at least be an option like -ffloat-compare so that
there is a mid-ground between the performance hit of
using -ffloat-store and the reliability hit of not
using -ffloat-store.
>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the Gcc-bugs mailing list