POK
|
00001 /* 00002 * POK header 00003 * 00004 * The following file is a part of the POK project. Any modification should 00005 * made according to the POK licence. You CANNOT use this file or a part of 00006 * this file is this part of a file for your own project 00007 * 00008 * For more information on the POK licence, please see our LICENCE FILE 00009 * 00010 * Please follow the coding guidelines described in doc/CODING_GUIDELINES 00011 * 00012 * Copyright (c) 2007-2009 POK team 00013 * 00014 * Created by julien on Fri Jan 30 14:41:34 2009 00015 */ 00016 00017 /* @(#)e_rem_pio2.c 5.1 93/09/24 */ 00018 /* 00019 * ==================================================== 00020 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 00021 * 00022 * Developed at SunPro, a Sun Microsystems, Inc. business. 00023 * Permission to use, copy, modify, and distribute this 00024 * software is freely granted, provided that this notice 00025 * is preserved. 00026 * ==================================================== 00027 */ 00028 00029 /* __ieee754_rem_pio2(x,y) 00030 * 00031 * return the remainder of x rem pi/2 in y[0]+y[1] 00032 * use __kernel_rem_pio2() 00033 */ 00034 00035 #ifdef POK_NEEDS_LIBMATH 00036 00037 #include <libm.h> 00038 #include "math_private.h" 00039 00040 /* 00041 * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi 00042 */ 00043 static const int32_t two_over_pi[] = { 00044 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 00045 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 00046 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 00047 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 00048 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, 00049 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, 00050 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 00051 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 00052 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 00053 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 00054 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, 00055 }; 00056 00057 static const int32_t npio2_hw[] = { 00058 0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, 00059 0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C, 00060 0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, 00061 0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C, 00062 0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB, 00063 0x404858EB, 0x404921FB, 00064 }; 00065 00066 /* 00067 * invpio2: 53 bits of 2/pi 00068 * pio2_1: first 33 bit of pi/2 00069 * pio2_1t: pi/2 - pio2_1 00070 * pio2_2: second 33 bit of pi/2 00071 * pio2_2t: pi/2 - (pio2_1+pio2_2) 00072 * pio2_3: third 33 bit of pi/2 00073 * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) 00074 */ 00075 00076 static const double 00077 zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ 00078 half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ 00079 two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ 00080 invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ 00081 pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ 00082 pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ 00083 pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ 00084 pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ 00085 pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ 00086 pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ 00087 00088 int32_t 00089 __ieee754_rem_pio2(double x, double *y) 00090 { 00091 double z,w,t,r,fn; 00092 double tx[3]; 00093 int32_t e0,i,j,nx,n,ix,hx; 00094 uint32_t low; 00095 00096 z = 0; 00097 GET_HIGH_WORD(hx,x); /* high word of x */ 00098 ix = hx&0x7fffffff; 00099 if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */ 00100 {y[0] = x; y[1] = 0; return 0;} 00101 if(ix<0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */ 00102 if(hx>0) { 00103 z = x - pio2_1; 00104 if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ 00105 y[0] = z - pio2_1t; 00106 y[1] = (z-y[0])-pio2_1t; 00107 } else { /* near pi/2, use 33+33+53 bit pi */ 00108 z -= pio2_2; 00109 y[0] = z - pio2_2t; 00110 y[1] = (z-y[0])-pio2_2t; 00111 } 00112 return 1; 00113 } else { /* negative x */ 00114 z = x + pio2_1; 00115 if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ 00116 y[0] = z + pio2_1t; 00117 y[1] = (z-y[0])+pio2_1t; 00118 } else { /* near pi/2, use 33+33+53 bit pi */ 00119 z += pio2_2; 00120 y[0] = z + pio2_2t; 00121 y[1] = (z-y[0])+pio2_2t; 00122 } 00123 return -1; 00124 } 00125 } 00126 if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */ 00127 t = fabs(x); 00128 n = (int32_t) (t*invpio2+half); 00129 fn = (double)n; 00130 r = t-fn*pio2_1; 00131 w = fn*pio2_1t; /* 1st round good to 85 bit */ 00132 if(n<32&&ix!=npio2_hw[n-1]) { 00133 y[0] = r-w; /* quick check no cancellation */ 00134 } else { 00135 uint32_t high; 00136 j = ix>>20; 00137 y[0] = r-w; 00138 GET_HIGH_WORD(high,y[0]); 00139 i = j-((high>>20)&0x7ff); 00140 if(i>16) { /* 2nd iteration needed, good to 118 */ 00141 t = r; 00142 w = fn*pio2_2; 00143 r = t-w; 00144 w = fn*pio2_2t-((t-r)-w); 00145 y[0] = r-w; 00146 GET_HIGH_WORD(high,y[0]); 00147 i = j-((high>>20)&0x7ff); 00148 if(i>49) { /* 3rd iteration need, 151 bits acc */ 00149 t = r; /* will cover all possible cases */ 00150 w = fn*pio2_3; 00151 r = t-w; 00152 w = fn*pio2_3t-((t-r)-w); 00153 y[0] = r-w; 00154 } 00155 } 00156 } 00157 y[1] = (r-y[0])-w; 00158 if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} 00159 else return n; 00160 } 00161 /* 00162 * all other (large) arguments 00163 */ 00164 if(ix>=0x7ff00000) { /* x is inf or NaN */ 00165 y[0]=y[1]=x-x; return 0; 00166 } 00167 /* set z = scalbn(|x|,ilogb(x)-23) */ 00168 GET_LOW_WORD(low,x); 00169 SET_LOW_WORD(z,low); 00170 e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */ 00171 SET_HIGH_WORD(z, ix - ((int32_t)(e0<<20))); 00172 for(i=0;i<2;i++) { 00173 tx[i] = (double)((int32_t)(z)); 00174 z = (z-tx[i])*two24; 00175 } 00176 tx[2] = z; 00177 nx = 3; 00178 while(tx[nx-1]==zero) nx--; /* skip zero term */ 00179 n = __kernel_rem_pio2(tx,y,e0,nx,2,(int*)two_over_pi); 00180 if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} 00181 return n; 00182 } 00183 #endif