home *** CD-ROM | disk | FTP | other *** search
- #include <math.h>
- #include "complex.h"
-
- /* Use 4-multiply complex multiply for MSC */
- #ifdef DOS /* IBM C */
- #define MULT4
- #endif
- #ifdef MSDOS /* Microsoft C */
- #define MULT4
- #endif
-
- #define PI 3.1415926535979
-
- fftn(data, nn, ndim, isign)
-
- #ifdef SPEED
- struct fcomplex data[];
- #else
- struct complex data[];
- #endif
-
- unsigned nn[];
- int ndim, isign;
- {
- int idim;
- unsigned i1, i2rev, i3rev, ibit;
- unsigned ip2, ifp1, ifp2, k2, n;
- unsigned nprev = 1, nrem, ntot = 1;
- register unsigned i2, i3;
- double theta;
- struct complex w, wp;
-
- #ifdef SPEED
- float wtemp;
- struct fcomplex temp, wt;
- #else
- double wtemp;
- struct complex temp, wt;
- #endif
-
- #ifndef MULT4 /* Temporary variables needed for 3-multiply complex mult. */
- double t1, t2;
- #endif
-
- /* Compute total number of complex values */
- for (idim = 0; idim < ndim; ++idim)
- ntot *= nn[idim];
-
- for (idim = ndim - 1; idim >= 0; --idim) {
- n = nn[idim];
-
- nrem = ntot / (n * nprev);
- ip2 = nprev * n; /* Unit step for next dimension */
- i2rev = 0; /* Bit reversed i2 */
-
- /* This is the bit reversal section of the routine */
- /* Loop over current dimension */
- for (i2 = 0; i2 < ip2; i2 += nprev) {
- if (i2 < i2rev)
- /* Loop over lower dimensions */
- for (i1 = i2; i1 < i2 + nprev; ++i1)
- /* Loop over higher dimensions */
- for (i3 = i1; i3 < ntot; i3 += ip2) {
- i3rev = i3 + i2rev - i2;
- temp = data[i3];
- data[i3] = data[i3rev];
- data[i3rev] = temp;
- }
-
- ibit = ip2;
- /* Increment from high end of i2rev to low */
- do {
- ibit >>= 1;
- i2rev ^= ibit;
- } while (ibit >= nprev && !(ibit & i2rev));
- }
-
- /* Here begins the Danielson-Lanczos section of the routine */
- /* Loop over step sizes */
- for (ifp1 = nprev; ifp1 < ip2; ifp1 <<= 1) {
- ifp2 = ifp1 << 1;
- /* Initialize for the trig. recurrence */
- theta = isign * 2.0 * PI / (ifp2 / nprev);
- wp.x = sin(0.5 * theta);
- wp.x *= -2.0 * wp.x;
- wp.y = sin(theta);
- w.x = 1.0;
- w.y = 0.0;
-
- /* Loop by unit step in current dimension */
- for (i3 = 0; i3 < ifp1; i3 += nprev) {
- /* Loop over lower dimensions */
- for (i1 = i3; i1 < i3 + nprev; ++i1)
- /* Loop over higher dimensions */
- for (i2 = i1; i2 < ntot; i2 += ifp2) {
- /* Danielson-Lanczos formula */
- k2 = i2 + ifp1;
- wt = data[k2];
-
- #ifdef MULT4
- /* Complex multiply using 4 real multiplies. Faster in MSC */
- data[k2].x = data[i2].x - (temp.x = w.x * wt.x - w.y * wt.y);
- data[k2].y = data[i2].y - (temp.y = w.x * wt.y + w.y * wt.x);
- #else
- /* Complex multiply using 3 real multiplies. Should usually be faster. */
- data[k2].x = data[i2].x - (temp.x =
- (t1 = w.x * wt.x) - (t2 = w.y * wt.y));
- data[k2].y = data[i2].y - (temp.y =
- (w.x + w.y) * (wt.x + wt.y) - t1 - t2);
- #endif
- data[i2].x += temp.x;
- data[i2].y += temp.y;
- }
- /* Trigonometric recurrence */
- wtemp = w.x;
- #ifdef MULT4
- /* Complex multiply using 4 real multiplies. */
- w.x += w.x * wp.x - w.y * wp.y;
- w.y += wtemp * wp.y + w.y * wp.x;
- #else
- /* Complex multiply using 3 real multiplies. */
- w.x += (t1 = w.x * wp.x) - (t2 = w.y * wp.y);
- w.y += (wtemp + w.y) * (wp.x + wp.y) - t1 - t2;
- #endif
- }
- }
- nprev *= n;
- }
- }
-