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 Sat Jan 31 20:12:07 2009 00015 */ 00016 00017 /* k_rem_pio2f.c -- float version of k_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 #ifdef POK_NEEDS_LIBMATH 00033 00034 #include <libm.h> 00035 #include "math_private.h" 00036 00037 /* In the float version, the input parameter x contains 8 bit 00038 integers, not 24 bit integers. 113 bit precision is not supported. */ 00039 00040 static const int init_jk[] = {4,7,9}; /* initial value for jk */ 00041 00042 static const float PIo2[] = { 00043 1.5703125000e+00, /* 0x3fc90000 */ 00044 4.5776367188e-04, /* 0x39f00000 */ 00045 2.5987625122e-05, /* 0x37da0000 */ 00046 7.5437128544e-08, /* 0x33a20000 */ 00047 6.0026650317e-11, /* 0x2e840000 */ 00048 7.3896444519e-13, /* 0x2b500000 */ 00049 5.3845816694e-15, /* 0x27c20000 */ 00050 5.6378512969e-18, /* 0x22d00000 */ 00051 8.3009228831e-20, /* 0x1fc40000 */ 00052 3.2756352257e-22, /* 0x1bc60000 */ 00053 6.3331015649e-25, /* 0x17440000 */ 00054 }; 00055 00056 static const float 00057 zero = 0.0, 00058 one = 1.0, 00059 two8 = 2.5600000000e+02, /* 0x43800000 */ 00060 twon8 = 3.9062500000e-03; /* 0x3b800000 */ 00061 00062 int 00063 __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const int *ipio2) 00064 { 00065 int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; 00066 float z,fw,f[20],fq[20],q[20]; 00067 00068 /* initialize jk*/ 00069 jk = init_jk[prec]; 00070 jp = jk; 00071 00072 /* determine jx,jv,q0, note that 3>q0 */ 00073 jx = nx-1; 00074 jv = (e0-3)/8; if(jv<0) jv=0; 00075 q0 = e0-8*(jv+1); 00076 00077 /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ 00078 j = jv-jx; m = jx+jk; 00079 for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j]; 00080 00081 /* compute q[0],q[1],...q[jk] */ 00082 for (i=0;i<=jk;i++) { 00083 for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; 00084 } 00085 00086 jz = jk; 00087 recompute: 00088 /* distill q[] into iq[] reversingly */ 00089 for(i=0,j=jz,z=q[jz];j>0;i++,j--) { 00090 fw = (float)((int32_t)(twon8* z)); 00091 iq[i] = (int32_t)(z-two8*fw); 00092 z = q[j-1]+fw; 00093 } 00094 00095 /* compute n */ 00096 z = scalbnf(z,q0); /* actual value of z */ 00097 z -= (float)8.0*floorf(z*(float)0.125); /* trim off integer >= 8 */ 00098 n = (int32_t) z; 00099 z -= (float)n; 00100 ih = 0; 00101 if(q0>0) { /* need iq[jz-1] to determine n */ 00102 i = (iq[jz-1]>>(8-q0)); n += i; 00103 iq[jz-1] -= i<<(8-q0); 00104 ih = iq[jz-1]>>(7-q0); 00105 } 00106 else if(q0==0) ih = iq[jz-1]>>8; 00107 else if(z>=(float)0.5) ih=2; 00108 00109 if(ih>0) { /* q > 0.5 */ 00110 n += 1; carry = 0; 00111 for(i=0;i<jz ;i++) { /* compute 1-q */ 00112 j = iq[i]; 00113 if(carry==0) { 00114 if(j!=0) { 00115 carry = 1; iq[i] = 0x100- j; 00116 } 00117 } else iq[i] = 0xff - j; 00118 } 00119 if(q0>0) { /* rare case: chance is 1 in 12 */ 00120 switch(q0) { 00121 case 1: 00122 iq[jz-1] &= 0x7f; break; 00123 case 2: 00124 iq[jz-1] &= 0x3f; break; 00125 } 00126 } 00127 if(ih==2) { 00128 z = one - z; 00129 if(carry!=0) z -= scalbnf(one,q0); 00130 } 00131 } 00132 00133 /* check if recomputation is needed */ 00134 if(z==zero) { 00135 j = 0; 00136 for (i=jz-1;i>=jk;i--) j |= iq[i]; 00137 if(j==0) { /* need recomputation */ 00138 for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */ 00139 00140 for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */ 00141 f[jx+i] = (float) ipio2[jv+i]; 00142 for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; 00143 q[i] = fw; 00144 } 00145 jz += k; 00146 goto recompute; 00147 } 00148 } 00149 00150 /* chop off zero terms */ 00151 if(z==(float)0.0) { 00152 jz -= 1; q0 -= 8; 00153 while(iq[jz]==0) { jz--; q0-=8;} 00154 } else { /* break z into 8-bit if necessary */ 00155 z = scalbnf(z,-q0); 00156 if(z>=two8) { 00157 fw = (float)((int32_t)(twon8*z)); 00158 iq[jz] = (int32_t)(z-two8*fw); 00159 jz += 1; q0 += 8; 00160 iq[jz] = (int32_t) fw; 00161 } else iq[jz] = (int32_t) z ; 00162 } 00163 00164 /* convert integer "bit" chunk to floating-point value */ 00165 fw = scalbnf(one,q0); 00166 for(i=jz;i>=0;i--) { 00167 q[i] = fw*(float)iq[i]; fw*=twon8; 00168 } 00169 00170 /* compute PIo2[0,...,jp]*q[jz,...,0] */ 00171 for(i=jz;i>=0;i--) { 00172 for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; 00173 fq[jz-i] = fw; 00174 } 00175 00176 /* compress fq[] into y[] */ 00177 switch(prec) { 00178 case 0: 00179 fw = 0.0; 00180 for (i=jz;i>=0;i--) fw += fq[i]; 00181 y[0] = (ih==0)? fw: -fw; 00182 break; 00183 case 1: 00184 case 2: 00185 fw = 0.0; 00186 for (i=jz;i>=0;i--) fw += fq[i]; 00187 y[0] = (ih==0)? fw: -fw; 00188 fw = fq[0]-fw; 00189 for (i=1;i<=jz;i++) fw += fq[i]; 00190 y[1] = (ih==0)? fw: -fw; 00191 break; 00192 case 3: /* painful */ 00193 for (i=jz;i>0;i--) { 00194 fw = fq[i-1]+fq[i]; 00195 fq[i] += fq[i-1]-fw; 00196 fq[i-1] = fw; 00197 } 00198 for (i=jz;i>1;i--) { 00199 fw = fq[i-1]+fq[i]; 00200 fq[i] += fq[i-1]-fw; 00201 fq[i-1] = fw; 00202 } 00203 for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; 00204 if(ih==0) { 00205 y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; 00206 } else { 00207 y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; 00208 } 00209 } 00210 return n&7; 00211 } 00212 00213 #endif