/*
fftpack.c : A set of FFT routines in C.
Algorithmically based on Fortran-77 FFTPACK by Paul N. Swarztrauber (Version 4, 1985).

*/

/* isign is +1 for backward and -1 for forward transforms */

#include <math.h>
#include <stdio.h>
#define DOUBLE

#ifdef DOUBLE
#define Treal double
#else
#define Treal float
#endif


#define ref(u,a) u[a]

#define MAXFAC 13    /* maximum number of factors in factorization of n */
#define NSPECIAL 4   /* number of factors for which we have special-case routines */

#ifdef __cplusplus
extern "C" {
#endif


/* ----------------------------------------------------------------------
   passf2, passf3, passf4, passf5, passf. Complex FFT passes fwd and bwd.
---------------------------------------------------------------------- */

static void passf2(int ido, int l1, const Treal cc[], Treal ch[], const Treal wa1[], int isign)
  /* isign==+1 for backward transform */
  {
    int i, k, ah, ac;
    Treal ti2, tr2;
    if (ido <= 2) {
      for (k=0; k<l1; k++) {
        ah = k*ido;
        ac = 2*k*ido;
        ch[ah]              = ref(cc,ac) + ref(cc,ac + ido);
        ch[ah + ido*l1]     = ref(cc,ac) - ref(cc,ac + ido);
        ch[ah+1]            = ref(cc,ac+1) + ref(cc,ac + ido + 1);
        ch[ah + ido*l1 + 1] = ref(cc,ac+1) - ref(cc,ac + ido + 1);
      }
    } else {
      for (k=0; k<l1; k++) {
        for (i=0; i<ido-1; i+=2) {
          ah = i + k*ido;
          ac = i + 2*k*ido;
          ch[ah]   = ref(cc,ac) + ref(cc,ac + ido);
          tr2      = ref(cc,ac) - ref(cc,ac + ido);
          ch[ah+1] = ref(cc,ac+1) + ref(cc,ac + 1 + ido);
          ti2      = ref(cc,ac+1) - ref(cc,ac + 1 + ido);
          ch[ah+l1*ido+1] = wa1[i]*ti2 + isign*wa1[i+1]*tr2;
          ch[ah+l1*ido]   = wa1[i]*tr2 - isign*wa1[i+1]*ti2;
        }
      }
    }
  } /* passf2 */


static void passf3(int ido, int l1, const Treal cc[], Treal ch[],
      const Treal wa1[], const Treal wa2[], int isign)
  /* isign==+1 for backward transform */
  {
    static const Treal taur = -0.5;
    static const Treal taui = 0.866025403784439;
    int i, k, ac, ah;
    Treal ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
    if (ido == 2) {
      for (k=1; k<=l1; k++) {
        ac = (3*k - 2)*ido;
        tr2 = ref(cc,ac) + ref(cc,ac + ido);
        cr2 = ref(cc,ac - ido) + taur*tr2;
        ah = (k - 1)*ido;
        ch[ah] = ref(cc,ac - ido) + tr2;

        ti2 = ref(cc,ac + 1) + ref(cc,ac + ido + 1);
        ci2 = ref(cc,ac - ido + 1) + taur*ti2;
        ch[ah + 1] = ref(cc,ac - ido + 1) + ti2;

        cr3 = isign*taui*(ref(cc,ac) - ref(cc,ac + ido));
        ci3 = isign*taui*(ref(cc,ac + 1) - ref(cc,ac + ido + 1));
        ch[ah + l1*ido] = cr2 - ci3;
        ch[ah + 2*l1*ido] = cr2 + ci3;
        ch[ah + l1*ido + 1] = ci2 + cr3;
        ch[ah + 2*l1*ido + 1] = ci2 - cr3;
      }
    } else {
      for (k=1; k<=l1; k++) {
        for (i=0; i<ido-1; i+=2) {
          ac = i + (3*k - 2)*ido;
          tr2 = ref(cc,ac) + ref(cc,ac + ido);
          cr2 = ref(cc,ac - ido) + taur*tr2;
          ah = i + (k-1)*ido;
          ch[ah] = ref(cc,ac - ido) + tr2;
          ti2 = ref(cc,ac + 1) + ref(cc,ac + ido + 1);
          ci2 = ref(cc,ac - ido + 1) + taur*ti2;
          ch[ah + 1] = ref(cc,ac - ido + 1) + ti2;
          cr3 = isign*taui*(ref(cc,ac) - ref(cc,ac + ido));
          ci3 = isign*taui*(ref(cc,ac + 1) - ref(cc,ac + ido + 1));
          dr2 = cr2 - ci3;
          dr3 = cr2 + ci3;
          di2 = ci2 + cr3;
          di3 = ci2 - cr3;
          ch[ah + l1*ido + 1] = wa1[i]*di2 + isign*wa1[i+1]*dr2;
          ch[ah + l1*ido] = wa1[i]*dr2 - isign*wa1[i+1]*di2;
          ch[ah + 2*l1*ido + 1] = wa2[i]*di3 + isign*wa2[i+1]*dr3;
          ch[ah + 2*l1*ido] = wa2[i]*dr3 - isign*wa2[i+1]*di3;
        }
      }
    }
  } /* passf3 */


static void passf4(int ido, int l1, const Treal cc[], Treal ch[],
      const Treal wa1[], const Treal wa2[], const Treal wa3[], int isign)
  /* isign == -1 for forward transform and +1 for backward transform */
  {
    int i, k, ac, ah;
    Treal ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
    if (ido == 2) {
      for (k=0; k<l1; k++) {
        ac = 4*k*ido + 1;
        ti1 = ref(cc,ac) - ref(cc,ac + 2*ido);
        ti2 = ref(cc,ac) + ref(cc,ac + 2*ido);
        tr4 = ref(cc,ac + 3*ido) - ref(cc,ac + ido);
        ti3 = ref(cc,ac + ido) + ref(cc,ac + 3*ido);
        tr1 = ref(cc,ac - 1) - ref(cc,ac + 2*ido - 1);
        tr2 = ref(cc,ac - 1) + ref(cc,ac + 2*ido - 1);
        ti4 = ref(cc,ac + ido - 1) - ref(cc,ac + 3*ido - 1);
        tr3 = ref(cc,ac + ido - 1) + ref(cc,ac + 3*ido - 1);
        ah = k*ido;
        ch[ah] = tr2 + tr3;
        ch[ah + 2*l1*ido] = tr2 - tr3;
        ch[ah + 1] = ti2 + ti3;
        ch[ah + 2*l1*ido + 1] = ti2 - ti3;
        ch[ah + l1*ido] = tr1 + isign*tr4;
        ch[ah + 3*l1*ido] = tr1 - isign*tr4;
        ch[ah + l1*ido + 1] = ti1 + isign*ti4;
        ch[ah + 3*l1*ido + 1] = ti1 - isign*ti4;
      }
    } else {
      for (k=0; k<l1; k++) {
        for (i=0; i<ido-1; i+=2) {
          ac = i + 1 + 4*k*ido;
          ti1 = ref(cc,ac) - ref(cc,ac + 2*ido);
          ti2 = ref(cc,ac) + ref(cc,ac + 2*ido);
          ti3 = ref(cc,ac + ido) + ref(cc,ac + 3*ido);
          tr4 = ref(cc,ac + 3*ido) - ref(cc,ac + ido);
          tr1 = ref(cc,ac - 1) - ref(cc,ac + 2*ido - 1);
          tr2 = ref(cc,ac - 1) + ref(cc,ac + 2*ido - 1);
          ti4 = ref(cc,ac + ido - 1) - ref(cc,ac + 3*ido - 1);
          tr3 = ref(cc,ac + ido - 1) + ref(cc,ac + 3*ido - 1);
          ah = i + k*ido;
          ch[ah] = tr2 + tr3;
          cr3 = tr2 - tr3;
          ch[ah + 1] = ti2 + ti3;
          ci3 = ti2 - ti3;
          cr2 = tr1 + isign*tr4;
          cr4 = tr1 - isign*tr4;
          ci2 = ti1 + isign*ti4;
          ci4 = ti1 - isign*ti4;
          ch[ah + l1*ido] = wa1[i]*cr2 - isign*wa1[i + 1]*ci2;
          ch[ah + l1*ido + 1] = wa1[i]*ci2 + isign*wa1[i + 1]*cr2;
          ch[ah + 2*l1*ido] = wa2[i]*cr3 - isign*wa2[i + 1]*ci3;
          ch[ah + 2*l1*ido + 1] = wa2[i]*ci3 + isign*wa2[i + 1]*cr3;
          ch[ah + 3*l1*ido] = wa3[i]*cr4 -isign*wa3[i + 1]*ci4;
          ch[ah + 3*l1*ido + 1] = wa3[i]*ci4 + isign*wa3[i + 1]*cr4;
        }
      }
    }
  } /* passf4 */


static void passf5(int ido, int l1, const Treal cc[], Treal ch[],
      const Treal wa1[], const Treal wa2[], const Treal wa3[], const Treal wa4[], int isign)
  /* isign == -1 for forward transform and +1 for backward transform */
  {
    static const Treal tr11 = 0.309016994374947;
    static const Treal ti11 = 0.951056516295154;
    static const Treal tr12 = -0.809016994374947;
    static const Treal ti12 = 0.587785252292473;
    int i, k, ac, ah;
    Treal ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3,
        ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
    if (ido == 2) {
      for (k = 1; k <= l1; ++k) {
        ac = (5*k - 4)*ido + 1;
        ti5 = ref(cc,ac) - ref(cc,ac + 3*ido);
        ti2 = ref(cc,ac) + ref(cc,ac + 3*ido);
        ti4 = ref(cc,ac + ido) - ref(cc,ac + 2*ido);
        ti3 = ref(cc,ac + ido) + ref(cc,ac + 2*ido);
        tr5 = ref(cc,ac - 1) - ref(cc,ac + 3*ido - 1);
        tr2 = ref(cc,ac - 1) + ref(cc,ac + 3*ido - 1);
        tr4 = ref(cc,ac + ido - 1) - ref(cc,ac + 2*ido - 1);
        tr3 = ref(cc,ac + ido - 1) + ref(cc,ac + 2*ido - 1);
        ah = (k - 1)*ido;
        ch[ah] = ref(cc,ac - ido - 1) + tr2 + tr3;
        ch[ah + 1] = ref(cc,ac - ido) + ti2 + ti3;
        cr2 = ref(cc,ac - ido - 1) + tr11*tr2 + tr12*tr3;
        ci2 = ref(cc,ac - ido) + tr11*ti2 + tr12*ti3;
        cr3 = ref(cc,ac - ido - 1) + tr12*tr2 + tr11*tr3;
        ci3 = ref(cc,ac - ido) + tr12*ti2 + tr11*ti3;
        cr5 = isign*(ti11*tr5 + ti12*tr4);
        ci5 = isign*(ti11*ti5 + ti12*ti4);
        cr4 = isign*(ti12*tr5 - ti11*tr4);
        ci4 = isign*(ti12*ti5 - ti11*ti4);
        ch[ah + l1*ido] = cr2 - ci5;
        ch[ah + 4*l1*ido] = cr2 + ci5;
        ch[ah + l1*ido + 1] = ci2 + cr5;
        ch[ah + 2*l1*ido + 1] = ci3 + cr4;
        ch[ah + 2*l1*ido] = cr3 - ci4;
        ch[ah + 3*l1*ido] = cr3 + ci4;
        ch[ah + 3*l1*ido + 1] = ci3 - cr4;
        ch[ah + 4*l1*ido + 1] = ci2 - cr5;
      }
    } else {
      for (k=1; k<=l1; k++) {
        for (i=0; i<ido-1; i+=2) {
          ac = i + 1 + (k*5 - 4)*ido;
          ti5 = ref(cc,ac) - ref(cc,ac + 3*ido);
          ti2 = ref(cc,ac) + ref(cc,ac + 3*ido);
          ti4 = ref(cc,ac + ido) - ref(cc,ac + 2*ido);
          ti3 = ref(cc,ac + ido) + ref(cc,ac + 2*ido);
          tr5 = ref(cc,ac - 1) - ref(cc,ac + 3*ido - 1);
          tr2 = ref(cc,ac - 1) + ref(cc,ac + 3*ido - 1);
          tr4 = ref(cc,ac + ido - 1) - ref(cc,ac + 2*ido - 1);
          tr3 = ref(cc,ac + ido - 1) + ref(cc,ac + 2*ido - 1);
          ah = i + (k - 1)*ido;
          ch[ah] = ref(cc,ac - ido - 1) + tr2 + tr3;
          ch[ah + 1] = ref(cc,ac - ido) + ti2 + ti3;
          cr2 = ref(cc,ac - ido - 1) + tr11*tr2 + tr12*tr3;

          ci2 = ref(cc,ac - ido) + tr11*ti2 + tr12*ti3;
          cr3 = ref(cc,ac - ido - 1) + tr12*tr2 + tr11*tr3;

          ci3 = ref(cc,ac - ido) + tr12*ti2 + tr11*ti3;
          cr5 = isign*(ti11*tr5 + ti12*tr4);
          ci5 = isign*(ti11*ti5 + ti12*ti4);
          cr4 = isign*(ti12*tr5 - ti11*tr4);
          ci4 = isign*(ti12*ti5 - ti11*ti4);
          dr3 = cr3 - ci4;
          dr4 = cr3 + ci4;
          di3 = ci3 + cr4;
          di4 = ci3 - cr4;
          dr5 = cr2 + ci5;
          dr2 = cr2 - ci5;
          di5 = ci2 - cr5;
          di2 = ci2 + cr5;
          ch[ah + l1*ido] = wa1[i]*dr2 - isign*wa1[i+1]*di2;
          ch[ah + l1*ido + 1] = wa1[i]*di2 + isign*wa1[i+1]*dr2;
          ch[ah + 2*l1*ido] = wa2[i]*dr3 - isign*wa2[i+1]*di3;
          ch[ah + 2*l1*ido + 1] = wa2[i]*di3 + isign*wa2[i+1]*dr3;
          ch[ah + 3*l1*ido] = wa3[i]*dr4 - isign*wa3[i+1]*di4;
          ch[ah + 3*l1*ido + 1] = wa3[i]*di4 + isign*wa3[i+1]*dr4;
          ch[ah + 4*l1*ido] = wa4[i]*dr5 - isign*wa4[i+1]*di5;
          ch[ah + 4*l1*ido + 1] = wa4[i]*di5 + isign*wa4[i+1]*dr5;
        }
      }
    }
  } /* passf5 */


static void passf(int *nac, int ido, int ip, int l1, int idl1,
      Treal cc[], Treal ch[],
      const Treal wa[], int isign)
  /* isign is -1 for forward transform and +1 for backward transform */
  {
    int idij, idlj, idot, ipph, i, j, k, l, jc, lc, ik, idj, idl, inc,idp;
    Treal wai, war;

    idot = ido / 2;
    /* nt = ip*idl1;*/
    ipph = (ip + 1) / 2;
    idp = ip*ido;
    if (ido >= l1) {
      for (j=1; j<ipph; j++) {
        jc = ip - j;
        for (k=0; k<l1; k++) {
          for (i=0; i<ido; i++) {
            ch[i + (k + j*l1)*ido] =
                ref(cc,i + (j + k*ip)*ido) + ref(cc,i + (jc + k*ip)*ido);
            ch[i + (k + jc*l1)*ido] =
                ref(cc,i + (j + k*ip)*ido) - ref(cc,i + (jc + k*ip)*ido);
          }
        }
      }
      for (k=0; k<l1; k++)
        for (i=0; i<ido; i++)
          ch[i + k*ido] = ref(cc,i + k*ip*ido);
    } else {
      for (j=1; j<ipph; j++) {
        jc = ip - j;
        for (i=0; i<ido; i++) {
          for (k=0; k<l1; k++) {
            ch[i + (k + j*l1)*ido] = ref(cc,i + (j + k*ip)*ido) + ref(cc,i + (jc + k*
                ip)*ido);
            ch[i + (k + jc*l1)*ido] = ref(cc,i + (j + k*ip)*ido) - ref(cc,i + (jc + k*
                ip)*ido);
          }
        }
      }
      for (i=0; i<ido; i++)
        for (k=0; k<l1; k++)
          ch[i + k*ido] = ref(cc,i + k*ip*ido);
    }

    idl = 2 - ido;
    inc = 0;
    for (l=1; l<ipph; l++) {
      lc = ip - l;
      idl += ido;
      for (ik=0; ik<idl1; ik++) {
        cc[ik + l*idl1] = ch[ik] + wa[idl - 2]*ch[ik + idl1];
        cc[ik + lc*idl1] = isign*wa[idl-1]*ch[ik + (ip-1)*idl1];
      }
      idlj = idl;
      inc += ido;
      for (j=2; j<ipph; j++) {
        jc = ip - j;
        idlj += inc;
        if (idlj > idp) idlj -= idp;
        war = wa[idlj - 2];
        wai = wa[idlj-1];
        for (ik=0; ik<idl1; ik++) {
          cc[ik + l*idl1] += war*ch[ik + j*idl1];
          cc[ik + lc*idl1] += isign*wai*ch[ik + jc*idl1];
        }
      }
    }
    for (j=1; j<ipph; j++)
      for (ik=0; ik<idl1; ik++)
        ch[ik] += ch[ik + j*idl1];
    for (j=1; j<ipph; j++) {
      jc = ip - j;
      for (ik=1; ik<idl1; ik+=2) {
        ch[ik - 1 + j*idl1] = cc[ik - 1 + j*idl1] - cc[ik + jc*idl1];
        ch[ik - 1 + jc*idl1] = cc[ik - 1 + j*idl1] + cc[ik + jc*idl1];
        ch[ik + j*idl1] = cc[ik + j*idl1] + cc[ik - 1 + jc*idl1];
        ch[ik + jc*idl1] = cc[ik + j*idl1] - cc[ik - 1 + jc*idl1];
      }
    }
    *nac = 1;
    if (ido == 2) return;
    *nac = 0;
    for (ik=0; ik<idl1; ik++)
      cc[ik] = ch[ik];
    for (j=1; j<ip; j++) {
      for (k=0; k<l1; k++) {
        cc[(k + j*l1)*ido + 0] = ch[(k + j*l1)*ido + 0];
        cc[(k + j*l1)*ido + 1] = ch[(k + j*l1)*ido + 1];
      }
    }
    if (idot <= l1) {
      idij = 0;
      for (j=1; j<ip; j++) {
        idij += 2;
        for (i=3; i<ido; i+=2) {
          idij += 2;
          for (k=0; k<l1; k++) {
            cc[i - 1 + (k + j*l1)*ido] =
                wa[idij - 2]*ch[i - 1 + (k + j*l1)*ido] -
                isign*wa[idij-1]*ch[i + (k + j*l1)*ido];
            cc[i + (k + j*l1)*ido] =
                wa[idij - 2]*ch[i + (k + j*l1)*ido] +
                isign*wa[idij-1]*ch[i - 1 + (k + j*l1)*ido];
          }
        }
      }
    } else {
      idj = 2 - ido;
      for (j=1; j<ip; j++) {
        idj += ido;
        for (k = 0; k < l1; k++) {
          idij = idj;
          for (i=3; i<ido; i+=2) {
            idij += 2;
            cc[i - 1 + (k + j*l1)*ido] =
                wa[idij - 2]*ch[i - 1 + (k + j*l1)*ido] -
                isign*wa[idij-1]*ch[i + (k + j*l1)*ido];
            cc[i + (k + j*l1)*ido] =
                wa[idij - 2]*ch[i + (k + j*l1)*ido] +
                isign*wa[idij-1]*ch[i - 1 + (k + j*l1)*ido];
          }
        }
      }
    }
  } /* passf */


  /* ----------------------------------------------------------------------
radf2,radb2, radf3,radb3, radf4,radb4, radf5,radb5, radfg,radbg.
Treal FFT passes fwd and bwd.
---------------------------------------------------------------------- */

static void radf2(int ido, int l1, const Treal cc[], Treal ch[], const Treal wa1[])
  {
    int i, k, ic;
    Treal ti2, tr2;
    for (k=0; k<l1; k++) {
      ch[2*k*ido] =
          ref(cc,k*ido) + ref(cc,(k + l1)*ido);
      ch[(2*k+1)*ido + ido-1] =
          ref(cc,k*ido) - ref(cc,(k + l1)*ido);
    }
    if (ido < 2) return;
    if (ido != 2) {
      for (k=0; k<l1; k++) {
        for (i=2; i<ido; i+=2) {
          ic = ido - i;
          tr2 = wa1[i - 2]*ref(cc, i-1 + (k + l1)*ido) + wa1[i - 1]*ref(cc, i + (k + l1)*ido);
          ti2 = wa1[i - 2]*ref(cc, i + (k + l1)*ido) - wa1[i - 1]*ref(cc, i-1 + (k + l1)*ido);
          ch[i + 2*k*ido] = ref(cc,i + k*ido) + ti2;
          ch[ic + (2*k+1)*ido] = ti2 - ref(cc,i + k*ido);
          ch[i - 1 + 2*k*ido] = ref(cc,i - 1 + k*ido) + tr2;
          ch[ic - 1 + (2*k+1)*ido] = ref(cc,i - 1 + k*ido) - tr2;
        }
      }
      if (ido % 2 == 1) return;
    }
    for (k=0; k<l1; k++) {
      ch[(2*k+1)*ido] = -ref(cc,ido-1 + (k + l1)*ido);
      ch[ido-1 + 2*k*ido] = ref(cc,ido-1 + k*ido);
    }
  } /* radf2 */


static void radb2(int ido, int l1, const Treal cc[], Treal ch[], const Treal wa1[])
  {
    int i, k, ic;
    Treal ti2, tr2;
    for (k=0; k<l1; k++) {
      ch[k*ido] =
          ref(cc,2*k*ido) + ref(cc,ido-1 + (2*k+1)*ido);
      ch[(k + l1)*ido] =
          ref(cc,2*k*ido) - ref(cc,ido-1 + (2*k+1)*ido);
    }
    if (ido < 2) return;
    if (ido != 2) {
      for (k = 0; k < l1; ++k) {
        for (i = 2; i < ido; i += 2) {
          ic = ido - i;
          ch[i-1 + k*ido] =
              ref(cc,i-1 + 2*k*ido) + ref(cc,ic-1 + (2*k+1)*ido);
          tr2 = ref(cc,i-1 + 2*k*ido) - ref(cc,ic-1 + (2*k+1)*ido);
          ch[i + k*ido] =
              ref(cc,i + 2*k*ido) - ref(cc,ic + (2*k+1)*ido);
          ti2 = ref(cc,i + (2*k)*ido) + ref(cc,ic + (2*k+1)*ido);
          ch[i-1 + (k + l1)*ido] =
              wa1[i - 2]*tr2 - wa1[i - 1]*ti2;
          ch[i + (k + l1)*ido] =
              wa1[i - 2]*ti2 + wa1[i - 1]*tr2;
        }
      }
      if (ido % 2 == 1) return;
    }
    for (k = 0; k < l1; k++) {
      ch[ido-1 + k*ido] = 2*ref(cc,ido-1 + 2*k*ido);
      ch[ido-1 + (k + l1)*ido] = -2*ref(cc,(2*k+1)*ido);
    }
  } /* radb2 */


static void radf3(int ido, int l1, const Treal cc[], Treal ch[],
      const Treal wa1[], const Treal wa2[])
  {
    static const Treal taur = -0.5;
    static const Treal taui = 0.866025403784439;
    int i, k, ic;
    Treal ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3;
    for (k=0; k<l1; k++) {
      cr2 = ref(cc,(k + l1)*ido) + ref(cc,(k + 2*l1)*ido);
      ch[3*k*ido] = ref(cc,k*ido) + cr2;
      ch[(3*k+2)*ido] = taui*(ref(cc,(k + l1*2)*ido) - ref(cc,(k + l1)*ido));
      ch[ido-1 + (3*k + 1)*ido] = ref(cc,k*ido) + taur*cr2;
    }
    if (ido == 1) return;
    for (k=0; k<l1; k++) {
      for (i=2; i<ido; i+=2) {
        ic = ido - i;
        dr2 = wa1[i - 2]*ref(cc,i - 1 + (k + l1)*ido) +
            wa1[i - 1]*ref(cc,i + (k + l1)*ido);
        di2 = wa1[i - 2]*ref(cc,i + (k + l1)*ido) - wa1[i - 1]*ref(cc,i - 1 + (k + l1)*ido);
        dr3 = wa2[i - 2]*ref(cc,i - 1 + (k + l1*2)*ido) + wa2[i - 1]*ref(cc,i + (k + l1*2)*ido);
        di3 = wa2[i - 2]*ref(cc,i + (k + l1*2)*ido) - wa2[i - 1]*ref(cc,i - 1 + (k + l1*2)*ido);
        cr2 = dr2 + dr3;
        ci2 = di2 + di3;
        ch[i - 1 + 3*k*ido] = ref(cc,i - 1 + k*ido) + cr2;
        ch[i + 3*k*ido] = ref(cc,i + k*ido) + ci2;
        tr2 = ref(cc,i - 1 + k*ido) + taur*cr2;
        ti2 = ref(cc,i + k*ido) + taur*ci2;
        tr3 = taui*(di2 - di3);
        ti3 = taui*(dr3 - dr2);
        ch[i - 1 + (3*k + 2)*ido] = tr2 + tr3;
        ch[ic - 1 + (3*k + 1)*ido] = tr2 - tr3;
        ch[i + (3*k + 2)*ido] = ti2 + ti3;
        ch[ic + (3*k + 1)*ido] = ti3 - ti2;
      }
    }
  } /* radf3 */


static void radb3(int ido, int l1, const Treal cc[], Treal ch[],
      const Treal wa1[], const Treal wa2[])
  {
    static const Treal taur = -0.5;
    static const Treal taui = 0.866025403784439;
    int i, k, ic;
    Treal ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2;
    for (k=0; k<l1; k++) {
      tr2 = 2*ref(cc,ido-1 + (3*k + 1)*ido);
      cr2 = ref(cc,3*k*ido) + taur*tr2;
      ch[k*ido] = ref(cc,3*k*ido) + tr2;
      ci3 = 2*taui*ref(cc,(3*k + 2)*ido);
      ch[(k + l1)*ido] = cr2 - ci3;
      ch[(k + 2*l1)*ido] = cr2 + ci3;
    }
    if (ido == 1) return;
    for (k=0; k<l1; k++) {
      for (i=2; i<ido; i+=2) {
        ic = ido - i;
        tr2 = ref(cc,i - 1 + (3*k + 2)*ido) + ref(cc,ic - 1 + (3*k + 1)*ido);
        cr2 = ref(cc,i - 1 + 3*k*ido) + taur*tr2;
        ch[i - 1 + k*ido] = ref(cc,i - 1 + 3*k*ido) + tr2;
        ti2 = ref(cc,i + (3*k + 2)*ido) - ref(cc,ic + (3*k + 1)*ido);
        ci2 = ref(cc,i + 3*k*ido) + taur*ti2;
        ch[i + k*ido] = ref(cc,i + 3*k*ido) + ti2;
        cr3 = taui*(ref(cc,i - 1 + (3*k + 2)*ido) - ref(cc,ic - 1 + (3*k + 1)*ido));
        ci3 = taui*(ref(cc,i + (3*k + 2)*ido) + ref(cc,ic + (3*k + 1)*ido));
        dr2 = cr2 - ci3;
        dr3 = cr2 + ci3;
        di2 = ci2 + cr3;
        di3 = ci2 - cr3;
        ch[i - 1 + (k + l1)*ido] = wa1[i - 2]*dr2 - wa1[i - 1]*di2;
        ch[i + (k + l1)*ido] = wa1[i - 2]*di2 + wa1[i - 1]*dr2;
        ch[i - 1 + (k + 2*l1)*ido] = wa2[i - 2]*dr3 - wa2[i - 1]*di3;
        ch[i + (k + 2*l1)*ido] = wa2[i - 2]*di3 + wa2[i - 1]*dr3;
      }
    }
  } /* radb3 */


static void radf4(int ido, int l1, const Treal cc[], Treal ch[],
      const Treal wa1[], const Treal wa2[], const Treal wa3[])
  {
    static const Treal hsqt2 = 0.7071067811865475;
    int i, k, ic;
    Treal ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
    for (k=0; k<l1; k++) {
      tr1 = ref(cc,(k + l1)*ido) + ref(cc,(k + 3*l1)*ido);
      tr2 = ref(cc,k*ido) + ref(cc,(k + 2*l1)*ido);
      ch[4*k*ido] = tr1 + tr2;
      ch[ido-1 + (4*k + 3)*ido] = tr2 - tr1;
      ch[ido-1 + (4*k + 1)*ido] = ref(cc,k*ido) - ref(cc,(k + 2*l1)*ido);
      ch[(4*k + 2)*ido] = ref(cc,(k + 3*l1)*ido) - ref(cc,(k + l1)*ido);
    }
    if (ido < 2) return;
    if (ido != 2) {
      for (k=0; k<l1; k++) {
        for (i=2; i<ido; i += 2) {
          ic = ido - i;
          cr2 = wa1[i - 2]*ref(cc,i - 1 + (k + l1)*ido) + wa1[i - 1]*ref(cc,i + (k + l1)*ido);
          ci2 = wa1[i - 2]*ref(cc,i + (k + l1)*ido) - wa1[i - 1]*ref(cc,i - 1 + (k + l1)*ido);
          cr3 = wa2[i - 2]*ref(cc,i - 1 + (k + 2*l1)*ido) + wa2[i - 1]*ref(cc,i + (k + 2*l1)*
              ido);
          ci3 = wa2[i - 2]*ref(cc,i + (k + 2*l1)*ido) - wa2[i - 1]*ref(cc,i - 1 + (k + 2*l1)*
              ido);
          cr4 = wa3[i - 2]*ref(cc,i - 1 + (k + 3*l1)*ido) + wa3[i - 1]*ref(cc,i + (k + 3*l1)*
              ido);
          ci4 = wa3[i - 2]*ref(cc,i + (k + 3*l1)*ido) - wa3[i - 1]*ref(cc,i - 1 + (k + 3*l1)*
              ido);
          tr1 = cr2 + cr4;
          tr4 = cr4 - cr2;
          ti1 = ci2 + ci4;
          ti4 = ci2 - ci4;
          ti2 = ref(cc,i + k*ido) + ci3;
          ti3 = ref(cc,i + k*ido) - ci3;
          tr2 = ref(cc,i - 1 + k*ido) + cr3;
          tr3 = ref(cc,i - 1 + k*ido) - cr3;
          ch[i - 1 + 4*k*ido] = tr1 + tr2;
          ch[ic - 1 + (4*k + 3)*ido] = tr2 - tr1;
          ch[i + 4*k*ido] = ti1 + ti2;
          ch[ic + (4*k + 3)*ido] = ti1 - ti2;
          ch[i - 1 + (4*k + 2)*ido] = ti4 + tr3;
          ch[ic - 1 + (4*k + 1)*ido] = tr3 - ti4;
          ch[i + (4*k + 2)*ido] = tr4 + ti3;
          ch[ic + (4*k + 1)*ido] = tr4 - ti3;
        }
      }
      if (ido % 2 == 1) return;
    }
    for (k=0; k<l1; k++) {
      ti1 = -hsqt2*(ref(cc,ido-1 + (k + l1)*ido) + ref(cc,ido-1 + (k + 3*l1)*ido));
      tr1 = hsqt2*(ref(cc,ido-1 + (k + l1)*ido) - ref(cc,ido-1 + (k + 3*l1)*ido));
      ch[ido-1 + 4*k*ido] = tr1 + ref(cc,ido-1 + k*ido);
      ch[ido-1 + (4*k + 2)*ido] = ref(cc,ido-1 + k*ido) - tr1;
      ch[(4*k + 1)*ido] = ti1 - ref(cc,ido-1 + (k + 2*l1)*ido);
      ch[(4*k + 3)*ido] = ti1 + ref(cc,ido-1 + (k + 2*l1)*ido);
    }
  } /* radf4 */


static void radb4(int ido, int l1, const Treal cc[], Treal ch[],
      const Treal wa1[], const Treal wa2[], const Treal wa3[])
  {
    static const Treal sqrt2 = 1.414213562373095;
    int i, k, ic;
    Treal ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4;
    for (k = 0; k < l1; k++) {
      tr1 = ref(cc,4*k*ido) - ref(cc,ido-1 + (4*k + 3)*ido);
      tr2 = ref(cc,4*k*ido) + ref(cc,ido-1 + (4*k + 3)*ido);
      tr3 = ref(cc,ido-1 + (4*k + 1)*ido) + ref(cc,ido-1 + (4*k + 1)*ido);
      tr4 = ref(cc,(4*k + 2)*ido) + ref(cc,(4*k + 2)*ido);
      ch[k*ido] = tr2 + tr3;
      ch[(k + l1)*ido] = tr1 - tr4;
      ch[(k + 2*l1)*ido] = tr2 - tr3;
      ch[(k + 3*l1)*ido] = tr1 + tr4;
    }
    if (ido < 2) return;
    if (ido != 2) {
      for (k = 0; k < l1; ++k) {
        for (i = 2; i < ido; i += 2) {
          ic = ido - i;
          ti1 = ref(cc,i + 4*k*ido) + ref(cc,ic + (4*k + 3)*ido);
          ti2 = ref(cc,i + 4*k*ido) - ref(cc,ic + (4*k + 3)*ido);
          ti3 = ref(cc,i + (4*k + 2)*ido) - ref(cc,ic + (4*k + 1)*ido);
          tr4 = ref(cc,i + (4*k + 2)*ido) + ref(cc,ic + (4*k + 1)*ido);
          tr1 = ref(cc,i - 1 + 4*k*ido) - ref(cc,ic - 1 + (4*k + 3)*ido);
          tr2 = ref(cc,i - 1 + 4*k*ido) + ref(cc,ic - 1 + (4*k + 3)*ido);
          ti4 = ref(cc,i - 1 + (4*k + 2)*ido) - ref(cc,ic - 1 + (4*k + 1)*ido);
          tr3 = ref(cc,i - 1 + (4*k + 2)*ido) + ref(cc,ic - 1 + (4*k + 1)*ido);
          ch[i - 1 + k*ido] = tr2 + tr3;
          cr3 = tr2 - tr3;
          ch[i + k*ido] = ti2 + ti3;
          ci3 = ti2 - ti3;
          cr2 = tr1 - tr4;
          cr4 = tr1 + tr4;
          ci2 = ti1 + ti4;
          ci4 = ti1 - ti4;
          ch[i - 1 + (k + l1)*ido] = wa1[i - 2]*cr2 - wa1[i - 1]*ci2;
          ch[i + (k + l1)*ido] = wa1[i - 2]*ci2 + wa1[i - 1]*cr2;
          ch[i - 1 + (k + 2*l1)*ido] = wa2[i - 2]*cr3 - wa2[i - 1]*ci3;
          ch[i + (k + 2*l1)*ido] = wa2[i - 2]*ci3 + wa2[i - 1]*cr3;
          ch[i - 1 + (k + 3*l1)*ido] = wa3[i - 2]*cr4 - wa3[i - 1]*ci4;
          ch[i + (k + 3*l1)*ido] = wa3[i - 2]*ci4 + wa3[i - 1]*cr4;
        }
      }
      if (ido % 2 == 1) return;
    }
    for (k = 0; k < l1; k++) {
      ti1 = ref(cc,(4*k + 1)*ido) + ref(cc,(4*k + 3)*ido);
      ti2 = ref(cc,(4*k + 3)*ido) - ref(cc,(4*k + 1)*ido);
      tr1 = ref(cc,ido-1 + 4*k*ido) - ref(cc,ido-1 + (4*k + 2)*ido);
      tr2 = ref(cc,ido-1 + 4*k*ido) + ref(cc,ido-1 + (4*k + 2)*ido);
      ch[ido-1 + k*ido] = tr2 + tr2;
      ch[ido-1 + (k + l1)*ido] = sqrt2*(tr1 - ti1);
      ch[ido-1 + (k + 2*l1)*ido] = ti2 + ti2;
      ch[ido-1 + (k + 3*l1)*ido] = -sqrt2*(tr1 + ti1);
    }
  } /* radb4 */


static void radf5(int ido, int l1, const Treal cc[], Treal ch[],
      const Treal wa1[], const Treal wa2[], const Treal wa3[], const Treal wa4[])
  {
    static const Treal tr11 = 0.309016994374947;
    static const Treal ti11 = 0.951056516295154;
    static const Treal tr12 = -0.809016994374947;
    static const Treal ti12 = 0.587785252292473;
    int i, k, ic;
    Treal ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, dr4, dr5,
        cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5;
    for (k = 0; k < l1; k++) {
      cr2 = ref(cc,(k + 4*l1)*ido) + ref(cc,(k + l1)*ido);
      ci5 = ref(cc,(k + 4*l1)*ido) - ref(cc,(k + l1)*ido);
      cr3 = ref(cc,(k + 3*l1)*ido) + ref(cc,(k + 2*l1)*ido);
      ci4 = ref(cc,(k + 3*l1)*ido) - ref(cc,(k + 2*l1)*ido);
      ch[5*k*ido] = ref(cc,k*ido) + cr2 + cr3;
      ch[ido-1 + (5*k + 1)*ido] = ref(cc,k*ido) + tr11*cr2 + tr12*cr3;
      ch[(5*k + 2)*ido] = ti11*ci5 + ti12*ci4;
      ch[ido-1 + (5*k + 3)*ido] = ref(cc,k*ido) + tr12*cr2 + tr11*cr3;
      ch[(5*k + 4)*ido] = ti12*ci5 - ti11*ci4;
    }
    if (ido == 1) return;
    for (k = 0; k < l1; ++k) {
      for (i = 2; i < ido; i += 2) {
        ic = ido - i;
        dr2 = wa1[i - 2]*ref(cc,i - 1 + (k + l1)*ido) + wa1[i - 1]*ref(cc,i + (k + l1)*ido);
        di2 = wa1[i - 2]*ref(cc,i + (k + l1)*ido) - wa1[i - 1]*ref(cc,i - 1 + (k + l1)*ido);
        dr3 = wa2[i - 2]*ref(cc,i - 1 + (k + 2*l1)*ido) + wa2[i - 1]*ref(cc,i + (k + 2*l1)*ido);
        di3 = wa2[i - 2]*ref(cc,i + (k + 2*l1)*ido) - wa2[i - 1]*ref(cc,i - 1 + (k + 2*l1)*ido);
        dr4 = wa3[i - 2]*ref(cc,i - 1 + (k + 3*l1)*ido) + wa3[i - 1]*ref(cc,i + (k + 3*l1)*ido);
        di4 = wa3[i - 2]*ref(cc,i + (k + 3*l1)*ido) - wa3[i - 1]*ref(cc,i - 1 + (k + 3*l1)*ido);
        dr5 = wa4[i - 2]*ref(cc,i - 1 + (k + 4*l1)*ido) + wa4[i - 1]*ref(cc,i + (k + 4*l1)*ido);
        di5 = wa4[i - 2]*ref(cc,i + (k + 4*l1)*ido) - wa4[i - 1]*ref(cc,i - 1 + (k + 4*l1)*ido);
        cr2 = dr2 + dr5;
        ci5 = dr5 - dr2;
        cr5 = di2 - di5;
        ci2 = di2 + di5;
        cr3 = dr3 + dr4;
        ci4 = dr4 - dr3;
        cr4 = di3 - di4;
        ci3 = di3 + di4;
        ch[i - 1 + 5*k*ido] = ref(cc,i - 1 + k*ido) + cr2 + cr3;
        ch[i + 5*k*ido] = ref(cc,i + k*ido) + ci2 + ci3;
        tr2 = ref(cc,i - 1 + k*ido) + tr11*cr2 + tr12*cr3;
        ti2 = ref(cc,i + k*ido) + tr11*ci2 + tr12*ci3;
        tr3 = ref(cc,i - 1 + k*ido) + tr12*cr2 + tr11*cr3;
        ti3 = ref(cc,i + k*ido) + tr12*ci2 + tr11*ci3;
        tr5 = ti11*cr5 + ti12*cr4;
        ti5 = ti11*ci5 + ti12*ci4;
        tr4 = ti12*cr5 - ti11*cr4;
        ti4 = ti12*ci5 - ti11*ci4;
        ch[i - 1 + (5*k + 2)*ido] = tr2 + tr5;
        ch[ic - 1 + (5*k + 1)*ido] = tr2 - tr5;
        ch[i + (5*k + 2)*ido] = ti2 + ti5;
        ch[ic + (5*k + 1)*ido] = ti5 - ti2;
        ch[i - 1 + (5*k + 4)*ido] = tr3 + tr4;
        ch[ic - 1 + (5*k + 3)*ido] = tr3 - tr4;
        ch[i + (5*k + 4)*ido] = ti3 + ti4;
        ch[ic + (5*k + 3)*ido] = ti4 - ti3;
      }
    }
  } /* radf5 */


static void radb5(int ido, int l1, const Treal cc[], Treal ch[],
      const Treal wa1[], const Treal wa2[], const Treal wa3[], const Treal wa4[])
  {
    static const Treal tr11 = 0.309016994374947;
    static const Treal ti11 = 0.951056516295154;
    static const Treal tr12 = -0.809016994374947;
    static const Treal ti12 = 0.587785252292473;
    int i, k, ic;
    Treal ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3,
        ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5;
    for (k = 0; k < l1; k++) {
      ti5 = 2*ref(cc,(5*k + 2)*ido);
      ti4 = 2*ref(cc,(5*k + 4)*ido);
      tr2 = 2*ref(cc,ido-1 + (5*k + 1)*ido);
      tr3 = 2*ref(cc,ido-1 + (5*k + 3)*ido);
      ch[k*ido] = ref(cc,5*k*ido) + tr2 + tr3;
      cr2 = ref(cc,5*k*ido) + tr11*tr2 + tr12*tr3;
      cr3 = ref(cc,5*k*ido) + tr12*tr2 + tr11*tr3;
      ci5 = ti11*ti5 + ti12*ti4;
      ci4 = ti12*ti5 - ti11*ti4;
      ch[(k + l1)*ido] = cr2 - ci5;
      ch[(k + 2*l1)*ido] = cr3 - ci4;
      ch[(k + 3*l1)*ido] = cr3 + ci4;
      ch[(k + 4*l1)*ido] = cr2 + ci5;
    }
    if (ido == 1) return;
    for (k = 0; k < l1; ++k) {
      for (i = 2; i < ido; i += 2) {
        ic = ido - i;
        ti5 = ref(cc,i + (5*k + 2)*ido) + ref(cc,ic + (5*k + 1)*ido);
        ti2 = ref(cc,i + (5*k + 2)*ido) - ref(cc,ic + (5*k + 1)*ido);
        ti4 = ref(cc,i + (5*k + 4)*ido) + ref(cc,ic + (5*k + 3)*ido);
        ti3 = ref(cc,i + (5*k + 4)*ido) - ref(cc,ic + (5*k + 3)*ido);
        tr5 = ref(cc,i - 1 + (5*k + 2)*ido) - ref(cc,ic - 1 + (5*k + 1)*ido);
        tr2 = ref(cc,i - 1 + (5*k + 2)*ido) + ref(cc,ic - 1 + (5*k + 1)*ido);
        tr4 = ref(cc,i - 1 + (5*k + 4)*ido) - ref(cc,ic - 1 + (5*k + 3)*ido);
        tr3 = ref(cc,i - 1 + (5*k + 4)*ido) + ref(cc,ic - 1 + (5*k + 3)*ido);
        ch[i - 1 + k*ido] = ref(cc,i - 1 + 5*k*ido) + tr2 + tr3;
        ch[i + k*ido] = ref(cc,i + 5*k*ido) + ti2 + ti3;
        cr2 = ref(cc,i - 1 + 5*k*ido) + tr11*tr2 + tr12*tr3;

        ci2 = ref(cc,i + 5*k*ido) + tr11*ti2 + tr12*ti3;
        cr3 = ref(cc,i - 1 + 5*k*ido) + tr12*tr2 + tr11*tr3;

        ci3 = ref(cc,i + 5*k*ido) + tr12*ti2 + tr11*ti3;
        cr5 = ti11*tr5 + ti12*tr4;
        ci5 = ti11*ti5 + ti12*ti4;
        cr4 = ti12*tr5 - ti11*tr4;
        ci4 = ti12*ti5 - ti11*ti4;
        dr3 = cr3 - ci4;
        dr4 = cr3 + ci4;
        di3 = ci3 + cr4;
        di4 = ci3 - cr4;
        dr5 = cr2 + ci5;
        dr2 = cr2 - ci5;
        di5 = ci2 - cr5;
        di2 = ci2 + cr5;
        ch[i - 1 + (k + l1)*ido] = wa1[i - 2]*dr2 - wa1[i - 1]*di2;
        ch[i + (k + l1)*ido] = wa1[i - 2]*di2 + wa1[i - 1]*dr2;
        ch[i - 1 + (k + 2*l1)*ido] = wa2[i - 2]*dr3 - wa2[i - 1]*di3;
        ch[i + (k + 2*l1)*ido] = wa2[i - 2]*di3 + wa2[i - 1]*dr3;
        ch[i - 1 + (k + 3*l1)*ido] = wa3[i - 2]*dr4 - wa3[i - 1]*di4;
        ch[i + (k + 3*l1)*ido] = wa3[i - 2]*di4 + wa3[i - 1]*dr4;
        ch[i - 1 + (k + 4*l1)*ido] = wa4[i - 2]*dr5 - wa4[i - 1]*di5;
        ch[i + (k + 4*l1)*ido] = wa4[i - 2]*di5 + wa4[i - 1]*dr5;
      }
    }
  } /* radb5 */


static void radfg(int ido, int ip, int l1, int idl1,
      Treal cc[], Treal ch[], const Treal wa[])
  {
    static const Treal twopi = 6.28318530717959;
    int idij, ipph, i, j, k, l, j2, ic, jc, lc, ik, is, nbd;
    Treal dc2, ai1, ai2, ar1, ar2, ds2, dcp, arg, dsp, ar1h, ar2h;
    arg = twopi / ip;
    dcp = cos(arg);
    dsp = sin(arg);
    ipph = (ip + 1) / 2;
    nbd = (ido - 1) / 2;
    if (ido != 1) {
      for (ik=0; ik<idl1; ik++) ch[ik] = cc[ik];
      for (j=1; j<ip; j++)
        for (k=0; k<l1; k++)
          ch[(k + j*l1)*ido] = cc[(k + j*l1)*ido];
      if (nbd <= l1) {
        is = -ido;
        for (j=1; j<ip; j++) {
          is += ido;
          idij = is-1;
          for (i=2; i<ido; i+=2) {
            idij += 2;
            for (k=0; k<l1; k++) {
              ch[i - 1 + (k + j*l1)*ido] =
                  wa[idij - 1]*cc[i - 1 + (k + j*l1)*ido] + wa[idij]*cc[i + (k + j*l1)*ido];
              ch[i + (k + j*l1)*ido] =
                  wa[idij - 1]*cc[i + (k + j*l1)*ido] - wa[idij]*cc[i - 1 + (k + j*l1)*ido];
            }
          }
        }
      } else {
        is = -ido;
        for (j=1; j<ip; j++) {
          is += ido;
          for (k=0; k<l1; k++) {
            idij = is-1;
            for (i=2; i<ido; i+=2) {
              idij += 2;
              ch[i - 1 + (k + j*l1)*ido] =
                  wa[idij - 1]*cc[i - 1 + (k + j*l1)*ido] + wa[idij]*cc[i + (k + j*l1)*ido];
              ch[i + (k + j*l1)*ido] =
                  wa[idij - 1]*cc[i + (k + j*l1)*ido] - wa[idij]*cc[i - 1 + (k + j*l1)*ido];
            }
          }
        }
      }
      if (nbd >= l1) {
        for (j=1; j<ipph; j++) {
          jc = ip - j;
          for (k=0; k<l1; k++) {
            for (i=2; i<ido; i+=2) {
              cc[i - 1 + (k + j*l1)*ido] = ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
              cc[i - 1 + (k + jc*l1)*ido] = ch[i + (k + j*l1)*ido] - ch[i + (k + jc*l1)*ido];
              cc[i + (k + j*l1)*ido] = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
              cc[i + (k + jc*l1)*ido] = ch[i - 1 + (k + jc*l1)*ido] - ch[i - 1 + (k + j*l1)*ido];
            }
          }
        }
      } else {
        for (j=1; j<ipph; j++) {
          jc = ip - j;
          for (i=2; i<ido; i+=2) {
            for (k=0; k<l1; k++) {
              cc[i - 1 + (k + j*l1)*ido] =
                  ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
              cc[i - 1 + (k + jc*l1)*ido] = ch[i + (k + j*l1)*ido] - ch[i + (k + jc*l1)*ido];
              cc[i + (k + j*l1)*ido] = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
              cc[i + (k + jc*l1)*ido] = ch[i - 1 + (k + jc*l1)*ido] - ch[i - 1 + (k + j*l1)*ido];
            }
          }
        }
      }
    } else {  /* now ido == 1 */
      for (ik=0; ik<idl1; ik++) cc[ik] = ch[ik];
    }
    for (j=1; j<ipph; j++) {
      jc = ip - j;
      for (k=0; k<l1; k++) {
        cc[(k + j*l1)*ido] = ch[(k + j*l1)*ido] + ch[(k + jc*l1)*ido];
        cc[(k + jc*l1)*ido] = ch[(k + jc*l1)*ido] - ch[(k + j*l1)*ido];
      }
    }

    ar1 = 1;
    ai1 = 0;
    for (l=1; l<ipph; l++) {
      lc = ip - l;
      ar1h = dcp*ar1 - dsp*ai1;
      ai1 = dcp*ai1 + dsp*ar1;
      ar1 = ar1h;
      for (ik=0; ik<idl1; ik++) {
        ch[ik + l*idl1] = cc[ik] + ar1*cc[ik + idl1];
        ch[ik + lc*idl1] = ai1*cc[ik + (ip-1)*idl1];
      }
      dc2 = ar1;
      ds2 = ai1;
      ar2 = ar1;
      ai2 = ai1;
      for (j=2; j<ipph; j++) {
        jc = ip - j;
        ar2h = dc2*ar2 - ds2*ai2;
        ai2 = dc2*ai2 + ds2*ar2;
        ar2 = ar2h;
        for (ik=0; ik<idl1; ik++) {
          ch[ik + l*idl1] += ar2*cc[ik + j*idl1];
          ch[ik + lc*idl1] += ai2*cc[ik + jc*idl1];
        }
      }
    }
    for (j=1; j<ipph; j++)
      for (ik=0; ik<idl1; ik++)
        ch[ik] += cc[ik + j*idl1];

    if (ido >= l1) {
      for (k=0; k<l1; k++) {
        for (i=0; i<ido; i++) {
          ref(cc,i + k*ip*ido) = ch[i + k*ido];
        }
      }
    } else {
      for (i=0; i<ido; i++) {
        for (k=0; k<l1; k++) {
          ref(cc,i + k*ip*ido) = ch[i + k*ido];
        }
      }
    }
    for (j=1; j<ipph; j++) {
      jc = ip - j;
      j2 = 2*j;
      for (k=0; k<l1; k++) {
        ref(cc,ido-1 + (j2 - 1 + k*ip)*ido) =
            ch[(k + j*l1)*ido];
        ref(cc,(j2 + k*ip)*ido) =
            ch[(k + jc*l1)*ido];
      }
    }
    if (ido == 1) return;
    if (nbd >= l1) {
      for (j=1; j<ipph; j++) {
        jc = ip - j;
        j2 = 2*j;
        for (k=0; k<l1; k++) {
          for (i=2; i<ido; i+=2) {
            ic = ido - i;
            ref(cc,i - 1 + (j2 + k*ip)*ido) = ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
            ref(cc,ic - 1 + (j2 - 1 + k*ip)*ido) = ch[i - 1 + (k + j*l1)*ido] - ch[i - 1 + (k + jc*l1)*ido];
            ref(cc,i + (j2 + k*ip)*ido) = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
            ref(cc,ic + (j2 - 1 + k*ip)*ido) = ch[i + (k + jc*l1)*ido] - ch[i + (k + j*l1)*ido];
          }
        }
      }
    } else {
      for (j=1; j<ipph; j++) {
        jc = ip - j;
        j2 = 2*j;
        for (i=2; i<ido; i+=2) {
          ic = ido - i;
          for (k=0; k<l1; k++) {
            ref(cc,i - 1 + (j2 + k*ip)*ido) = ch[i - 1 + (k + j*l1)*ido] + ch[i - 1 + (k + jc*l1)*ido];
            ref(cc,ic - 1 + (j2 - 1 + k*ip)*ido) = ch[i - 1 + (k + j*l1)*ido] - ch[i - 1 + (k + jc*l1)*ido];
            ref(cc,i + (j2 + k*ip)*ido) = ch[i + (k + j*l1)*ido] + ch[i + (k + jc*l1)*ido];
            ref(cc,ic + (j2 - 1 + k*ip)*ido) = ch[i + (k + jc*l1)*ido] - ch[i + (k + j*l1)*ido];
          }
        }
      }
    }
  } /* radfg */


static void radbg(int ido, int ip, int l1, int idl1,
      Treal cc[], Treal ch[], const Treal wa[])
  {
    static const Treal twopi = 6.28318530717959;
    int idij, ipph, i, j, k, l, j2, ic, jc, lc, ik, is;
    Treal dc2, ai1, ai2, ar1, ar2, ds2;
    int nbd;
    Treal dcp, arg, dsp, ar1h, ar2h;
    arg = twopi / ip;
    dcp = cos(arg);
    dsp = sin(arg);
    nbd = (ido - 1) / 2;
    ipph = (ip + 1) / 2;
    if (ido >= l1) {
      for (k=0; k<l1; k++) {
        for (i=0; i<ido; i++) {
          ch[i + k*ido] = ref(cc,i + k*ip*ido);
        }
      }
    } else {
      for (i=0; i<ido; i++) {
        for (k=0; k<l1; k++) {
          ch[i + k*ido] = ref(cc,i + k*ip*ido);
        }
      }
    }
    for (j=1; j<ipph; j++) {
      jc = ip - j;
      j2 = 2*j;
      for (k=0; k<l1; k++) {
        ch[(k + j*l1)*ido] = ref(cc,ido-1 + (j2 - 1 + k*ip)*ido) + ref(cc,ido-1 + (j2 - 1 + k*ip)*
            ido);
        ch[(k + jc*l1)*ido] = ref(cc,(j2 + k*ip)*ido) + ref(cc,(j2 + k*ip)*ido);
      }
    }

    if (ido != 1) {
      if (nbd >= l1) {
        for (j=1; j<ipph; j++) {
          jc = ip - j;
          for (k=0; k<l1; k++) {
            for (i=2; i<ido; i+=2) {
              ic = ido - i;
              ch[i - 1 + (k + j*l1)*ido] = ref(cc,i - 1 + (2*j + k*ip)*ido) + ref(cc,
                  ic - 1 + (2*j - 1 + k*ip)*ido);
              ch[i - 1 + (k + jc*l1)*ido] = ref(cc,i - 1 + (2*j + k*ip)*ido) -
                  ref(cc,ic - 1 + (2*j - 1 + k*ip)*ido);
              ch[i + (k + j*l1)*ido] = ref(cc,i + (2*j + k*ip)*ido) - ref(cc,ic
                  + (2*j - 1 + k*ip)*ido);
              ch[i + (k + jc*l1)*ido] = ref(cc,i + (2*j + k*ip)*ido) + ref(cc,ic
                  + (2*j - 1 + k*ip)*ido);
            }
          }
        }
      } else {
        for (j=1; j<ipph; j++) {
          jc = ip - j;
          for (i=2; i<ido; i+=2) {
            ic = ido - i;
            for (k=0; k<l1; k++) {
              ch[i - 1 + (k + j*l1)*ido] = ref(cc,i - 1 + (2*j + k*ip)*ido) + ref(cc,
                  ic - 1 + (2*j - 1 + k*ip)*ido);
              ch[i - 1 + (k + jc*l1)*ido] = ref(cc,i - 1 + (2*j + k*ip)*ido) -
                  ref(cc,ic - 1 + (2*j - 1 + k*ip)*ido);
              ch[i + (k + j*l1)*ido] = ref(cc,i + (2*j + k*ip)*ido) - ref(cc,ic
                  + (2*j - 1 + k*ip)*ido);
              ch[i + (k + jc*l1)*ido] = ref(cc,i + (2*j + k*ip)*ido) + ref(cc,ic
                  + (2*j - 1 + k*ip)*ido);
            }
          }
        }
      }
    }

    ar1 = 1;
    ai1 = 0;
    for (l=1; l<ipph; l++) {
      lc = ip - l;
      ar1h = dcp*ar1 - dsp*ai1;
      ai1 = dcp*ai1 + dsp*ar1;
      ar1 = ar1h;
      for (ik=0; ik<idl1; ik++) {
        cc[ik + l*idl1] = ch[ik] + ar1*ch[ik + idl1];
        cc[ik + lc*idl1] = ai1*ch[ik + (ip-1)*idl1];
      }
      dc2 = ar1;
      ds2 = ai1;
      ar2 = ar1;
      ai2 = ai1;
      for (j=2; j<ipph; j++) {
        jc = ip - j;
        ar2h = dc2*ar2 - ds2*ai2;
        ai2 = dc2*ai2 + ds2*ar2;
        ar2 = ar2h;
        for (ik=0; ik<idl1; ik++) {
          cc[ik + l*idl1] += ar2*ch[ik + j*idl1];
          cc[ik + lc*idl1] += ai2*ch[ik + jc*idl1];
        }
      }
    }
    for (j=1; j<ipph; j++) {
      for (ik=0; ik<idl1; ik++) {
        ch[ik] += ch[ik + j*idl1];
      }
    }
    for (j=1; j<ipph; j++) {
      jc = ip - j;
      for (k=0; k<l1; k++) {
        ch[(k + j*l1)*ido] = cc[(k + j*l1)*ido] - cc[(k + jc*l1)*ido];
        ch[(k + jc*l1)*ido] = cc[(k + j*l1)*ido] + cc[(k + jc*l1)*ido];
      }
    }

    if (ido == 1) return;
    if (nbd >= l1) {
      for (j=1; j<ipph; j++) {
        jc = ip - j;
        for (k=0; k<l1; k++) {
          for (i=2; i<ido; i+=2) {
            ch[i - 1 + (k + j*l1)*ido] = cc[i - 1 + (k + j*l1)*ido] - cc[i + (k + jc*l1)*ido];
            ch[i - 1 + (k + jc*l1)*ido] = cc[i - 1 + (k + j*l1)*ido] + cc[i + (k + jc*l1)*ido];
            ch[i + (k + j*l1)*ido] = cc[i + (k + j*l1)*ido] + cc[i - 1 + (k + jc*l1)*ido];
            ch[i + (k + jc*l1)*ido] = cc[i + (k + j*l1)*ido] - cc[i - 1 + (k + jc*l1)*ido];
          }
        }
      }
    } else {
      for (j=1; j<ipph; j++) {
        jc = ip - j;
        for (i=2; i<ido; i+=2) {
          for (k=0; k<l1; k++) {
            ch[i - 1 + (k + j*l1)*ido] = cc[i - 1 + (k + j*l1)*ido] - cc[i + (k + jc*l1)*ido];
            ch[i - 1 + (k + jc*l1)*ido] = cc[i - 1 + (k + j *l1)*ido] + cc[i + (k + jc*l1)*ido];
            ch[i + (k + j*l1)*ido] = cc[i + (k + j*l1)*ido] + cc[i - 1 + (k + jc*l1)*ido];
            ch[i + (k + jc*l1)*ido] = cc[i + (k + j*l1)*ido] - cc[i - 1 + (k + jc*l1)*ido];
          }
        }
      }
    }
    for (ik=0; ik<idl1; ik++) cc[ik] = ch[ik];
    for (j=1; j<ip; j++)
      for (k=0; k<l1; k++)
        cc[(k + j*l1)*ido] = ch[(k + j*l1)*ido];
    if (nbd <= l1) {
      is = -ido;
      for (j=1; j<ip; j++) {
        is += ido;
        idij = is-1;
        for (i=2; i<ido; i+=2) {
          idij += 2;
          for (k=0; k<l1; k++) {
            cc[i - 1 + (k + j*l1)*ido] = wa[idij - 1]*ch[i - 1 + (k + j*l1)*ido] - wa[idij]*
                ch[i + (k + j*l1)*ido];
            cc[i + (k + j*l1)*ido] = wa[idij - 1]*ch[i + (k + j*l1)*ido] + wa[idij]*ch[i - 1 + (k + j*l1)*ido];
          }
        }
      }
    } else {
      is = -ido;
      for (j=1; j<ip; j++) {
        is += ido;
        for (k=0; k<l1; k++) {
          idij = is - 1;
          for (i=2; i<ido; i+=2) {
            idij += 2;
            cc[i - 1 + (k + j*l1)*ido] = wa[idij-1]*ch[i - 1 + (k + j*l1)*ido] - wa[idij]*
                ch[i + (k + j*l1)*ido];
            cc[i + (k + j*l1)*ido] = wa[idij-1]*ch[i + (k + j*l1)*ido] + wa[idij]*ch[i - 1 + (k + j*l1)*ido];
          }
        }
      }
    }
  } /* radbg */

  /* ----------------------------------------------------------------------
cfftf1, cfftf, cfftb, cffti1, cffti. Complex FFTs.
---------------------------------------------------------------------- */

static void cfftf1(int n, Treal c[], Treal ch[], const Treal wa[], const int ifac[MAXFAC+2], int isign)
  {
    int idot, i;
    int k1, l1, l2;
    int na, nf, ip, iw, ix2, ix3, ix4, nac, ido, idl1;
    Treal *cinput, *coutput;
    nf = ifac[1];
    na = 0;
    l1 = 1;
    iw = 0;
    for (k1=2; k1<=nf+1; k1++) {
      ip = ifac[k1];
      l2 = ip*l1;
      ido = n / l2;
      idot = ido + ido;
      idl1 = idot*l1;
      if (na) {
        cinput = ch;
        coutput = c;
      } else {
        cinput = c;
        coutput = ch;
      }
      switch (ip) {
      case 4:
        ix2 = iw + idot;
        ix3 = ix2 + idot;
        passf4(idot, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], isign);
        na = !na;
        break;
      case 2:
        passf2(idot, l1, cinput, coutput, &wa[iw], isign);
        na = !na;
        break;
      case 3:
        ix2 = iw + idot;
        passf3(idot, l1, cinput, coutput, &wa[iw], &wa[ix2], isign);
        na = !na;
        break;
      case 5:
        ix2 = iw + idot;
        ix3 = ix2 + idot;
        ix4 = ix3 + idot;
        passf5(idot, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4], isign);
        na = !na;
        break;
      default:
        passf(&nac, idot, ip, l1, idl1, cinput, coutput, &wa[iw], isign);
        if (nac != 0) na = !na;
      }
      l1 = l2;
      iw += (ip - 1)*idot;
    }
    if (na == 0) return;
    for (i=0; i<2*n; i++) c[i] = ch[i];
  } /* cfftf1 */


