From ab2b993da90d47e29d4b52de3f3abf9477b4c93c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sat, 6 Sep 2008 15:00:33 +0000 Subject: [PATCH] added nexttoward() git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27349 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/posix/math.h | 5 + .../posix/glibc/arch/generic/s_nexttoward.c | 1 + .../posix/glibc/arch/generic/s_nexttowardf.c | 78 +++++++++++++ .../posix/glibc/arch/generic/s_nexttowardl.c | 1 + .../libroot/posix/glibc/arch/m68k/Jamfile | 1 + .../libroot/posix/glibc/arch/ppc/Jamfile | 1 + .../libroot/posix/glibc/arch/x86/Jamfile | 2 + .../posix/glibc/arch/x86/s_nexttoward.c | 106 ++++++++++++++++++ .../posix/glibc/arch/x86/s_nexttowardf.c | 86 ++++++++++++++ 9 files changed, 281 insertions(+) create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_nexttoward.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_nexttowardf.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_nexttowardl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86/s_nexttoward.c create mode 100644 src/system/libroot/posix/glibc/arch/x86/s_nexttowardf.c diff --git a/headers/posix/math.h b/headers/posix/math.h index 771f26fade..edce3eb21c 100644 --- a/headers/posix/math.h +++ b/headers/posix/math.h @@ -178,6 +178,7 @@ extern double lgamma_r(double x, int *y); extern double log1p(double x); extern double logb(double x); extern double nextafter(double x, double y); +extern double nexttoward(double x, long double y); extern double remainder(double x, double y); extern double rint(double x); extern double scalb (double x, double y); @@ -213,12 +214,16 @@ extern float gammaf_r(float x, int *y); extern float lgammaf_r(float x, int *y); extern float rintf(float x); extern float nextafterf(float x, float y); +extern float nexttowardf(float x, long double y); extern float remainderf(float x, float y); extern float scalbf(float x, float n); extern float scalbnf(float x, int n); extern int ilogbf(float x); +extern long double nextafterl(long double x, long double y); +extern long double nexttowardl(long double x, long double y); extern long double remainderl(long double x, long double y); +extern long double rintl(long double x); extern long double scalbnl(long double x, int n); extern long double scalblnl(long double x, long n); diff --git a/src/system/libroot/posix/glibc/arch/generic/s_nexttoward.c b/src/system/libroot/posix/glibc/arch/generic/s_nexttoward.c new file mode 100644 index 0000000000..c68ba98cb3 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_nexttoward.c @@ -0,0 +1 @@ +/* This function is the same as nextafter so we use an alias there. */ diff --git a/src/system/libroot/posix/glibc/arch/generic/s_nexttowardf.c b/src/system/libroot/posix/glibc/arch/generic/s_nexttowardf.c new file mode 100644 index 0000000000..a1c38b5d4c --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_nexttowardf.c @@ -0,0 +1,78 @@ +/* s_nexttowardf.c -- float version of s_nextafter.c. + * 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| */ + + 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)<<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) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_nexttowardl.c b/src/system/libroot/posix/glibc/arch/generic/s_nexttowardl.c new file mode 100644 index 0000000000..73c3610fc1 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_nexttowardl.c @@ -0,0 +1 @@ +/* This function is the same as nextafterl so we use an alias there. */ diff --git a/src/system/libroot/posix/glibc/arch/m68k/Jamfile b/src/system/libroot/posix/glibc/arch/m68k/Jamfile index 42a472a596..20765f47d7 100644 --- a/src/system/libroot/posix/glibc/arch/m68k/Jamfile +++ b/src/system/libroot/posix/glibc/arch/m68k/Jamfile @@ -83,6 +83,7 @@ local genericSources = s_modf.c s_modff.c # s_modfl.c s_nan.c s_nanf.c # s_nanl.c s_nextafter.c s_nextafterf.c # s_nextafterl.c + s_nexttoward.c # s_nexttowardf.c s_nexttowardl.c s_round.c s_roundf.c # s_roundl.c s_scalbn.c s_scalbnf.c # s_scalbnl.c s_signbit.c s_signbitf.c # s_signbitl.c diff --git a/src/system/libroot/posix/glibc/arch/ppc/Jamfile b/src/system/libroot/posix/glibc/arch/ppc/Jamfile index 959deaac34..554fb9ab6c 100644 --- a/src/system/libroot/posix/glibc/arch/ppc/Jamfile +++ b/src/system/libroot/posix/glibc/arch/ppc/Jamfile @@ -80,6 +80,7 @@ local genericSources = s_lround.c s_lroundf.c s_modf.c s_modff.c # s_modfl.c s_nan.c s_nanf.c # s_nanl.c + # s_nexttoward.c s_nexttowardf.c s_nexttowardl.c s_round.c s_roundf.c # s_roundl.c s_scalbn.c s_scalbnf.c # s_scalbnl.c s_signbit.c s_signbitf.c # s_signbitl.c diff --git a/src/system/libroot/posix/glibc/arch/x86/Jamfile b/src/system/libroot/posix/glibc/arch/x86/Jamfile index e02678d629..be5d499357 100644 --- a/src/system/libroot/posix/glibc/arch/x86/Jamfile +++ b/src/system/libroot/posix/glibc/arch/x86/Jamfile @@ -63,6 +63,7 @@ local genericSources = s_modf.c s_modff.c # s_modfl.c s_nan.c s_nanf.c s_nextafter.c s_nextafterf.c + s_nexttowardl.c s_signbit.c s_signbitf.c s_signbitl.c s_round.c s_roundf.c s_roundl.c s_signgam.c @@ -158,6 +159,7 @@ MergeObject posix_gnu_arch_$(TARGET_ARCH)_s.o : s_lrint.S s_lrintf.S s_lrintl.S s_nearbyint.S s_nearbyintf.S s_nearbyintl.S s_nextafterl.c + s_nexttoward.c s_nexttowardf.c s_remquo.S s_remquof.S s_remquol.S s_rint.S s_rintf.S s_rintl.c s_scalbln.c s_scalblnf.c s_scalblnl.c diff --git a/src/system/libroot/posix/glibc/arch/x86/s_nexttoward.c b/src/system/libroot/posix/glibc/arch/x86/s_nexttoward.c new file mode 100644 index 0000000000..2bd768e448 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86/s_nexttoward.c @@ -0,0 +1,106 @@ +/* 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) { + x = x+x; /* overflow */ + /* Force conversion to double. */ + asm ("" : "=m"(x) : "m"(x)); + return x; + } + 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 diff --git a/src/system/libroot/posix/glibc/arch/x86/s_nexttowardf.c b/src/system/libroot/posix/glibc/arch/x86/s_nexttowardf.c new file mode 100644 index 0000000000..3fbe53c338 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86/s_nexttowardf.c @@ -0,0 +1,86 @@ +/* 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) { + x = x+x; /* overflow */ + /* Force conversion to float. */ + asm ("" : "=m"(x) : "m"(x)); + return x; + } + 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)