#include "fftservintf.h" /*! \class SOPHYA::FFTServerInterface \ingroup NTools Defines the interface for FFT (Fast Fourier Transform) operations. Definitions : - Sampling period \b T - Sampling frequency \b fs=1/T - Total number of samples \b N - Frequency step in Fourier space \b =fs/N=1/(N*T) - Component frequencies - k=0 -> 0 - k=1 -> 1/(N*T) - k -> k/(N*T) - k=N/2 -> 1/(2*T) (Nyquist frequency) - k>N/2 -> k/(N*T) (or negative frequency -(N-k)/(N*T)) For a sampling period T=1, the computed Fourier components correspond to : \verbatim 0 1/N 2/N ... 1/2 1/2+1/N 1/2+2/N ... 1-2/N 1-1/N 0 1/N 2/N ... 1/2 ... -2/N -1/N \endverbatim For complex one-dimensional transforms: \f[ out(i) = F_{norm} \Sigma_{j} \ e^{-2 \pi \sqrt{-1} \ i \ j} \ {\rm (forward)} \f] \f[ out(i) = F_{norm} \Sigma_{j} \ e^{2 \pi \sqrt{-1} \ i \ j} \ {\rm (backward)} \f] i,j= 0..N-1 , where N is the input or the output array size. For complex multi-dimensional transforms: \f[ out(i1,i2,...,id) = F_{norm} \Sigma_{j1} \Sigma_{j2} ... \Sigma_{jd} \ e^{-2 \pi \sqrt{-1} \ i1 \ j1} ... e^{-2 \pi \sqrt{-1} \ id \ jd} \ {\rm (forward)} \f] \f[ out(i1,i2,...,id) = F_{norm} \Sigma_{j1} \Sigma_{j2} ... \Sigma_{jd} \ e^{2 \pi \sqrt{-1} \ i1 \ j1} ... e^{2 \pi \sqrt{-1} \ id \ jd} \ {\rm (backward)} \f] For real forward transforms, the input array is real, and the output array complex, with Fourier components up to k=N/2. For real backward transforms, the input array is complex and the output array is real. */ /* --Methode-- */ FFTServerInterface::FFTServerInterface(string info) { _info = info; _fgnorm = true; } /* --Methode-- */ FFTServerInterface::~FFTServerInterface() { } // ----------------- Transforme pour les double ------------------- /* --Methode-- */ //! Forward Fourier transform for double precision complex data /*! \param in : Input complex array \param out : Output complex array */ void FFTServerInterface::FFTForward(TArray< complex > const &, TArray< complex > &) { throw NotAvailableOperation("FFTServer::FFTForward(TArray...) Unsupported operation !"); } /* --Methode-- */ //! Backward (inverse) Fourier transform for double precision complex data /*! \param in : Input complex array \param out : Output complex array */ void FFTServerInterface::FFTBackward(TArray< complex > const &, TArray< complex > &) { throw NotAvailableOperation("FFTServer::FFTBackward(TArray...) Unsupported operation !"); } /* --Methode-- */ //! Forward Fourier transform for double precision real input data /*! \param in : Input real array \param out : Output complex array */ void FFTServerInterface::FFTForward(TArray< r_8 > const &, TArray< complex > &) { throw NotAvailableOperation("FFTServer::FFTForward(TArray...) Unsupported operation !"); } /* --Methode-- */ //! Backward (inverse) Fourier transform for double precision real output data /*! \param in : Input complex array \param out : Output real array \param usoutsz : if true, use the output array size for computing the inverse FFT. */ void FFTServerInterface::FFTBackward(TArray< complex > const &, TArray< r_8 > &, bool) { throw NotAvailableOperation("FFTServer::FFTBackward(TArray...) Unsupported operation !"); } // ----------------- Transforme pour les float ------------------- /* --Methode-- */ //! Forward Fourier transform for complex data /*! \param in : Input complex array \param out : Output complex array */ void FFTServerInterface::FFTForward(TArray< complex > const &, TArray< complex > &) { throw NotAvailableOperation("FFTServer::FFTForward(TArray r_4 ... ) Unsupported operation !"); } /* --Methode-- */ //! Backward (inverse) Fourier transform for complex data /*! \param in : Input complex array \param out : Output complex array */ void FFTServerInterface::FFTBackward(TArray< complex > const &, TArray< complex > &) { throw NotAvailableOperation("FFTServer::FFTBackward(TArray r_4 ... ) Unsupported operation !"); } /* --Methode-- */ //! Forward Fourier transform for real input data /*! \param in : Input real array \param out : Output complex array */ void FFTServerInterface::FFTForward(TArray< r_4 > const &, TArray< complex > &) { throw NotAvailableOperation("FFTServer::FFTForward(TArray r_4 ... ) Unsupported operation !"); } /* --Methode-- */ //! Backward (inverse) Fourier transform for real output data /*! \param in : Input complex array \param out : Output real array \param usoutsz : if true, use the output array size for computing the inverse FFT. */ void FFTServerInterface::FFTBackward(TArray< complex > const &, TArray< r_4 > &, bool) { throw NotAvailableOperation("FFTServer::FFTBackward(TArray r_4 ... ) Unsupported operation !"); } /* --Methode-- */ /*! \class SOPHYA::FFTArrayChecker \ingroup NTools Service class for checking array size and resizing output arrays, to be used by FFTServer classes */ template FFTArrayChecker::FFTArrayChecker(string msg, bool checkpack, bool onedonly) { _msg = msg + " FFTArrayChecker::"; _checkpack = checkpack; _onedonly = onedonly; } /* --Methode-- */ template FFTArrayChecker::~FFTArrayChecker() { } template T FFTArrayChecker::ZeroThreshold() { return(0); } r_8 FFTArrayChecker< r_8 >::ZeroThreshold() { return(1.e-18); } r_4 FFTArrayChecker< r_4 >::ZeroThreshold() { return(1.e-9); } /* --Methode-- */ template int FFTArrayChecker::CheckResize(TArray< complex > const & in, TArray< complex > & out) { int k; string msg; if (in.Size() < 1) { msg = _msg + "CheckResize(complex in, complex out) - Unallocated input array !"; throw(SzMismatchError(msg)); } if (_checkpack) if ( !in.IsPacked() ) { msg = _msg + "CheckResize(complex in, complex out) - Not packed input array !"; throw(SzMismatchError(msg)); } int ndg1 = 0; for(k=0; k 1) ndg1++; if (_onedonly) if (ndg1 > 1) { msg = _msg + "CheckResize(complex in, complex out) - Only 1-D array accepted !"; throw(SzMismatchError(msg)); } out.ReSize(in); // sa_size_t sz[BASEARRAY_MAXNDIMS]; // for(k=0; k int FFTArrayChecker::CheckResize(TArray< T > const & in, TArray< complex > & out) { int k; string msg; if (in.Size() < 1) { msg = _msg + "CheckResize(real in, complex out) - Unallocated input array !"; throw(SzMismatchError(msg)); } if (_checkpack) if ( !in.IsPacked() ) { msg = _msg + "CheckResize(real in, complex out) - Not packed input array !"; throw(SzMismatchError(msg)); } int ndg1 = 0; for(k=0; k 1) ndg1++; if (_onedonly) if (ndg1 > 1) { msg = _msg + "CheckResize(real in, complex out) - Only 1-D array accepted !"; throw(SzMismatchError(msg)); } sa_size_t sz[BASEARRAY_MAXNDIMS]; // if (ndg1 > 1) { sz[0] = in.Size(0)/2+1; for(k=1; k int FFTArrayChecker::CheckResize(TArray< complex > const & in, TArray< T > & out, bool usoutsz) { int k; string msg; if (in.Size() < 1) { msg = _msg + "CheckResize(complex in, real out) - Unallocated input array !"; throw(SzMismatchError(msg)); } if (_checkpack) if ( !in.IsPacked() ) { msg = _msg + "CheckResize(complex in, real out) - Not packed input array !"; throw(SzMismatchError(msg)); } int ndg1 = 0; for(k=0; k 1) ndg1++; if (_onedonly) if (ndg1 > 1) { msg = _msg + "CheckResize(complex in, real out) - Only 1-D array accepted !"; throw(SzMismatchError(msg)); } if (usoutsz) { // We have to use output array size bool fgerr = false; if (ndg1 > 1) { if (in.Size(0) != out.Size(0)/2+1) fgerr = true; } else { if (in.Size(in.MaxSizeKA()) != out.Size(in.MaxSizeKA())/2+1) fgerr = true; } if (fgerr) { msg = _msg + "CheckResize(complex in, real out) - Incompatible in-out sizes !"; throw(SzMismatchError(msg)); } } else { // We have to resize the output array sa_size_t sz[BASEARRAY_MAXNDIMS]; if (ndg1 > 1) { sz[0] = 2*in.Size(0)-1; for(k=1; k thr) ) ? ncs = 2*n-1 : ncs = 2*n-2; sz[in.MaxSizeKA()] = ncs; } out.ReSize(in.NbDimensions(), sz); } return(ndg1); } #ifdef __CXX_PRAGMA_TEMPLATES__ #pragma define_template FFTArrayChecker #pragma define_template FFTArrayChecker #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) template class FFTArrayChecker; template class FFTArrayChecker; #endif