xref: /illumos-gate/usr/src/lib/libm/common/Q/atanl.c (revision ddc0e0b5)
125c28e83SPiotr Jasiukajtis /*
225c28e83SPiotr Jasiukajtis  * CDDL HEADER START
325c28e83SPiotr Jasiukajtis  *
425c28e83SPiotr Jasiukajtis  * The contents of this file are subject to the terms of the
525c28e83SPiotr Jasiukajtis  * Common Development and Distribution License (the "License").
625c28e83SPiotr Jasiukajtis  * You may not use this file except in compliance with the License.
725c28e83SPiotr Jasiukajtis  *
825c28e83SPiotr Jasiukajtis  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
925c28e83SPiotr Jasiukajtis  * or http://www.opensolaris.org/os/licensing.
1025c28e83SPiotr Jasiukajtis  * See the License for the specific language governing permissions
1125c28e83SPiotr Jasiukajtis  * and limitations under the License.
1225c28e83SPiotr Jasiukajtis  *
1325c28e83SPiotr Jasiukajtis  * When distributing Covered Code, include this CDDL HEADER in each
1425c28e83SPiotr Jasiukajtis  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1525c28e83SPiotr Jasiukajtis  * If applicable, add the following below this CDDL HEADER, with the
1625c28e83SPiotr Jasiukajtis  * fields enclosed by brackets "[]" replaced with your own identifying
1725c28e83SPiotr Jasiukajtis  * information: Portions Copyright [yyyy] [name of copyright owner]
1825c28e83SPiotr Jasiukajtis  *
1925c28e83SPiotr Jasiukajtis  * CDDL HEADER END
2025c28e83SPiotr Jasiukajtis  */
2125c28e83SPiotr Jasiukajtis 
2225c28e83SPiotr Jasiukajtis /*
2325c28e83SPiotr Jasiukajtis  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
2425c28e83SPiotr Jasiukajtis  */
2525c28e83SPiotr Jasiukajtis /*
2625c28e83SPiotr Jasiukajtis  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
2725c28e83SPiotr Jasiukajtis  * Use is subject to license terms.
2825c28e83SPiotr Jasiukajtis  */
2925c28e83SPiotr Jasiukajtis 
30*ddc0e0b5SRichard Lowe #pragma weak __atanl = atanl
3125c28e83SPiotr Jasiukajtis 
3225c28e83SPiotr Jasiukajtis /*
3325c28e83SPiotr Jasiukajtis  * atanl(x)
3425c28e83SPiotr Jasiukajtis  * Table look-up algorithm
3525c28e83SPiotr Jasiukajtis  * By K.C. Ng, March 9, 1989
3625c28e83SPiotr Jasiukajtis  *
3725c28e83SPiotr Jasiukajtis  * Algorithm.
3825c28e83SPiotr Jasiukajtis  *
3925c28e83SPiotr Jasiukajtis  * The algorithm is based on atan(x)=atan(y)+atan((x-y)/(1+x*y)).
4025c28e83SPiotr Jasiukajtis  * We use poly1(x) to approximate atan(x) for x in [0,1/8] with
4125c28e83SPiotr Jasiukajtis  * error (relative)
4225c28e83SPiotr Jasiukajtis  * 	|(atan(x)-poly1(x))/x|<= 2^-115.94 	long double
4325c28e83SPiotr Jasiukajtis  * 	|(atan(x)-poly1(x))/x|<= 2^-58.85	double
4425c28e83SPiotr Jasiukajtis  * 	|(atan(x)-poly1(x))/x|<= 2^-25.53 	float
4525c28e83SPiotr Jasiukajtis  * and use poly2(x) to approximate atan(x) for x in [0,1/65] with
4625c28e83SPiotr Jasiukajtis  * error (absolute)
4725c28e83SPiotr Jasiukajtis  *	|atan(x)-poly2(x)|<= 2^-122.15		long double
4825c28e83SPiotr Jasiukajtis  *	|atan(x)-poly2(x)|<= 2^-64.79		double
4925c28e83SPiotr Jasiukajtis  *	|atan(x)-poly2(x)|<= 2^-35.36		float
5025c28e83SPiotr Jasiukajtis  * Here poly1 and poly2 are odd polynomial with the following form:
5125c28e83SPiotr Jasiukajtis  *		x + x^3*(a1+x^2*(a2+...))
5225c28e83SPiotr Jasiukajtis  *
5325c28e83SPiotr Jasiukajtis  * (0). Purge off Inf and NaN and 0
5425c28e83SPiotr Jasiukajtis  * (1). Reduce x to positive by atan(x) = -atan(-x).
5525c28e83SPiotr Jasiukajtis  * (2). For x <= 1/8, use
5625c28e83SPiotr Jasiukajtis  *	(2.1) if x < 2^(-prec/2-2), atan(x) =  x  with inexact
5725c28e83SPiotr Jasiukajtis  *	(2.2) Otherwise
5825c28e83SPiotr Jasiukajtis  *		atan(x) = poly1(x)
5925c28e83SPiotr Jasiukajtis  * (3). For x >= 8 then
6025c28e83SPiotr Jasiukajtis  *	(3.1) if x >= 2^(prec+2),   atan(x) = atan(inf) - pio2lo
6125c28e83SPiotr Jasiukajtis  *	(3.2) if x >= 2^(prec/3+2), atan(x) = atan(inf) - 1/x
6225c28e83SPiotr Jasiukajtis  *	(3.3) if x >  65,           atan(x) = atan(inf) - poly2(1/x)
6325c28e83SPiotr Jasiukajtis  *	(3.4) Otherwise,	    atan(x) = atan(inf) - poly1(1/x)
6425c28e83SPiotr Jasiukajtis  *
6525c28e83SPiotr Jasiukajtis  * (4). Now x is in (0.125, 8)
6625c28e83SPiotr Jasiukajtis  *      Find y that match x to 4.5 bit after binary (easy).
6725c28e83SPiotr Jasiukajtis  *	If iy is the high word of y, then
6825c28e83SPiotr Jasiukajtis  *		single : j = (iy - 0x3e000000) >> 19
6925c28e83SPiotr Jasiukajtis  *		double : j = (iy - 0x3fc00000) >> 16
7025c28e83SPiotr Jasiukajtis  *		quad   : j = (iy - 0x3ffc0000) >> 12
7125c28e83SPiotr Jasiukajtis  *
7225c28e83SPiotr Jasiukajtis  *	Let s = (x-y)/(1+x*y). Then
7325c28e83SPiotr Jasiukajtis  *	atan(x) = atan(y) + poly1(s)
7425c28e83SPiotr Jasiukajtis  *		= _TBL_atanl_hi[j] + (_TBL_atanl_lo[j] + poly2(s) )
7525c28e83SPiotr Jasiukajtis  *
7625c28e83SPiotr Jasiukajtis  *	Note. |s| <= 1.5384615385e-02 = 1/65. Maxium occurs at x = 1.03125
7725c28e83SPiotr Jasiukajtis  *
7825c28e83SPiotr Jasiukajtis  */
7925c28e83SPiotr Jasiukajtis 
8025c28e83SPiotr Jasiukajtis #include "libm.h"
8125c28e83SPiotr Jasiukajtis 
8225c28e83SPiotr Jasiukajtis extern const long double _TBL_atanl_hi[], _TBL_atanl_lo[];
8325c28e83SPiotr Jasiukajtis static const long double
8425c28e83SPiotr Jasiukajtis 	one	=   1.0L,
8525c28e83SPiotr Jasiukajtis 	p1  	=  -3.333333333333333333333333333331344526118e-0001L,
8625c28e83SPiotr Jasiukajtis 	p2  	=   1.999999999999999999999999989931277668570e-0001L,
8725c28e83SPiotr Jasiukajtis 	p3  	=  -1.428571428571428571428553606221309530901e-0001L,
8825c28e83SPiotr Jasiukajtis 	p4  	=   1.111111111111111111095219842737139747418e-0001L,
8925c28e83SPiotr Jasiukajtis 	p5  	=  -9.090909090909090825503603835248061123323e-0002L,
9025c28e83SPiotr Jasiukajtis 	p6  	=   7.692307692307664052130743214708925258904e-0002L,
9125c28e83SPiotr Jasiukajtis 	p7  	=  -6.666666666660213835187713228363717388266e-0002L,
9225c28e83SPiotr Jasiukajtis 	p8  	=   5.882352940152439399097283359608661949504e-0002L,
9325c28e83SPiotr Jasiukajtis 	p9  	=  -5.263157780447533993046614040509529668487e-0002L,
9425c28e83SPiotr Jasiukajtis 	p10 	=   4.761895816878184933175855990886788439447e-0002L,
9525c28e83SPiotr Jasiukajtis 	p11 	=  -4.347345005832274022681019724553538135922e-0002L,
9625c28e83SPiotr Jasiukajtis 	p12 	=   3.983031914579635037502589204647752042736e-0002L,
9725c28e83SPiotr Jasiukajtis 	p13 	=  -3.348206704469830575196657749413894897554e-0002L,
9825c28e83SPiotr Jasiukajtis 	q1  	=  -3.333333333333333333333333333195273650186e-0001L,
9925c28e83SPiotr Jasiukajtis 	q2  	=   1.999999999999999999999988146114392615808e-0001L,
10025c28e83SPiotr Jasiukajtis 	q3  	=  -1.428571428571428571057630319435467111253e-0001L,
10125c28e83SPiotr Jasiukajtis 	q4  	=   1.111111111111105373263048208994541544098e-0001L,
10225c28e83SPiotr Jasiukajtis 	q5  	=  -9.090909090421834209167373258681021816441e-0002L,
10325c28e83SPiotr Jasiukajtis 	q6  	=   7.692305377813692706850171767150701644539e-0002L,
10425c28e83SPiotr Jasiukajtis 	q7  	=  -6.660896644393861499914731734305717901330e-0002L,
10525c28e83SPiotr Jasiukajtis 	pio2hi	=   1.570796326794896619231321691639751398740e+0000L,
10625c28e83SPiotr Jasiukajtis 	pio2lo	=   4.335905065061890512398522013021675984381e-0035L;
10725c28e83SPiotr Jasiukajtis 
10825c28e83SPiotr Jasiukajtis #define	i0	0
10925c28e83SPiotr Jasiukajtis #define	i1	3
11025c28e83SPiotr Jasiukajtis 
11125c28e83SPiotr Jasiukajtis long double
atanl(long double x)11225c28e83SPiotr Jasiukajtis atanl(long double x) {
11325c28e83SPiotr Jasiukajtis 	long double y, z, r, p, s;
11425c28e83SPiotr Jasiukajtis 	int *px = (int *) &x, *py = (int *) &y;
11525c28e83SPiotr Jasiukajtis 	int ix, iy, sign, j;
11625c28e83SPiotr Jasiukajtis 
11725c28e83SPiotr Jasiukajtis 	ix = px[i0];
11825c28e83SPiotr Jasiukajtis 	sign = ix & 0x80000000;
11925c28e83SPiotr Jasiukajtis 	ix ^= sign;
12025c28e83SPiotr Jasiukajtis 
12125c28e83SPiotr Jasiukajtis 	/* for |x| < 1/8 */
12225c28e83SPiotr Jasiukajtis 	if (ix < 0x3ffc0000) {
12325c28e83SPiotr Jasiukajtis 		if (ix < 0x3feb0000) {	/* when |x| < 2**(-prec/6-2) */
12425c28e83SPiotr Jasiukajtis 			if (ix < 0x3fc50000) {	/* if |x| < 2**(-prec/2-2) */
12525c28e83SPiotr Jasiukajtis 				s = one;
12625c28e83SPiotr Jasiukajtis 				*(3 - i0 + (int *) &s) = -1;	/* s = 1-ulp */
12725c28e83SPiotr Jasiukajtis 				*(1 + (int *) &s) = -1;
12825c28e83SPiotr Jasiukajtis 				*(2 + (int *) &s) = -1;
12925c28e83SPiotr Jasiukajtis 				*(i0 + (int *) &s) -= 1;
13025c28e83SPiotr Jasiukajtis 				if ((int) (s * x) < 1)
13125c28e83SPiotr Jasiukajtis 					return (x);	/* raise inexact */
13225c28e83SPiotr Jasiukajtis 			}
13325c28e83SPiotr Jasiukajtis 			z = x * x;
13425c28e83SPiotr Jasiukajtis 			if (ix < 0x3fe20000) {	/* if |x| < 2**(-prec/4-1) */
13525c28e83SPiotr Jasiukajtis 				return (x + (x * z) * p1);
13625c28e83SPiotr Jasiukajtis 			} else {	/* if |x| < 2**(-prec/6-2) */
13725c28e83SPiotr Jasiukajtis 				return (x + (x * z) * (p1 + z * p2));
13825c28e83SPiotr Jasiukajtis 			}
13925c28e83SPiotr Jasiukajtis 		}
14025c28e83SPiotr Jasiukajtis 		z = x * x;
14125c28e83SPiotr Jasiukajtis 		return (x + (x * z) * (p1 + z * (p2 + z * (p3 + z * (p4 +
14225c28e83SPiotr Jasiukajtis 			z * (p5 + z * (p6 + z * (p7 + z * (p8 + z * (p9 +
14325c28e83SPiotr Jasiukajtis 			z * (p10 + z * (p11 + z * (p12 + z * p13)))))))))))));
14425c28e83SPiotr Jasiukajtis 	}
14525c28e83SPiotr Jasiukajtis 
14625c28e83SPiotr Jasiukajtis 	/* for |x| >= 8.0 */
14725c28e83SPiotr Jasiukajtis 	if (ix >= 0x40020000) {
14825c28e83SPiotr Jasiukajtis 		px[i0] = ix;
14925c28e83SPiotr Jasiukajtis 		if (ix < 0x40050400) {	/* x <  65 */
15025c28e83SPiotr Jasiukajtis 			r = one / x;
15125c28e83SPiotr Jasiukajtis 			z = r * r;
15225c28e83SPiotr Jasiukajtis 			/*
15325c28e83SPiotr Jasiukajtis 			 * poly1
15425c28e83SPiotr Jasiukajtis 			 */
15525c28e83SPiotr Jasiukajtis 			y = r * (one + z * (p1 + z * (p2 + z * (p3 +
15625c28e83SPiotr Jasiukajtis 				z * (p4 + z * (p5 + z * (p6 + z * (p7 +
15725c28e83SPiotr Jasiukajtis 				z * (p8 + z * (p9 + z * (p10 + z * (p11 +
15825c28e83SPiotr Jasiukajtis 				z * (p12 + z * p13)))))))))))));
15925c28e83SPiotr Jasiukajtis 			y -= pio2lo;
16025c28e83SPiotr Jasiukajtis 		} else if (ix < 0x40260000) {	/* x <  2**(prec/3+2) */
16125c28e83SPiotr Jasiukajtis 			r = one / x;
16225c28e83SPiotr Jasiukajtis 			z = r * r;
16325c28e83SPiotr Jasiukajtis 			/*
16425c28e83SPiotr Jasiukajtis 			 * poly2
16525c28e83SPiotr Jasiukajtis 			 */
16625c28e83SPiotr Jasiukajtis 			y = r * (one + z * (q1 + z * (q2 + z * (q3 + z * (q4 +
16725c28e83SPiotr Jasiukajtis 				z * (q5 + z * (q6 + z * q7)))))));
16825c28e83SPiotr Jasiukajtis 			y -= pio2lo;
16925c28e83SPiotr Jasiukajtis 		} else if (ix < 0x40720000) {	/* x <  2**(prec+2) */
17025c28e83SPiotr Jasiukajtis 			y = one / x - pio2lo;
17125c28e83SPiotr Jasiukajtis 		} else if (ix < 0x7fff0000) {	/* x <  inf */
17225c28e83SPiotr Jasiukajtis 			y = -pio2lo;
17325c28e83SPiotr Jasiukajtis 		} else {		/* x is inf or NaN */
17425c28e83SPiotr Jasiukajtis 			if (((ix - 0x7fff0000) | px[1] | px[2] | px[i1]) != 0)
17525c28e83SPiotr Jasiukajtis 				return (x - x);
17625c28e83SPiotr Jasiukajtis 			y = -pio2lo;
17725c28e83SPiotr Jasiukajtis 		}
17825c28e83SPiotr Jasiukajtis 
17925c28e83SPiotr Jasiukajtis 		if (sign == 0)
18025c28e83SPiotr Jasiukajtis 			return (pio2hi - y);
18125c28e83SPiotr Jasiukajtis 		else
18225c28e83SPiotr Jasiukajtis 			return (y - pio2hi);
18325c28e83SPiotr Jasiukajtis 	}
18425c28e83SPiotr Jasiukajtis 
18525c28e83SPiotr Jasiukajtis 	/* now x is between 1/8 and 8 */
18625c28e83SPiotr Jasiukajtis 	px[i0] = ix;
18725c28e83SPiotr Jasiukajtis 	iy = (ix + 0x00000800) & 0x7ffff000;
18825c28e83SPiotr Jasiukajtis 	py[i0] = iy;
18925c28e83SPiotr Jasiukajtis 	py[1] = py[2] = py[i1] = 0;
19025c28e83SPiotr Jasiukajtis 	j = (iy - 0x3ffc0000) >> 12;
19125c28e83SPiotr Jasiukajtis 
19225c28e83SPiotr Jasiukajtis 	if (sign == 0)
19325c28e83SPiotr Jasiukajtis 		s = (x - y) / (one + x * y);
19425c28e83SPiotr Jasiukajtis 	else
19525c28e83SPiotr Jasiukajtis 		s = (y - x) / (one + x * y);
19625c28e83SPiotr Jasiukajtis 	z = s * s;
19725c28e83SPiotr Jasiukajtis 	if (ix == iy)
19825c28e83SPiotr Jasiukajtis 		p = s * (one + z * (q1 + z * (q2 + z * (q3 + z * q4))));
19925c28e83SPiotr Jasiukajtis 	else
20025c28e83SPiotr Jasiukajtis 		p = s * (one + z * (q1 + z * (q2 + z * (q3 + z * (q4 +
20125c28e83SPiotr Jasiukajtis 			z * (q5 + z * (q6 + z * q7)))))));
20225c28e83SPiotr Jasiukajtis 	if (sign == 0) {
20325c28e83SPiotr Jasiukajtis 		r = p + _TBL_atanl_lo[j];
20425c28e83SPiotr Jasiukajtis 		return (r + _TBL_atanl_hi[j]);
20525c28e83SPiotr Jasiukajtis 	} else {
20625c28e83SPiotr Jasiukajtis 		r = p - _TBL_atanl_lo[j];
20725c28e83SPiotr Jasiukajtis 		return (r - _TBL_atanl_hi[j]);
20825c28e83SPiotr Jasiukajtis 	}
20925c28e83SPiotr Jasiukajtis }
210