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

Last change on this file since 2615 was 2615, checked in by cmv, 21 years ago

using namespace sophya enleve de machdefs.h, nouveau sopnamsp.h cmv 10/09/2004

File size: 7.5 KB
Line 
1#include "sopnamsp.h"
2#include "fftpserver.h"
3#include "fftpackc.h"
4
5#include <iostream>
6
7
8/*!
9 \class SOPHYA::FFTPackServer
10 \ingroup NTools
11 An implementation of FFTServerInterface based on fftpack, for
12 one dimensional arrays.
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.
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
39*/
40
41
42FFTPackServer::FFTPackServer()
43 : FFTServerInterface("FFTPackServer using extended FFTPack (C-version) package")
44 , ckR4("FFTPackServer: ", true, true) , ckR8("FFTPackServer: ", true, true)
45{
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;
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;
61if (ws_dfft) delete[] ws_dfft;
62if (ws_cfft) delete[] ws_cfft;
63if (ws_cdfft) delete[] ws_cdfft;
64}
65
66FFTServerInterface * FFTPackServer::Clone()
67{
68 return (new FFTPackServer);
69}
70
71
72void FFTPackServer::FFTForward(TArray< complex<r_8> > const & in, TArray< complex<r_8> > & out)
73{
74 ckR8.CheckResize(in, out);
75 out = in;
76 fftf(out.Size(), out.Data());
77 if (getNormalize()) out *= (1./(r_8)(in.Size()));
78}
79
80void FFTPackServer::FFTBackward(TArray< complex<r_8> > const & in, TArray< complex<r_8> > & out)
81{
82 ckR8.CheckResize(in, out);
83 out = in;
84 fftb(out.Size(), out.Data());
85}
86
87
88void FFTPackServer::FFTForward(TArray< complex<r_4> > const & in, TArray< complex<r_4> > & out)
89{
90 ckR4.CheckResize(in, out);
91 out = in;
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 ? 2*n-1 : 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.