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_pio2f.c -- float version of e_rem_pio2.c 00018 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. 00019 */ 00020 00021 /* 00022 * ==================================================== 00023 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 00024 * 00025 * Developed at SunPro, a Sun Microsystems, Inc. business. 00026 * Permission to use, copy, modify, and distribute this 00027 * software is freely granted, provided that this notice 00028 * is preserved. 00029 * ==================================================== 00030 */ 00031 00032 /* __ieee754_rem_pio2f(x,y) 00033 * 00034 * return the remainder of x rem pi/2 in y[0]+y[1] 00035 * use __kernel_rem_pio2f() 00036 */ 00037 00038 #ifdef POK_NEEDS_LIBMATH 00039 #include <libm.h> 00040 #include "math_private.h" 00041 00042 /* 00043 * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi 00044 */ 00045 static const int32_t two_over_pi[] = { 00046 0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC, 00047 0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62, 00048 0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63, 00049 0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A, 00050 0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09, 00051 0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29, 00052 0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44, 00053 0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41, 00054 0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C, 00055 0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8, 00056 0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11, 00057 0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF, 00058 0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E, 00059 0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5, 00060 0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92, 00061 0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08, 00062 0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0, 00063 0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3, 00064 0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85, 00065 0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80, 00066 0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA, 00067 0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B, 00068 }; 00069 00070 /* This array is like the one in e_rem_pio2.c, but the numbers are 00071 single precision and the last 8 bits are forced to 0. */ 00072 static const int32_t npio2_hw[] = { 00073 0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00, 00074 0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00, 00075 0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100, 00076 0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00, 00077 0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00, 00078 0x4242c700, 0x42490f00 00079 }; 00080 00081 /* 00082 * invpio2: 24 bits of 2/pi 00083 * pio2_1: first 17 bit of pi/2 00084 * pio2_1t: pi/2 - pio2_1 00085 * pio2_2: second 17 bit of pi/2 00086 * pio2_2t: pi/2 - (pio2_1+pio2_2) 00087 * pio2_3: third 17 bit of pi/2 00088 * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) 00089 */ 00090 00091 static const float 00092 zero = 0.0000000000e+00, /* 0x00000000 */ 00093 half = 5.0000000000e-01, /* 0x3f000000 */ 00094 two8 = 2.5600000000e+02, /* 0x43800000 */ 00095 invpio2 = 6.3661980629e-01, /* 0x3f22f984 */ 00096 pio2_1 = 1.5707855225e+00, /* 0x3fc90f80 */ 00097 pio2_1t = 1.0804334124e-05, /* 0x37354443 */ 00098 pio2_2 = 1.0804273188e-05, /* 0x37354400 */ 00099 pio2_2t = 6.0770999344e-11, /* 0x2e85a308 */ 00100 pio2_3 = 6.0770943833e-11, /* 0x2e85a300 */ 00101 pio2_3t = 6.1232342629e-17; /* 0x248d3132 */ 00102 00103 int32_t 00104 __ieee754_rem_pio2f(float x, float *y) 00105 { 00106 float z,w,t,r,fn; 00107 float tx[3]; 00108 int32_t e0,i,j,nx,n,ix,hx; 00109 00110 GET_FLOAT_WORD(hx,x); 00111 ix = hx&0x7fffffff; 00112 if(ix<=0x3f490fd8) /* |x| ~<= pi/4 , no need for reduction */ 00113 {y[0] = x; y[1] = 0; return 0;} 00114 if(ix<0x4016cbe4) { /* |x| < 3pi/4, special case with n=+-1 */ 00115 if(hx>0) { 00116 z = x - pio2_1; 00117 if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */ 00118 y[0] = z - pio2_1t; 00119 y[1] = (z-y[0])-pio2_1t; 00120 } else { /* near pi/2, use 24+24+24 bit pi */ 00121 z -= pio2_2; 00122 y[0] = z - pio2_2t; 00123 y[1] = (z-y[0])-pio2_2t; 00124 } 00125 return 1; 00126 } else { /* negative x */ 00127 z = x + pio2_1; 00128 if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */ 00129 y[0] = z + pio2_1t; 00130 y[1] = (z-y[0])+pio2_1t; 00131 } else { /* near pi/2, use 24+24+24 bit pi */ 00132 z += pio2_2; 00133 y[0] = z + pio2_2t; 00134 y[1] = (z-y[0])+pio2_2t; 00135 } 00136 return -1; 00137 } 00138 } 00139 if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */ 00140 t = fabsf(x); 00141 n = (int32_t) (t*invpio2+half); 00142 fn = (float)n; 00143 r = t-fn*pio2_1; 00144 w = fn*pio2_1t; /* 1st round good to 40 bit */ 00145 if(n<32&&(int32_t)(ix&0xffffff00)!=npio2_hw[n-1]) { 00146 y[0] = r-w; /* quick check no cancellation */ 00147 } else { 00148 uint32_t high; 00149 j = ix>>23; 00150 y[0] = r-w; 00151 GET_FLOAT_WORD(high,y[0]); 00152 i = j-((high>>23)&0xff); 00153 if(i>8) { /* 2nd iteration needed, good to 57 */ 00154 t = r; 00155 w = fn*pio2_2; 00156 r = t-w; 00157 w = fn*pio2_2t-((t-r)-w); 00158 y[0] = r-w; 00159 GET_FLOAT_WORD(high,y[0]); 00160 i = j-((high>>23)&0xff); 00161 if(i>25) { /* 3rd iteration need, 74 bits acc */ 00162 t = r; /* will cover all possible cases */ 00163 w = fn*pio2_3; 00164 r = t-w; 00165 w = fn*pio2_3t-((t-r)-w); 00166 y[0] = r-w; 00167 } 00168 } 00169 } 00170 y[1] = (r-y[0])-w; 00171 if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} 00172 else return n; 00173 } 00174 /* 00175 * all other (large) arguments 00176 */ 00177 if(ix>=0x7f800000) { /* x is inf or NaN */ 00178 y[0]=y[1]=x-x; return 0; 00179 } 00180 /* set z = scalbn(|x|,ilogb(x)-7) */ 00181 e0 = (ix>>23)-134; /* e0 = ilogb(z)-7; */ 00182 SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23))); 00183 for(i=0;i<2;i++) { 00184 tx[i] = (float)((int32_t)(z)); 00185 z = (z-tx[i])*two8; 00186 } 00187 tx[2] = z; 00188 nx = 3; 00189 while(tx[nx-1]==zero) nx--; /* skip zero term */ 00190 n = __kernel_rem_pio2f(tx,y,e0,nx,2,(int*)two_over_pi); 00191 if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} 00192 return n; 00193 } 00194 #endif