| [765] | 1 | #include "fftwserver.h" | 
|---|
|  | 2 | #include "FFTW/fftw.h" | 
|---|
|  | 3 | #include "FFTW/rfftw.h" | 
|---|
|  | 4 |  | 
|---|
|  | 5 | class FFTWServerPlan{ | 
|---|
|  | 6 | public: | 
|---|
|  | 7 | FFTWServerPlan(int n, fftw_direction dir, bool fgreal=false); | 
|---|
|  | 8 | FFTWServerPlan(int nx, int ny, fftw_direction dir, bool fgreal=false); | 
|---|
|  | 9 | ~FFTWServerPlan(); | 
|---|
|  | 10 | void Recreate(int n); | 
|---|
|  | 11 | void Recreate(int nx, int ny); | 
|---|
|  | 12 |  | 
|---|
|  | 13 | int _n; | 
|---|
|  | 14 | int _nx, _ny; | 
|---|
|  | 15 | fftw_direction _dir; | 
|---|
|  | 16 |  | 
|---|
|  | 17 | fftw_plan p; | 
|---|
|  | 18 | rfftw_plan rp; | 
|---|
|  | 19 | fftwnd_plan pnd; | 
|---|
|  | 20 | rfftwnd_plan rpnd; | 
|---|
|  | 21 |  | 
|---|
|  | 22 | }; | 
|---|
|  | 23 |  | 
|---|
|  | 24 | FFTWServerPlan::FFTWServerPlan(int n, fftw_direction dir, bool fgreal) | 
|---|
|  | 25 | { | 
|---|
|  | 26 | if (n < 1) | 
|---|
|  | 27 | throw ParmError("FFTWServerPlan: Array size <= 0 !"); | 
|---|
|  | 28 | p = NULL; | 
|---|
|  | 29 | rp = NULL; | 
|---|
|  | 30 | pnd = NULL; | 
|---|
|  | 31 | rpnd = NULL; | 
|---|
|  | 32 | _nx = _ny = -10; | 
|---|
|  | 33 | _n = n; | 
|---|
|  | 34 | _dir = dir; | 
|---|
|  | 35 | if (fgreal) rp = rfftw_create_plan(n, dir, FFTW_ESTIMATE); | 
|---|
|  | 36 | else p = fftw_create_plan(n, dir, FFTW_ESTIMATE); | 
|---|
|  | 37 | } | 
|---|
|  | 38 | FFTWServerPlan::FFTWServerPlan(int nx, int ny, fftw_direction dir, bool fgreal) | 
|---|
|  | 39 | { | 
|---|
|  | 40 | if ( (nx < 1) || (ny <1) ) | 
|---|
|  | 41 | throw ParmError("FFTWServerPlan: Array size Nx or Ny <= 0 !"); | 
|---|
|  | 42 | p = NULL; | 
|---|
|  | 43 | rp = NULL; | 
|---|
|  | 44 | pnd = NULL; | 
|---|
|  | 45 | rpnd = NULL; | 
|---|
|  | 46 | _n = -10; | 
|---|
|  | 47 | _nx = nx; | 
|---|
|  | 48 | _ny = ny; | 
|---|
|  | 49 | _dir = dir; | 
|---|
|  | 50 | int sz[2]; | 
|---|
|  | 51 | sz[0]= nx; sz[1] = ny; | 
|---|
|  | 52 | if (fgreal) rpnd = rfftwnd_create_plan(2, sz, dir, FFTW_ESTIMATE); | 
|---|
|  | 53 | else pnd = fftwnd_create_plan(2, sz, dir, FFTW_ESTIMATE); | 
|---|
|  | 54 | } | 
|---|
|  | 55 |  | 
|---|
|  | 56 | FFTWServerPlan::~FFTWServerPlan() | 
|---|
|  | 57 | { | 
|---|
|  | 58 | if (p) fftw_destroy_plan(p); | 
|---|
|  | 59 | if (rp) rfftw_destroy_plan(rp); | 
|---|
|  | 60 | if (pnd) fftwnd_destroy_plan(pnd); | 
|---|
|  | 61 | if (rpnd) rfftwnd_destroy_plan(rpnd); | 
|---|
|  | 62 | } | 
|---|
|  | 63 |  | 
|---|
|  | 64 | void | 
|---|
|  | 65 | FFTWServerPlan::Recreate(int n) | 
|---|
|  | 66 | { | 
|---|
|  | 67 | if (n < 1) | 
|---|
|  | 68 | throw ParmError("FFTWServerPlan::Recreate(n) n < 0 !"); | 
|---|
|  | 69 | if ((_nx > 0) || (_ny > 0)) | 
|---|
|  | 70 | throw ParmError("FFTWServerPlan::Recreate(n) Nx or Ny > 0 !"); | 
|---|
|  | 71 | if (n == _n) return; | 
|---|
|  | 72 | _n = n; | 
|---|
|  | 73 | if (p) { | 
|---|
|  | 74 | fftw_destroy_plan(p); | 
|---|
|  | 75 | p = fftw_create_plan(n, _dir, FFTW_ESTIMATE); | 
|---|
|  | 76 | } | 
|---|
|  | 77 | else { | 
|---|
|  | 78 | rfftw_destroy_plan(rp); | 
|---|
|  | 79 | rp = rfftw_create_plan(n, _dir, FFTW_ESTIMATE); | 
|---|
|  | 80 | } | 
|---|
|  | 81 | } | 
|---|
|  | 82 |  | 
|---|
|  | 83 | void | 
|---|
|  | 84 | FFTWServerPlan::Recreate(int nx, int ny) | 
|---|
|  | 85 | { | 
|---|
|  | 86 | if ( (nx < 1) || (ny <1) ) | 
|---|
|  | 87 | throw ParmError("FFTWServerPlan:Recreate(nx, ny) size Nx or Ny <= 0 !"); | 
|---|
|  | 88 | if (_n > 0) | 
|---|
|  | 89 | throw ParmError("FFTWServerPlan::Recreate(nx, ny) N > 0 !"); | 
|---|
|  | 90 | if ((nx == _nx) && (ny == _ny)) return; | 
|---|
|  | 91 | _nx = nx; | 
|---|
|  | 92 | _ny = ny; | 
|---|
|  | 93 | int sz[2]; | 
|---|
|  | 94 | sz[0]= nx; sz[1] = ny; | 
|---|
|  | 95 | if (pnd) { | 
|---|
|  | 96 | fftwnd_destroy_plan(pnd); | 
|---|
|  | 97 | pnd = fftwnd_create_plan(2, sz,_dir, FFTW_ESTIMATE); | 
|---|
|  | 98 | } | 
|---|
|  | 99 | else { | 
|---|
|  | 100 | rfftwnd_destroy_plan(rpnd); | 
|---|
|  | 101 | rpnd = rfftwnd_create_plan(2, sz, _dir, FFTW_ESTIMATE); | 
|---|
|  | 102 | } | 
|---|
|  | 103 |  | 
|---|
|  | 104 | } | 
|---|
|  | 105 |  | 
|---|
|  | 106 |  | 
|---|
|  | 107 | /* --Methode-- */ | 
|---|
|  | 108 | FFTWServer::FFTWServer() | 
|---|
|  | 109 | : FFTServerInterface("FFTServer using FFTW package") | 
|---|
|  | 110 | { | 
|---|
|  | 111 | _p1df = NULL; | 
|---|
|  | 112 | _p1db = NULL; | 
|---|
|  | 113 | _p2df = NULL; | 
|---|
|  | 114 | _p2db = NULL; | 
|---|
|  | 115 |  | 
|---|
|  | 116 | _p1drf = NULL; | 
|---|
|  | 117 | _p1drb = NULL; | 
|---|
|  | 118 | _p2drf = NULL; | 
|---|
|  | 119 | _p2drb = NULL; | 
|---|
|  | 120 | } | 
|---|
|  | 121 |  | 
|---|
|  | 122 |  | 
|---|
|  | 123 | /* --Methode-- */ | 
|---|
|  | 124 | FFTWServer::~FFTWServer() | 
|---|
|  | 125 | { | 
|---|
|  | 126 | if (_p1df) delete _p1df ; | 
|---|
|  | 127 | if (_p1db) delete _p1db ; | 
|---|
|  | 128 | if (_p2df) delete _p2df ; | 
|---|
|  | 129 | if (_p2db) delete _p2db ; | 
|---|
|  | 130 |  | 
|---|
|  | 131 | if (_p1drf) delete _p1drf ; | 
|---|
|  | 132 | if (_p1drb) delete _p1drb ; | 
|---|
|  | 133 | if (_p2drf) delete _p2drf ; | 
|---|
|  | 134 | if (_p2drb) delete _p2drb ; | 
|---|
|  | 135 | } | 
|---|
|  | 136 |  | 
|---|
|  | 137 | /* --Methode-- */ | 
|---|
|  | 138 | FFTServerInterface * FFTWServer::Clone() | 
|---|
|  | 139 | { | 
|---|
|  | 140 | return (new FFTWServer) ; | 
|---|
|  | 141 | } | 
|---|
|  | 142 |  | 
|---|
|  | 143 | /* --Methode-- */ | 
|---|
|  | 144 | void | 
|---|
|  | 145 | FFTWServer::FFTForward(TVector< complex<double> > const & in, TVector< complex<double> > & out) | 
|---|
|  | 146 | { | 
|---|
|  | 147 | if (_p1df) _p1df->Recreate(in.NElts()); | 
|---|
|  | 148 | else _p1df = new FFTWServerPlan(in.NElts(), FFTW_FORWARD, false); | 
|---|
|  | 149 | out.ReSize(in.NElts()); | 
|---|
|  | 150 | fftw_one(_p1df->p, (fftw_complex *)(in.Data()) , (fftw_complex *)(out.Data()) ); | 
|---|
|  | 151 | if(this->getNormalize()) out=out/complex<double>(pow(in.NElts(),0.5),0.); | 
|---|
|  | 152 | } | 
|---|
|  | 153 | /* --Methode-- */ | 
|---|
|  | 154 | void FFTWServer::FFTBackward(TVector< complex<double> > const & in, TVector< complex<double> > & out) | 
|---|
|  | 155 | { | 
|---|
|  | 156 | if (_p1db) _p1db->Recreate(in.NElts()); | 
|---|
|  | 157 | else _p1db = new FFTWServerPlan(in.NElts(), FFTW_BACKWARD, false); | 
|---|
|  | 158 | out.ReSize(in.NElts()); | 
|---|
|  | 159 | fftw_one(_p1db->p, (fftw_complex *)(in.Data()) , (fftw_complex *)(out.Data()) ); | 
|---|
|  | 160 | if(this->getNormalize()) out=out/complex<double>(pow(in.NElts(),0.5),0.); | 
|---|
|  | 161 |  | 
|---|
|  | 162 | } | 
|---|
|  | 163 |  | 
|---|
|  | 164 |  | 
|---|
|  | 165 | void FFTWServer::FFTForward(TVector< double > const & in, TVector< complex<double> > & out) | 
|---|
|  | 166 | { | 
|---|
|  | 167 | int size = in.NElts()/2; | 
|---|
|  | 168 |  | 
|---|
|  | 169 | if(in.NElts()%2 != 0)  { size = in.NElts()/2 +1;} | 
|---|
|  | 170 | else  { size = in.NElts()/2 +1 ;} | 
|---|
|  | 171 |  | 
|---|
|  | 172 | TVector< double > const outTemp(in.NElts()); | 
|---|
|  | 173 | out.ReSize(size); | 
|---|
|  | 174 | if (_p1drf) _p1drf->Recreate(in.NElts()); | 
|---|
|  | 175 | else _p1drf = new FFTWServerPlan(in.NElts(), FFTW_REAL_TO_COMPLEX, true); | 
|---|
|  | 176 | rfftw_one(_p1drf->rp, (fftw_real *)(in.Data()) , (fftw_real *)(outTemp.Data())); | 
|---|
|  | 177 | ReShapetoCompl(outTemp, out); | 
|---|
|  | 178 | if(this->getNormalize()) out=out/complex<double>(pow(in.NElts(),0.5),0.); | 
|---|
|  | 179 | } | 
|---|
|  | 180 |  | 
|---|
|  | 181 |  | 
|---|
|  | 182 |  | 
|---|
|  | 183 | void FFTWServer::FFTBackward(TVector< complex<double> > const & in, TVector< double > & out) | 
|---|
|  | 184 | { | 
|---|
|  | 185 | int size; | 
|---|
|  | 186 | if(in(in.NElts()).imag()  == 0) { size = 2*in.NElts()-2;} | 
|---|
|  | 187 | else { size = 2*in.NElts()-1;} | 
|---|
|  | 188 |  | 
|---|
|  | 189 | TVector< double > inTemp(size); | 
|---|
|  | 190 | out.ReSize(size); | 
|---|
|  | 191 |  | 
|---|
|  | 192 | if (_p1drb) _p1drb->Recreate(size); | 
|---|
|  | 193 | else _p1drb = new FFTWServerPlan(size, FFTW_COMPLEX_TO_REAL, true); | 
|---|
|  | 194 |  | 
|---|
|  | 195 | ReShapetoReal(in, inTemp); | 
|---|
|  | 196 | rfftw_one(_p1drb->rp, (fftw_real *)(inTemp.Data()) , (fftw_real *)(out.Data())); | 
|---|
|  | 197 | if(this->getNormalize()) out=out/pow(size,0.5); | 
|---|
|  | 198 | } | 
|---|
|  | 199 |  | 
|---|
|  | 200 | /* --Methode-- */ | 
|---|
|  | 201 | void FFTWServer::FFTForward(TMatrix< complex<double> > const & in, TMatrix< complex<double> > & out) | 
|---|
|  | 202 | { | 
|---|
|  | 203 | out.ReSize(in.NRows(),in.NCols()); | 
|---|
|  | 204 |  | 
|---|
|  | 205 | if (_p2df) _p2df->Recreate( in.NRows(),in.NCols()); | 
|---|
|  | 206 | else _p2df = new FFTWServerPlan( in.NCols(),in.NRows(), FFTW_FORWARD, false); | 
|---|
|  | 207 |  | 
|---|
|  | 208 | fftwnd_one(_p2df->pnd, (fftw_complex *)(in.Data()) , (fftw_complex *)(out.Data()) ); | 
|---|
|  | 209 | if(this->getNormalize()) out=out/complex<double>(pow(in.NRows()*in.NCols(),0.5),0.); | 
|---|
|  | 210 | } | 
|---|
|  | 211 |  | 
|---|
|  | 212 | /* --Methode-- */ | 
|---|
|  | 213 | void FFTWServer::FFTBackward(TMatrix< complex<double> > const & in, TMatrix< complex<double> > & out) | 
|---|
|  | 214 | { | 
|---|
|  | 215 | if (_p2db) _p2db->Recreate(in.NCols(), in.NRows()); | 
|---|
|  | 216 | else _p2db = new FFTWServerPlan(in.NCols(), in.NRows(), FFTW_BACKWARD, false); | 
|---|
|  | 217 | out.ReSize(in.NRows(), in.NCols()); | 
|---|
|  | 218 | fftwnd_one(_p2db->pnd, (fftw_complex *)(in.Data()) , (fftw_complex *)(out.Data()) ); | 
|---|
|  | 219 | if(this->getNormalize()) out=out/complex<double>(pow(in.NRows()*in.NCols(),0.5),0.); | 
|---|
|  | 220 |  | 
|---|
|  | 221 | } | 
|---|
|  | 222 |  | 
|---|
|  | 223 |  | 
|---|
|  | 224 | /* --Methode-- */ | 
|---|
|  | 225 | void FFTWServer::FFTForward(TMatrix< double > const & in, TMatrix< complex<double> > & out) | 
|---|
|  | 226 | { | 
|---|
|  | 227 |  | 
|---|
|  | 228 | TMatrix< double > inNew(in.NCols(),in.NRows()); | 
|---|
|  | 229 | for(int i=0; i<in.NRows(); i++) | 
|---|
|  | 230 | for(int j=0;j<in.NCols(); j++) | 
|---|
|  | 231 | inNew(j,i) = in(i,j); | 
|---|
|  | 232 |  | 
|---|
|  | 233 | if (_p2drf) _p2drf->Recreate(inNew.NRows(),inNew.NCols()); | 
|---|
|  | 234 | else _p2drf = new FFTWServerPlan(inNew.NRows(), inNew.NCols(),FFTW_REAL_TO_COMPLEX, true); | 
|---|
| [834] | 235 | //  rfftwnd_plan p; | 
|---|
| [765] | 236 | TMatrix< complex<double> > outTemp; | 
|---|
|  | 237 | outTemp.ReSize(in.NRows(),in.NCols()); | 
|---|
|  | 238 |  | 
|---|
|  | 239 | rfftwnd_one_real_to_complex(_p2drf->rpnd, (fftw_real *)(in.Data()) , (fftw_complex *)(out.Data()) ); | 
|---|
|  | 240 | } | 
|---|
|  | 241 |  | 
|---|
|  | 242 | /* --Methode-- */ | 
|---|
|  | 243 | void FFTWServer::FFTBackward(TMatrix< complex<double> > const & in, TMatrix< double > & out) | 
|---|
|  | 244 | { | 
|---|
|  | 245 |  | 
|---|
|  | 246 | TMatrix< complex<double> > inNew(in.NCols(),in.NRows()); | 
|---|
|  | 247 | for(int i=0; i<in.NRows(); i++) | 
|---|
|  | 248 | for(int j=0;j<in.NCols(); j++) | 
|---|
|  | 249 | inNew(j,i) = in(i,j); | 
|---|
|  | 250 |  | 
|---|
|  | 251 | if (_p2drb) _p2drb->Recreate(inNew.NRows(),inNew.NCols()); | 
|---|
|  | 252 | else _p2drb = new FFTWServerPlan(inNew.NRows(), inNew.NCols(),FFTW_COMPLEX_TO_REAL, true); | 
|---|
| [834] | 253 | //  rfftwnd_plan p; | 
|---|
| [765] | 254 | out.ReSize(in.NRows(),in.NCols()); | 
|---|
|  | 255 |  | 
|---|
|  | 256 | rfftwnd_one_complex_to_real(_p2drb->rpnd, (fftw_complex *)(in.Data()) , (fftw_real *)(out.Data()) ); | 
|---|
|  | 257 | cout << " in the function !!!" << endl; | 
|---|
|  | 258 | if(this->getNormalize()) | 
|---|
|  | 259 | { | 
|---|
|  | 260 | double norm = (double)(in.NRows()*in.NCols()); | 
|---|
|  | 261 | out=out/norm; | 
|---|
|  | 262 | } | 
|---|
|  | 263 | } | 
|---|
|  | 264 |  | 
|---|
|  | 265 |  | 
|---|
|  | 266 | /* --Methode-- */ | 
|---|
|  | 267 | void FFTWServer::ReShapetoReal( TVector< complex<double> > const & in, TVector< double >  & out) | 
|---|
|  | 268 | { | 
|---|
|  | 269 | int N = in.NElts(); | 
|---|
| [834] | 270 | int i; | 
|---|
| [765] | 271 | if (in(in.NElts()).imag() == 0) | 
|---|
|  | 272 | { | 
|---|
|  | 273 | out(0) = in(0).real(); | 
|---|
| [834] | 274 | for(i=1; i<in.NElts(); i++) | 
|---|
| [765] | 275 | { | 
|---|
|  | 276 | out(i) = in(i).real(); | 
|---|
|  | 277 | } | 
|---|
| [834] | 278 | for(i=1; i<in.NElts(); i++) | 
|---|
| [765] | 279 | { | 
|---|
|  | 280 | out(i+in.NElts()-1) = in(in.NElts()-i-1).imag(); | 
|---|
|  | 281 | } | 
|---|
|  | 282 | } | 
|---|
|  | 283 | else | 
|---|
|  | 284 | { | 
|---|
|  | 285 | out(0) = in(0).real(); | 
|---|
| [834] | 286 | for(i=1; i<in.NElts(); i++) | 
|---|
| [765] | 287 | { | 
|---|
|  | 288 | out(i) = in(i).real(); | 
|---|
|  | 289 | } | 
|---|
| [834] | 290 | for(i=1; i<in.NElts(); i++) | 
|---|
| [765] | 291 | { | 
|---|
|  | 292 | out(i+in.NElts()-1) = in(in.NElts()-i).imag(); | 
|---|
|  | 293 | } | 
|---|
|  | 294 | } | 
|---|
|  | 295 | //  for(int k=0; k<out.NElts(); k++) cout << "ReShapetoReal out " << k << " " << out(k) << endl; | 
|---|
|  | 296 | } | 
|---|
|  | 297 |  | 
|---|
|  | 298 |  | 
|---|
|  | 299 | /* --Methode-- */ | 
|---|
|  | 300 | void FFTWServer::ReShapetoCompl(TVector< double > const & in, TVector< complex<double> > & out) | 
|---|
|  | 301 | { | 
|---|
|  | 302 | int N = in.NElts(); | 
|---|
|  | 303 | //  for(int k=0; k<in.NElts(); k++) cout << "ReShapetoCompl in " << k << " "  << in(k) << endl; | 
|---|
|  | 304 | out(0) = complex<double> (in(0),0.); | 
|---|
|  | 305 | if(in.NElts()%2 !=0) | 
|---|
|  | 306 | { | 
|---|
|  | 307 | for(int k=1;k<=N/2+1;k++) | 
|---|
|  | 308 | { | 
|---|
|  | 309 | out(k) =  complex<double> (in(k),in(N-k)); | 
|---|
|  | 310 | } | 
|---|
|  | 311 | } | 
|---|
|  | 312 | else | 
|---|
|  | 313 | { | 
|---|
|  | 314 | for(int k=1;k<N/2;k++) | 
|---|
|  | 315 | { | 
|---|
|  | 316 | out(k) =  complex<double> (in(k),in(N-k)); | 
|---|
|  | 317 | } | 
|---|
|  | 318 | out(N/2) = complex<double> (in(N/2),0.); | 
|---|
|  | 319 | } | 
|---|
|  | 320 | //  for(int k=0; k<out.NElts(); k++) cout << "ReShapetoCompl out " << k << " "  << out(k) << endl; | 
|---|
|  | 321 | } | 
|---|
|  | 322 |  | 
|---|