void cfftf(int n, Treal c[], Treal wsave[])
  {
    int iw1, iw2;
    if (n == 1) return;
    iw1 = 2*n;
    iw2 = iw1 + 2*n;
    cfftf1(n, c, wsave, wsave+iw1, (int*)(wsave+iw2), -1);
  } /* cfftf */


void cfftb(int n, Treal c[], Treal wsave[])
  {
    int iw1, iw2;
    if (n == 1) return;
    iw1 = 2*n;
    iw2 = iw1 + 2*n;
    cfftf1(n, c, wsave, wsave+iw1, (int*)(wsave+iw2), +1);
  } /* cfftb */


static void factorize(int n, int ifac[MAXFAC+2], const int ntryh[NSPECIAL])
  /* Factorize n in factors in ntryh and rest. On exit,
ifac[0] contains n and ifac[1] contains number of factors,
the factors start from ifac[2]. */
  {
    int ntry=3, i, j=0, ib, nf=0, nl=n, nq, nr;
startloop:
    if (j < NSPECIAL)
      ntry = ntryh[j];
    else
      ntry+= 2;
    j++;
    do {
      nq = nl / ntry;
      nr = nl - ntry*nq;
      if (nr != 0) goto startloop;
      nf++;
      ifac[nf + 1] = ntry;
      nl = nq;
      if (ntry == 2 && nf != 1) {
        for (i=2; i<=nf; i++) {
          ib = nf - i + 2;
          ifac[ib + 1] = ifac[ib];
        }
        ifac[2] = 2;
      }
    } while (nl != 1);
    ifac[0] = n;
    ifac[1] = nf;
  }


