// To use the simple FFT implementation // g++ -o demofft -I.. -Wall -O3 FFT.cpp // To use the FFTW implementation // g++ -o demofft -I.. -DUSE_FFTW -Wall -O3 FFT.cpp -lfftw3 -lfftw3f -lfftw3l #ifdef USE_FFTW #include #endif #include #include #include #include #include #include #include using namespace std; using namespace Eigen; template T mag2(T a) { return a * a; } template T mag2(std::complex a) { return norm(a); } template T mag2(const std::vector& vec) { T out = 0; for (size_t k = 0; k < vec.size(); ++k) out += mag2(vec[k]); return out; } template T mag2(const std::vector >& vec) { T out = 0; for (size_t k = 0; k < vec.size(); ++k) out += mag2(vec[k]); return out; } template vector operator-(const vector& a, const vector& b) { vector c(a); for (size_t k = 0; k < b.size(); ++k) c[k] -= b[k]; return c; } template void RandomFill(std::vector& vec) { for (size_t k = 0; k < vec.size(); ++k) vec[k] = T(rand()) / T(RAND_MAX) - T(.5); } template void RandomFill(std::vector >& vec) { for (size_t k = 0; k < vec.size(); ++k) vec[k] = std::complex(T(rand()) / T(RAND_MAX) - T(.5), T(rand()) / T(RAND_MAX) - T(.5)); } template void fwd_inv(size_t nfft) { typedef typename NumTraits::Real Scalar; vector timebuf(nfft); RandomFill(timebuf); vector freqbuf; static FFT fft; fft.fwd(freqbuf, timebuf); vector timebuf2; fft.inv(timebuf2, freqbuf); T_time rmse = mag2(timebuf - timebuf2) / mag2(timebuf); cout << "roundtrip rmse: " << rmse << endl; } template void two_demos(int nfft) { cout << " scalar "; fwd_inv >(nfft); cout << " complex "; fwd_inv, std::complex >(nfft); } void demo_all_types(int nfft) { cout << "nfft=" << nfft << endl; cout << " float" << endl; two_demos(nfft); cout << " double" << endl; two_demos(nfft); cout << " long double" << endl; two_demos(nfft); } int main() { demo_all_types(2 * 3 * 4 * 5 * 7); demo_all_types(2 * 9 * 16 * 25); demo_all_types(1024); return 0; }