From e6e370642eb6c6f98bf7fe6bb31efd3747873361 Mon Sep 17 00:00:00 2001 From: Vincent Samy Date: Mon, 30 Mar 2020 17:15:34 +0900 Subject: [PATCH] Build and test pass with clang 6.0.0. --- CMakeLists.txt | 2 +- include/BaseFilter.tpp | 4 +- include/Butterworth.tpp | 8 +- include/GenericFilter.h | 22 +- include/MovingAverage.h | 6 +- include/differentiators.h | 120 +++++------ include/difi | 60 +++--- include/math_utils.h | 2 +- tests/CMakeLists.txt | 2 +- tests/DigitalFilterTests.cpp | 2 +- tests/diffTesters.h | 332 ++++++++++++++++++++----------- tests/differentiator_tests.cpp | 119 ++++++----- tests/noisy_function_generator.h | 8 +- tests/warning_macro.h | 15 +- 14 files changed, 419 insertions(+), 283 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a461ad..7d304f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ SET(PROJECT_DEBUG_POSTFIX "_d") set(INSTALL_GENERATED_HEADERS OFF) set(DOXYGEN_USE_MATHJAX "NO") -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) option(BUILD_TESTING "Disable unit tests." ON) option(BUILD_TEST_STATIC_BOOST "Build unit tests with static boost libraries" OFF) diff --git a/include/BaseFilter.tpp b/include/BaseFilter.tpp index 9e955b2..a589c8f 100644 --- a/include/BaseFilter.tpp +++ b/include/BaseFilter.tpp @@ -60,9 +60,9 @@ void BaseFilter::getCoeffs(vectX_t& aCoeff, vectX_t& bCoeff) c template BaseFilter::BaseFilter(const vectX_t& aCoeff, const vectX_t& bCoeff, FilterType type) - : m_aCoeff(aCoeff) + : m_type(type) + , m_aCoeff(aCoeff) , m_bCoeff(bCoeff) - , m_type(type) , m_filteredData(aCoeff.size()) , m_rawData(bCoeff.size()) { diff --git a/include/Butterworth.tpp b/include/Butterworth.tpp index 3868bf5..5daa5d1 100644 --- a/include/Butterworth.tpp +++ b/include/Butterworth.tpp @@ -131,7 +131,7 @@ void Butterworth::computeDigitalRep(T fc) } scaleAmplitude(aCoeff, bCoeff); - setCoeffs(std::move(aCoeff), std::move(bCoeff)); + this->setCoeffs(std::move(aCoeff), std::move(bCoeff)); } template @@ -164,14 +164,14 @@ void Butterworth::computeBandDigitalRep(T fLower, T fUpper) else scaleAmplitude(aCoeff, bCoeff); - setCoeffs(std::move(aCoeff), std::move(bCoeff)); + this->setCoeffs(std::move(aCoeff), std::move(bCoeff)); } template std::complex Butterworth::generateAnalogPole(int k, T fpw1) { auto thetaK = [pi = pi, order = m_order](int k) -> T { - return (2 * k - 1) * pi / (2 * order); + return static_cast(2 * k - 1) * pi / static_cast(2 * order); }; std::complex analogPole(-std::sin(thetaK(k)), std::cos(thetaK(k))); @@ -189,7 +189,7 @@ template std::pair, std::complex> Butterworth::generateBandAnalogPole(int k, T fpw0, T bw) { auto thetaK = [pi = pi, order = m_order](int k) -> T { - return (2 * k - 1) * pi / (2 * order); + return static_cast(2 * k - 1) * pi / static_cast(2 * order); }; std::complex analogPole(-std::sin(thetaK(k)), std::cos(thetaK(k))); diff --git a/include/GenericFilter.h b/include/GenericFilter.h index 68cd064..d241a0f 100644 --- a/include/GenericFilter.h +++ b/include/GenericFilter.h @@ -33,6 +33,13 @@ namespace difi { template class GenericFilter : public BaseFilter> { + using Base = BaseFilter>; + using Base::m_isInitialized; + using Base::m_aCoeff; + using Base::m_bCoeff; + using Base::m_rawData; + using Base::m_filteredData; + public: /*! \brief Filter a new data. * @@ -54,12 +61,19 @@ public: protected: GenericFilter() = default; GenericFilter(const vectX_t& aCoeff, const vectX_t& bCoeff, FilterType type = FilterType::Backward) - : BaseFilter(aCoeff, bCoeff, type) + : Base(aCoeff, bCoeff, type) {} }; template class TVGenericFilter : public BaseFilter> { + using Base = BaseFilter>; + using Base::m_isInitialized; + using Base::m_aCoeff; + using Base::m_bCoeff; + using Base::m_rawData; + using Base::m_filteredData; + public: /*! \brief Filter a new data. * @@ -81,12 +95,12 @@ public: protected: TVGenericFilter() = default; TVGenericFilter(size_t differentialOrder, const vectX_t& aCoeff, const vectX_t& bCoeff, FilterType type = FilterType::Backward) - : BaseFilter() + : Base() , m_diffOrder(differentialOrder) { Expects(differentialOrder >= 1); - setCoeffs(aCoeff, bCoeff); - setType(type); + this->setCoeffs(aCoeff, bCoeff); + this->setType(type); } private: diff --git a/include/MovingAverage.h b/include/MovingAverage.h index bb142d3..417569c 100644 --- a/include/MovingAverage.h +++ b/include/MovingAverage.h @@ -50,16 +50,16 @@ public: MovingAverage(int windowSize, FilterType type = FilterType::Backward) { setWindowSize(windowSize); - setType(type); + this->setType(type); } /*! \brief Set the size of the moving average window. */ void setWindowSize(int windowSize) { Expects(windowSize > 0); - setCoeffs(vectX_t::Constant(1, T(1)), vectX_t::Constant(windowSize, T(1) / windowSize)); + this->setCoeffs(vectX_t::Constant(1, T(1)), vectX_t::Constant(windowSize, T(1) / static_cast(windowSize))); } /*! \brief Get the size of the moving average window. */ - int windowSize() const noexcept { return bOrder(); } + int windowSize() const noexcept { return this->bOrder(); } }; } // namespace difi diff --git a/include/differentiators.h b/include/differentiators.h index a0ae300..7768178 100644 --- a/include/differentiators.h +++ b/include/differentiators.h @@ -39,7 +39,7 @@ namespace details { // N: Number of points // Centered differentiators: http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/central-differences/ -template struct GetCDCoeffs { +template struct GetCDCoeffs { vectN_t operator()() const; }; template struct GetCDCoeffs { @@ -56,18 +56,18 @@ template struct GetCDCoeffs { }; // Low-noise Lanczos differentiators: http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/lanczos-low-noise-differentiators/ -template +template struct GetLNLCoeffs { vectN_t operator()() const { static_assert(N > 2 && N % 2 == 1, "'N' must be odd."); - constexpr const size_t M = (N - 1) / 2; - constexpr const size_t Den = M * (M + 1) * (2 * M + 1); + constexpr const int M = (N - 1) / 2; + constexpr const int Den = M * (M + 1) * (2 * M + 1); vectN_t v{}; v(M) = T(0); - for (size_t k = 0; k < M; ++k) { - v(k) = T(3) * (M - k) / static_cast(Den); + for (int k = 0; k < M; ++k) { + v(k) = T(3) * static_cast(M - k) / static_cast(Den); v(N - k - 1) = -v(k); } return v; @@ -75,7 +75,7 @@ struct GetLNLCoeffs { }; // Super Low-noise Lanczos differentiators: http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/lanczos-low-noise-differentiators/ -template struct GetSLNLCoeffs { +template struct GetSLNLCoeffs { vectN_t operator()() const; }; template struct GetSLNLCoeffs { @@ -89,19 +89,19 @@ template struct GetSLNLCoeffs { }; // Backward Noise-Robust differentiators; http://www.holoborodko.com/pavel/wp-content/uploads/OneSidedNoiseRobustDifferentiators.pdf -template +template struct GetFNRCoeffs { vectN_t operator()() const { static_assert(N >= 2, "N should be greater than 2"); - constexpr const size_t BinCoeff = N - 2; - constexpr const size_t M = N / 2; + constexpr const int BinCoeff = N - 2; + constexpr const int M = N / 2; vectN_t v{}; v(0) = T(1); v(M) = T(0); v(N - 1) = T(-1); - for (size_t i = 1; i < M; ++i) { + for (int i = 1; i < M; ++i) { v(i) = Binomial(BinCoeff, i) - Binomial(BinCoeff, i - 1); v(N - i - 1) = -v(i); } @@ -112,7 +112,7 @@ struct GetFNRCoeffs { }; // Backward Hybrid Noise-Robust differentiators; http://www.holoborodko.com/pavel/wp-content/uploads/OneSidedNoiseRobustDifferentiators.pdf -template struct GetFHNRCoeffs { +template struct GetFHNRCoeffs { vectN_t operator()() const; }; template struct GetFHNRCoeffs { @@ -143,25 +143,25 @@ template struct GetFHNRCoeffs { vectN_t operator()() const { return (vectN_t() << T(322), T(217), T(110), T(35), T(-42), T(-87), T(-134), T(-149), T(-166), T(-151), T(-138), T(-93), T(-50), T(28), T(98), T(203)).finished() / T(2856); } }; -template vectN_t GetBackwardISDCoeffs() +template vectN_t GetBackwardISDCoeffs() { vectN_t v{}; const vectN_t v0 = BackwardCoeffs{}(); for (Eigen::Index k = 0; k < N; ++k) v(k) = k * v0(k); - return v(k); + return v; } // Backward Noise-Robust differentiators for irregular space data -template struct GetFNRISDCoeffs { +template struct GetFNRISDCoeffs { vectN_t operator()() const { return GetBackwardISDCoeffs>(); } }; // Backward Hybrid Noise-Robust differentiators for irregular space data -template struct GetFHNRISDCoeffs { +template struct GetFHNRISDCoeffs { vectN_t operator()() const { return GetBackwardISDCoeffs>(); } }; // Centered Noise-Robust differentiators (tangency at 2nd order): http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/smooth-low-noise-differentiators/ -template +template struct GetCNR2Coeffs { vectN_t operator()() const { @@ -171,7 +171,7 @@ struct GetCNR2Coeffs { }; // Centered Noise-Robust differentiators (tangency at 4th order): http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/smooth-low-noise-differentiators/ -template struct GetCNR4Coeffs { +template struct GetCNR4Coeffs { vectN_t operator()() const; }; template struct GetCNR4Coeffs { @@ -185,9 +185,9 @@ template struct GetCNR4Coeffs { }; // Centered Noise-Robust differentiators for irregular space data: http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/smooth-low-noise-differentiators/ -template vectN_t GetCNRISDCoeffs() +template vectN_t GetCNRISDCoeffs() { - constexpr const size_t M = (N - 1) / 2; + constexpr const int M = (N - 1) / 2; vectN_t v{}; const vectN_t v0 = CNRCoeffs{}(); v(M) = 0; @@ -198,10 +198,10 @@ template vectN_t GetCNRISDCoeff return v; } -template struct GetCNR2ISDCoeffs { +template struct GetCNR2ISDCoeffs { vectN_t operator()() const { return GetCNRISDCoeffs>(); } }; -template struct GetCNR4ISDCoeffs { +template struct GetCNR4ISDCoeffs { vectN_t operator()() const { return GetCNRISDCoeffs>(); } }; @@ -210,7 +210,7 @@ template struct GetCNR4ISDCoeffs { */ template -constexpr T GetSONRBaseCoeff(size_t N, size_t M, size_t k) +constexpr T GetSONRBaseCoeff(int N, int M, int k) { if (k > M) return T(0); @@ -220,28 +220,28 @@ constexpr T GetSONRBaseCoeff(size_t N, size_t M, size_t k) return ((T(2) * N - T(10)) * GetSONRBaseCoeff(N, M, k + 1) - (N + T(2) * k + T(3)) * GetSONRBaseCoeff(N, M, k + 2)) / (N - T(2) * k - T(1)); } -template vectN_t GetSONRBaseCoeffs() +template vectN_t GetSONRBaseCoeffs() { static_assert(N >= 5 && N % 2 == 1, "N must be a odd number >= 5"); - constexpr const size_t M = (N - 1) / 2; + constexpr const int M = (N - 1) / 2; vectN_t s{}; - for (size_t k = 0; k < M + 1; ++k) + for (int k = 0; k < M + 1; ++k) s(k) = GetSONRBaseCoeff(N, M, k); return s; } // Second-Order Centered Noise-Robust differentiator: http://www.holoborodko.com/pavel/downloads/NoiseRobustSecondDerivative.pdf -template +template struct GetSOCNRCoeffs { vectN_t operator()() const { - constexpr const size_t M = (N - 1) / 2; - constexpr const T Den = pow(size_t(2), N - 3); + constexpr const int M = (N - 1) / 2; + constexpr const T Den = pow(2, N - 3); vectN_t v{}; vectN_t s = GetSONRBaseCoeffs(); v(M) = s(0); - for (size_t k = 1; k < M + 1; ++k) { + for (int k = 1; k < M + 1; ++k) { v(M + k) = s(k); v(M - k) = s(k); } @@ -251,25 +251,25 @@ struct GetSOCNRCoeffs { } }; // Second-Order Backward Noise-Robust differentiator: http://www.holoborodko.com/pavel/downloads/NoiseRobustSecondDerivative.pdf -template struct GetSOFNRCoeffs { +template struct GetSOFNRCoeffs { vectN_t operator()() const { return GetSOCNRCoeffs(); } }; // Coefficients are the same. // Second-Order Centered Noise-Robust Irregular Space Data differentiator: http://www.holoborodko.com/pavel/downloads/NoiseRobustSecondDerivative.pdf -template +template struct GetSOCNRISDCoeffs { vectN_t operator()() const { - constexpr const size_t M = (N - 1) / 2; - constexpr const T Den = pow(size_t(2), N - 3); + constexpr const int M = (N - 1) / 2; + constexpr const T Den = pow(2, N - 3); vectN_t v{}; const vectN_t s = GetSONRBaseCoeffs(); - const auto alpha = [&s](size_t k) -> T { return T(4) * k * k * s(k); }; + const auto alpha = [&s](int k) -> T { return T(4) * k * k * s(k); }; v(M) = T(0); - for (size_t k = 1; k < M + 1; ++k) { + for (int k = 1; k < M + 1; ++k) { auto alph = alpha(k); v(M) -= T(2) * alph; v(M + k) = alph; @@ -282,7 +282,7 @@ struct GetSOCNRISDCoeffs { }; // Second-Order Backward Noise-Robust Irregular Space Data differentiator: http://www.holoborodko.com/pavel/downloads/NoiseRobustSecondDerivative.pdf -template struct GetSOFNRISDCoeffs { +template struct GetSOFNRISDCoeffs { vectN_t operator()() const { return GetSOCNRISDCoeffs(); } }; // Same coefficients @@ -290,7 +290,7 @@ template struct GetSOFNRISDCoeffs { * Differentiator Generator */ -template +template class BackwardDifferentiator : public GenericFilter { public: BackwardDifferentiator() @@ -299,11 +299,11 @@ public: BackwardDifferentiator(T timestep) : GenericFilter(vectX_t::Constant(1, T(1)), CoeffGetter{}() / std::pow(timestep, Order)) {} - void setTimestep(T timestep) { setCoeffs(vectX_t::Constant(1, T(1)), CoeffGetter{}() / std::pow(timestep, Order)); } - T timestep() const noexcept { return std::pow(bCoeff()(0) / CoeffGetter{}()(0), T(1) / Order); } + void setTimestep(T timestep) { this->setCoeffs(vectX_t::Constant(1, T(1)), CoeffGetter{}() / std::pow(timestep, Order)); } + T timestep() const noexcept { return std::pow(this->bCoeff()(0) / CoeffGetter{}()(0), T(1) / Order); } }; -template +template class CenteredDifferentiator : public GenericFilter { public: CenteredDifferentiator() @@ -312,11 +312,11 @@ public: CenteredDifferentiator(T timestep) : GenericFilter(vectX_t::Constant(1, T(1)), CoeffGetter{}() / std::pow(timestep, Order)) {} - void setTimestep(T timestep) { setCoeffs(vectX_t::Constant(1, T(1)), CoeffGetter{}() / std::pow(timestep, Order)); } - T timestep() const noexcept { return std::pow(bCoeff()(0) / CoeffGetter{}()(0), T(1) / Order); } + void setTimestep(T timestep) { this->setCoeffs(vectX_t::Constant(1, T(1)), CoeffGetter{}() / std::pow(timestep, Order)); } + T timestep() const noexcept { return std::pow(this->bCoeff()(0) / CoeffGetter{}()(0), T(1) / Order); } }; -template +template class TVBackwardDifferentiator : public TVGenericFilter { static_assert(Order >= 1, "Order must be greater or equal to 1"); @@ -326,7 +326,7 @@ public: {} }; -template +template class TVCenteredDifferentiator : public TVGenericFilter { static_assert(Order >= 1, "Order must be greater or equal to 1"); @@ -339,30 +339,30 @@ public: } // namespace details // Backward differentiators -template using BackwardDiffNoiseRobust = details::BackwardDifferentiator>; -template using BackwardDiffHybridNoiseRobust = details::BackwardDifferentiator>; +template using BackwardDiffNoiseRobust = details::BackwardDifferentiator>; +template using BackwardDiffHybridNoiseRobust = details::BackwardDifferentiator>; // Time-Varying backward differentiators -template using TVBackwardDiffNoiseRobust = details::TVBackwardDifferentiator>; -template using TVBackwardDiffHybridNoiseRobust = details::TVBackwardDifferentiator>; +template using TVBackwardDiffNoiseRobust = details::TVBackwardDifferentiator>; +template using TVBackwardDiffHybridNoiseRobust = details::TVBackwardDifferentiator>; // Centered differentiators -template using CenteredDiffBasic = details::CenteredDifferentiator>; -template using CenteredDiffLowNoiseLanczos = details::CenteredDifferentiator>; -template using CenteredDiffSuperLowNoiseLanczos = details::CenteredDifferentiator>; -template using CenteredDiffNoiseRobust2 = details::CenteredDifferentiator>; -template using CenteredDiffNoiseRobust4 = details::CenteredDifferentiator>; +template using CenteredDiffBasic = details::CenteredDifferentiator>; +template using CenteredDiffLowNoiseLanczos = details::CenteredDifferentiator>; +template using CenteredDiffSuperLowNoiseLanczos = details::CenteredDifferentiator>; +template using CenteredDiffNoiseRobust2 = details::CenteredDifferentiator>; +template using CenteredDiffNoiseRobust4 = details::CenteredDifferentiator>; // Time-Varying centered differentiators -template using TVCenteredDiffNoiseRobust2 = details::TVCenteredDifferentiator>; -template using TVCenteredDiffNoiseRobust4 = details::TVCenteredDifferentiator>; +template using TVCenteredDiffNoiseRobust2 = details::TVCenteredDifferentiator>; +template using TVCenteredDiffNoiseRobust4 = details::TVCenteredDifferentiator>; // Second-order backward differentiators -template using BackwardDiffSecondOrder = details::BackwardDifferentiator>; +template using BackwardDiffSecondOrder = details::BackwardDifferentiator>; // Second-order Time-Varying backward differentiators -template using TVBackwardDiffSecondOrder = details::TVBackwardDifferentiator>; +template using TVBackwardDiffSecondOrder = details::TVBackwardDifferentiator>; // Second-order centered differentiators -template using CenteredDiffSecondOrder = details::CenteredDifferentiator>; +template using CenteredDiffSecondOrder = details::CenteredDifferentiator>; // Second-order Time-Varying centered differentiators -template using TVCenteredDiffSecondOrder = details::TVCenteredDifferentiator>; +template using TVCenteredDiffSecondOrder = details::TVCenteredDifferentiator>; } // namespace difi \ No newline at end of file diff --git a/include/difi b/include/difi index 2e7679a..8d64bcb 100644 --- a/include/difi +++ b/include/difi @@ -61,41 +61,41 @@ using BilinearTransformcf = BilinearTransform>; using BilinearTransformcd = BilinearTransform>; // 1st order centered differentiators -template using CenteredDiffBasicf = CenteredDiffBasic; -template using CenteredDiffBasicd = CenteredDiffBasic; -template using CenteredDiffLowNoiseLanczosf = CenteredDiffLowNoiseLanczos; -template using CenteredDiffLowNoiseLanczosd = CenteredDiffLowNoiseLanczos; -template using CenteredDiffSuperLowNoiseLanczosf = CenteredDiffSuperLowNoiseLanczos; -template using CenteredDiffSuperLowNoiseLanczosd = CenteredDiffSuperLowNoiseLanczos; -template using CenteredDiffNoiseRobust2f = CenteredDiffNoiseRobust2; -template using CenteredDiffNoiseRobust2d = CenteredDiffNoiseRobust2; -template using CenteredDiffNoiseRobust4f = CenteredDiffNoiseRobust4; -template using CenteredDiffNoiseRobust4d = CenteredDiffNoiseRobust4; -template using TVCenteredDiffNoiseRobust2f = TVCenteredDiffNoiseRobust2; -template using TVCenteredDiffNoiseRobust2d = TVCenteredDiffNoiseRobust2; -template using TVCenteredDiffNoiseRobust4f = TVCenteredDiffNoiseRobust4; -template using TVCenteredDiffNoiseRobust4d = TVCenteredDiffNoiseRobust4; +template using CenteredDiffBasicf = CenteredDiffBasic; +template using CenteredDiffBasicd = CenteredDiffBasic; +template using CenteredDiffLowNoiseLanczosf = CenteredDiffLowNoiseLanczos; +template using CenteredDiffLowNoiseLanczosd = CenteredDiffLowNoiseLanczos; +template using CenteredDiffSuperLowNoiseLanczosf = CenteredDiffSuperLowNoiseLanczos; +template using CenteredDiffSuperLowNoiseLanczosd = CenteredDiffSuperLowNoiseLanczos; +template using CenteredDiffNoiseRobust2f = CenteredDiffNoiseRobust2; +template using CenteredDiffNoiseRobust2d = CenteredDiffNoiseRobust2; +template using CenteredDiffNoiseRobust4f = CenteredDiffNoiseRobust4; +template using CenteredDiffNoiseRobust4d = CenteredDiffNoiseRobust4; +template using TVCenteredDiffNoiseRobust2f = TVCenteredDiffNoiseRobust2; +template using TVCenteredDiffNoiseRobust2d = TVCenteredDiffNoiseRobust2; +template using TVCenteredDiffNoiseRobust4f = TVCenteredDiffNoiseRobust4; +template using TVCenteredDiffNoiseRobust4d = TVCenteredDiffNoiseRobust4; // 2nd order centered differentiators -template using CenteredDiffSecondOrderf = CenteredDiffSecondOrder; -template using CenteredDiffSecondOrderd = CenteredDiffSecondOrder; -template using TVCenteredDiffSecondOrderf = TVCenteredDiffSecondOrder; -template using TVCenteredDiffSecondOrderd = TVCenteredDiffSecondOrder; +template using CenteredDiffSecondOrderf = CenteredDiffSecondOrder; +template using CenteredDiffSecondOrderd = CenteredDiffSecondOrder; +template using TVCenteredDiffSecondOrderf = TVCenteredDiffSecondOrder; +template using TVCenteredDiffSecondOrderd = TVCenteredDiffSecondOrder; // 1st order backward differentiators -template using BackwardDiffNoiseRobustf = BackwardDiffNoiseRobust; -template using BackwardDiffNoiseRobustd = BackwardDiffNoiseRobust; -template using BackwardDiffHybridNoiseRobustf = BackwardDiffHybridNoiseRobust; -template using BackwardDiffHybridNoiseRobustd = BackwardDiffHybridNoiseRobust; -template using TVBackwardDiffNoiseRobustf = TVBackwardDiffNoiseRobust; -template using TVBackwardDiffNoiseRobustd = TVBackwardDiffNoiseRobust; -template using TVBackwardDiffHybridNoiseRobustf = TVBackwardDiffHybridNoiseRobust; -template using TVBackwardDiffHybridNoiseRobustd = TVBackwardDiffHybridNoiseRobust; +template using BackwardDiffNoiseRobustf = BackwardDiffNoiseRobust; +template using BackwardDiffNoiseRobustd = BackwardDiffNoiseRobust; +template using BackwardDiffHybridNoiseRobustf = BackwardDiffHybridNoiseRobust; +template using BackwardDiffHybridNoiseRobustd = BackwardDiffHybridNoiseRobust; +template using TVBackwardDiffNoiseRobustf = TVBackwardDiffNoiseRobust; +template using TVBackwardDiffNoiseRobustd = TVBackwardDiffNoiseRobust; +template using TVBackwardDiffHybridNoiseRobustf = TVBackwardDiffHybridNoiseRobust; +template using TVBackwardDiffHybridNoiseRobustd = TVBackwardDiffHybridNoiseRobust; // 2nd order backward differentiators -template using BackwardDiffSecondOrderf = BackwardDiffSecondOrder; -template using BackwardDiffSecondOrderd = BackwardDiffSecondOrder; -template using TVBackwardDiffSecondOrderf = TVBackwardDiffSecondOrder; -template using TVBackwardDiffSecondOrderd = TVBackwardDiffSecondOrder; +template using BackwardDiffSecondOrderf = BackwardDiffSecondOrder; +template using BackwardDiffSecondOrderd = BackwardDiffSecondOrder; +template using TVBackwardDiffSecondOrderf = TVBackwardDiffSecondOrder; +template using TVBackwardDiffSecondOrderd = TVBackwardDiffSecondOrder; } // namespace difi \ No newline at end of file diff --git a/include/math_utils.h b/include/math_utils.h index 7b247e4..c44cbd2 100644 --- a/include/math_utils.h +++ b/include/math_utils.h @@ -32,7 +32,7 @@ namespace difi { // https://stackoverflow.com/questions/44718971/calculate-binomial-coffeficient-very-reliably template -constexpr T Binomial(size_t n, size_t k) +constexpr T Binomial(int n, int k) { if (k > n) return T(0); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bc8fd5d..77cffd1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -44,7 +44,7 @@ addTest(GenericFilterTests) addTest(polynome_functions_tests) addTest(DigitalFilterTests) addTest(MovingAverageFilterTests) -addTest(ButterWorthFilterTests) +addTest(ButterworthFilterTests) # Differentiators addTest(differentiator_tests) \ No newline at end of file diff --git a/tests/DigitalFilterTests.cpp b/tests/DigitalFilterTests.cpp index 6a2e714..3550861 100644 --- a/tests/DigitalFilterTests.cpp +++ b/tests/DigitalFilterTests.cpp @@ -45,7 +45,7 @@ DISABLE_CONVERSION_WARNING_END TEMPLATE_TEST_CASE_METHOD(System, "Digital filter", "[df]", float, double) { System s; - auto df = difi::DigitalFilter(aCoeff, bCoeff); + auto df = difi::DigitalFilter(s.aCoeff, s.bCoeff); test_coeffs(s.aCoeff, s.bCoeff, df, std::numeric_limits::epsilon() * 10); test_results(s.results, s.data, df, std::numeric_limits::epsilon() * 10); } diff --git a/tests/diffTesters.h b/tests/diffTesters.h index 125df6b..d6fd644 100644 --- a/tests/diffTesters.h +++ b/tests/diffTesters.h @@ -33,135 +33,245 @@ using namespace difi; -template -class DiffTester { - friend Derived; - static constexpr const size_t TSize = std::tuple_size_v; +namespace tester { -public: - DiffTester(const Tuple& filters, const vectX_t& f, const vectX_t& df) - : m_filters(filters) - , m_f(f) - , m_df(df) - {} +namespace details { - void run(const std::array& eps) { testRunner(eps); } - -private: - template - void test(Filter& filt, T eps) +template +struct set_time_step { + static void impl(Tuple& filters, double dt) { - static_cast(*this).testFilter(filt, eps); + std::get(filters).setTimestep(dt); + set_time_step::impl(filters, dt); } - - template - void testRunner(const std::array& eps) - { - test(std::get(m_filters), eps[Index]); - testRunner(eps); - } - - template <> - void testRunner<0>(const std::array& eps) { test(std::get<0>(m_filters), eps[0]); } - -private: - vectX_t m_f; - vectX_t m_df; - Tuple m_filters; }; -template -class TFDiffTester : public DiffTester> { - friend DiffTester>; - -public: - TFDiffTester(const Tuple& filters, const vectX_t& f, const vectX_t& df) - : DiffTester(filters, f, df) - {} - - void setFilterTimestep(T step) { setStep(step); } - -private: - template - void testFilter(Filter& filt, T eps) +template +struct set_time_step { + static void impl(Tuple& filters, double dt) { - for (int i = 0; i < 50; ++i) { - auto value = filt.stepFilter(m_f(i)); // First initialize, some steps - value = 2.; - } - - for (int i = 50; i < STEPS; ++i) { - auto value = filt.stepFilter(m_f(i)); - REQUIRE_SMALL(std::abs(value - m_df(i - filt.center())), eps); - } + std::get<0>(filters).setTimestep(dt); } - - template - void setStep(T step) - { - std::get(m_filters).setTimestep(step); - setStep(step); - } - - template <> - void setStep<0>(T step) { std::get<0>(m_filters).setTimestep(step); } }; -template -class TVDiffTester : public DiffTester> { - friend DiffTester>; - -public: - TVDiffTester(const Tuple& filters, const vectX_t& t, const vectX_t& f, const vectX_t& df) - : DiffTester(filters, f, df) - , m_time(t) - {} - -private: - template - void testFilter(Filter& filt, T eps) - { - for (int i = 0; i < 50; ++i) { - auto value = filt.stepFilter(m_time(i), m_f(i)); // First initialize, some steps - value = 2.; - } - - for (int i = 50; i < STEPS; ++i) { - auto value = filt.stepFilter(m_time(i), m_f(i)); - REQUIRE_SMALL(std::abs(value - m_df(i - filt.center())), eps); - } +// For TF tests +template +void test_filter(Filter& filt, const vectX_t& f, const vectX_t& df, double eps) +{ + for (int i = 0; i < 50; ++i) { + filt.stepFilter(f(i)); // First initialize, some steps + // auto value = filt.stepFilter(f(i)); // First initialize, some steps + // value = 2.; } -private: - vectX_t m_time; + for (int i = 50; i < f.size(); ++i) { + auto value = filt.stepFilter(f(i)); + REQUIRE_SMALL(std::abs(value - df(i - filt.center())), eps); + } +} + +// For TV tests +template +void test_filter(Filter& filt, const vectX_t& t, const vectX_t& f, const vectX_t& df, double eps) +{ + for (int i = 0; i < 50; ++i) { + filt.stepFilter(t(i), f(i)); // First initialize, some steps + // auto value = filt.stepFilter(f(i)); // First initialize, some steps + // value = 2.; + } + + for (int i = 50; i < f.size(); ++i) { + auto value = filt.stepFilter(t(i), f(i)); + REQUIRE_SMALL(std::abs(value - df(i - filt.center())), eps); + } +} + +template +struct run_test { + static constexpr size_t ind = Index; + + // For TF tests + static void impl(Tuple& filters, const vectX_t& f, const vectX_t& df, const vectX_t& eps) + { + test_filter(std::get(filters), f, df, eps(ind)); + run_test::impl(filters, f, df, eps); + } + + // For TV tests + static void impl(Tuple& filters, const vectX_t& t, const vectX_t& f, const vectX_t& df, const vectX_t& eps) + { + test_filter(std::get(filters), t, f, df, eps(ind)); + run_test::impl(filters, t, f, df, eps); + } }; -template +template +struct run_test { + // For TF tests + static void impl(Tuple& filters, const vectX_t& f, const vectX_t& df, const vectX_t& eps) + { + test_filter(std::get<0>(filters), f, df, eps(0)); + } + + // For TV tests + static void impl(Tuple& filters, const vectX_t& t, const vectX_t& f, const vectX_t& df, const vectX_t& eps) + { + test_filter(std::get<0>(filters), t, f, df, eps(0)); + } +}; + +} // namespace details + + +template +void set_time_steps(Tuple& filters, double dt) +{ + details::set_time_step::value - 1>::impl(filters, dt); +} + +template +void run_tests(Tuple& filters, const vectX_t& f, const vectX_t& df, const vectX_t& eps) +{ + details::run_test::value - 1>::impl(filters, f, df, eps); +} + +template +void run_tests(Tuple& filters, const vectX_t& t, const vectX_t& f, const vectX_t& df, const vectX_t& eps) +{ + details::run_test::value - 1>::impl(filters, t, f, df, eps); +} + +// template +// class DiffTester { +// friend Derived; +// static constexpr const size_t TSize = std::tuple_size_v; + +// public: +// DiffTester(const Tuple& filters, const vectX_t& f, const vectX_t& df) +// : m_filters(filters) +// , m_f(f) +// , m_df(df) +// {} + +// void run(const std::array& eps) { testRunner(eps); } + +// private: +// template +// void test(Filter& filt, T eps) +// { +// static_cast(*this).testFilter(filt, eps); +// } + +// template +// void testRunner(const std::array& eps) +// { +// test(std::get(m_filters), eps[Index]); +// testRunner(eps); +// } + +// template <> +// void testRunner<0>(const std::array& eps) { test(std::get<0>(m_filters), eps[0]); } + +// private: +// vectX_t m_f; +// vectX_t m_df; +// Tuple m_filters; +// }; + +// template +// class TFDiffTester : public DiffTester> { +// friend DiffTester>; + +// public: +// TFDiffTester(const Tuple& filters, const vectX_t& f, const vectX_t& df) +// : DiffTester(filters, f, df) +// {} + +// void setFilterTimestep(T step) { setStep(step); } + +// private: +// template +// void testFilter(Filter& filt, T eps) +// { +// for (int i = 0; i < 50; ++i) { +// auto value = filt.stepFilter(m_f(i)); // First initialize, some steps +// value = 2.; +// } + +// for (int i = 50; i < STEPS; ++i) { +// auto value = filt.stepFilter(m_f(i)); +// REQUIRE_SMALL(std::abs(value - m_df(i - filt.center())), eps); +// } +// } + +// template +// void setStep(T step) +// { +// std::get(m_filters).setTimestep(step); +// setStep(step); +// } + +// template <> +// void setStep<0>(T step) { std::get<0>(m_filters).setTimestep(step); } +// }; + +// template +// class TVDiffTester : public DiffTester> { +// friend DiffTester>; + +// public: +// TVDiffTester(const Tuple& filters, const vectX_t& t, const vectX_t& f, const vectX_t& df) +// : DiffTester(filters, f, df) +// , m_time(t) +// {} + +// private: +// template +// void testFilter(Filter& filt, T eps) +// { +// for (int i = 0; i < 50; ++i) { +// auto value = filt.stepFilter(m_time(i), m_f(i)); // First initialize, some steps +// value = 2.; +// } + +// for (int i = 50; i < STEPS; ++i) { +// auto value = filt.stepFilter(m_time(i), m_f(i)); +// REQUIRE_SMALL(std::abs(value - m_df(i - filt.center())), eps); +// } +// } + +// private: +// vectX_t m_time; +// }; + +template using central_list = std::tuple, CenteredDiffLowNoiseLanczosd, CenteredDiffSuperLowNoiseLanczosd, CenteredDiffNoiseRobust2d, CenteredDiffNoiseRobust4d>; -template -TFDiffTester> generateCTester(const vectX_t& f, const vectX_t& df) -{ - return { central_list{}, f, df }; -} +// template +// TFDiffTester> generateCTester(const vectX_t& f, const vectX_t& df) +// { +// return { central_list{}, f, df }; +// } -template -TFDiffTester>> generateC2OTester(const vectX_t& f, const vectX_t& df) -{ - return { std::tuple>{}, f, df }; -} +// template +// TFDiffTester>> generateC2OTester(const vectX_t& f, const vectX_t& df) +// { +// return { std::tuple>{}, f, df }; +// } -template +template using tv_central_list = std::tuple, TVCenteredDiffNoiseRobust4d>; -template -TVDiffTester> generateTVCTester(const vectX_t& t, const vectX_t& f, const vectX_t& df) -{ - return { tv_central_list{}, t, f, df }; -} +// template +// TVDiffTester> generateTVCTester(const vectX_t& t, const vectX_t& f, const vectX_t& df) +// { +// return { tv_central_list{}, t, f, df }; +// } -template -TVDiffTester>> generateTVC2OTester(const vectX_t& t, const vectX_t& f, const vectX_t& df) -{ - return { std::tuple>{}, t, f, df }; -} \ No newline at end of file +// template +// TVDiffTester>> generateTVC2OTester(const vectX_t& t, const vectX_t& f, const vectX_t& df) +// { +// return { std::tuple>{}, t, f, df }; +// } + +} // namespace tester \ No newline at end of file diff --git a/tests/differentiator_tests.cpp b/tests/differentiator_tests.cpp index b718715..501ce48 100644 --- a/tests/differentiator_tests.cpp +++ b/tests/differentiator_tests.cpp @@ -25,7 +25,6 @@ // of the authors and should not be interpreted as representing official policies, // either expressed or implied, of the FreeBSD Project. -#pragma once #include "catch_helper.h" #include "diffTesters.h" #include "noisy_function_generator.h" @@ -38,13 +37,13 @@ constexpr const int SIN_FREQUENCY = 1; template constexpr const std::array POLY_4 = { 2, -3, 3, 2, -5 }; template constexpr const std::array POLY_7 = { 10, -12, 5, 6, -9, -3, -2, 4 }; -template +template vectN_t generateLNLCoeffs() { static_assert(N > 2 && N % 2 == 1, "N must be odd"); vectN_t lnl; - const size_t M = (N - 1) / 2; - for (size_t i = 0; i < M + 1; ++i) { + const int M = (N - 1) / 2; + for (int i = 0; i < M + 1; ++i) { lnl(i) = static_cast(M - i); lnl(M + i) = -static_cast(i); } @@ -52,10 +51,10 @@ vectN_t generateLNLCoeffs() return lnl; } -template +template void checkCoeffs(const vectN_t& coeffs, const vectN_t& goodCoeffs) { - for (size_t i = 0; i < N; ++i) + for (int i = 0; i < N; ++i) REQUIRE_SMALL(std::abs(coeffs(i) - goodCoeffs(i)), std::numeric_limits::epsilon() * 5); } @@ -83,15 +82,17 @@ TEST_CASE("Sinus time-fixed central derivative", "[sin][central][1st]") { double dt = 0.001; auto sg = sinGenerator(STEPS, SIN_AMPLITUDE, SIN_FREQUENCY, dt); - auto ct7 = generateCTester<7>(std::get<0>(sg), std::get<1>(sg)); - auto ct9 = generateCTester<9>(std::get<0>(sg), std::get<1>(sg)); + auto ct7 = tester::central_list<7>{}; + auto ct9 = tester::central_list<9>{}; - ct7.setFilterTimestep(dt); - ct9.setFilterTimestep(dt); + tester::set_time_steps(ct7, dt); + tester::set_time_steps(ct9, dt); - std::array eps = { 1e-10, 1e-1, 1e-6, 1e-1, 1e-6 }; // Value checked with MATLAB - ct7.run(eps); - ct9.run(eps); + difi::vectX_t eps{5}; + eps << 1e-10, 1e-1, 1e-6, 1e-1, 1e-6; // Value checked with MATLAB + + tester::run_tests(ct7, std::get<0>(sg), std::get<1>(sg), eps); + tester::run_tests(ct9, std::get<0>(sg), std::get<1>(sg), eps); } TEST_CASE("Polynome time-fixed central derivative", "[poly][central][1st]") @@ -99,27 +100,31 @@ TEST_CASE("Polynome time-fixed central derivative", "[poly][central][1st]") double dt = 0.001; { auto pg = polyGenerator(STEPS, POLY_4, dt); - auto ct7 = generateCTester<7>(std::get<0>(pg), std::get<1>(pg)); - auto ct9 = generateCTester<9>(std::get<0>(pg), std::get<1>(pg)); + auto ct7 = tester::central_list<7>{}; + auto ct9 = tester::central_list<9>{}; - ct7.setFilterTimestep(dt); - ct9.setFilterTimestep(dt); + tester::set_time_steps(ct7, dt); + tester::set_time_steps(ct9, dt); - std::array eps = { 1e-12, 1e-4, 1e-12, 1e-4, 1e-12 }; // Value checked with MATLAB - ct7.run(eps); - ct9.run(eps); + difi::vectX_t eps{5}; + eps << 1e-12, 1e-4, 1e-12, 1e-4, 1e-12; // Value checked with MATLAB + + tester::run_tests(ct7, std::get<0>(pg), std::get<1>(pg), eps); + tester::run_tests(ct9, std::get<0>(pg), std::get<1>(pg), eps); } { auto pg = polyGenerator(STEPS, POLY_7, dt); - auto ct7 = generateCTester<7>(std::get<0>(pg), std::get<1>(pg)); - auto ct9 = generateCTester<9>(std::get<0>(pg), std::get<1>(pg)); + auto ct7 = tester::central_list<7>{}; + auto ct9 = tester::central_list<9>{}; - ct7.setFilterTimestep(dt); - ct9.setFilterTimestep(dt); + tester::set_time_steps(ct7, dt); + tester::set_time_steps(ct9, dt); - std::array eps = { 1e-11, 1e-3, 1e-9, 1e-4, 1e-9 }; // Value checked with MATLAB - ct7.run(eps); - ct9.run(eps); + difi::vectX_t eps{5}; + eps << 1e-11, 1e-3, 1e-9, 1e-4, 1e-9; // Value checked with MATLAB + + tester::run_tests(ct7, std::get<0>(pg), std::get<1>(pg), eps); + tester::run_tests(ct9, std::get<0>(pg), std::get<1>(pg), eps); } } @@ -127,30 +132,34 @@ TEST_CASE("2nd order sinus time-fixed center derivative", "[sin][center][2nd]") { double dt = 0.001; auto sg = sinGenerator(STEPS, SIN_AMPLITUDE, SIN_FREQUENCY, dt); - auto ct7 = generateC2OTester<7>(std::get<0>(sg), std::get<2>(sg)); - auto ct9 = generateC2OTester<9>(std::get<0>(sg), std::get<2>(sg)); - auto ct11 = generateC2OTester<11>(std::get<0>(sg), std::get<2>(sg)); + auto ct7 = std::tuple>{}; + auto ct9 = std::tuple>{}; + auto ct11 = std::tuple>{}; - ct7.setFilterTimestep(dt); - ct9.setFilterTimestep(dt); - ct11.setFilterTimestep(dt); + tester::set_time_steps(ct7, dt); + tester::set_time_steps(ct9, dt); + tester::set_time_steps(ct11, dt); - std::array eps = { 2e-1 }; // Value checked with MATLAB - ct7.run(eps); - ct9.run(eps); - ct11.run(eps); + difi::vectX_t eps{1}; + eps << 2e-1; + + tester::run_tests(ct7, std::get<0>(sg), std::get<2>(sg), eps); + tester::run_tests(ct9, std::get<0>(sg), std::get<2>(sg), eps); + tester::run_tests(ct11, std::get<0>(sg), std::get<2>(sg), eps); } TEST_CASE("Sinus time-varying central derivative", "[tv][sin][central][1st]") { double dt = 0.001; auto sg = tvSinGenerator(STEPS, SIN_AMPLITUDE, SIN_FREQUENCY, dt); - auto ct7 = generateTVCTester<7>(std::get<0>(sg), std::get<1>(sg), std::get<2>(sg)); - auto ct9 = generateTVCTester<9>(std::get<0>(sg), std::get<1>(sg), std::get<2>(sg)); + auto ct7 = tester::tv_central_list<7>{}; + auto ct9 = tester::tv_central_list<9>{}; - std::array eps = { 1., 1. }; - ct7.run(eps); - ct9.run(eps); + difi::vectX_t eps{2}; + eps << 1., 1.; + + tester::run_tests(ct7, std::get<0>(sg), std::get<1>(sg), std::get<2>(sg), eps); + tester::run_tests(ct9, std::get<0>(sg), std::get<1>(sg), std::get<2>(sg), eps); } TEST_CASE("Polynome time-varying central derivative", "[tv][poly][central][1st]") @@ -158,21 +167,25 @@ TEST_CASE("Polynome time-varying central derivative", "[tv][poly][central][1st]" double dt = 0.001; { auto pg = tvPolyGenerator(STEPS, POLY_4, dt); - auto ct7 = generateTVCTester<7>(std::get<0>(pg), std::get<1>(pg), std::get<2>(pg)); - auto ct9 = generateTVCTester<9>(std::get<0>(pg), std::get<1>(pg), std::get<2>(pg)); + auto ct7 = tester::tv_central_list<7>{}; + auto ct9 = tester::tv_central_list<9>{}; - std::array eps = { 1e-3, 1e-3 }; - ct7.run(eps); - ct9.run(eps); + difi::vectX_t eps{2}; + eps << 1e-3, 1e-3; + + tester::run_tests(ct7, std::get<0>(pg), std::get<1>(pg), std::get<2>(pg), eps); + tester::run_tests(ct9, std::get<0>(pg), std::get<1>(pg), std::get<2>(pg), eps); } { - auto pg = tvPolyGenerator(STEPS, POLY_4, dt); - auto ct7 = generateTVCTester<7>(std::get<0>(pg), std::get<1>(pg), std::get<2>(pg)); - auto ct9 = generateTVCTester<9>(std::get<0>(pg), std::get<1>(pg), std::get<2>(pg)); + auto pg = tvPolyGenerator(STEPS, POLY_7, dt); + auto ct7 = tester::tv_central_list<7>{}; + auto ct9 = tester::tv_central_list<9>{}; - std::array eps = { 1e-3, 1e-3 }; - ct7.run(eps); - ct9.run(eps); + difi::vectX_t eps{2}; + eps << 1e-2, 1e-2; + + tester::run_tests(ct7, std::get<0>(pg), std::get<1>(pg), std::get<2>(pg), eps); + tester::run_tests(ct9, std::get<0>(pg), std::get<1>(pg), std::get<2>(pg), eps); } } diff --git a/tests/noisy_function_generator.h b/tests/noisy_function_generator.h index 5861a6b..884cfc9 100644 --- a/tests/noisy_function_generator.h +++ b/tests/noisy_function_generator.h @@ -76,11 +76,11 @@ FunctionGenerator polyGenerator(int nrSteps, std::array coeffs, T dt) }; std::array dCoeffs; - for (Eigen::Index i = 1; i < N; ++i) + for (size_t i = 1; i < N; ++i) dCoeffs[i - 1] = i * coeffs[i]; std::array ddCoeffs; - for (Eigen::Index i = 1; i < N - 1; ++i) + for (size_t i = 1; i < N - 1; ++i) ddCoeffs[i - 1] = i * dCoeffs[i]; vectX_t f(nrSteps); @@ -159,11 +159,11 @@ TVFunctionGenerator tvPolyGenerator(int nrSteps, std::array coeffs, T m }; std::array dCoeffs; - for (Eigen::Index i = 1; i < N; ++i) + for (size_t i = 1; i < N; ++i) dCoeffs[i - 1] = i * coeffs[i]; std::array ddCoeffs; - for (Eigen::Index i = 1; i < N - 1; ++i) + for (size_t i = 1; i < N - 1; ++i) ddCoeffs[i - 1] = i * dCoeffs[i]; vectX_t t(nrSteps); diff --git a/tests/warning_macro.h b/tests/warning_macro.h index af87959..9c4549c 100644 --- a/tests/warning_macro.h +++ b/tests/warning_macro.h @@ -27,18 +27,17 @@ #pragma once -#ifdef _MSC_VER +#if defined(_MSC_VER) #define DCW_BEGIN \ __pragma(warning(push)) \ - __pragma(warning(disable : 4305)) + __pragma(warning(disable : 4305)) #define DCW_END __pragma(warning(pop)) -#else -#ifdef __GNUC__ || __clang__ +#elif defined(__GNUC__) || defined(__clang__) #define DCW_BEGIN \ - _Pragma("GCC warning push") \ - _Pragma("GCC diagnostic ignored \"-Wconversion\"") -#define DCW_END _Pragma("GCC warning pop") -#endif + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wfloat-conversion\"") \ + _Pragma("GCC diagnostic ignored \"-Wconversion\"") // Only needed for clang +#define DCW_END _Pragma("GCC diagnostic pop") #endif #ifdef DCW_BEGIN