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

Last change on this file since 2283 was 1652, checked in by cmv, 24 years ago

bug ecrit a=() ? a=blabla: a=blibli; cmv 21/9/01

File size: 7.5 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 fftf(out.Size(), out.Data());
92 if (getNormalize()) out *= (1./(r_4)(in.Size()));
93}
94
95void FFTPackServer::FFTBackward(TArray< complex<r_4> > const & in, TArray< complex<r_4> > & out)
96{
97 ckR4.CheckResize(in, out);
98 out = in;
99 fftb(out.Size(), out.Data());
100}
101
102void FFTPackServer::FFTForward(TArray< r_4 > const & in, TArray< complex<r_4> > & out)
103{
104 ckR4.CheckResize(in, out);
105 TArray< r_4 > inout(in, false);
106 fftf(inout.Size(), inout.Data());
107 ReShapetoCompl(inout, out);
108 if (getNormalize()) out *= complex<r_4>((1./(r_4)(in.Size())), 0.);
109}
110
111void FFTPackServer::FFTBackward(TArray< complex<r_4> > const & in, TArray< r_4 > & out,
112 bool usoutsz)
113{
114 ckR4.CheckResize(in, out, usoutsz);
115 ReShapetoReal(in, out);
116 fftb(out.Size(), out.Data());
117}
118
119
120void FFTPackServer::FFTForward(TArray< r_8 > const & in, TArray< complex<r_8> > & out)
121{
122 ckR8.CheckResize(in, out);
123 TArray< r_8 > inout(in, false);
124 fftf(inout.Size(), inout.Data());
125 ReShapetoCompl(inout, out);
126 if (getNormalize()) out *= complex<r_8>((1./(r_8)(in.Size())), 0.);
127}
128
129void FFTPackServer::FFTBackward(TArray< complex<r_8> > const & in, TArray< r_8 > & out,
130 bool usoutsz)
131{
132 ckR8.CheckResize(in, out, usoutsz);
133 ReShapetoReal(in, out);
134 fftb(out.Size(), out.Data());
135}
136
137
138template <class T>
139void FFTPack_ReShapetoReal(TArray< complex<T> > const & ina, TArray< T > & outa)
140{
141 TVector< complex<T> > in(ina);
142 TVector< T > out(outa);
143 sa_size_t n = in.NElts();
144 T thr = FFTArrayChecker<T>::ZeroThreshold();
145 sa_size_t ncs = ( (in(n-1).imag() < -thr) || (in(n-1).imag() > thr) )
146 ? 2*n-1 : 2*n-2;
147
148 if (out.NElts() != ncs) {
149 cerr << "DEBUG-FFTPack_ReShapetoReal() ncs = " << ncs
150 << " out.NElts()= " << out.NElts() << endl;
151 throw SzMismatchError("FFTPack_ReShapetoReal() - Wrong output array size !");
152 }
153
154 sa_size_t k;
155
156 out(0) = in(0).real();
157 for(k=1;k<n-1;k++) {
158 out(2*k-1) = in(k).real();
159 out(2*k) = in(k).imag();
160 }
161 if (ncs == n*2-2) out(ncs-1) = in(n-1).real();
162 else { out(ncs-2) = in(n-1).real(); out(ncs-1) = in(n-1).imag(); }
163
164 return;
165}
166
167template <class T>
168void FFTPack_ReShapetoCompl(TArray< T > const & ina, TArray< complex<T> > & outa)
169{
170 TVector< T > in(ina);
171 TVector< complex<T> > out(outa);
172 sa_size_t n = in.NElts();
173 sa_size_t ncs = n/2+1;
174 sa_size_t nc = (n%2 != 0) ? n/2+1 : n/2;
175 if (out.NElts() != ncs) {
176 cerr << "DBG-ReShapetoCompl() ncs=" << ncs
177 << " out.NElts()= " << out.NElts() << endl;
178 throw SzMismatchError("FFTPack_ReShapetoCompl() - Wrong output array size !");
179 }
180 out(0) = complex<T> (in(0),0.);
181 for(int k=1;k<nc;k++)
182 out(k) = complex<r_4> (in(2*k-1), in(2*k));
183 if (n%2 == 0) out(ncs-1) = complex<T>(in(n-1), 0.);
184
185 return;
186}
187
188void FFTPackServer::ReShapetoReal(TArray< complex<r_8> > const & in, TArray< r_8 > & out)
189{
190 FFTPack_ReShapetoReal<r_8>(in, out);
191}
192
193void FFTPackServer::ReShapetoCompl(TArray< r_8 > const & in, TArray< complex<r_8> > & out)
194{
195 FFTPack_ReShapetoCompl<r_8>(in, out);
196}
197
198void FFTPackServer::ReShapetoReal(TArray< complex<r_4> > const & in, TArray< r_4 > & out)
199{
200 FFTPack_ReShapetoReal<r_4>(in, out);
201}
202
203void FFTPackServer::ReShapetoCompl(TArray< r_4 > const & in, TArray< complex<r_4> > & out)
204{
205 FFTPack_ReShapetoCompl<r_4>(in, out);
206}
207
208void FFTPackServer::checkint_rfft(int_4 l)
209{
210 if (sz_rfft == l) return; //checkint functions check and reallocate
211 //memory for the work arrays when performing
212 if (ws_rfft) delete[] ws_rfft; //a transform
213 sz_rfft = l;
214 ws_rfft = new r_4[2*l+15];
215 rffti_(&l, ws_rfft);
216}
217
218void FFTPackServer::checkint_cfft(int_4 l)
219{
220 if (sz_cfft == l) return;
221
222 if (ws_cfft) delete[] ws_cfft;
223 sz_cfft = l;
224 ws_cfft = new r_4[4*l+15];
225 cffti_(&l, ws_cfft);
226}
227
228void FFTPackServer::checkint_dfft(int_4 l)
229{
230 if (sz_dfft == l) return;
231
232 if (ws_dfft) delete[] ws_dfft;
233 sz_dfft = l;
234 ws_dfft = new r_8[2*l+15];
235 dffti_(&l, ws_dfft);
236}
237
238void FFTPackServer::checkint_cdfft(int_4 l)
239{
240 if (sz_cdfft == l) return;
241
242 if (ws_cdfft) delete[] ws_cdfft;
243 sz_cdfft = l;
244 ws_cdfft = new r_8[4*l+15];
245 cdffti_(&l, ws_cdfft);
246}
247
248/* In general forward transformations are resorted since fftpack functions
249 return inverse transformations */
250
251void FFTPackServer::fftf(int_4 l, r_4* inout)
252{
253 checkint_rfft(l);
254 rfftf_(&l, inout, ws_rfft);
255 // for (int k= 2;k<=(l+1)/2;k++) inout[2*k-2]=-inout[2*k-2];
256}
257
258void FFTPackServer::fftf(int_4 l, r_8* inout)
259{
260 checkint_dfft(l);
261 dfftf_(&l, inout, ws_dfft);
262 // for (int k= 2;k<=(l+1)/2;k++) inout[2*k-2]=-inout[2*k-2];
263}
264
265void FFTPackServer::fftf(int_4 l, complex<r_4>* inout)
266{
267 checkint_cfft(l);
268 cfftf_(&l, (r_4 *)(inout), ws_cfft);
269}
270
271void FFTPackServer::fftf(int_4 l, complex<r_8>* inout)
272{
273 checkint_cdfft(l);
274 cdfftf_(&l, (r_8*)(inout), ws_cdfft);
275}
276
277void FFTPackServer::fftb(int_4 l, r_4* inout)
278{
279 checkint_rfft(l);
280 rfftb_(&l, inout, ws_rfft);
281}
282
283void FFTPackServer::fftb(int_4 l, r_8* inout)
284{
285 checkint_dfft(l);
286 dfftb_(&l, inout, ws_dfft);
287}
288
289void FFTPackServer::fftb(int_4 l, complex<r_4>* inout)
290{
291 checkint_cfft(l);
292 cfftb_(&l, (r_4 *)(inout), ws_cfft);
293}
294
295void FFTPackServer::fftb(int_4 l, complex<r_8>* inout)
296{
297 checkint_cdfft(l);
298 cdfftb_(&l, (r_8 *)(inout), ws_cdfft);
299}
300
301
Note: See TracBrowser for help on using the repository browser.