/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* atanl(x)
* Table look-up algorithm
* By K.C. Ng, March 9, 1989
*
* Algorithm.
*
* The algorithm is based on atan(x)=atan(y)+atan((x-y)/(1+x*y)).
* We use poly1(x) to approximate atan(x) for x in [0,1/8] with
* error (relative)
* |(atan(x)-poly1(x))/x|<= 2^-115.94 long double
* |(atan(x)-poly1(x))/x|<= 2^-58.85 double
* |(atan(x)-poly1(x))/x|<= 2^-25.53 float
* and use poly2(x) to approximate atan(x) for x in [0,1/65] with
* error (absolute)
* |atan(x)-poly2(x)|<= 2^-122.15 long double
* |atan(x)-poly2(x)|<= 2^-64.79 double
* |atan(x)-poly2(x)|<= 2^-35.36 float
* Here poly1 and poly2 are odd polynomial with the following form:
* x + x^3*(a1+x^2*(a2+...))
*
* (0). Purge off Inf and NaN and 0
* (1). Reduce x to positive by atan(x) = -atan(-x).
* (2). For x <= 1/8, use
* (2.1) if x < 2^(-prec/2-2), atan(x) = x with inexact
* (2.2) Otherwise
* atan(x) = poly1(x)
* (3). For x >= 8 then
* (3.1) if x >= 2^(prec+2), atan(x) = atan(inf) - pio2lo
* (3.2) if x >= 2^(prec/3+2), atan(x) = atan(inf) - 1/x
* (3.3) if x > 65, atan(x) = atan(inf) - poly2(1/x)
* (3.4) Otherwise, atan(x) = atan(inf) - poly1(1/x)
*
* (4). Now x is in (0.125, 8)
* Find y that match x to 4.5 bit after binary (easy).
* If iy is the high word of y, then
* single : j = (iy - 0x3e000000) >> 19
* double : j = (iy - 0x3fc00000) >> 16
* quad : j = (iy - 0x3ffc0000) >> 12
*
* Let s = (x-y)/(1+x*y). Then
* atan(x) = atan(y) + poly1(s)
* = _TBL_atanl_hi[j] + (_TBL_atanl_lo[j] + poly2(s) )
*
* Note. |s| <= 1.5384615385e-02 = 1/65. Maxium occurs at x = 1.03125
*
*/
#include "libm.h"
extern const long double _TBL_atanl_hi[], _TBL_atanl_lo[];
static const long double
#define i0 0
long double
atanl(long double x) {
long double y, z, r, p, s;
/* for |x| < 1/8 */
if (ix < 0x3ffc0000) {
s = one;
*(1 + (int *) &s) = -1;
*(2 + (int *) &s) = -1;
*(i0 + (int *) &s) -= 1;
if ((int) (s * x) < 1)
return (x); /* raise inexact */
}
z = x * x;
return (x + (x * z) * p1);
} else { /* if |x| < 2**(-prec/6-2) */
}
}
z = x * x;
}
/* for |x| >= 8.0 */
if (ix >= 0x40020000) {
r = one / x;
z = r * r;
/*
* poly1
*/
y -= pio2lo;
r = one / x;
z = r * r;
/*
* poly2
*/
y -= pio2lo;
y = -pio2lo;
} else { /* x is inf or NaN */
return (x - x);
y = -pio2lo;
}
if (sign == 0)
return (pio2hi - y);
else
return (y - pio2hi);
}
/* now x is between 1/8 and 8 */
if (sign == 0)
s = (x - y) / (one + x * y);
else
s = (y - x) / (one + x * y);
z = s * s;
else
if (sign == 0) {
r = p + _TBL_atanl_lo[j];
return (r + _TBL_atanl_hi[j]);
} else {
r = p - _TBL_atanl_lo[j];
return (r - _TBL_atanl_hi[j]);
}
}