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 __atanf = atanf 3125c28e83SPiotr Jasiukajtis 3225c28e83SPiotr Jasiukajtis /* INDENT OFF */ 3325c28e83SPiotr Jasiukajtis /* 3425c28e83SPiotr Jasiukajtis * float atanf(float x); 3525c28e83SPiotr Jasiukajtis * Table look-up algorithm 3625c28e83SPiotr Jasiukajtis * By K.C. Ng, March 9, 1989 3725c28e83SPiotr Jasiukajtis * 3825c28e83SPiotr Jasiukajtis * Algorithm. 3925c28e83SPiotr Jasiukajtis * 4025c28e83SPiotr Jasiukajtis * The algorithm is based on atan(x)=atan(y)+atan((x-y)/(1+x*y)). 4125c28e83SPiotr Jasiukajtis * We use poly1(x) to approximate atan(x) for x in [0,1/8] with 4225c28e83SPiotr Jasiukajtis * error (relative) 4325c28e83SPiotr Jasiukajtis * |(atan(x)-poly1(x))/x|<= 2^-115.94 long double 4425c28e83SPiotr Jasiukajtis * |(atan(x)-poly1(x))/x|<= 2^-58.85 double 4525c28e83SPiotr Jasiukajtis * |(atan(x)-poly1(x))/x|<= 2^-25.53 float 4625c28e83SPiotr Jasiukajtis * and use poly2(x) to approximate atan(x) for x in [0,1/65] with 4725c28e83SPiotr Jasiukajtis * error (absolute) 4825c28e83SPiotr Jasiukajtis * |atan(x)-poly2(x)|<= 2^-122.15 long double 4925c28e83SPiotr Jasiukajtis * |atan(x)-poly2(x)|<= 2^-64.79 double 5025c28e83SPiotr Jasiukajtis * |atan(x)-poly2(x)|<= 2^-35.36 float 5125c28e83SPiotr Jasiukajtis * and use poly3(x) to approximate atan(x) for x in [1/8,7/16] with 5225c28e83SPiotr Jasiukajtis * error (relative, on for single precision) 5325c28e83SPiotr Jasiukajtis * |(atan(x)-poly1(x))/x|<= 2^-25.53 float 5425c28e83SPiotr Jasiukajtis * 5525c28e83SPiotr Jasiukajtis * Here poly1-3 are odd polynomial with the following form: 5625c28e83SPiotr Jasiukajtis * x + x^3*(a1+x^2*(a2+...)) 5725c28e83SPiotr Jasiukajtis * 5825c28e83SPiotr Jasiukajtis * (0). Purge off Inf and NaN and 0 5925c28e83SPiotr Jasiukajtis * (1). Reduce x to positive by atan(x) = -atan(-x). 6025c28e83SPiotr Jasiukajtis * (2). For x <= 1/8, use 6125c28e83SPiotr Jasiukajtis * (2.1) if x < 2^(-prec/2-2), atan(x) = x with inexact 6225c28e83SPiotr Jasiukajtis * (2.2) Otherwise 6325c28e83SPiotr Jasiukajtis * atan(x) = poly1(x) 6425c28e83SPiotr Jasiukajtis * (3). For x >= 8 then 6525c28e83SPiotr Jasiukajtis * (3.1) if x >= 2^(prec+2), atan(x) = atan(inf) - pio2lo 6625c28e83SPiotr Jasiukajtis * (3.2) if x >= 2^(prec/3+2), atan(x) = atan(inf) - 1/x 6725c28e83SPiotr Jasiukajtis * (3.3) if x > 65, atan(x) = atan(inf) - poly2(1/x) 6825c28e83SPiotr Jasiukajtis * (3.4) Otherwise, atan(x) = atan(inf) - poly1(1/x) 6925c28e83SPiotr Jasiukajtis * 7025c28e83SPiotr Jasiukajtis * (4). Now x is in (0.125, 8) 7125c28e83SPiotr Jasiukajtis * Find y that match x to 4.5 bit after binary (easy). 7225c28e83SPiotr Jasiukajtis * If iy is the high word of y, then 7325c28e83SPiotr Jasiukajtis * single : j = (iy - 0x3e000000) >> 19 7425c28e83SPiotr Jasiukajtis * (single is modified to (iy-0x3f000000)>>19) 7525c28e83SPiotr Jasiukajtis * double : j = (iy - 0x3fc00000) >> 16 7625c28e83SPiotr Jasiukajtis * quad : j = (iy - 0x3ffc0000) >> 12 7725c28e83SPiotr Jasiukajtis * 7825c28e83SPiotr Jasiukajtis * Let s = (x-y)/(1+x*y). Then 7925c28e83SPiotr Jasiukajtis * atan(x) = atan(y) + poly1(s) 8025c28e83SPiotr Jasiukajtis * = _TBL_r_atan_hi[j] + (_TBL_r_atan_lo[j] + poly2(s) ) 8125c28e83SPiotr Jasiukajtis * 8225c28e83SPiotr Jasiukajtis * Note. |s| <= 1.5384615385e-02 = 1/65. Maxium occurs at x = 1.03125 8325c28e83SPiotr Jasiukajtis * 8425c28e83SPiotr Jasiukajtis */ 8525c28e83SPiotr Jasiukajtis 8625c28e83SPiotr Jasiukajtis #include "libm.h" 8725c28e83SPiotr Jasiukajtis 8825c28e83SPiotr Jasiukajtis extern const float _TBL_r_atan_hi[], _TBL_r_atan_lo[]; 8925c28e83SPiotr Jasiukajtis static const float 9025c28e83SPiotr Jasiukajtis big = 1.0e37F, 9125c28e83SPiotr Jasiukajtis one = 1.0F, 9225c28e83SPiotr Jasiukajtis p1 = -3.333185951111688247225368498733544672172e-0001F, 9325c28e83SPiotr Jasiukajtis p2 = 1.969352894213455405211341983203180636021e-0001F, 9425c28e83SPiotr Jasiukajtis q1 = -3.332921964095646819563419704110132937456e-0001F, 9525c28e83SPiotr Jasiukajtis a1 = -3.333323465223893614063523351509338934592e-0001F, 9625c28e83SPiotr Jasiukajtis a2 = 1.999425625935277805494082274808174062403e-0001F, 9725c28e83SPiotr Jasiukajtis a3 = -1.417547090509737780085769846290301788559e-0001F, 9825c28e83SPiotr Jasiukajtis a4 = 1.016250813871991983097273733227432685084e-0001F, 9925c28e83SPiotr Jasiukajtis a5 = -5.137023693688358515753093811791755221805e-0002F, 10025c28e83SPiotr Jasiukajtis pio2hi = 1.570796371e+0000F, 10125c28e83SPiotr Jasiukajtis pio2lo = -4.371139000e-0008F; 10225c28e83SPiotr Jasiukajtis /* INDENT ON */ 10325c28e83SPiotr Jasiukajtis 10425c28e83SPiotr Jasiukajtis float 10525c28e83SPiotr Jasiukajtis atanf(float xx) { 10625c28e83SPiotr Jasiukajtis float x, y, z, r, p, s; 10725c28e83SPiotr Jasiukajtis volatile double dummy; 10825c28e83SPiotr Jasiukajtis int ix, iy, sign, j; 10925c28e83SPiotr Jasiukajtis 11025c28e83SPiotr Jasiukajtis x = xx; 11125c28e83SPiotr Jasiukajtis ix = *(int *) &x; 11225c28e83SPiotr Jasiukajtis sign = ix & 0x80000000; 11325c28e83SPiotr Jasiukajtis ix ^= sign; 11425c28e83SPiotr Jasiukajtis 11525c28e83SPiotr Jasiukajtis /* for |x| < 1/8 */ 11625c28e83SPiotr Jasiukajtis if (ix < 0x3e000000) { 11725c28e83SPiotr Jasiukajtis if (ix < 0x38800000) { /* if |x| < 2**(-prec/2-2) */ 11825c28e83SPiotr Jasiukajtis dummy = big + x; /* get inexact flag if x != 0 */ 11925c28e83SPiotr Jasiukajtis #ifdef lint 12025c28e83SPiotr Jasiukajtis dummy = dummy; 12125c28e83SPiotr Jasiukajtis #endif 12225c28e83SPiotr Jasiukajtis return (x); 12325c28e83SPiotr Jasiukajtis } 12425c28e83SPiotr Jasiukajtis z = x * x; 12525c28e83SPiotr Jasiukajtis if (ix < 0x3c000000) { /* if |x| < 2**(-prec/4-1) */ 12625c28e83SPiotr Jasiukajtis x = x + (x * z) * p1; 12725c28e83SPiotr Jasiukajtis return (x); 12825c28e83SPiotr Jasiukajtis } else { 12925c28e83SPiotr Jasiukajtis x = x + (x * z) * (p1 + z * p2); 13025c28e83SPiotr Jasiukajtis return (x); 13125c28e83SPiotr Jasiukajtis } 13225c28e83SPiotr Jasiukajtis } 13325c28e83SPiotr Jasiukajtis 13425c28e83SPiotr Jasiukajtis /* for |x| >= 8.0 */ 13525c28e83SPiotr Jasiukajtis if (ix >= 0x41000000) { 13625c28e83SPiotr Jasiukajtis *(int *) &x = ix; 13725c28e83SPiotr Jasiukajtis if (ix < 0x42820000) { /* x < 65 */ 13825c28e83SPiotr Jasiukajtis r = one / x; 13925c28e83SPiotr Jasiukajtis z = r * r; 14025c28e83SPiotr Jasiukajtis y = r * (one + z * (p1 + z * p2)); /* poly1 */ 14125c28e83SPiotr Jasiukajtis y -= pio2lo; 14225c28e83SPiotr Jasiukajtis } else if (ix < 0x44800000) { /* x < 2**(prec/3+2) */ 14325c28e83SPiotr Jasiukajtis r = one / x; 14425c28e83SPiotr Jasiukajtis z = r * r; 14525c28e83SPiotr Jasiukajtis y = r * (one + z * q1); /* poly2 */ 14625c28e83SPiotr Jasiukajtis y -= pio2lo; 14725c28e83SPiotr Jasiukajtis } else if (ix < 0x4c800000) { /* x < 2**(prec+2) */ 14825c28e83SPiotr Jasiukajtis y = one / x - pio2lo; 14925c28e83SPiotr Jasiukajtis } else if (ix < 0x7f800000) { /* x < inf */ 15025c28e83SPiotr Jasiukajtis y = -pio2lo; 15125c28e83SPiotr Jasiukajtis } else { /* x is inf or NaN */ 15225c28e83SPiotr Jasiukajtis if (ix > 0x7f800000) { 15325c28e83SPiotr Jasiukajtis return (x * x); /* - -> * for Cheetah */ 15425c28e83SPiotr Jasiukajtis } 15525c28e83SPiotr Jasiukajtis y = -pio2lo; 15625c28e83SPiotr Jasiukajtis } 15725c28e83SPiotr Jasiukajtis 15825c28e83SPiotr Jasiukajtis if (sign == 0) 15925c28e83SPiotr Jasiukajtis x = pio2hi - y; 16025c28e83SPiotr Jasiukajtis else 16125c28e83SPiotr Jasiukajtis x = y - pio2hi; 16225c28e83SPiotr Jasiukajtis return (x); 16325c28e83SPiotr Jasiukajtis } 16425c28e83SPiotr Jasiukajtis 16525c28e83SPiotr Jasiukajtis 16625c28e83SPiotr Jasiukajtis /* now x is between 1/8 and 8 */ 16725c28e83SPiotr Jasiukajtis if (ix < 0x3f000000) { /* between 1/8 and 1/2 */ 16825c28e83SPiotr Jasiukajtis z = x * x; 16925c28e83SPiotr Jasiukajtis x = x + (x * z) * (a1 + z * (a2 + z * (a3 + z * (a4 + 17025c28e83SPiotr Jasiukajtis z * a5)))); 17125c28e83SPiotr Jasiukajtis return (x); 17225c28e83SPiotr Jasiukajtis } 17325c28e83SPiotr Jasiukajtis *(int *) &x = ix; 17425c28e83SPiotr Jasiukajtis iy = (ix + 0x00040000) & 0x7ff80000; 17525c28e83SPiotr Jasiukajtis *(int *) &y = iy; 17625c28e83SPiotr Jasiukajtis j = (iy - 0x3f000000) >> 19; 17725c28e83SPiotr Jasiukajtis 17825c28e83SPiotr Jasiukajtis if (ix == iy) 17925c28e83SPiotr Jasiukajtis p = x - y; /* p=0.0 */ 18025c28e83SPiotr Jasiukajtis else { 18125c28e83SPiotr Jasiukajtis if (sign == 0) 18225c28e83SPiotr Jasiukajtis s = (x - y) / (one + x * y); 18325c28e83SPiotr Jasiukajtis else 18425c28e83SPiotr Jasiukajtis s = (y - x) / (one + x * y); 18525c28e83SPiotr Jasiukajtis z = s * s; 18625c28e83SPiotr Jasiukajtis p = s * (one + z * q1); 18725c28e83SPiotr Jasiukajtis } 18825c28e83SPiotr Jasiukajtis if (sign == 0) { 18925c28e83SPiotr Jasiukajtis r = p + _TBL_r_atan_lo[j]; 19025c28e83SPiotr Jasiukajtis x = r + _TBL_r_atan_hi[j]; 19125c28e83SPiotr Jasiukajtis } else { 19225c28e83SPiotr Jasiukajtis r = p - _TBL_r_atan_lo[j]; 19325c28e83SPiotr Jasiukajtis x = r - _TBL_r_atan_hi[j]; 19425c28e83SPiotr Jasiukajtis } 19525c28e83SPiotr Jasiukajtis return (x); 19625c28e83SPiotr Jasiukajtis } 197