content: /**
   * Copyright 2007 DFKI GmbH.
   * All Rights Reserved.  Use is subject to license terms.
   * <p/>
   * This file is part of MARY TTS.
   * <p/>
   * MARY TTS is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Lesser General Public License as published by
   * the Free Software Foundation, version 3 of the License.
   * <p/>
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU Lesser General Public License for more details.
   * <p/>
   * You should have received a copy of the GNU Lesser General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  package marytts.util.math;
  
  /**
   * FFT for non-power-of-two sequences
   * Note that, this algorithm is significantly slower than FFT.java.
   * Please re-check if zero-padding works for your application and if so,
   * use FFT.java with zero padding to the closest power of two length
   *
   * @author Oytun T&uumlrk
   */
  public class FFTMixedRadix {
      //  maxf must be >= the maximum prime factor of fftSize.
      private static int maxf = 10000;
  
      //  maxp must be > the number of prime factors of fftSize.
      private static int maxp = 10000;
  
      private static int[] nfac;
      private static int[] np;
      private static double[] at;
      private static double[] ck;
      private static double[] bt;
      private static double[] sk;
      private static int factInd; //In original code: i
      private static int nt;
      private static int ks;
      private static int kspan;
      private static int nn;
      private static int jc;
      private static double radf;
      private static int jf;
      private static double sd;
      private static double cd;
      private static int kk;
      private static int k1;
      private static int k2;
      private static double ak;
      private static double bk;
      private static double c1;
      private static double s1;
      private static double aj;
      private static double bj;
      private static int kspnn;
      private static int k3;
      private static int k4;
      private static double akp;
      private static double akm;
      private static double ajp;
      private static double ajm;
      private static double bkp;
      private static double bkm;
      private static double bjp;
      private static double bjm;
      private static double c2;
      private static double s2;
      private static double c3;
      private static double s3;
      private static double aa;
      private static double bb;
      private static int currentFactor; //In original code: k
      private static int jCount; //In original code: j
      private static int jj;
      private static int jn;
      private static int kt;
      private static int mCount;//In original code: m
  
      private static int inc;
      private static double c72;
      private static double s72;
      private static double s120;
      private static double rad;
  
      //FFT power spectrum of real valued data x
      public static double[] fftPowerSpectrum(double[] x) {
          return fftPowerSpectrum(x, x.length);
      }
      //
  
      //fftSize point FFT power spectrum of real valued data x
      public static double[] fftPowerSpectrum(double[] x, int fftSize) {
          int xlen = x.length;
  
          ComplexArray h = new ComplexArray(fftSize);
          double[] Ps = new double[fftSize];
          int w;
  
          for (w = 0; w < xlen; w++) {
              h.real[w] = x[w];
              h.imag[w] = 0.0;
          }
  
          for (w = xlen; w < fftSize; w++) {
              h.real[w] = 0.0;
              h.imag[w] = 0.0;
          }
  
          mixedRadixFFTBase(h.real, h.imag, fftSize, fftSize, fftSize, 1);
  
          for (w = 0; w < fftSize; w++)
              h.imag[w] = -h.imag[w];
  
          for (w = 0; w < fftSize; w++)
              Ps[w] = 10 * MathUtils.log10(h.real[w] * h.real[w] + h.imag[w] * h.imag[w]);
  
          return Ps;
      }
      //
  
      // Absolute FFT spectrum of real valued data x
      public static double[] fftAbsSpectrum(double[] x) {
          return fftAbsSpectrum(x, x.length);
      }
      //
  
      // fftSize-point Absolute FFT spectrum of real valued data x
      public static double[] fftAbsSpectrum(double[] x, int fftSize) {
          int xlen = x.length;
  
          ComplexArray h = new ComplexArray(fftSize);
          double[] Ps = new double[fftSize];
          int w;
  
          for (w = 0; w < xlen; w++) {
              h.real[w] = x[w];
              h.imag[w] = 0.0;
          }
  
          for (w = xlen; w < fftSize; w++) {
              h.real[w] = 0.0;
              h.imag[w] = 0.0;
          }
  
          mixedRadixFFTBase(h.real, h.imag, fftSize, fftSize, fftSize, 1);
  
          for (w = 0; w < fftSize; w++)
              h.imag[w] = -h.imag[w];
  
          for (w = 0; w < fftSize; w++)
              Ps[w] = Math.sqrt(h.real[w] * h.real[w] + h.imag[w] * h.imag[w]);
  
          return Ps;
      }
      //
  
      // xlen-point FFT of real valued data x of length xlen.
      // The result is returned as a pointer to a ComplexArray object 
      //   which holds a real and an imag array of size xlen
      public static ComplexArray fftReal(double[] x, int xlen) {
          ComplexArray h = new ComplexArray(xlen);
  
          int w;
  
          for (w = 0; w < xlen; w++) {
              h.real[w] = x[w];
              h.imag[w] = 0.0;
          }
  
          mixedRadixFFTBase(h.real, h.imag, xlen, xlen, xlen, 1);
  
          for (w = 0; w < xlen; w++)
              h.imag[w] = -h.imag[w];
  
          return h;
      }
  
  
      //  fftSize-point FFT of real valued data x of length xlen.
      //  The result is returned as a pointer to a ComplexArray object 
      //      which holds a real and an imag array of size fftSize
      //  fftSize can be greater than, equal to, or less than xlen
      public static ComplexArray fftReal(double[] x, int xlen, int fftSize) {
          if (xlen > fftSize)
              xlen = fftSize;
  
          double[] x2 = new double[fftSize];
  
          int w;
          for (w = 0; w < xlen; w++)
              x2[w] = x[w];
  
          for (w = xlen; w < fftSize; w++)
              x2[w] = 0.0;
  
          ComplexArray h = fftReal(x2, fftSize);
  
          return h;
      }
  
      //  fftSize-point FFT of complex valued data in x of length x.length.
      //  The result is returned as a pointer to a ComplexArray object 
      //      which holds a real and an imag array of size fftSize
      //  fftSize can be greater than, equal to, or less than x.length.
      public static ComplexArray fftComplex(ComplexArray x, int fftSize) {
          ComplexArray h = new ComplexArray(fftSize);
  
          int w;
          for (w = 0; w < Math.min(x.real.length, fftSize); w++) {
              h.real[w] = x.real[w];
              h.imag[w] = x.imag[w];
          }
  
          for (w = x.real.length; w < fftSize; w++) {
              h.real[w] = 0.0;
              h.imag[w] = 0.0;
          }
  
          mixedRadixFFTBase(h.real, h.imag, fftSize, fftSize, fftSize, 1);
  
          int midVal = (int) (Math.floor(fftSize / 2) + 1);
  
          double tmp;
          for (w = 1; w < midVal; w++) {
              tmp = h.real[w];
              h.real[w] = h.real[fftSize - w];
              h.real[fftSize - w] = tmp;
  
              tmp = h.imag[w];
              h.imag[w] = h.imag[fftSize - w];
              h.imag[fftSize - w] = tmp;
          }
  
          return h;
      }
  
      public static void fftComplexInPlace(double[] real, double[] imag) {
          ComplexArray c = fftComplex(real, imag, Math.min(real.length, imag.length));
          System.arraycopy(c.real, 0, real, 0, c.real.length);
          System.arraycopy(c.imag, 0, imag, 0, c.imag.length);
      }
  
      public static ComplexArray fftComplex(double[] real, double[] imag) {
          return fftComplex(new ComplexArray(real, imag));
      }
  
      public static ComplexArray fftComplex(double[] real, double[] imag, int ifftSize) {
          return fftComplex(new ComplexArray(real, imag), ifftSize);
      }
  
      //  x.length-point FFT of complex valued data in x of length x.length.
      //  The result is returned as a pointer to a ComplexArray object 
      //      which holds a real and an imag array of size x.length.
      //  fftSize can be greater than, equal to, or less than x.length.
      public static ComplexArray fftComplex(ComplexArray x) {
          return fftComplex(x, x.real.length);
      }
  
      //  ifftSize-point inverse FFT of complex valued data in x of length x.length.
      //  The result is returned as a pointer to a ComplexArray object 
      //      which holds a real and an imag array of size ifftSize.
      //  ifftSize can be greater than, equal to, or less than x.length.
      public static ComplexArray ifft(ComplexArray x, int ifftSize) {
          ComplexArray h = null;
          int w;
  
          if (x.real.length > ifftSize) {
              ComplexArray h2 = ifft(x);
              h = new ComplexArray(ifftSize);
              for (w = 0; w < ifftSize; w++) {
                  h.real[w] = h2.real[w];
                  h.imag[w] = h2.imag[w];
              }
          } else if (x.real.length == ifftSize)
              h = ifft(x);
          else {
              ComplexArray h2 = ifft(x);
              h = new ComplexArray(ifftSize);
              for (w = 0; w < h2.real.length; w++) {
                  h.real[w] = h2.real[w];
                  h.imag[w] = h2.imag[w];
              }
              for (w = h2.real.length; w < ifftSize; w++) {
                  h.real[w] = 0.0;
                  h.imag[w] = 0.0;
              }
          }
  
          return h;
      }
  
      public static ComplexArray ifft(double[] real, double[] imag) {
          return ifft(new ComplexArray(real, imag));
      }
  
      public static ComplexArray ifft(double[] real, double[] imag, int ifftSize) {
          return ifft(new ComplexArray(real, imag), ifftSize);
      }
  
      //  x.length-point inverse FFT of complex valued data in x of length x.length.
      //  The result is returned as a pointer to a ComplexArray object 
      //      which holds a real and an imag array of size x.length.
      public static ComplexArray ifft(ComplexArray x) {
          ComplexArray h = new ComplexArray(x.real.length);
  
          int w;
          for (w = 0; w < x.real.length; w++) {
              h.real[w] = x.real[w] / x.real.length;
              h.imag[w] = x.imag[w] / x.real.length;
          }
  
          mixedRadixFFTBase(h.real, h.imag, x.real.length, x.real.length, x.real.length, -1);
  
          int midVal = (int) (Math.floor(x.real.length / 2) + 1);
  
          double tmp;
          for (w = 1; w < midVal; w++) {
              tmp = h.real[w];
              h.real[w] = h.real[x.real.length - w];
              h.real[x.real.length - w] = tmp;
  
              tmp = h.imag[w];
              h.imag[w] = h.imag[x.real.length - w];
              h.imag[x.real.length - w] = tmp;
          }
  
          return h;
      }
  
      //  ifftSize-point inverse FFT of complex valued data in x of length x.length.
      //  The result is returned as a pointer to a real valued array of size ifftSize.
      //  This function is for inverse FFT of Fourier coefficients of real-valued data.
      //  Therefore, in order to obtain correct results, please make sure data in x 
      //      conforms to the properties of Fourier coefficients of real valued data
      //      (i.e. even-symmetry of real coefficients, odd-symmetry of imag coefficients).
      public static double[] ifftReal(ComplexArray x, int ifftSize) {
          ComplexArray h = ifft(x);
          double[] y = new double[ifftSize];
          int w;
  
          for (w = 0; w < Math.min(h.real.length, ifftSize); w++)
              y[w] = h.real[w];
  
          for (w = Math.min(h.real.length, ifftSize); w < ifftSize; w++)
              y[w] = 0.0;
  
          return y;
      }
  
  
      //   In place mixed-radix FFT/IFFT algorithm
      //   a: Real part of sequence to be transformed
      //   b: Imaginary part of sequence to be transformed
      //   ntot = fftSize = nspan = length of a and b vectors = number of points in FFT (for simply computing FFT)
      //    (There are more complex uses of this function, for details refer to [Singleton, 1969])
      //    isn: 1  => FFT
      //         -1 => Inverse FFT
      //    The output is directly written to a and b vectors.
      //    Extra scaling and re-arranging of the output might be required for different cases.
      //    Please use wrapper functions fftComplex, fftReal, ifft, ifftReal for simplicity.
      //    Please refer to these functions if you want to add new functions calling mixedRadixFFTBase.
      private static void mixedRadixFFTBase(double[] a, double[] b, int ntot, int fftSize, int nspan, int isn) {
          //Local variables for handling goto statements
          boolean bLoopLine924 = false;
          boolean bJumpToLine924 = false;
  
          boolean bJumpToLine950 = true;
  
          boolean bLoopLine730 = false;
          boolean bJumpToLine730 = false;
  
          boolean bLoopLine640 = false;
          boolean bJumpToLine640 = false;
  
          boolean bJumpToLine640_0 = true;
  
          boolean bLoopLine520 = false;
          boolean bJumpToLine520 = false;
  
          boolean bLoopLine230 = false;
          boolean bJumpToLine230 = false;
  
          boolean bLoopLine210 = false;
          boolean bJumpToLine210 = false;
  
          boolean bLoopLine820 = false;
          boolean bJumpToLine820 = false;
  
          boolean bLoopLine830 = false;
          boolean bJumpToLine830 = false;
  
          boolean bLoopLine840 = false;
          boolean bJumpToLine840 = false;
  
          boolean bLoopLine850 = false;
          boolean bJumpToLine850 = false;
  
          boolean bLoopLine870 = false;
          boolean bJumpToLine870 = false;
  
          boolean bLoopLine880 = false;
          boolean bJumpToLine880 = false;
  
          boolean bLoopLine910 = false;
          boolean bJumpToLine910 = false;
  
          boolean bJumpToLine914_0 = true;
  
          boolean bLoopLine914 = false;
          boolean bJumpToLine914 = false;
  
          boolean bLoopLine420 = false;
          boolean bJumpToLine420 = false;
  
          boolean bLoopLine440 = false;
  
          boolean bJumpToLine460 = false;
  
          boolean bJumpToLine450 = false;
  
          boolean bLoopLine430 = false;
          boolean bJumpToLine430 = false;
  
          boolean bLoopLine410 = false;
          boolean bJumpToLine410 = false;
  
          boolean bLoopLine320 = false;
          boolean bJumpToLine320 = false;
          boolean bLoopLine320Prev = false;
          boolean bJumpToLine320Prev = false;
          boolean bLoopLine320Prev_2 = false;
          boolean bJumpToLine320Prev_2 = false;
          boolean bLoopLine320Prev_3 = false;
          boolean bJumpToLine320Prev_3 = false;
  
          boolean bLoopLine100 = false;
          boolean bJumpToLine100 = false;
          boolean bJumpToLine100_2 = false;
          boolean bJumpToLine100_3 = false;
  
          boolean bJumpToLine400 = false;
  
          boolean bLoopLine510 = false;
          boolean bJumpToLine510 = false;
          boolean bLoopLine510Prev_2 = false;
          boolean bJumpToLine510Prev_2 = false;
          boolean bLoopLine510Prev_3 = false;
          boolean bJumpToLine510Prev_3 = false;
  
          boolean bLoopLine902 = false;
          boolean bJumpToLine902 = false;
  
          boolean bLoopLine904 = false;
          boolean bJumpToLine904 = false;
  
          boolean bJumpToLine906 = false;
  
          boolean bJumpToLine890 = false;
  
          boolean bJumpToLine800 = false;
          boolean bJumpToLine800_1 = false;
  
          boolean bLoopLine410Prev = false;
          boolean bLoopLine420Prev = false;
          boolean bLoopLine430Prev = false;
          boolean bLoopLine440Prev = false;
          boolean bJumpToLine410Prev = false;
          boolean bJumpToLine420Prev = false;
          boolean bJumpToLine430Prev = false;
          boolean bLoopLine410Prev_2 = false;
          boolean bLoopLine420Prev_2 = false;
          boolean bLoopLine430Prev_2 = false;
          boolean bLoopLine440Prev_2 = false;
          boolean bJumpToLine410Prev_2 = false;
          boolean bJumpToLine420Prev_2 = false;
          boolean bJumpToLine430Prev_2 = false;
  
          boolean bJumpToLine700 = false;
          //
  
          nfac = new int[200];
          np = new int[maxp];
          at = new double[maxf];
          ck = new double[maxf];
          bt = new double[maxf];
          sk = new double[maxf];
  
          inc = isn;
          c72 = 0.30901699437494742;
          s72 = 0.95105651629515357;
          s120 = 0.86602540378443865;
          rad = 6.2831853071796;
  
          if (fftSize < 2)
              return;
  
          if (isn < 0) {
              s72 = -s72;
              s120 = -s120;
              rad = -rad;
              inc = -inc;
          }
  
          nt = inc * ntot;
          ks = inc * nspan;
          kspan = ks;
          nn = nt - inc;
          jc = ks / fftSize;
          radf = rad * jc * 0.5;
          factInd = 0;
          jf = 0;
  
          //Determine factors of fftSize
          mCount = 0;
          currentFactor = fftSize;
  
          if (fftSize < 2)
              nfac[0] = fftSize;
          else {
              while (currentFactor % 16 == 0) {
                  mCount++;
                  nfac[mCount - 1] = 4;
                  currentFactor /= 16;
              }
  
              jn = 3;
              jj = 9;
              while (currentFactor % jj == 0) {
                  mCount++;
                  nfac[mCount - 1] = jn;
                  currentFactor /= jj;
              }
  
              jn += 2;
              jj = jn * jn;
              while (jj <= currentFactor) {
                  while (currentFactor % jj == 0) {
                      mCount++;
                      nfac[mCount - 1] = jn;
                      currentFactor /= jj;
                  }
  
                  jn += 2;
                  jj = jn * jn;
              }
  
              boolean bGoto80 = false;
              if (currentFactor <= 4) {
                  kt = mCount;
                  nfac[mCount] = currentFactor;
                  if (currentFactor != 1)
                      mCount++;
  
                  bGoto80 = true;
                  if (kt != 0) {
                      jn = kt;
                      boolean bGoto90 = true;
                      while (jn != 0 || bGoto90) {
                          bGoto90 = false;
                          mCount++;
                          nfac[mCount - 1] = nfac[jn - 1];
                          jn--;
                      }
                  }
              }
  
              if (!bGoto80) {
                  if (currentFactor - Math.floor(currentFactor / 4.0) * 4 == 0) {
                      mCount++;
                      nfac[mCount - 1] = 2;
                      currentFactor /= 4;
                  }
                  kt = mCount;
                  jn = 2;
  
                  boolean bGoto60 = true;
                  while (jn <= currentFactor || bGoto60) {
                      bGoto60 = false;
                      if (currentFactor % jn == 0) {
                          mCount++;
                          nfac[mCount - 1] = jn;
                          currentFactor /= jn;
                      }
  
                      jn = (int) (Math.floor((jn + 1.0) / 2) * 2 + 1);
                  }
  
                  if (kt != 0) {
                      jn = kt;
                      boolean bGoto90 = true;
                      while (jn != 0 || bGoto90) {
                          bGoto90 = false;
                          mCount++;
                          nfac[mCount - 1] = nfac[jn - 1];
                          jn--;
                      }
                  }
              }
          }
          //
  
          //compute fourier transform
          do { //line100
              //if (fLog!=NULL)
              //    fprintf(fLog, "100\fftSize");
  
              bLoopLine100 = false;
              if (bJumpToLine100_2) {
                  bJumpToLine100_2 = false;
                  bLoopLine440 = bLoopLine440Prev_2;
                  bLoopLine430 = bLoopLine430Prev_2;
                  bLoopLine420 = bLoopLine420Prev_2;
                  bLoopLine410 = bLoopLine410Prev_2;
                  bLoopLine510 = bLoopLine510Prev_2;
                  bLoopLine320 = bLoopLine320Prev_2;
                  bJumpToLine410 = bJumpToLine410Prev_2;
                  bJumpToLine420 = bJumpToLine420Prev_2;
                  bJumpToLine430 = bJumpToLine430Prev_2;
                  bJumpToLine510 = bJumpToLine510Prev_2;
                  bJumpToLine320 = bJumpToLine320Prev_2;
              }
  
              if (bJumpToLine100_3) {
                  bJumpToLine100_3 = false;
                  bLoopLine510 = bLoopLine510Prev_3;
                  bLoopLine320 = bLoopLine320Prev_3;
                  bJumpToLine510 = bJumpToLine510Prev_3;
                  bJumpToLine320 = bJumpToLine320Prev_3;
              }
  
              if (bJumpToLine100)
                  bJumpToLine100 = false;
  
              sd = radf / kspan;
              cd = 2.0 * Math.sin(sd) * Math.sin(sd);
              sd = Math.sin(sd + sd);
              kk = 1;
              factInd = factInd + 1;
              bJumpToLine400 = nfac[factInd - 1] != 2;
  
              if (!bJumpToLine400) {
                  //transform for factor of 2 including rotation factor
                  kspan = kspan / 2;
                  k1 = kspan + 2;
  
                  do { //line210
                      //if (fLog!=NULL)
                      //    fprintf(fLog, "210\fftSize");
  
                      bLoopLine210 = false;
                      bJumpToLine210 = false;
                      k2 = kk + kspan;
                      ak = a[k2 - 1];
                      bk = b[k2 - 1];
                      a[k2 - 1] = a[kk - 1] - ak;
                      b[k2 - 1] = b[kk - 1] - bk;
                      a[kk - 1] = a[kk - 1] + ak;
                      b[kk - 1] = b[kk - 1] + bk;
                      kk = k2 + kspan;
                      if (kk <= nn) {
                          bLoopLine210 = true;
                          bJumpToLine210 = true;
                      } else {
                          bLoopLine210 = false;
                          bJumpToLine210 = false;
                      }
  
                      if (!bJumpToLine210) {
                          kk = kk - nn;
                          if (kk <= jc) {
                              bLoopLine210 = true;
                              bJumpToLine210 = true;
                          } else {
                              bLoopLine210 = false;
                              bJumpToLine210 = false;
                          }
                      }
                  } while (bLoopLine210);
  
                  bJumpToLine800 = kk > kspan;
  
                  if (!bJumpToLine800) {
                      do { //line220
                          //if (fLog!=NULL)
                          //    fprintf(fLog, "220\fftSize");
                          c1 = 1.0 - cd;
                          s1 = sd;
  
                          do { //line230
                              //if (fLog!=NULL)
                              //    fprintf(fLog, "230\fftSize");
  
                              bLoopLine230 = false;
                              bJumpToLine230 = false;
                              k2 = kk + kspan;
                              ak = a[kk - 1] - a[k2 - 1];
                              bk = b[kk - 1] - b[k2 - 1];
                              a[kk - 1] = a[kk - 1] + a[k2 - 1];
                              b[kk - 1] = b[kk - 1] + b[k2 - 1];
                              a[k2 - 1] = c1 * ak - s1 * bk;
                              b[k2 - 1] = s1 * ak + c1 * bk;
                              kk = k2 + kspan;
  
                              if (kk < nt) {
                                  bLoopLine230 = true;
                                  bJumpToLine230 = true;
                              } else {
                                  bLoopLine230 = false;
                                  bJumpToLine230 = false;
                              }
  
                              if (!bJumpToLine230) {
                                  k2 = kk - nt;
                                  c1 = -c1;
                                  kk = k1 - k2;
  
                                  if (kk > k2) {
                                      bLoopLine230 = true;
                                      bJumpToLine230 = true;
                                  } else {
                                      bLoopLine230 = false;
                                      bJumpToLine230 = false;
                                  }
  
                                  if (!bJumpToLine230) {
                                      ak = c1 - (cd * c1 + sd * s1);
                                      s1 = (sd * c1 - cd * s1) + s1;
                                      c1 = 2.0 - (ak * ak + s1 * s1);
                                      s1 = c1 * s1;
                                      c1 = c1 * ak;
                                      kk = kk + jc;
  
                                      if (kk < k2) {
                                          bLoopLine230 = true;
                                          bJumpToLine230 = true;
                                      } else {
                                          bLoopLine230 = false;
                                          bJumpToLine230 = false;
                                      }
                                  }
                              }
                          } while (bLoopLine230);
  
                          k1 = k1 + inc + inc;
                          kk = (k1 - kspan) / 2 + jc;
  
                      } while (kk <= jc + jc);
  
                      bLoopLine100 = true;
                      bJumpToLine100 = true;
                  }
              }
  
              if (!bJumpToLine100 || bJumpToLine400 || bJumpToLine800) {
                  // transform for factor of 3 (optional code)
                  do {
                      if (!bJumpToLine800) {
                          if (!bJumpToLine400) { //line320
                              //if (fLog!=NULL)
                              //    fprintf(fLog, "320\fftSize");
  
                              bLoopLine320 = false;
                              bJumpToLine320 = false;
  
                              k1 = kk + kspan;
                              k2 = k1 + kspan;
                              ak = a[kk - 1];
                              bk = b[kk - 1];
                              aj = a[k1 - 1] + a[k2 - 1];
                              bj = b[k1 - 1] + b[k2 - 1];
                              a[kk - 1] = ak + aj;
                              b[kk - 1] = bk + bj;
                              ak = -0.5 * aj + ak;
                              bk = -0.5 * bj + bk;
                              aj = (a[k1 - 1] - a[k2 - 1]) * s120;
                              bj = (b[k1 - 1] - b[k2 - 1]) * s120;
                              a[k1 - 1] = ak - bj;
                              b[k1 - 1] = bk + aj;
                              a[k2 - 1] = ak + bj;
                              b[k2 - 1] = bk - aj;
                              kk = k2 + kspan;
                              if (kk < nn) {
                                  bLoopLine320 = true;
                                  bJumpToLine320 = true;
                              } else {
                                  bLoopLine320 = false;
                                  bJumpToLine320 = false;
                              }
                          }
                      }
  
                      if (!bJumpToLine320 || bJumpToLine400 || bJumpToLine800) {
                          if (!bJumpToLine800) {
                              if (!bJumpToLine400) {
                                  kk = kk - nn;
                                  if (kk <= kspan) {
                                      bLoopLine320 = true;
                                      bJumpToLine320 = true;
                                  } else {
                                      bLoopLine320 = false;
                                      bJumpToLine320 = false;
                                  }
                              }
                          }
  
  
                          if (!bJumpToLine320 || bJumpToLine400 || bJumpToLine800) {
                              if (!bJumpToLine800) {
                                  if (!bJumpToLine700) {
                                      bJumpToLine700 = !bJumpToLine400;
                                  }
                              }
  
                              do {
                                  if (!bJumpToLine700 || bJumpToLine400) {
                                      if (!bJumpToLine800 || bJumpToLine400) {
                                          bJumpToLine400 = false;
                                          if (nfac[factInd - 1] == 4 || bJumpToLine510) {
                                              if (!bJumpToLine510) {
                                                  //if (fLog!=NULL)
                                                  //    fprintf(fLog, "400\fftSize");
  
                                                  kspnn = kspan;
                                                  kspan = kspan / 4;
  
                                                  do { //line410
                                                      //if (fLog!=NULL)
                                                      //    fprintf(fLog, "410\fftSize");
  
                                                      bLoopLine410 = false;
                                                      bJumpToLine410 = false;
  
                                                      c1 = 1.0;
                                                      s1 = 0;
  
                                                      do { //line420
                                                          //if (fLog!=NULL)
                                                          //    fprintf(fLog, "420\fftSize");
  
                                                          bLoopLine420 = false;
                                                          bJumpToLine420 = false;
  
                                                          k1 = kk + kspan;
                                                          k2 = k1 + kspan;
                                                          k3 = k2 + kspan;
                                                          akp = a[kk - 1] + a[k2 - 1];
                                                          akm = a[kk - 1] - a[k2 - 1];
                                                          ajp = a[k1 - 1] + a[k3 - 1];
                                                          ajm = a[k1 - 1] - a[k3 - 1];
                                                          a[kk - 1] = akp + ajp;
                                                          ajp = akp - ajp;
                                                          bkp = b[kk - 1] + b[k2 - 1];
                                                          bkm = b[kk - 1] - b[k2 - 1];
                                                          bjp = b[k1 - 1] + b[k3 - 1];
                                                          bjm = b[k1 - 1] - b[k3 - 1];
                                                          b[kk - 1] = bkp + bjp;
                                                          bjp = bkp - bjp;
                                                          bJumpToLine450 = isn < 0;
  
                                                          if (!bJumpToLine450) {
                                                              akp = akm - bjm;
                                                              akm = akm + bjm;
                                                              bkp = bkm + ajm;
                                                              bkm = bkm - ajm;
                                                              bJumpToLine460 = s1 == 0;
                                                          }
  
                                                          do { //line430
                                                              //if (fLog!=NULL)
                                                              //    fprintf(fLog, "430\fftSize");
                                                              bLoopLine430 = false;
                                                              bJumpToLine430 = false;
  
                                                              if (!bJumpToLine460) {
                                                                  if (!bJumpToLine450) {
                                                                      a[k1 - 1] = akp * c1 - bkp * s1;
                                                                      b[k1 - 1] = akp * s1 + bkp * c1;
                                                                      a[k2 - 1] = ajp * c2 - bjp * s2;
                                                                      b[k2 - 1] = ajp * s2 + bjp * c2;
                                                                      a[k3 - 1] = akm * c3 - bkm * s3;
                                                                      b[k3 - 1] = akm * s3 + bkm * c3;
                                                                      kk = k3 + kspan;
                                                                      if (kk <= nt) {
                                                                          bLoopLine420 = true;
                                                                          bJumpToLine420 = true;
                                                                      } else {
                                                                          bLoopLine420 = false;
                                                                          bJumpToLine420 = false;
                                                                      }
                                                                  }
                                                              }
  
                                                              if (!bJumpToLine420 || bJumpToLine460 || bJumpToLine450) {
                                                                  do {
                                                                      if (!bJumpToLine460) {
                                                                          if (!bJumpToLine450) {
                                                                              //if (fLog!=NULL)
                                                                              //fprintf(fLog, "440\fftSize");
  
                                                                              bLoopLine440 = false;
  
                                                                              c2 = c1 - (cd * c1 + sd * s1);
                                                                              s1 = (sd * c1 - cd * s1) + s1;
                                                                              c1 = 2.0 - (c2 * c2 + s1 * s1);
                                                                              s1 = c1 * s1;
                                                                              c1 = c1 * c2;
                                                                              c2 = c1 * c1 - s1 * s1;
                                                                              s2 = 2.0 * c1 * s1;
                                                                              c3 = c2 * c1 - s2 * s1;
                                                                              s3 = c2 * s1 + s2 * c1;
                                                                              kk = kk - nt + jc;
                                                                              if (kk <= kspan) {
                                                                                  bLoopLine420 = true;
                                                                                  bJumpToLine420 = true;
                                                                              } else {
                                                                                  bLoopLine420 = false;
                                                                                  bJumpToLine420 = false;
                                                                              }
                                                                          }
                                                                      }
  
                                                                      if (!bJumpToLine420 || bJumpToLine460 || bJumpToLine450) {
                                                                          if (!bJumpToLine460) {
                                                                              if (!bJumpToLine450) {
                                                                                  kk = kk - kspan + inc;
                                                                                  if (kk <= jc) {
                                                                                      bLoopLine410 = true;
                                                                                      bJumpToLine410 = true;
                                                                                      bLoopLine440 = false;
                                                                                      bLoopLine430 = false;
                                                                                      bJumpToLine430 = false;
                                                                                      bLoopLine420 = false;
                                                                                      bJumpToLine420 = false;
                                                                                  } else {
                                                                                      bLoopLine410 = false;
                                                                                      bJumpToLine410 = false;
                                                                                  }
  
                                                                                  if (!bJumpToLine410) {
                                                                                      if (kspan == jc) {
                                                                                          bJumpToLine800_1 = true;
                                                                                          bLoopLine410Prev = bLoopLine410;
                                                                                          bLoopLine420Prev = bLoopLine420;
                                                                                          bLoopLine430Prev = bLoopLine430;
                                                                                          bLoopLine440Prev = bLoopLine440;
                                                                                          bJumpToLine410Prev = bJumpToLine410;
                                                                                          bJumpToLine420Prev = bJumpToLine420;
                                                                                          bJumpToLine430Prev = bJumpToLine430;
  
                                                                                          bLoopLine410 = false;
                                                                                          bLoopLine420 = false;
                                                                                          bLoopLine430 = false;
                                                                                          bLoopLine440 = false;
                                                                                          bJumpToLine410 = false;
                                                                                          bJumpToLine420 = false;
                                                                                          bJumpToLine430 = false;
                                                                                      } else
                                                                                          bJumpToLine800_1 = false;
  
                                                                                      if (!bJumpToLine800_1) {
                                                                                          bLoopLine100 = true;
                                                                                          bJumpToLine100_2 = true;
  
                                                                                          bLoopLine410Prev_2 = bLoopLine410;
                                                                                          bLoopLine420Prev_2 = bLoopLine420;
                                                                                          bLoopLine430Prev_2 = bLoopLine430;
                                                                                          bLoopLine440Prev_2 = bLoopLine440;
                                                                                          bLoopLine510Prev_2 = bLoopLine510;
                                                                                          bLoopLine320Prev_2 = bLoopLine320;
                                                                                          bJumpToLine410Prev_2 = bJumpToLine410;
                                                                                          bJumpToLine420Prev_2 = bJumpToLine420;
                                                                                          bJumpToLine430Prev_2 = bJumpToLine430;
                                                                                          bJumpToLine510Prev_2 = bJumpToLine510;
                                                                                          bJumpToLine320Prev_2 = bJumpToLine320;
  
                                                                                          bLoopLine440 = false;
                                                                                          bLoopLine430 = false;
                                                                                          bLoopLine420 = false;
                                                                                          bLoopLine410 = false;
                                                                                          bLoopLine510 = false;
                                                                                          bLoopLine320 = false;
                                                                                          bJumpToLine410 = false;
                                                                                          bJumpToLine420 = false;
                                                                                          bJumpToLine430 = false;
                                                                                          bJumpToLine510 = false;
                                                                                          bJumpToLine320 = false;
                                                                                      }
                                                                                  }
                                                                              }
  
                                                                              if (!bJumpToLine100_2) {
                                                                                  if (!bJumpToLine800_1) {
                                                                                      if (!bJumpToLine410) {
                                                                                          //if (fLog!=NULL)
                                                                                          //fprintf(fLog, "450\fftSize");
  
                                                                                          bJumpToLine450 = false;
                                                                                          akp = akm + bjm;
                                                                                          akm = akm - bjm;
                                                                                          bkp = bkm - ajm;
                                                                                          bkm = bkm + ajm;
                                                                                          if (s1 != 0) {
                                                                                              bLoopLine430 = true;
                                                                                              bJumpToLine430 = true;
                                                                                              bLoopLine440 = false;
                                                                                          } else {
                                                                                              bLoopLine430 = false;
                                                                                              bJumpToLine430 = false;
                                                                                          }
                                                                                      }
                                                                                  }
                                                                              }
                                                                          }
  
                                                                          if (!bJumpToLine100_2) {
                                                                              if (!bJumpToLine800_1) {
                                                                                  if (!bJumpToLine430 && !bJumpToLine410) {
                                                                                      //if (fLog!=NULL)
                                                                                      //fprintf(fLog, "460\fftSize");
  
                                                                                      bJumpToLine460 = false;
                                                                                      a[k1 - 1] = akp;
                                                                                      b[k1 - 1] = bkp;
                                                                                      a[k2 - 1] = ajp;
                                                                                      b[k2 - 1] = bjp;
                                                                                      a[k3 - 1] = akm;
                                                                                      b[k3 - 1] = bkm;
                                                                                      kk = k3 + kspan;
                                                                                      if (kk <= nt) {
                                                                                          bLoopLine420 = true;
                                                                                          bJumpToLine420 = true;
                                                                                      } else {
                                                                                          bLoopLine420 = false;
                                                                                          bJumpToLine420 = false;
                                                                                      }
  
                                                                                      bLoopLine440 = !bJumpToLine420;
                                                                                  }
                                                                              }
                                                                          }
                                                                      }
                                                                  } while (bLoopLine440);
                                                              }
                                                          } while (bLoopLine430);
                                                      } while (bLoopLine420);
                                                  } while (bLoopLine410);
                                              }
  
                                              if (!bJumpToLine100_2) {
                                                  if (!bJumpToLine800_1) {
                                                      //transform for factor of 5 (optional code)
                                                      if (bJumpToLine510) {
                                                          bJumpToLine510 = false;
                                                          bLoopLine510 = false;
                                                          bJumpToLine320 = bJumpToLine320Prev;
                                                          bLoopLine320 = bLoopLine320Prev;
                                                      }
  
                                                      //if (fLog!=NULL)
                                                      //fprintf(fLog, "510\fftSize");
  
                                                      c2 = c72 * c72 - s72 * s72;
                                                      s2 = 2.0 * c72 * s72;
  
                                                      do { //line520
                                                          //if (fLog!=NULL)
                                                          //fprintf(fLog, "520\fftSize");
  
                                                          bLoopLine520 = false;
                                                          bJumpToLine520 = false;
                                                          k1 = kk + kspan;
                                                          k2 = k1 + kspan;
                                                          k3 = k2 + kspan;
                                                          k4 = k3 + kspan;
                                                          akp = a[k1 - 1] + a[k4 - 1];
                                                          akm = a[k1 - 1] - a[k4 - 1];
                                                          bkp = b[k1 - 1] + b[k4 - 1];
                                                          bkm = b[k1 - 1] - b[k4 - 1];
                                                          ajp = a[k2 - 1] + a[k3 - 1];
                                                          ajm = a[k2 - 1] - a[k3 - 1];
                                                          bjp = b[k2 - 1] + b[k3 - 1];
                                                          bjm = b[k2 - 1] - b[k3 - 1];
                                                          aa = a[kk - 1];
                                                          bb = b[kk - 1];
                                                          a[kk - 1] = aa + akp + ajp;
                                                          b[kk - 1] = 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;
                                                          a[k1 - 1] = ak - bj;
                                                          a[k4 - 1] = ak + bj;
                                                          b[k1 - 1] = bk + aj;
                                                          b[k4 - 1] = bk - aj;
                                                          ak = akp * c2 + ajp * c72 + aa;
                                                          bk = bkp * c2 + bjp * c72 + bb;
                                                          aj = akm * s2 - ajm * s72;
                                                          bj = bkm * s2 - bjm * s72;
                                                          a[k2 - 1] = ak - bj;
                                                          a[k3 - 1] = ak + bj;
                                                          b[k2 - 1] = bk + aj;
                                                          b[k3 - 1] = bk - aj;
                                                          kk = k4 + kspan;
                                                          if (kk < nn) {
                                                              bLoopLine520 = true;
                                                              bJumpToLine520 = true;
                                                          } else {
                                                              bLoopLine520 = false;
                                                              bJumpToLine520 = false;
                                                          }
  
                                                          if (!bJumpToLine520) {
                                                              kk = kk - nn;
                                                              if (kk <= kspan) {
                                                                  bLoopLine520 = true;
                                                                  bJumpToLine520 = true;
                                                              } else {
                                                                  bLoopLine520 = false;
                                                                  bJumpToLine520 = false;
                                                              }
                                                          }
                                                      } while (bLoopLine520);
  
                                                      bJumpToLine700 = true;
                                                  }
                                              }
                                          }
  
                                          if (!bJumpToLine100_2 && !bJumpToLine800_1 && !bJumpToLine700) {
                                              //line600
                                              //if (fLog!=NULL)
                                              //fprintf(fLog, "600\fftSize");
  
                                              //transform for odd factors
                                              currentFactor = nfac[factInd - 1];
                                              kspnn = kspan;
                                              kspan = kspan / currentFactor;
                                              if (currentFactor == 3) {
                                                  bLoopLine320 = true;
                                                  bJumpToLine320 = true;
                                              } else {
                                                  bLoopLine320 = false;
                                                  bJumpToLine320 = false;
                                              }
                                          }
                                      }
                                  }
  
                                  if (!bJumpToLine100_2) {
                                      if (!bJumpToLine320 || bJumpToLine800 || bJumpToLine800_1 || bJumpToLine700) {
                                          if (!bJumpToLine800 && !bJumpToLine800_1 && !bJumpToLine700) {
                                              if (currentFactor == 5) {
                                                  bLoopLine510 = true;
                                                  bJumpToLine510 = true;
                                                  bJumpToLine320Prev = bJumpToLine320;
                                                  bLoopLine320Prev = bLoopLine320;
                                                  bLoopLine320 = false;
                                                  bJumpToLine320 = false;
                                              } else {
                                                  bLoopLine510 = false;
                                                  bJumpToLine510 = false;
                                              }
                                          }
  
                                          if (!bJumpToLine510 || bJumpToLine800 || bJumpToLine800_1 || bJumpToLine700) {
                                              if (!bJumpToLine800 && !bJumpToLine800_1) {
                                                  if (!bJumpToLine700) {
                                                      bJumpToLine640_0 = currentFactor == jf;
  
                                                      if (!bJumpToLine640_0) {
                                                          jf = currentFactor;
                                                          s1 = rad / currentFactor;
                                                          c1 = Math.cos(s1);
                                                          s1 = Math.sin(s1);
                                                          if (jf > maxf) {
                                                              isn = 0;
                                                              System.out.println("Array bounds exceeded within subroutine fft\fftSize");
                                                              return;
                                                          }
  
                                                          ck[jf - 1] = 1.0;
                                                          sk[jf - 1] = 0.0;
  
                                                          jCount = 1;
  
                                                          do { //line630
                                                              //if (fLog!=NULL)
                                                              //fprintf(fLog, "630\fftSize");
  
                                                              ck[jCount - 1] = ck[currentFactor - 1] * c1 + sk[currentFactor - 1] * s1;
                                                              sk[jCount - 1] = ck[currentFactor - 1] * s1 - sk[currentFactor - 1] * c1;
                                                              currentFactor = currentFactor - 1;
                                                              ck[currentFactor - 1] = ck[jCount - 1];
                                                              sk[currentFactor - 1] = -sk[jCount - 1];
                                                              jCount = jCount + 1;
                                                          } while (jCount < currentFactor);
                                                      }
  
                                                      do { //line640
                                                          //if (fLog!=NULL)
                                                          //fprintf(fLog, "640\fftSize");
  
                                                          bLoopLine640 = false;
                                                          bJumpToLine640 = false;
                                                          k1 = kk;
                                                          k2 = kk + kspnn;
                                                          aa = a[kk - 1];
                                                          bb = b[kk - 1];
                                                          ak = aa;
                                                          bk = bb;
                                                          jCount = 1;
                                                          k1 = k1 + kspan;
  
                                                          do { //line650
                                                              //if (fLog!=NULL)
                                                              //fprintf(fLog, "650\fftSize");
  
                                                              k2 = k2 - kspan;
                                                              jCount = jCount + 1;
                                                              at[jCount - 1] = a[k1 - 1] + a[k2 - 1];
                                                              ak = at[jCount - 1] + ak;
                                                              bt[jCount - 1] = b[k1 - 1] + b[k2 - 1];
                                                              bk = bt[jCount - 1] + bk;
                                                              jCount = jCount + 1;
                                                              at[jCount - 1] = a[k1 - 1] - a[k2 - 1];
                                                              bt[jCount - 1] = b[k1 - 1] - b[k2 - 1];
                                                              k1 = k1 + kspan;
                                                          } while (k1 < k2);
  
                                                          a[kk - 1] = ak;
                                                          b[kk - 1] = bk;
                                                          k1 = kk;
                                                          k2 = kk + kspnn;
                                                          jCount = 1;
  
                                                          do { //line660
                                                              //if (fLog!=NULL)
                                                              //fprintf(fLog, "660\fftSize");
  
                                                              k1 = k1 + kspan;
                                                              k2 = k2 - kspan;
                                                              jj = jCount;
                                                              ak = aa;
                                                              bk = bb;
                                                              aj = 0.0;
                                                              bj = 0.0;
                                                              currentFactor = 1;
  
                                                              do { //line670
                                                                  //if (fLog!=NULL)
                                                                  //fprintf(fLog, "670\fftSize");
  
                                                                  currentFactor = currentFactor + 1;
                                                                  ak = at[currentFactor - 1] * ck[jj - 1] + ak;
                                                                  bk = bt[currentFactor - 1] * ck[jj - 1] + bk;
                                                                  currentFactor = currentFactor + 1;
  
                                                                  aj = at[currentFactor - 1] * sk[jj - 1] + aj;
                                                                  bj = bt[currentFactor - 1] * sk[jj - 1] + bj;
                                                                  jj = jj + jCount;
                                                                  if (jj > jf)
                                                                      jj = jj - jf;
                                                              } while (currentFactor < jf);
  
                                                              currentFactor = jf - jCount;
                                                              a[k1 - 1] = ak - bj;
                                                              b[k1 - 1] = bk + aj;
                                                              a[k2 - 1] = ak + bj;
                                                              b[k2 - 1] = bk - aj;
                                                              jCount = jCount + 1;
                                                          } while (jCount < currentFactor);
  
                                                          kk = kk + kspnn;
                                                          if (kk <= nn) {
                                                              bLoopLine640 = true;
                                                              bJumpToLine640 = true;
                                                          } else {
                                                              bLoopLine640 = false;
                                                              bJumpToLine640 = false;
                                                          }
  
                                                          if (!bJumpToLine640) {
                                                              kk = kk - nn;
                                                              if (kk <= kspan) {
                                                                  bLoopLine640 = true;
                                                                  bJumpToLine640 = true;
                                                              } else {
                                                                  bLoopLine640 = false;
                                                                  bJumpToLine640 = false;
                                                              }
                                                          }
                                                      } while (bLoopLine640);
                                                  }
  
                                                  //multiply by rotation factor [except for factors of 2 and 4-1]
                                                  //line700
                                                  //if (fLog!=NULL)
                                                  //fprintf(fLog, "700\fftSize");
  
                                                  bJumpToLine700 = false;
                                                  bJumpToLine800 = factInd == mCount;
  
                                                  if (!bJumpToLine800) {
                                                      kk = jc + 1;
  
                                                      do { //line710
                                                          //if (fLog!=NULL)
                                                          //fprintf(fLog, "710\fftSize");
                                                          c2 = 1.0 - cd;
                                                          s1 = sd;
  
                                                          do { //line720
                                                              //if (fLog!=NULL)
                                                              //fprintf(fLog, "720\fftSize");
                                                              c1 = c2;
                                                              s2 = s1;
                                                              kk = kk + kspan;
  
                                                              do { //line730
                                                                  //if (fLog!=NULL)
                                                                  //fprintf(fLog, "730\fftSize");
  
                                                                  bJumpToLine730 = false;
                                                                  bLoopLine730 = false;
  
                                                                  ak = a[kk - 1];
                                                                  a[kk - 1] = c2 * ak - s2 * b[kk - 1];
                                                                  b[kk - 1] = s2 * ak + c2 * b[kk - 1];
                                                                  kk = kk + kspnn;
                                                                  if (kk <= nt) {
                                                                      bJumpToLine730 = true;
                                                                      bLoopLine730 = true;
                                                                  } else {
                                                                      bJumpToLine730 = false;
                                                                      bLoopLine730 = false;
                                                                  }
  
                                                                  if (!bJumpToLine730) {
                                                                      ak = s1 * s2;
                                                                      s2 = s1 * c2 + c1 * s2;
                                                                      c2 = c1 * c2 - ak;
                                                                      kk = kk - nt + kspan;
  
                                                                      if (kk <= kspnn) {
                                                                          bJumpToLine730 = true;
                                                                          bLoopLine730 = true;
                                                                      } else {
                                                                          bJumpToLine730 = false;
                                                                          bLoopLine730 = false;
                                                                      }
                                                                  }
  
                                                              } while (bLoopLine730);
  
                                                              c2 = c1 - (cd * c1 + sd * s1);
                                                              s1 = s1 + (sd * c1 - cd * s1);
                                                              c1 = 2.0 - (c2 * c2 + s1 * s1);
                                                              s1 = c1 * s1;
                                                              c2 = c1 * c2;
                                                              kk = kk - kspnn + jc;
                                                          } while (kk <= kspan);
  
                                                          kk = kk - kspan + jc + inc;
                                                      } while (kk <= jc + jc);
  
                                                      bLoopLine100 = true;
                                                      bJumpToLine100_3 = true;
  
                                                      bLoopLine510Prev_3 = bLoopLine510;
                                                      bLoopLine320Prev_3 = bLoopLine320;
                                                      bJumpToLine510Prev_3 = bJumpToLine510;
                                                      bJumpToLine320Prev_3 = bJumpToLine320;
  
                                                      bLoopLine510 = false;
                                                      bLoopLine320 = false;
                                                      bJumpToLine510 = false;
                                                      bJumpToLine320 = false;
                                                  }
                                              }
  
                                              if (!bJumpToLine100_3) {
                                                  //permute the results to normal order---done in two stages
                                                  // permutation for square factors of fftSize
                                                  bJumpToLine800 = false;
                                                  bJumpToLine800_1 = false;
  
                                                  //line800
                                                  //if (fLog!=NULL)
                                                  //fprintf(fLog, "800\fftSize");
  
                                                  np[1 - 1] = ks;
                                                  if (kt == 0)
                                                      bJumpToLine890 = true;
  
                                                  if (!bJumpToLine890) {
                                                      currentFactor = kt + kt + 1;
                                                      if (mCount < currentFactor)
                                                          currentFactor = currentFactor - 1;
                                                      jCount = 1;
                                                      np[currentFactor + 1 - 1] = jc;
  
                                                      do { //line810
                                                          //if (fLog!=NULL)
                                                          //fprintf(fLog, "810\fftSize");
  
                                                          np[jCount + 1 - 1] = np[jCount - 1] / nfac[jCount - 1];
                                                          np[currentFactor - 1] = np[currentFactor + 1 - 1] * nfac[jCount - 1];
                                                          jCount = jCount + 1;
                                                          currentFactor = currentFactor - 1;
                                                      } while (jCount < currentFactor);
  
                                                      k3 = np[currentFactor + 1 - 1];
                                                      kspan = np[2 - 1];
                                                      kk = jc + 1;
                                                      k2 = kspan + 1;
                                                      jCount = 1;
                                                  }
  
                                                  if (fftSize == ntot || !bJumpToLine890) {
                                                      if (!bJumpToLine890) {
                                                          //permutation for single-variate transform [optional code-1]
                                                          do { //line820
                                                              //if (fLog!=NULL)
                                                              //fprintf(fLog, "820\fftSize");
  
                                                              bLoopLine820 = false;
                                                              bJumpToLine820 = false;
                                                              ak = a[kk - 1];
                                                              a[kk - 1] = a[k2 - 1];
                                                              a[k2 - 1] = ak;
                                                              bk = b[kk - 1];
                                                              b[kk - 1] = b[k2 - 1];
                                                              b[k2 - 1] = bk;
                                                              kk = kk + inc;
                                                              k2 = kspan + k2;
                                                              if (k2 < ks) {
                                                                  bLoopLine820 = true;
                                                                  bJumpToLine820 = true;
                                                              } else {
                                                                  bLoopLine820 = false;
                                                                  bJumpToLine820 = false;
                                                              }
  
                                                              if (!bJumpToLine820) {
                                                                  do { //line830
                                                                      //if (fLog!=NULL)
                                                                      //fprintf(fLog, "830\fftSize");
  
                                                                      bLoopLine830 = false;
                                                                      bJumpToLine830 = false;
  
                                                                      k2 = k2 - np[jCount - 1];
                                                                      jCount = jCount + 1;
                                                                      k2 = np[jCount + 1 - 1] + k2;
                                                                      if (k2 > np[jCount - 1]) {
                                                                          bLoopLine830 = true;
                                                                          bJumpToLine830 = true;
                                                                      } else {
                                                                          bLoopLine830 = false;
                                                                          bJumpToLine830 = false;
                                                                      }
  
                                                                      if (!bJumpToLine830) {
                                                                          jCount = 1;
  
                                                                          do { //line840
                                                                              //if (fLog!=NULL)
                                                                              //fprintf(fLog, "840\fftSize");
  
                                                                              bLoopLine840 = false;
                                                                              bJumpToLine840 = false;
                                                                              if (kk < k2) {
                                                                                  bLoopLine820 = true;
                                                                                  bJumpToLine820 = true;
                                                                                  bLoopLine830 = false;
                                                                                  bJumpToLine830 = false;
                                                                              } else {
                                                                                  bLoopLine820 = false;
                                                                                  bJumpToLine820 = false;
                                                                              }
  
                                                                              if (!bJumpToLine820) {
                                                                                  kk = kk + inc;
                                                                                  k2 = kspan + k2;
                                                                                  if (k2 < ks) {
                                                                                      bLoopLine840 = true;
                                                                                      bJumpToLine840 = true;
                                                                                  } else {
                                                                                      bLoopLine840 = false;
                                                                                      bJumpToLine840 = false;
                                                                                  }
  
                                                                                  if (!bJumpToLine840) {
                                                                                      if (kk < ks) {
                                                                                          bLoopLine830 = true;
                                                                                          bJumpToLine830 = true;
                                                                                      } else {
                                                                                          bLoopLine830 = false;
                                                                                          bJumpToLine830 = false;
                                                                                      }
  
                                                                                      if (!bJumpToLine830)
                                                                                          jc = k3;
                                                                                  }
                                                                              }
                                                                          } while (bLoopLine840);
                                                                      }
                                                                  } while (bLoopLine830);
                                                              }
                                                          } while (bLoopLine820);
                                                      }
  
                                                      bJumpToLine890 = true;
                                                  }
  
                                                  if (!bJumpToLine890) {
                                                      //permutation for multivariate transform
                                                      do { //line850
                                                          //if (fLog!=NULL)
                                                          //fprintf(fLog, "850\fftSize");
  
                                                          bLoopLine850 = false;
                                                          bJumpToLine850 = false;
  
                                                          currentFactor = kk + jc;
  
                                                          do { //line860
                                                              //if (fLog!=NULL)
                                                              //fprintf(fLog, "860\fftSize");
  
                                                              ak = a[kk - 1];
                                                              a[kk - 1] = a[k2 - 1];
                                                              a[k2 - 1] = ak;
                                                              bk = b[kk - 1];
                                                              b[kk - 1] = b[k2 - 1];
                                                              b[k2 - 1] = bk;
                                                              kk = kk + inc;
                                                              k2 = k2 + inc;
                                                          } while (kk < currentFactor);
  
                                                          kk = kk + ks - jc;
                                                          k2 = k2 + ks - jc;
                                                          if (kk < nt) {
                                                              bLoopLine850 = true;
                                                              bJumpToLine850 = true;
                                                          } else {
                                                              bLoopLine850 = false;
                                                              bJumpToLine850 = false;
                                                          }
  
                                                          if (!bJumpToLine850) {
                                                              k2 = k2 - nt + kspan;
                                                              kk = kk - nt + jc;
                                                              if (k2 < ks) {
                                                                  bLoopLine850 = true;
                                                                  bJumpToLine850 = true;
                                                              } else {
                                                                  bLoopLine850 = false;
                                                                  bJumpToLine850 = false;
                                                              }
  
                                                              if (!bJumpToLine850) {
                                                                  do { //line870
                                                                      //if (fLog!=NULL)
                                                                      //fprintf(fLog, "870\fftSize");
  
                                                                      bLoopLine870 = false;
                                                                      bJumpToLine870 = false;
                                                                      k2 = k2 - np[jCount - 1];
                                                                      jCount = jCount + 1;
                                                                      k2 = np[jCount + 1 - 1] + k2;
                                                                      if (k2 > np[jCount - 1]) {
                                                                          bLoopLine870 = true;
                                                                          bJumpToLine870 = true;
                                                                      } else {
                                                                          bLoopLine870 = false;
                                                                          bJumpToLine870 = false;
                                                                      }
  
                                                                      if (!bJumpToLine870) {
                                                                          jCount = 1;
  
                                                                          do { //line880
                                                                              //if (fLog!=NULL)
                                                                              //fprintf(fLog, "880\fftSize");
  
                                                                              bLoopLine880 = false;
                                                                              bJumpToLine880 = false;
  
                                                                              if (kk < k2) {
                                                                                  bLoopLine850 = true;
                                                                                  bJumpToLine850 = true;
                                                                              } else {
                                                                                  bLoopLine850 = false;
                                                                                  bJumpToLine850 = false;
                                                                              }
  
                                                                              if (!bJumpToLine850) {
                                                                                  kk = kk + jc;
                                                                                  k2 = kspan + k2;
                                                                                  if (k2 < ks) {
                                                                                      bLoopLine880 = true;
                                                                                      bJumpToLine880 = true;
                                                                                  } else {
                                                                                      bLoopLine880 = false;
                                                                                      bJumpToLine880 = false;
                                                                                  }
  
                                                                                  if (!bJumpToLine880) {
                                                                                      if (kk < ks) {
                                                                                          bLoopLine870 = true;
                                                                                          bJumpToLine870 = true;
                                                                                      } else {
                                                                                          bLoopLine870 = false;
                                                                                          bJumpToLine870 = false;
                                                                                      }
  
                                                                                      if (!bJumpToLine870)
                                                                                          jc = k3;
                                                                                  }
                                                                              }
                                                                          } while (bLoopLine880);
                                                                      }
                                                                  } while (bLoopLine870);
                                                              }
                                                          }
                                                      } while (bLoopLine850);
                                                  }
  
                                                  //line890
                                                  //if (fLog!=NULL)
                                                  //fprintf(fLog, "890\fftSize");
  
                                                  bJumpToLine890 = false;
                                                  if (2 * kt + 1 >= mCount)
                                                      return;
                                                  kspnn = np[kt + 1 - 1];
                                                  //permutation for square-free factors of fftSize
                                                  jCount = mCount - kt;
                                                  nfac[jCount + 1 - 1] = 1;
  
                                                  do { //line900
                                                      //if (fLog!=NULL)
                                                      //fprintf(fLog, "900\fftSize");
  
                                                      nfac[jCount - 1] = nfac[jCount - 1] * nfac[jCount + 1 - 1];
                                                      jCount = jCount - 1;
                                                  } while (jCount != kt);
  
                                                  kt = kt + 1;
                                                  nn = nfac[kt - 1] - 1;
                                                  if (nn > maxp) {
                                                      isn = 0;
                                                      System.out.println("Array bounds exceeded within subroutine fft\fftSize");
                                                      return;
                                                  }
  
                                                  jj = 0;
                                                  jCount = 0;
                                                  bJumpToLine906 = true;
  
                                                  do {
                                                      if (!bJumpToLine906) {
                                                          //line902
                                                          //if (fLog!=NULL)
                                                          //fprintf(fLog, "902\fftSize");
  
                                                          bLoopLine902 = false;
                                                          bJumpToLine902 = false;
                                                          jj = jj - k2;
                                                          k2 = kk;
                                                          currentFactor = currentFactor + 1;
                                                          kk = nfac[currentFactor - 1];
                                                      }
  
                                                      do {
                                                          if (!bJumpToLine906) {
                                                              //line904
                                                              //if (fLog!=NULL)
                                                              //fprintf(fLog, "904\fftSize");
  
                                                              bLoopLine904 = false;
                                                              bJumpToLine904 = false;
  
                                                              jj = kk + jj;
                                                              if (jj >= k2) {
                                                                  bLoopLine902 = true;
                                                                  bJumpToLine902 = true;
                                                              } else {
                                                                  bLoopLine902 = false;
                                                                  bJumpToLine902 = false;
                                                              }
                                                          }
  
                                                          if (!bJumpToLine902 || bJumpToLine906) {
                                                              if (!bJumpToLine906)
                                                                  np[jCount - 1] = jj;
  
                                                              //line906
                                                              //if (fLog!=NULL)
                                                              //fprintf(fLog, "906\fftSize");
  
                                                              bJumpToLine906 = false;
                                                              k2 = nfac[kt - 1];
                                                              currentFactor = kt + 1;
                                                              kk = nfac[currentFactor - 1];
                                                              jCount = jCount + 1;
                                                              if (jCount <= nn) {
                                                                  bLoopLine904 = true;
                                                                  bJumpToLine904 = true;
                                                              } else {
                                                                  bLoopLine904 = false;
                                                                  bJumpToLine904 = false;
                                                              }
  
                                                              if (!bJumpToLine904) {
                                                                  //determine the permutation cycles of length greater than 1
                                                                  jCount = 0;
  
                                                                  bJumpToLine914_0 = true;
  
                                                                  do {
                                                                      if (!bJumpToLine914_0) {
                                                                          //line910
                                                                          //if (fLog!=NULL)
                                                                          //fprintf(fLog, "910\fftSize");
  
                                                                          bLoopLine910 = false;
                                                                          bJumpToLine910 = false;
                                                                          currentFactor = kk;
                                                                          kk = np[currentFactor - 1];
                                                                          np[currentFactor - 1] = -kk;
                                                                          if (kk != jCount) {
                                                                              bLoopLine910 = true;
                                                                              bJumpToLine910 = true;
                                                                          } else {
                                                                              bLoopLine910 = false;
                                                                              bJumpToLine910 = false;
                                                                          }
                                                                      }
  
                                                                      if (!bJumpToLine910 || bJumpToLine914_0) {
                                                                          if (!bJumpToLine914_0)
                                                                              k3 = kk;
  
                                                                          do { //line914
                                                                              //if (fLog!=NULL)
                                                                              //fprintf(fLog, "914\fftSize");
  
                                                                              bLoopLine914 = false;
                                                                              bJumpToLine914 = false;
                                                                              bJumpToLine914_0 = false;
  
                                                                              jCount = jCount + 1;
                                                                              kk = np[jCount - 1];
                                                                              if (kk < 0) {
                                                                                  bLoopLine914 = true;
                                                                                  bJumpToLine914 = true;
                                                                              } else {
                                                                                  bLoopLine914 = false;
                                                                                  bJumpToLine914 = false;
                                                                              }
  
                                                                              if (!bJumpToLine914) {
                                                                                  if (kk != jCount) {
                                                                                      bLoopLine910 = true;
                                                                                      bJumpToLine910 = true;
                                                                                  } else {
                                                                                      bLoopLine910 = false;
                                                                                      bJumpToLine910 = false;
                                                                                  }
  
                                                                                  if (!bJumpToLine910) {
                                                                                      np[jCount - 1] = -jCount;
                                                                                      if (jCount != nn) {
                                                                                          bLoopLine914 = true;
                                                                                          bJumpToLine914 = true;
                                                                                      } else {
                                                                                          bLoopLine914 = false;
                                                                                          bJumpToLine914 = false;
                                                                                      }
  
                                                                                      if (!bJumpToLine914) {
                                                                                          maxf = inc * maxf;
                                                                                          bJumpToLine950 = true;
                                                                                      }
                                                                                  }
                                                                              }
                                                                          } while (bLoopLine914);
                                                                      }
                                                                  } while (bLoopLine910);
  
                                                                  //reorder a and b, following the permutation cycles
                                                                  do {
                                                                      bLoopLine924 = false;
                                                                      bJumpToLine924 = false;
                                                                      if (!bJumpToLine950) {
                                                                          //line924
                                                                          //if (fLog!=NULL)
                                                                          //fprintf(fLog, "924\fftSize");
  
                                                                          jCount = jCount - 1;
                                                                          if (np[jCount - 1] < 0) {
                                                                              bLoopLine924 = true;
                                                                              bJumpToLine924 = true;
                                                                          } else {
                                                                              bLoopLine924 = false;
                                                                              bJumpToLine924 = false;
                                                                          }
  
                                                                          if (!bJumpToLine924) {
                                                                              jj = jc;
  
                                                                              do { //line926
                                                                                  //if (fLog!=NULL)
                                                                                  //fprintf(fLog, "926\fftSize");
  
                                                                                  kspan = jj;
                                                                                  if (jj > maxf)
                                                                                      kspan = maxf;
                                                                                  jj = jj - kspan;
                                                                                  currentFactor = np[jCount - 1];
                                                                                  kk = jc * currentFactor + factInd + jj;
                                                                                  k1 = kk + kspan;
                                                                                  k2 = 0;
  
                                                                                  do { //line928
                                                                                      //if (fLog!=NULL)
                                                                                      //fprintf(fLog, "928\fftSize");
  
                                                                                      k2 = k2 + 1;
                                                                                      at[k2 - 1] = a[k1 - 1];
                                                                                      bt[k2 - 1] = b[k1 - 1];
                                                                                      k1 = k1 - inc;
                                                                                  } while (k1 != kk);
  
                                                                                  do { //line932
                                                                                      //if (fLog!=NULL)
                                                                                      //fprintf(fLog, "932\fftSize");
  
                                                                                      k1 = kk + kspan;
                                                                                      k2 = k1 - jc * (currentFactor + np[currentFactor - 1]);
                                                                                      currentFactor = -np[currentFactor - 1];
  
                                                                                      do { //line936
                                                                                          //if (fLog!=NULL)
                                                                                          //fprintf(fLog, "936\fftSize");
  
                                                                                          a[k1 - 1] = a[k2 - 1];
                                                                                          b[k1 - 1] = b[k2 - 1];
                                                                                          k1 = k1 - inc;
                                                                                          k2 = k2 - inc;
                                                                                      }
                                                                                      while (k1 != kk);
  
                                                                                      kk = k2;
                                                                                  }
                                                                                  while (currentFactor != jCount);
  
                                                                                  k1 = kk + kspan;
                                                                                  k2 = 0;
  
                                                                                  do { //line940
                                                                                      //if (fLog!=NULL)
                                                                                      //fprintf(fLog, "940\fftSize");
  
                                                                                      k2 = k2 + 1;
                                                                                      a[k1 - 1] = at[k2 - 1];
                                                                                      b[k1 - 1] = bt[k2 - 1];
                                                                                      k1 = k1 - inc;
                                                                                  } while (k1 != kk);
                                                                              } while (jj != 0);
  
                                                                              if (jCount != 1) {
                                                                                  bLoopLine924 = true;
                                                                                  bJumpToLine924 = true;
                                                                              } else {
                                                                                  bLoopLine924 = false;
                                                                                  bJumpToLine924 = false;
                                                                              }
                                                                          }
                                                                      }
  
                                                                      if (bJumpToLine950 || !bJumpToLine924) {
                                                                          //line950
                                                                          //if (fLog!=NULL)
                                                                          //fprintf(fLog, "950\fftSize");
  
                                                                          bJumpToLine950 = false;
                                                                          jCount = k3 + 1;
                                                                          nt = nt - kspnn;
                                                                          factInd = nt - inc + 1;
                                                                          if (nt >= 0) {
                                                                              bLoopLine924 = true;
                                                                              bJumpToLine924 = true;
                                                                          } else {
                                                                              bLoopLine924 = false;
                                                                              bJumpToLine924 = false;
                                                                          }
                                                                      }
                                                                  } while (bLoopLine924);
                                                              }
                                                          }
                                                      } while (bLoopLine904);
                                                  } while (bLoopLine902);
                                              }
                                          }
                                      }
                                  }
                              } while (bLoopLine510);
                          }
                      }
                  } while (bLoopLine320);
              }
          } while (bLoopLine100);
      }
  
      // Run a random number of tests:
      // By creating a real-valued sequence of random size filled in with random values
      // Taking a random point FFT (fftSize>=total real points)
      // Taking a random point IFFT (ifftSize>=total real points)
      // Comparing the original random real sequence with the IFFT output
      public static void test_fft_ifft_real_random() {
          String strMessage;
  
          int i, fftSize, ifftSize;
          int totalPoints = (int) (10 * Math.random() + 50);
          int[] numPoints = new int[totalPoints];
  
          for (i = 0; i < totalPoints; i++)
              numPoints[i] = (int) (6000 * Math.random() + 23);
  
          for (i = 0; i < totalPoints; i++) {
              fftSize = numPoints[i] + (int) (100 * Math.random());
              ifftSize = numPoints[i] + (int) (100 * Math.random());
  
              double[] x = new double[numPoints[i]];
  
              for (int j = 0; j < numPoints[i]; j++)
                  x[j] = 40000 * (Math.random() - 0.5);
  
              ComplexArray h = fftReal(x, numPoints[i], fftSize);
  
              strMessage = fftSize + "-point FFT computed from " + numPoints[i] + " random real values...";
              System.out.println(strMessage);
  
              double[] y = ifftReal(h, ifftSize);
  
              strMessage = ifftSize + "-point IFFT computed...";
              System.out.println(strMessage);
  
              for (int j = 0; j < numPoints[i]; j++) {
                  if (Math.abs(x[j] - y[j]) > 1e-4)
                      System.out.println("Detected difference...");
              }
  
              strMessage = "Test #" + (i + 1) + " of " + totalPoints + " complete for " + numPoints[i] + " random values...\n";
              System.out.println(strMessage);
          }
      }
  
      /**
       * @param args
       */
      public static void main(String[] args) {
          test_fft_ifft_real_random();
      }
  
  }
  
  