source: Sophya/trunk/SophyaExt/IFFTW/fftwserver.cc@ 1395

Last change on this file since 1395 was 1395, checked in by ansari, 25 years ago

Corrections- adaptation interface FFTServer - Reza 12/2/2001

File size: 11.4 KB
RevLine 
[765]1#include "fftwserver.h"
2#include "FFTW/fftw.h"
3#include "FFTW/rfftw.h"
4
[1391]5
6#define MAXND_FFTW 5
7
8class FFTWServerPlan {
[765]9public:
10 FFTWServerPlan(int n, fftw_direction dir, bool fgreal=false);
[1391]11 FFTWServerPlan(int nd, int * nxyz, fftw_direction dir, bool fgreal=false);
[765]12 ~FFTWServerPlan();
13 void Recreate(int n);
[1391]14 void Recreate(int nd, int * nxyz);
[765]15
[1391]16 int _n; // Array dimension for 1-d arrays
17 int _nd; // Nb of dimensions for n-d arrays
18 int _nxyz[MAXND_FFTW]; // Array dimensions for n-d arrays
[765]19 fftw_direction _dir;
20
21 fftw_plan p;
22 rfftw_plan rp;
23 fftwnd_plan pnd;
24 rfftwnd_plan rpnd;
25
26};
27
28FFTWServerPlan::FFTWServerPlan(int n, fftw_direction dir, bool fgreal)
29{
30 if (n < 1)
31 throw ParmError("FFTWServerPlan: Array size <= 0 !");
32 p = NULL;
33 rp = NULL;
34 pnd = NULL;
35 rpnd = NULL;
[1391]36 _nd = -1;
37 for(int k=0; k<MAXND_FFTW; k++) _nxyz[k] = -10;
[765]38 _n = n;
39 _dir = dir;
40 if (fgreal) rp = rfftw_create_plan(n, dir, FFTW_ESTIMATE);
41 else p = fftw_create_plan(n, dir, FFTW_ESTIMATE);
42}
[1391]43
44FFTWServerPlan::FFTWServerPlan(int nd, int * nxyz, fftw_direction dir, bool fgreal)
[765]45{
[1391]46 int k;
47 if (nd > MAXND_FFTW)
48 throw ParmError("FFTWServerPlan: Array rank (nd) > MAXND_FFTW !");
[765]49 p = NULL;
50 rp = NULL;
51 pnd = NULL;
52 rpnd = NULL;
53 _n = -10;
[1391]54 _nd = nd;
55 for(k=0; k<nd; k++) {
56 if (nxyz[k] < 1)
57 throw ParmError("FFTWServerPlan: One of the Array size <= 0 !");
58 _nxyz[k] = nxyz[k];
59 }
60 for(k=nd; k<MAXND_FFTW; k++) _nxyz[k] = -10;
[765]61 _dir = dir;
[1391]62 if (fgreal) rpnd = rfftwnd_create_plan(_nd, _nxyz, dir, FFTW_ESTIMATE);
63 else pnd = fftwnd_create_plan(_nd, _nxyz, dir, FFTW_ESTIMATE);
[765]64}
65
66FFTWServerPlan::~FFTWServerPlan()
67{
68 if (p) fftw_destroy_plan(p);
69 if (rp) rfftw_destroy_plan(rp);
70 if (pnd) fftwnd_destroy_plan(pnd);
71 if (rpnd) rfftwnd_destroy_plan(rpnd);
72}
73
74void
75FFTWServerPlan::Recreate(int n)
76{
77 if (n < 1)
78 throw ParmError("FFTWServerPlan::Recreate(n) n < 0 !");
[1391]79 if (_nd > 0)
80 throw ParmError("FFTWServerPlan::Recreate(n) Multi-dimensional plan ! > 0 !");
[765]81 if (n == _n) return;
82 _n = n;
83 if (p) {
84 fftw_destroy_plan(p);
85 p = fftw_create_plan(n, _dir, FFTW_ESTIMATE);
86 }
87 else {
88 rfftw_destroy_plan(rp);
89 rp = rfftw_create_plan(n, _dir, FFTW_ESTIMATE);
90 }
91}
92
93void
[1391]94FFTWServerPlan::Recreate(int nd, int * nxyz)
[765]95{
96 if (_n > 0)
[1391]97 throw ParmError("FFTWServerPlan::Recreate(nd, nxyz) 1-dimensional plan !");
98 int k;
99 if (nd == _nd) {
100 bool samepl = true;
101 for (int k=0; k<nd; k++)
102 if (nxyz[k] != _nxyz[k]) samepl = false;
103 if (samepl) return;
104 }
105 if (nd > MAXND_FFTW)
106 throw ParmError("FFTWServerPlan::Recreate(nd, nxyz) Array rank (nd) > MAXND_FFTW !");
107 _nd = nd;
108 for(k=0; k<nd; k++) {
109 if (nxyz[k] < 1)
110 throw ParmError("FFTWServerPlan::Recreate(nd, nxyz) One of the Array size <= 0 !");
111 _nxyz[k] = nxyz[k];
112 }
113 for(k=nd; k<MAXND_FFTW; k++) _nxyz[k] = -10;
[765]114 if (pnd) {
115 fftwnd_destroy_plan(pnd);
[1391]116 pnd = fftwnd_create_plan(_nd, _nxyz, _dir, FFTW_ESTIMATE);
[765]117 }
118 else {
119 rfftwnd_destroy_plan(rpnd);
[1391]120 rpnd = rfftwnd_create_plan(_nd, _nxyz, _dir, FFTW_ESTIMATE);
[765]121 }
122
123}
124
125
126/* --Methode-- */
127FFTWServer::FFTWServer()
128 : FFTServerInterface("FFTServer using FFTW package")
[1395]129 , ckR8("FFTWServer - ", true, false)
[1391]130
[765]131{
132 _p1df = NULL;
133 _p1db = NULL;
[1391]134 _pndf = NULL;
135 _pndb = NULL;
[765]136
137 _p1drf = NULL;
138 _p1drb = NULL;
[1391]139 _pndrf = NULL;
140 _pndrb = NULL;
[765]141}
142
143
144/* --Methode-- */
145FFTWServer::~FFTWServer()
146{
147 if (_p1df) delete _p1df ;
148 if (_p1db) delete _p1db ;
[1391]149 if (_pndf) delete _pndf ;
150 if (_pndb) delete _pndb ;
[765]151
152 if (_p1drf) delete _p1drf ;
153 if (_p1drb) delete _p1drb ;
[1391]154 if (_pndrf) delete _pndrf ;
155 if (_pndrb) delete _pndrb ;
[765]156}
157
158/* --Methode-- */
159FFTServerInterface * FFTWServer::Clone()
160{
161 return (new FFTWServer) ;
162}
163
164/* --Methode-- */
165void
[1391]166FFTWServer::FFTForward(TArray< complex<r_8> > const & in, TArray< complex<r_8> > & out)
[765]167{
[1391]168 int rank = ckR8.CheckResize(in, out);
169 if (rank == 1) { // One dimensional transform
170 if (_p1df) _p1df->Recreate(in.Size());
171 else _p1df = new FFTWServerPlan(in.Size(), FFTW_FORWARD, false);
172 fftw_one(_p1df->p, (fftw_complex *)(in.Data()) , (fftw_complex *)(out.Data()) );
173 }
174 else { // Multi dimensional
175 if (in.NbDimensions() > MAXND_FFTW)
176 throw ParmError("FFTWServer::FFTForward( complex<r_8>, complex<r_8> ) rank > MAXND_FFTW !");
177 int sz[MAXND_FFTW];
178 int k1 = 0;
179 int k2 = 0;
180 for(k1=in.NbDimensions()-1; k1>=0; k1--) {
181 sz[k2] = in.Size(k1); k2++;
182 }
183 if (_pndf) _pndf->Recreate(in.NbDimensions(), sz);
184 else _pndf = new FFTWServerPlan(in.NbDimensions(), sz, FFTW_FORWARD, false);
185 fftwnd_one(_pndf->pnd, (fftw_complex *)(in.Data()) , (fftw_complex *)(out.Data()) );
186 }
[1395]187 if(this->getNormalize()) out=out/complex<r_8>((double)in.Size(),0.);
[1391]188 return;
[765]189}
[1391]190
[765]191/* --Methode-- */
[1391]192void FFTWServer::FFTBackward(TArray< complex<r_8> > const & in, TArray< complex<r_8> > & out)
[765]193{
[1391]194 int rank = ckR8.CheckResize(in, out);
195 if (rank == 1) { // One dimensional transform
196 if (_p1db) _p1db->Recreate(in.Size());
197 else _p1db = new FFTWServerPlan(in.Size(), FFTW_BACKWARD, false);
198 fftw_one(_p1db->p, (fftw_complex *)(in.Data()) , (fftw_complex *)(out.Data()) );
199 }
200 else { // Multi dimensional
201 if (in.NbDimensions() > MAXND_FFTW)
202 throw ParmError("FFTWServer::FFTForward( complex<r_8>, complex<r_8> ) rank > MAXND_FFTW !");
203 int sz[MAXND_FFTW];
204 int k1 = 0;
205 int k2 = 0;
206 for(k1=in.NbDimensions()-1; k1>=0; k1--) {
207 sz[k2] = in.Size(k1); k2++;
208 }
209 if (_pndb) _pndb->Recreate(in.NbDimensions(), sz);
210 else _pndb = new FFTWServerPlan(in.NbDimensions(), sz, FFTW_BACKWARD, false);
211 }
[1395]212
[1391]213 return;
[765]214}
215
216
[1391]217void FFTWServer::FFTForward(TArray< r_8 > const & in, TArray< complex<r_8> > & out)
[765]218{
[1391]219 int rank = ckR8.CheckResize(in, out);
220 TArray<r_8> outtemp(in, false);
[765]221
[1391]222 if (rank == 1) { // One dimensional transform
223 if (_p1drf) _p1drf->Recreate(in.Size());
224 else _p1drf = new FFTWServerPlan(in.Size(), FFTW_REAL_TO_COMPLEX, true);
225 rfftw_one(_p1drf->rp, (fftw_real *)(in.Data()) , (fftw_real *)(outtemp.Data()));
226 ReShapetoCompl(outtemp, out);
227 }
228 else { // Multi dimensional
229 if (in.NbDimensions() > MAXND_FFTW)
230 throw ParmError("FFTWServer::FFTForward( complex<r_8>, complex<r_8> ) rank > MAXND_FFTW !");
231 int sz[MAXND_FFTW];
232 int k1 = 0;
233 int k2 = 0;
234 for(k1=in.NbDimensions()-1; k1>=0; k1--) {
235 sz[k2] = in.Size(k1); k2++;
236 }
237 if (_pndrf) _pndrf->Recreate(in.NbDimensions(), sz);
238 else _pndrf = new FFTWServerPlan(in.NbDimensions(), sz, FFTW_REAL_TO_COMPLEX, true);
239 rfftwnd_one_real_to_complex(_pndrf->rpnd, (fftw_real *)(in.Data()) ,
240 (fftw_complex *)(out.Data()) );
241 }
[1395]242 if(this->getNormalize()) out=out/complex<r_8>((double)in.Size(),0.);
[1391]243 return;
244
[765]245}
246
247
248
[1391]249void FFTWServer::FFTBackward(TArray< complex<r_8> > const & in, TArray< r_8 > & out)
[765]250{
251
[1395]252 int rank = ckR8.CheckResize(in, out);
253 if (rank == 1) { // One dimensional transform
254 TArray<r_8> intemp(out, false);
255 if (_p1drb) _p1drb->Recreate(out.Size());
256 else _p1drb = new FFTWServerPlan(out.Size(), FFTW_COMPLEX_TO_REAL, true);
[765]257
[1395]258 ReShapetoReal(in, intemp);
259 cerr << " DEBUG-FFTWServer::FFTBackward() in = \n" << in << endl;
260 cerr << " DEBUG-FFTWServer::FFTBackward() intemp = \n" << intemp << endl;
261 rfftw_one(_p1drb->rp, (fftw_real *)(intemp.Data()) , (fftw_real *)(out.Data()));
[765]262
[1395]263 }
264 else { // Multi dimensional
265 if (in.NbDimensions() > MAXND_FFTW)
266 throw ParmError("FFTWServer::FFTForward( complex<r_8>, complex<r_8> ) rank > MAXND_FFTW !");
267 int sz[MAXND_FFTW];
268 int k1 = 0;
269 int k2 = 0;
270 for(k1=in.NbDimensions()-1; k1>=0; k1--) {
271 sz[k2] = in.Size(k1); k2++;
272 }
273 if (_pndrb) _pndrb->Recreate(in.NbDimensions(), sz);
274 else _pndrb = new FFTWServerPlan(in.NbDimensions(), sz, FFTW_COMPLEX_TO_REAL, true);
275
276 rfftwnd_one_complex_to_real(_pndrb->rpnd, (fftw_complex *)(in.Data()) , (fftw_real *)(out.Data()) );
277 }
278 return;
[765]279}
280
[1391]281/*
282void FFTWServer::FFTForward(TArray< complex<r_8> > const & in, TArray< complex<r_8> > & out)
[765]283{
284 out.ReSize(in.NRows(),in.NCols());
285
[1391]286 if (_pndf) _pndf->Recreate( in.NRows(),in.NCols());
287 else _pndf = new FFTWServerPlan( in.NCols(),in.NRows(), FFTW_FORWARD, false);
[765]288
[1391]289 fftwnd_one(_pndf->pnd, (fftw_complex *)(in.Data()) , (fftw_complex *)(out.Data()) );
290 if(this->getNormalize()) out=out/complex<r_8>(pow(in.NRows()*in.NCols(),0.5),0.);
[765]291}
292
[1391]293void FFTWServer::FFTBackward(TArray< complex<r_8> > const & in, TArray< complex<r_8> > & out)
[765]294{
[1391]295 if (_pndb) _pndb->Recreate(in.NCols(), in.NRows());
296 else _pndb = new FFTWServerPlan(in.NCols(), in.NRows(), FFTW_BACKWARD, false);
[765]297 out.ReSize(in.NRows(), in.NCols());
[1391]298 fftwnd_one(_pndb->pnd, (fftw_complex *)(in.Data()) , (fftw_complex *)(out.Data()) );
299 if(this->getNormalize()) out=out/complex<r_8>(pow(in.NRows()*in.NCols(),0.5),0.);
[765]300
301}
302
303
[1391]304void FFTWServer::FFTForward(TArray< r_8 > const & in, TArray< complex<r_8> > & out)
[765]305{
306
[1391]307 TArray< r_8 > inNew(in.NCols(),in.NRows());
[765]308 for(int i=0; i<in.NRows(); i++)
309 for(int j=0;j<in.NCols(); j++)
310 inNew(j,i) = in(i,j);
311
[1391]312 if (_pndrf) _pndrf->Recreate(inNew.NRows(),inNew.NCols());
313 else _pndrf = new FFTWServerPlan(inNew.NRows(), inNew.NCols(),FFTW_REAL_TO_COMPLEX, true);
[834]314 // rfftwnd_plan p;
[1391]315 TArray< complex<r_8> > outTemp;
[765]316 outTemp.ReSize(in.NRows(),in.NCols());
317
[1391]318 rfftwnd_one_real_to_complex(_pndrf->rpnd, (fftw_real *)(in.Data()) , (fftw_complex *)(out.Data()) );
[765]319}
320
[1391]321void FFTWServer::FFTBackward(TArray< complex<r_8> > const & in, TArray< r_8 > & out)
[765]322{
323
[1391]324 TArray< complex<r_8> > inNew(in.NCols(),in.NRows());
[765]325 for(int i=0; i<in.NRows(); i++)
326 for(int j=0;j<in.NCols(); j++)
327 inNew(j,i) = in(i,j);
328
[1391]329 if (_pndrb) _pndrb->Recreate(inNew.NRows(),inNew.NCols());
330 else _pndrb = new FFTWServerPlan(inNew.NRows(), inNew.NCols(),FFTW_COMPLEX_TO_REAL, true);
[834]331 // rfftwnd_plan p;
[765]332 out.ReSize(in.NRows(),in.NCols());
333
[1391]334 rfftwnd_one_complex_to_real(_pndrb->rpnd, (fftw_complex *)(in.Data()) , (fftw_real *)(out.Data()) );
[765]335 cout << " in the function !!!" << endl;
336 if(this->getNormalize())
337 {
[1391]338 r_8 norm = (r_8)(in.NRows()*in.NCols());
[765]339 out=out/norm;
340 }
341}
342
[1391]343*/
[765]344
[1391]345
[765]346/* --Methode-- */
[1395]347void FFTWServer::ReShapetoReal(TArray< complex<r_8> > const & ina, TArray< r_8 > & outa)
[765]348{
[1395]349 TVector< complex<r_8> > in(ina);
350 TVector< r_8> out(outa);
351 int n = in.NElts();
352 r_8 thr = FFTArrayChecker<r_8>::ZeroThreshold();
353 sa_size_t ncs = ( (in(n-1).imag() < -thr) || (in(n-1).imag() > thr) ) ?
354 ncs = 2*n-1 : ncs = 2*n-2;
355
356 if (out.NElts() != ncs) {
357 cerr << " DEBUG-FFTWServer::ReShapetoReal() ncs= " << ncs
358 << " out.NElts()= " << out.NElts() << endl;
359 throw SzMismatchError("FFTWServer::ReShapetoReal() - Wrong output array size !");
[1391]360 }
[1395]361 // if (ncs == 2*n-2) {
362 out(0) = in(0).real();
363 for(int k=1; k<n; k++) {
364 out(k) = in(k).real();
365 out(ncs-k) = in(k).imag();
366 }
367 if (ncs == 2*n-2)
368 out(ncs-1) = in(n-1).real();
[1391]369
[765]370 // for(int k=0; k<out.NElts(); k++) cout << "ReShapetoReal out " << k << " " << out(k) << endl;
371}
372
373
374/* --Methode-- */
[1395]375void FFTWServer::ReShapetoCompl(TArray< r_8 > const & ina, TArray< complex<r_8> > & outa)
[765]376{
[1395]377 TVector< r_8> in(ina);
378 TVector< complex<r_8> > out(outa);
379
380 sa_size_t n = in.NElts();
381 sa_size_t ncs = n/2+1;
382 sa_size_t nc = (n%2 != 0) ? n/2+1 : n/2;
383 if (out.NElts() != ncs)
384 throw SzMismatchError("FFTWServer::ReShapetoCompl() - Wrong output array size !");
385
386 out(0) = complex<r_8> (in(0),0.);
387 for(int k=1; k<ncs; k++)
388 out(k) = complex<r_8>(in(k), in(n-k));
389 if (n%2 == 0) out(ncs-1) = complex<r_8>(in(n/2), 0.);
390
[765]391}
392
Note: See TracBrowser for help on using the repository browser.