[BACK]Return to dft.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / fft

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>