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

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

Adaptation aux modifications de TArray<T>/TVector<T> - linfit.cc integre
a TArray/sopemtx.cc - Reza 03/04/2000

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