static void cffti1(int n, Treal wa[], int ifac[MAXFAC+2])
  {
    static const Treal twopi = 6.28318530717959;
    Treal arg, argh, argld, fi;
    int idot, i, j;
    int i1, k1, l1, l2;
    int ld, ii, nf, ip;
    int ido, ipm;

    static const int ntryh[NSPECIAL] = {
      3,4,2,5    }; /* Do not change the order of these. */

    factorize(n,ifac,ntryh);
    nf = ifac[1];
    argh = twopi/(Treal)n;
    i = 1;
    l1 = 1;
    for (k1=1; k1<=nf; k1++) {
      ip = ifac[k1+1];
      ld = 0;
      l2 = l1*ip;
      ido = n / l2;
      idot = ido + ido + 2;
      ipm = ip - 1;
      for (j=1; j<=ipm; j++) {
        i1 = i;
        wa[i-1] = 1;
        wa[i] = 0;
        ld += l1;
        fi = 0;
        argld = ld*argh;
        for (ii=4; ii<=idot; ii+=2) {
          i+= 2;
          fi+= 1;
          arg = fi*argld;
          wa[i-1] = cos(arg);
          wa[i] = sin(arg);
        }
        if (ip > 5) {
          wa[i1-1] = wa[i-1];
          wa[i1] = wa[i];
        }
      }
      l1 = l2;
    }
  } /* cffti1 */


