//! \~\file pifft.h //! \~\ingroup Math //! \~\ingroup FFTW //! \~\brief //! \~english FFT, IFFT and Hilbert transformations //! \~russian БПФ, ОБПФ и преобразования Гильберта /* PIP - Platform Independent Primitives Class for FFT, IFFT and Hilbert transformations Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ //! \defgroup FFTW FFTW //! \~\brief //! \~english Optimized FFT support via libfftw3 //! \~russian Оптимизированный БПФ с помощью libfftw3 //! //! \~\details //! \~english \section cmake_module_FFTW Building with CMake //! \~russian \section cmake_module_FFTW Сборка с использованием CMake //! //! \~\code //! find_package(PIP REQUIRED) //! target_link_libraries([target] PIP::FFTW) //! \endcode //! //! \~english \par Common //! \~russian \par Общее //! //! \~english //! These files provides FFT using [libfftw3](https://fftw.org/) //! //! \~russian //! Эти файлы обеспечивают БПФ с использованием [libfftw3](https://fftw.org/) //! //! \~\authors //! \~english //! Ivan Pelipenko peri4ko@yandex.ru; //! Andrey Bychkov work.a.b@yandex.ru; //! \~russian //! Иван Пелипенко peri4ko@yandex.ru; //! Андрей Бычков work.a.b@yandex.ru; //! #ifndef PIFFT_H #define PIFFT_H #include "pimathcomplex.h" #ifndef MICRO_PIP # include "pip_fftw_export.h" //! \~\ingroup Math //! \~\ingroup FFTW //! \~\brief //! \~english Double-precision FFT helper that stores the last transform result. //! \~russian Вспомогательный класс БПФ двойной точности, сохраняющий результат последнего преобразования. class PIP_EXPORT PIFFT_double { public: //! \~english Constructs an empty transformer. //! \~russian Создает пустой объект преобразования. PIFFT_double(); //! \~english Calculates complex FFT for the input signal. //! \~russian Вычисляет комплексное БПФ для входного сигнала. PIVector * calcFFT(const PIVector & val); //! \~english Calculates FFT for a real-valued input signal. //! \~russian Вычисляет БПФ для вещественного входного сигнала. PIVector * calcFFT(const PIVector & val); //! \~english Calculates inverse FFT for a complex spectrum. //! \~russian Вычисляет обратное БПФ для комплексного спектра. PIVector * calcFFTinverse(const PIVector & val); //! \~english Calculates the analytic signal using a Hilbert transform. //! \~russian Вычисляет аналитический сигнал с помощью преобразования Гильберта. PIVector * calcHilbert(const PIVector & val); //! \~english Returns magnitudes of the last calculated result. //! \~russian Возвращает модули последнего вычисленного результата. PIVector getAmplitude() const; //! \~english Returns real parts of the last calculated result. //! \~russian Возвращает действительные части последнего вычисленного результата. PIVector getReal() const; //! \~english Returns imaginary parts of the last calculated result. //! \~russian Возвращает мнимые части последнего вычисленного результата. PIVector getImag() const; private: PIVector result; typedef ptrdiff_t ae_int_t; struct ftplan { PIVector plan; PIVector precomputed; PIVector tmpbuf; PIVector stackbuf; }; ftplan curplan; void fftc1d(const PIVector & a, uint n); void fftc1r(const PIVector & a, uint n); void fftc1dinv(const PIVector & a, uint n); void createPlan(uint n); void ftbasegeneratecomplexfftplan(uint n, ftplan * plan); void ftbase_ftbasegenerateplanrec(int n, int tasktype, ftplan * plan, int * plansize, int * precomputedsize, int * planarraysize, int * tmpmemsize, int * stackmemsize, ae_int_t stackptr, int debugi = 0); void ftbase_ftbaseprecomputeplanrec(ftplan * plan, int entryoffset, ae_int_t stackptr); void ftbasefactorize(int n, int * n1, int * n2); void ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int * best); int ftbasefindsmooth(int n); void ftbaseexecuteplan(PIVector * a, int aoffset, int n, ftplan * plan); void ftbaseexecuteplanrec(PIVector * a, int aoffset, ftplan * plan, int entryoffset, ae_int_t stackptr); void ftbase_internalcomplexlintranspose(PIVector * a, int m, int n, int astart, PIVector * buf); void ftbase_ffticltrec(PIVector * a, int astart, int astride, PIVector * b, int bstart, int bstride, int m, int n); void ftbase_internalreallintranspose(PIVector * a, int m, int n, int astart, PIVector * buf); void ftbase_fftirltrec(PIVector * a, int astart, int astride, PIVector * b, int bstart, int bstride, int m, int n); void ftbase_ffttwcalc(PIVector * a, int aoffset, int n1, int n2); }; //! \~\ingroup Math //! \~\ingroup FFTW //! \~\brief //! \~english Single-precision FFT helper that stores the last transform result. //! \~russian Вспомогательный класс БПФ одинарной точности, сохраняющий результат последнего преобразования. class PIP_EXPORT PIFFT_float { public: //! \~english Constructs an empty transformer. //! \~russian Создает пустой объект преобразования. PIFFT_float(); //! \~english Calculates complex FFT for the input signal. //! \~russian Вычисляет комплексное БПФ для входного сигнала. PIVector * calcFFT(const PIVector & val); //! \~english Calculates FFT for a real-valued input signal. //! \~russian Вычисляет БПФ для вещественного входного сигнала. PIVector * calcFFT(const PIVector & val); //! \~english Calculates inverse FFT for a complex spectrum. //! \~russian Вычисляет обратное БПФ для комплексного спектра. PIVector * calcFFTinverse(const PIVector & val); //! \~english Calculates the analytic signal using a Hilbert transform. //! \~russian Вычисляет аналитический сигнал с помощью преобразования Гильберта. PIVector * calcHilbert(const PIVector & val); //! \~english Returns magnitudes of the last calculated result. //! \~russian Возвращает модули последнего вычисленного результата. PIVector getAmplitude() const; //! \~english Returns real parts of the last calculated result. //! \~russian Возвращает действительные части последнего вычисленного результата. PIVector getReal() const; //! \~english Returns imaginary parts of the last calculated result. //! \~russian Возвращает мнимые части последнего вычисленного результата. PIVector getImag() const; private: PIVector result; typedef ptrdiff_t ae_int_t; struct ftplan { PIVector plan; PIVector precomputed; PIVector tmpbuf; PIVector stackbuf; }; ftplan curplan; void fftc1d(const PIVector & a, uint n); void fftc1r(const PIVector & a, uint n); void fftc1dinv(const PIVector & a, uint n); void createPlan(uint n); void ftbasegeneratecomplexfftplan(uint n, ftplan * plan); void ftbase_ftbasegenerateplanrec(int n, int tasktype, ftplan * plan, int * plansize, int * precomputedsize, int * planarraysize, int * tmpmemsize, int * stackmemsize, ae_int_t stackptr, int debugi = 0); void ftbase_ftbaseprecomputeplanrec(ftplan * plan, int entryoffset, ae_int_t stackptr); void ftbasefactorize(int n, int * n1, int * n2); void ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int * best); int ftbasefindsmooth(int n); void ftbaseexecuteplan(PIVector * a, int aoffset, int n, ftplan * plan); void ftbaseexecuteplanrec(PIVector * a, int aoffset, ftplan * plan, int entryoffset, ae_int_t stackptr); void ftbase_internalcomplexlintranspose(PIVector * a, int m, int n, int astart, PIVector * buf); void ftbase_ffticltrec(PIVector * a, int astart, int astride, PIVector * b, int bstart, int bstride, int m, int n); void ftbase_internalreallintranspose(PIVector * a, int m, int n, int astart, PIVector * buf); void ftbase_fftirltrec(PIVector * a, int astart, int astride, PIVector * b, int bstart, int bstride, int m, int n); void ftbase_ffttwcalc(PIVector * a, int aoffset, int n1, int n2); }; //! \~english Default FFT helper alias based on double precision. //! \~russian Псевдоним стандартного FFT-помощника на базе двойной точности. typedef PIFFT_double PIFFT; //! \~english Double-precision FFT helper alias. //! \~russian Псевдоним FFT-помощника двойной точности. typedef PIFFT_double PIFFTd; //! \~english Single-precision FFT helper alias. //! \~russian Псевдоним FFT-помощника одинарной точности. typedef PIFFT_float PIFFTf; # ifndef CC_VC # define _PIFFTW_H(type) \ class PIP_FFTW_EXPORT _PIFFTW_P_##type##_ { \ public: \ _PIFFTW_P_##type##_(); \ ~_PIFFTW_P_##type##_(); \ const PIVector> & calcFFT(const PIVector> & in); \ const PIVector> & calcFFTR(const PIVector & in); \ const PIVector> & calcFFTI(const PIVector> & in); \ void preparePlan(int size, int op); \ void * impl; \ }; _PIFFTW_H(float) _PIFFTW_H(double) _PIFFTW_H(ldouble) //! \~\ingroup Math //! \~\ingroup FFTW //! \~\brief //! \~english Thin wrapper over libfftw3 plans for a selected scalar type. //! \~russian Тонкая обертка над планами libfftw3 для выбранного скалярного типа. template class PIFFTW { public: //! \~english Constructs the backend object for the selected precision. //! \~russian Создает внутренний объект для выбранной точности. explicit PIFFTW() { p = 0; newP(p); } //! \~english Destroys the backend object and its cached plans. //! \~russian Уничтожает внутренний объект и его кэшированные планы. ~PIFFTW() { deleteP(p); } //! \~english Calculates complex FFT for the input signal. //! \~russian Вычисляет комплексное БПФ для входного сигнала. inline const PIVector> & calcFFT(const PIVector> & in) { return PIVector>().resize(in.size()); } //! \~english Calculates FFT for a real-valued input signal. //! \~russian Вычисляет БПФ для вещественного входного сигнала. inline const PIVector> & calcFFT(const PIVector & in) { return PIVector>().resize(in.size()); } //! \~english Calculates inverse FFT for a complex spectrum. //! \~russian Вычисляет обратное БПФ для комплексного спектра. inline const PIVector> & calcFFTinverse(const PIVector> & in) { return PIVector>().resize(in.size()); } //! \~english Operation kind for precomputed FFTW plans. //! \~russian Тип операции для заранее подготовленных планов FFTW. enum FFT_Operation { foReal /** \~english Forward transform for real input \~russian Прямое преобразование для вещественного входа */, foComplex /** \~english Forward transform for complex input \~russian Прямое преобразование для комплексного входа */, foInverse /** \~english Inverse complex transform \~russian Обратное комплексное преобразование */ }; //! \~english Prepares and caches a plan for the specified signal size and operation. //! \~russian Подготавливает и кэширует план для указанного размера сигнала и операции. inline void preparePlan(int size, FFT_Operation op) {} private: void operator=(const PIFFTW &); PIFFTW(const PIFFTW &); inline void newP(void *& _p) {} inline void deleteP(void *& _p) {} void * p; }; template<> inline const PIVector> & PIFFTW::calcFFT(const PIVector> & in) { return ((_PIFFTW_P_float_ *)p)->calcFFT(in); } template<> inline const PIVector> & PIFFTW::calcFFT(const PIVector & in) { return ((_PIFFTW_P_float_ *)p)->calcFFTR(in); } template<> inline const PIVector> & PIFFTW::calcFFTinverse(const PIVector> & in) { return ((_PIFFTW_P_float_ *)p)->calcFFTI(in); } template<> inline void PIFFTW::preparePlan(int size, FFT_Operation op) { ((_PIFFTW_P_float_ *)p)->preparePlan(size, op); } template<> inline void PIFFTW::newP(void *& _p) { _p = new _PIFFTW_P_float_(); } template<> inline void PIFFTW::deleteP(void *& _p) { if (_p) delete (_PIFFTW_P_float_ *)_p; _p = 0; } //! \~english Single-precision FFTW wrapper. //! \~russian Обертка FFTW одинарной точности. typedef PIFFTW PIFFTWf; template<> inline const PIVector> & PIFFTW::calcFFT(const PIVector> & in) { return ((_PIFFTW_P_double_ *)p)->calcFFT(in); } template<> inline const PIVector> & PIFFTW::calcFFT(const PIVector & in) { return ((_PIFFTW_P_double_ *)p)->calcFFTR(in); } template<> inline const PIVector> & PIFFTW::calcFFTinverse(const PIVector> & in) { return ((_PIFFTW_P_double_ *)p)->calcFFTI(in); } template<> inline void PIFFTW::preparePlan(int size, FFT_Operation op) { ((_PIFFTW_P_double_ *)p)->preparePlan(size, op); } template<> inline void PIFFTW::newP(void *& _p) { _p = new _PIFFTW_P_double_(); } template<> inline void PIFFTW::deleteP(void *& _p) { if (_p) delete (_PIFFTW_P_double_ *)_p; _p = 0; } //! \~english Double-precision FFTW wrapper. //! \~russian Обертка FFTW двойной точности. typedef PIFFTW PIFFTWd; template<> inline const PIVector> & PIFFTW::calcFFT(const PIVector> & in) { return ((_PIFFTW_P_ldouble_ *)p)->calcFFT(in); } template<> inline const PIVector> & PIFFTW::calcFFT(const PIVector & in) { return ((_PIFFTW_P_ldouble_ *)p)->calcFFTR(in); } template<> inline const PIVector> & PIFFTW::calcFFTinverse(const PIVector> & in) { return ((_PIFFTW_P_ldouble_ *)p)->calcFFTI(in); } template<> inline void PIFFTW::preparePlan(int size, FFT_Operation op) { ((_PIFFTW_P_ldouble_ *)p)->preparePlan(size, op); } template<> inline void PIFFTW::newP(void *& _p) { _p = new _PIFFTW_P_ldouble_(); } template<> inline void PIFFTW::deleteP(void *& _p) { if (_p) delete (_PIFFTW_P_ldouble_ *)_p; _p = 0; } //! \~english Extended-precision FFTW wrapper. //! \~russian Обертка FFTW расширенной точности. typedef PIFFTW PIFFTWld; # endif #endif // MICRO_PIP #endif // PIFFT_H