00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef EIGEN_FFT_H
00026 #define EIGEN_FFT_H
00027
00028 #include <complex>
00029 #include <vector>
00030 #include <map>
00031 #include <Eigen/Core>
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 #ifdef EIGEN_FFTW_DEFAULT
00089
00090 # include <fftw3.h>
00091 namespace Eigen {
00092 # include "src/FFT/ei_fftw_impl.h"
00093
00094 template <typename T> struct default_fft_impl : public internal::fftw_impl<T> {};
00095 }
00096 #elif defined EIGEN_MKL_DEFAULT
00097
00098
00099 namespace Eigen {
00100 # include "src/FFT/ei_imklfft_impl.h"
00101 template <typename T> struct default_fft_impl : public internal::imklfft_impl {};
00102 }
00103 #else
00104
00105
00106 namespace Eigen {
00107 # include "src/FFT/ei_kissfft_impl.h"
00108 template <typename T>
00109 struct default_fft_impl : public internal::kissfft_impl<T> {};
00110 }
00111 #endif
00112
00113 namespace Eigen {
00114
00115
00116
00117 template<typename T_SrcMat,typename T_FftIfc> struct fft_fwd_proxy;
00118 template<typename T_SrcMat,typename T_FftIfc> struct fft_inv_proxy;
00119
00120 namespace internal {
00121 template<typename T_SrcMat,typename T_FftIfc>
00122 struct traits< fft_fwd_proxy<T_SrcMat,T_FftIfc> >
00123 {
00124 typedef typename T_SrcMat::PlainObject ReturnType;
00125 };
00126 template<typename T_SrcMat,typename T_FftIfc>
00127 struct traits< fft_inv_proxy<T_SrcMat,T_FftIfc> >
00128 {
00129 typedef typename T_SrcMat::PlainObject ReturnType;
00130 };
00131 }
00132
00133 template<typename T_SrcMat,typename T_FftIfc>
00134 struct fft_fwd_proxy
00135 : public ReturnByValue<fft_fwd_proxy<T_SrcMat,T_FftIfc> >
00136 {
00137 typedef DenseIndex Index;
00138
00139 fft_fwd_proxy(const T_SrcMat& src,T_FftIfc & fft, Index nfft) : m_src(src),m_ifc(fft), m_nfft(nfft) {}
00140
00141 template<typename T_DestMat> void evalTo(T_DestMat& dst) const;
00142
00143 Index rows() const { return m_src.rows(); }
00144 Index cols() const { return m_src.cols(); }
00145 protected:
00146 const T_SrcMat & m_src;
00147 T_FftIfc & m_ifc;
00148 Index m_nfft;
00149 private:
00150 fft_fwd_proxy& operator=(const fft_fwd_proxy&);
00151 };
00152
00153 template<typename T_SrcMat,typename T_FftIfc>
00154 struct fft_inv_proxy
00155 : public ReturnByValue<fft_inv_proxy<T_SrcMat,T_FftIfc> >
00156 {
00157 typedef DenseIndex Index;
00158
00159 fft_inv_proxy(const T_SrcMat& src,T_FftIfc & fft, Index nfft) : m_src(src),m_ifc(fft), m_nfft(nfft) {}
00160
00161 template<typename T_DestMat> void evalTo(T_DestMat& dst) const;
00162
00163 Index rows() const { return m_src.rows(); }
00164 Index cols() const { return m_src.cols(); }
00165 protected:
00166 const T_SrcMat & m_src;
00167 T_FftIfc & m_ifc;
00168 Index m_nfft;
00169 private:
00170 fft_inv_proxy& operator=(const fft_inv_proxy&);
00171 };
00172
00173
00174 template <typename T_Scalar,
00175 typename T_Impl=default_fft_impl<T_Scalar> >
00176 class FFT
00177 {
00178 public:
00179 typedef T_Impl impl_type;
00180 typedef DenseIndex Index;
00181 typedef typename impl_type::Scalar Scalar;
00182 typedef typename impl_type::Complex Complex;
00183
00184 enum Flag {
00185 Default=0,
00186 Unscaled=1,
00187 HalfSpectrum=2,
00188
00189 Speedy=32767
00190 };
00191
00192 FFT( const impl_type & impl=impl_type() , Flag flags=Default ) :m_impl(impl),m_flag(flags) { }
00193
00194 inline
00195 bool HasFlag(Flag f) const { return (m_flag & (int)f) == f;}
00196
00197 inline
00198 void SetFlag(Flag f) { m_flag |= (int)f;}
00199
00200 inline
00201 void ClearFlag(Flag f) { m_flag &= (~(int)f);}
00202
00203 inline
00204 void fwd( Complex * dst, const Scalar * src, Index nfft)
00205 {
00206 m_impl.fwd(dst,src,static_cast<int>(nfft));
00207 if ( HasFlag(HalfSpectrum) == false)
00208 ReflectSpectrum(dst,nfft);
00209 }
00210
00211 inline
00212 void fwd( Complex * dst, const Complex * src, Index nfft)
00213 {
00214 m_impl.fwd(dst,src,static_cast<int>(nfft));
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 template <typename _Input>
00226 inline
00227 void fwd( std::vector<Complex> & dst, const std::vector<_Input> & src)
00228 {
00229 if ( NumTraits<_Input>::IsComplex == 0 && HasFlag(HalfSpectrum) )
00230 dst.resize( (src.size()>>1)+1);
00231 else
00232 dst.resize(src.size());
00233 fwd(&dst[0],&src[0],src.size());
00234 }
00235
00236 template<typename InputDerived, typename ComplexDerived>
00237 inline
00238 void fwd( MatrixBase<ComplexDerived> & dst, const MatrixBase<InputDerived> & src, Index nfft=-1)
00239 {
00240 typedef typename ComplexDerived::Scalar dst_type;
00241 typedef typename InputDerived::Scalar src_type;
00242 EIGEN_STATIC_ASSERT_VECTOR_ONLY(InputDerived)
00243 EIGEN_STATIC_ASSERT_VECTOR_ONLY(ComplexDerived)
00244 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ComplexDerived,InputDerived)
00245 EIGEN_STATIC_ASSERT((internal::is_same<dst_type, Complex>::value),
00246 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00247 EIGEN_STATIC_ASSERT(int(InputDerived::Flags)&int(ComplexDerived::Flags)&DirectAccessBit,
00248 THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES)
00249
00250 if (nfft<1)
00251 nfft = src.size();
00252
00253 if ( NumTraits< src_type >::IsComplex == 0 && HasFlag(HalfSpectrum) )
00254 dst.derived().resize( (nfft>>1)+1);
00255 else
00256 dst.derived().resize(nfft);
00257
00258 if ( src.innerStride() != 1 || src.size() < nfft ) {
00259 Matrix<src_type,1,Dynamic> tmp;
00260 if (src.size()<nfft) {
00261 tmp.setZero(nfft);
00262 tmp.block(0,0,src.size(),1 ) = src;
00263 }else{
00264 tmp = src;
00265 }
00266 fwd( &dst[0],&tmp[0],nfft );
00267 }else{
00268 fwd( &dst[0],&src[0],nfft );
00269 }
00270 }
00271
00272 template<typename InputDerived>
00273 inline
00274 fft_fwd_proxy< MatrixBase<InputDerived>, FFT<T_Scalar,T_Impl> >
00275 fwd( const MatrixBase<InputDerived> & src, Index nfft=-1)
00276 {
00277 return fft_fwd_proxy< MatrixBase<InputDerived> ,FFT<T_Scalar,T_Impl> >( src, *this,nfft );
00278 }
00279
00280 template<typename InputDerived>
00281 inline
00282 fft_inv_proxy< MatrixBase<InputDerived>, FFT<T_Scalar,T_Impl> >
00283 inv( const MatrixBase<InputDerived> & src, Index nfft=-1)
00284 {
00285 return fft_inv_proxy< MatrixBase<InputDerived> ,FFT<T_Scalar,T_Impl> >( src, *this,nfft );
00286 }
00287
00288 inline
00289 void inv( Complex * dst, const Complex * src, Index nfft)
00290 {
00291 m_impl.inv( dst,src,static_cast<int>(nfft) );
00292 if ( HasFlag( Unscaled ) == false)
00293 scale(dst,Scalar(1./nfft),nfft);
00294 }
00295
00296 inline
00297 void inv( Scalar * dst, const Complex * src, Index nfft)
00298 {
00299 m_impl.inv( dst,src,static_cast<int>(nfft) );
00300 if ( HasFlag( Unscaled ) == false)
00301 scale(dst,Scalar(1./nfft),nfft);
00302 }
00303
00304 template<typename OutputDerived, typename ComplexDerived>
00305 inline
00306 void inv( MatrixBase<OutputDerived> & dst, const MatrixBase<ComplexDerived> & src, Index nfft=-1)
00307 {
00308 typedef typename ComplexDerived::Scalar src_type;
00309 typedef typename OutputDerived::Scalar dst_type;
00310 const bool realfft= (NumTraits<dst_type>::IsComplex == 0);
00311 EIGEN_STATIC_ASSERT_VECTOR_ONLY(OutputDerived)
00312 EIGEN_STATIC_ASSERT_VECTOR_ONLY(ComplexDerived)
00313 EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(ComplexDerived,OutputDerived)
00314 EIGEN_STATIC_ASSERT((internal::is_same<src_type, Complex>::value),
00315 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00316 EIGEN_STATIC_ASSERT(int(OutputDerived::Flags)&int(ComplexDerived::Flags)&DirectAccessBit,
00317 THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES)
00318
00319 if (nfft<1) {
00320 if ( realfft && HasFlag(HalfSpectrum) )
00321 nfft = 2*(src.size()-1);
00322 else
00323 nfft = src.size();
00324 }
00325 dst.derived().resize( nfft );
00326
00327
00328 Index resize_input= ( realfft && HasFlag(HalfSpectrum) )
00329 ? ( (nfft/2+1) - src.size() )
00330 : ( nfft - src.size() );
00331
00332 if ( src.innerStride() != 1 || resize_input ) {
00333
00334 Matrix<src_type,1,Dynamic> tmp;
00335 if ( resize_input ) {
00336 size_t ncopy = std::min(src.size(),src.size() + resize_input);
00337 tmp.setZero(src.size() + resize_input);
00338 if ( realfft && HasFlag(HalfSpectrum) ) {
00339
00340 tmp.head(ncopy) = src.head(ncopy);
00341 tmp(ncopy-1) = real(tmp(ncopy-1));
00342 }else{
00343 size_t nhead,ntail;
00344 nhead = 1+ncopy/2-1;
00345 ntail = ncopy/2-1;
00346 tmp.head(nhead) = src.head(nhead);
00347 tmp.tail(ntail) = src.tail(ntail);
00348 if (resize_input<0) {
00349 tmp(nhead) = ( src(nfft/2) + src( src.size() - nfft/2 ) )*src_type(.5);
00350 }else{
00351 tmp(nhead) = src(nhead) * src_type(.5);
00352 tmp(tmp.size()-nhead) = tmp(nhead);
00353 }
00354 }
00355 }else{
00356 tmp = src;
00357 }
00358 inv( &dst[0],&tmp[0], nfft);
00359 }else{
00360 inv( &dst[0],&src[0], nfft);
00361 }
00362 }
00363
00364 template <typename _Output>
00365 inline
00366 void inv( std::vector<_Output> & dst, const std::vector<Complex> & src,Index nfft=-1)
00367 {
00368 if (nfft<1)
00369 nfft = ( NumTraits<_Output>::IsComplex == 0 && HasFlag(HalfSpectrum) ) ? 2*(src.size()-1) : src.size();
00370 dst.resize( nfft );
00371 inv( &dst[0],&src[0],nfft);
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 inline
00387 impl_type & impl() {return m_impl;}
00388 private:
00389
00390 template <typename T_Data>
00391 inline
00392 void scale(T_Data * x,Scalar s,Index nx)
00393 {
00394 #if 1
00395 for (int k=0;k<nx;++k)
00396 *x++ *= s;
00397 #else
00398 if ( ((ptrdiff_t)x) & 15 )
00399 Matrix<T_Data, Dynamic, 1>::Map(x,nx) *= s;
00400 else
00401 Matrix<T_Data, Dynamic, 1>::MapAligned(x,nx) *= s;
00402
00403 #endif
00404 }
00405
00406 inline
00407 void ReflectSpectrum(Complex * freq, Index nfft)
00408 {
00409
00410 Index nhbins=(nfft>>1)+1;
00411 for (Index k=nhbins;k < nfft; ++k )
00412 freq[k] = conj(freq[nfft-k]);
00413 }
00414
00415 impl_type m_impl;
00416 int m_flag;
00417 };
00418
00419 template<typename T_SrcMat,typename T_FftIfc>
00420 template<typename T_DestMat> inline
00421 void fft_fwd_proxy<T_SrcMat,T_FftIfc>::evalTo(T_DestMat& dst) const
00422 {
00423 m_ifc.fwd( dst, m_src, m_nfft);
00424 }
00425
00426 template<typename T_SrcMat,typename T_FftIfc>
00427 template<typename T_DestMat> inline
00428 void fft_inv_proxy<T_SrcMat,T_FftIfc>::evalTo(T_DestMat& dst) const
00429 {
00430 m_ifc.inv( dst, m_src, m_nfft);
00431 }
00432
00433 }
00434 #endif
00435