11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* @(#)s_atan.c 5.1 93/09/24 */ 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ==================================================== 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Developed at SunPro, a Sun Microsystems, Inc. business. 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * software is freely granted, provided that this notice 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is preserved. 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ==================================================== 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 13a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <sys/cdefs.h> 14a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes__FBSDID("$FreeBSD$"); 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* atan(x) 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Method 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Reduce x to positive by atan(x) = -atan(-x). 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. According to the integer k=4t+0.25 chopped, t=x, the argument 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is further reduced to one of the following intervals and the 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * arctangent of t is evaluated by the corresponding formula: 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Constants: 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The hexadecimal values are the intended ones for the following 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * constants. The decimal values may be used, provided that the 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * compiler will convert from decimal to binary accurately enough 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * to produce the hexadecimal values shown. 341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 36a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <float.h> 37a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math.h" 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math_private.h" 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const double atanhi[] = { 421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const double atanlo[] = { 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const double aT[] = { 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project static const double 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectone = 1.0, 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecthuge = 1.0e300; 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdouble 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectatan(double x) 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project double w,s1,s2,z; 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int32_t ix,hx,id; 781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_HIGH_WORD(hx,x); 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ix = hx&0x7fffffff; 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(ix>=0x44100000) { /* if |x| >= 2^66 */ 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int32_t low; 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_LOW_WORD(low,x); 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(ix>0x7ff00000|| 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (ix==0x7ff00000&&(low!=0))) 861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return x+x; /* NaN */ 87a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes if(hx>0) return atanhi[3]+*(volatile double *)&atanlo[3]; 88a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes else return -atanhi[3]-*(volatile double *)&atanlo[3]; 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ 90a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes if (ix < 0x3e400000) { /* |x| < 2^-27 */ 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if(huge+x>one) return x; /* raise inexact */ 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project id = -1; 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project x = fabs(x); 961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ix < 0x3ff30000) { /* |x| < 1.1875 */ 971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */ 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project id = 0; x = (2.0*x-one)/(2.0+x); 991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { /* 11/16<=|x|< 19/16 */ 1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project id = 1; x = (x-one)/(x+one); 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ix < 0x40038000) { /* |x| < 2.4375 */ 1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project id = 2; x = (x-1.5)/(one+1.5*x); 1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { /* 2.4375 <= |x| < 2^66 */ 1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project id = 3; x = -1.0/x; 1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project }} 1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* end of argument reduction */ 1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project z = x*x; 1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project w = z*z; 1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ 1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10]))))); 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9])))); 1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (id<0) return x - x*(s1+s2); 1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else { 1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); 1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (hx<0)? -z:z; 1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 121a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes 122a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#if LDBL_MANT_DIG == 53 123a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes__weak_reference(atan, atanl); 124a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#endif 125