diff --git a/include/GenericFilter.tpp b/include/GenericFilter.tpp index d843bca..457ef05 100644 --- a/include/GenericFilter.tpp +++ b/include/GenericFilter.tpp @@ -80,7 +80,7 @@ T TVGenericFilter::stepFilter(const T& data, const T& time) m_timeDiffs(i) = m_timeDiffs(i - 1); m_timeDiffs(0) = std::pow(time - m_timers(1), m_order); } else { - const Eigen::Index S = data.size() - 1; + const Eigen::Index S = m_rawData.size() - 1; const Eigen::Index M = S / 2; m_timeDiffs(M) = T(1); for (Eigen::Index i = 1; i < M; ++i) { diff --git a/include/differentiators.h b/include/differentiators.h index 6c75501..7f5fee4 100644 --- a/include/differentiators.h +++ b/include/differentiators.h @@ -40,15 +40,16 @@ namespace details { // N: Number of points // Central differentiators: http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/central-differences/ -template vectN_t GetCDCoeffs(); -template vectN_t GetCDCoeffs() { return vectN_t{ T(1), T(0), T(-1) } / T(2); } -template vectN_t GetCDCoeffs() { return vectN_t{ T(-1), T(8), T(0), T(8), T(1) } / T(12); } -template vectN_t GetCDCoeffs() { return vectN_t{ T(1), T(-9), T(45), T(0), T(-45), T(9), T(-1) } / T(60); } -template vectN_t GetCDCoeffs() { return vectN_t{ T(-3), T(32), T(-168), T(672), T(0), T(-672), T(168), T(-32), T(3) } / T(840); } +template struct GetCDCoeffs { vectN_t operator()() const; }; +template struct GetCDCoeffs { vectN_t operator()() const { return vectN_t{ T(1), T(0), T(-1) } / T(2); } }; +template struct GetCDCoeffs { vectN_t operator()() const { return vectN_t{ T(-1), T(8), T(0), T(8), T(1) } / T(12); } }; +template struct GetCDCoeffs { vectN_t operator()() const { return vectN_t{ T(1), T(-9), T(45), T(0), T(-45), T(9), T(-1) } / T(60); } }; +template struct GetCDCoeffs { vectN_t operator()() const { return vectN_t{ T(-3), T(32), T(-168), T(672), T(0), T(-672), T(168), T(-32), T(3) } / T(840); } }; // Low-noise Lanczos differentiators: http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/lanczos-low-noise-differentiators/ -template -vectN_t GetLNLCoeffs() +template +struct GetLNLCoeffs { +vectN_t operator()() const { static_assert(N % 2 == 1. "'N' must be odd."); constexpr T GetCoeff = [](size_t n, size_t k) { @@ -61,21 +62,22 @@ vectN_t GetLNLCoeffs() v(k) = GetCoeff(N, k); return v; } -template vectN_t GetLNLCoeffs() { return vectN_t{ T(2), T(1), T(0), T(-1), T(-2) } / T(10); } -template vectN_t GetLNLCoeffs() { return vectN_t{ T(3), T(2), T(1), T(0), T(-1), T(-2), T(-3) } / T(28); } -template vectN_t GetLNLCoeffs() { return vectN_t{ T(4), T(3), T(2), T(1), T(0), T(-1), T(-2), T(-3), T(-4) } / T(60); } -template vectN_t GetLNLCoeffs() { return vectN_t{ T(5), T(4), T(3), T(2), T(1), T(0), T(-1), T(-2), T(-3), T(-4), T(-5) } / T(110); } +}; +template struct GetLNLCoeffs { vectN_t operator()() const { return vectN_t{ T(2), T(1), T(0), T(-1), T(-2) } / T(10); } }; +template struct GetLNLCoeffs { vectN_t operator()() const { return vectN_t{ T(3), T(2), T(1), T(0), T(-1), T(-2), T(-3) } / T(28); } }; +template struct GetLNLCoeffs { vectN_t operator()() const { return vectN_t{ T(4), T(3), T(2), T(1), T(0), T(-1), T(-2), T(-3), T(-4) } / T(60); } }; +template struct GetLNLCoeffs { vectN_t operator()() const { return vectN_t{ T(5), T(4), T(3), T(2), T(1), T(0), T(-1), T(-2), T(-3), T(-4), T(-5) } / T(110); } }; // Super Low-noise Lanczos differentiators: http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/lanczos-low-noise-differentiators/ -template vectN_t GetSLNLCoeffs(); -template vectN_t GetSLNLCoeffs() { return vectN_t{ T(-22), T(67), T(58), T(0), T(-58), T(-67), T(22) } / T(252); } -template vectN_t GetSLNLCoeffs() { return vectN_t{ T(-86), T(142), T(193), T(126), T(0), T(-126), T(-193), T(-142), T(86) } / T(1188); } -template vectN_t GetSLNLCoeffs() { return vectN_t{ T(-300), T(294), T(532), T(503), T(296), T(0), T(-296), T(-503), T(-532), T(-294), T(300) } / T(5148); } +template struct GetSLNLCoeffs { vectN_t operator()() const; }; +template struct GetSLNLCoeffs { vectN_t operator()() const { return vectN_t{ T(-22), T(67), T(58), T(0), T(-58), T(-67), T(22) } / T(252); } }; +template struct GetSLNLCoeffs { vectN_t operator()() const { return vectN_t{ T(-86), T(142), T(193), T(126), T(0), T(-126), T(-193), T(-142), T(86) } / T(1188); } }; +template struct GetSLNLCoeffs { vectN_t operator()() const { return vectN_t{ T(-300), T(294), T(532), T(503), T(296), T(0), T(-296), T(-503), T(-532), T(-294), T(300) } / T(5148); } }; // Backward Noise-Robust differentiators; http://www.holoborodko.com/pavel/wp-content/uploads/OneSidedNoiseRobustDifferentiators.pdf -template -vectN_t GetFNRCoeffs() -{ +template +struct GetFNRCoeffs { +vectN_t operator()() const { constexpr const int BinCoeff = N - 2; vectN_t v{}; v(0) = T(1); @@ -84,65 +86,64 @@ vectN_t GetFNRCoeffs() v(i) = (Binomial(N, i) - Binomial(N, i - 1)) / std::pow(T(2), T(BinCoeff)); return v; -} -template vectN_t GetFNRCoeffs() { return vectN_t{ T(1), T(0), T(-1) } / T(2); } -template vectN_t GetFNRCoeffs() { return vectN_t{ T(1), T(1), T(-1), T(-1) } / T(4); } -template vectN_t GetFNRCoeffs() { return vectN_t{ T(1), T(2), T(0), T(-2), T(-1) } / T(8); } -template vectN_t GetFNRCoeffs() { return vectN_t{ T(1), T(3), T(2), T(-2), T(-3), T(-1) } / T(16); } -template vectN_t GetFNRCoeffs() { return vectN_t{ T(1), T(4), T(5), T(0), T(-5), T(-4), T(-1) } / T(32); } -template vectN_t GetFNRCoeffs() { return vectN_t{ T(1), T(5), T(9), T(5), T(-5), T(-9), T(-5), T(-1) } / T(64); } -template vectN_t GetFNRCoeffs() { return vectN_t{ T(1), T(6), T(14), T(14), T(0), T(-14), T(-14), T(-6), T(-1) } / T(128); } -template vectN_t GetFNRCoeffs() { return vectN_t{ T(1), T(7), T(20), T(28), T(14), T(-14), T(-28), T(-20), T(-7), T(-1) } / T(256); } -template vectN_t GetFNRCoeffs() { return vectN_t{ T(1), T(8), T(27), T(48), T(42), T(0), T(-42), T(-48), T(-27), T(-8), T(-1) } / T(512); } + } +}; +template struct GetFNRCoeffs { vectN_t operator()() const { return vectN_t{ T(1), T(0), T(-1) } / T(2); } }; +template struct GetFNRCoeffs { vectN_t operator()() const { return vectN_t{ T(1), T(1), T(-1), T(-1) } / T(4); } }; +template struct GetFNRCoeffs { vectN_t operator()() const { return vectN_t{ T(1), T(2), T(0), T(-2), T(-1) } / T(8); } }; +template struct GetFNRCoeffs { vectN_t operator()() const { return vectN_t{ T(1), T(3), T(2), T(-2), T(-3), T(-1) } / T(16); } }; +template struct GetFNRCoeffs { vectN_t operator()() const { return vectN_t{ T(1), T(4), T(5), T(0), T(-5), T(-4), T(-1) } / T(32); } }; +template struct GetFNRCoeffs { vectN_t operator()() const { return vectN_t{ T(1), T(5), T(9), T(5), T(-5), T(-9), T(-5), T(-1) } / T(64); } }; +template struct GetFNRCoeffs { vectN_t operator()() const { return vectN_t{ T(1), T(6), T(14), T(14), T(0), T(-14), T(-14), T(-6), T(-1) } / T(128); } }; +template struct GetFNRCoeffs { vectN_t operator()() const { return vectN_t{ T(1), T(7), T(20), T(28), T(14), T(-14), T(-28), T(-20), T(-7), T(-1) } / T(256); } }; +template struct GetFNRCoeffs { vectN_t operator()() const { return vectN_t{ T(1), T(8), T(27), T(48), T(42), T(0), T(-42), T(-48), T(-27), T(-8), T(-1) } / T(512); } }; // Backward Hybrid Noise-Robust differentiators; http://www.holoborodko.com/pavel/wp-content/uploads/OneSidedNoiseRobustDifferentiators.pdf -template vectN_t GetFHNRCoeffs(); -template vectN_t GetFHNRCoeffs() { return vectN_t{ T(2), T(-1), T(-2), T(1) } / T(2); } -template vectN_t GetFHNRCoeffs() { return vectN_t{ T(7), T(1), T(-10), T(-1), T(3) } / T(10); } -template vectN_t GetFHNRCoeffs() { return vectN_t{ T(16), T(1), T(-10), T(-10), T(-6), T(9) } / T(28); } -template vectN_t GetFHNRCoeffs() { return vectN_t{ T(12), T(5), T(-8), T(-6), T(-10), T(1), T(6) } / T(28); } -template vectN_t GetFHNRCoeffs() { return vectN_t{ T(22), T(7), T(-6), T(-11), T(-14), T(-9), T(-2), T(13) } / T(60); } -template vectN_t GetFHNRCoeffs() { return vectN_t{ T(52), T(29), T(-14), T(-17), T(-40), T(-23), T(-26), T(11), T(28) } / T(180); } -template vectN_t GetFHNRCoeffs() { return vectN_t{ T(56), T(26), T(-2), T(-17), T(-30), T(-30), T(-28), T(-13), T(4), T(34) } / T(220); } -template vectN_t GetFHNRCoeffs() { return vectN_t{ T(320), T(206), T(-8), T(-47), T(-186), T(-150), T(-214), T(-103), T(-92), T(94), T(180) } / T(1540); } +template struct GetFHNRCoeffs { vectN_t operator()() const; }; +template struct GetFHNRCoeffs { vectN_t operator()() const { return vectN_t{ T(2), T(-1), T(-2), T(1) } / T(2); } }; +template struct GetFHNRCoeffs { vectN_t operator()() const { return vectN_t{ T(7), T(1), T(-10), T(-1), T(3) } / T(10); } }; +template struct GetFHNRCoeffs { vectN_t operator()() const { return vectN_t{ T(16), T(1), T(-10), T(-10), T(-6), T(9) } / T(28); } }; +template struct GetFHNRCoeffs { vectN_t operator()() const { return vectN_t{ T(12), T(5), T(-8), T(-6), T(-10), T(1), T(6) } / T(28); } }; +template struct GetFHNRCoeffs { vectN_t operator()() const { return vectN_t{ T(22), T(7), T(-6), T(-11), T(-14), T(-9), T(-2), T(13) } / T(60); } }; +template struct GetFHNRCoeffs { vectN_t operator()() const { return vectN_t{ T(52), T(29), T(-14), T(-17), T(-40), T(-23), T(-26), T(11), T(28) } / T(180); } }; +template struct GetFHNRCoeffs { vectN_t operator()() const { return vectN_t{ T(56), T(26), T(-2), T(-17), T(-30), T(-30), T(-28), T(-13), T(4), T(34) } / T(220); } }; +template struct GetFHNRCoeffs { vectN_t operator()() const { return vectN_t{ T(320), T(206), T(-8), T(-47), T(-186), T(-150), T(-214), T(-103), T(-92), T(94), T(180) } / T(1540); } }; -template typename Foo> vectN_t GetForwardISDCoeffs() +template vectN_t GetForwardISDCoeffs() { vectN_t v{}; - const vectN_t v0 = Foo(); + const vectN_t v0 = ForwardCoeffs{}(); for (Eigen::Index k = 0; k < N; ++k) v(k) = k * v0(k); return v(k); } // Backward Noise-Robust differentiators for irregular space data -template vectN_t GetFNRISDCoeffs() { return GetForwardISDCoeffs(); } +template struct GetFNRISDCoeffs { vectN_t operator()() const { return GetForwardISDCoeffs>(); } }; // Backward Hybrid Noise-Robust differentiators for irregular space data -template vectN_t GetFHNRISDCoeffs() { return GetForwardISDCoeffs(); } +template struct GetFHNRISDCoeffs { vectN_t operator()() const { return GetForwardISDCoeffs>(); } }; // Centered Noise-Robust differentiators (tangency at 2nd order): http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/smooth-low-noise-differentiators/ template -vectN_t GetCNR2Coeffs() +struct GetCNR2Coeffs { +vectN_t operator()() const { static_assert(N % 2 == 1. "'N' must be odd."); - return GetFNRCoeffs(); // Same coefficients + return GetFNRCoeffs{}(); // Same coefficients } -template vectN_t GetCNR2Coeffs() { return vectN_t{ T(1), T(2), T(0), T(-2), T(-1) } / T(8); } -template vectN_t GetCNR2Coeffs() { return vectN_t{ T(1), T(4), T(5), T(0), T(-5), T(-4), T(-1) } / T(32); } -template vectN_t GetCNR2Coeffs() { return vectN_t{ T(1), T(6), T(14), T(14), T(0), T(-14), T(-14), T(-6), T(-1) } / T(128); } -template vectN_t GetCNR2Coeffs() { return vectN_t{ T(1), T(8), T(27), T(48), T(42), T(0), T(-42), T(-48), T(-27), T(-8), T(-1) } / T(512); } +}; // Centered Noise-Robust differentiators (tangency at 4th order): http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/smooth-low-noise-differentiators/ -template vectN_t GetCNR4Coeffs(); -template vectN_t GetCNR4Coeffs() { return vectN_t{ T(-5), T(12), T(39), T(0), T(-39), T(-12), T(5) } / T(96); } -template vectN_t GetCNR4Coeffs() { return vectN_t{ T(-2), T(-1), T(16), T(27) } / T(96); } -template vectN_t GetCNR4Coeffs() { return vectN_t{ T(-11), T(-32), T(39), T(256), T(322) } / T(1536); } +template struct GetCNR4Coeffs { vectN_t operator()() const; }; +template struct GetCNR4Coeffs { vectN_t operator()() const { return vectN_t{ T(-5), T(12), T(39), T(0), T(-39), T(-12), T(5) } / T(96); } }; +template struct GetCNR4Coeffs { vectN_t operator()() const { return vectN_t{ T(-2), T(-1), T(16), T(27) } / T(96); } }; +template struct GetCNR4Coeffs { vectN_t operator()() const { return vectN_t{ T(-11), T(-32), T(39), T(256), T(322) } / T(1536); } }; // Centered Noise-Robust differentiators for irregular space data: http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/smooth-low-noise-differentiators/ -template typename Foo> vectN_t GetCNRISDCoeffs() +template vectN_t GetCNRISDCoeffs() { constexpr const size_t M = (N - 1) / 2; vectN_t v{}; - const vectN_t v0 = Foo(); + const vectN_t v0 = CNRCoeffs{}(); v(M) = 0; for (Eigen::Index k = 1; k < M; ++k) { v(M - k) = T(2) * k * v0(M - k); @@ -150,8 +151,8 @@ template typename Foo> vectN_t vectN_t GetCNR2ISDCoeffs() { return GetCNRISDCoeffs(); } -template vectN_t GetCNR4ISDCoeffs() { return GetCNRISDCoeffs(); } +template struct GetCNR2ISDCoeffs { vectN_t operator()() const { return GetCNRISDCoeffs>(); } }; +template struct GetCNR4ISDCoeffs { vectN_t operator()() const { return GetCNRISDCoeffs>(); } }; /* * Second order differentiators @@ -181,7 +182,8 @@ template vectN_t GetSONRBaseCoeffs() // Second-Order Centered Noise-Robust differentiator: http://www.holoborodko.com/pavel/downloads/NoiseRobustSecondDerivative.pdf template -vectN_t GetSOCNRCoeffs() +struct GetSOCNRCoeffs { +vectN_t operator()() const { constexpr const size_t M = (N - 1) / 2; constexpr const T Den = pow(size_t(2), N - 3); @@ -196,14 +198,14 @@ vectN_t GetSOCNRCoeffs() v /= Den; return v; } - +}; // Second-Order Backward Noise-Robust differentiator: http://www.holoborodko.com/pavel/downloads/NoiseRobustSecondDerivative.pdf -template -vectN_t GetSOFNRCoeffs() { return GetSOCNRCoeffs(); } // Coefficients are the same. +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 -vectN_t GetSOCNRISDCoeffs() +struct GetSOCNRISDCoeffs { +vectN_t operator()() const { constexpr const size_t M = (N - 1) / 2; constexpr const T Den = pow(size_t(2), N - 3); @@ -222,90 +224,90 @@ vectN_t GetSOCNRISDCoeffs() v /= Den; return v; } +}; // Second-Order Backward Noise-Robust Irregular Space Data differentiator: http://www.holoborodko.com/pavel/downloads/NoiseRobustSecondDerivative.pdf -template -vectN_t GetSOFNRISDCoeffs() { return GetSOCNRISDCoeffs(); } // Same coefficients +template struct GetSOFNRISDCoeffs { vectN_t operator()() const { return GetSOCNRISDCoeffs(); } }; // Same coefficients /* * Differentiator Generator */ -template typename CoeffGetter> +template class ForwardDifferentiator : public GenericFilter { public: ForwardDifferentiator() - : GenericFilter({T(1)}, CoeffGetter()) + : GenericFilter({T(1)}, CoeffGetter{}()) {} ForwardDifferentiator(T timestep) - : GenericFilter({T(1)}, CoeffGetter() / std::pow(timestep, Order)) + : GenericFilter({T(1)}, CoeffGetter{}() / std::pow(timestep, Order)) {} - void setTimestep(T timestep) { setCoeffs({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) { setCoeffs({T(1)}, CoeffGetter{}() / std::pow(timestep, Order)); } + T timestep() const noexcept { return std::pow(bCoeff()(0) / CoeffGetter{}()(0), T(1) / Order); } }; -template typename CoeffGetter> +template class CentralDifferentiator : public GenericFilter { public: CentralDifferentiator() - : GenericFilter({T(1)}, CoeffGetter(), Type::Centered) + : GenericFilter({T(1)}, CoeffGetter{}(), Type::Centered) {} CentralDifferentiator(T timestep) - : GenericFilter({T(1)}, CoeffGetter() / std::pow(timestep, Order)) + : GenericFilter({T(1)}, CoeffGetter{}() / std::pow(timestep, Order)) {} - void setTimestep(T timestep) { setCoeffs({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) { setCoeffs({T(1)}, CoeffGetter{}() / std::pow(timestep, Order)); } + T timestep() const noexcept { return std::pow(bCoeff()(0) / CoeffGetter{}()(0), T(1) / Order); } }; -template typename CoeffGetter> +template class TVForwardDifferentiator : public TVGenericFilter { - static_assert(Order >= 1); + static_assert(Order >= 1, "Order must be greater or equal to 1"); public: TVForwardDifferentiator() - : TVGenericFilter(Order, {T(1)}, CoeffGetter()) + : TVGenericFilter(Order, {T(1)}, CoeffGetter{}()) {} }; -template typename CoeffGetter> +template class TVCentralDifferentiator : public TVGenericFilter { - static_assert(Order >= 1); + static_assert(Order >= 1, "Order must be greater or equal to 1"); public: TVCentralDifferentiator() - : TVGenericFilter(Order, {T(1)}, CoeffGetter(), Type::Centered) + : TVGenericFilter(Order, {T(1)}, CoeffGetter{}(), Type::Centered) {} }; } // namespace details // Backward differentiators -template using ForwardNoiseRobustDiff = ForwardDifferentiator; -template using ForwardHybridNoiseRobustDiff = ForwardDifferentiator; +template using ForwardNoiseRobustDiff = details::ForwardDifferentiator>; +template using ForwardHybridNoiseRobustDiff = details::ForwardDifferentiator>; // Time-Varying backward differentiators -template using TVForwardNoiseRobustDiff = TVForwardDifferentiator; -template using TVForwardHybridNoiseRobustDiff = TVForwardDifferentiator; +template using TVForwardNoiseRobustDiff = details::TVForwardDifferentiator>; +template using TVForwardHybridNoiseRobustDiff = details::TVForwardDifferentiator>; // Central differentiators -template using CentralDiff = CentralDifferentiator; -template using LowNoiseLanczosDiff = CentralDifferentiator; -template using SuperLowNoiseLanczosDiff = CentralDifferentiator; -template using CenteredNoiseRobust2Diff = CentralDifferentiator; -template using CenteredNoiseRobust4Diff = CentralDifferentiator; +template using CentralDiff = details::CentralDifferentiator>; +template using LowNoiseLanczosDiff = details::CentralDifferentiator>; +template using SuperLowNoiseLanczosDiff = details::CentralDifferentiator>; +template using CenteredNoiseRobust2Diff = details::CentralDifferentiator>; +template using CenteredNoiseRobust4Diff = details::CentralDifferentiator>; // Time-Varying central differentiators -template using TVCenteredNoiseRobust2Diff = TVCentralDifferentiator; -template using TVCenteredNoiseRobust4Diff = TVCentralDifferentiator; +template using TVCenteredNoiseRobust2Diff = details::TVCentralDifferentiator>; +template using TVCenteredNoiseRobust4Diff = details::TVCentralDifferentiator>; // Second-order backward differentiators -template using ForwardSecondOrderDiff = ForwardDifferentiator; +template using ForwardSecondOrderDiff = details::ForwardDifferentiator>; // Second-order Time-Varying backward differentiators -template using TVForwardSecondOrderDiff = TVForwardDifferentiator; +template using TVForwardSecondOrderDiff = details::TVForwardDifferentiator>; // Second-order central differentiators -template using CenteredSecondOrderDiff = CentralDifferentiator; +template using CenteredSecondOrderDiff = details::CentralDifferentiator>; // Second-order Time-Varying backward differentiators -template using TVCenteredSecondOrderDiff = TVCentralDifferentiator; +template using TVCenteredSecondOrderDiff = details::TVCentralDifferentiator>; } // namespace difi \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 149f103..22a2b04 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -33,7 +33,7 @@ macro(addTest testName) add_executable(${testName} ${testName}.cpp) target_link_libraries(${testName} PRIVATE Catch2::Catch2) target_compile_definitions(${testName} PRIVATE CATCH_CONFIG_MAIN) - target_include_directories(${testName} SYSTEM PUBLIC "${EIGEN3_INCLUDE_DIR}") + target_include_directories(${testName} SYSTEM PUBLIC "${EIGEN3_INCLUDE_DIR}") # Adding a project configuration file (for MSVC only) generate_msvc_dot_user_file(${testName}) @@ -44,4 +44,7 @@ addTest(GenericFilterTests) addTest(polynome_functions_tests) addTest(DigitalFilterTests) addTest(MovingAverageFilterTests) -addTest(ButterWorthFilterTests) \ No newline at end of file +addTest(ButterWorthFilterTests) + +# Differentiators +addTest(differentiator_tests) \ No newline at end of file diff --git a/tests/DigitalFilterTests.cpp b/tests/DigitalFilterTests.cpp index c960ee1..6a2e714 100644 --- a/tests/DigitalFilterTests.cpp +++ b/tests/DigitalFilterTests.cpp @@ -28,7 +28,7 @@ #include "difi" #include "test_functions.h" #include "warning_macro.h" -#include "catch2/catch.hpp" +#include DISABLE_CONVERSION_WARNING_BEGIN diff --git a/tests/differentiator_tests.cpp b/tests/differentiator_tests.cpp new file mode 100644 index 0000000..182327c --- /dev/null +++ b/tests/differentiator_tests.cpp @@ -0,0 +1,35 @@ +// Copyright (c) 2019, Vincent SAMY +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: + +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// The views and conclusions contained in the software and documentation are those +// of the authors and should not be interpreted as representing official policies, +// either expressed or implied, of the FreeBSD Project. + +#pragma once +#include "differentiators.h" +#include + +TEMPLATE_TEST_CASE("Sinus central derivative", "[sin][dentral]", float, double) +{ + +} diff --git a/tests/noisy_function_generator.h b/tests/noisy_function_generator.h new file mode 100644 index 0000000..adbb823 --- /dev/null +++ b/tests/noisy_function_generator.h @@ -0,0 +1,104 @@ +// Copyright (c) 2019, Vincent SAMY +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: + +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. + +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// The views and conclusions contained in the software and documentation are those +// of the authors and should not be interpreted as representing official policies, +// either expressed or implied, of the FreeBSD Project. + +#pragma once + +#include "typedefs.h" +#include +#include +#include + +template +using FunctionGenerator = std::tuple, difi::vectX_t, difi::vectX_t>; + +template +FunctionGenerator sinGenerator(int nrSteps, T omega, T dt = 0.001) +{ + using namespace difi; + + std::random_device rd{}; + std::mt19937 gen{rd()}; + + vectX_t truth; + vectX_t noisy; + vectX_t derivative; + + for (int i = 0; i < nrSteps; ++i) { + // truth + truth(i) = std::sin(2 * pi * omega * i * dt); + + // noisy + std::normal_distribution d{truth(i), T(0.01)}; + noisy(i) = truth(i) + d(gen); + + // derivative + derivative(i) = 2 * pi * omega * i * std::cos(2 * pi * omega * i * dt); + } + + return { truth, noisy, derivative }; +} + +template +FunctionGenerator polyGenerator(int nrSteps, difi::VectX_t coeffs, T dt = 0.001) +{ + using namespace difi; + Expects(coeffs.size() >=2); + std::random_device rd{}; + std::mt19937 gen{rd()}; + + auto computePoly = [](const VectX_t& coeffs, T time) { + auto recursiveComputation = [time, &coeffs](int i, T result) { + if (i > 0) + return recursiveComputation(i - 1, time * result + coeffs(i - 1)); + else + return result; + }; + + return recursiveComputation(coeffs.size(), 0); + }; + + vectX_t derivativeCoeffs(coeffs.size() - 1); + for (Eigen::Index i = 1; i < coeffs.size(); ++i) + derivativeCoeffs(i - 1) = i * coeffs.tail(i); + + vectX_t truth; + vectX_t noisy; + vectX_t derivative; + for (int i = 0; i < nrSteps; ++i) { + // truth + truth(i) = computePoly(coeffs, i * dt); + + // noisy + std::normal_distribution d{truth(i), T(0.01)}; + noisy(i) = truth(i) + d(gen); + + // derivative + derivative(i) = computePoly(derivativeCoeffs, i * dt); + } + + return { truth, noisy, derivative }; +} \ No newline at end of file