Annotation of OpenXM_contrib2/asir2000/fft/dft.c, Revision 1.1.1.1
1.1 noro 1: /* $OpenXM: OpenXM/src/asir99/fft/dft.c,v 1.1.1.1 1999/11/10 08:12:27 noro Exp $ */
2: /*
3: * store arith modulus
4: * -------------------------------------------------------
5: * IEEE: float (23+1) <-> double (52+1) 24 bits
6: * int (32) <-> double (52+1) 26 bits
7: * 370: float (24) <-> double (56) 24/25 bits
8: * int (32) <-> double (56) 28 bits
9: */
10:
11:
12: #include "dft.h"
13:
14:
15: /*
16: #define C_DFT_FORE C_DFTfore
17: #define C_DFT_BACK C_DFTback
18: #define C_PREP_ALPHA C_prep_alpha
19: */
20:
21:
22: /*****************************************************/
23:
24: void C_DFT_FORE( in, nin, i1, K, powa,
25: #ifdef POWA_STRIDE
26: a1,
27: #endif
28: out, o1, P, Pinv, wk )
29: ModNum in[], powa[], out[], wk[];
30: ModNum P;
31: int nin, i1, K, o1;
32: #ifdef POWA_STRIDE
33: int a1;
34: #endif
35: double Pinv;
36: /*
37: * Let N = 2^K, and \alpha be a primitive N-th root of 1.
38: * out[0:N-1][o1] = DFT of in[0:nin-1][i1] using \alpha modulo P.
39: * The powers \alpha (to the degrees upto N/2=2^{K-1} at least) are given in powa[*],
40: * (or powa[a1**]).
41: * nin <= N assumed.
42: * wk[] must have 2^K entries at least.
43: */
44: {
45: int istep, ostep, i, j, k, idist, odist, n, Ndiv2n, K_k,
46: #ifndef OPT
47: K_k_1,
48: #endif
49: #ifdef POWA_STRIDE
50: aj,
51: #endif
52: inwk;
53: int idistwk, idistout, iostep, oostep;
54: ModNum *qi, *qo, *qis, *qos, a, t0, tn;
55:
56: /*
57: * for k = K-1, ..., 0 do the following:
58: *
59: * Out[2^{K-k}*i + j] <= t0 + \alpha^{2^k * j} * tn;
60: * Out[2^{K-k}*i + j + 2^{K-k-1}] <= t0 - \alpha^{2^k * j} * tn;
61: *
62: * where t0 = In[2^{K-k-1}*i + j] and
63: * tn = In[2^{K-k-1}*i + j + 2^{K-1}],
64: * for 0 <= i < 2^k and 0 <= j < 2^{K-k-1}.
65: *
66: */
67: /* In the following, n = 2^k and Ndiv2n = 2^{K-k-1}.
68: */
69: n = 1 << (k = K - 1);
70: idistwk = n, idistout = o1 << k;
71: /* when k = K-1, Out[2*i] <= In[i] + In[i+2^{K-1}],
72: * and Out[2*i+1] <= In[i] - In[i+2^{K-1}], for 0 <= i < 2^{K-1}.
73: */
74: if ( k&1 ) qo = wk, ostep = 2, inwk = 1, odist = 1;
75: else qo = out, ostep = o1 << 1, inwk = 0, odist = o1;
76: qi = in;
77: /**/
78: if ( nin <= n ) {
79: for ( i = nin; i > 0; i--, qi += i1, qo += ostep ) qo[0] = qo[odist] = qi[0];
80: for ( i = n - nin; i > 0; i--, qo += ostep ) qo[0] = qo[odist] = 0;
81: } else {
82: idist = i1 << k; /* distance = 2^{K-1} */
83: for ( j = i = nin - n; i > 0; i--, qi += i1, qo += ostep ) {
84: t0 = qi[0], tn = qi[idist];
85: if ( tn == (ModNum)0 ) qo[0] = qo[odist] = t0;
86: else {
87: qo[0] = AplusBmodP( t0, tn, P );
88: qo[odist] = A_BmodP( t0, tn, P );
89: }
90: }
91: for ( i = n - j; i > 0; i--, qi += i1, qo += ostep )
92: qo[0] = qo[odist] = qi[0];
93: }
94: /******/
95: #ifndef J_INNER
96: for ( K_k = 1, Ndiv2n = 1; --k > 0; inwk = 1 - inwk ) {
97: #ifndef OPT
98: K_k = (K_k_1 = K_k) + 1;
99: #endif
100: n >>= 1; /* == 2^k */
101: Ndiv2n <<= 1; /* == 2^{K-k-1} */
102: if ( inwk )
103: qi = wk, qo = out, iostep = 1, oostep = o1, idist = idistwk;
104: else
105: qi = out, qo = wk, iostep = o1, oostep = 1, idist = idistout;
106: qis = qi, qos = qo;
107: /**/
108: istep = ostep; /* = iostep << K_k_1; */
109: #ifndef OPT
110: ostep = oostep << K_k;
111: odist = oostep << K_k_1;
112: #else
113: odist = oostep << K_k;
114: ++K_k;
115: ostep = oostep << K_k;
116: #endif /* OPT */
117: /* j = 0 */
118: for ( i = n; i-- > 0; qi += istep, qo += ostep ) {
119: t0 = qi[0], tn = qi[idist];
120: if ( tn == (ModNum)0 ) qo[0] = qo[odist] = t0;
121: else {
122: qo[0] = AplusBmodP( t0, tn, P );
123: qo[odist] = A_BmodP( t0, tn, P );
124: }
125: }
126: /**/
127: #ifdef POWA_STRIDE
128: for ( aj = a1, j = 1; j < Ndiv2n; aj += a1, j++ ) {
129: a = powa[aj << k];
130: #else
131: for ( j = 1; j < Ndiv2n; j++ ) {
132: a = powa[j << k];
133: #endif
134: qi = (qis += iostep), qo = (qos += oostep);
135: for ( i = 0; i < n; i++, qi += istep, qo += ostep ) {
136: t0 = qi[0], tn = qi[idist];
137: if ( tn == (ModNum)0 ) qo[0] = qo[odist] = t0;
138: else {
139: AxBmodP( tn, ModNum, tn, a, P, Pinv );
140: qo[0] = AplusBmodP( t0, tn, P );
141: qo[odist] = A_BmodP( t0, tn, P );
142: }
143: }
144: }
145: }
146: /*
147: * When k = 0, for i = 0 (0 <= i < 2^0=1) and 0 <= j < 2^{K-1},
148: * Out[j] <= t0 + \alpha^{j}*tn and Out[j+2^{K-1}] <= t0 - \alpha^{j}*tn,
149: * where t0 = In[j] and tn = In[j + 2^{K-1}].
150: */
151: qi = wk, qo = out, idist = idistwk, odist = idistout;
152: /* == 2^{K-1}, == o1 << (K-1) */
153: t0 = qi[0], tn = qi[idist];
154: if ( tn == (ModNum)0 ) qo[0] = qo[odist] = t0;
155: else {
156: qo[0] = AplusBmodP( t0, tn, P );
157: qo[odist] = A_BmodP( t0, tn, P );
158: }
159: #ifdef POWA_STRIDE
160: for ( k = o1, aj = a1, j = 1; j < idist; aj += a1, j++ ) {
161: #else
162: for ( k = o1, j = 1; j < idist; j++ ) {
163: #endif
164: qi++, qo += k;
165: t0 = qi[0], tn = qi[idist];
166: if ( tn == (ModNum)0 ) qo[0] = qo[odist] = t0;
167: else {
168: #ifdef POWA_STRIDE
169: a = powa[aj];
170: #else
171: a = powa[j];
172: #endif
173: AxBmodP( tn, ModNum, tn, a, P, Pinv );
174: qo[0] = AplusBmodP( t0, tn, P );
175: qo[odist] = A_BmodP( t0, tn, P );
176: }
177: }
178: #else
179: for ( K_k = 1, Ndiv2n = 1; --k >= 0; inwk = 1 - inwk ) {
180: #ifndef OPT
181: K_k = (K_k_1 = K_k) + 1;
182: #endif
183: n >>= 1; /* == 2^k */
184: Ndiv2n <<= 1; /* == 2^{K-k-1} */
185: if ( inwk ) qi = wk, qo = out, istep = 1, ostep = o1, idist = idistwk;
186: else qi = out, qo = wk, istep = o1, ostep = 1, idist = idistout;
187: qis = qi, qos = qo;
188: /**/
189: iostep = oostep; /* = istep << K_k_1; */
190: #ifndef OPT
191: oostep = ostep << K_k;
192: odist = ostep << K_k_1;
193: #else
194: odist = ostep << K_k;
195: ++K_k;
196: oostep = ostep << K_k;
197: #endif /* OPT */
198: for ( i = n; i-- > 0; qis += iostep, qos += oostep ) {
199: /* j = 0 */
200: t0 = qis[0], tn = qis[idist];
201: if ( tn == (ModNum)0 ) qos[0] = qos[odist] = t0;
202: else {
203: qos[0] = AplusBmodP( t0, tn, P );
204: qos[odist] = A_BmodP( t0, tn, P );
205: }
206: #ifdef POWA_STRIDE
207: for ( aj = a1, j = 1, qi = qis, qo = qos; j < Ndiv2n; aj += a1, j++ ) {
208: #else
209: for ( j = 1, qi = qis, qo = qos; j < Ndiv2n; j++ ) {
210: #endif
211: qi += istep, qo += ostep;
212: t0 = qi[0], tn = qi[idist];
213: if ( tn == (ModNum)0 ) qo[0] = qo[odist] = t0;
214: else {
215: #ifdef POWA_STRIDE
216: a = powa[aj << k];
217: #else
218: a = powa[j << k];
219: #endif
220: AxBmodP( tn, ModNum, tn, a, P, Pinv );
221: qo[0] = AplusBmodP( t0, tn, P );
222: qo[odist] = A_BmodP( t0, tn, P );
223: }
224: }
225: }
226: }
227: #endif
228: }
229:
230: /*********************************************************************
231: *
232: * NOTE:
233: * (1) Let \alpha be a primitive N-th root of unity modulo P,
234: * where N is even,
235: * and t be an integer s.t. 0 <= t < N/2.
236: * Then, 1/\alpha^t is given by (- \alpha^s) with s = N/2 - t.
237: *
238: * (2) Let P be a prime s.t. P = 2^n*Q + 1, where Q is an odd integer.
239: * Then, for 0 < s <= n, 2^{-s} \equiv - 2^{n-s}*Q \bmod P,
240: * because 1 \equiv - 2^n*Q \bmod P.
241: *
242: **********************************************************************/
243:
244: void C_DFT_BACK( in, N, i1, log2N, powa,
245: #ifdef POWA_STRIDE
246: a1,
247: #endif
248: out, o1, osi, nout, Ninv, P, Pinv, wk )
249: ModNum in[], powa[], out[], wk[];
250: int N, log2N, osi, nout, i1, o1;
251: #ifdef POWA_STRIDE
252: int a1;
253: #endif
254: ModNum P, Ninv;
255: double Pinv;
256: /*
257: * Let K denote log2N. Let N = 2^K, and \alpha be a primitive N-th root of 1.
258: * This routine computes the inverse discrete-Fourier transform of in[0:N-1][i1]
259: * using \alpha^{-1} modulo P, and store the `nout' transformed data from the
260: * `osi'-th in out[0:nout-1][o1]. 0 <= osi < N-1 and 0 < nout <= N.
261: * The powers of \alpha (to the degrees upto N/2=2^{K-1} at least) are given in powa[*] (or powa[a1* *]).
262: * The area wk[] is used to contain the intermediate transformed data, and thus,
263: * must have 2*N entries at least. Notice that `out' cannot be used because
264: * its space amount (`nout') may not be sufficient for this purpose.
265: */
266: {
267: int i, j, k, n, is, os, istep, ostep, idist, inwk, halfN;
268: #ifdef POWA_STRIDE
269: int aj, halfNa;
270: #endif
271: ModNum *qi, *qo, *qis, *qos, a, t0, tn, tt;
272:
273: /*
274: * for k = K-1, ..., 0 do the following:
275: *
276: * Out[2^{K-k}*i + j] <= t0 + \alpha^{- 2^k * j} * tn;
277: * = t0 - \alpha^{N/2 - 2^k * j}*tn;
278: * Out[2^{K-k}*i + j + 2^{K-k-1}] <= t0 - \alpha^{- 2^k * j} * tn;
279: * = t0 + \alpha^{N/2 - 2^k * j}*tn;
280: *
281: * where t0 = In[2^{K-k-1}*i + j] and
282: * tn = In[2^{K-k-1}*i + j + 2^{K-1}],
283: * for 0 <= i < 2^k and 0 <= j < 2^{K-k-1}.
284: *
285: */
286: if ( log2N == 1 ) {
287: /* K = 1, k = 0, 0 <= i < 1, 0 <= j < 1.
288: * Out[0] <= t0 + tn, Out[1] <= t0 - tn,
289: * where t0 = In[0] and Tn = In[1].
290: */
291: t0 = in[0], tn = in[i1];
292: if ( osi == 0 ) {
293: /* out[0] = (t0 + tn)*Ninv; */
294: tt = tn == (ModNum)0 ? t0 : AplusBmodP( t0, tn, P );
295: if ( tt != (ModNum)0 ) {
296: AxBmodP( tt, ModNum, tt, Ninv, P, Pinv );
297: }
298: out[0] = tt;
299: i = 1;
300: } else i = 0;
301: /**/
302: if ( osi + nout >= 2 ) {
303: /* out[osi == 0 ? 1 : 0] = (t0 - tn)*Ninv; */
304: tt = tn == (ModNum)0 ? t0 : A_BmodP( t0, tn, P );
305: if ( tt != (ModNum)0 ) {
306: AxBmodP( tt, ModNum, tt, Ninv, P, Pinv );
307: }
308: out[i] = tt;
309: }
310: return;
311: }
312: /****/
313: halfN = n = 1 << (k = log2N - 1); /* == 2^{K-1} */
314: #ifdef POWA_STRIDE
315: halfNa = a1 << k;
316: #endif
317: /*
318: * when k = K-1,
319: * Out[2*i] <= t0 + tn, and Out[2*i+1] <= t0 - tn,
320: * where t0 = In[i] and tn = In[i+2^{K-1}],
321: * for 0 <= i < 2^{K-1}.
322: */
323: qi = in, istep = i1, idist = i1 << k, qo = wk, inwk = 0;
324: for ( i = n; i-- > 0; qi += istep, qo += 2 ) {
325: t0 = qi[0], tn = qi[idist];
326: if ( tn == (ModNum)0 ) qo[0] = qo[1] = t0;
327: else {
328: qo[0] = AplusBmodP( t0, tn, P );
329: qo[1] = A_BmodP( t0, tn, P );
330: }
331: }
332: #ifdef EBUG
333: fprintf( stderr, "::: DFT^{-1} ::: after the first step\n" );
334: for ( qo = wk, i = 0; i < N; i++ ) {
335: if ( (i%5) == 0 ) fprintf( stderr, "\t" );
336: fprintf( stderr, "%10d,", (int)wk[i] );
337: if ( (i%5) == 4 ) fprintf( stderr, "\n" );
338: }
339: if ( (i%5) != 0 ) fprintf( stderr, "\n" );
340: #endif
341: /**/
342: idist = halfN;
343: for ( ostep = 2; --k > 0; inwk = 1 - inwk ) {
344: n >>= 1;
345: istep = ostep; /* == 2^{K-k-1} */
346: ostep <<= 1; /* == 2^{K-k} */
347: if ( inwk ) qi = &wk[N], qo = wk;
348: else qi = wk, qo = &wk[N];
349: qis = qi, qos = qo;
350: /*
351: * for j = 0,
352: * Out[2^{K-k}*i] <= t0 + tn, and Out[2^{K-k}*i + 2^{K-k-1}] <= t0 - tn,
353: * where t0 = In[2^{K-k-1}*i] and tn = In[2^{K-k-1}*i + 2^{K-1}].
354: */
355: for ( i = n, is = os = 0; i-- > 0; qi += istep, qo += ostep ) {
356: t0 = qi[0], tn = qi[idist];
357: if ( tn == (ModNum)0 ) qo[0] = qo[istep] = t0;
358: else {
359: qo[0] = AplusBmodP( t0, tn, P );
360: qo[istep] = A_BmodP( t0, tn, P );
361: }
362: }
363: #ifdef POWA_STRIDE
364: for ( aj = a1, j = 1; j < istep; aj += a1, j++ ) {
365: /*** a = P - powa[halfNa - (aj << k)]; ***/
366: a = powa[halfNa - (aj << k)];
367: #else
368: for ( j = 1; j < istep; j++ ) {
369: /*** a = P - powa[halfN - (j << k)]; ***/
370: a = powa[halfN - (j << k)];
371: #endif
372: qi = ++qis, qo = ++qos;
373: for ( i = n; i-- > 0; qi += istep, qo += ostep ) {
374: t0 = qi[0], tn = qi[idist];
375: if ( tn == (ModNum)0 ) qo[0] = qo[istep] = t0;
376: else {
377: AxBmodP( tn, ModNum, tn, a, P, Pinv );
378: /*** qo[0] = AplusBmodP( t0, tn, P ); ***/
379: /*** qo[istep] = A_BmodP( t0, tn, P ); ***/
380: qo[0] = A_BmodP( t0, tn, P );
381: qo[istep] = AplusBmodP( t0, tn, P );
382: }
383: }
384: }
385: }
386: #if 0
387: final:
388: #endif
389: /*
390: * The final step of k = 0. i can take only the value 0.
391: *
392: * Out[j] <= t0 + \alpha^{-j} * tn;
393: * Out[j + 2^{K-1}] <= t0 - \alpha^{-j} * tn;
394: *
395: * where t0 = In[j] and tn = In[j + 2^{K-1}],
396: * for 0 <= j < 2^{K-1}.
397: *
398: */
399: qo = out, qi = &wk[inwk ? N : 0];
400: if ( (n = osi + nout) > N ) nout = (n = N) - osi; /* true nout */
401: if ( (k = nout - halfN) <= 0 ) { /* no overlap, i.e., no +- */
402: if ( osi <= 0 ) {
403: t0 = qi[0], tn = qi[idist];
404: if ( tn != (ModNum)0 ) t0 = AplusBmodP( t0, tn, P );
405: if ( t0 == (ModNum)0 ) qo[0] = t0;
406: else {
407: AxBmodP( qo[0], ModNum, t0, Ninv, P, Pinv );
408: }
409: #ifdef POWA_STRIDE
410: aj = a1;
411: #endif
412: j = 1, k = n, i = 0, qo += o1;
413: } else {
414: j = osi;
415: #ifdef POWA_STRIDE
416: aj = osi*a1;
417: #endif
418: if ( n <= halfN ) i = 0, k = n; /* lower only */
419: else if ( j == halfN ) goto L_halfN; /* start with j = N/2 */
420: else if ( j > halfN ) goto L_upper; /* upper only */
421: else i = n - halfN + 1, k = halfN; /* we have lower, and i upper */
422: }
423: } else {
424: os = o1*halfN;
425: #ifdef EBUG
426: fprintf( stderr, "::::: DFT^{-1} ::: os=%d*%d=%d\n", o1, halfN, os );
427: #endif
428: if ( osi <= 0 ) {
429: t0 = qi[0], tn = qi[idist];
430: if ( tn == (ModNum)0 ) {
431: if ( t0 == (ModNum)0 ) tt = t0;
432: else { AxBmodP( tt, ModNum, t0, Ninv, P, Pinv ); }
433: qo[0] = qo[os] = tt;
434: } else {
435: tt = AplusBmodP( t0, tn, P );
436: if ( tt == (ModNum)0 ) qo[0] = tt;
437: else { AxBmodP( qo[0], ModNum, tt, Ninv, P, Pinv ); }
438: tt = A_BmodP( t0, tn, P );
439: if ( tt == (ModNum)0 ) qo[os] = tt;
440: else { AxBmodP( qo[os], ModNum, tt, Ninv, P, Pinv ); }
441: }
442: #ifdef EBUG
443: fprintf( stderr, "::::: DFT^{-1} ::: [0]=%d, [%d]=%d\n", (int)qo[0], os, (int)qo[os] );
444: #endif
445: #ifdef POWA_STRIDE
446: j = 1, aj = a1, n = halfN, i = 0, qo += o1, k--;
447: } else j = osi, aj = osi*a1, i = (n -= k) - halfN;
448: /**/
449: for ( ; k-- > 0; aj += a1, j++, qo += o1 ) {
450: #else
451: j = 1, n = halfN, i = 0, qo += o1, k--;
452: } else j = osi, i = (n -= k) - halfN;
453: /**/
454: for ( ; k-- > 0; j++, qo += o1 ) {
455: #endif
456: t0 = qi[j], tn = qi[j+idist];
457: if ( tn == (ModNum)0 ) {
458: if ( t0 != (ModNum)0 ) {
459: AxBmodP( t0, ModNum, t0, Ninv, P, Pinv );
460: }
461: qo[0] = qo[os] = t0;
462: } else {
463: #ifdef POWA_STRIDE
464: /*** a = P - powa[halfNa - aj]; ***/
465: a = powa[halfNa - aj];
466: #else
467: /*** a = P - powa[halfN - j]; ***/
468: a = powa[halfN - j];
469: #endif
470: AxBmodP( tn, ModNum, tn, a, P, Pinv );
471: /*** tt = AplusBmodP( t0, tn, P ); ***/
472: tt = A_BmodP( t0, tn, P );
473: if ( tt == (ModNum)0 ) qo[0] = tt;
474: else { AxBmodP( qo[0], ModNum, tt, Ninv, P, Pinv ); }
475: /*** tt = A_BmodP( t0, tn, P ); ***/
476: tt = AplusBmodP( t0, tn, P );
477: if ( tt == (ModNum)0 ) qo[os] = tt;
478: else { AxBmodP( qo[os], ModNum, tt, Ninv, P, Pinv ); }
479: }
480: }
481: k = halfN;
482: }
483: /*
484: * At this point, k is an upper limit < N/2 for j, i is the number of j's
485: * > N/2, and n is the real upper limit of j.
486: */
487: #ifdef POWA_STRIDE
488: for ( ; j < k; aj += a1, j++, qo += o1 ) {
489: #else
490: for ( ; j < k; j++, qo += o1 ) {
491: #endif
492: t0 = qi[j], tn = qi[j+idist];
493: if ( tn == (ModNum)0 ) {
494: if ( t0 == (ModNum)0 ) qo[0] = t0;
495: else { AxBmodP( qo[0], ModNum, t0, Ninv, P, Pinv ); }
496: } else {
497: #ifdef POWA_STRIDE
498: a = P - powa[halfNa - aj];
499: #else
500: a = P - powa[halfN - j];
501: #endif
502: AxBplusCmodP( tt, ModNum, tn, a, t0, P, Pinv );
503: if ( tt == (ModNum)0 ) qo[0] = tt;
504: else { AxBmodP( qo[0], ModNum, tt, Ninv, P, Pinv ); }
505: }
506: }
507: if ( i <= 0 ) return;
508: /**/
509: L_halfN:
510: t0 = qi[0], tn = qi[idist];
511: tt = tn == (ModNum)0 ? t0 : A_BmodP( t0, tn, P );
512: if ( tt == (ModNum)0 ) qo[0] = tt;
513: else { AxBmodP( qo[0], ModNum, tt, Ninv, P, Pinv ); }
514: qo += o1, j++;
515: /**/
516: L_upper:
517: #ifdef POWA_STRIDE
518: for ( n -= halfN, aj = a1, j = 1; j < n; aj += a1, j++, qo += o1 ) {
519: #else
520: for ( n -= halfN, j = 1; j < n; j++, qo += o1 ) {
521: #endif
522: t0 = qi[j], tn = qi[j+idist];
523: if ( tn == (ModNum)0 ) {
524: if ( t0 == (ModNum)0 ) qo[0] = t0;
525: else { AxBmodP( qo[0], ModNum, t0, Ninv, P, Pinv ); }
526: } else {
527: #ifdef POWA_STRIDE
528: a = powa[halfNa - aj];
529: #else
530: a = powa[halfN - j];
531: #endif
532: AxBplusCmodP( tt, ModNum, tn, a, t0, P, Pinv );
533: if ( tt == (ModNum)0 ) qo[0] = tt;
534: else { AxBmodP( qo[0], ModNum, tt, Ninv, P, Pinv ); }
535: }
536: }
537: }
538:
539: #if USE_FLOAT
540: void C_PREP_ALPHA( r, log2ord, log2k, n, tbl, P, Pinv )
541: ModNum r, tbl[], P;
542: int log2ord, log2k, n;
543: double Pinv;
544: /*
545: * Let K and k denote log2ord and log2k, respectively.
546: * Let r be a primitive (2^K)-th root of unity in Z/(P), where P is a prime.
547: * Compute a = r^{2^{K-k}}, a primitive (2^k)-th root of unity, and
548: * its powers to the degrees upto n in tbl[*].
549: */
550: {
551: int i;
552: ModNum *q;
553: double t, w, dp = (double) P;
554:
555: for ( w = (double) r, i = log2ord - log2k; i > 0; i-- ) {
556: w *= w;
557: if ( w < dp ) continue;
558: w -= (dp*(double)((int) (w*Pinv)));
559: }
560: tbl[0] = 1;
561: tbl[1] = (ModNum)(t = w);
562: for ( q = &tbl[2], i = n - 1; i > 0; i-- ) {
563: t *= w;
564: if ( t >= dp ) t -= (dp*(double)((int) (t*Pinv)));
565: *q++ = t;
566: }
567: }
568: #else
569:
570: void C_PREP_ALPHA( r, log2ord, log2k, n, tbl, P, Pinv )
571: ModNum r, tbl[], P;
572: int log2ord, log2k, n;
573: double Pinv;
574: /*
575: * Let K and k denote log2ord and log2k, respectively.
576: * Let r be a primitive (2^K)-th root of unity in Z/(P), where P is a prime.
577: * Compute a = r^{2^{K-k}}, a primitive (2^k)-th root of unity, and
578: * its powers to the degrees upto n in tbl[*].
579: */
580: {
581: int i;
582: ModNum *q;
583: ModNum t, w, s;
584:
585: for ( w = r, i = log2ord - log2k; i > 0; i-- ) {
586: AxBmodP( t, ModNum, w, w, P, Pinv );
587: w = t;
588: }
589: tbl[0] = 1;
590: tbl[1] = (ModNum)(t = w);
591: for ( q = &tbl[2], i = n - 1; i > 0; i-- ) {
592: AxBmodP( s, ModNum, t, w, P, Pinv );
593: t = s;
594: *q++ = t;
595: }
596: }
597: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>