This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Hi! Some of nextafter* and nexttoward* are buggy. Namely, i386 style INFINITY is 0x7fff, 0x80000000, 0x0 but the code would do very complicated check (((hx|lx)|-(hx|lx))&hx)!=0 which is non-zero for INFINITY as well, also ldbl-96/s_nextafterl had wrong sign e.g. for nextafterl(-0.0, INFINITY) or nextafterl(0.0, -INFINITY). 2001-06-15 Jakub Jelinek <jakub@redhat.com> * math/test-misc.c (main): Add tests for nextafter and nexttoward with +-Inf as second argument. * sysdeps/generic/s_nexttowardf.c (__nexttowardf): Only check for NaN, not Inf. * sysdeps/i386/fpu/s_nextafterl.c (__nextafterl): Fix check for NaN. * sysdeps/i386/fpu/s_nexttoward.c: New. * sysdeps/i386/fpu/s_nexttowardf.c: New. * sysdeps/ieee754/ldbl-96/s_nexttoward.c (__nexttoward): Simplify check for NaN, optimize x==+-0 handling. * sysdeps/ieee754/ldbl-96/s_nexttowardf.c (__nexttowardf): Likewise. * sysdeps/ieee754/ldbl-96/s_nextafterl.c (__nextafterl): Simplify check for NaN, fix sign in x==+-0 case. * sysdeps/ia64/fpu/s_nexttoward.c: New. * sysdeps/ia64/fpu/s_nexttowardf.c: New. --- libc/math/test-misc.c.jj Sat Jun 2 20:36:01 2001 +++ libc/math/test-misc.c Fri Jun 15 13:44:11 2001 @@ -384,6 +384,24 @@ main (void) v2.ieee.negative); result = 1; } + + if (nextafterf (0.0f, INFINITY) != nextafterf (0.0f, 1.0f) + || nextafterf (-0.0f, INFINITY) != nextafterf (-0.0f, 1.0f) + || nextafterf (0.0f, -INFINITY) != nextafterf (0.0f, -1.0f) + || nextafterf (-0.0f, -INFINITY) != nextafterf (-0.0f, -1.0f)) + { + printf ("nextafterf (+-0, +-Inf) != nextafterf (+-0, +-1)\n"); + result = 1; + } + + if (nexttowardf (0.0f, INFINITY) != nexttowardf (0.0f, 1.0f) + || nexttowardf (-0.0f, INFINITY) != nexttowardf (-0.0f, 1.0f) + || nexttowardf (0.0f, -INFINITY) != nexttowardf (0.0f, -1.0f) + || nexttowardf (-0.0f, -INFINITY) != nexttowardf (-0.0f, -1.0f)) + { + printf ("nexttowardf (+-0, +-Inf) != nexttowardf (+-0, +-1)\n"); + result = 1; + } } { @@ -680,6 +698,24 @@ main (void) v2.ieee.negative); result = 1; } + + if (nextafter (0.0, INFINITY) != nextafter (0.0, 1.0) + || nextafter (-0.0, INFINITY) != nextafter (-0.0, 1.0) + || nextafter (0.0, -INFINITY) != nextafter (0.0, -1.0) + || nextafter (-0.0, -INFINITY) != nextafter (-0.0, -1.0)) + { + printf ("nextafter (+-0, +-Inf) != nextafter (+-0, +-1)\n"); + result = 1; + } + + if (nexttoward (0.0, INFINITY) != nexttoward (0.0, 1.0) + || nexttoward (-0.0, INFINITY) != nexttoward (-0.0, 1.0) + || nexttoward (0.0, -INFINITY) != nexttoward (0.0, -1.0) + || nexttoward (-0.0, -INFINITY) != nexttoward (-0.0, -1.0)) + { + printf ("nexttoward (+-0, +-Inf) != nexttoward (+-0, +-1)\n"); + result = 1; + } } #ifndef NO_LONG_DOUBLE @@ -978,6 +1014,24 @@ main (void) { printf ("0.0L down: negative differs: 1 vs %d\n", v2.ieee.negative); + result = 1; + } + + if (nextafterl (0.0, INFINITY) != nextafterl (0.0, 1.0) + || nextafterl (-0.0, INFINITY) != nextafterl (-0.0, 1.0) + || nextafterl (0.0, -INFINITY) != nextafterl (0.0, -1.0) + || nextafterl (-0.0, -INFINITY) != nextafterl (-0.0, -1.0)) + { + printf ("nextafterl (+-0, +-Inf) != nextafterl (+-0, +-1)\n"); + result = 1; + } + + if (nexttowardl (0.0L, INFINITY) != nexttowardl (0.0L, 1.0L) + || nexttowardl (-0.0L, INFINITY) != nexttowardl (-0.0L, 1.0L) + || nexttowardl (0.0L, -INFINITY) != nexttowardl (0.0L, -1.0L) + || nexttowardl (-0.0L, -INFINITY) != nexttowardl (-0.0L, -1.0L)) + { + printf ("nexttowardl (+-0, +-Inf) != nexttowardl (+-0, +-1)\n"); result = 1; } } --- libc/sysdeps/generic/s_nexttowardf.c.jj Tue Oct 12 17:39:31 1999 +++ libc/sysdeps/generic/s_nexttowardf.c Fri Jun 15 13:04:26 2001 @@ -39,7 +39,7 @@ ix = hx&0x7fffffff; /* |x| */ iy = hy&0x7fffffff; /* |y| */ - if((ix>=0x7f800000) || /* x is nan */ + if((ix>0x7f800000) || /* x is nan */ ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */ return x+y; if((long double) x==y) return y; /* x=y, return y */ --- libc/sysdeps/i386/fpu/s_nextafterl.c.jj Tue Jan 2 14:18:03 2001 +++ libc/sysdeps/i386/fpu/s_nextafterl.c Fri Jun 15 13:17:43 2001 @@ -45,10 +45,10 @@ static char rcsid[] = "$NetBSD: $"; ix = esx&0x7fff; /* |x| */ iy = esy&0x7fff; /* |y| */ - /* The additional &hx/&hy is required because Intel's extended format - has the normally implicit 1 explicit present. Sigh! */ - if(((ix==0x7fff)&&(((hx|lx)|-(hx|lx))&hx)>>31!=0) || /* x is nan */ - ((iy==0x7fff)&&(((hy|ly)|-(hy|ly))&hy)>>31!=0)) /* y is nan */ + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + 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 */ --- libc/sysdeps/i386/fpu/s_nexttoward.c.jj Fri Jun 15 13:22:20 2001 +++ libc/sysdeps/i386/fpu/s_nexttoward.c Fri Jun 15 13:23:14 2001 @@ -0,0 +1,101 @@ +/* s_nexttoward.c + * Special i387 version + * Conversion from s_nextafter.c by Ulrich Drepper, Cygnus Support, + * drepper@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +/* IEEE functions + * nexttoward(x,y) + * return the next machine floating-point number of x in the + * direction toward y. + * Special cases: + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + double __nexttoward(double x, long double y) +#else + double __nexttoward(x,y) + double x; + long double y; +#endif +{ + int32_t hx,ix,iy; + u_int32_t lx,hy,ly,esy; + + EXTRACT_WORDS(hx,lx,x); + GET_LDOUBLE_WORDS(esy,hy,ly,y); + ix = hx&0x7fffffff; /* |x| */ + iy = esy&0x7fff; /* |y| */ + + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ + ((iy>=0x7fff)&&((hy&0x7fffffff)|ly)!=0)) /* y is nan */ + return x+y; + if((long double) x==y) return y; /* x=y, return y */ + if((ix|lx)==0) { /* x == 0 */ + double x2; + INSERT_WORDS(x,(esy&0x8000)<<16,1); /* return +-minsub */ + x2 = x*x; + if(x2==x) return x2; else return x; /* raise underflow flag */ + } + if(hx>=0) { /* x > 0 */ + if (esy>=0x8000||((ix>>20)&0x7ff)>iy-0x3c00 + || (((ix>>20)&0x7ff)==iy-0x3c00 + && (((hx<<11)|(lx>>21))>(hy&0x7fffffff) + || (((hx<<11)|(lx>>21))==(hy&0x7fffffff) + && (lx<<11)>ly)))) { /* x > y, x -= ulp */ + if(lx==0) hx -= 1; + lx -= 1; + } else { /* x < y, x += ulp */ + lx += 1; + if(lx==0) hx += 1; + } + } else { /* x < 0 */ + if (esy<0x8000||((ix>>20)&0x7ff)>iy-0x3c00 + || (((ix>>20)&0x7ff)==iy-0x3c00 + && (((hx<<11)|(lx>>21))>(hy&0x7fffffff) + || (((hx<<11)|(lx>>21))==(hy&0x7fffffff) + && (lx<<11)>ly)))) {/* x < y, x -= ulp */ + if(lx==0) hx -= 1; + lx -= 1; + } else { /* x > y, x += ulp */ + lx += 1; + if(lx==0) hx += 1; + } + } + hy = hx&0x7ff00000; + if(hy>=0x7ff00000) return x+x; /* overflow */ + if(hy<0x00100000) { /* underflow */ + double x2 = x*x; + if(x2!=x) { /* raise underflow flag */ + INSERT_WORDS(x2,hx,lx); + return x2; + } + } + INSERT_WORDS(x,hx,lx); + return x; +} +weak_alias (__nexttoward, nexttoward) +#ifdef NO_LONG_DOUBLE +strong_alias (__nexttoward, __nexttowardl) +weak_alias (__nexttoward, nexttowardl) +#endif --- libc/sysdeps/i386/fpu/s_nexttowardf.c.jj Fri Jun 15 13:25:44 2001 +++ libc/sysdeps/i386/fpu/s_nexttowardf.c Fri Jun 15 13:27:31 2001 @@ -0,0 +1,81 @@ +/* s_nexttowardf.c -- float version of s_nextafter.c. + * Special i387 version. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + float __nexttowardf(float x, long double y) +#else + float __nexttowardf(x,y) + float x; + long double y; +#endif +{ + int32_t hx,ix,iy; + u_int32_t hy,ly,esy; + + GET_FLOAT_WORD(hx,x); + GET_LDOUBLE_WORDS(esy,hy,ly,y); + ix = hx&0x7fffffff; /* |x| */ + iy = esy&0x7fff; /* |y| */ + + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + if((ix>0x7f800000) || /* x is nan */ + (iy>=0x7fff&&(((hy&0x7fffffff)|ly)!=0))) /* y is nan */ + return x+y; + if((long double) x==y) return y; /* x=y, return y */ + if(ix==0) { /* x == 0 */ + float x2; + SET_FLOAT_WORD(x,((esy&0x8000)<<16)|1);/* return +-minsub*/ + x2 = x*x; + if(x2==x) return x2; else return x; /* raise underflow flag */ + } + if(hx>=0) { /* x > 0 */ + if(esy>=0x8000||((ix>>23)&0xff)>iy-0x3f80 + || (((ix>>23)&0xff)==iy-0x3f80 + && ((ix&0x7fffff)<<8)>(hy&0x7fffffff))) {/* x > y, x -= ulp */ + hx -= 1; + } else { /* x < y, x += ulp */ + hx += 1; + } + } else { /* x < 0 */ + if(esy<0x8000||((ix>>23)&0xff)>iy-0x3f80 + || (((ix>>23)&0xff)==iy-0x3f80 + && ((ix&0x7fffff)<<8)>(hy&0x7fffffff))) {/* x < y, x -= ulp */ + hx -= 1; + } else { /* x > y, x += ulp */ + hx += 1; + } + } + hy = hx&0x7f800000; + if(hy>=0x7f800000) return x+x; /* overflow */ + if(hy<0x00800000) { /* underflow */ + float x2 = x*x; + if(x2!=x) { /* raise underflow flag */ + SET_FLOAT_WORD(x2,hx); + return x2; + } + } + SET_FLOAT_WORD(x,hx); + return x; +} +weak_alias (__nexttowardf, nexttowardf) --- libc/sysdeps/ieee754/ldbl-96/s_nexttoward.c.jj Thu Nov 2 08:52:19 2000 +++ libc/sysdeps/ieee754/ldbl-96/s_nexttoward.c Fri Jun 15 13:28:40 2001 @@ -45,12 +45,12 @@ static char rcsid[] = "$NetBSD: $"; iy = esy&0x7fff; /* |y| */ if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ - ((iy>=0x7fff)&&((hy|ly)|-(hy|ly))!=0)) /* y is nan */ + ((iy>=0x7fff)&&(hy|ly)!=0)) /* y is nan */ return x+y; if((long double) x==y) return y; /* x=y, return y */ if((ix|lx)==0) { /* x == 0 */ double x2; - INSERT_WORDS(x,esy&0x8000?0x80000000:0,1);/* return +-minsub */ + INSERT_WORDS(x,(esy&0x8000)<<16,1); /* return +-minsub */ x2 = x*x; if(x2==x) return x2; else return x; /* raise underflow flag */ } --- libc/sysdeps/ieee754/ldbl-96/s_nextafterl.c.jj Wed Jul 14 02:14:34 1999 +++ libc/sysdeps/ieee754/ldbl-96/s_nextafterl.c Fri Jun 15 13:07:08 2001 @@ -43,12 +43,12 @@ static char rcsid[] = "$NetBSD: $"; ix = esx&0x7fff; /* |x| */ iy = esy&0x7fff; /* |y| */ - if(((ix==0x7fff)&&((hx|lx)|-(hx|lx))!=0) || /* x is nan */ - ((iy==0x7fff)&&((hy|ly)|-(hy|ly))!=0)) /* y is nan */ + if(((ix==0x7fff)&&((hx|lx)!=0) || /* x is nan */ + ((iy==0x7fff)&&((hy|ly)!=0)) /* y is nan */ return x+y; if(x==y) return y; /* x=y, return y */ if((ix|hx|lx)==0) { /* x == 0 */ - SET_LDOUBLE_WORDS(x,esx&0x8000,0,1);/* return +-minsubnormal */ + SET_LDOUBLE_WORDS(x,esy&0x8000,0,1);/* return +-minsubnormal */ y = x*x; if(y==x) return y; else return x; /* raise underflow flag */ } --- libc/sysdeps/ieee754/ldbl-96/s_nexttowardf.c.jj Wed Jul 14 02:14:43 1999 +++ libc/sysdeps/ieee754/ldbl-96/s_nexttowardf.c Fri Jun 15 13:10:52 2001 @@ -36,13 +36,13 @@ static char rcsid[] = "$NetBSD: $"; ix = hx&0x7fffffff; /* |x| */ iy = esy&0x7fff; /* |y| */ - if((ix>0x7f800000) || /* x is nan */ - (iy>=0x7fff&&((hy|ly)|-(hy|ly))!=0)) /* y is nan */ + if((ix>0x7f800000) || /* x is nan */ + (iy>=0x7fff&&((hy|ly)!=0))) /* y is nan */ return x+y; if((long double) x==y) return y; /* x=y, return y */ if(ix==0) { /* x == 0 */ float x2; - SET_FLOAT_WORD(x,(esy&0x8000?0x80000000:0)|1);/* return +-minsub*/ + SET_FLOAT_WORD(x,((esy&0x8000)<<16)|1);/* return +-minsub*/ x2 = x*x; if(x2==x) return x2; else return x; /* raise underflow flag */ } --- libc/sysdeps/ia64/fpu/s_nexttoward.c.jj Fri Jun 15 13:24:52 2001 +++ libc/sysdeps/ia64/fpu/s_nexttoward.c Fri Jun 15 13:24:48 2001 @@ -0,0 +1 @@ +#include <sysdeps/i386/fpu/s_nexttoward.c> --- libc/sysdeps/ia64/fpu/s_nexttowardf.c.jj Fri Jun 15 13:24:52 2001 +++ libc/sysdeps/ia64/fpu/s_nexttowardf.c Fri Jun 15 13:25:23 2001 @@ -0,0 +1 @@ +#include <sysdeps/i386/fpu/s_nexttowardf.c> Jakub
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |