Bug 12639 - long double comparison is broken
Summary: long double comparison is broken
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 3.3
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2003-10-16 12:59 UTC by Not yet assigned to anyone
Modified: 2011-03-05 18:37 UTC (History)
3 users (show)

See Also:
Host: alphaev56-dec-osf5.1
Target: alphaev56-dec-osf5.1
Build: alphaev56-dec-osf5.1
Known to work: 4.2.4, 4.3.5, 4.4.5, 4.5.2
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Not yet assigned to anyone 2003-10-16 12:59:03 UTC
	
The comparison between 0 and the largest power of 2 that fits in a long double
gives a non-zero result!!!

Environment:
System: OSF1 spe171.testdrive.hp.com V5.1 2650 alpha
Architecture: alphaev56-dec-osf5.1
host: alphaev56-dec-osf5.1
build: alphaev56-dec-osf5.1
target: alphaev56-dec-osf5.1
configured with: ../configure

How-To-Repeat:
	
spe171.testdrive.hp.com> cat bug.c
#include <stdio.h>
#include <stdlib.h>
#include <float.h>

int
main ()
{
  long double d;
  d = 1.0; while (d < LDBL_MAX / 2.0) d += d;
  printf ("d=%1.30Le\n", d);
  if (d == (long double) 0.0)
    printf ("d equals 0.0\n");
}

spe171.testdrive.hp.com> gcc -O1 bug.c
spe171.testdrive.hp.com> ./a.out
d=5.948657476786158825428796633140e+4931
d equals 0.0
Comment 1 Christian Ehrhardt 2003-10-16 14:04:51 UTC
Please read http://gcc.gnu.org/bugs.html. Also have a look at
bug 323 and its duplicates.

Comment 2 Falk Hueffner 2005-10-16 09:07:48 UTC
(In reply to comment #1)
> Please read http://gcc.gnu.org/bugs.html. Also have a look at
> bug 323 and its duplicates.

Well, brushing off equality of 5*10^4931 and 0 as rounding error is maybe 
stretching it a bit ;-) This sure seems like a bug.
Comment 3 Christopher Eltschka 2005-10-27 09:11:33 UTC
I just stumbled on the same problem, but with much more conventional numbers. The following C++ test program demonstrates it:

#include <iostream>

// this just serves to calculate a positive number which the optimizer
// will not figure out at compile time
long double f()
{
  long double value = 1.0;
  for (int i = 0; i < 10; ++i)
    value += (long double)i;
  return value;
}

int main()
{
  long double a = f();
  std::cout << a;
  if (a > 0)
    std::cout << " > 0\n";
  else if (a < 0)
    std::cout << " < 0\n";
  else if (a == 0)
    std::cout << " == 0\n";
  else
    std::cout << "oops!\n";
}

Compiling and running gives:
> g++ longdouble.cc -O3 && a.out
46 == 0

which is clearly wrong. The same result happens with -O2 and -O1. With -O0 I correctly get the output 46 > 0.

The compiler is:

> g++ -v
Reading specs from /usr/local/lib/gcc-lib/alphaev67-dec-osf5.1/3.3/specs
Configured with: ../gcc-3.3/configure --with-libiconv-prefix=/usr/local --with-included-gettext
Thread model: single
gcc version 3.3

As workaround for == 0, !! seems to work. Unfortunately I don't know a workaround for > 0 and < 0.
Comment 4 Christopher Eltschka 2005-10-27 10:38:27 UTC
(In reply to comment #3)
> As workaround for == 0, !! seems to work. Unfortunately I don't know a
> workaround for > 0 and < 0.
> 

Sorry for self-reply, but now I've found a simple workaround for all cases:
Instead of comparing with 0, just add 1 and compare with 1.
For some reason this works even if the number to compare with happens to be -1 (i.e. if after adding 1 you get 0).
Comment 5 Serge Belyshev 2011-03-05 18:37:52 UTC
Works on ev56 and ev67 linux-gnu with gcc 4.2 .. 4.5, assuming fixed.