christ@tybalt.caltech.edu (Christian L. Keppenne) (08/16/89)
Does someone have a C++ implementation of the general FFT algorithm. I would prefer the mixed radix case (number of points not necessarily a power of two) but the standard Cooley Tukey algorithm would do too. I am sure this must be available somewhere and I will be grateful to the person who will help me save the time of reprogramming it myself. Thank you in advance. Christian Keppenne christ&tybalt.caltech.edu
jima@hplsla.HP.COM (Jim Adcock) (08/18/89)
#include <complex.h>
#include <stream.h>
// fft a double precision complex array x of size (2 to the m)
// this is like I have posted before, but contains a bug workaround
// necessary for some C++ compilers.
int fft(complex* x, unsigned m)
{
complex u, w, t;
unsigned n = 1 << m;
unsigned nv2 = n >> 1;
unsigned nm1 = n - 1;
unsigned j = 0;
for (unsigned i = 0; i < nm1; ++i)
{
if (i < j) {t = x[j]; x[j] = x[i]; x[i] = t;}
unsigned k = nv2;
while ((k-1) < j) {j -= k; k >>= 1;}
j += k;
}
for (unsigned l = 1; l <= m; ++l)
{
unsigned le = 1 << l;
unsigned le1 = le >> 1;
complex u(1.0, 0.0);
double cs = cos(M_PI/double(le1)); //temporaries introduced to fix bug
double sn = sin(M_PI/double(le1));
complex w(cs,sn);
for (j = 0; j < le1; ++j)
{
for (i = j; i < n; i += le)
{
unsigned ip = i + le1;
t = x[ip] * u;
x[ip] = x[i] - t;
x[i] += t;
}
u *= w;
}
}
return m;
}
#define SZ 16
#define LGSZ 4
main()
{
complex x[SZ];
for (long i = 0; i < SZ; ++i)
{
for (long j = 0; j < SZ; ++j) x[j] = 0.0;
x[i] = 1.0;
fft(x, LGSZ);
fft(x, LGSZ); //two ffts in a row without conjugation causes time
//reversal and scaling by SZ
for (j = 0; j < SZ; ++j)
{
//to make a pretty output force small numbers to zero
if (abs(real(x[j])) < 1.0e-10) x[j] = complex(0.0,imag(x[j]));
if (abs(imag(x[j])) < 1.0e-10) x[j] = complex(real(x[j]),0.0);
cout << "(" << real(x[j]) << "+i" << imag(x[j]) << ")" << " ";
}
cout << "\n\n";
}
}