This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: PATCH: Update sysdeps/mips/fpu/libm-test-ulps


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]