|  | /* | 
|  | * Copyright(c)1995,97 Mark Olesen <olesen@me.QueensU.CA> | 
|  | *    Queen's Univ at Kingston (Canada) | 
|  | * | 
|  | * Permission to use, copy, modify, and distribute this software for | 
|  | * any purpose without fee is hereby granted, provided that this | 
|  | * entire notice is included in all copies of any software which is | 
|  | * or includes a copy or modification of this software and in all | 
|  | * copies of the supporting documentation for such software. | 
|  | * | 
|  | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR | 
|  | * IMPLIED WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR QUEEN'S | 
|  | * UNIVERSITY AT KINGSTON MAKES ANY REPRESENTATION OR WARRANTY OF ANY | 
|  | * KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS | 
|  | * FITNESS FOR ANY PARTICULAR PURPOSE. | 
|  | * | 
|  | * All of which is to say that you can do what you like with this | 
|  | * source code provided you don't try to sell it as your own and you | 
|  | * include an unaltered copy of this message (including the | 
|  | * copyright). | 
|  | * | 
|  | * It is also implicitly understood that bug fixes and improvements | 
|  | * should make their way back to the general Internet community so | 
|  | * that everyone benefits. | 
|  | * | 
|  | * Changes: | 
|  | *   Trivial type modifications by the WebRTC authors. | 
|  | */ | 
|  |  | 
|  |  | 
|  | /* | 
|  | * File: | 
|  | * WebRtcIsac_Fftn.c | 
|  | * | 
|  | * Public: | 
|  | * WebRtcIsac_Fftn / fftnf (); | 
|  | * | 
|  | * Private: | 
|  | * WebRtcIsac_Fftradix / fftradixf (); | 
|  | * | 
|  | * Descript: | 
|  | * multivariate complex Fourier transform, computed in place | 
|  | * using mixed-radix Fast Fourier Transform algorithm. | 
|  | * | 
|  | * Fortran code by: | 
|  | * RC Singleton, Stanford Research Institute, Sept. 1968 | 
|  | * | 
|  | * translated by f2c (version 19950721). | 
|  | * | 
|  | * int WebRtcIsac_Fftn (int ndim, const int dims[], REAL Re[], REAL Im[], | 
|  | *     int iSign, double scaling); | 
|  | * | 
|  | * NDIM = the total number dimensions | 
|  | * DIMS = a vector of array sizes | 
|  | * if NDIM is zero then DIMS must be zero-terminated | 
|  | * | 
|  | * RE and IM hold the real and imaginary components of the data, and return | 
|  | * the resulting real and imaginary Fourier coefficients.  Multidimensional | 
|  | * data *must* be allocated contiguously.  There is no limit on the number | 
|  | * of dimensions. | 
|  | * | 
|  | * ISIGN = the sign of the complex exponential (ie, forward or inverse FFT) | 
|  | * the magnitude of ISIGN (normally 1) is used to determine the | 
|  | * correct indexing increment (see below). | 
|  | * | 
|  | * SCALING = normalizing constant by which the final result is *divided* | 
|  | * if SCALING == -1, normalize by total dimension of the transform | 
|  | * if SCALING <  -1, normalize by the square-root of the total dimension | 
|  | * | 
|  | * example: | 
|  | * tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3] | 
|  | * | 
|  | * int dims[3] = {n1,n2,n3} | 
|  | * WebRtcIsac_Fftn (3, dims, Re, Im, 1, scaling); | 
|  | * | 
|  | *-----------------------------------------------------------------------* | 
|  | * int WebRtcIsac_Fftradix (REAL Re[], REAL Im[], size_t nTotal, size_t nPass, | 
|  | *   size_t nSpan, int iSign, size_t max_factors, | 
|  | *   size_t max_perm); | 
|  | * | 
|  | * RE, IM - see above documentation | 
|  | * | 
|  | * Although there is no limit on the number of dimensions, WebRtcIsac_Fftradix() must | 
|  | * be called once for each dimension, but the calls may be in any order. | 
|  | * | 
|  | * NTOTAL = the total number of complex data values | 
|  | * NPASS  = the dimension of the current variable | 
|  | * NSPAN/NPASS = the spacing of consecutive data values while indexing the | 
|  | * current variable | 
|  | * ISIGN - see above documentation | 
|  | * | 
|  | * example: | 
|  | * tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3] | 
|  | * | 
|  | * WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n1,       n1, 1, maxf, maxp); | 
|  | * WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n2,    n1*n2, 1, maxf, maxp); | 
|  | * WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n3, n1*n2*n3, 1, maxf, maxp); | 
|  | * | 
|  | * single-variate transform, | 
|  | *    NTOTAL = N = NSPAN = (number of complex data values), | 
|  | * | 
|  | * WebRtcIsac_Fftradix (Re, Im, n, n, n, 1, maxf, maxp); | 
|  | * | 
|  | * The data can also be stored in a single array with alternating real and | 
|  | * imaginary parts, the magnitude of ISIGN is changed to 2 to give correct | 
|  | * indexing increment, and data [0] and data [1] used to pass the initial | 
|  | * addresses for the sequences of real and imaginary values, | 
|  | * | 
|  | * example: | 
|  | * REAL data [2*NTOTAL]; | 
|  | * WebRtcIsac_Fftradix ( &data[0], &data[1], NTOTAL, nPass, nSpan, 2, maxf, maxp); | 
|  | * | 
|  | * for temporary allocation: | 
|  | * | 
|  | * MAX_FACTORS >= the maximum prime factor of NPASS | 
|  | * MAX_PERM >= the number of prime factors of NPASS.  In addition, | 
|  | * if the square-free portion K of NPASS has two or more prime | 
|  | * factors, then MAX_PERM >= (K-1) | 
|  | * | 
|  | * storage in FACTOR for a maximum of 15 prime factors of NPASS. if NPASS | 
|  | * has more than one square-free factor, the product of the square-free | 
|  | * factors must be <= 210 array storage for maximum prime factor of 23 the | 
|  | * following two constants should agree with the array dimensions. | 
|  | * | 
|  | *----------------------------------------------------------------------*/ | 
|  |  | 
|  | #include <stdlib.h> | 
|  | #include <math.h> | 
|  |  | 
|  | #include "modules/third_party/fft/fft.h" | 
|  |  | 
|  | /* double precision routine */ | 
|  | static int | 
|  | WebRtcIsac_Fftradix (double Re[], double Im[], | 
|  | size_t nTotal, size_t nPass, size_t nSpan, int isign, | 
|  | int max_factors, unsigned int max_perm, | 
|  | FFTstr *fftstate); | 
|  |  | 
|  |  | 
|  |  | 
|  | #ifndef M_PI | 
|  | # define M_PI 3.14159265358979323846264338327950288 | 
|  | #endif | 
|  |  | 
|  | #ifndef SIN60 | 
|  | # define SIN60 0.86602540378443865 /* sin(60 deg) */ | 
|  | # define COS72 0.30901699437494742 /* cos(72 deg) */ | 
|  | # define SIN72 0.95105651629515357 /* sin(72 deg) */ | 
|  | #endif | 
|  |  | 
|  | # define REAL  double | 
|  | # define FFTN  WebRtcIsac_Fftn | 
|  | # define FFTNS  "fftn" | 
|  | # define FFTRADIX WebRtcIsac_Fftradix | 
|  | # define FFTRADIXS "fftradix" | 
|  |  | 
|  |  | 
|  | int  WebRtcIsac_Fftns(unsigned int ndim, const int dims[], | 
|  | double Re[], | 
|  | double Im[], | 
|  | int iSign, | 
|  | double scaling, | 
|  | FFTstr *fftstate) | 
|  | { | 
|  |  | 
|  | size_t nSpan, nPass, nTotal; | 
|  | unsigned int i; | 
|  | int ret, max_factors, max_perm; | 
|  |  | 
|  | /* | 
|  | * tally the number of elements in the data array | 
|  | * and determine the number of dimensions | 
|  | */ | 
|  | nTotal = 1; | 
|  | if (ndim && dims [0]) | 
|  | { | 
|  | for (i = 0; i < ndim; i++) | 
|  | { | 
|  | if (dims [i] <= 0) | 
|  | { | 
|  | return -1; | 
|  | } | 
|  | nTotal *= dims [i]; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | ndim = 0; | 
|  | for (i = 0; dims [i]; i++) | 
|  | { | 
|  | if (dims [i] <= 0) | 
|  | { | 
|  | return -1; | 
|  | } | 
|  | nTotal *= dims [i]; | 
|  | ndim++; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* determine maximum number of factors and permuations */ | 
|  | #if 1 | 
|  | /* | 
|  | * follow John Beale's example, just use the largest dimension and don't | 
|  | * worry about excess allocation.  May be someone else will do it? | 
|  | */ | 
|  | max_factors = max_perm = 1; | 
|  | for (i = 0; i < ndim; i++) | 
|  | { | 
|  | nSpan = dims [i]; | 
|  | if ((int)nSpan > max_factors) | 
|  | { | 
|  | max_factors = (int)nSpan; | 
|  | } | 
|  | if ((int)nSpan > max_perm) | 
|  | { | 
|  | max_perm = (int)nSpan; | 
|  | } | 
|  | } | 
|  | #else | 
|  | /* use the constants used in the original Fortran code */ | 
|  | max_factors = 23; | 
|  | max_perm = 209; | 
|  | #endif | 
|  | /* loop over the dimensions: */ | 
|  | nPass = 1; | 
|  | for (i = 0; i < ndim; i++) | 
|  | { | 
|  | nSpan = dims [i]; | 
|  | nPass *= nSpan; | 
|  | ret = FFTRADIX (Re, Im, nTotal, nSpan, nPass, iSign, | 
|  | max_factors, max_perm, fftstate); | 
|  | /* exit, clean-up already done */ | 
|  | if (ret) | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* Divide through by the normalizing constant: */ | 
|  | if (scaling && scaling != 1.0) | 
|  | { | 
|  | if (iSign < 0) iSign = -iSign; | 
|  | if (scaling < 0.0) | 
|  | { | 
|  | scaling = (double)nTotal; | 
|  | if (scaling < -1.0) | 
|  | scaling = sqrt (scaling); | 
|  | } | 
|  | scaling = 1.0 / scaling; /* multiply is often faster */ | 
|  | for (i = 0; i < nTotal; i += iSign) | 
|  | { | 
|  | Re [i] *= scaling; | 
|  | Im [i] *= scaling; | 
|  | } | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * singleton's mixed radix routine | 
|  | * | 
|  | * could move allocation out to WebRtcIsac_Fftn(), but leave it here so that it's | 
|  | * possible to make this a standalone function | 
|  | */ | 
|  |  | 
|  | static int   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) | 
|  | { | 
|  | int ii, mfactor, kspan, ispan, inc; | 
|  | int j, jc, jf, jj, k, k1, k2, k3, k4, kk, kt, nn, ns, nt; | 
|  |  | 
|  |  | 
|  | REAL radf; | 
|  | REAL c1, c2, c3, cd, aa, aj, ak, ajm, ajp, akm, akp; | 
|  | REAL s1, s2, s3, sd, bb, bj, bk, bjm, bjp, bkm, bkp; | 
|  |  | 
|  | REAL *Rtmp = NULL; /* temp space for real part*/ | 
|  | REAL *Itmp = NULL; /* temp space for imaginary part */ | 
|  | REAL *Cos = NULL; /* Cosine values */ | 
|  | REAL *Sin = NULL; /* Sine values */ | 
|  |  | 
|  | REAL s60 = SIN60;  /* sin(60 deg) */ | 
|  | REAL c72 = COS72;  /* cos(72 deg) */ | 
|  | REAL s72 = SIN72;  /* sin(72 deg) */ | 
|  | REAL pi2 = M_PI;  /* use PI first, 2 PI later */ | 
|  |  | 
|  |  | 
|  | fftstate->SpaceAlloced = 0; | 
|  | fftstate->MaxPermAlloced = 0; | 
|  |  | 
|  |  | 
|  | // initialize to avoid warnings | 
|  | k3 = c2 = c3 = s2 = s3 = 0.0; | 
|  |  | 
|  | if (nPass < 2) | 
|  | return 0; | 
|  |  | 
|  | /*  allocate storage */ | 
|  | if (fftstate->SpaceAlloced < max_factors * sizeof (REAL)) | 
|  | { | 
|  | #ifdef SUN_BROKEN_REALLOC | 
|  | if (!fftstate->SpaceAlloced) /* first time */ | 
|  | { | 
|  | fftstate->SpaceAlloced = max_factors * sizeof (REAL); | 
|  | } | 
|  | else | 
|  | { | 
|  | #endif | 
|  | fftstate->SpaceAlloced = max_factors * sizeof (REAL); | 
|  | #ifdef SUN_BROKEN_REALLOC | 
|  | } | 
|  | #endif | 
|  | } | 
|  | else | 
|  | { | 
|  | /* allow full use of alloc'd space */ | 
|  | max_factors = fftstate->SpaceAlloced / sizeof (REAL); | 
|  | } | 
|  | if (fftstate->MaxPermAlloced < max_perm) | 
|  | { | 
|  | #ifdef SUN_BROKEN_REALLOC | 
|  | if (!fftstate->MaxPermAlloced) /* first time */ | 
|  | else | 
|  | #endif | 
|  | fftstate->MaxPermAlloced = max_perm; | 
|  | } | 
|  | else | 
|  | { | 
|  | /* allow full use of alloc'd space */ | 
|  | max_perm = fftstate->MaxPermAlloced; | 
|  | } | 
|  |  | 
|  | /* assign pointers */ | 
|  | Rtmp = (REAL *) fftstate->Tmp0; | 
|  | Itmp = (REAL *) fftstate->Tmp1; | 
|  | Cos  = (REAL *) fftstate->Tmp2; | 
|  | Sin  = (REAL *) fftstate->Tmp3; | 
|  |  | 
|  | /* | 
|  | * Function Body | 
|  | */ | 
|  | inc = iSign; | 
|  | if (iSign < 0) { | 
|  | s72 = -s72; | 
|  | s60 = -s60; | 
|  | pi2 = -pi2; | 
|  | inc = -inc;  /* absolute value */ | 
|  | } | 
|  |  | 
|  | /* adjust for strange increments */ | 
|  | nt = inc * (int)nTotal; | 
|  | ns = inc * (int)nSpan; | 
|  | kspan = ns; | 
|  |  | 
|  | nn = nt - inc; | 
|  | jc = ns / (int)nPass; | 
|  | radf = pi2 * (double) jc; | 
|  | pi2 *= 2.0;   /* use 2 PI from here on */ | 
|  |  | 
|  | ii = 0; | 
|  | jf = 0; | 
|  | /*  determine the factors of n */ | 
|  | mfactor = 0; | 
|  | k = (int)nPass; | 
|  | while (k % 16 == 0) { | 
|  | mfactor++; | 
|  | fftstate->factor [mfactor - 1] = 4; | 
|  | k /= 16; | 
|  | } | 
|  | j = 3; | 
|  | jj = 9; | 
|  | do { | 
|  | while (k % jj == 0) { | 
|  | mfactor++; | 
|  | fftstate->factor [mfactor - 1] = j; | 
|  | k /= jj; | 
|  | } | 
|  | j += 2; | 
|  | jj = j * j; | 
|  | } while (jj <= k); | 
|  | if (k <= 4) { | 
|  | kt = mfactor; | 
|  | fftstate->factor [mfactor] = k; | 
|  | if (k != 1) | 
|  | mfactor++; | 
|  | } else { | 
|  | if (k - (k / 4 << 2) == 0) { | 
|  | mfactor++; | 
|  | fftstate->factor [mfactor - 1] = 2; | 
|  | k /= 4; | 
|  | } | 
|  | kt = mfactor; | 
|  | j = 2; | 
|  | do { | 
|  | if (k % j == 0) { | 
|  | mfactor++; | 
|  | fftstate->factor [mfactor - 1] = j; | 
|  | k /= j; | 
|  | } | 
|  | j = ((j + 1) / 2 << 1) + 1; | 
|  | } while (j <= k); | 
|  | } | 
|  | if (kt) { | 
|  | j = kt; | 
|  | do { | 
|  | mfactor++; | 
|  | fftstate->factor [mfactor - 1] = fftstate->factor [j - 1]; | 
|  | j--; | 
|  | } while (j); | 
|  | } | 
|  |  | 
|  | /* test that mfactors is in range */ | 
|  | if (mfactor > FFT_NFACTOR) | 
|  | { | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* compute fourier transform */ | 
|  | for (;;) { | 
|  | sd = radf / (double) kspan; | 
|  | cd = sin(sd); | 
|  | cd = 2.0 * cd * cd; | 
|  | sd = sin(sd + sd); | 
|  | kk = 0; | 
|  | ii++; | 
|  |  | 
|  | switch (fftstate->factor [ii - 1]) { | 
|  | case 2: | 
|  | /* transform for factor of 2 (including rotation factor) */ | 
|  | kspan /= 2; | 
|  | k1 = kspan + 2; | 
|  | do { | 
|  | do { | 
|  | k2 = kk + kspan; | 
|  | ak = Re [k2]; | 
|  | bk = Im [k2]; | 
|  | Re [k2] = Re [kk] - ak; | 
|  | Im [k2] = Im [kk] - bk; | 
|  | Re [kk] += ak; | 
|  | Im [kk] += bk; | 
|  | kk = k2 + kspan; | 
|  | } while (kk < nn); | 
|  | kk -= nn; | 
|  | } while (kk < jc); | 
|  | if (kk >= kspan) | 
|  | goto Permute_Results_Label;  /* exit infinite loop */ | 
|  | do { | 
|  | c1 = 1.0 - cd; | 
|  | s1 = sd; | 
|  | do { | 
|  | do { | 
|  | do { | 
|  | k2 = kk + kspan; | 
|  | ak = Re [kk] - Re [k2]; | 
|  | bk = Im [kk] - Im [k2]; | 
|  | Re [kk] += Re [k2]; | 
|  | Im [kk] += Im [k2]; | 
|  | Re [k2] = c1 * ak - s1 * bk; | 
|  | Im [k2] = s1 * ak + c1 * bk; | 
|  | kk = k2 + kspan; | 
|  | } while (kk < (nt-1)); | 
|  | k2 = kk - nt; | 
|  | c1 = -c1; | 
|  | kk = k1 - k2; | 
|  | } while (kk > k2); | 
|  | ak = c1 - (cd * c1 + sd * s1); | 
|  | s1 = sd * c1 - cd * s1 + s1; | 
|  | c1 = 2.0 - (ak * ak + s1 * s1); | 
|  | s1 *= c1; | 
|  | c1 *= ak; | 
|  | kk += jc; | 
|  | } while (kk < k2); | 
|  | k1 += inc + inc; | 
|  | kk = (k1 - kspan + 1) / 2 + jc - 1; | 
|  | } while (kk < (jc + jc)); | 
|  | break; | 
|  |  | 
|  | case 4:   /* transform for factor of 4 */ | 
|  | ispan = kspan; | 
|  | kspan /= 4; | 
|  |  | 
|  | do { | 
|  | c1 = 1.0; | 
|  | s1 = 0.0; | 
|  | do { | 
|  | do { | 
|  | k1 = kk + kspan; | 
|  | k2 = k1 + kspan; | 
|  | k3 = k2 + kspan; | 
|  | akp = Re [kk] + Re [k2]; | 
|  | akm = Re [kk] - Re [k2]; | 
|  | ajp = Re [k1] + Re [k3]; | 
|  | ajm = Re [k1] - Re [k3]; | 
|  | bkp = Im [kk] + Im [k2]; | 
|  | bkm = Im [kk] - Im [k2]; | 
|  | bjp = Im [k1] + Im [k3]; | 
|  | bjm = Im [k1] - Im [k3]; | 
|  | Re [kk] = akp + ajp; | 
|  | Im [kk] = bkp + bjp; | 
|  | ajp = akp - ajp; | 
|  | bjp = bkp - bjp; | 
|  | if (iSign < 0) { | 
|  | akp = akm + bjm; | 
|  | bkp = bkm - ajm; | 
|  | akm -= bjm; | 
|  | bkm += ajm; | 
|  | } else { | 
|  | akp = akm - bjm; | 
|  | bkp = bkm + ajm; | 
|  | akm += bjm; | 
|  | bkm -= ajm; | 
|  | } | 
|  | /* avoid useless multiplies */ | 
|  | if (s1 == 0.0) { | 
|  | Re [k1] = akp; | 
|  | Re [k2] = ajp; | 
|  | Re [k3] = akm; | 
|  | Im [k1] = bkp; | 
|  | Im [k2] = bjp; | 
|  | Im [k3] = bkm; | 
|  | } else { | 
|  | Re [k1] = akp * c1 - bkp * s1; | 
|  | Re [k2] = ajp * c2 - bjp * s2; | 
|  | Re [k3] = akm * c3 - bkm * s3; | 
|  | Im [k1] = akp * s1 + bkp * c1; | 
|  | Im [k2] = ajp * s2 + bjp * c2; | 
|  | Im [k3] = akm * s3 + bkm * c3; | 
|  | } | 
|  | kk = k3 + kspan; | 
|  | } while (kk < nt); | 
|  |  | 
|  | c2 = c1 - (cd * c1 + sd * s1); | 
|  | s1 = sd * c1 - cd * s1 + s1; | 
|  | c1 = 2.0 - (c2 * c2 + s1 * s1); | 
|  | s1 *= c1; | 
|  | c1 *= c2; | 
|  | /* values of c2, c3, s2, s3 that will get used next time */ | 
|  | c2 = c1 * c1 - s1 * s1; | 
|  | s2 = 2.0 * c1 * s1; | 
|  | c3 = c2 * c1 - s2 * s1; | 
|  | s3 = c2 * s1 + s2 * c1; | 
|  | kk = kk - nt + jc; | 
|  | } while (kk < kspan); | 
|  | kk = kk - kspan + inc; | 
|  | } while (kk < jc); | 
|  | if (kspan == jc) | 
|  | goto Permute_Results_Label;  /* exit infinite loop */ | 
|  | break; | 
|  |  | 
|  | default: | 
|  | /*  transform for odd factors */ | 
|  | #ifdef FFT_RADIX4 | 
|  | return -1; | 
|  | break; | 
|  | #else /* FFT_RADIX4 */ | 
|  | k = fftstate->factor [ii - 1]; | 
|  | ispan = kspan; | 
|  | kspan /= k; | 
|  |  | 
|  | switch (k) { | 
|  | case 3: /* transform for factor of 3 (optional code) */ | 
|  | do { | 
|  | do { | 
|  | k1 = kk + kspan; | 
|  | k2 = k1 + kspan; | 
|  | ak = Re [kk]; | 
|  | bk = Im [kk]; | 
|  | aj = Re [k1] + Re [k2]; | 
|  | bj = Im [k1] + Im [k2]; | 
|  | Re [kk] = ak + aj; | 
|  | Im [kk] = bk + bj; | 
|  | ak -= 0.5 * aj; | 
|  | bk -= 0.5 * bj; | 
|  | aj = (Re [k1] - Re [k2]) * s60; | 
|  | bj = (Im [k1] - Im [k2]) * s60; | 
|  | Re [k1] = ak - bj; | 
|  | Re [k2] = ak + bj; | 
|  | Im [k1] = bk + aj; | 
|  | Im [k2] = bk - aj; | 
|  | kk = k2 + kspan; | 
|  | } while (kk < (nn - 1)); | 
|  | kk -= nn; | 
|  | } while (kk < kspan); | 
|  | break; | 
|  |  | 
|  | case 5: /*  transform for factor of 5 (optional code) */ | 
|  | c2 = c72 * c72 - s72 * s72; | 
|  | s2 = 2.0 * c72 * s72; | 
|  | do { | 
|  | do { | 
|  | k1 = kk + kspan; | 
|  | k2 = k1 + kspan; | 
|  | k3 = k2 + kspan; | 
|  | k4 = k3 + kspan; | 
|  | akp = Re [k1] + Re [k4]; | 
|  | akm = Re [k1] - Re [k4]; | 
|  | bkp = Im [k1] + Im [k4]; | 
|  | bkm = Im [k1] - Im [k4]; | 
|  | ajp = Re [k2] + Re [k3]; | 
|  | ajm = Re [k2] - Re [k3]; | 
|  | bjp = Im [k2] + Im [k3]; | 
|  | bjm = Im [k2] - Im [k3]; | 
|  | aa = Re [kk]; | 
|  | bb = Im [kk]; | 
|  | Re [kk] = aa + akp + ajp; | 
|  | Im [kk] = bb + bkp + bjp; | 
|  | ak = akp * c72 + ajp * c2 + aa; | 
|  | bk = bkp * c72 + bjp * c2 + bb; | 
|  | aj = akm * s72 + ajm * s2; | 
|  | bj = bkm * s72 + bjm * s2; | 
|  | Re [k1] = ak - bj; | 
|  | Re [k4] = ak + bj; | 
|  | Im [k1] = bk + aj; | 
|  | Im [k4] = bk - aj; | 
|  | ak = akp * c2 + ajp * c72 + aa; | 
|  | bk = bkp * c2 + bjp * c72 + bb; | 
|  | aj = akm * s2 - ajm * s72; | 
|  | bj = bkm * s2 - bjm * s72; | 
|  | Re [k2] = ak - bj; | 
|  | Re [k3] = ak + bj; | 
|  | Im [k2] = bk + aj; | 
|  | Im [k3] = bk - aj; | 
|  | kk = k4 + kspan; | 
|  | } while (kk < (nn-1)); | 
|  | kk -= nn; | 
|  | } while (kk < kspan); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | if (k != jf) { | 
|  | jf = k; | 
|  | s1 = pi2 / (double) k; | 
|  | c1 = cos(s1); | 
|  | s1 = sin(s1); | 
|  | if (jf > max_factors){ | 
|  | return -1; | 
|  | } | 
|  | Cos [jf - 1] = 1.0; | 
|  | Sin [jf - 1] = 0.0; | 
|  | j = 1; | 
|  | do { | 
|  | Cos [j - 1] = Cos [k - 1] * c1 + Sin [k - 1] * s1; | 
|  | Sin [j - 1] = Cos [k - 1] * s1 - Sin [k - 1] * c1; | 
|  | k--; | 
|  | Cos [k - 1] = Cos [j - 1]; | 
|  | Sin [k - 1] = -Sin [j - 1]; | 
|  | j++; | 
|  | } while (j < k); | 
|  | } | 
|  | do { | 
|  | do { | 
|  | k1 = kk; | 
|  | k2 = kk + ispan; | 
|  | ak = aa = Re [kk]; | 
|  | bk = bb = Im [kk]; | 
|  | j = 1; | 
|  | k1 += kspan; | 
|  | do { | 
|  | k2 -= kspan; | 
|  | j++; | 
|  | Rtmp [j - 1] = Re [k1] + Re [k2]; | 
|  | ak += Rtmp [j - 1]; | 
|  | Itmp [j - 1] = Im [k1] + Im [k2]; | 
|  | bk += Itmp [j - 1]; | 
|  | j++; | 
|  | Rtmp [j - 1] = Re [k1] - Re [k2]; | 
|  | Itmp [j - 1] = Im [k1] - Im [k2]; | 
|  | k1 += kspan; | 
|  | } while (k1 < k2); | 
|  | Re [kk] = ak; | 
|  | Im [kk] = bk; | 
|  | k1 = kk; | 
|  | k2 = kk + ispan; | 
|  | j = 1; | 
|  | do { | 
|  | k1 += kspan; | 
|  | k2 -= kspan; | 
|  | jj = j; | 
|  | ak = aa; | 
|  | bk = bb; | 
|  | aj = 0.0; | 
|  | bj = 0.0; | 
|  | k = 1; | 
|  | do { | 
|  | k++; | 
|  | ak += Rtmp [k - 1] * Cos [jj - 1]; | 
|  | bk += Itmp [k - 1] * Cos [jj - 1]; | 
|  | k++; | 
|  | aj += Rtmp [k - 1] * Sin [jj - 1]; | 
|  | bj += Itmp [k - 1] * Sin [jj - 1]; | 
|  | jj += j; | 
|  | if (jj > jf) { | 
|  | jj -= jf; | 
|  | } | 
|  | } while (k < jf); | 
|  | k = jf - j; | 
|  | Re [k1] = ak - bj; | 
|  | Im [k1] = bk + aj; | 
|  | Re [k2] = ak + bj; | 
|  | Im [k2] = bk - aj; | 
|  | j++; | 
|  | } while (j < k); | 
|  | kk += ispan; | 
|  | } while (kk < nn); | 
|  | kk -= nn; | 
|  | } while (kk < kspan); | 
|  | break; | 
|  | } | 
|  |  | 
|  | /*  multiply by rotation factor (except for factors of 2 and 4) */ | 
|  | if (ii == mfactor) | 
|  | goto Permute_Results_Label;  /* exit infinite loop */ | 
|  | kk = jc; | 
|  | do { | 
|  | c2 = 1.0 - cd; | 
|  | s1 = sd; | 
|  | do { | 
|  | c1 = c2; | 
|  | s2 = s1; | 
|  | kk += kspan; | 
|  | do { | 
|  | do { | 
|  | ak = Re [kk]; | 
|  | Re [kk] = c2 * ak - s2 * Im [kk]; | 
|  | Im [kk] = s2 * ak + c2 * Im [kk]; | 
|  | kk += ispan; | 
|  | } while (kk < nt); | 
|  | ak = s1 * s2; | 
|  | s2 = s1 * c2 + c1 * s2; | 
|  | c2 = c1 * c2 - ak; | 
|  | kk = kk - nt + kspan; | 
|  | } while (kk < ispan); | 
|  | c2 = c1 - (cd * c1 + sd * s1); | 
|  | s1 += sd * c1 - cd * s1; | 
|  | c1 = 2.0 - (c2 * c2 + s1 * s1); | 
|  | s1 *= c1; | 
|  | c2 *= c1; | 
|  | kk = kk - ispan + jc; | 
|  | } while (kk < kspan); | 
|  | kk = kk - kspan + jc + inc; | 
|  | } while (kk < (jc + jc)); | 
|  | break; | 
|  | #endif /* FFT_RADIX4 */ | 
|  | } | 
|  | } | 
|  |  | 
|  | /*  permute the results to normal order---done in two stages */ | 
|  | /*  permutation for square factors of n */ | 
|  | Permute_Results_Label: | 
|  | fftstate->Perm [0] = ns; | 
|  | if (kt) { | 
|  | k = kt + kt + 1; | 
|  | if (mfactor < k) | 
|  | k--; | 
|  | j = 1; | 
|  | fftstate->Perm [k] = jc; | 
|  | do { | 
|  | fftstate->Perm [j] = fftstate->Perm [j - 1] / fftstate->factor [j - 1]; | 
|  | fftstate->Perm [k - 1] = fftstate->Perm [k] * fftstate->factor [j - 1]; | 
|  | j++; | 
|  | k--; | 
|  | } while (j < k); | 
|  | k3 = fftstate->Perm [k]; | 
|  | kspan = fftstate->Perm [1]; | 
|  | kk = jc; | 
|  | k2 = kspan; | 
|  | j = 1; | 
|  | if (nPass != nTotal) { | 
|  | /*  permutation for multivariate transform */ | 
|  | Permute_Multi_Label: | 
|  | do { | 
|  | do { | 
|  | k = kk + jc; | 
|  | do { | 
|  | /* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */ | 
|  | ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak; | 
|  | bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk; | 
|  | kk += inc; | 
|  | k2 += inc; | 
|  | } while (kk < (k-1)); | 
|  | kk += ns - jc; | 
|  | k2 += ns - jc; | 
|  | } while (kk < (nt-1)); | 
|  | k2 = k2 - nt + kspan; | 
|  | kk = kk - nt + jc; | 
|  | } while (k2 < (ns-1)); | 
|  | do { | 
|  | do { | 
|  | k2 -= fftstate->Perm [j - 1]; | 
|  | j++; | 
|  | k2 = fftstate->Perm [j] + k2; | 
|  | } while (k2 > fftstate->Perm [j - 1]); | 
|  | j = 1; | 
|  | do { | 
|  | if (kk < (k2-1)) | 
|  | goto Permute_Multi_Label; | 
|  | kk += jc; | 
|  | k2 += kspan; | 
|  | } while (k2 < (ns-1)); | 
|  | } while (kk < (ns-1)); | 
|  | } else { | 
|  | /*  permutation for single-variate transform (optional code) */ | 
|  | Permute_Single_Label: | 
|  | do { | 
|  | /* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */ | 
|  | ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak; | 
|  | bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk; | 
|  | kk += inc; | 
|  | k2 += kspan; | 
|  | } while (k2 < (ns-1)); | 
|  | do { | 
|  | do { | 
|  | k2 -= fftstate->Perm [j - 1]; | 
|  | j++; | 
|  | k2 = fftstate->Perm [j] + k2; | 
|  | } while (k2 >= fftstate->Perm [j - 1]); | 
|  | j = 1; | 
|  | do { | 
|  | if (kk < k2) | 
|  | goto Permute_Single_Label; | 
|  | kk += inc; | 
|  | k2 += kspan; | 
|  | } while (k2 < (ns-1)); | 
|  | } while (kk < (ns-1)); | 
|  | } | 
|  | jc = k3; | 
|  | } | 
|  |  | 
|  | if ((kt << 1) + 1 >= mfactor) | 
|  | return 0; | 
|  | ispan = fftstate->Perm [kt]; | 
|  | /* permutation for square-free factors of n */ | 
|  | j = mfactor - kt; | 
|  | fftstate->factor [j] = 1; | 
|  | do { | 
|  | fftstate->factor [j - 1] *= fftstate->factor [j]; | 
|  | j--; | 
|  | } while (j != kt); | 
|  | kt++; | 
|  | nn = fftstate->factor [kt - 1] - 1; | 
|  | if (nn > (int) max_perm) { | 
|  | return -1; | 
|  | } | 
|  | j = jj = 0; | 
|  | for (;;) { | 
|  | k = kt + 1; | 
|  | k2 = fftstate->factor [kt - 1]; | 
|  | kk = fftstate->factor [k - 1]; | 
|  | j++; | 
|  | if (j > nn) | 
|  | break;    /* exit infinite loop */ | 
|  | jj += kk; | 
|  | while (jj >= k2) { | 
|  | jj -= k2; | 
|  | k2 = kk; | 
|  | k++; | 
|  | kk = fftstate->factor [k - 1]; | 
|  | jj += kk; | 
|  | } | 
|  | fftstate->Perm [j - 1] = jj; | 
|  | } | 
|  | /*  determine the permutation cycles of length greater than 1 */ | 
|  | j = 0; | 
|  | for (;;) { | 
|  | do { | 
|  | j++; | 
|  | kk = fftstate->Perm [j - 1]; | 
|  | } while (kk < 0); | 
|  | if (kk != j) { | 
|  | do { | 
|  | k = kk; | 
|  | kk = fftstate->Perm [k - 1]; | 
|  | fftstate->Perm [k - 1] = -kk; | 
|  | } while (kk != j); | 
|  | k3 = kk; | 
|  | } else { | 
|  | fftstate->Perm [j - 1] = -j; | 
|  | if (j == nn) | 
|  | break;  /* exit infinite loop */ | 
|  | } | 
|  | } | 
|  | max_factors *= inc; | 
|  | /*  reorder a and b, following the permutation cycles */ | 
|  | for (;;) { | 
|  | j = k3 + 1; | 
|  | nt -= ispan; | 
|  | ii = nt - inc + 1; | 
|  | if (nt < 0) | 
|  | break;   /* exit infinite loop */ | 
|  | do { | 
|  | do { | 
|  | j--; | 
|  | } while (fftstate->Perm [j - 1] < 0); | 
|  | jj = jc; | 
|  | do { | 
|  | kspan = jj; | 
|  | if (jj > max_factors) { | 
|  | kspan = max_factors; | 
|  | } | 
|  | jj -= kspan; | 
|  | k = fftstate->Perm [j - 1]; | 
|  | kk = jc * k + ii + jj; | 
|  | k1 = kk + kspan - 1; | 
|  | k2 = 0; | 
|  | do { | 
|  | k2++; | 
|  | Rtmp [k2 - 1] = Re [k1]; | 
|  | Itmp [k2 - 1] = Im [k1]; | 
|  | k1 -= inc; | 
|  | } while (k1 != (kk-1)); | 
|  | do { | 
|  | k1 = kk + kspan - 1; | 
|  | k2 = k1 - jc * (k + fftstate->Perm [k - 1]); | 
|  | k = -fftstate->Perm [k - 1]; | 
|  | do { | 
|  | Re [k1] = Re [k2]; | 
|  | Im [k1] = Im [k2]; | 
|  | k1 -= inc; | 
|  | k2 -= inc; | 
|  | } while (k1 != (kk-1)); | 
|  | kk = k2 + 1; | 
|  | } while (k != j); | 
|  | k1 = kk + kspan - 1; | 
|  | k2 = 0; | 
|  | do { | 
|  | k2++; | 
|  | Re [k1] = Rtmp [k2 - 1]; | 
|  | Im [k1] = Itmp [k2 - 1]; | 
|  | k1 -= inc; | 
|  | } while (k1 != (kk-1)); | 
|  | } while (jj); | 
|  | } while (j != 1); | 
|  | } | 
|  | return 0;   /* exit point here */ | 
|  | } | 
|  | /* ---------------------- end-of-file (c source) ---------------------- */ | 
|  |  |