Maciej W. Rozycki (macro@linux-mips.org) writes:
> > I have a long standing patch for FPU emulator to fix a segmentation
> > fault in pow() library function.
> >
> > Here is a test program to reproduce it.
> >
> > main()
> > {
> > union {
> > double d;
> > struct {
> > #ifdef __MIPSEB
> > unsigned int high, low;
> > #else
> > unsigned int low, high;
> > #endif
> > } i;
> > } x, y, z;
> > x.i.low = 0x00000000;
> > x.i.high = 0xfff00001;
> > y.i.low = 0x80000000;
> > y.i.high = 0xcff00000;
> > z.d = pow(x.d, y.d);
> > printf("%x %x\n", z.i.high, z.i.low);
> > return 0;
> > }
> >
> >
> > If you run this program, you will get segmentation fault (unless your
> > FPU does not raise Unimplemented exception for NaN operands). The
> > segmentation fault is caused by endless recursion in __ieee754_pow().
> >
> > It looks glibc's pow() assume unary '-' operation for any number
> > (including NaN) always invert its sign bit.
>
> AFAICS, the IEEE 754 standard explicitly leaves interpretation of the
> sign bit for NaNs as unspecified. Therefore our implementation is correct
> and its glibc that should be fixed instead. Please file a bug report
> against glibc.
You are both right, in a sense.
"Annex A Recommended Functions and Predicates" of IEEE754 (the
annexe is not part of the formal spec) includes a recommendation:
"x is x copied with its sign reversed, not 0x; the distinction is
germane when x is ±0 or NaN."
And in fact that's how the MIPS neg.d operation works: it never
generates an exception, just blindly flips the sign bit.
In the body of IEEE754 it says:
"This standard does not interpret the sign of an NaN."
So there you are. According to the book, the library function should
not depend on the sign of a NaN, but it would also be better if the
compiler/emulator/whatever ensures that "-x" is always and only
implemented by reversing the sign bit.
So file a bug against glibc, but we should fix the emulator so it
correctly imitates the MIPS instruction set...
--
Dominic Sweetman
MIPS Technologies.
|