diff --git a/CMakeLists.txt b/CMakeLists.txt index 67b0bed8..1d9313b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,10 +52,13 @@ include_directories("src") foreach(F ${PIP_FOLDERS}) include_directories("src/${F}") file(GLOB HS "src/${F}/*.h") + file(GLOB PHS "src/${F}/*_p.h") file(GLOB CS "src/${F}/*.cpp") list(APPEND HDRS ${HS}) + list(APPEND PHDRS ${PHS}) list(APPEND CPPS ${CS}) endforeach(F) +list(REMOVE_ITEM HDRS ${PHDRS}) # Check Bessel functions set(CMAKE_REQUIRED_INCLUDES math.h) @@ -150,7 +153,7 @@ if (FFTW) if (WIN32) list(APPEND LIBS fftw3-3 fftw3f-3 fftw3l-3) else () - list(APPEND LIBS fftw3 fftw3f fftw3l) + list(APPEND LIBS fftw3 fftw3f) endif () else () message(STATUS "Building without fftw3 support") @@ -183,7 +186,7 @@ if (WIN32) list(APPEND LIBS ws2_32 iphlpapi psapi) list(APPEND CPPS "pip_resource_win.rc") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPSAPI_VERSION=1") - add_library(pip SHARED ${CPPS} ${HDRS}) + add_library(pip SHARED ${CPPS} ${HDRS} ${PHDRS}) if (${CMAKE_C_COMPILER} STREQUAL "cl") include(GenerateExportHeader) generate_export_header(pip) diff --git a/main.cpp b/main.cpp index 794eb8ad..019f70e3 100644 --- a/main.cpp +++ b/main.cpp @@ -43,8 +43,9 @@ int asize(ssize_t s, size_t pid_rsize) { int main(int argc, char *argv[]) { PIFFTWf fft; PIVector in; - for (int i = 0; i < 32; ++i) + for (int i = 0; i < 50; ++i) in << i%10; + fft.preparePlan(50, PIFFTWf::foReal); PIVector out = fft.calcFFT(in); piCout << out; /*for (int i = 0; i < 16; ++i) { diff --git a/src/math/picrypt.cpp b/src/math/picrypt.cpp index bed068e1..3559f0d9 100644 --- a/src/math/picrypt.cpp +++ b/src/math/picrypt.cpp @@ -35,7 +35,7 @@ PICrypt::PICrypt() { randombytes_buf(key_.data(), key_.size()); randombytes_buf(nonce_.data(), nonce_.size()); #else - piCout << "[PICrypt]" << "Warning: PICrypt is disabled, to enable install sodium library and build pip with -DCRYPT="; + piCout << "[PICrypt]" << "Warning: PICrypt is disabled, to enable install libsodium-dev library and build pip with -DCRYPT=1"; #endif } diff --git a/src/math/pifft.h b/src/math/pifft.h index edce2688..80dcc1dc 100644 --- a/src/math/pifft.h +++ b/src/math/pifft.h @@ -153,6 +153,7 @@ public: private: void operator =(const PIFFTW & ); + PIFFTW(const PIFFTW &); inline void newP(void *& _p) {} inline void deleteP(void *& _p) {} @@ -167,6 +168,8 @@ template<> inline void PIFFTW::preparePlan(int size, FFT_Operation 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);} @@ -175,7 +178,10 @@ template<> inline void PIFFTW::preparePlan(int size, FFT_Operation 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; + +#ifdef WINDOWS 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);} @@ -183,10 +189,7 @@ template<> inline void PIFFTW::preparePlan(int size, FFT_Operation 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 PIFFTWf; -typedef PIFFTW PIFFTWd; typedef PIFFTW PIFFTWld; - +#endif // WINDOWS #endif // PIFFT_H diff --git a/src/math/pifft_p.h b/src/math/pifft_p.h index c43e53a9..a3fe041e 100644 --- a/src/math/pifft_p.h +++ b/src/math/pifft_p.h @@ -25,7 +25,7 @@ #include "pivector.h" #include "pimutex.h" -#include +#include "picout.h" #ifdef PIP_FFTW # include "fftw3.h" #else @@ -36,106 +36,136 @@ #endif -static PIMutex __pip_fft_plan_mutex; - - template class PIFFTW_Private { public: - explicit PIFFTW_Private() {plan = 0; newPlan(plan);} - ~PIFFTW_Private() {deletePlan(plan);} + explicit PIFFTW_Private() { + plan = 0; +#ifdef PIP_FFTW +// fftwf_m +#else + piCout << "[PIFFTW]" << "Warning: PIFFTW is disabled, to enable install libfftw3-dev library and build pip with -DFFTW=1"; +#endif + p_makeThreadSafe(); + } + ~PIFFTW_Private() {p_destroyPlan(plan);} const PIVector > & calcFFT(const PIVector > & in) { - result.resize(in.size()); - __pip_fft_plan_mutex.lock(); - createPlan_c_1d(plan, in.size_s(), in.data(), result.data(), FFTW_FORWARD, FFTW_ESTIMATE); - __pip_fft_plan_mutex.unlock(); - executePlan(plan); - destroyPlan(plan); - return result; + if (prepare != PlanParams(in.size(), fo_complex)) { + p_out.resize(in.size()); + piCout << "[PIFFTW]" << "creating plan"; + p_createPlan_c2c_1d(plan, in.size(), in.data(), p_out.data(), FFTW_FORWARD, FFTW_ESTIMATE | FFTW_UNALIGNED); + prepare = PlanParams(in.size(), fo_complex); + } + p_executePlan_c2c(plan, in.data(), p_out.data()); + return p_out; } const PIVector > & calcFFT(const PIVector & in) { - result.resize(in.size()); - __pip_fft_plan_mutex.lock(); - createPlan_r2c_1d(plan, in.size_s(), in.data(), result.data(), FFTW_ESTIMATE); - __pip_fft_plan_mutex.unlock(); - executePlan(plan); - destroyPlan(plan); - return result; + if (prepare != PlanParams(in.size(), fo_real)) { + p_out.resize(in.size()); + piCout << "[PIFFTW]" << "creating plan"; + p_createPlan_r2c_1d(plan, in.size(), in.data(), p_out.data(), FFTW_ESTIMATE | FFTW_UNALIGNED); + prepare = PlanParams(in.size(), fo_real); + } + p_executePlan_r2c(plan, in.data(), p_out.data()); + return p_out; } const PIVector > & calcFFTinverse(const PIVector > & in) { - result.resize(in.size()); - __pip_fft_plan_mutex.lock(); - createPlan_c_1d(plan, in.size_s(), in.data(), result.data(), FFTW_BACKWARD, FFTW_ESTIMATE); - __pip_fft_plan_mutex.unlock(); - executePlan(plan); - destroyPlan(plan); - return result; + if (prepare != PlanParams(in.size(), fo_inverse)) { + p_out.resize(in.size()); + piCout << "[PIFFTW]" << "creating plan"; + p_createPlan_c2c_1d(plan, in.size(), in.data(), p_out.data(), FFTW_BACKWARD, FFTW_ESTIMATE | FFTW_UNALIGNED); + prepare = PlanParams(in.size(), fo_inverse); + } + p_executePlan_c2c(plan, in.data(), p_out.data()); + return p_out; } enum FFT_Operation {fo_real, fo_complex, fo_inverse}; void preparePlan(int size, int op) { - PIVector > in(size), out(size); - PIVector inr(size); - __pip_fft_plan_mutex.lock(); + p_inr.clear(); + p_in.clear(); + p_out.clear(); switch ((FFT_Operation)op) { - case fo_real: - createPlan_r2c_1d(plan, in.size_s(), inr.data(), out.data(), FFTW_MEASURE); + case fo_real: + p_inr.resize(size); + p_out.resize(size); + p_createPlan_r2c_1d(plan, size, p_inr.data(), p_out.data(), FFTW_MEASURE | FFTW_UNALIGNED); break; - case fo_complex: - createPlan_c_1d(plan, in.size_s(), in.data(), out.data(), FFTW_FORWARD, FFTW_MEASURE); + case fo_complex: + p_in.resize(size); + p_out.resize(size); + p_createPlan_c2c_1d(plan, size, p_in.data(), p_out.data(), FFTW_FORWARD, FFTW_MEASURE | FFTW_UNALIGNED); break; - case fo_inverse: - createPlan_c_1d(plan, in.size_s(), in.data(), out.data(), FFTW_BACKWARD, FFTW_MEASURE); + case fo_inverse: + p_in.resize(size); + p_out.resize(size); + p_createPlan_c2c_1d(plan, size, p_in.data(), p_out.data(), FFTW_BACKWARD, FFTW_MEASURE | FFTW_UNALIGNED); + break; + default: + size = 0; break; } - __pip_fft_plan_mutex.unlock(); + prepare = PlanParams(size, (FFT_Operation)op); } - inline void createPlan_c_1d(void * plan, int size, const void * in, void * out, int dir, int flags) {} - inline void createPlan_r2c_1d(void * plan, int size, const void * in, void * out, int flags) {} - inline void executePlan(void * plan) {} - inline void destroyPlan(void * plan) {} - inline void newPlan(void *& plan) {} - inline void deletePlan(void *& plan) {} + inline void p_createPlan_c2c_1d(void *& plan, int size, const void * in, void * out, int dir, int flags) {} + inline void p_createPlan_r2c_1d(void *& plan, int size, const void * in, void * out, int flags) {} + inline void p_executePlan_c2c(void * plan, const void * in, void * out) {} + inline void p_executePlan_r2c(void * plan, const void * in, void * out) {} + inline void p_destroyPlan(void *& plan) {} + inline void p_makeThreadSafe() {} - PIVector > result; + struct PlanParams { + PlanParams() {size = 0; op = fo_complex;} + PlanParams(int size_, FFT_Operation op_) {size = size_; op = op_;} + bool isValid() {return size > 0;} + bool operator ==(const PlanParams & v) const {return (v.size == size) && (v.op == op);} + bool operator !=(const PlanParams & v) const {return !(*this == v);} + int size; + FFT_Operation op; + }; + + PIVector > p_in; + PIVector p_inr; + PIVector > p_out; void * plan; + PlanParams prepare; }; #ifdef PIP_FFTW +template<> inline void PIFFTW_Private::p_createPlan_c2c_1d(void *& plan, int size, const void * in, void * out, int dir, int flags) { + plan = fftwf_plan_dft_1d(size, (fftwf_complex *)in, (fftwf_complex *)out, dir, flags);} +template<> inline void PIFFTW_Private::p_createPlan_r2c_1d(void *& plan, int size, const void * in, void * out, int flags) { + plan = fftwf_plan_dft_r2c_1d(size, (float *)in, (fftwf_complex *)out, flags);} +template<> inline void PIFFTW_Private::p_executePlan_c2c(void * plan, const void * in, void * out) {fftwf_execute_dft((fftwf_plan)plan, (fftwf_complex *)in, (fftwf_complex *)out);} +template<> inline void PIFFTW_Private::p_executePlan_r2c(void * plan, const void * in, void * out) {fftwf_execute_dft_r2c((fftwf_plan)plan, (float *)in, (fftwf_complex *)out);} +template<> inline void PIFFTW_Private::p_destroyPlan(void *& plan) {if (plan) fftwf_destroy_plan((fftwf_plan)plan); plan = 0;} +template<> inline void PIFFTW_Private::p_makeThreadSafe() {fftwf_make_planner_thread_safe();} -template<> inline void PIFFTW_Private::createPlan_c_1d(void * plan, int size, const void * in, void * out, int dir, int flags) { - *(fftwf_plan*)plan = fftwf_plan_dft_1d(size, (fftwf_complex *)in, (fftwf_complex *)out, dir, flags);} -template<> inline void PIFFTW_Private::createPlan_r2c_1d(void * plan, int size, const void * in, void * out, int flags) { - *(fftwf_plan*)plan = fftwf_plan_dft_r2c_1d(size, (float *)in, (fftwf_complex *)out, flags);} -template<> inline void PIFFTW_Private::executePlan(void * plan) {fftwf_execute(*(fftwf_plan*)plan);} -template<> inline void PIFFTW_Private::destroyPlan(void * plan) {fftwf_destroy_plan(*(fftwf_plan*)plan);} -template<> inline void PIFFTW_Private::newPlan(void *& plan) {plan = new fftwf_plan();} -template<> inline void PIFFTW_Private::deletePlan(void *& plan) {if (plan) delete (fftwf_plan*)plan; plan = 0;} +template<> inline void PIFFTW_Private::p_createPlan_c2c_1d(void *& plan, int size, const void * in, void * out, int dir, int flags) { + plan = fftw_plan_dft_1d(size, (fftw_complex *)in, (fftw_complex *)out, dir, flags);} +template<> inline void PIFFTW_Private::p_createPlan_r2c_1d(void *& plan, int size, const void * in, void * out, int flags) { + plan = fftw_plan_dft_r2c_1d(size, (double *)in, (fftw_complex *)out, flags);} +template<> inline void PIFFTW_Private::p_executePlan_c2c(void * plan, const void * in, void * out) {fftw_execute_dft((fftw_plan)plan, (fftw_complex *)in, (fftw_complex *)out);} +template<> inline void PIFFTW_Private::p_executePlan_r2c(void * plan, const void * in, void * out) {fftw_execute_dft_r2c((fftw_plan)plan, (double *)in, (fftw_complex *)out);} +template<> inline void PIFFTW_Private::p_destroyPlan(void *& plan) {if (plan) fftw_destroy_plan((fftw_plan)plan); plan = 0;} +template<> inline void PIFFTW_Private::p_makeThreadSafe() {fftw_make_planner_thread_safe();} +#ifdef WINDOWS +template<> inline void PIFFTW_Private::p_createPlan_c2c_1d(void *& plan, int size, const void * in, void * out, int dir, int flags) { + plan = fftwl_plan_dft_1d(size, (fftwl_complex *)in, (fftwl_complex *)out, dir, flags);} +template<> inline void PIFFTW_Private::p_createPlan_r2c_1d(void *& plan, int size, const void * in, void * out, int flags) { + plan = fftwl_plan_dft_r2c_1d(size, (ldouble *)in, (fftwl_complex *)out, flags);} +template<> inline void PIFFTW_Private::p_executePlan_c2c(void * plan, const void * in, void * out) {fftwl_execute_dft((fftwl_plan)plan, (fftwl_complex *)in, (fftwl_complex *)out);} +template<> inline void PIFFTW_Private::p_executePlan_r2c(void * plan, const void * in, void * out) {fftwl_execute_dft_r2c((fftwl_plan)plan, (ldouble *)in, (fftwl_complex *)out);} +template<> inline void PIFFTW_Private::p_destroyPlan(void *& plan) {if (plan) fftwl_destroy_plan((fftwl_plan)plan); plan = 0;} +template<> inline void PIFFTW_Private::p_makeThreadSafe() {fftwl_make_planner_thread_safe();} +#endif // WINDOWS -template<> inline void PIFFTW_Private::createPlan_c_1d(void * plan, int size, const void * in, void * out, int dir, int flags) { - *(fftw_plan*)plan = fftw_plan_dft_1d(size, (fftw_complex *)in, (fftw_complex *)out, dir, flags);} -template<> inline void PIFFTW_Private::createPlan_r2c_1d(void * plan, int size, const void * in, void * out, int flags) { - *(fftw_plan*)plan = fftw_plan_dft_r2c_1d(size, (double *)in, (fftw_complex *)out, flags);} -template<> inline void PIFFTW_Private::executePlan(void * plan) {fftw_execute(*(fftw_plan*)plan);} -template<> inline void PIFFTW_Private::destroyPlan(void * plan) {fftw_destroy_plan(*(fftw_plan*)plan);} -template<> inline void PIFFTW_Private::newPlan(void *& plan) {plan = new fftw_plan();} -template<> inline void PIFFTW_Private::deletePlan(void *& plan) {if (plan) delete (fftw_plan*)plan; plan = 0;} - - -template<> inline void PIFFTW_Private::createPlan_c_1d(void * plan, int size, const void * in, void * out, int dir, int flags) { - *(fftwl_plan*)plan = fftwl_plan_dft_1d(size, (fftwl_complex *)in, (fftwl_complex *)out, dir, flags);} -template<> inline void PIFFTW_Private::createPlan_r2c_1d(void * plan, int size, const void * in, void * out, int flags) { - *(fftwl_plan*)plan = fftwl_plan_dft_r2c_1d(size, (ldouble *)in, (fftwl_complex *)out, flags);} -template<> inline void PIFFTW_Private::executePlan(void * plan) {fftwl_execute(*(fftwl_plan*)plan);} -template<> inline void PIFFTW_Private::destroyPlan(void * plan) {fftwl_destroy_plan(*(fftwl_plan*)plan);} -template<> inline void PIFFTW_Private::newPlan(void *& plan) {plan = new fftwl_plan();} -template<> inline void PIFFTW_Private::deletePlan(void *& plan) {if (plan) delete (fftwl_plan*)plan; plan = 0;} #endif // PIP_FFTW