> > Another bug. Intel chose an extended precision format with an > explicit integer bit, and the code doesn't handle that. Assuming we > don't support machines with extended precision format that have an > implicit integer bit, the following diff (an adaptation of the code in > glibc) should fix things. Not entirely happy with the fix though, so > I'm still thinking about improvements.
confirming that this patch fixes the failing numpy regress test on i386. let me know if you want me to test a different diff. > > Index: src/ld80/s_nextafterl.c > =================================================================== > RCS file: /cvs/src/lib/libm/src/ld80/s_nextafterl.c,v > retrieving revision 1.4 > diff -u -p -r1.4 s_nextafterl.c > --- src/ld80/s_nextafterl.c 12 Nov 2013 21:07:28 -0000 1.4 > +++ src/ld80/s_nextafterl.c 2 Jun 2014 13:21:58 -0000 > @@ -32,8 +32,8 @@ nextafterl(long double x, long double y) > ix = esx&0x7fff; /* |x| */ > iy = esy&0x7fff; /* |y| */ > > - if (((ix==0x7fff)&&((hx|lx)!=0)) || /* x is nan */ > - ((iy==0x7fff)&&((hy|ly)!=0))) /* y is nan */ > + if (((ix==0x7fff)&&((hx&=0x7fffffff|lx)!=0)) || /* x is nan */ > + ((iy==0x7fff)&&((hy&-0x7fffffff|ly)!=0))) /* y is nan */ > return x+y; > if(x==y) return y; /* x=y, return y */ > if((ix|hx|lx)==0) { /* x == 0 */ > @@ -47,31 +47,50 @@ nextafterl(long double x, long double y) > if(ix>iy||((ix==iy) && (hx>hy||((hx==hy)&&(lx>ly))))) { > /* x > y, x -= ulp */ > if(lx==0) { > - if (hx==0) esx -= 1; > - hx -= 1; > + if (hx <= 0x80000000) { > + if (esx == 0) { > + --hx; > + } else { > + esx -= 1; > + hx = hx - 1; > + if (esx > 0) > + hx |= 0x80000000; > + } > + } else > + hx -= 1; > } > lx -= 1; > } else { /* x < y, x += ulp */ > lx += 1; > if(lx==0) { > hx += 1; > - if (hx==0) > + if (hx==0 || (esx == 0 && hx == 0x80000000)) { > esx += 1; > + hx |= 0x80000000; > + } > } > } > } else { /* x < 0 */ > if(esy>=0||(ix>iy||((ix==iy)&&(hx>hy||((hx==hy)&&(lx>ly)))))){ > /* x < y, x -= ulp */ > if(lx==0) { > - if (hx==0) esx -= 1; > - hx -= 1; > + if (hx <= 0x80000000) { > + esx -= 1; > + hx = hx - 1; > + if ((esx&0x7fff) > 0) > + hx |= 0x80000000; > + } else > + hx -= 1; > } > lx -= 1; > } else { /* x > y, x += ulp */ > lx += 1; > if(lx==0) { > hx += 1; > - if (hx==0) esx += 1; > + if (hx==0 || (esx == 0xffff8000 && hx == 0x80000000)) { > + esx += 1; > + hx |= 0x80000000; > + } > } > } > }