//! \addtogroup Math //! \{ //! \file pifft.h //! \brief //! \~english Declares \a PIFFT classes //! \~russian Объявление классов \a PIFFT //! \~\authors //! \~english Ivan Pelipenko peri4ko@yandex.ru; Andrey Bychkov work.a.b@yandex.ru //! \~russian Иван Пелипенко peri4ko@yandex.ru; Андрей Бычков work.a.b@yandex.ru //! \~\} /* 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" //! \addtogroup Math //! \{ //! \class PIFFT_double //! \brief //! \~english Fast Fourier Transform implementation for double precision. //! \~russian Реализация быстрого преобразования Фурье для двойной точности. //! \~\} //! \sa \a PIFFT_float, \a PIFFTW class PIP_EXPORT PIFFT_double { public: //! \~english Default constructor. //! \~russian Конструктор по умолчанию. PIFFT_double(); //! \~english Calculate FFT from complex vector. //! \~russian Вычисление БПФ из комплексного вектора. PIVector * calcFFT(const PIVector & val); //! \~english Calculate FFT from real vector. //! \~russian Вычисление БПФ из вещественного вектора. PIVector * calcFFT(const PIVector & val); //! \~english Calculate inverse FFT. //! \~russian Вычисление обратного БПФ. PIVector * calcFFTinverse(const PIVector & val); //! \~english Calculate Hilbert transform. //! \~russian Вычисление преобразования Гильберта. PIVector * calcHilbert(const PIVector & val); //! \~english Get amplitude spectrum. //! \~russian Получить амплитудный спектр. PIVector getAmplitude() const; //! \~english Get real part. //! \~russian Получить действительную часть. PIVector getReal() const; //! \~english Get imaginary part. //! \~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); }; //! \addtogroup Math //! \{ //! \class PIFFT_float //! \brief //! \~english Fast Fourier Transform implementation for single precision. //! \~russian Реализация быстрого преобразования Фурье для одинарной точности. //! \~\} //! \sa \a PIFFT_double, \a PIFFTW class PIP_EXPORT PIFFT_float { public: //! \~english Default constructor. //! \~russian Конструктор по умолчанию. PIFFT_float(); //! \~english Calculate FFT from complex vector. //! \~russian Вычисление БПФ из комплексного вектора. PIVector * calcFFT(const PIVector & val); //! \~english Calculate FFT from real vector. //! \~russian Вычисление БПФ из вещественного вектора. PIVector * calcFFT(const PIVector & val); //! \~english Calculate inverse FFT. //! \~russian Вычисление обратного БПФ. PIVector * calcFFTinverse(const PIVector & val); //! \~english Calculate Hilbert transform. //! \~russian Вычисление преобразования Гильберта. PIVector * calcHilbert(const PIVector & val); //! \~english Get amplitude spectrum. //! \~russian Получить амплитудный спектр. PIVector getAmplitude() const; //! \~english Get real part. //! \~russian Получить действительную часть. PIVector getReal() const; //! \~english Get imaginary part. //! \~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); }; //! \~\} typedef PIFFT_double PIFFT; typedef PIFFT_double PIFFTd; 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) //! \addtogroup FFTW //! \{ //! \class PIFFTW //! \brief //! \~english FFTW wrapper for arbitrary precision types. //! \~russian Обёртка FFTW для типов произвольной точности. //! \~\} //! \note Requires linking against libfftw3 //! \sa \a PIFFT_double, \a PIFFT_float template class PIFFTW { public: //! \~english Default constructor. //! \~russian Конструктор по умолчанию. explicit PIFFTW() { p = 0; newP(p); } //! \~english Destructor. //! \~russian Деструктор. ~PIFFTW() { deleteP(p); } //! \~english Calculate FFT from complex vector. //! \~russian Вычисление БПФ из комплексного вектора. inline const PIVector> & calcFFT(const PIVector> & in) { return PIVector>().resize(in.size()); } //! \~english Calculate FFT from real vector. //! \~russian Вычисление БПФ из вещественного вектора. inline const PIVector> & calcFFT(const PIVector & in) { return PIVector>().resize(in.size()); } //! \~english Calculate inverse FFT. //! \~russian Вычисление обратного БПФ. inline const PIVector> & calcFFTinverse(const PIVector> & in) { return PIVector>().resize(in.size()); } //! \~english FFT operation type. //! \~russian Тип операции БПФ. enum FFT_Operation { foReal, foComplex, foInverse }; //! \~english Prepare computation plan. //! \~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; } 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; } 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; } typedef PIFFTW PIFFTWld; # endif #endif // MICRO_PIP #endif // PIFFT_H