diff options
author | das <das@FreeBSD.org> | 2008-07-31 22:41:26 +0000 |
---|---|---|
committer | das <das@FreeBSD.org> | 2008-07-31 22:41:26 +0000 |
commit | fea2240d10b31df0708048e117338954d65683f2 (patch) | |
tree | 9fb6bc383ad54766e5719d186bb7517c92a90c9f /lib/msun/src | |
parent | 9c7525b3ac9d147ed50fdd2bbd0728d63af7968a (diff) | |
download | FreeBSD-src-fea2240d10b31df0708048e117338954d65683f2.zip FreeBSD-src-fea2240d10b31df0708048e117338954d65683f2.tar.gz |
Add implementations of acosl(), asinl(), atanl(), atan2l(),
and cargl().
Reviewed by: bde
sparc64 testing resources from: remko
Diffstat (limited to 'lib/msun/src')
-rw-r--r-- | lib/msun/src/e_acos.c | 6 | ||||
-rw-r--r-- | lib/msun/src/e_acosl.c | 77 | ||||
-rw-r--r-- | lib/msun/src/e_asin.c | 5 | ||||
-rw-r--r-- | lib/msun/src/e_asinl.c | 77 | ||||
-rw-r--r-- | lib/msun/src/e_atan2.c | 6 | ||||
-rw-r--r-- | lib/msun/src/e_atan2l.c | 107 | ||||
-rw-r--r-- | lib/msun/src/math.h | 6 | ||||
-rw-r--r-- | lib/msun/src/s_atan.c | 6 | ||||
-rw-r--r-- | lib/msun/src/s_atanl.c | 85 | ||||
-rw-r--r-- | lib/msun/src/s_cargl.c | 38 |
10 files changed, 413 insertions, 0 deletions
diff --git a/lib/msun/src/e_acos.c b/lib/msun/src/e_acos.c index 5b1b85a..1f6dca5 100644 --- a/lib/msun/src/e_acos.c +++ b/lib/msun/src/e_acos.c @@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$"); * Function needed: sqrt */ +#include <float.h> + #include "math.h" #include "math_private.h" @@ -103,3 +105,7 @@ __ieee754_acos(double x) return 2.0*(df+w); } } + +#if LDBL_MANT_DIG == 53 +__weak_reference(acos, acosl); +#endif diff --git a/lib/msun/src/e_acosl.c b/lib/msun/src/e_acosl.c new file mode 100644 index 0000000..4e9df52 --- /dev/null +++ b/lib/msun/src/e_acosl.c @@ -0,0 +1,77 @@ + +/* @(#)e_acos.c 1.3 95/01/18 */ +/* FreeBSD: head/lib/msun/src/e_acos.c 176451 2008-02-22 02:30:36Z das */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * See comments in e_acos.c. + * Converted to long double by David Schultz <das@FreeBSD.ORG>. + */ + +#include <float.h> + +#include "invtrig.h" +#include "math.h" +#include "math_private.h" + +static const long double +one= 1.00000000000000000000e+00, +pi = 3.14159265358979323846264338327950280e+00L; + +long double +acosl(long double x) +{ + union IEEEl2bits u; + long double z,p,q,r,w,s,c,df; + int16_t expsign, expt; + u.e = x; + expsign = u.xbits.expsign; + expt = expsign & 0x7fff; + if(expt >= BIAS) { /* |x| >= 1 */ + if(expt==BIAS && ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)==0) { + if (expsign>0) return 0.0; /* acos(1) = 0 */ + else return pi+2.0*pio2_lo; /* acos(-1)= pi */ + } + return (x-x)/(x-x); /* acos(|x|>1) is NaN */ + } + if(expt<BIAS-1) { /* |x| < 0.5 */ + if(expt<ACOS_CONST) return pio2_hi+pio2_lo;/*x tiny: acosl=pi/2*/ + z = x*x; + p = P(z); + q = Q(z); + r = p/q; + return pio2_hi - (x - (pio2_lo-x*r)); + } else if (expsign<0) { /* x < -0.5 */ + z = (one+x)*0.5; + p = P(z); + q = Q(z); + s = sqrtl(z); + r = p/q; + w = r*s-pio2_lo; + return pi - 2.0*(s+w); + } else { /* x > 0.5 */ + z = (one-x)*0.5; + s = sqrtl(z); + u.e = s; + u.bits.manl = 0; + df = u.e; + c = (z-df*df)/(s+df); + p = P(z); + q = Q(z); + r = p/q; + w = r*s+c; + return 2.0*(df+w); + } +} diff --git a/lib/msun/src/e_asin.c b/lib/msun/src/e_asin.c index 149a533..4458604 100644 --- a/lib/msun/src/e_asin.c +++ b/lib/msun/src/e_asin.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); * */ +#include <float.h> #include "math.h" #include "math_private.h" @@ -110,3 +111,7 @@ __ieee754_asin(double x) } if(hx>0) return t; else return -t; } + +#if LDBL_MANT_DIG == 53 +__weak_reference(asin, asinl); +#endif diff --git a/lib/msun/src/e_asinl.c b/lib/msun/src/e_asinl.c new file mode 100644 index 0000000..ee7f5af --- /dev/null +++ b/lib/msun/src/e_asinl.c @@ -0,0 +1,77 @@ + +/* @(#)e_asin.c 1.3 95/01/18 */ +/* FreeBSD: head/lib/msun/src/e_asin.c 176451 2008-02-22 02:30:36Z das */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * See comments in e_asin.c. + * Converted to long double by David Schultz <das@FreeBSD.ORG>. + */ + +#include <float.h> + +#include "invtrig.h" +#include "math.h" +#include "math_private.h" + +static const long double +one = 1.00000000000000000000e+00, +huge = 1.000e+300; + +long double +asinl(long double x) +{ + union IEEEl2bits u; + long double t=0.0,w,p,q,c,r,s; + int16_t expsign, expt; + u.e = x; + expsign = u.xbits.expsign; + expt = expsign & 0x7fff; + if(expt >= BIAS) { /* |x|>= 1 */ + if(expt==BIAS && ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)==0) + /* asin(1)=+-pi/2 with inexact */ + return x*pio2_hi+x*pio2_lo; + return (x-x)/(x-x); /* asin(|x|>1) is NaN */ + } else if (expt<BIAS-1) { /* |x|<0.5 */ + if(expt<ASIN_LINEAR) { /* if |x| is small, asinl(x)=x */ + if(huge+x>one) return x;/* return x with inexact if x!=0*/ + } else + t = x*x; + p = P(t); + q = Q(t); + w = p/q; + return x+x*w; + } + /* 1> |x|>= 0.5 */ + w = one-fabsl(x); + t = w*0.5; + p = P(t); + q = Q(t); + s = sqrtl(t); + if(u.bits.manh>=THRESH) { /* if |x| is close to 1 */ + w = p/q; + t = pio2_hi-(2.0*(s+s*w)-pio2_lo); + } else { + u.e = s; + u.bits.manl = 0; + w = u.e; + c = (t-w*w)/(s+w); + r = p/q; + p = 2.0*s*r-(pio2_lo-2.0*c); + q = pio4_hi-2.0*w; + t = pio4_hi-(p-q); + } + if(expsign>0) return t; else return -t; +} diff --git a/lib/msun/src/e_atan2.c b/lib/msun/src/e_atan2.c index ba0b618..399822a 100644 --- a/lib/msun/src/e_atan2.c +++ b/lib/msun/src/e_atan2.c @@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$"); * to produce the hexadecimal values shown. */ +#include <float.h> + #include "math.h" #include "math_private.h" @@ -123,3 +125,7 @@ __ieee754_atan2(double y, double x) return (z-pi_lo)-pi;/* atan(-,-) */ } } + +#if LDBL_MANT_DIG == 53 +__weak_reference(atan2, atan2l); +#endif diff --git a/lib/msun/src/e_atan2l.c b/lib/msun/src/e_atan2l.c new file mode 100644 index 0000000..8368bbf --- /dev/null +++ b/lib/msun/src/e_atan2l.c @@ -0,0 +1,107 @@ + +/* @(#)e_atan2.c 1.3 95/01/18 */ +/* FreeBSD: head/lib/msun/src/e_atan2.c 176451 2008-02-22 02:30:36Z das */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * See comments in e_atan2.c. + * Converted to long double by David Schultz <das@FreeBSD.ORG>. + */ + +#include <float.h> + +#include "invtrig.h" +#include "math.h" +#include "math_private.h" + +static volatile long double +tiny = 1.0e-300; +static const long double +zero = 0.0, +pi = 3.14159265358979323846264338327950280e+00L; + +long double +atan2l(long double y, long double x) +{ + union IEEEl2bits ux, uy; + long double z; + int32_t k,m; + int16_t exptx, expsignx, expty, expsigny; + + uy.e = y; + expsigny = uy.xbits.expsign; + expty = expsigny & 0x7fff; + ux.e = x; + expsignx = ux.xbits.expsign; + exptx = expsignx & 0x7fff; + + if ((exptx==BIAS+LDBL_MAX_EXP && + ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)!=0) || /* x is NaN */ + (expty==BIAS+LDBL_MAX_EXP && + ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* y is NaN */ + return x+y; + if (expsignx==BIAS && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0) + return atanl(y); /* x=1.0 */ + m = ((expsigny>>15)&1)|((expsignx>>14)&2); /* 2*sign(x)+sign(y) */ + + /* when y = 0 */ + if(expty==0 && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)==0) { + switch(m) { + case 0: + case 1: return y; /* atan(+-0,+anything)=+-0 */ + case 2: return pi+tiny;/* atan(+0,-anything) = pi */ + case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ + } + } + /* when x = 0 */ + if(exptx==0 && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0) + return (expsigny<0)? -pio2_hi-tiny: pio2_hi+tiny; + + /* when x is INF */ + if(exptx==BIAS+LDBL_MAX_EXP) { + if(expty==BIAS+LDBL_MAX_EXP) { + switch(m) { + case 0: return pio2_hi*0.5+tiny;/* atan(+INF,+INF) */ + case 1: return -pio2_hi*0.5-tiny;/* atan(-INF,+INF) */ + case 2: return 1.5*pio2_hi+tiny;/*atan(+INF,-INF)*/ + case 3: return -1.5*pio2_hi-tiny;/*atan(-INF,-INF)*/ + } + } else { + switch(m) { + case 0: return zero ; /* atan(+...,+INF) */ + case 1: return -zero ; /* atan(-...,+INF) */ + case 2: return pi+tiny ; /* atan(+...,-INF) */ + case 3: return -pi-tiny ; /* atan(-...,-INF) */ + } + } + } + /* when y is INF */ + if(expty==BIAS+LDBL_MAX_EXP) + return (expsigny<0)? -pio2_hi-tiny: pio2_hi+tiny; + + /* compute y/x */ + k = expty-exptx; + if(k > LDBL_MANT_DIG+2) z=pio2_hi+pio2_lo; /* |y/x| huge */ + else if(expsignx<0&&k<-LDBL_MANT_DIG-2) z=0.0; /* |y/x| tiny, x<0 */ + else z=atanl(fabsl(y/x)); /* safe to do y/x */ + switch (m) { + case 0: return z ; /* atan(+,+) */ + case 1: return -z ; /* atan(-,+) */ + case 2: return pi-(z-pi_lo);/* atan(+,-) */ + default: /* case 3 */ + return (z-pi_lo)-pi;/* atan(-,-) */ + } +} diff --git a/lib/msun/src/math.h b/lib/msun/src/math.h index 97d1a58..374f95f 100644 --- a/lib/msun/src/math.h +++ b/lib/msun/src/math.h @@ -394,12 +394,18 @@ float significandf(float); #if __ISO_C_VISIBLE >= 1999 #if 0 long double acoshl(long double); +#endif long double acosl(long double); +#if 0 long double asinhl(long double); +#endif long double asinl(long double); long double atan2l(long double, long double); +#if 0 long double atanhl(long double); +#endif long double atanl(long double); +#if 0 long double cbrtl(long double); #endif long double ceill(long double); diff --git a/lib/msun/src/s_atan.c b/lib/msun/src/s_atan.c index 01e7bea..24daed5 100644 --- a/lib/msun/src/s_atan.c +++ b/lib/msun/src/s_atan.c @@ -33,6 +33,8 @@ __FBSDID("$FreeBSD$"); * to produce the hexadecimal values shown. */ +#include <float.h> + #include "math.h" #include "math_private.h" @@ -116,3 +118,7 @@ atan(double x) return (hx<0)? -z:z; } } + +#if LDBL_MANT_DIG == 53 +__weak_reference(atan, atanl); +#endif diff --git a/lib/msun/src/s_atanl.c b/lib/msun/src/s_atanl.c new file mode 100644 index 0000000..ff29c3c --- /dev/null +++ b/lib/msun/src/s_atanl.c @@ -0,0 +1,85 @@ +/* @(#)s_atan.c 5.1 93/09/24 */ +/* FreeBSD: head/lib/msun/src/s_atan.c 176451 2008-02-22 02:30:36Z das */ +/* + * ==================================================== + * 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. + * ==================================================== + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * See comments in s_atan.c. + * Converted to long double by David Schultz <das@FreeBSD.ORG>. + */ + +#include <float.h> + +#include "invtrig.h" +#include "math.h" +#include "math_private.h" + +static const long double +one = 1.0, +huge = 1.0e300; + +long double +atanl(long double x) +{ + union IEEEl2bits u; + long double w,s1,s2,z; + int id; + int16_t expsign, expt; + int32_t expman; + + u.e = x; + expsign = u.xbits.expsign; + expt = expsign & 0x7fff; + if(expt >= ATAN_CONST) { /* if |x| is large, atan(x)~=pi/2 */ + if(expt == BIAS + LDBL_MAX_EXP && + ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)!=0) + return x+x; /* NaN */ + if(expsign>0) return atanhi[3]+atanlo[3]; + else return -atanhi[3]-atanlo[3]; + } + /* Extract the exponent and the first few bits of the mantissa. */ + /* XXX There should be a more convenient way to do this. */ + expman = (expt << 8) | ((u.bits.manh >> (MANH_SIZE - 9)) & 0xff); + if (expman < ((BIAS - 2) << 8) + 0xc0) { /* |x| < 0.4375 */ + if (expt < ATAN_LINEAR) { /* if |x| is small, atanl(x)~=x */ + if(huge+x>one) return x; /* raise inexact */ + } + id = -1; + } else { + x = fabsl(x); + if (expman < (BIAS << 8) + 0x30) { /* |x| < 1.1875 */ + if (expman < ((BIAS - 1) << 8) + 0x60) { /* 7/16 <=|x|<11/16 */ + id = 0; x = (2.0*x-one)/(2.0+x); + } else { /* 11/16<=|x|< 19/16 */ + id = 1; x = (x-one)/(x+one); + } + } else { + if (expman < ((BIAS + 1) << 8) + 0x38) { /* |x| < 2.4375 */ + id = 2; x = (x-1.5)/(one+1.5*x); + } else { /* 2.4375 <= |x| < 2^ATAN_CONST */ + id = 3; x = -1.0/x; + } + }} + /* end of argument reduction */ + z = x*x; + w = z*z; + /* break sum aT[i]z**(i+1) into odd and even poly */ + s1 = z*T_even(w); + s2 = w*T_odd(w); + if (id<0) return x - x*(s1+s2); + else { + z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); + return (expsign<0)? -z:z; + } +} diff --git a/lib/msun/src/s_cargl.c b/lib/msun/src/s_cargl.c new file mode 100644 index 0000000..0555083 --- /dev/null +++ b/lib/msun/src/s_cargl.c @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2005-2008 David Schultz <das@FreeBSD.ORG> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <complex.h> +#include <math.h> + +long double +cargl(long double complex z) +{ + + return (atan2l(cimagl(z), creall(z))); +} |