[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
-0.0L on Irix (Re: problems with long double NaN on Irix)
From: |
Eric Blake |
Subject: |
-0.0L on Irix (Re: problems with long double NaN on Irix) |
Date: |
Fri, 09 Jan 2009 19:50:10 -0700 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.19) Gecko/20081209 Thunderbird/2.0.0.19 Mnenhy/0.7.5.666 |
According to Bruno Haible on 12/26/2008 4:33 AM:
>> the latest m4 source code, where test-frexpl, test-isnanl, and
>> test-vasprintf-posix all failed on an Irix 6.5 host:
>>
>> checking whether isnanl works... no
>> checking where to find the exponent in a 'long double'... word 0 bit 20
>>
>> test-isnanl.h:67: assertion failed
>> /bin/ksh[10]: 691015 Abort(coredump)
>> FAIL: test-isnanl-nolibm
>
> I fear I cannot do anything about it since I cannot reproduce it. On IRIX 6.5,
> all these tests pass for me with CC=gcc, and I get another failure (for -0.0L)
> with CC="cc -O".
>
> Can you debug this a bit?
I'm still looking into the NaN issue. But so far, I've discovered this
about -0.0L on Irix 6.2:
With 'cc -n32', LDBL_MIN is a compile-time constant; but with 'gcc', I get
an error when trying to use it to initialize a global variable (note,
however, that it can be used inside the body of a method):
foo.c:9: error: initializer element is not constant
To work around that, I used 1e-300 as a close approximation to LDBL_MIN;
similarly for LDBL_MAX.
With this test program:
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
long double x = 1.0L;
long double y = -0.0L;
long double z = 0.0L;
long double yy = -1e-300 * 1e-300;
long double yyy = -1e-300 / 1e300;
int different_from_plus_zero (long double arg)
{
return memcmp (&arg, &z, sizeof (z)) != 0;
}
int main()
{
printf ("%Lf\n", x / y);
printf ("%d\n", x / y < 0);
printf ("%d\n", different_from_plus_zero (y));
printf ("%Lf\n", x / yy);
printf ("%d\n", x / yy < 0);
printf ("%d\n", different_from_plus_zero (yy));
printf ("%Lf\n", x / yyy);
printf ("%d\n", x / yyy < 0);
printf ("%d\n", different_from_plus_zero (yyy));
{
long double x = 1.0L;
long double y = -0.0L;
printf ("%Lf\n", x / y);
printf ("%d\n", x / y < 0);
printf ("%d\n", different_from_plus_zero (y));
}
#define x 1.0L
#define y -0.0L
printf ("%Lf\n", x / y);
printf ("%d\n", x / y < 0);
printf ("%d\n", different_from_plus_zero (y));
#undef y
#define y -z
printf ("%Lf\n", x / y);
printf ("%d\n", x / y < 0);
printf ("%d\n", different_from_plus_zero (y));
#undef y
#define y (-LDBL_MIN * LDBL_MIN)
printf ("%Lf\n", x / y);
printf ("%d\n", x / y < 0);
printf ("%d\n", different_from_plus_zero (y));
#undef y
#define y (-LDBL_MIN / LDBL_MAX)
printf ("%Lf\n", x / y);
printf ("%d\n", x / y < 0);
printf ("%d\n", different_from_plus_zero (y));
return 0;
}
cc gives the following:
inf
0
0
inf
0
0
inf
0
0
-inf
1
1
-inf
1
1
-inf
1
1
-inf
1
1
-inf
1
1
while gcc gives:
-inf
1
1
-inf
1
1
-inf
1
1
-inf
1
1
-inf
1
1
-inf
1
1
-inf
1
1
-inf
1
1
My conclusion: cc is buggy when representing -0.0L as a global variable,
but any variant that computes -0.0L during the body of a method works.
Therefore, we need to scrub gnulib tests to guarantee that we never
compute -0.0L except inside a method. For example, m4/signbit.m4 looks
okay, whereas tests/test-ceill.c does not. I think the only sane way to
work around this is to write a helper function (since Irix cc can compute
-0.0L inside a function), then use that function instead of global storage
in all of our unit tests.
Bruno, do you want to tackle this, or do you want me to take a first shot
at it?
--
Don't work too hard, make some time for fun as well!
Eric Blake address@hidden
signature.asc
Description: OpenPGP digital signature
- -0.0L on Irix (Re: problems with long double NaN on Irix),
Eric Blake <=