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

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

Ajout documentation - Reza 15/2/2001

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