Bug 48341 - LDBL_EPSILON is wrong on IRIX 6.5
Summary: LDBL_EPSILON is wrong on IRIX 6.5
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: 47406
  Show dependency treegraph
 
Reported: 2011-03-29 17:32 UTC by Rainer Orth
Modified: 2013-08-02 11:00 UTC (History)
1 user (show)

See Also:
Host: mips-sgi-irix6.5
Target: mips-sgi-irix6.5
Build: mips-sgi-irix6.5
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Rainer Orth 2011-03-29 17:32:21 UTC
When looking at a libstdc++ testsuite failure on IRIX 6.5

FAIL: 18_support/numeric_limits/epsilon.cc execution test

Assertion failed: EX, file /vol/gcc/src/hg/gcc-4.6-branch/local/libstdc++-v3/testsuite/18_support/numeric_limits/epsilon.cc, line 37

I found that the testcase aborts checking long double LDBL_EPSILON:

Program received signal SIGABRT, Aborted.
0x0fa4ac28 in _prctl () from /usr/lib32/libc.so.1
(gdb) where
[...]
#5  0x0fa756c4 in __assert () at /xlv86/patches/7207/work/irix/lib/libc/libc_n32_M4/gen/assert.c:59
#6  0x10002210 in test_epsilon<long double> () at /vol/gcc/src/hg/trunk/local/libstdc++-v3/testsuite/18_support/numeric_limits/epsilon.cc:37
#7  0x10002108 in main () at /vol/gcc/src/hg/trunk/local/libstdc++-v3/testsuite/18_support/numeric_limits/epsilon.cc:44

While epsilon is printed as 0 here, in mips-sgi-irix6.5/libstdc++-v3/include/limits, I find __LDBL_EPSILON__ is -1.596672247627775849325098170429471e+293

Running the testcase through g++ -g3 -save-temps, epsilon.ii reveals

#define __FLT_EPSILON__ 1.19209289550781250000000000000000e-7F
#define __DBL_EPSILON__ double(2.22044604925031308084726333618164e-16L)
#define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L

which is obviously bogus.  The native <internal/float_core.h> has

#define FLT_EPSILON     1.19209290E-07F
#define DBL_EPSILON     2.2204460492503131E-16
#define LDBL_EPSILON    1.232595164407830945955825883254353E-32L

IRIX 6 uses the IBM double format for long double.  As expected, the gcc.target/powerpc/rs6000-ldouble-2.c testcase also FAILs.

eps is correctly determined:

(gdb) p eps
$1 = 2.465190328815661891911651766508707e-32

This can be seen with the following test:

$ cat ld.c
#include <stdio.h>
#include <float.h>

int
main (void)
{
  printf ("LDBL_EPSILON = %Lg\n", LDBL_EPSILON);
  return 0;
}
$ cc -o ld-cc ld.c
$ ./ld-cc 
LDBL_EPSILON = 1.2326e-32
$ ./xgcc -B./ -o ld-gcc ld.c
$ ./ld-gcc 
LDBL_EPSILON = 4.94066e-324
Comment 1 joseph@codesourcery.com 2011-03-29 18:50:47 UTC
On Tue, 29 Mar 2011, ro at gcc dot gnu.org wrote:

> Running the testcase through g++ -g3 -save-temps, epsilon.ii reveals
> 
> #define __FLT_EPSILON__ 1.19209289550781250000000000000000e-7F
> #define __DBL_EPSILON__ double(2.22044604925031308084726333618164e-16L)
> #define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L
> 
> which is obviously bogus.  The native <internal/float_core.h> has

Why do you think this is bogus?  It's correct for IBM long double, where 
the mantissa bits can be discontiguous, and so the least value greater 
than 1 that is representable has such discontiguous bits.  See PR 19405 
and <http://gcc.gnu.org/ml/gcc-patches/2005-01/msg00374.html>.
Comment 2 ro@CeBiTec.Uni-Bielefeld.DE 2011-03-30 15:16:57 UTC
> Why do you think this is bogus?  It's correct for IBM long double, where 
> the mantissa bits can be discontiguous, and so the least value greater 
> than 1 that is representable has such discontiguous bits.  See PR 19405 
> and <http://gcc.gnu.org/ml/gcc-patches/2005-01/msg00374.html>.

But why do both that exact testcase and the libstdc++ one fail with this
LDFL_EPSILON value on IRIX, and disagree with both the one from the
system headers, which is identical to the one found in the
gcc.target/powerpc/rs6000-ldouble-2.c test?

	Rainer
Comment 3 joseph@codesourcery.com 2011-03-30 15:43:53 UTC
On Wed, 30 Mar 2011, ro at CeBiTec dot Uni-Bielefeld.DE wrote:

