Annotation of OpenXM_contrib2/asir2000/fft/dft.c, Revision 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>