This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
Re: PATCH: Update sysdeps/mips/fpu/libm-test-ulps
- To: Kjeld Borch Egevang <kjelde at mips dot com>
- Subject: Re: PATCH: Update sysdeps/mips/fpu/libm-test-ulps
- From: Jakub Jelinek <jakub at redhat dot com>
- Date: Mon, 1 Oct 2001 12:10:53 +0200
- Cc: "H . J . Lu" <hjl at lucon dot org>, GNU C Library <libc-alpha at sourceware dot cygnus dot com>, linux-mips mailing list <linux-mips at oss dot sgi dot com>
- References: <20010914111751.A17316@lucon.org> <Pine.LNX.4.30.0110011106360.16270-100000@coplin19.mips.com>
- Reply-To: Jakub Jelinek <jakub at redhat dot com>
On Mon, Oct 01, 2001 at 11:38:16AM +0200, Kjeld Borch Egevang wrote:
> I discovered a problem in glibc-2.2.4-11.2.src.rpm concerning QNaN and
> SNaN (quiet not-a-number and signalling not-a-number). It seems that
> NaN's are always interpreted the Intel-way.
>
> In glibc-2.2.4/soft-fp/quad.h it says:
>
> #define _FP_QNANBIT_Q \
> ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2) % _FP_W_TYPE_SIZE)
>
> But this is not correct on MIPS processors, where SNaNs has the bit set
> and QNaNs has the bit cleared. Changing the definition above to 0 doesn't
> seem to solve the problem (I probably haven't found the root of the
> problem).
If you're changing _FP_QNANBIT_Q definition and testing it on double NaNs,
then certainly nothing should change.
The way soft-fp interprets Quiet NaNs is not just Intel-way, e.g. SPARC,
Alpha work the same way. E.g. on SPARC, signalling NaN is exp=max,
f=.0xxxxxxxxxx...xxx where at least one of the x bits is set, quiet NaN is
exp=max, f=.1xxxxxxxxxx...xxxxxx.
If MIPS has it backwards, then the solution definitely is not to set
_FP_QNANBIT_* there to 0, but instead define some boolean macro in
sfp-machine.h (_FP_QNAN_SET?, _FP_QNAN_SET == 1 iff Quiet Nan has
_FP_QNANBIT set, 0 otherwise) and use it in the soft-fp/* macros,
particularly in op-comon.h:
- if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
+ if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) == !_FP_QNAN_SET) \
- _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \
+ if (_FP_QNAN_SET) \
+ _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \
+ else
+ _FP_FRAC_HIGH_RAW_##fs(X) &= ~_FP_QNANBIT_##fs; \
- && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
+ && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) == !_FP_QNAN_SET) \
and sed 's/_FP_QNANBIT_D/(_FP_QNAN_SET ? _FP_QNANBIT_D : 0)/g' soft-fp/testit.c
> The following piece of code gives the wrong result on a MIPS processor:
>
> -------------------- cut here --------------
> #include <math.h>
>
> typedef union {
> long long ll;
> double d;
> } t_number;
>
> int main()
> {
> t_number x, z;
>
> x.ll = 0x7ff7ffffffffffff; /* QNaN */
> z.d = sqrt(x.d);
> printf("%e %016llx\n", z.d, z.ll);
> }
> -------------------- cut here --------------
>
>
> The result is a signalling NaN:
>
> nan 7ff8000000000000
>
> (I expected 0x7ff7ffffffffffff)
Jakub