void cffti(int n, Treal wsave[])
 {
    int iw1, iw2;
    if (n == 1) return;
    iw1 = 2*n;
    iw2 = iw1 + 2*n;
    cffti1(n, wsave+iw1, (int*)(wsave+iw2));
  } /* cffti */

  /* ----------------------------------------------------------------------
rfftf1, rfftb1, rfftf, rfftb, rffti1, rffti. Treal FFTs.
---------------------------------------------------------------------- */

static void rfftf1(int n, Treal c[], Treal ch[], const Treal wa[], const int ifac[MAXFAC+2])
  {
    int i;
    int k1, l1, l2, na, kh, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
    Treal *cinput, *coutput;
    nf = ifac[1];
    na = 1;
    l2 = n;
    iw = n-1;
    for (k1 = 1; k1 <= nf; ++k1) {
      kh = nf - k1;
      ip = ifac[kh + 2];
      l1 = l2 / ip;
      ido = n / l2;
      idl1 = ido*l1;
      iw -= (ip - 1)*ido;
      na = !na;
      if (na) {
        cinput = ch;
        coutput = c;
      } else {
        cinput = c;
        coutput = ch;
      }
      switch (ip) {
      case 4:
        ix2 = iw + ido;
        ix3 = ix2 + ido;
        radf4(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3]);
        break;
      case 2:
        radf2(ido, l1, cinput, coutput, &wa[iw]);
        break;
      case 3:
        ix2 = iw + ido;
        radf3(ido, l1, cinput, coutput, &wa[iw], &wa[ix2]);
        break;
      case 5:
        ix2 = iw + ido;
        ix3 = ix2 + ido;
        ix4 = ix3 + ido;
        radf5(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4]);
        break;
      default:
        if (ido == 1)
          na = !na;
        if (na == 0) {
          radfg(ido, ip, l1, idl1, c, ch, &wa[iw]);
          na = 1;
        } else {
          radfg(ido, ip, l1, idl1, ch, c, &wa[iw]);
          na = 0;
        }
      }
      l2 = l1;
    }
    if (na == 1) return;
    for (i = 0; i < n; i++) c[i] = ch[i];
  } /* rfftf1 */


