ei_fftw_impl.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra. 
00003 //
00004 // Copyright (C) 2009 Mark Borgerding mark a borgerding net
00005 //
00006 // Eigen is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 3 of the License, or (at your option) any later version.
00010 //
00011 // Alternatively, you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public License as
00013 // published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00017 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License and a copy of the GNU General Public License along with
00023 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00024 
00025 namespace internal {
00026 
00027   // FFTW uses non-const arguments
00028   // so we must use ugly const_cast calls for all the args it uses
00029   //
00030   // This should be safe as long as 
00031   // 1. we use FFTW_ESTIMATE for all our planning
00032   //       see the FFTW docs section 4.3.2 "Planner Flags"
00033   // 2. fftw_complex is compatible with std::complex
00034   //    This assumes std::complex<T> layout is array of size 2 with real,imag
00035   template <typename T> 
00036   inline 
00037   T * fftw_cast(const T* p)
00038   { 
00039       return const_cast<T*>( p); 
00040   }
00041 
00042   inline 
00043   fftw_complex * fftw_cast( const std::complex<double> * p)
00044   {
00045       return const_cast<fftw_complex*>( reinterpret_cast<const fftw_complex*>(p) ); 
00046   }
00047 
00048   inline 
00049   fftwf_complex * fftw_cast( const std::complex<float> * p)
00050   { 
00051       return const_cast<fftwf_complex*>( reinterpret_cast<const fftwf_complex*>(p) ); 
00052   }
00053 
00054   inline 
00055   fftwl_complex * fftw_cast( const std::complex<long double> * p)
00056   { 
00057       return const_cast<fftwl_complex*>( reinterpret_cast<const fftwl_complex*>(p) ); 
00058   }
00059 
00060   template <typename T> 
00061   struct fftw_plan {};
00062 
00063   template <> 
00064   struct fftw_plan<float>
00065   {
00066       typedef float scalar_type;
00067       typedef fftwf_complex complex_type;
00068       fftwf_plan m_plan;
00069       fftw_plan() :m_plan(NULL) {}
00070       ~fftw_plan() {if (m_plan) fftwf_destroy_plan(m_plan);}
00071 
00072       inline
00073       void fwd(complex_type * dst,complex_type * src,int nfft) {
00074           if (m_plan==NULL) m_plan = fftwf_plan_dft_1d(nfft,src,dst, FFTW_FORWARD, FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00075           fftwf_execute_dft( m_plan, src,dst);
00076       }
00077       inline
00078       void inv(complex_type * dst,complex_type * src,int nfft) {
00079           if (m_plan==NULL) m_plan = fftwf_plan_dft_1d(nfft,src,dst, FFTW_BACKWARD , FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00080           fftwf_execute_dft( m_plan, src,dst);
00081       }
00082       inline
00083       void fwd(complex_type * dst,scalar_type * src,int nfft) {
00084           if (m_plan==NULL) m_plan = fftwf_plan_dft_r2c_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00085           fftwf_execute_dft_r2c( m_plan,src,dst);
00086       }
00087       inline
00088       void inv(scalar_type * dst,complex_type * src,int nfft) {
00089           if (m_plan==NULL)
00090               m_plan = fftwf_plan_dft_c2r_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00091           fftwf_execute_dft_c2r( m_plan, src,dst);
00092       }
00093 
00094       inline 
00095       void fwd2( complex_type * dst,complex_type * src,int n0,int n1) {
00096           if (m_plan==NULL) m_plan = fftwf_plan_dft_2d(n0,n1,src,dst,FFTW_FORWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00097           fftwf_execute_dft( m_plan, src,dst);
00098       }
00099       inline 
00100       void inv2( complex_type * dst,complex_type * src,int n0,int n1) {
00101           if (m_plan==NULL) m_plan = fftwf_plan_dft_2d(n0,n1,src,dst,FFTW_BACKWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00102           fftwf_execute_dft( m_plan, src,dst);
00103       }
00104 
00105   };
00106   template <> 
00107   struct fftw_plan<double>
00108   {
00109       typedef double scalar_type;
00110       typedef fftw_complex complex_type;
00111       ::fftw_plan m_plan;
00112       fftw_plan() :m_plan(NULL) {}
00113       ~fftw_plan() {if (m_plan) fftw_destroy_plan(m_plan);}
00114 
00115       inline
00116       void fwd(complex_type * dst,complex_type * src,int nfft) {
00117           if (m_plan==NULL) m_plan = fftw_plan_dft_1d(nfft,src,dst, FFTW_FORWARD, FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00118           fftw_execute_dft( m_plan, src,dst);
00119       }
00120       inline
00121       void inv(complex_type * dst,complex_type * src,int nfft) {
00122           if (m_plan==NULL) m_plan = fftw_plan_dft_1d(nfft,src,dst, FFTW_BACKWARD , FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00123           fftw_execute_dft( m_plan, src,dst);
00124       }
00125       inline
00126       void fwd(complex_type * dst,scalar_type * src,int nfft) {
00127           if (m_plan==NULL) m_plan = fftw_plan_dft_r2c_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00128           fftw_execute_dft_r2c( m_plan,src,dst);
00129       }
00130       inline
00131       void inv(scalar_type * dst,complex_type * src,int nfft) {
00132           if (m_plan==NULL)
00133               m_plan = fftw_plan_dft_c2r_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00134           fftw_execute_dft_c2r( m_plan, src,dst);
00135       }
00136       inline 
00137       void fwd2( complex_type * dst,complex_type * src,int n0,int n1) {
00138           if (m_plan==NULL) m_plan = fftw_plan_dft_2d(n0,n1,src,dst,FFTW_FORWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00139           fftw_execute_dft( m_plan, src,dst);
00140       }
00141       inline 
00142       void inv2( complex_type * dst,complex_type * src,int n0,int n1) {
00143           if (m_plan==NULL) m_plan = fftw_plan_dft_2d(n0,n1,src,dst,FFTW_BACKWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00144           fftw_execute_dft( m_plan, src,dst);
00145       }
00146   };
00147   template <> 
00148   struct fftw_plan<long double>
00149   {
00150       typedef long double scalar_type;
00151       typedef fftwl_complex complex_type;
00152       fftwl_plan m_plan;
00153       fftw_plan() :m_plan(NULL) {}
00154       ~fftw_plan() {if (m_plan) fftwl_destroy_plan(m_plan);}
00155 
00156       inline
00157       void fwd(complex_type * dst,complex_type * src,int nfft) {
00158           if (m_plan==NULL) m_plan = fftwl_plan_dft_1d(nfft,src,dst, FFTW_FORWARD, FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00159           fftwl_execute_dft( m_plan, src,dst);
00160       }
00161       inline
00162       void inv(complex_type * dst,complex_type * src,int nfft) {
00163           if (m_plan==NULL) m_plan = fftwl_plan_dft_1d(nfft,src,dst, FFTW_BACKWARD , FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00164           fftwl_execute_dft( m_plan, src,dst);
00165       }
00166       inline
00167       void fwd(complex_type * dst,scalar_type * src,int nfft) {
00168           if (m_plan==NULL) m_plan = fftwl_plan_dft_r2c_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00169           fftwl_execute_dft_r2c( m_plan,src,dst);
00170       }
00171       inline
00172       void inv(scalar_type * dst,complex_type * src,int nfft) {
00173           if (m_plan==NULL)
00174               m_plan = fftwl_plan_dft_c2r_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00175           fftwl_execute_dft_c2r( m_plan, src,dst);
00176       }
00177       inline 
00178       void fwd2( complex_type * dst,complex_type * src,int n0,int n1) {
00179           if (m_plan==NULL) m_plan = fftwl_plan_dft_2d(n0,n1,src,dst,FFTW_FORWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00180           fftwl_execute_dft( m_plan, src,dst);
00181       }
00182       inline 
00183       void inv2( complex_type * dst,complex_type * src,int n0,int n1) {
00184           if (m_plan==NULL) m_plan = fftwl_plan_dft_2d(n0,n1,src,dst,FFTW_BACKWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
00185           fftwl_execute_dft( m_plan, src,dst);
00186       }
00187   };
00188 
00189   template <typename _Scalar>
00190   struct fftw_impl
00191   {
00192       typedef _Scalar Scalar;
00193       typedef std::complex<Scalar> Complex;
00194 
00195       inline
00196       void clear() 
00197       {
00198         m_plans.clear();
00199       }
00200 
00201       // complex-to-complex forward FFT
00202       inline
00203       void fwd( Complex * dst,const Complex *src,int nfft)
00204       {
00205         get_plan(nfft,false,dst,src).fwd(fftw_cast(dst), fftw_cast(src),nfft );
00206       }
00207 
00208       // real-to-complex forward FFT
00209       inline
00210       void fwd( Complex * dst,const Scalar * src,int nfft) 
00211       {
00212           get_plan(nfft,false,dst,src).fwd(fftw_cast(dst), fftw_cast(src) ,nfft);
00213       }
00214 
00215       // 2-d complex-to-complex
00216       inline
00217       void fwd2(Complex * dst, const Complex * src, int n0,int n1)
00218       {
00219           get_plan(n0,n1,false,dst,src).fwd2(fftw_cast(dst), fftw_cast(src) ,n0,n1);
00220       }
00221 
00222       // inverse complex-to-complex
00223       inline
00224       void inv(Complex * dst,const Complex  *src,int nfft)
00225       {
00226         get_plan(nfft,true,dst,src).inv(fftw_cast(dst), fftw_cast(src),nfft );
00227       }
00228 
00229       // half-complex to scalar
00230       inline
00231       void inv( Scalar * dst,const Complex * src,int nfft) 
00232       {
00233         get_plan(nfft,true,dst,src).inv(fftw_cast(dst), fftw_cast(src),nfft );
00234       }
00235 
00236       // 2-d complex-to-complex
00237       inline
00238       void inv2(Complex * dst, const Complex * src, int n0,int n1)
00239       {
00240         get_plan(n0,n1,true,dst,src).inv2(fftw_cast(dst), fftw_cast(src) ,n0,n1);
00241       }
00242 
00243 
00244   protected:
00245       typedef fftw_plan<Scalar> PlanData;
00246 
00247       typedef std::map<int64_t,PlanData> PlanMap;
00248 
00249       PlanMap m_plans;
00250 
00251       inline
00252       PlanData & get_plan(int nfft,bool inverse,void * dst,const void * src)
00253       {
00254           bool inplace = (dst==src);
00255           bool aligned = ( (reinterpret_cast<size_t>(src)&15) | (reinterpret_cast<size_t>(dst)&15) ) == 0;
00256           int64_t key = ( (nfft<<3 ) | (inverse<<2) | (inplace<<1) | aligned ) << 1;
00257           return m_plans[key];
00258       }
00259 
00260       inline
00261       PlanData & get_plan(int n0,int n1,bool inverse,void * dst,const void * src)
00262       {
00263           bool inplace = (dst==src);
00264           bool aligned = ( (reinterpret_cast<size_t>(src)&15) | (reinterpret_cast<size_t>(dst)&15) ) == 0;
00265           int64_t key = ( ( (((int64_t)n0) << 30)|(n1<<3 ) | (inverse<<2) | (inplace<<1) | aligned ) << 1 ) + 1;
00266           return m_plans[key];
00267       }
00268   };
00269 
00270 } // end namespace internal
00271 
00272 /* vim: set filetype=cpp et sw=2 ts=2 ai: */


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:31:02