source: Sophya/trunk/SophyaLib/NTools/fftpserver.cc@ 2988

Last change on this file since 2988 was 2988, checked in by ansari, 19 years ago

1/ MAJ documentation/commentaire dans FFTServerInterface (fftservintf.cc)
2/ Ajout flag use_out_size d'utilisation de la taille du tableau reel de
sortie pour FFTBack(complex->real) dans ReShapetoReal() pour FFTPackServer
(fichiers fftpserver.h .cc)

Reza 23 Juin 2006

File size: 7.8 KB
RevLine 
[2615]1#include "sopnamsp.h"
[710]2#include "fftpserver.h"
3#include "fftpackc.h"
4
[2322]5#include <iostream>
[710]6
7
[896]8/*!
[1371]9 \class SOPHYA::FFTPackServer
10 \ingroup NTools
11 An implementation of FFTServerInterface based on fftpack, for
12 one dimensional arrays.
[710]13
14The class calls the c library ``fftpack'', which is accessible and documented
15at http://www.netlib.org/fftpack/. However, the class functions do not
16necessarily correspond with the equivalent fftpack function. For example,
17fftpack "forward" transformations are in fact inverse fourier transformations.
18
19Due to the way that fftpack manages
20its work arrays, an object can run faster if the length of the input arrays
21does not change. For example, if you need to do a series of FFT's
22of differing length, it may be more efficient to create an fftserver object
23for each length.
[1405]24
25 \code
26 #include "fftpserver.h"
27 // ...
28 TVector<r_8> in(32);
29 TVector< complex<r_8> > out;
30 in = RandomSequence();
31 FFTPackServer ffts;
32 ffts.setNormalize(true); // To have normalized transforms
33 cout << " FFTServer info string= " << ffts.getInfo() << endl;
34 cout << "in= " << in << endl;
35 cout << " Calling ffts.FFTForward(in, out) : " << endl;
36 ffts.FFTForward(in, out);
37 cout << "out= " << out << endl;
38 \endcode
[710]39*/
40
41
42FFTPackServer::FFTPackServer()
[717]43 : FFTServerInterface("FFTPackServer using extended FFTPack (C-version) package")
[1394]44 , ckR4("FFTPackServer: ", true, true) , ckR8("FFTPackServer: ", true, true)
[710]45{
[1313]46//the working array and its size for the different
47//possible numerical types
48 sz_rfft = 0;
49 ws_rfft = NULL;
50 sz_dfft = 0;
51 ws_dfft = NULL;
[710]52 sz_cfft = 0;
53 ws_cfft = NULL;
54 sz_cdfft = 0;
55 ws_cdfft = NULL;
56}
57
58FFTPackServer::~FFTPackServer()
59{
60if (ws_rfft) delete[] ws_rfft;
[1313]61if (ws_dfft) delete[] ws_dfft;
[710]62if (ws_cfft) delete[] ws_cfft;
63if (ws_cdfft) delete[] ws_cdfft;
64}
65
66FFTServerInterface * FFTPackServer::Clone()
67{
68 return (new FFTPackServer);
69}
70
[717]71
[1390]72void FFTPackServer::FFTForward(TArray< complex<r_8> > const & in, TArray< complex<r_8> > & out)
[710]73{
[1390]74 ckR8.CheckResize(in, out);
[710]75 out = in;
[1390]76 fftf(out.Size(), out.Data());
77 if (getNormalize()) out *= (1./(r_8)(in.Size()));
[710]78}
79
[1390]80void FFTPackServer::FFTBackward(TArray< complex<r_8> > const & in, TArray< complex<r_8> > & out)
[710]81{
[1390]82 ckR8.CheckResize(in, out);
[710]83 out = in;
[1390]84 fftb(out.Size(), out.Data());
[710]85}
86
[717]87
[1390]88void FFTPackServer::FFTForward(TArray< complex<r_4> > const & in, TArray< complex<r_4> > & out)
[710]89{
[1390]90 ckR4.CheckResize(in, out);
[710]91 out = in;
[1390]92 fftf(out.Size(), out.Data());
93 if (getNormalize()) out *= (1./(r_4)(in.Size()));
[710]94}
95
[1390]96void FFTPackServer::FFTBackward(TArray< complex<r_4> > const & in, TArray< complex<r_4> > & out)
[710]97{
[1390]98 ckR4.CheckResize(in, out);
[710]99 out = in;
[1390]100 fftb(out.Size(), out.Data());
[710]101}
102
[1390]103void FFTPackServer::FFTForward(TArray< r_4 > const & in, TArray< complex<r_4> > & out)
[710]104{
[1390]105 ckR4.CheckResize(in, out);
106 TArray< r_4 > inout(in, false);
107 fftf(inout.Size(), inout.Data());
[1394]108 ReShapetoCompl(inout, out);
[1390]109 if (getNormalize()) out *= complex<r_4>((1./(r_4)(in.Size())), 0.);
[710]110}
111
[1402]112void FFTPackServer::FFTBackward(TArray< complex<r_4> > const & in, TArray< r_4 > & out,
113 bool usoutsz)
[710]114{
[1402]115 ckR4.CheckResize(in, out, usoutsz);
[2988]116 ReShapetoReal(in, out, usoutsz);
[1390]117 fftb(out.Size(), out.Data());
[710]118}
119
[717]120
[1390]121void FFTPackServer::FFTForward(TArray< r_8 > const & in, TArray< complex<r_8> > & out)
[710]122{
[1390]123 ckR8.CheckResize(in, out);
124 TArray< r_8 > inout(in, false);
125 fftf(inout.Size(), inout.Data());
[1394]126 ReShapetoCompl(inout, out);
[1390]127 if (getNormalize()) out *= complex<r_8>((1./(r_8)(in.Size())), 0.);
[710]128}
129
[1402]130void FFTPackServer::FFTBackward(TArray< complex<r_8> > const & in, TArray< r_8 > & out,
131 bool usoutsz)
[710]132{
[1402]133 ckR8.CheckResize(in, out, usoutsz);
[2988]134 ReShapetoReal(in, out, usoutsz);
[1390]135 fftb(out.Size(), out.Data());
[710]136}
137
138
[1394]139template <class T>
[2988]140void FFTPack_ReShapetoReal(TArray< complex<T> > const & ina, TArray< T > & outa, bool usz)
[1394]141{
142 TVector< complex<T> > in(ina);
143 TVector< T > out(outa);
144 sa_size_t n = in.NElts();
[2988]145 sa_size_t ncs;
146 if (usz) {
147 if ( (out.NElts() != 2*n-1) && (out.NElts() != 2*n-2) )
148 throw SzMismatchError("FFTPack_ReShapetoReal(..., true) - Wrong output array size ");
149 ncs = out.NElts();
[1400]150 }
[2988]151 else {
152 T thr = FFTArrayChecker<T>::ZeroThreshold();
153 ncs = ( (in(n-1).imag() < -thr) || (in(n-1).imag() > thr) ) ? 2*n-1 : 2*n-2;
154
155 if (out.NElts() != ncs) {
156 cerr << "DEBUG-FFTPack_ReShapetoReal() ncs = " << ncs
157 << " out.NElts()= " << out.NElts() << endl;
158 throw SzMismatchError("FFTPack_ReShapetoReal() - Wrong output array size !");
159 }
160 }
[1394]161
162 sa_size_t k;
163
164 out(0) = in(0).real();
165 for(k=1;k<n-1;k++) {
166 out(2*k-1) = in(k).real();
167 out(2*k) = in(k).imag();
168 }
169 if (ncs == n*2-2) out(ncs-1) = in(n-1).real();
170 else { out(ncs-2) = in(n-1).real(); out(ncs-1) = in(n-1).imag(); }
171
172 return;
173}
174
175template <class T>
176void FFTPack_ReShapetoCompl(TArray< T > const & ina, TArray< complex<T> > & outa)
177{
178 TVector< T > in(ina);
179 TVector< complex<T> > out(outa);
180 sa_size_t n = in.NElts();
181 sa_size_t ncs = n/2+1;
182 sa_size_t nc = (n%2 != 0) ? n/2+1 : n/2;
[1400]183 if (out.NElts() != ncs) {
184 cerr << "DBG-ReShapetoCompl() ncs=" << ncs
185 << " out.NElts()= " << out.NElts() << endl;
[1394]186 throw SzMismatchError("FFTPack_ReShapetoCompl() - Wrong output array size !");
[1400]187 }
[1394]188 out(0) = complex<T> (in(0),0.);
189 for(int k=1;k<nc;k++)
190 out(k) = complex<r_4> (in(2*k-1), in(2*k));
191 if (n%2 == 0) out(ncs-1) = complex<T>(in(n-1), 0.);
192
193 return;
194}
195
[2988]196void FFTPackServer::ReShapetoReal(TArray< complex<r_8> > const & in, TArray< r_8 > & out,
197 bool usz)
[1394]198{
[2988]199 FFTPack_ReShapetoReal<r_8>(in, out, usz);
[1394]200}
201
202void FFTPackServer::ReShapetoCompl(TArray< r_8 > const & in, TArray< complex<r_8> > & out)
203{
204 FFTPack_ReShapetoCompl<r_8>(in, out);
205}
206
[2988]207void FFTPackServer::ReShapetoReal(TArray< complex<r_4> > const & in, TArray< r_4 > & out,
208 bool usz)
[1394]209{
[2988]210 FFTPack_ReShapetoReal<r_4>(in, out, usz);
[1394]211}
212
213void FFTPackServer::ReShapetoCompl(TArray< r_4 > const & in, TArray< complex<r_4> > & out)
214{
215 FFTPack_ReShapetoCompl<r_4>(in, out);
216}
217
[791]218void FFTPackServer::checkint_rfft(int_4 l)
[710]219{
220 if (sz_rfft == l) return; //checkint functions check and reallocate
221 //memory for the work arrays when performing
222 if (ws_rfft) delete[] ws_rfft; //a transform
223 sz_rfft = l;
[717]224 ws_rfft = new r_4[2*l+15];
[710]225 rffti_(&l, ws_rfft);
226}
227
[791]228void FFTPackServer::checkint_cfft(int_4 l)
[710]229{
230 if (sz_cfft == l) return;
231
232 if (ws_cfft) delete[] ws_cfft;
233 sz_cfft = l;
[717]234 ws_cfft = new r_4[4*l+15];
[710]235 cffti_(&l, ws_cfft);
236}
237
[791]238void FFTPackServer::checkint_dfft(int_4 l)
[710]239{
240 if (sz_dfft == l) return;
241
242 if (ws_dfft) delete[] ws_dfft;
243 sz_dfft = l;
[717]244 ws_dfft = new r_8[2*l+15];
[710]245 dffti_(&l, ws_dfft);
246}
247
[791]248void FFTPackServer::checkint_cdfft(int_4 l)
[710]249{
250 if (sz_cdfft == l) return;
251
252 if (ws_cdfft) delete[] ws_cdfft;
253 sz_cdfft = l;
[717]254 ws_cdfft = new r_8[4*l+15];
[710]255 cdffti_(&l, ws_cdfft);
256}
257
258/* In general forward transformations are resorted since fftpack functions
259 return inverse transformations */
260
[791]261void FFTPackServer::fftf(int_4 l, r_4* inout)
[710]262{
263 checkint_rfft(l);
264 rfftf_(&l, inout, ws_rfft);
[717]265 // for (int k= 2;k<=(l+1)/2;k++) inout[2*k-2]=-inout[2*k-2];
[710]266}
267
[791]268void FFTPackServer::fftf(int_4 l, r_8* inout)
[710]269{
270 checkint_dfft(l);
271 dfftf_(&l, inout, ws_dfft);
[717]272 // for (int k= 2;k<=(l+1)/2;k++) inout[2*k-2]=-inout[2*k-2];
[710]273}
274
[791]275void FFTPackServer::fftf(int_4 l, complex<r_4>* inout)
[710]276{
277 checkint_cfft(l);
[717]278 cfftf_(&l, (r_4 *)(inout), ws_cfft);
[710]279}
280
[791]281void FFTPackServer::fftf(int_4 l, complex<r_8>* inout)
[710]282{
283 checkint_cdfft(l);
[717]284 cdfftf_(&l, (r_8*)(inout), ws_cdfft);
[710]285}
286
[791]287void FFTPackServer::fftb(int_4 l, r_4* inout)
[710]288{
289 checkint_rfft(l);
[717]290 rfftb_(&l, inout, ws_rfft);
[710]291}
292
[791]293void FFTPackServer::fftb(int_4 l, r_8* inout)
[710]294{
295 checkint_dfft(l);
[717]296 dfftb_(&l, inout, ws_dfft);
[710]297}
298
[791]299void FFTPackServer::fftb(int_4 l, complex<r_4>* inout)
[710]300{
301 checkint_cfft(l);
[717]302 cfftb_(&l, (r_4 *)(inout), ws_cfft);
[710]303}
304
[791]305void FFTPackServer::fftb(int_4 l, complex<r_8>* inout)
[710]306{
307 checkint_cdfft(l);
[717]308 cdfftb_(&l, (r_8 *)(inout), ws_cdfft);
309}
310
311
Note: See TracBrowser for help on using the repository browser.