[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 |
|
---|