void rfftb1(int n, Treal c[], Treal ch[], const Treal wa[], const int ifac[MAXFAC+2])
  {
    int i;
    int k1, l1, l2, na, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
    Treal *cinput, *coutput;
    nf = ifac[1];
    na = 0;
    l1 = 1;
    iw = 0;
    for (k1=1; k1<=nf; k1++) {
      ip = ifac[k1 + 1];
      l2 = ip*l1;
      ido = n / l2;
      idl1 = ido*l1;
      if (na) {
        cinput = ch;
        coutput = c;
      } else {
        cinput = c;
        coutput = ch;
      }
      switch (ip) {
      case 4:
        ix2 = iw + ido;
        ix3 = ix2 + ido;
        radb4(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3]);
        na = !na;
        break;
      case 2:
        radb2(ido, l1, cinput, coutput, &wa[iw]);
        na = !na;
        break;
      case 3:
        ix2 = iw + ido;
        radb3(ido, l1, cinput, coutput, &wa[iw], &wa[ix2]);
        na = !na;
        break;
      case 5:
        ix2 = iw + ido;
        ix3 = ix2 + ido;
        ix4 = ix3 + ido;
        radb5(ido, l1, cinput, coutput, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4]);
        na = !na;
        break;
      default:
        radbg(ido, ip, l1, idl1, cinput, coutput, &wa[iw]);
        if (ido == 1) na = !na;
      }
      l1 = l2;
      iw += (ip - 1)*ido;
    }
    if (na == 0) return;
    for (i=0; i<n; i++) c[i] = ch[i];
  } /* rfftb1 */


