// 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 <fftw3.h>
#endif
#include <vector>
#include <complex>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <Eigen/Core>
#include <unsupported/Eigen/FFT>
using namespace std;
using namespace Eigen;
template <typename T>
T mag2(T a)
{
return a*a;
}
template <typename T>
T mag2(std::complex<T> a)
{
return norm(a);
}
template <typename T>
T mag2(const std::vector<T> & vec)
{
T out=0;
for (size_t k=0;k<vec.size();++k)
out += mag2(vec[k]);
return out;
}
template <typename T>
T mag2(const std::vector<std::complex<T> > & vec)
{
T out=0;
for (size_t k=0;k<vec.size();++k)
out += mag2(vec[k]);
return out;
}
template <typename T>
vector<T> operator-(const vector<T> & a,const vector<T> & b )
{
vector<T> c(a);
for (size_t k=0;k<b.size();++k)
c[k] -= b[k];
return c;
}
template <typename T>
void RandomFill(std::vector<T> & vec)
{
for (size_t k=0;k<vec.size();++k)
vec[k] = T( rand() )/T(RAND_MAX) - .5;
}
template <typename T>
void RandomFill(std::vector<std::complex<T> > & vec)
{
for (size_t k=0;k<vec.size();++k)
vec[k] = std::complex<T> ( T( rand() )/T(RAND_MAX) - .5, T( rand() )/T(RAND_MAX) - .5);
}
template <typename T_time,typename T_freq>
void fwd_inv(size_t nfft)
{
typedef typename NumTraits<T_freq>::Real Scalar;
vector<T_time> timebuf(nfft);
RandomFill(timebuf);
vector<T_freq> freqbuf;
static FFT<Scalar> fft;
fft.fwd(freqbuf,timebuf);
vector<T_time> timebuf2;
fft.inv(timebuf2,freqbuf);
long double rmse = mag2(timebuf - timebuf2) / mag2(timebuf);
cout << "roundtrip rmse: " << rmse << endl;
}
template <typename T_scalar>
void two_demos(int nfft)
{
cout << " scalar ";
fwd_inv<T_scalar,std::complex<T_scalar> >(nfft);
cout << " complex ";
fwd_inv<std::complex<T_scalar>,std::complex<T_scalar> >(nfft);
}
void demo_all_types(int nfft)
{
cout << "nfft=" << nfft << endl;
cout << " float" << endl;
two_demos<float>(nfft);
cout << " double" << endl;
two_demos<double>(nfft);
cout << " long double" << endl;
two_demos<long double>(nfft);
}
int main()
{
demo_all_types( 2*3*4*5*7 );
demo_all_types( 2*9*16*25 );
demo_all_types( 1024 );
return 0;
}