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