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

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

Suppression const des arguments FFTForward/Backward + adaptation de Toeplitz, cmv+Reza 03/07/2006

File size: 8.0 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
42//! Constructor - If preserve_input==true, input arrays will not be overwritten.
43FFTPackServer::FFTPackServer(bool preserve_input)
44 : FFTServerInterface("FFTPackServer using extended FFTPack (C-version) package")
45 , ckR4("FFTPackServer: ", true, true) , ckR8("FFTPackServer: ", true, true),
46 _preserve_input(preserve_input)
47{
48//the working array and its size for the different
49//possible numerical types
50 sz_rfft = 0;
51 ws_rfft = NULL;
52 sz_dfft = 0;
53 ws_dfft = NULL;
54 sz_cfft = 0;
55 ws_cfft = NULL;
56 sz_cdfft = 0;
57 ws_cdfft = NULL;
58}
59
60FFTPackServer::~FFTPackServer()
61{
62if (ws_rfft) delete[] ws_rfft;
63if (ws_dfft) delete[] ws_dfft;
64if (ws_cfft) delete[] ws_cfft;
65if (ws_cdfft) delete[] ws_cdfft;
66}
67
68FFTServerInterface * FFTPackServer::Clone()
69{
70 return (new FFTPackServer(_preserve_input) );
71}
72
73
74void FFTPackServer::FFTForward(TArray< complex<r_8> > & in, TArray< complex<r_8> > & out)
75{
76 ckR8.CheckResize(in, out);
77 out = in;
78 fftf(out.Size(), out.Data());
79 if (getNormalize()) out *= (1./(r_8)(in.Size()));
80}
81
82void FFTPackServer::FFTBackward(TArray< complex<r_8> > & in, TArray< complex<r_8> > & out)
83{
84 ckR8.CheckResize(in, out);
85 out = in;
86 fftb(out.Size(), out.Data());
87}
88
89
90void FFTPackServer::FFTForward(TArray< complex<r_4> > & in, TArray< complex<r_4> > & out)
91{
92 ckR4.CheckResize(in, out);
93 out = in;
94 fftf(out.Size(), out.Data());
95 if (getNormalize()) out *= (1./(r_4)(in.Size()));
96}
97
98void FFTPackServer::FFTBackward(TArray< complex<r_4> > & in, TArray< complex<r_4> > & out)
99{
100 ckR4.CheckResize(in, out);
101 out = in;
102 fftb(out.Size(), out.Data());
103}
104
105void FFTPackServer::FFTForward(TArray< r_4 > & in, TArray< complex<r_4> > & out)
106{
107 ckR4.CheckResize(in, out);
108 bool share = (_preserve_input) ? false : true;
109 TArray< r_4 > inout(in, share);
110 fftf(inout.Size(), inout.Data());
111 ReShapetoCompl(inout, out);
112 if (getNormalize()) out *= complex<r_4>((1./(r_4)(in.Size())), 0.);
113}
114
115void FFTPackServer::FFTBackward(TArray< complex<r_4> > & in, TArray< r_4 > & out,
116 bool usoutsz)
117{
118 ckR4.CheckResize(in, out, usoutsz);
119 ReShapetoReal(in, out, usoutsz);
120 fftb(out.Size(), out.Data());
121}
122
123
124void FFTPackServer::FFTForward(TArray< r_8 > & in, TArray< complex<r_8> > & out)
125{
126 ckR8.CheckResize(in, out);
127 bool share = (_preserve_input) ? false : true;
128 TArray< r_8 > inout(in, share);
129 fftf(inout.Size(), inout.Data());
130 ReShapetoCompl(inout, out);
131 if (getNormalize()) out *= complex<r_8>((1./(r_8)(in.Size())), 0.);
132}
133
134void FFTPackServer::FFTBackward(TArray< complex<r_8> > & in, TArray< r_8 > & out,
135 bool usoutsz)
136{
137 ckR8.CheckResize(in, out, usoutsz);
138 ReShapetoReal(in, out, usoutsz);
139 fftb(out.Size(), out.Data());
140}
141
142
143template <class T>
144void FFTPack_ReShapetoReal(TArray< complex<T> > const & ina, TArray< T > & outa, bool usz)
145{
146 TVector< complex<T> > in(ina);
147 TVector< T > out(outa);
148 sa_size_t n = in.NElts();
149 sa_size_t ncs;
150 if (usz) {
151 if ( (out.NElts() != 2*n-1) && (out.NElts() != 2*n-2) )
152 throw SzMismatchError("FFTPack_ReShapetoReal(..., true) - Wrong output array size ");
153 ncs = out.NElts();
154 }
155 else {
156 T thr = FFTArrayChecker<T>::ZeroThreshold();
157 ncs = ( (in(n-1).imag() < -thr) || (in(n-1).imag() > thr) ) ? 2*n-1 : 2*n-2;
158
159 if (out.NElts() != ncs) {
160 cerr << "DEBUG-FFTPack_ReShapetoReal() ncs = " << ncs
161 << " out.NElts()= " << out.NElts() << endl;
162 throw SzMismatchError("FFTPack_ReShapetoReal() - Wrong output array size !");
163 }
164 }
165
166 sa_size_t k;
167
168 out(0) = in(0).real();
169 for(k=1;k<n-1;k++) {
170 out(2*k-1) = in(k).real();
171 out(2*k) = in(k).imag();
172 }
173 if (ncs == n*2-2) out(ncs-1) = in(n-1).real();
174 else { out(ncs-2) = in(n-1).real(); out(ncs-1) = in(n-1).imag(); }
175
176 return;
177}
178
179template <class T>
180void FFTPack_ReShapetoCompl(TArray< T > const & ina, TArray< complex<T> > & outa)
181{
182 TVector< T > in(ina);
183 TVector< complex<T> > out(outa);
184 sa_size_t n = in.NElts();
185 sa_size_t ncs = n/2+1;
186 sa_size_t nc = (n%2 != 0) ? n/2+1 : n/2;
187 if (out.NElts() != ncs) {
188 cerr << "DBG-ReShapetoCompl() ncs=" << ncs
189 << " out.NElts()= " << out.NElts() << endl;
190 throw SzMismatchError("FFTPack_ReShapetoCompl() - Wrong output array size !");
191 }
192 out(0) = complex<T> (in(0),0.);
193 for(int k=1;k<nc;k++)
194 out(k) = complex<r_4> (in(2*k-1), in(2*k));
195 if (n%2 == 0) out(ncs-1) = complex<T>(in(n-1), 0.);
196
197 return;
198}
199
200void FFTPackServer::ReShapetoReal(TArray< complex<r_8> > const & in, TArray< r_8 > & out,
201 bool usz)
202{
203 FFTPack_ReShapetoReal<r_8>(in, out, usz);
204}
205
206void FFTPackServer::ReShapetoCompl(TArray< r_8 > const & in, TArray< complex<r_8> > & out)
207{
208 FFTPack_ReShapetoCompl<r_8>(in, out);
209}
210
211void FFTPackServer::ReShapetoReal(TArray< complex<r_4> > const & in, TArray< r_4 > & out,
212 bool usz)
213{
214 FFTPack_ReShapetoReal<r_4>(in, out, usz);
215}
216
217void FFTPackServer::ReShapetoCompl(TArray< r_4 > const & in, TArray< complex<r_4> > & out)
218{
219 FFTPack_ReShapetoCompl<r_4>(in, out);
220}
221
222void FFTPackServer::checkint_rfft(int_4 l)
223{
224 if (sz_rfft == l) return; //checkint functions check and reallocate
225 //memory for the work arrays when performing
226 if (ws_rfft) delete[] ws_rfft; //a transform
227 sz_rfft = l;
228 ws_rfft = new r_4[2*l+15];
229 rffti_(&l, ws_rfft);
230}
231
232void FFTPackServer::checkint_cfft(int_4 l)
233{
234 if (sz_cfft == l) return;
235
236 if (ws_cfft) delete[] ws_cfft;
237 sz_cfft = l;
238 ws_cfft = new r_4[4*l+15];
239 cffti_(&l, ws_cfft);
240}
241
242void FFTPackServer::checkint_dfft(int_4 l)
243{
244 if (sz_dfft == l) return;
245
246 if (ws_dfft) delete[] ws_dfft;
247 sz_dfft = l;
248 ws_dfft = new r_8[2*l+15];
249 dffti_(&l, ws_dfft);
250}
251
252void FFTPackServer::checkint_cdfft(int_4 l)
253{
254 if (sz_cdfft == l) return;
255
256 if (ws_cdfft) delete[] ws_cdfft;
257 sz_cdfft = l;
258 ws_cdfft = new r_8[4*l+15];
259 cdffti_(&l, ws_cdfft);
260}
261
262/* In general forward transformations are resorted since fftpack functions
263 return inverse transformations */
264
265void FFTPackServer::fftf(int_4 l, r_4* inout)
266{
267 checkint_rfft(l);
268 rfftf_(&l, inout, ws_rfft);
269 // for (int k= 2;k<=(l+1)/2;k++) inout[2*k-2]=-inout[2*k-2];
270}
271
272void FFTPackServer::fftf(int_4 l, r_8* inout)
273{
274 checkint_dfft(l);
275 dfftf_(&l, inout, ws_dfft);
276 // for (int k= 2;k<=(l+1)/2;k++) inout[2*k-2]=-inout[2*k-2];
277}
278
279void FFTPackServer::fftf(int_4 l, complex<r_4>* inout)
280{
281 checkint_cfft(l);
282 cfftf_(&l, (r_4 *)(inout), ws_cfft);
283}
284
285void FFTPackServer::fftf(int_4 l, complex<r_8>* inout)
286{
287 checkint_cdfft(l);
288 cdfftf_(&l, (r_8*)(inout), ws_cdfft);
289}
290
291void FFTPackServer::fftb(int_4 l, r_4* inout)
292{
293 checkint_rfft(l);
294 rfftb_(&l, inout, ws_rfft);
295}
296
297void FFTPackServer::fftb(int_4 l, r_8* inout)
298{
299 checkint_dfft(l);
300 dfftb_(&l, inout, ws_dfft);
301}
302
303void FFTPackServer::fftb(int_4 l, complex<r_4>* inout)
304{
305 checkint_cfft(l);
306 cfftb_(&l, (r_4 *)(inout), ws_cfft);
307}
308
309void FFTPackServer::fftb(int_4 l, complex<r_8>* inout)
310{
311 checkint_cdfft(l);
312 cdfftb_(&l, (r_8 *)(inout), ws_cdfft);
313}
314
315
Note: See TracBrowser for help on using the repository browser.