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

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

Modifs-debug FFTServerInterface FFTPackServer - Reza 13/2/2001

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