| Elliott Hughes | a0ee078 | 2013-01-30 19:06:37 -0800 | [diff] [blame] | 1 |  | 
| Elliott Hughes | a0ee078 | 2013-01-30 19:06:37 -0800 | [diff] [blame] | 2 | /* FreeBSD: head/lib/msun/src/e_acos.c 176451 2008-02-22 02:30:36Z das */ | 
 | 3 | /* | 
 | 4 |  * ==================================================== | 
 | 5 |  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. | 
 | 6 |  * | 
 | 7 |  * Developed at SunSoft, a Sun Microsystems, Inc. business. | 
 | 8 |  * Permission to use, copy, modify, and distribute this | 
 | 9 |  * software is freely granted, provided that this notice  | 
 | 10 |  * is preserved. | 
 | 11 |  * ==================================================== | 
 | 12 |  */ | 
 | 13 |  | 
| Elliott Hughes | a0ee078 | 2013-01-30 19:06:37 -0800 | [diff] [blame] | 14 | /* | 
 | 15 |  * See comments in e_acos.c. | 
 | 16 |  * Converted to long double by David Schultz <das@FreeBSD.ORG>. | 
 | 17 |  */ | 
 | 18 |  | 
 | 19 | #include <float.h> | 
 | 20 |  | 
 | 21 | #include "invtrig.h" | 
 | 22 | #include "math.h" | 
 | 23 | #include "math_private.h" | 
 | 24 |  | 
 | 25 | static const long double | 
 | 26 | one=  1.00000000000000000000e+00; | 
 | 27 |  | 
 | 28 | #ifdef __i386__ | 
 | 29 | /* XXX Work around the fact that gcc truncates long double constants on i386 */ | 
 | 30 | static volatile double | 
 | 31 | pi1 =  3.14159265358979311600e+00,	/*  0x1.921fb54442d18p+1  */ | 
 | 32 | pi2 =  1.22514845490862001043e-16;	/*  0x1.1a80000000000p-53 */ | 
 | 33 | #define	pi	((long double)pi1 + pi2) | 
 | 34 | #else | 
 | 35 | static const long double | 
 | 36 | pi =  3.14159265358979323846264338327950280e+00L; | 
 | 37 | #endif | 
 | 38 |  | 
 | 39 | long double | 
 | 40 | acosl(long double x) | 
 | 41 | { | 
 | 42 | 	union IEEEl2bits u; | 
 | 43 | 	long double z,p,q,r,w,s,c,df; | 
 | 44 | 	int16_t expsign, expt; | 
 | 45 | 	u.e = x; | 
 | 46 | 	expsign = u.xbits.expsign; | 
 | 47 | 	expt = expsign & 0x7fff; | 
 | 48 | 	if(expt >= BIAS) {	/* |x| >= 1 */ | 
 | 49 | 	    if(expt==BIAS && ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)==0) { | 
 | 50 | 		if (expsign>0) return 0.0;	/* acos(1) = 0  */ | 
 | 51 | 		else return pi+2.0*pio2_lo;	/* acos(-1)= pi */ | 
 | 52 | 	    } | 
 | 53 | 	    return (x-x)/(x-x);		/* acos(|x|>1) is NaN */ | 
 | 54 | 	} | 
 | 55 | 	if(expt<BIAS-1) {	/* |x| < 0.5 */ | 
 | 56 | 	    if(expt<ACOS_CONST) return pio2_hi+pio2_lo;/*x tiny: acosl=pi/2*/ | 
 | 57 | 	    z = x*x; | 
 | 58 | 	    p = P(z); | 
 | 59 | 	    q = Q(z); | 
 | 60 | 	    r = p/q; | 
 | 61 | 	    return pio2_hi - (x - (pio2_lo-x*r)); | 
 | 62 | 	} else  if (expsign<0) {	/* x < -0.5 */ | 
 | 63 | 	    z = (one+x)*0.5; | 
 | 64 | 	    p = P(z); | 
 | 65 | 	    q = Q(z); | 
 | 66 | 	    s = sqrtl(z); | 
 | 67 | 	    r = p/q; | 
 | 68 | 	    w = r*s-pio2_lo; | 
 | 69 | 	    return pi - 2.0*(s+w); | 
 | 70 | 	} else {			/* x > 0.5 */ | 
 | 71 | 	    z = (one-x)*0.5; | 
 | 72 | 	    s = sqrtl(z); | 
 | 73 | 	    u.e = s; | 
 | 74 | 	    u.bits.manl = 0; | 
 | 75 | 	    df = u.e; | 
 | 76 | 	    c  = (z-df*df)/(s+df); | 
 | 77 | 	    p = P(z); | 
 | 78 | 	    q = Q(z); | 
 | 79 | 	    r = p/q; | 
 | 80 | 	    w = r*s+c; | 
 | 81 | 	    return 2.0*(df+w); | 
 | 82 | 	} | 
 | 83 | } |