From 8b4afe3debb47bf15ea291a7f2d21d863d546536 Mon Sep 17 00:00:00 2001 From: Mark Borgerding Date: Fri, 22 May 2009 22:37:59 -0400 Subject: [PATCH] added non-optimized real forward fft (no inverse yet) --- unsupported/Eigen/FFT.h | 27 ++++- unsupported/Eigen/src/FFT/simple_fft_traits.h | 10 +- unsupported/test/FFT.cpp | 113 ++++++++++++------ 3 files changed, 106 insertions(+), 44 deletions(-) diff --git a/unsupported/Eigen/FFT.h b/unsupported/Eigen/FFT.h index 03490d2c5..a1f87a609 100644 --- a/unsupported/Eigen/FFT.h +++ b/unsupported/Eigen/FFT.h @@ -57,21 +57,36 @@ class FFT FFT(const traits_type & traits=traits_type() ) :m_traits(traits) { } - void fwd( Complex * dst, const Complex * src, int nfft) + template + void fwd( Complex * dst, const _Input * src, int nfft) { m_traits.prepare(nfft,false,dst,src); m_traits.exec(dst,src); m_traits.postprocess(dst); } - void inv( Complex * dst, const Complex * src, int nfft) + template + void fwd( std::vector & dst, const std::vector<_Input> & src) { - m_traits.prepare(nfft,true,dst,src); - m_traits.exec(dst,src); - m_traits.postprocess(dst); + dst.resize( src.size() ); + fwd( &dst[0],&src[0],src.size() ); + } + + template + void inv( _Output * dst, const Complex * src, int nfft) + { + m_traits.prepare(nfft,true,dst,src); + m_traits.exec(dst,src); + m_traits.postprocess(dst); + } + + template + void inv( std::vector<_Output> & dst, const std::vector & src) + { + dst.resize( src.size() ); + inv( &dst[0],&src[0],src.size() ); } - // TODO: fwd,inv for Scalar // TODO: multi-dimensional FFTs // TODO: handle Eigen MatrixBase diff --git a/unsupported/Eigen/src/FFT/simple_fft_traits.h b/unsupported/Eigen/src/FFT/simple_fft_traits.h index 6fbbeac2e..5a910dd1f 100644 --- a/unsupported/Eigen/src/FFT/simple_fft_traits.h +++ b/unsupported/Eigen/src/FFT/simple_fft_traits.h @@ -34,7 +34,8 @@ namespace Eigen { typedef std::complex Complex; simple_fft_traits() : m_nfft(0) {} - void prepare(int nfft,bool inverse,Complex * dst,const Complex *src) + template + void prepare(int nfft,bool inverse,Complex * dst,const _Src *src) { if (m_nfft == nfft) { // reuse the twiddles, conjugate if necessary @@ -73,7 +74,8 @@ namespace Eigen { }while(n>1); } - void exec(Complex * dst, const Complex * src) + template + void exec(Complex * dst, const _Src * src) { work(0, dst, src, 1,1); } @@ -89,7 +91,9 @@ namespace Eigen { private: - void work( int stage,Complex * Fout, const Complex * f, size_t fstride,size_t in_stride) + + template + void work( int stage,Complex * Fout, const _Src * f, size_t fstride,size_t in_stride) { int p = m_stageRadix[stage]; int m = m_stageRemainder[stage]; diff --git a/unsupported/test/FFT.cpp b/unsupported/test/FFT.cpp index 8347bb76b..ef03359e2 100644 --- a/unsupported/test/FFT.cpp +++ b/unsupported/test/FFT.cpp @@ -25,55 +25,98 @@ #include "main.h" #include + using namespace std; +template < typename T> +complex promote(complex x) { return complex(x.real(),x.imag()); } + +complex promote(float x) { return complex( x); } +complex promote(double x) { return complex( x); } +complex promote(long double x) { return complex( x); } + + + template + long double fft_rmse( const vector & fftbuf,const vector & timebuf) + { + long double totalpower=0; + long double difpower=0; + for (size_t k0=0;k0 acc = 0; + long double phinc = -2.*k0* M_PIl / timebuf.size(); + for (size_t k1=0;k1(0,k1*phinc) ); + } + totalpower += norm(acc); + complex x = promote(fftbuf[k0]); + complex dif = acc - x; + difpower += norm(dif); + cerr << k0 << ":" << acc << " " << x << endl; + } + cerr << "rmse:" << sqrt(difpower/totalpower) << endl; + return sqrt(difpower/totalpower); + } + + template + long double dif_rmse( const vector buf1,const vector buf2) + { + long double totalpower=0; + long double difpower=0; + size_t n = min( buf1.size(),buf2.size() ); + for (size_t k=0;k -void test_fft(int nfft) +void test_scalar(int nfft) +{ + typedef typename Eigen::FFT::Complex Complex; + typedef typename Eigen::FFT::Scalar Scalar; + + FFT fft; + vector inbuf(nfft); + vector outbuf; + for (int k=0;k +void test_complex(int nfft) { typedef typename Eigen::FFT::Complex Complex; FFT fft; vector inbuf(nfft); - vector buf3(nfft); - vector outbuf(nfft); + vector outbuf; + vector buf3; for (int k=0;k acc = 0; - long double phinc = 2*k0* M_PIl / nfft; - for (int k1=0;k1 x(inbuf[k1].real(),inbuf[k1].imag()); - acc += x * exp( complex(0,-k1*phinc) ); - } - totalpower += norm(acc); - complex x(outbuf[k0].real(),outbuf[k0].imag()); - complex dif = acc - x; - difpower += norm(dif); - } - long double rmse = sqrt(difpower/totalpower); - VERIFY( rmse < 1e-5 );// gross check + VERIFY( fft_rmse(outbuf,inbuf) < 1e-5 );// gross check - totalpower=0; - difpower=0; - for (int k=0;k(32) )); CALL_SUBTEST(( test_fft(32) )); CALL_SUBTEST(( test_fft(32) )); - CALL_SUBTEST(( test_fft(1024) )); CALL_SUBTEST(( test_fft(1024) )); CALL_SUBTEST(( test_fft(1024) )); - CALL_SUBTEST(( test_fft(2*3*4*5*7) )); CALL_SUBTEST(( test_fft(2*3*4*5*7) )); CALL_SUBTEST(( test_fft(2*3*4*5*7) )); + CALL_SUBTEST( test_complex(32) ); CALL_SUBTEST( test_complex(32) ); CALL_SUBTEST( test_complex(32) ); + CALL_SUBTEST( test_complex(1024) ); CALL_SUBTEST( test_complex(1024) ); CALL_SUBTEST( test_complex(1024) ); + CALL_SUBTEST( test_complex(3*8) ); CALL_SUBTEST( test_complex(3*8) ); CALL_SUBTEST( test_complex(3*8) ); + CALL_SUBTEST( test_complex(5*32) ); CALL_SUBTEST( test_complex(5*32) ); CALL_SUBTEST( test_complex(5*32) ); + CALL_SUBTEST( test_complex(2*3*4) ); CALL_SUBTEST( test_complex(2*3*4) ); CALL_SUBTEST( test_complex(2*3*4) ); + CALL_SUBTEST( test_complex(2*3*4*5) ); CALL_SUBTEST( test_complex(2*3*4*5) ); CALL_SUBTEST( test_complex(2*3*4*5) ); + CALL_SUBTEST( test_complex(2*3*4*5*7) ); CALL_SUBTEST( test_complex(2*3*4*5*7) ); CALL_SUBTEST( test_complex(2*3*4*5*7) ); + + CALL_SUBTEST( test_scalar(32) ); CALL_SUBTEST( test_scalar(32) ); CALL_SUBTEST( test_scalar(32) ); + CALL_SUBTEST( test_scalar(1024) ); CALL_SUBTEST( test_scalar(1024) ); CALL_SUBTEST( test_scalar(1024) ); + CALL_SUBTEST( test_scalar(2*3*4*5*7) ); CALL_SUBTEST( test_scalar(2*3*4*5*7) ); CALL_SUBTEST( test_scalar(2*3*4*5*7) ); }