source: Sophya/trunk/SophyaLib/NTools/fftservintf.cc@ 1405

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

Ajout documentation - Reza 15/2/2001

File size: 9.4 KB
RevLine 
[710]1#include "fftservintf.h"
2
3
[1371]4/*!
5 \class SOPHYA::FFTServerInterface
6 \ingroup NTools
7 Defines the interface for FFT (Fast Fourier Transform) operations.
[1405]8 Definitions :
9 - Sampling period \b T
10 - Sampling frequency \b fs=1/T
11 - Total number of samples \b N
12 - Frequency step in Fourier space \b =fs/N=1/(N*T)
13 - Component frequencies
14 - k=0 -> 0
15 - k=1 -> 1/(N*T)
16 - k -> k/(N*T)
17 - k=N/2 -> 1/(2*T) (Nyquist frequency)
18 - k>N/2 -> k/(N*T) (or negative frequency -(N-k)/(N*T))
19
20 For a sampling period T=1, the computed Fourier components correspond to :
21 \verbatim
22 0 1/N 2/N ... 1/2 1/2+1/N 1/2+2/N ... 1-2/N 1-1/N
23 0 1/N 2/N ... 1/2 ... -2/N -1/N
24 \endverbatim
25
26 For complex one-dimensional transforms:
27 \f[
28 out(i) = F_{norm} \Sigma_{j} \ e^{-2 \pi \sqrt{-1} \ i \ j} \ {\rm (forward)}
29 \f]
30 \f[
31 out(i) = F_{norm} \Sigma_{j} \ e^{2 \pi \sqrt{-1} \ i \ j} \ {\rm (backward)}
32 \f]
33 i,j= 0..N-1 , where N is the input or the output array size.
34
35 For complex multi-dimensional transforms:
36 \f[
37 out(i1,i2,...,id) = F_{norm} \Sigma_{j1} \Sigma_{j2} ... \Sigma_{jd} \
38 e^{-2 \pi \sqrt{-1} \ i1 \ j1} ... e^{-2 \pi \sqrt{-1} \ id \ jd} \ {\rm (forward)}
39 \f]
40 \f[
41 out(i1,i2,...,id) = F_{norm} \Sigma_{j1} \Sigma_{j2} ... \Sigma_{jd} \
42 e^{2 \pi \sqrt{-1} \ i1 \ j1} ... e^{2 \pi \sqrt{-1} \ id \ jd} \ {\rm (backward)}
43 \f]
44
45 For real forward transforms, the input array is real, and
46 the output array complex, with Fourier components up to k=N/2.
47 For real backward transforms, the input array is complex and
48 the output array is real.
[1371]49*/
[710]50
51/* --Methode-- */
52FFTServerInterface::FFTServerInterface(string info)
53{
54 _info = info;
[717]55 _fgnorm = true;
[710]56}
57
58/* --Methode-- */
59FFTServerInterface::~FFTServerInterface()
60{
61}
62
[1390]63// ----------------- Transforme pour les double -------------------
64
[710]65/* --Methode-- */
[1405]66//! Forward Fourier transform for double precision complex data
67/*!
68 \param in : Input complex array
69 \param out : Output complex array
70 */
[1390]71void FFTServerInterface::FFTForward(TArray< complex<r_8> > const &, TArray< complex<r_8> > &)
[710]72{
[1390]73 throw NotAvailableOperation("FFTServer::FFTForward(TArray...) Unsupported operation !");
[710]74}
75
76/* --Methode-- */
[1405]77//! Backward (inverse) Fourier transform for double precision complex data
78/*!
79 \param in : Input complex array
80 \param out : Output complex array
81 */
[1390]82void FFTServerInterface::FFTBackward(TArray< complex<r_8> > const &, TArray< complex<r_8> > &)
[710]83{
[1390]84 throw NotAvailableOperation("FFTServer::FFTBackward(TArray...) Unsupported operation !");
[710]85}
86
87/* --Methode-- */
[1405]88//! Forward Fourier transform for double precision real input data
89/*!
90 \param in : Input real array
91 \param out : Output complex array
92 */
[1390]93void FFTServerInterface::FFTForward(TArray< r_8 > const &, TArray< complex<r_8> > &)
[710]94{
[1390]95 throw NotAvailableOperation("FFTServer::FFTForward(TArray...) Unsupported operation !");
[710]96}
97
98/* --Methode-- */
[1405]99//! Backward (inverse) Fourier transform for double precision real output data
100/*!
101 \param in : Input complex array
102 \param out : Output real array
103 \param usoutsz : if true, use the output array size for computing the inverse FFT.
104 */
[1402]105void FFTServerInterface::FFTBackward(TArray< complex<r_8> > const &, TArray< r_8 > &, bool)
[710]106{
[1390]107 throw NotAvailableOperation("FFTServer::FFTBackward(TArray...) Unsupported operation !");
[710]108}
109
[1390]110
111// ----------------- Transforme pour les float -------------------
112
[710]113/* --Methode-- */
[1405]114//! Forward Fourier transform for complex data
115/*!
116 \param in : Input complex array
117 \param out : Output complex array
118 */
[1390]119void FFTServerInterface::FFTForward(TArray< complex<r_4> > const &, TArray< complex<r_4> > &)
[710]120{
[1390]121 throw NotAvailableOperation("FFTServer::FFTForward(TArray r_4 ... ) Unsupported operation !");
[710]122}
123
124/* --Methode-- */
[1405]125//! Backward (inverse) Fourier transform for complex data
126/*!
127 \param in : Input complex array
128 \param out : Output complex array
129 */
[1390]130void FFTServerInterface::FFTBackward(TArray< complex<r_4> > const &, TArray< complex<r_4> > &)
[710]131{
[1390]132 throw NotAvailableOperation("FFTServer::FFTBackward(TArray r_4 ... ) Unsupported operation !");
[710]133}
134
135/* --Methode-- */
[1405]136//! Forward Fourier transform for real input data
137/*!
138 \param in : Input real array
139 \param out : Output complex array
140 */
[1390]141void FFTServerInterface::FFTForward(TArray< r_4 > const &, TArray< complex<r_4> > &)
[710]142{
[1390]143 throw NotAvailableOperation("FFTServer::FFTForward(TArray r_4 ... ) Unsupported operation !");
[710]144}
145
146/* --Methode-- */
[1405]147//! Backward (inverse) Fourier transform for real output data
148/*!
149 \param in : Input complex array
150 \param out : Output real array
151 \param usoutsz : if true, use the output array size for computing the inverse FFT.
152 */
[1402]153void FFTServerInterface::FFTBackward(TArray< complex<r_4> > const &, TArray< r_4 > &, bool)
[710]154{
[1390]155 throw NotAvailableOperation("FFTServer::FFTBackward(TArray r_4 ... ) Unsupported operation !");
[710]156}
157
158
159
160/* --Methode-- */
[1405]161/*!
162 \class SOPHYA::FFTArrayChecker
163 \ingroup NTools
164 Service class for checking array size and resizing output arrays,
165 to be used by FFTServer classes
166*/
167
[1390]168template <class T>
[1394]169FFTArrayChecker<T>::FFTArrayChecker(string msg, bool checkpack, bool onedonly)
[710]170{
[1394]171 _msg = msg + " FFTArrayChecker::";
[1390]172 _checkpack = checkpack;
173 _onedonly = onedonly;
[710]174}
175
176/* --Methode-- */
[1390]177template <class T>
178FFTArrayChecker<T>::~FFTArrayChecker()
[710]179{
180}
181
[1394]182template <class T>
183T FFTArrayChecker<T>::ZeroThreshold()
184{
185 return(0);
186}
187
188r_8 FFTArrayChecker< r_8 >::ZeroThreshold()
189{
190 return(1.e-18);
191}
192
193r_4 FFTArrayChecker< r_4 >::ZeroThreshold()
194{
195 return(1.e-9);
196}
197
198
199
[710]200/* --Methode-- */
[1390]201template <class T>
202int FFTArrayChecker<T>::CheckResize(TArray< complex<T> > const & in, TArray< complex<T> > & out)
[710]203{
[1390]204 int k;
[1394]205 string msg;
206 if (in.Size() < 1) {
207 msg = _msg + "CheckResize(complex in, complex out) - Unallocated input array !";
208 throw(SzMismatchError(msg));
209 }
[1390]210 if (_checkpack)
[1394]211 if ( !in.IsPacked() ) {
212 msg = _msg + "CheckResize(complex in, complex out) - Not packed input array !";
213 throw(SzMismatchError(msg));
214 }
[1390]215 int ndg1 = 0;
216 for(k=0; k<in.NbDimensions(); k++)
217 if (in.Size(k) > 1) ndg1++;
218 if (_onedonly)
[1394]219 if (ndg1 > 1) {
220 msg = _msg + "CheckResize(complex in, complex out) - Only 1-D array accepted !";
221 throw(SzMismatchError(msg));
222 }
223 out.ReSize(in);
224 // sa_size_t sz[BASEARRAY_MAXNDIMS];
225 // for(k=0; k<in.NbDimensions(); k++)
226 // sz[k] = in.Size(k);
227 // out.ReSize(in.NbDimensions(), sz);
[1390]228
229 return(ndg1);
[710]230}
231
232/* --Methode-- */
[1390]233template <class T>
234int FFTArrayChecker<T>::CheckResize(TArray< T > const & in, TArray< complex<T> > & out)
[710]235{
[1390]236 int k;
[1394]237 string msg;
238 if (in.Size() < 1) {
239 msg = _msg + "CheckResize(real in, complex out) - Unallocated input array !";
240 throw(SzMismatchError(msg));
241 }
[1390]242 if (_checkpack)
[1394]243 if ( !in.IsPacked() ) {
244 msg = _msg + "CheckResize(real in, complex out) - Not packed input array !";
245 throw(SzMismatchError(msg));
246 }
[1390]247 int ndg1 = 0;
248 for(k=0; k<in.NbDimensions(); k++)
249 if (in.Size(k) > 1) ndg1++;
250 if (_onedonly)
[1394]251 if (ndg1 > 1) {
252 msg = _msg + "CheckResize(real in, complex out) - Only 1-D array accepted !";
253 throw(SzMismatchError(msg));
254 }
[1390]255 sa_size_t sz[BASEARRAY_MAXNDIMS];
[1400]256 //
257 if (ndg1 > 1) {
258 sz[0] = in.Size(0)/2+1;
259 for(k=1; k<in.NbDimensions(); k++)
260 sz[k] = in.Size(k);
261 }
262 else {
263 for(k=0; k<BASEARRAY_MAXNDIMS; k++) sz[k] = 1;
264 sz[in.MaxSizeKA()] = in.Size(in.MaxSizeKA())/2+1;
265 // sz[k] = in.Size(k)/2+1;
266 // sz[k] = (in.Size(k)%2 != 0) ? in.Size(k)/2+1 : in.Size(k)/2;
267 }
[1390]268 out.ReSize(in.NbDimensions(), sz);
269
270 return(ndg1);
[710]271}
272
273/* --Methode-- */
[1390]274template <class T>
[1402]275int FFTArrayChecker<T>::CheckResize(TArray< complex<T> > const & in, TArray< T > & out,
276 bool usoutsz)
[710]277{
[1390]278 int k;
[1394]279 string msg;
280 if (in.Size() < 1) {
281 msg = _msg + "CheckResize(complex in, real out) - Unallocated input array !";
282 throw(SzMismatchError(msg));
283 }
[1390]284 if (_checkpack)
[1394]285 if ( !in.IsPacked() ) {
286 msg = _msg + "CheckResize(complex in, real out) - Not packed input array !";
287 throw(SzMismatchError(msg));
288 }
[1390]289 int ndg1 = 0;
290 for(k=0; k<in.NbDimensions(); k++)
291 if (in.Size(k) > 1) ndg1++;
292 if (_onedonly)
[1394]293 if (ndg1 > 1) {
294 msg = _msg + "CheckResize(complex in, real out) - Only 1-D array accepted !";
295 throw(SzMismatchError(msg));
296 }
[1402]297 if (usoutsz) { // We have to use output array size
298 bool fgerr = false;
299 if (ndg1 > 1) {
300 if (in.Size(0) != out.Size(0)/2+1) fgerr = true;
301 }
302 else {
303 if (in.Size(in.MaxSizeKA()) != out.Size(in.MaxSizeKA())/2+1) fgerr = true;
304 }
305 if (fgerr) {
306 msg = _msg + "CheckResize(complex in, real out) - Incompatible in-out sizes !";
307 throw(SzMismatchError(msg));
308 }
309 }
310 else { // We have to resize the output array
311 sa_size_t sz[BASEARRAY_MAXNDIMS];
312 if (ndg1 > 1) {
313 sz[0] = 2*in.Size(0)-1;
314 for(k=1; k<in.NbDimensions(); k++)
315 sz[k] = in.Size(k);
[1400]316 // sz[k] = in.Size(k)*2-1;
[1402]317 }
318 else {
319 for(k=0; k<BASEARRAY_MAXNDIMS; k++) sz[k] = 1;
320 T thr = ZeroThreshold();
321 sa_size_t n = in.Size(in.MaxSizeKA());
322 sa_size_t ncs = ( (in[n-1].imag() < -thr) || (in[n-1].imag() > thr) ) ?
323 ncs = 2*n-1 : ncs = 2*n-2;
324 sz[in.MaxSizeKA()] = ncs;
325 }
326 out.ReSize(in.NbDimensions(), sz);
[1394]327 }
328
[1390]329 return(ndg1);
330
[710]331}
332
333
[1390]334#ifdef __CXX_PRAGMA_TEMPLATES__
335#pragma define_template FFTArrayChecker<r_4>
336#pragma define_template FFTArrayChecker<r_8>
337#endif
338
339#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
340template class FFTArrayChecker<r_4>;
341template class FFTArrayChecker<r_8>;
342#endif
Note: See TracBrowser for help on using the repository browser.