void rfftf(int n, Treal r[], Treal wsave[])
  {
    if (n == 1) return;
    rfftf1(n, r, wsave, wsave+n, (int*)(wsave+2*n));
  } /* rfftf */


void rfftb(int n, Treal r[], Treal wsave[])
  {
    if (n == 1) return;
    rfftb1(n, r, wsave, wsave+n, (int*)(wsave+2*n));
  } /* rfftb */


static void rffti1(int n, Treal wa[], int ifac[MAXFAC+2])
  {
    static const Treal twopi = 6.28318530717959;
    Treal arg, argh, argld, fi;
    int i, j;
    int k1, l1, l2;
    int ld, ii, nf, ip, is;
    int ido, ipm, nfm1;
    static const int ntryh[NSPECIAL] = {
      4,2,3,5    }; /* Do not change the order of these. */
    factorize(n,ifac,ntryh);
    nf = ifac[1];
    argh = twopi / n;
    is = 0;
    nfm1 = nf - 1;
    l1 = 1;
    if (nfm1 == 0) return;
    for (k1 = 1; k1 <= nfm1; k1++) {
      ip = ifac[k1 + 1];
      ld = 0;
      l2 = l1*ip;
      ido = n / l2;
      ipm = ip - 1;
      for (j = 1; j <= ipm; ++j) {
        ld += l1;
        i = is;
        argld = (Treal) ld*argh;
        fi = 0;
        for (ii = 3; ii <= ido; ii += 2) {
          i += 2;
          fi += 1;
          arg = fi*argld;
          wa[i - 2] = cos(arg);
          wa[i - 1] = sin(arg);
        }
        is += ido;
      }
      l1 = l2;
    }
  } /* rffti1 */


void rffti(int n, Treal wsave[])
  {
    if (n == 1) return;
    rffti1(n, wsave+n, (int*)(wsave+2*n));
  } /* rffti */

#ifdef __cplusplus
}
#endif
