/* * fftpack.c : A set of FFT routines in C. * Algorithmically based on Fortran-77 FFTPACK by Paul N. Swarztrauber (Version 4, 1985). */ #define NPY_NO_DEPRECATED_API NPY_API_VERSION #include #include #include #include #define DOUBLE #ifdef DOUBLE #define Treal double #else #define Treal float #endif #define ref(u,a) u[a] /* Macros for accurate calculation of the twiddle factors. */ #define TWOPI 6.283185307179586476925286766559005768391 #define cos2pi(m, n) cos((TWOPI * (m)) / (n)) #define sin2pi(m, n) sin((TWOPI * (m)) / (n)) #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 static void sincos2pi(int m, int n, Treal* si, Treal* co) /* Calculates sin(2pi * m/n) and cos(2pi * m/n). It is more accurate * than the naive calculation as the fraction m/n is reduced to [0, 1/8) first. * Due to the symmetry of sin(x) and cos(x) the values for all x can be * determined from the function values of the reduced argument in the first * octant. */ { int n8, m8, octant; n8 = 8 * n; m8 = (8 * m) % n8; octant = m8 / n; m8 = m8 % n; switch(octant) { case 0: *co = cos2pi(m8, n8); *si = sin2pi(m8, n8); break; case 1: *co = sin2pi(n-m8, n8); *si = cos2pi(n-m8, n8); break; case 2: *co = -sin2pi(m8, n8); *si = cos2pi(m8, n8); break; case 3: *co = -cos2pi(n-m8, n8); *si = sin2pi(n-m8, n8); break; case 4: *co = -cos2pi(m8, n8); *si = -sin2pi(m8, n8); break; case 5: *co = -sin2pi(n-m8, n8); *si = -cos2pi(n-m8, n8); break; case 6: *co = sin2pi(m8, n8); *si = -cos2pi(m8, n8); break; case 7: *co = cos2pi(n-m8, n8); *si = -sin2pi(n-m8, n8); break; } } /* ---------------------------------------------------------------------- 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) { for (j=1; j idp) idlj -= idp; war = wa[idlj - 2]; wai = wa[idlj-1]; for (ik=0; ik= l1) { for (j=1; j= l1) { for (k=0; k= l1) { for (j=1; j= l1) { for (k=0; k= l1) { for (j=1; j= l1) { for (j=1; j 5) { wa[i1-1] = wa[i-1]; wa[i1] = wa[i]; } } l1 = l2; } } /* cffti1 */ NPY_VISIBILITY_HIDDEN void npy_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)); } /* npy_cffti */ /* ------------------------------------------------------------------- rfftf1, rfftb1, npy_rfftf, npy_rfftb, rffti1, npy_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 */ static 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