bug-gnulib
[Top][All Lists]
Advanced

[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

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]