Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "main.h"
00011 #include <unsupported/Eigen/FFT>
00012
00013 template <typename T>
00014 std::complex<T> RandomCpx() { return std::complex<T>( (T)(rand()/(T)RAND_MAX - .5), (T)(rand()/(T)RAND_MAX - .5) ); }
00015
00016 using namespace std;
00017 using namespace Eigen;
00018
00019
00020 template < typename T>
00021 complex<long double> promote(complex<T> x) { return complex<long double>(x.real(),x.imag()); }
00022
00023 complex<long double> promote(float x) { return complex<long double>( x); }
00024 complex<long double> promote(double x) { return complex<long double>( x); }
00025 complex<long double> promote(long double x) { return complex<long double>( x); }
00026
00027
00028 template <typename VT1,typename VT2>
00029 long double fft_rmse( const VT1 & fftbuf,const VT2 & timebuf)
00030 {
00031 long double totalpower=0;
00032 long double difpower=0;
00033 long double pi = acos((long double)-1 );
00034 for (size_t k0=0;k0<(size_t)fftbuf.size();++k0) {
00035 complex<long double> acc = 0;
00036 long double phinc = -2.*k0* pi / timebuf.size();
00037 for (size_t k1=0;k1<(size_t)timebuf.size();++k1) {
00038 acc += promote( timebuf[k1] ) * exp( complex<long double>(0,k1*phinc) );
00039 }
00040 totalpower += numext::abs2(acc);
00041 complex<long double> x = promote(fftbuf[k0]);
00042 complex<long double> dif = acc - x;
00043 difpower += numext::abs2(dif);
00044
00045 }
00046 cerr << "rmse:" << sqrt(difpower/totalpower) << endl;
00047 return sqrt(difpower/totalpower);
00048 }
00049
00050 template <typename VT1,typename VT2>
00051 long double dif_rmse( const VT1 buf1,const VT2 buf2)
00052 {
00053 long double totalpower=0;
00054 long double difpower=0;
00055 size_t n = (min)( buf1.size(),buf2.size() );
00056 for (size_t k=0;k<n;++k) {
00057 totalpower += (numext::abs2( buf1[k] ) + numext::abs2(buf2[k]) )/2.;
00058 difpower += numext::abs2(buf1[k] - buf2[k]);
00059 }
00060 return sqrt(difpower/totalpower);
00061 }
00062
00063 enum { StdVectorContainer, EigenVectorContainer };
00064
00065 template<int Container, typename Scalar> struct VectorType;
00066
00067 template<typename Scalar> struct VectorType<StdVectorContainer,Scalar>
00068 {
00069 typedef vector<Scalar> type;
00070 };
00071
00072 template<typename Scalar> struct VectorType<EigenVectorContainer,Scalar>
00073 {
00074 typedef Matrix<Scalar,Dynamic,1> type;
00075 };
00076
00077 template <int Container, typename T>
00078 void test_scalar_generic(int nfft)
00079 {
00080 typedef typename FFT<T>::Complex Complex;
00081 typedef typename FFT<T>::Scalar Scalar;
00082 typedef typename VectorType<Container,Scalar>::type ScalarVector;
00083 typedef typename VectorType<Container,Complex>::type ComplexVector;
00084
00085 FFT<T> fft;
00086 ScalarVector tbuf(nfft);
00087 ComplexVector freqBuf;
00088 for (int k=0;k<nfft;++k)
00089 tbuf[k]= (T)( rand()/(double)RAND_MAX - .5);
00090
00091
00092
00093 fft.SetFlag(fft.HalfSpectrum );
00094 fft.fwd( freqBuf,tbuf);
00095 VERIFY((size_t)freqBuf.size() == (size_t)( (nfft>>1)+1) );
00096 VERIFY( fft_rmse(freqBuf,tbuf) < test_precision<T>() );
00097
00098 fft.ClearFlag(fft.HalfSpectrum );
00099 fft.fwd( freqBuf,tbuf);
00100 VERIFY( (size_t)freqBuf.size() == (size_t)nfft);
00101 VERIFY( fft_rmse(freqBuf,tbuf) < test_precision<T>() );
00102
00103 if (nfft&1)
00104 return;
00105
00106 ScalarVector tbuf2;
00107 fft.inv( tbuf2 , freqBuf);
00108 VERIFY( dif_rmse(tbuf,tbuf2) < test_precision<T>() );
00109
00110
00111
00112 ScalarVector tbuf3;
00113 fft.SetFlag(fft.Unscaled);
00114
00115 fft.inv( tbuf3 , freqBuf);
00116
00117 for (int k=0;k<nfft;++k)
00118 tbuf3[k] *= T(1./nfft);
00119
00120
00121
00122
00123
00124 VERIFY( dif_rmse(tbuf,tbuf3) < test_precision<T>() );
00125
00126
00127 fft.ClearFlag(fft.Unscaled);
00128 fft.inv( tbuf2 , freqBuf);
00129 VERIFY( dif_rmse(tbuf,tbuf2) < test_precision<T>() );
00130 }
00131
00132 template <typename T>
00133 void test_scalar(int nfft)
00134 {
00135 test_scalar_generic<StdVectorContainer,T>(nfft);
00136
00137 }
00138
00139
00140 template <int Container, typename T>
00141 void test_complex_generic(int nfft)
00142 {
00143 typedef typename FFT<T>::Complex Complex;
00144 typedef typename VectorType<Container,Complex>::type ComplexVector;
00145
00146 FFT<T> fft;
00147
00148 ComplexVector inbuf(nfft);
00149 ComplexVector outbuf;
00150 ComplexVector buf3;
00151 for (int k=0;k<nfft;++k)
00152 inbuf[k]= Complex( (T)(rand()/(double)RAND_MAX - .5), (T)(rand()/(double)RAND_MAX - .5) );
00153 fft.fwd( outbuf , inbuf);
00154
00155 VERIFY( fft_rmse(outbuf,inbuf) < test_precision<T>() );
00156 fft.inv( buf3 , outbuf);
00157
00158 VERIFY( dif_rmse(inbuf,buf3) < test_precision<T>() );
00159
00160
00161 ComplexVector buf4;
00162 fft.SetFlag(fft.Unscaled);
00163 fft.inv( buf4 , outbuf);
00164 for (int k=0;k<nfft;++k)
00165 buf4[k] *= T(1./nfft);
00166 VERIFY( dif_rmse(inbuf,buf4) < test_precision<T>() );
00167
00168
00169 fft.ClearFlag(fft.Unscaled);
00170 fft.inv( buf3 , outbuf);
00171 VERIFY( dif_rmse(inbuf,buf3) < test_precision<T>() );
00172 }
00173
00174 template <typename T>
00175 void test_complex(int nfft)
00176 {
00177 test_complex_generic<StdVectorContainer,T>(nfft);
00178 test_complex_generic<EigenVectorContainer,T>(nfft);
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 void test_return_by_value(int len)
00212 {
00213 VectorXf in;
00214 VectorXf in1;
00215 in.setRandom( len );
00216 VectorXcf out1,out2;
00217 FFT<float> fft;
00218
00219 fft.SetFlag(fft.HalfSpectrum );
00220
00221 fft.fwd(out1,in);
00222 out2 = fft.fwd(in);
00223 VERIFY( (out1-out2).norm() < test_precision<float>() );
00224 in1 = fft.inv(out1);
00225 VERIFY( (in1-in).norm() < test_precision<float>() );
00226 }
00227
00228 void test_FFTW()
00229 {
00230 CALL_SUBTEST( test_return_by_value(32) );
00231
00232
00233 CALL_SUBTEST( test_complex<float>(32) ); CALL_SUBTEST( test_complex<double>(32) );
00234 CALL_SUBTEST( test_complex<float>(256) ); CALL_SUBTEST( test_complex<double>(256) );
00235 CALL_SUBTEST( test_complex<float>(3*8) ); CALL_SUBTEST( test_complex<double>(3*8) );
00236 CALL_SUBTEST( test_complex<float>(5*32) ); CALL_SUBTEST( test_complex<double>(5*32) );
00237 CALL_SUBTEST( test_complex<float>(2*3*4) ); CALL_SUBTEST( test_complex<double>(2*3*4) );
00238 CALL_SUBTEST( test_complex<float>(2*3*4*5) ); CALL_SUBTEST( test_complex<double>(2*3*4*5) );
00239 CALL_SUBTEST( test_complex<float>(2*3*4*5*7) ); CALL_SUBTEST( test_complex<double>(2*3*4*5*7) );
00240
00241 CALL_SUBTEST( test_scalar<float>(32) ); CALL_SUBTEST( test_scalar<double>(32) );
00242 CALL_SUBTEST( test_scalar<float>(45) ); CALL_SUBTEST( test_scalar<double>(45) );
00243 CALL_SUBTEST( test_scalar<float>(50) ); CALL_SUBTEST( test_scalar<double>(50) );
00244 CALL_SUBTEST( test_scalar<float>(256) ); CALL_SUBTEST( test_scalar<double>(256) );
00245 CALL_SUBTEST( test_scalar<float>(2*3*4*5*7) ); CALL_SUBTEST( test_scalar<double>(2*3*4*5*7) );
00246
00247 #ifdef EIGEN_HAS_FFTWL
00248 CALL_SUBTEST( test_complex<long double>(32) );
00249 CALL_SUBTEST( test_complex<long double>(256) );
00250 CALL_SUBTEST( test_complex<long double>(3*8) );
00251 CALL_SUBTEST( test_complex<long double>(5*32) );
00252 CALL_SUBTEST( test_complex<long double>(2*3*4) );
00253 CALL_SUBTEST( test_complex<long double>(2*3*4*5) );
00254 CALL_SUBTEST( test_complex<long double>(2*3*4*5*7) );
00255
00256 CALL_SUBTEST( test_scalar<long double>(32) );
00257 CALL_SUBTEST( test_scalar<long double>(45) );
00258 CALL_SUBTEST( test_scalar<long double>(50) );
00259 CALL_SUBTEST( test_scalar<long double>(256) );
00260 CALL_SUBTEST( test_scalar<long double>(2*3*4*5*7) );
00261 #endif
00262 }