11 #include <unsupported/Eigen/FFT> 14 std::complex<T>
RandomCpx() {
return std::complex<T>( (T)(rand()/(T)RAND_MAX - .5), (T)(rand()/(T)RAND_MAX - .5) ); }
17 using namespace Eigen;
20 template <
typename T>
21 complex<long double>
promote(complex<T> x) {
return complex<long double>((
long double)x.real(),(
long double)x.imag()); }
23 complex<long double>
promote(
float x) {
return complex<long double>((
long double)x); }
24 complex<long double>
promote(
double x) {
return complex<long double>((
long double)x); }
25 complex<long double>
promote(
long double x) {
return complex<long double>((
long double)x); }
28 template <
typename VT1,
typename VT2>
29 long double fft_rmse(
const VT1 & fftbuf,
const VT2 & timebuf)
31 long double totalpower=0;
32 long double difpower=0;
33 long double pi =
acos((
long double)-1 );
34 for (
size_t k0=0;k0<(size_t)fftbuf.size();++k0) {
35 complex<long double> acc = 0;
36 long double phinc = (
long double)(-2.)*k0* pi / timebuf.size();
37 for (
size_t k1=0;k1<(size_t)timebuf.size();++k1) {
38 acc +=
promote( timebuf[k1] ) *
exp( complex<long double>(0,k1*phinc) );
41 complex<long double> x =
promote(fftbuf[k0]);
42 complex<long double> dif = acc - x;
46 cerr <<
"rmse:" <<
sqrt(difpower/totalpower) << endl;
47 return sqrt(difpower/totalpower);
50 template <
typename VT1,
typename VT2>
51 long double dif_rmse(
const VT1 buf1,
const VT2 buf2)
53 long double totalpower=0;
54 long double difpower=0;
55 size_t n = (
min)( buf1.size(),buf2.size() );
56 for (
size_t k=0;k<n;++k) {
58 difpower += (
long double)(
numext::abs2(buf1[k] - buf2[k]));
60 return sqrt(difpower/totalpower);
65 template<
int Container,
typename Scalar>
struct VectorType;
69 typedef vector<Scalar>
type;
77 template <
int Container,
typename T>
80 typedef typename FFT<T>::Complex Complex;
81 typedef typename FFT<T>::Scalar Scalar;
86 ScalarVector tbuf(nfft);
87 ComplexVector freqBuf;
88 for (
int k=0;k<nfft;++k)
89 tbuf[k]= (T)( rand()/(double)RAND_MAX - .5);
93 fft.SetFlag(fft.HalfSpectrum );
94 fft.fwd( freqBuf,tbuf);
95 VERIFY((
size_t)freqBuf.size() == (size_t)( (nfft>>1)+1) );
96 VERIFY( T(
fft_rmse(freqBuf,tbuf)) < test_precision<T>() );
98 fft.ClearFlag(fft.HalfSpectrum );
99 fft.fwd( freqBuf,tbuf);
100 VERIFY( (
size_t)freqBuf.size() == (size_t)nfft);
101 VERIFY( T(
fft_rmse(freqBuf,tbuf)) < test_precision<T>() );
107 fft.inv( tbuf2 , freqBuf);
108 VERIFY( T(
dif_rmse(tbuf,tbuf2)) < test_precision<T>() );
113 fft.SetFlag(fft.Unscaled);
115 fft.inv( tbuf3 , freqBuf);
117 for (
int k=0;k<nfft;++k)
118 tbuf3[k] *= T(1./nfft);
124 VERIFY( T(
dif_rmse(tbuf,tbuf3)) < test_precision<T>() );
127 fft.ClearFlag(fft.Unscaled);
128 fft.inv( tbuf2 , freqBuf);
129 VERIFY( T(
dif_rmse(tbuf,tbuf2)) < test_precision<T>() );
132 template <
typename T>
135 test_scalar_generic<StdVectorContainer,T>(nfft);
140 template <
int Container,
typename T>
143 typedef typename FFT<T>::Complex Complex;
148 ComplexVector inbuf(nfft);
149 ComplexVector outbuf;
151 for (
int k=0;k<nfft;++k)
152 inbuf[k]= Complex( (T)(rand()/(
double)RAND_MAX - .5), (T)(rand()/(
double)RAND_MAX - .5) );
153 fft.fwd( outbuf , inbuf);
155 VERIFY( T(
fft_rmse(outbuf,inbuf)) < test_precision<T>() );
156 fft.inv( buf3 , outbuf);
158 VERIFY( T(
dif_rmse(inbuf,buf3)) < test_precision<T>() );
162 fft.SetFlag(fft.Unscaled);
163 fft.inv( buf4 , outbuf);
164 for (
int k=0;k<nfft;++k)
165 buf4[k] *= T(1./nfft);
166 VERIFY( T(
dif_rmse(inbuf,buf4)) < test_precision<T>() );
169 fft.ClearFlag(fft.Unscaled);
170 fft.inv( buf3 , outbuf);
171 VERIFY( T(
dif_rmse(inbuf,buf3)) < test_precision<T>() );
174 template <
typename T>
177 test_complex_generic<StdVectorContainer,T>(nfft);
178 test_complex_generic<EigenVectorContainer,T>(nfft);
219 fft.SetFlag(fft.HalfSpectrum );
223 VERIFY( (out1-out2).norm() < test_precision<float>() );
225 VERIFY( (in1-in).norm() < test_precision<float>() );
233 CALL_SUBTEST( test_complex<float>(32) ); CALL_SUBTEST( test_complex<double>(32) );
234 CALL_SUBTEST( test_complex<float>(256) ); CALL_SUBTEST( test_complex<double>(256) );
235 CALL_SUBTEST( test_complex<float>(3*8) ); CALL_SUBTEST( test_complex<double>(3*8) );
236 CALL_SUBTEST( test_complex<float>(5*32) ); CALL_SUBTEST( test_complex<double>(5*32) );
237 CALL_SUBTEST( test_complex<float>(2*3*4) ); CALL_SUBTEST( test_complex<double>(2*3*4) );
238 CALL_SUBTEST( test_complex<float>(2*3*4*5) ); CALL_SUBTEST( test_complex<double>(2*3*4*5) );
239 CALL_SUBTEST( test_complex<float>(2*3*4*5*7) ); CALL_SUBTEST( test_complex<double>(2*3*4*5*7) );
241 CALL_SUBTEST( test_scalar<float>(32) ); CALL_SUBTEST( test_scalar<double>(32) );
242 CALL_SUBTEST( test_scalar<float>(45) ); CALL_SUBTEST( test_scalar<double>(45) );
243 CALL_SUBTEST( test_scalar<float>(50) ); CALL_SUBTEST( test_scalar<double>(50) );
244 CALL_SUBTEST( test_scalar<float>(256) ); CALL_SUBTEST( test_scalar<double>(256) );
245 CALL_SUBTEST( test_scalar<float>(2*3*4*5*7) ); CALL_SUBTEST( test_scalar<double>(2*3*4*5*7) );
247 #ifdef EIGEN_HAS_FFTWL 248 CALL_SUBTEST( test_complex<long double>(32) );
249 CALL_SUBTEST( test_complex<long double>(256) );
250 CALL_SUBTEST( test_complex<long double>(3*8) );
251 CALL_SUBTEST( test_complex<long double>(5*32) );
252 CALL_SUBTEST( test_complex<long double>(2*3*4) );
253 CALL_SUBTEST( test_complex<long double>(2*3*4*5) );
254 CALL_SUBTEST( test_complex<long double>(2*3*4*5*7) );
256 CALL_SUBTEST( test_scalar<long double>(32) );
257 CALL_SUBTEST( test_scalar<long double>(45) );
258 CALL_SUBTEST( test_scalar<long double>(50) );
259 CALL_SUBTEST( test_scalar<long double>(256) );
260 CALL_SUBTEST( test_scalar<long double>(2*3*4*5*7) );
void test_complex(int nfft)
EIGEN_DEVICE_FUNC const ExpReturnType exp() const
void test_complex_generic(int nfft)
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
void test_scalar(int nfft)
long double dif_rmse(const VT1 buf1, const VT2 buf2)
void test_return_by_value(int len)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Abs2ReturnType abs2() const
EIGEN_DEVICE_FUNC const AcosReturnType acos() const
complex< long double > promote(complex< T > x)
Matrix< Scalar, Dynamic, 1 > type
void test_scalar_generic(int nfft)
std::complex< T > RandomCpx()
long double fft_rmse(const VT1 &fftbuf, const VT2 &timebuf)