> --- Comment #2 from ro at CeBiTec dot Uni-Bielefeld.DE <ro at CeBiTec dot Uni-Bielefeld.DE> 2011-03-30 15:16:57 UTC ---
> > Why do you think this is bogus?  It's correct for IBM long double, where 
> > the mantissa bits can be discontiguous, and so the least value greater 
> > than 1 that is representable has such discontiguous bits.  See PR 19405 
> > and <http://gcc.gnu.org/ml/gcc-patches/2005-01/msg00374.html>.
> 
> But why do both that exact testcase and the libstdc++ one fail with this
> LDFL_EPSILON value on IRIX, and disagree with both the one from the
> system headers, which is identical to the one found in the
> gcc.target/powerpc/rs6000-ldouble-2.c test?

Presumably the implementation of long double arithmetic being used on IRIX 
is less accurate in this case than the one being used on Power.

Perhaps it would make sense to look at using darwin-ldouble.c (with 
function names appropriately adjusted) in some way on IRIX, in place of 
the code in fp-bit.c.  Since IRIX is the only target using the IBM long 
double support in fp-bit.c, it would then be possible to simplify fp-bit.* 
by removing all the HALFFRACBITS code.

Alternatively, if the format on IRIX is actually defined differently so 
that the nonzero bits are always within a contiguous set of 106 bits - if 
that is what IRIX documentation and the IRIX system compiler / libraries 
always do - then the generic code could be taught about that difference 
and the code in fp-bit.c might be closer to being correct for that 
definition than darwin-ldouble.c
Comment 4 Vincent Lefèvre 2013-08-02 09:02:19 UTC
I can see the same problem under Linux (gcc110.fsffrance.org).

According to the C standard (C99 and C11), the *_EPSILON values are "the difference between 1 and the least value greater than 1 that is representable in the given floating point type, b^(1-p)".

Here b = 2 and p = LDBL_MANT_DIG = 106.

I think that the C standard is badly worded. It should have said "the difference between 1 and the least floating-point value greater than 1 that is representable in the given type, b^(1-p)". What is regarded as a floating-point value is specified by the standard: see 5.2.4.2.2p2 "A floating-point number (x) is defined by the following model: [...]".
Comment 5 Vincent Lefèvre 2013-08-02 09:09:25 UTC
(In reply to Vincent Lefèvre from comment #4)
> I can see the same problem under Linux (gcc110.fsffrance.org).

In case this wasn't clear, the architecture is also a PowerPC. The double-double format comes from the PowerPC ABI, and isn't directly related to the OS itself (FYI it was also used under Mac OS X / PowerPC).

Thus the summary of this bug should be changed to:

  LDBL_EPSILON is wrong on PowerPC
Comment 6 ro@CeBiTec.Uni-Bielefeld.DE 2013-08-02 10:49:35 UTC
> --- Comment #5 from Vincent Lefèvre <vincent-gcc at vinc17 dot net> ---
> (In reply to Vincent Lefèvre from comment #4)
>> I can see the same problem under Linux (gcc110.fsffrance.org).
>
> In case this wasn't clear, the architecture is also a PowerPC. The
> double-double format comes from the PowerPC ABI, and isn't directly related to
> the OS itself (FYI it was also used under Mac OS X / PowerPC).
>
> Thus the summary of this bug should be changed to:
>
>   LDBL_EPSILON is wrong on PowerPC

Certainly not: IRIX isn't PowerPC but MIPS!  If need be, just refer to
the double/double format.

	Rainer
Comment 7 Vincent Lefèvre 2013-08-02 10:56:45 UTC
(In reply to ro@CeBiTec.Uni-Bielefeld.DE from comment #6)
> Certainly not: IRIX isn't PowerPC but MIPS!

OK, that wasn't clear because the original but report mentioned:
"gcc.target/powerpc/rs6000-ldouble-2.c".
            ^^^^^^^

> If need be, just refer to the double/double format.

Yes.
Comment 8 ro@CeBiTec.Uni-Bielefeld.DE 2013-08-02 11:00:17 UTC
> --- Comment #7 from Vincent Lefèvre <vincent-gcc at vinc17 dot net> ---
> (In reply to ro@CeBiTec.Uni-Bielefeld.DE from comment #6)
>> Certainly not: IRIX isn't PowerPC but MIPS!
>
> OK, that wasn't clear because the original but report mentioned:
> "gcc.target/powerpc/rs6000-ldouble-2.c".
>             ^^^^^^^

Right, but that test isn't run on regular testsuite runs on IRIX,
although there's nothing powerpc specific in there except for the
-mlong-double-128 option which can only be used on powerpc targets.

Running it manually on IRIX shows the failure.

	Rainer