diff options
Diffstat (limited to 'sysdeps/libm-ieee754')
-rw-r--r-- | sysdeps/libm-ieee754/e_coshf.c | 10 | ||||
-rw-r--r-- | sysdeps/libm-ieee754/e_expf.c | 12 | ||||
-rw-r--r-- | sysdeps/libm-ieee754/e_hypot.c | 24 | ||||
-rw-r--r-- | sysdeps/libm-ieee754/e_hypotf.c | 6 | ||||
-rw-r--r-- | sysdeps/libm-ieee754/e_hypotl.c | 133 | ||||
-rw-r--r-- | sysdeps/libm-ieee754/e_powf.c | 4 | ||||
-rw-r--r-- | sysdeps/libm-ieee754/e_sinhl.c | 91 |
7 files changed, 252 insertions, 28 deletions
diff --git a/sysdeps/libm-ieee754/e_coshf.c b/sysdeps/libm-ieee754/e_coshf.c index e6f4ed6f37..223fbeea20 100644 --- a/sysdeps/libm-ieee754/e_coshf.c +++ b/sysdeps/libm-ieee754/e_coshf.c @@ -8,20 +8,20 @@ * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice + * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #if defined(LIBM_SCCS) && !defined(lint) -static char rcsid[] = "$NetBSD: e_coshf.c,v 1.5 1995/05/10 20:45:01 jtc Exp $"; +static char rcsid[] = "$NetBSD: e_coshf.c,v 1.6 1996/04/08 15:43:41 phil Exp $"; #endif #include "math.h" #include "math_private.h" #ifdef __STDC__ -static const volatile float huge = 1.0e30; +static const float huge = 1.0e30; static const float one = 1.0, half=0.5; #else static float one = 1.0, half=0.5, huge = 1.0e30; @@ -33,7 +33,7 @@ static float one = 1.0, half=0.5, huge = 1.0e30; float __ieee754_coshf(x) float x; #endif -{ +{ float t,w; int32_t ix; @@ -41,7 +41,7 @@ static float one = 1.0, half=0.5, huge = 1.0e30; ix &= 0x7fffffff; /* x is INF or NaN */ - if(ix>=0x7f800000) return x*x; + if(ix>=0x7f800000) return x*x; /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ if(ix<0x3eb17218) { diff --git a/sysdeps/libm-ieee754/e_expf.c b/sysdeps/libm-ieee754/e_expf.c index 80af17918f..fbf2691bf9 100644 --- a/sysdeps/libm-ieee754/e_expf.c +++ b/sysdeps/libm-ieee754/e_expf.c @@ -8,19 +8,19 @@ * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice + * software is freely granted, provided that this notice * is preserved. * ==================================================== */ #if defined(LIBM_SCCS) && !defined(lint) -static char rcsid[] = "$NetBSD: e_expf.c,v 1.5 1995/05/10 20:45:05 jtc Exp $"; +static char rcsid[] = "$NetBSD: e_expf.c,v 1.6 1996/04/08 15:43:43 phil Exp $"; #endif #include "math.h" #include "math_private.h" -static const volatile float huge = 1.0e+30; +static const float huge = 1.0e+30; #ifdef __STDC__ static const float @@ -69,7 +69,7 @@ P5 = 4.1381369442e-08; /* 0x3331bb4c */ } /* argument reduction */ - if(hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ + if(hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ if(hx < 0x3F851592) { /* and |x| < 1.5 ln2 */ hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb; } else { @@ -79,7 +79,7 @@ P5 = 4.1381369442e-08; /* 0x3331bb4c */ lo = t*ln2LO[0]; } x = hi - lo; - } + } else if(hx < 0x31800000) { /* when |x|<2**-28 */ if(huge+x>one) return one+x;/* trigger inexact */ } @@ -88,7 +88,7 @@ P5 = 4.1381369442e-08; /* 0x3331bb4c */ /* x is now in primary range */ t = x*x; c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); - if(k==0) return one-((x*c)/(c-(float)2.0)-x); + if(k==0) return one-((x*c)/(c-(float)2.0)-x); else y = one-((lo-(x*c)/((float)2.0-c))-hi); if(k >= -125) { u_int32_t hy; diff --git a/sysdeps/libm-ieee754/e_hypot.c b/sysdeps/libm-ieee754/e_hypot.c index 24c8ae452f..76a77ec33a 100644 --- a/sysdeps/libm-ieee754/e_hypot.c +++ b/sysdeps/libm-ieee754/e_hypot.c @@ -5,7 +5,7 @@ * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice + * software is freely granted, provided that this notice * is preserved. * ==================================================== */ @@ -16,12 +16,12 @@ static char rcsid[] = "$NetBSD: e_hypot.c,v 1.9 1995/05/12 04:57:27 jtc Exp $"; /* __ieee754_hypot(x,y) * - * Method : - * If (assume round-to-nearest) z=x*x+y*y - * has error less than sqrt(2)/2 ulp, than + * Method : + * If (assume round-to-nearest) z=x*x+y*y + * has error less than sqrt(2)/2 ulp, than * sqrt(z) has error less than 1 ulp (exercise). * - * So, compute sqrt(x*x+y*y) with some care as + * So, compute sqrt(x*x+y*y) with some care as * follows to get the error below 1 ulp: * * Assume x>y>0; @@ -31,10 +31,10 @@ static char rcsid[] = "$NetBSD: e_hypot.c,v 1.9 1995/05/12 04:57:27 jtc Exp $"; * where x1 = x with lower 32 bits cleared, x2 = x-x1; else * 2. if x <= 2y use * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y)) - * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1, + * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1, * y1= y with lower 32 bits chopped, y2 = y-y1. - * - * NOTE: scaling may be necessary if some argument is too + * + * NOTE: scaling may be necessary if some argument is too * large or too tiny * * Special cases: @@ -42,8 +42,8 @@ static char rcsid[] = "$NetBSD: e_hypot.c,v 1.9 1995/05/12 04:57:27 jtc Exp $"; * hypot(x,y) is NAN if x or y is NAN. * * Accuracy: - * hypot(x,y) returns sqrt(x^2+y^2) with error less - * than 1 ulps (units in the last place) + * hypot(x,y) returns sqrt(x^2+y^2) with error less + * than 1 ulps (units in the last place) */ #include "math.h" @@ -56,7 +56,7 @@ static char rcsid[] = "$NetBSD: e_hypot.c,v 1.9 1995/05/12 04:57:27 jtc Exp $"; double x, y; #endif { - double a=x,b=y,t1,t2,y1,y2,w; + double a,b,t1,t2,y1,y2,w; int32_t j,k,ha,hb; GET_HIGH_WORD(ha,x); @@ -84,7 +84,7 @@ static char rcsid[] = "$NetBSD: e_hypot.c,v 1.9 1995/05/12 04:57:27 jtc Exp $"; SET_HIGH_WORD(b,hb); } if(hb < 0x20b00000) { /* b < 2**-500 */ - if(hb <= 0x000fffff) { /* subnormal b or 0 */ + if(hb <= 0x000fffff) { /* subnormal b or 0 */ u_int32_t low; GET_LOW_WORD(low,b); if((hb|low)==0) return a; diff --git a/sysdeps/libm-ieee754/e_hypotf.c b/sysdeps/libm-ieee754/e_hypotf.c index 434cf94e8d..d6b1520cb8 100644 --- a/sysdeps/libm-ieee754/e_hypotf.c +++ b/sysdeps/libm-ieee754/e_hypotf.c @@ -8,7 +8,7 @@ * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice + * software is freely granted, provided that this notice * is preserved. * ==================================================== */ @@ -27,7 +27,7 @@ static char rcsid[] = "$NetBSD: e_hypotf.c,v 1.5 1995/05/12 04:57:30 jtc Exp $"; float x, y; #endif { - float a=x,b=y,t1,t2,y1,y2,w; + float a,b,t1,t2,y1,y2,w; int32_t j,k,ha,hb; GET_FLOAT_WORD(ha,x); @@ -52,7 +52,7 @@ static char rcsid[] = "$NetBSD: e_hypotf.c,v 1.5 1995/05/12 04:57:30 jtc Exp $"; SET_FLOAT_WORD(b,hb); } if(hb < 0x26800000) { /* b < 2**-50 */ - if(hb <= 0x007fffff) { /* subnormal b or 0 */ + if(hb <= 0x007fffff) { /* subnormal b or 0 */ if(hb==0) return a; SET_FLOAT_WORD(t1,0x3f000000); /* t1=2^126 */ b *= t1; diff --git a/sysdeps/libm-ieee754/e_hypotl.c b/sysdeps/libm-ieee754/e_hypotl.c new file mode 100644 index 0000000000..1a40c556dc --- /dev/null +++ b/sysdeps/libm-ieee754/e_hypotl.c @@ -0,0 +1,133 @@ +/* e_hypotl.c -- long double version of e_hypot.c. + * Conversion to long double 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 + +/* __ieee754_hypotl(x,y) + * + * Method : + * If (assume round-to-nearest) z=x*x+y*y + * has error less than sqrt(2)/2 ulp, than + * sqrt(z) has error less than 1 ulp (exercise). + * + * So, compute sqrt(x*x+y*y) with some care as + * follows to get the error below 1 ulp: + * + * Assume x>y>0; + * (if possible, set rounding to round-to-nearest) + * 1. if x > 2y use + * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y + * where x1 = x with lower 32 bits cleared, x2 = x-x1; else + * 2. if x <= 2y use + * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y)) + * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1, + * y1= y with lower 32 bits chopped, y2 = y-y1. + * + * NOTE: scaling may be necessary if some argument is too + * large or too tiny + * + * Special cases: + * hypot(x,y) is INF if x or y is +INF or -INF; else + * hypot(x,y) is NAN if x or y is NAN. + * + * Accuracy: + * hypot(x,y) returns sqrt(x^2+y^2) with error less + * than 1 ulps (units in the last place) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + long double __ieee754_hypotl(long double x, long double y) +#else + long double __ieee754_hypotl(x,y) + long double x, y; +#endif +{ + long double a,b,t1,t2,y1,y2,w; + u_int32_t j,k,ea,eb; + + GET_LDOUBLE_EXP(ea,x); + ea &= 0x7fff; + GET_LDOUBLE_EXP(eb,y); + eb &= 0x7fff; + if(eb > ea) {a=y;b=x;j=ea; ea=eb;eb=j;} else {a=x;b=y;} + SET_LDOUBLE_EXP(a,ea); /* a <- |a| */ + SET_LDOUBLE_EXP(b,eb); /* b <- |b| */ + if((ea-eb)>0x46) {return a+b;} /* x/y > 2**70 */ + k=0; + if(ea > 0x5f3f) { /* a>2**8000 */ + if(ea == 0x7fff) { /* Inf or NaN */ + u_int32_t exp,high,low; + w = a+b; /* for sNaN */ + GET_LDOUBLE_WORDS(exp,high,low,a); + if(((high&0x7fffffff)|low)==0) w = a; + GET_LDOUBLE_WORDS(exp,high,low,b); + if(((eb^0x7fff)|(high&0x7fffffff)|low)==0) w = b; + return w; + } + /* scale a and b by 2**-9600 */ + ea -= 0x2580; eb -= 0x2580; k += 9600; + SET_LDOUBLE_EXP(a,ea); + SET_LDOUBLE_EXP(b,eb); + } + if(eb < 0x20bf) { /* b < 2**-8000 */ + if(eb == 0) { /* subnormal b or 0 */ + u_int32_t exp,high,low; + GET_LDOUBLE_WORDS(exp,high,low,b); + if((high|low)==0) return a; + SET_LDOUBLE_WORDS(t1, 0x7ffd, 0, 0); /* t1=2^16382 */ + b *= t1; + a *= t1; + k -= 16382; + } else { /* scale a and b by 2^9600 */ + ea += 0x2580; /* a *= 2^9600 */ + eb += 0x2580; /* b *= 2^9600 */ + k -= 9600; + SET_LDOUBLE_EXP(a,ea); + SET_LDOUBLE_EXP(b,eb); + } + } + /* medium size a and b */ + w = a-b; + if (w>b) { + u_int32_t high; + GET_LDOUBLE_MSW(high,a); + SET_LDOUBLE_WORDS(t1,ea,high,0); + t2 = a-t1; + w = __ieee754_sqrtl(t1*t1-(b*(-b)-t2*(a+t1))); + } else { + u_int32_t high; + GET_LDOUBLE_MSW(high,b); + a = a+a; + SET_LDOUBLE_WORDS(y1,eb,high,0); + y2 = b - y1; + GET_LDOUBLE_MSW(high,a); + SET_LDOUBLE_WORDS(t1,ea+1,high,0); + t2 = a - t1; + w = __ieee754_sqrtl(t1*y1-(w*(-w)-(t1*y2+t2*b))); + } + if(k!=0) { + u_int32_t exp; + t1 = 1.0; + GET_LDOUBLE_EXP(exp,t1); + SET_LDOUBLE_EXP(t1,exp+k); + return t1*w; + } else return w; +} diff --git a/sysdeps/libm-ieee754/e_powf.c b/sysdeps/libm-ieee754/e_powf.c index 1358555128..4798340c84 100644 --- a/sysdeps/libm-ieee754/e_powf.c +++ b/sysdeps/libm-ieee754/e_powf.c @@ -14,13 +14,13 @@ */ #if defined(LIBM_SCCS) && !defined(lint) -static char rcsid[] = "$NetBSD: e_powf.c,v 1.6 1995/05/12 04:57:35 jtc Exp $"; +static char rcsid[] = "$NetBSD: e_powf.c,v 1.7 1996/04/08 15:43:44 phil Exp $"; #endif #include "math.h" #include "math_private.h" -static const volatile float huge = 1.0e+30, tiny = 1.0e-30; +static const float huge = 1.0e+30, tiny = 1.0e-30; #ifdef __STDC__ static const float diff --git a/sysdeps/libm-ieee754/e_sinhl.c b/sysdeps/libm-ieee754/e_sinhl.c new file mode 100644 index 0000000000..2d98562f94 --- /dev/null +++ b/sysdeps/libm-ieee754/e_sinhl.c @@ -0,0 +1,91 @@ +/* e_asinhl.c -- long double version of e_asinh.c. + * Conversion to long double 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 + +/* __ieee754_sinhl(x) + * Method : + * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2 + * 1. Replace x by |x| (sinhl(-x) = -sinhl(x)). + * 2. + * E + E/(E+1) + * 0 <= x <= 25 : sinhl(x) := --------------, E=expm1l(x) + * 2 + * + * 25 <= x <= lnovft : sinhl(x) := expl(x)/2 + * lnovft <= x <= ln2ovft: sinhl(x) := expl(x/2)/2 * expl(x/2) + * ln2ovft < x : sinhl(x) := x*shuge (overflow) + * + * Special cases: + * sinhl(x) is |x| if x is +INF, -INF, or NaN. + * only sinhl(0)=0 is exact for finite x. + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const long double one = 1.0, shuge = 1.0e4931L; +#else +static long double one = 1.0, shuge = 1.0e4931L; +#endif + +#ifdef __STDC__ + long double __ieee754_sinhl(long double x) +#else + long double __ieee754_sinhl(x) + long double x; +#endif +{ + long double t,w,h; + u_int32_t jx,ix,i0,i1; + + /* Words of |x|. */ + GET_LDOUBLE_WORDS(jx,i0,i1,x); + ix = jx&0x7fff; + + /* x is INF or NaN */ + if(ix==0x7fff) return x+x; + + h = 0.5; + if (jx<0) h = -h; + /* |x| in [0,25], return sign(x)*0.5*(E+E/(E+1))) */ + if (ix < 0x4003 || (ix == 0x4003 && i0 <= 0xc8000000)) { /* |x|<25 */ + if (ix<0x3fe3) /* |x|<2**-28 */ + if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */ + t = __expm1l(fabsl(x)); + if(ix<0x3fff) return h*(2.0*t-t*t/(t+one)); + return h*(t+t/(t+one)); + } + + /* |x| in [25, log(maxdouble)] return 0.5*exp(|x|) */ + if (ix < 0x400c || (ix == 0x400c && i0 < 0xb17217f7)) + return h*__ieee754_expl(fabsl(x)); + + /* |x| in [log(maxdouble), overflowthresold] */ + if (ix<0x400c || (ix == 0x400c && (i0 < 0xb174ddc0 + || (i0 == 0xb174ddc0 + && i1 <= 0x31aec0ea)))) { + w = __ieee754_expl(0.5*fabsl(x)); + t = h*w; + return t*w; + } + + /* |x| > overflowthresold, sinhl(x) overflow */ + return x*shuge; +} |