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

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

Modifs FFTServerInterface + FFTPackServer (Suite - Fin ?) - Reza 13/2/2001

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