1*05a0b428SJohn Marino /* k_rem_pio2f.c -- float version of k_rem_pio2.c 2*05a0b428SJohn Marino * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. 3*05a0b428SJohn Marino */ 4*05a0b428SJohn Marino 5*05a0b428SJohn Marino /* 6*05a0b428SJohn Marino * ==================================================== 7*05a0b428SJohn Marino * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 8*05a0b428SJohn Marino * 9*05a0b428SJohn Marino * Developed at SunPro, a Sun Microsystems, Inc. business. 10*05a0b428SJohn Marino * Permission to use, copy, modify, and distribute this 11*05a0b428SJohn Marino * software is freely granted, provided that this notice 12*05a0b428SJohn Marino * is preserved. 13*05a0b428SJohn Marino * ==================================================== 14*05a0b428SJohn Marino */ 15*05a0b428SJohn Marino 16*05a0b428SJohn Marino #include "math.h" 17*05a0b428SJohn Marino #include "math_private.h" 18*05a0b428SJohn Marino 19*05a0b428SJohn Marino /* In the float version, the input parameter x contains 8 bit 20*05a0b428SJohn Marino integers, not 24 bit integers. 113 bit precision is not supported. */ 21*05a0b428SJohn Marino 22*05a0b428SJohn Marino static const int init_jk[] = {4,7,9}; /* initial value for jk */ 23*05a0b428SJohn Marino 24*05a0b428SJohn Marino static const float PIo2[] = { 25*05a0b428SJohn Marino 1.5703125000e+00, /* 0x3fc90000 */ 26*05a0b428SJohn Marino 4.5776367188e-04, /* 0x39f00000 */ 27*05a0b428SJohn Marino 2.5987625122e-05, /* 0x37da0000 */ 28*05a0b428SJohn Marino 7.5437128544e-08, /* 0x33a20000 */ 29*05a0b428SJohn Marino 6.0026650317e-11, /* 0x2e840000 */ 30*05a0b428SJohn Marino 7.3896444519e-13, /* 0x2b500000 */ 31*05a0b428SJohn Marino 5.3845816694e-15, /* 0x27c20000 */ 32*05a0b428SJohn Marino 5.6378512969e-18, /* 0x22d00000 */ 33*05a0b428SJohn Marino 8.3009228831e-20, /* 0x1fc40000 */ 34*05a0b428SJohn Marino 3.2756352257e-22, /* 0x1bc60000 */ 35*05a0b428SJohn Marino 6.3331015649e-25, /* 0x17440000 */ 36*05a0b428SJohn Marino }; 37*05a0b428SJohn Marino 38*05a0b428SJohn Marino static const float 39*05a0b428SJohn Marino zero = 0.0, 40*05a0b428SJohn Marino one = 1.0, 41*05a0b428SJohn Marino two8 = 2.5600000000e+02, /* 0x43800000 */ 42*05a0b428SJohn Marino twon8 = 3.9062500000e-03; /* 0x3b800000 */ 43*05a0b428SJohn Marino 44*05a0b428SJohn Marino int 45*05a0b428SJohn Marino __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, 46*05a0b428SJohn Marino const int32_t *ipio2) 47*05a0b428SJohn Marino { 48*05a0b428SJohn Marino int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; 49*05a0b428SJohn Marino float z,fw,f[20],fq[20],q[20]; 50*05a0b428SJohn Marino 51*05a0b428SJohn Marino /* initialize jk*/ 52*05a0b428SJohn Marino jk = init_jk[prec]; 53*05a0b428SJohn Marino jp = jk; 54*05a0b428SJohn Marino 55*05a0b428SJohn Marino /* determine jx,jv,q0, note that 3>q0 */ 56*05a0b428SJohn Marino jx = nx-1; 57*05a0b428SJohn Marino jv = (e0-3)/8; if(jv<0) jv=0; 58*05a0b428SJohn Marino q0 = e0-8*(jv+1); 59*05a0b428SJohn Marino 60*05a0b428SJohn Marino /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ 61*05a0b428SJohn Marino j = jv-jx; m = jx+jk; 62*05a0b428SJohn Marino for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j]; 63*05a0b428SJohn Marino 64*05a0b428SJohn Marino /* compute q[0],q[1],...q[jk] */ 65*05a0b428SJohn Marino for (i=0;i<=jk;i++) { 66*05a0b428SJohn Marino for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; 67*05a0b428SJohn Marino } 68*05a0b428SJohn Marino 69*05a0b428SJohn Marino jz = jk; 70*05a0b428SJohn Marino recompute: 71*05a0b428SJohn Marino /* distill q[] into iq[] reversingly */ 72*05a0b428SJohn Marino for(i=0,j=jz,z=q[jz];j>0;i++,j--) { 73*05a0b428SJohn Marino fw = (float)((int32_t)(twon8* z)); 74*05a0b428SJohn Marino iq[i] = (int32_t)(z-two8*fw); 75*05a0b428SJohn Marino z = q[j-1]+fw; 76*05a0b428SJohn Marino } 77*05a0b428SJohn Marino 78*05a0b428SJohn Marino /* compute n */ 79*05a0b428SJohn Marino z = scalbnf(z,q0); /* actual value of z */ 80*05a0b428SJohn Marino z -= (float)8.0*floorf(z*(float)0.125); /* trim off integer >= 8 */ 81*05a0b428SJohn Marino n = (int32_t) z; 82*05a0b428SJohn Marino z -= (float)n; 83*05a0b428SJohn Marino ih = 0; 84*05a0b428SJohn Marino if(q0>0) { /* need iq[jz-1] to determine n */ 85*05a0b428SJohn Marino i = (iq[jz-1]>>(8-q0)); n += i; 86*05a0b428SJohn Marino iq[jz-1] -= i<<(8-q0); 87*05a0b428SJohn Marino ih = iq[jz-1]>>(7-q0); 88*05a0b428SJohn Marino } 89*05a0b428SJohn Marino else if(q0==0) ih = iq[jz-1]>>8; 90*05a0b428SJohn Marino else if(z>=(float)0.5) ih=2; 91*05a0b428SJohn Marino 92*05a0b428SJohn Marino if(ih>0) { /* q > 0.5 */ 93*05a0b428SJohn Marino n += 1; carry = 0; 94*05a0b428SJohn Marino for(i=0;i<jz ;i++) { /* compute 1-q */ 95*05a0b428SJohn Marino j = iq[i]; 96*05a0b428SJohn Marino if(carry==0) { 97*05a0b428SJohn Marino if(j!=0) { 98*05a0b428SJohn Marino carry = 1; iq[i] = 0x100- j; 99*05a0b428SJohn Marino } 100*05a0b428SJohn Marino } else iq[i] = 0xff - j; 101*05a0b428SJohn Marino } 102*05a0b428SJohn Marino if(q0>0) { /* rare case: chance is 1 in 12 */ 103*05a0b428SJohn Marino switch(q0) { 104*05a0b428SJohn Marino case 1: 105*05a0b428SJohn Marino iq[jz-1] &= 0x7f; break; 106*05a0b428SJohn Marino case 2: 107*05a0b428SJohn Marino iq[jz-1] &= 0x3f; break; 108*05a0b428SJohn Marino } 109*05a0b428SJohn Marino } 110*05a0b428SJohn Marino if(ih==2) { 111*05a0b428SJohn Marino z = one - z; 112*05a0b428SJohn Marino if(carry!=0) z -= scalbnf(one,q0); 113*05a0b428SJohn Marino } 114*05a0b428SJohn Marino } 115*05a0b428SJohn Marino 116*05a0b428SJohn Marino /* check if recomputation is needed */ 117*05a0b428SJohn Marino if(z==zero) { 118*05a0b428SJohn Marino j = 0; 119*05a0b428SJohn Marino for (i=jz-1;i>=jk;i--) j |= iq[i]; 120*05a0b428SJohn Marino if(j==0) { /* need recomputation */ 121*05a0b428SJohn Marino for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */ 122*05a0b428SJohn Marino 123*05a0b428SJohn Marino for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */ 124*05a0b428SJohn Marino f[jx+i] = (float) ipio2[jv+i]; 125*05a0b428SJohn Marino for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; 126*05a0b428SJohn Marino q[i] = fw; 127*05a0b428SJohn Marino } 128*05a0b428SJohn Marino jz += k; 129*05a0b428SJohn Marino goto recompute; 130*05a0b428SJohn Marino } 131*05a0b428SJohn Marino } 132*05a0b428SJohn Marino 133*05a0b428SJohn Marino /* chop off zero terms */ 134*05a0b428SJohn Marino if(z==(float)0.0) { 135*05a0b428SJohn Marino jz -= 1; q0 -= 8; 136*05a0b428SJohn Marino while(iq[jz]==0) { jz--; q0-=8;} 137*05a0b428SJohn Marino } else { /* break z into 8-bit if necessary */ 138*05a0b428SJohn Marino z = scalbnf(z,-q0); 139*05a0b428SJohn Marino if(z>=two8) { 140*05a0b428SJohn Marino fw = (float)((int32_t)(twon8*z)); 141*05a0b428SJohn Marino iq[jz] = (int32_t)(z-two8*fw); 142*05a0b428SJohn Marino jz += 1; q0 += 8; 143*05a0b428SJohn Marino iq[jz] = (int32_t) fw; 144*05a0b428SJohn Marino } else iq[jz] = (int32_t) z ; 145*05a0b428SJohn Marino } 146*05a0b428SJohn Marino 147*05a0b428SJohn Marino /* convert integer "bit" chunk to floating-point value */ 148*05a0b428SJohn Marino fw = scalbnf(one,q0); 149*05a0b428SJohn Marino for(i=jz;i>=0;i--) { 150*05a0b428SJohn Marino q[i] = fw*(float)iq[i]; fw*=twon8; 151*05a0b428SJohn Marino } 152*05a0b428SJohn Marino 153*05a0b428SJohn Marino /* compute PIo2[0,...,jp]*q[jz,...,0] */ 154*05a0b428SJohn Marino for(i=jz;i>=0;i--) { 155*05a0b428SJohn Marino for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; 156*05a0b428SJohn Marino fq[jz-i] = fw; 157*05a0b428SJohn Marino } 158*05a0b428SJohn Marino 159*05a0b428SJohn Marino /* compress fq[] into y[] */ 160*05a0b428SJohn Marino switch(prec) { 161*05a0b428SJohn Marino case 0: 162*05a0b428SJohn Marino fw = 0.0; 163*05a0b428SJohn Marino for (i=jz;i>=0;i--) fw += fq[i]; 164*05a0b428SJohn Marino y[0] = (ih==0)? fw: -fw; 165*05a0b428SJohn Marino break; 166*05a0b428SJohn Marino case 1: 167*05a0b428SJohn Marino case 2: 168*05a0b428SJohn Marino fw = 0.0; 169*05a0b428SJohn Marino for (i=jz;i>=0;i--) fw += fq[i]; 170*05a0b428SJohn Marino y[0] = (ih==0)? fw: -fw; 171*05a0b428SJohn Marino fw = fq[0]-fw; 172*05a0b428SJohn Marino for (i=1;i<=jz;i++) fw += fq[i]; 173*05a0b428SJohn Marino y[1] = (ih==0)? fw: -fw; 174*05a0b428SJohn Marino break; 175*05a0b428SJohn Marino case 3: /* painful */ 176*05a0b428SJohn Marino for (i=jz;i>0;i--) { 177*05a0b428SJohn Marino fw = fq[i-1]+fq[i]; 178*05a0b428SJohn Marino fq[i] += fq[i-1]-fw; 179*05a0b428SJohn Marino fq[i-1] = fw; 180*05a0b428SJohn Marino } 181*05a0b428SJohn Marino for (i=jz;i>1;i--) { 182*05a0b428SJohn Marino fw = fq[i-1]+fq[i]; 183*05a0b428SJohn Marino fq[i] += fq[i-1]-fw; 184*05a0b428SJohn Marino fq[i-1] = fw; 185*05a0b428SJohn Marino } 186*05a0b428SJohn Marino for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; 187*05a0b428SJohn Marino if(ih==0) { 188*05a0b428SJohn Marino y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; 189*05a0b428SJohn Marino } else { 190*05a0b428SJohn Marino y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; 191*05a0b428SJohn Marino } 192*05a0b428SJohn Marino } 193*05a0b428SJohn Marino return n&7; 194*05a0b428SJohn Marino } 195