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 namespace internal {
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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
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
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
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
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
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 }
00271
00272