1/*
2 * Copyright(c)1995,97 Mark Olesen <olesen@me.QueensU.CA>
3 *    Queen's Univ at Kingston (Canada)
4 *
5 * Permission to use, copy, modify, and distribute this software for
6 * any purpose without fee is hereby granted, provided that this
7 * entire notice is included in all copies of any software which is
8 * or includes a copy or modification of this software and in all
9 * copies of the supporting documentation for such software.
10 *
11 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
12 * IMPLIED WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR QUEEN'S
13 * UNIVERSITY AT KINGSTON MAKES ANY REPRESENTATION OR WARRANTY OF ANY
14 * KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
15 * FITNESS FOR ANY PARTICULAR PURPOSE.
16 *
17 * All of which is to say that you can do what you like with this
18 * source code provided you don't try to sell it as your own and you
19 * include an unaltered copy of this message (including the
20 * copyright).
21 *
22 * It is also implicitly understood that bug fixes and improvements
23 * should make their way back to the general Internet community so
24 * that everyone benefits.
25 *
26 * Changes:
27 *   Trivial type modifications by the WebRTC authors.
28 */
29
30
31/*
32 * File:
33 * WebRtcIsac_Fftn.c
34 *
35 * Public:
36 * WebRtcIsac_Fftn / fftnf ();
37 *
38 * Private:
39 * WebRtcIsac_Fftradix / fftradixf ();
40 *
41 * Descript:
42 * multivariate complex Fourier transform, computed in place
43 * using mixed-radix Fast Fourier Transform algorithm.
44 *
45 * Fortran code by:
46 * RC Singleton, Stanford Research Institute, Sept. 1968
47 *
48 * translated by f2c (version 19950721).
49 *
50 * int WebRtcIsac_Fftn (int ndim, const int dims[], REAL Re[], REAL Im[],
51 *     int iSign, double scaling);
52 *
53 * NDIM = the total number dimensions
54 * DIMS = a vector of array sizes
55 * if NDIM is zero then DIMS must be zero-terminated
56 *
57 * RE and IM hold the real and imaginary components of the data, and return
58 * the resulting real and imaginary Fourier coefficients.  Multidimensional
59 * data *must* be allocated contiguously.  There is no limit on the number
60 * of dimensions.
61 *
62 * ISIGN = the sign of the complex exponential (ie, forward or inverse FFT)
63 * the magnitude of ISIGN (normally 1) is used to determine the
64 * correct indexing increment (see below).
65 *
66 * SCALING = normalizing constant by which the final result is *divided*
67 * if SCALING == -1, normalize by total dimension of the transform
68 * if SCALING <  -1, normalize by the square-root of the total dimension
69 *
70 * example:
71 * tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3]
72 *
73 * int dims[3] = {n1,n2,n3}
74 * WebRtcIsac_Fftn (3, dims, Re, Im, 1, scaling);
75 *
76 *-----------------------------------------------------------------------*
77 * int WebRtcIsac_Fftradix (REAL Re[], REAL Im[], size_t nTotal, size_t nPass,
78 *   size_t nSpan, int iSign, size_t max_factors,
79 *   size_t max_perm);
80 *
81 * RE, IM - see above documentation
82 *
83 * Although there is no limit on the number of dimensions, WebRtcIsac_Fftradix() must
84 * be called once for each dimension, but the calls may be in any order.
85 *
86 * NTOTAL = the total number of complex data values
87 * NPASS  = the dimension of the current variable
88 * NSPAN/NPASS = the spacing of consecutive data values while indexing the
89 * current variable
90 * ISIGN - see above documentation
91 *
92 * example:
93 * tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3]
94 *
95 * WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n1,       n1, 1, maxf, maxp);
96 * WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n2,    n1*n2, 1, maxf, maxp);
97 * WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n3, n1*n2*n3, 1, maxf, maxp);
98 *
99 * single-variate transform,
100 *    NTOTAL = N = NSPAN = (number of complex data values),
101 *
102 * WebRtcIsac_Fftradix (Re, Im, n, n, n, 1, maxf, maxp);
103 *
104 * The data can also be stored in a single array with alternating real and
105 * imaginary parts, the magnitude of ISIGN is changed to 2 to give correct
106 * indexing increment, and data [0] and data [1] used to pass the initial
107 * addresses for the sequences of real and imaginary values,
108 *
109 * example:
110 * REAL data [2*NTOTAL];
111 * WebRtcIsac_Fftradix ( &data[0], &data[1], NTOTAL, nPass, nSpan, 2, maxf, maxp);
112 *
113 * for temporary allocation:
114 *
115 * MAX_FACTORS >= the maximum prime factor of NPASS
116 * MAX_PERM >= the number of prime factors of NPASS.  In addition,
117 * if the square-free portion K of NPASS has two or more prime
118 * factors, then MAX_PERM >= (K-1)
119 *
120 * storage in FACTOR for a maximum of 15 prime factors of NPASS. if NPASS
121 * has more than one square-free factor, the product of the square-free
122 * factors must be <= 210 array storage for maximum prime factor of 23 the
123 * following two constants should agree with the array dimensions.
124 *
125 *----------------------------------------------------------------------*/
126#include "fft.h"
127
128#include <stdlib.h>
129#include <math.h>
130
131
132
133/* double precision routine */
134static int
135WebRtcIsac_Fftradix (double Re[], double Im[],
136                    size_t nTotal, size_t nPass, size_t nSpan, int isign,
137                    int max_factors, unsigned int max_perm,
138                    FFTstr *fftstate);
139
140
141
142#ifndef M_PI
143# define M_PI 3.14159265358979323846264338327950288
144#endif
145
146#ifndef SIN60
147# define SIN60 0.86602540378443865 /* sin(60 deg) */
148# define COS72 0.30901699437494742 /* cos(72 deg) */
149# define SIN72 0.95105651629515357 /* sin(72 deg) */
150#endif
151
152# define REAL  double
153# define FFTN  WebRtcIsac_Fftn
154# define FFTNS  "fftn"
155# define FFTRADIX WebRtcIsac_Fftradix
156# define FFTRADIXS "fftradix"
157
158
159int  WebRtcIsac_Fftns(unsigned int ndim, const int dims[],
160                     double Re[],
161                     double Im[],
162                     int iSign,
163                     double scaling,
164                     FFTstr *fftstate)
165{
166
167  size_t nSpan, nPass, nTotal;
168  unsigned int i;
169  int ret, max_factors, max_perm;
170
171  /*
172   * tally the number of elements in the data array
173   * and determine the number of dimensions
174   */
175  nTotal = 1;
176  if (ndim && dims [0])
177  {
178    for (i = 0; i < ndim; i++)
179    {
180      if (dims [i] <= 0)
181      {
182        return -1;
183      }
184      nTotal *= dims [i];
185    }
186  }
187  else
188  {
189    ndim = 0;
190    for (i = 0; dims [i]; i++)
191    {
192      if (dims [i] <= 0)
193      {
194        return -1;
195      }
196      nTotal *= dims [i];
197      ndim++;
198    }
199  }
200
201  /* determine maximum number of factors and permuations */
202#if 1
203  /*
204   * follow John Beale's example, just use the largest dimension and don't
205   * worry about excess allocation.  May be someone else will do it?
206   */
207  max_factors = max_perm = 1;
208  for (i = 0; i < ndim; i++)
209  {
210    nSpan = dims [i];
211    if ((int)nSpan > max_factors)
212    {
213      max_factors = (int)nSpan;
214    }
215    if ((int)nSpan > max_perm)
216    {
217      max_perm = (int)nSpan;
218    }
219  }
220#else
221  /* use the constants used in the original Fortran code */
222  max_factors = 23;
223  max_perm = 209;
224#endif
225  /* loop over the dimensions: */
226  nPass = 1;
227  for (i = 0; i < ndim; i++)
228  {
229    nSpan = dims [i];
230    nPass *= nSpan;
231    ret = FFTRADIX (Re, Im, nTotal, nSpan, nPass, iSign,
232                    max_factors, max_perm, fftstate);
233    /* exit, clean-up already done */
234    if (ret)
235      return ret;
236  }
237
238  /* Divide through by the normalizing constant: */
239  if (scaling && scaling != 1.0)
240  {
241    if (iSign < 0) iSign = -iSign;
242    if (scaling < 0.0)
243    {
244      scaling = (double)nTotal;
245      if (scaling < -1.0)
246        scaling = sqrt (scaling);
247    }
248    scaling = 1.0 / scaling; /* multiply is often faster */
249    for (i = 0; i < nTotal; i += iSign)
250    {
251      Re [i] *= scaling;
252      Im [i] *= scaling;
253    }
254  }
255  return 0;
256}
257
258/*
259 * singleton's mixed radix routine
260 *
261 * could move allocation out to WebRtcIsac_Fftn(), but leave it here so that it's
262 * possible to make this a standalone function
263 */
264
265static int   FFTRADIX (REAL Re[],
266                       REAL Im[],
267                       size_t nTotal,
268                       size_t nPass,
269                       size_t nSpan,
270                       int iSign,
271                       int max_factors,
272                       unsigned int max_perm,
273                       FFTstr *fftstate)
274{
275  int ii, mfactor, kspan, ispan, inc;
276  int j, jc, jf, jj, k, k1, k2, k3, k4, kk, kt, nn, ns, nt;
277
278
279  REAL radf;
280  REAL c1, c2, c3, cd, aa, aj, ak, ajm, ajp, akm, akp;
281  REAL s1, s2, s3, sd, bb, bj, bk, bjm, bjp, bkm, bkp;
282
283  REAL *Rtmp = NULL; /* temp space for real part*/
284  REAL *Itmp = NULL; /* temp space for imaginary part */
285  REAL *Cos = NULL; /* Cosine values */
286  REAL *Sin = NULL; /* Sine values */
287
288  REAL s60 = SIN60;  /* sin(60 deg) */
289  REAL c72 = COS72;  /* cos(72 deg) */
290  REAL s72 = SIN72;  /* sin(72 deg) */
291  REAL pi2 = M_PI;  /* use PI first, 2 PI later */
292
293
294  fftstate->SpaceAlloced = 0;
295  fftstate->MaxPermAlloced = 0;
296
297
298  // initialize to avoid warnings
299  k3 = c2 = c3 = s2 = s3 = 0.0;
300
301  if (nPass < 2)
302    return 0;
303
304  /*  allocate storage */
305  if (fftstate->SpaceAlloced < max_factors * sizeof (REAL))
306  {
307#ifdef SUN_BROKEN_REALLOC
308    if (!fftstate->SpaceAlloced) /* first time */
309    {
310      fftstate->SpaceAlloced = max_factors * sizeof (REAL);
311    }
312    else
313    {
314#endif
315      fftstate->SpaceAlloced = max_factors * sizeof (REAL);
316#ifdef SUN_BROKEN_REALLOC
317    }
318#endif
319  }
320  else
321  {
322    /* allow full use of alloc'd space */
323    max_factors = fftstate->SpaceAlloced / sizeof (REAL);
324  }
325  if (fftstate->MaxPermAlloced < max_perm)
326  {
327#ifdef SUN_BROKEN_REALLOC
328    if (!fftstate->MaxPermAlloced) /* first time */
329    else
330#endif
331      fftstate->MaxPermAlloced = max_perm;
332  }
333  else
334  {
335    /* allow full use of alloc'd space */
336    max_perm = fftstate->MaxPermAlloced;
337  }
338  if (fftstate->Tmp0 == NULL || fftstate->Tmp1 == NULL || fftstate->Tmp2 == NULL || fftstate->Tmp3 == NULL
339      || fftstate->Perm == NULL) {
340    return -1;
341  }
342
343  /* assign pointers */
344  Rtmp = (REAL *) fftstate->Tmp0;
345  Itmp = (REAL *) fftstate->Tmp1;
346  Cos  = (REAL *) fftstate->Tmp2;
347  Sin  = (REAL *) fftstate->Tmp3;
348
349  /*
350   * Function Body
351   */
352  inc = iSign;
353  if (iSign < 0) {
354    s72 = -s72;
355    s60 = -s60;
356    pi2 = -pi2;
357    inc = -inc;  /* absolute value */
358  }
359
360  /* adjust for strange increments */
361  nt = inc * (int)nTotal;
362  ns = inc * (int)nSpan;
363  kspan = ns;
364
365  nn = nt - inc;
366  jc = ns / (int)nPass;
367  radf = pi2 * (double) jc;
368  pi2 *= 2.0;   /* use 2 PI from here on */
369
370  ii = 0;
371  jf = 0;
372  /*  determine the factors of n */
373  mfactor = 0;
374  k = (int)nPass;
375  while (k % 16 == 0) {
376    mfactor++;
377    fftstate->factor [mfactor - 1] = 4;
378    k /= 16;
379  }
380  j = 3;
381  jj = 9;
382  do {
383    while (k % jj == 0) {
384      mfactor++;
385      fftstate->factor [mfactor - 1] = j;
386      k /= jj;
387    }
388    j += 2;
389    jj = j * j;
390  } while (jj <= k);
391  if (k <= 4) {
392    kt = mfactor;
393    fftstate->factor [mfactor] = k;
394    if (k != 1)
395      mfactor++;
396  } else {
397    if (k - (k / 4 << 2) == 0) {
398      mfactor++;
399      fftstate->factor [mfactor - 1] = 2;
400      k /= 4;
401    }
402    kt = mfactor;
403    j = 2;
404    do {
405      if (k % j == 0) {
406        mfactor++;
407        fftstate->factor [mfactor - 1] = j;
408        k /= j;
409      }
410      j = ((j + 1) / 2 << 1) + 1;
411    } while (j <= k);
412  }
413  if (kt) {
414    j = kt;
415    do {
416      mfactor++;
417      fftstate->factor [mfactor - 1] = fftstate->factor [j - 1];
418      j--;
419    } while (j);
420  }
421
422  /* test that mfactors is in range */
423  if (mfactor > NFACTOR)
424  {
425    return -1;
426  }
427
428  /* compute fourier transform */
429  for (;;) {
430    sd = radf / (double) kspan;
431    cd = sin(sd);
432    cd = 2.0 * cd * cd;
433    sd = sin(sd + sd);
434    kk = 0;
435    ii++;
436
437    switch (fftstate->factor [ii - 1]) {
438      case 2:
439        /* transform for factor of 2 (including rotation factor) */
440        kspan /= 2;
441        k1 = kspan + 2;
442        do {
443          do {
444            k2 = kk + kspan;
445            ak = Re [k2];
446            bk = Im [k2];
447            Re [k2] = Re [kk] - ak;
448            Im [k2] = Im [kk] - bk;
449            Re [kk] += ak;
450            Im [kk] += bk;
451            kk = k2 + kspan;
452          } while (kk < nn);
453          kk -= nn;
454        } while (kk < jc);
455        if (kk >= kspan)
456          goto Permute_Results_Label;  /* exit infinite loop */
457        do {
458          c1 = 1.0 - cd;
459          s1 = sd;
460          do {
461            do {
462              do {
463                k2 = kk + kspan;
464                ak = Re [kk] - Re [k2];
465                bk = Im [kk] - Im [k2];
466                Re [kk] += Re [k2];
467                Im [kk] += Im [k2];
468                Re [k2] = c1 * ak - s1 * bk;
469                Im [k2] = s1 * ak + c1 * bk;
470                kk = k2 + kspan;
471              } while (kk < (nt-1));
472              k2 = kk - nt;
473              c1 = -c1;
474              kk = k1 - k2;
475            } while (kk > k2);
476            ak = c1 - (cd * c1 + sd * s1);
477            s1 = sd * c1 - cd * s1 + s1;
478            c1 = 2.0 - (ak * ak + s1 * s1);
479            s1 *= c1;
480            c1 *= ak;
481            kk += jc;
482          } while (kk < k2);
483          k1 += inc + inc;
484          kk = (k1 - kspan + 1) / 2 + jc - 1;
485        } while (kk < (jc + jc));
486        break;
487
488      case 4:   /* transform for factor of 4 */
489        ispan = kspan;
490        kspan /= 4;
491
492        do {
493          c1 = 1.0;
494          s1 = 0.0;
495          do {
496            do {
497              k1 = kk + kspan;
498              k2 = k1 + kspan;
499              k3 = k2 + kspan;
500              akp = Re [kk] + Re [k2];
501              akm = Re [kk] - Re [k2];
502              ajp = Re [k1] + Re [k3];
503              ajm = Re [k1] - Re [k3];
504              bkp = Im [kk] + Im [k2];
505              bkm = Im [kk] - Im [k2];
506              bjp = Im [k1] + Im [k3];
507              bjm = Im [k1] - Im [k3];
508              Re [kk] = akp + ajp;
509              Im [kk] = bkp + bjp;
510              ajp = akp - ajp;
511              bjp = bkp - bjp;
512              if (iSign < 0) {
513                akp = akm + bjm;
514                bkp = bkm - ajm;
515                akm -= bjm;
516                bkm += ajm;
517              } else {
518                akp = akm - bjm;
519                bkp = bkm + ajm;
520                akm += bjm;
521                bkm -= ajm;
522              }
523              /* avoid useless multiplies */
524              if (s1 == 0.0) {
525                Re [k1] = akp;
526                Re [k2] = ajp;
527                Re [k3] = akm;
528                Im [k1] = bkp;
529                Im [k2] = bjp;
530                Im [k3] = bkm;
531              } else {
532                Re [k1] = akp * c1 - bkp * s1;
533                Re [k2] = ajp * c2 - bjp * s2;
534                Re [k3] = akm * c3 - bkm * s3;
535                Im [k1] = akp * s1 + bkp * c1;
536                Im [k2] = ajp * s2 + bjp * c2;
537                Im [k3] = akm * s3 + bkm * c3;
538              }
539              kk = k3 + kspan;
540            } while (kk < nt);
541
542            c2 = c1 - (cd * c1 + sd * s1);
543            s1 = sd * c1 - cd * s1 + s1;
544            c1 = 2.0 - (c2 * c2 + s1 * s1);
545            s1 *= c1;
546            c1 *= c2;
547            /* values of c2, c3, s2, s3 that will get used next time */
548            c2 = c1 * c1 - s1 * s1;
549            s2 = 2.0 * c1 * s1;
550            c3 = c2 * c1 - s2 * s1;
551            s3 = c2 * s1 + s2 * c1;
552            kk = kk - nt + jc;
553          } while (kk < kspan);
554          kk = kk - kspan + inc;
555        } while (kk < jc);
556        if (kspan == jc)
557          goto Permute_Results_Label;  /* exit infinite loop */
558        break;
559
560      default:
561        /*  transform for odd factors */
562#ifdef FFT_RADIX4
563        return -1;
564        break;
565#else /* FFT_RADIX4 */
566        k = fftstate->factor [ii - 1];
567        ispan = kspan;
568        kspan /= k;
569
570        switch (k) {
571          case 3: /* transform for factor of 3 (optional code) */
572            do {
573              do {
574                k1 = kk + kspan;
575                k2 = k1 + kspan;
576                ak = Re [kk];
577                bk = Im [kk];
578                aj = Re [k1] + Re [k2];
579                bj = Im [k1] + Im [k2];
580                Re [kk] = ak + aj;
581                Im [kk] = bk + bj;
582                ak -= 0.5 * aj;
583                bk -= 0.5 * bj;
584                aj = (Re [k1] - Re [k2]) * s60;
585                bj = (Im [k1] - Im [k2]) * s60;
586                Re [k1] = ak - bj;
587                Re [k2] = ak + bj;
588                Im [k1] = bk + aj;
589                Im [k2] = bk - aj;
590                kk = k2 + kspan;
591              } while (kk < (nn - 1));
592              kk -= nn;
593            } while (kk < kspan);
594            break;
595
596          case 5: /*  transform for factor of 5 (optional code) */
597            c2 = c72 * c72 - s72 * s72;
598            s2 = 2.0 * c72 * s72;
599            do {
600              do {
601                k1 = kk + kspan;
602                k2 = k1 + kspan;
603                k3 = k2 + kspan;
604                k4 = k3 + kspan;
605                akp = Re [k1] + Re [k4];
606                akm = Re [k1] - Re [k4];
607                bkp = Im [k1] + Im [k4];
608                bkm = Im [k1] - Im [k4];
609                ajp = Re [k2] + Re [k3];
610                ajm = Re [k2] - Re [k3];
611                bjp = Im [k2] + Im [k3];
612                bjm = Im [k2] - Im [k3];
613                aa = Re [kk];
614                bb = Im [kk];
615                Re [kk] = aa + akp + ajp;
616                Im [kk] = bb + bkp + bjp;
617                ak = akp * c72 + ajp * c2 + aa;
618                bk = bkp * c72 + bjp * c2 + bb;
619                aj = akm * s72 + ajm * s2;
620                bj = bkm * s72 + bjm * s2;
621                Re [k1] = ak - bj;
622                Re [k4] = ak + bj;
623                Im [k1] = bk + aj;
624                Im [k4] = bk - aj;
625                ak = akp * c2 + ajp * c72 + aa;
626                bk = bkp * c2 + bjp * c72 + bb;
627                aj = akm * s2 - ajm * s72;
628                bj = bkm * s2 - bjm * s72;
629                Re [k2] = ak - bj;
630                Re [k3] = ak + bj;
631                Im [k2] = bk + aj;
632                Im [k3] = bk - aj;
633                kk = k4 + kspan;
634              } while (kk < (nn-1));
635              kk -= nn;
636            } while (kk < kspan);
637            break;
638
639          default:
640            if (k != jf) {
641              jf = k;
642              s1 = pi2 / (double) k;
643              c1 = cos(s1);
644              s1 = sin(s1);
645              if (jf > max_factors){
646                return -1;
647              }
648              Cos [jf - 1] = 1.0;
649              Sin [jf - 1] = 0.0;
650              j = 1;
651              do {
652                Cos [j - 1] = Cos [k - 1] * c1 + Sin [k - 1] * s1;
653                Sin [j - 1] = Cos [k - 1] * s1 - Sin [k - 1] * c1;
654                k--;
655                Cos [k - 1] = Cos [j - 1];
656                Sin [k - 1] = -Sin [j - 1];
657                j++;
658              } while (j < k);
659            }
660            do {
661              do {
662                k1 = kk;
663                k2 = kk + ispan;
664                ak = aa = Re [kk];
665                bk = bb = Im [kk];
666                j = 1;
667                k1 += kspan;
668                do {
669                  k2 -= kspan;
670                  j++;
671                  Rtmp [j - 1] = Re [k1] + Re [k2];
672                  ak += Rtmp [j - 1];
673                  Itmp [j - 1] = Im [k1] + Im [k2];
674                  bk += Itmp [j - 1];
675                  j++;
676                  Rtmp [j - 1] = Re [k1] - Re [k2];
677                  Itmp [j - 1] = Im [k1] - Im [k2];
678                  k1 += kspan;
679                } while (k1 < k2);
680                Re [kk] = ak;
681                Im [kk] = bk;
682                k1 = kk;
683                k2 = kk + ispan;
684                j = 1;
685                do {
686                  k1 += kspan;
687                  k2 -= kspan;
688                  jj = j;
689                  ak = aa;
690                  bk = bb;
691                  aj = 0.0;
692                  bj = 0.0;
693                  k = 1;
694                  do {
695                    k++;
696                    ak += Rtmp [k - 1] * Cos [jj - 1];
697                    bk += Itmp [k - 1] * Cos [jj - 1];
698                    k++;
699                    aj += Rtmp [k - 1] * Sin [jj - 1];
700                    bj += Itmp [k - 1] * Sin [jj - 1];
701                    jj += j;
702                    if (jj > jf) {
703                      jj -= jf;
704                    }
705                  } while (k < jf);
706                  k = jf - j;
707                  Re [k1] = ak - bj;
708                  Im [k1] = bk + aj;
709                  Re [k2] = ak + bj;
710                  Im [k2] = bk - aj;
711                  j++;
712                } while (j < k);
713                kk += ispan;
714              } while (kk < nn);
715              kk -= nn;
716            } while (kk < kspan);
717            break;
718        }
719
720        /*  multiply by rotation factor (except for factors of 2 and 4) */
721        if (ii == mfactor)
722          goto Permute_Results_Label;  /* exit infinite loop */
723        kk = jc;
724        do {
725          c2 = 1.0 - cd;
726          s1 = sd;
727          do {
728            c1 = c2;
729            s2 = s1;
730            kk += kspan;
731            do {
732              do {
733                ak = Re [kk];
734                Re [kk] = c2 * ak - s2 * Im [kk];
735                Im [kk] = s2 * ak + c2 * Im [kk];
736                kk += ispan;
737              } while (kk < nt);
738              ak = s1 * s2;
739              s2 = s1 * c2 + c1 * s2;
740              c2 = c1 * c2 - ak;
741              kk = kk - nt + kspan;
742            } while (kk < ispan);
743            c2 = c1 - (cd * c1 + sd * s1);
744            s1 += sd * c1 - cd * s1;
745            c1 = 2.0 - (c2 * c2 + s1 * s1);
746            s1 *= c1;
747            c2 *= c1;
748            kk = kk - ispan + jc;
749          } while (kk < kspan);
750          kk = kk - kspan + jc + inc;
751        } while (kk < (jc + jc));
752        break;
753#endif /* FFT_RADIX4 */
754    }
755  }
756
757  /*  permute the results to normal order---done in two stages */
758  /*  permutation for square factors of n */
759Permute_Results_Label:
760  fftstate->Perm [0] = ns;
761  if (kt) {
762    k = kt + kt + 1;
763    if (mfactor < k)
764      k--;
765    j = 1;
766    fftstate->Perm [k] = jc;
767    do {
768      fftstate->Perm [j] = fftstate->Perm [j - 1] / fftstate->factor [j - 1];
769      fftstate->Perm [k - 1] = fftstate->Perm [k] * fftstate->factor [j - 1];
770      j++;
771      k--;
772    } while (j < k);
773    k3 = fftstate->Perm [k];
774    kspan = fftstate->Perm [1];
775    kk = jc;
776    k2 = kspan;
777    j = 1;
778    if (nPass != nTotal) {
779      /*  permutation for multivariate transform */
780   Permute_Multi_Label:
781      do {
782        do {
783          k = kk + jc;
784          do {
785            /* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */
786            ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak;
787            bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk;
788            kk += inc;
789            k2 += inc;
790          } while (kk < (k-1));
791          kk += ns - jc;
792          k2 += ns - jc;
793        } while (kk < (nt-1));
794        k2 = k2 - nt + kspan;
795        kk = kk - nt + jc;
796      } while (k2 < (ns-1));
797      do {
798        do {
799          k2 -= fftstate->Perm [j - 1];
800          j++;
801          k2 = fftstate->Perm [j] + k2;
802        } while (k2 > fftstate->Perm [j - 1]);
803        j = 1;
804        do {
805          if (kk < (k2-1))
806            goto Permute_Multi_Label;
807          kk += jc;
808          k2 += kspan;
809        } while (k2 < (ns-1));
810      } while (kk < (ns-1));
811    } else {
812      /*  permutation for single-variate transform (optional code) */
813   Permute_Single_Label:
814      do {
815        /* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */
816        ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak;
817        bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk;
818        kk += inc;
819        k2 += kspan;
820      } while (k2 < (ns-1));
821      do {
822        do {
823          k2 -= fftstate->Perm [j - 1];
824          j++;
825          k2 = fftstate->Perm [j] + k2;
826        } while (k2 >= fftstate->Perm [j - 1]);
827        j = 1;
828        do {
829          if (kk < k2)
830            goto Permute_Single_Label;
831          kk += inc;
832          k2 += kspan;
833        } while (k2 < (ns-1));
834      } while (kk < (ns-1));
835    }
836    jc = k3;
837  }
838
839  if ((kt << 1) + 1 >= mfactor)
840    return 0;
841  ispan = fftstate->Perm [kt];
842  /* permutation for square-free factors of n */
843  j = mfactor - kt;
844  fftstate->factor [j] = 1;
845  do {
846    fftstate->factor [j - 1] *= fftstate->factor [j];
847    j--;
848  } while (j != kt);
849  kt++;
850  nn = fftstate->factor [kt - 1] - 1;
851  if (nn > (int) max_perm) {
852    return -1;
853  }
854  j = jj = 0;
855  for (;;) {
856    k = kt + 1;
857    k2 = fftstate->factor [kt - 1];
858    kk = fftstate->factor [k - 1];
859    j++;
860    if (j > nn)
861      break;    /* exit infinite loop */
862    jj += kk;
863    while (jj >= k2) {
864      jj -= k2;
865      k2 = kk;
866      k++;
867      kk = fftstate->factor [k - 1];
868      jj += kk;
869    }
870    fftstate->Perm [j - 1] = jj;
871  }
872  /*  determine the permutation cycles of length greater than 1 */
873  j = 0;
874  for (;;) {
875    do {
876      j++;
877      kk = fftstate->Perm [j - 1];
878    } while (kk < 0);
879    if (kk != j) {
880      do {
881        k = kk;
882        kk = fftstate->Perm [k - 1];
883        fftstate->Perm [k - 1] = -kk;
884      } while (kk != j);
885      k3 = kk;
886    } else {
887      fftstate->Perm [j - 1] = -j;
888      if (j == nn)
889        break;  /* exit infinite loop */
890    }
891  }
892  max_factors *= inc;
893  /*  reorder a and b, following the permutation cycles */
894  for (;;) {
895    j = k3 + 1;
896    nt -= ispan;
897    ii = nt - inc + 1;
898    if (nt < 0)
899      break;   /* exit infinite loop */
900    do {
901      do {
902        j--;
903      } while (fftstate->Perm [j - 1] < 0);
904      jj = jc;
905      do {
906        kspan = jj;
907        if (jj > max_factors) {
908          kspan = max_factors;
909        }
910        jj -= kspan;
911        k = fftstate->Perm [j - 1];
912        kk = jc * k + ii + jj;
913        k1 = kk + kspan - 1;
914        k2 = 0;
915        do {
916          k2++;
917          Rtmp [k2 - 1] = Re [k1];
918          Itmp [k2 - 1] = Im [k1];
919          k1 -= inc;
920        } while (k1 != (kk-1));
921        do {
922          k1 = kk + kspan - 1;
923          k2 = k1 - jc * (k + fftstate->Perm [k - 1]);
924          k = -fftstate->Perm [k - 1];
925          do {
926            Re [k1] = Re [k2];
927            Im [k1] = Im [k2];
928            k1 -= inc;
929            k2 -= inc;
930          } while (k1 != (kk-1));
931          kk = k2 + 1;
932        } while (k != j);
933        k1 = kk + kspan - 1;
934        k2 = 0;
935        do {
936          k2++;
937          Re [k1] = Rtmp [k2 - 1];
938          Im [k1] = Itmp [k2 - 1];
939          k1 -= inc;
940        } while (k1 != (kk-1));
941      } while (jj);
942    } while (j != 1);
943  }
944  return 0;   /* exit point here */
945}
946/* ---------------------- end-of-file (c source) ---------------------- */
947
948