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