This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: egcs 1.0.3 bug in comparing doubles


Olaf Lenzmann wrote:
> 
> Hello!
> 
> I encountered the following SEVERE bug w/ egcs (gcc version egcs-2.90.29
> 980515) on Linux
> RedHat5.1. When compiling the attached source with "gcc mtest.cc -lm
> -lstdc++" the result of
> the first comparison is falsely considered false.
> 
> Olaf Lenzmann
> 
>   ------------------------------------------------------------------------
> #include <stdio.h>
> #include <math.h>
> #include <iostream.h>
> 
> double snapToGrid(double value, double atomic)
> {
>   if( atomic == 0.0 )
>     return value;
> 
>   double remainder = fmod(value, atomic);
> 
>   // Which direction?
>   if(remainder < 0.5*atomic)
>     return value - remainder;
>   else
>     return value + atomic - remainder;
> }
> 
> int main (void) {
>   double a = 6.375e-10;
>   double b = 6.375e-10;
>   double grid = 1.25e-11;
> 
>   if( snapToGrid(a, grid) == snapToGrid(b, grid) )
>     cout << "Function calls yield equal result" << endl;
> 
>   double aResult = snapToGrid(a, grid);
>   double bResult = snapToGrid(b, grid);
> 
>   if( aResult == bResult )
>     cout << "Variables yield equal result" << endl;
> }

This is not a compiler error. This issue is related to the precision
setting of the FPU. The default is to use extended precision (10-byte fp
number) in order to minimize errors for longer sequences of fp
operations. The value is rounded to double (8-byte fp number) when
stored into a double variable. In the first comparison of main() one
value is still in a FPU register as 10-byte fp number while the other
value is temporarily stored in a double value as a rounded 8-byte fp
number.

Reducing the FPU precision to double will yield the expected behavior
(see attached example) but it will also decrease precision for longer
sequences of fp operations.

Regards,

Wolfgang.
-- 
Wolfgang Reimer (Dr.-Ing.)
 
T U I  --  Technical University of Ilmenau,  GERMANY, Thuringia
Address: TU Ilmenau, FEI/IKM, PF 100565, 98684 Ilmenau, GERMANY
http://ikmcip1.e-technik.tu-ilmenau.de  Phone: +49-3677-69-2619
mailto:reimer@e-technik.tu-ilmenau.de   Fax  : +49-3677-69-1195
#include <stdio.h>
#include <math.h>
#include <iostream.h>
#ifdef linux
#include <fpu_control.h>
#endif


double snapToGrid(double value, double atomic)
{
  if( atomic == 0.0 )
    return value;

  double remainder = fmod(value, atomic);

  // Which direction?
  if(remainder < 0.5*atomic)
    return value - remainder;
  else
    return value + atomic - remainder;
}

int main (void) {
  double a = 6.375e-10;
  double b = 6.375e-10;
  double grid = 1.25e-11;

#ifdef linux
  __setfpucw(_FPU_DEFAULT & ~_FPU_EXTENDED | _FPU_DOUBLE);
#endif
  if( (double)snapToGrid(a, grid) == (double)snapToGrid(b, grid) )
    cout << "Function calls yield equal result" << endl;

  double aResult = snapToGrid(a, grid);
  double bResult = snapToGrid(b, grid);

  if( aResult == bResult )
    cout << "Variables yield equal result" << endl;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]