Pass compilation

topic/diffentiators
vincent samy 2019-11-01 18:04:02 +09:00
rodzic d08dfd9971
commit 544bead65c
6 zmienionych plików z 241 dodań i 97 usunięć

Wyświetl plik

@ -80,7 +80,7 @@ T TVGenericFilter<T>::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) {

Wyświetl plik

@ -40,15 +40,16 @@ namespace details {
// N: Number of points
// Central differentiators: http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/central-differences/
template <typename T, size_t N> vectN_t<T, N> GetCDCoeffs();
template <typename T> vectN_t<T, 3> GetCDCoeffs() { return vectN_t<T, 3>{ T(1), T(0), T(-1) } / T(2); }
template <typename T> vectN_t<T, 5> GetCDCoeffs() { return vectN_t<T, 5>{ T(-1), T(8), T(0), T(8), T(1) } / T(12); }
template <typename T> vectN_t<T, 7> GetCDCoeffs() { return vectN_t<T, 7>{ T(1), T(-9), T(45), T(0), T(-45), T(9), T(-1) } / T(60); }
template <typename T> vectN_t<T, 9> GetCDCoeffs() { return vectN_t<T, 9>{ T(-3), T(32), T(-168), T(672), T(0), T(-672), T(168), T(-32), T(3) } / T(840); }
template <typename T, size_t N> struct GetCDCoeffs { vectN_t<T, N> operator()() const; };
template <typename T> struct GetCDCoeffs<T, 3> { vectN_t<T, 3> operator()() const { return vectN_t<T, 3>{ T(1), T(0), T(-1) } / T(2); } };
template <typename T> struct GetCDCoeffs<T, 5> { vectN_t<T, 5> operator()() const { return vectN_t<T, 5>{ T(-1), T(8), T(0), T(8), T(1) } / T(12); } };
template <typename T> struct GetCDCoeffs<T, 7> { vectN_t<T, 7> operator()() const { return vectN_t<T, 7>{ T(1), T(-9), T(45), T(0), T(-45), T(9), T(-1) } / T(60); } };
template <typename T> struct GetCDCoeffs<T, 9> { vectN_t<T, 9> operator()() const { return vectN_t<T, 9>{ 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 <typename T, size_t N>
vectN_t<T, N> GetLNLCoeffs()
template <typename T, size_t N>
struct GetLNLCoeffs {
vectN_t<T, N> 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<T, N> GetLNLCoeffs()
v(k) = GetCoeff(N, k);
return v;
}
template <typename T> vectN_t<T, 5> GetLNLCoeffs() { return vectN_t<T, 5>{ T(2), T(1), T(0), T(-1), T(-2) } / T(10); }
template <typename T> vectN_t<T, 7> GetLNLCoeffs() { return vectN_t<T, 7>{ T(3), T(2), T(1), T(0), T(-1), T(-2), T(-3) } / T(28); }
template <typename T> vectN_t<T, 9> GetLNLCoeffs() { return vectN_t<T, 9>{ T(4), T(3), T(2), T(1), T(0), T(-1), T(-2), T(-3), T(-4) } / T(60); }
template <typename T> vectN_t<T, 11> GetLNLCoeffs() { return vectN_t<T, 11>{ 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 <typename T> struct GetLNLCoeffs<T, 5> { vectN_t<T, 5> operator()() const { return vectN_t<T, 5>{ T(2), T(1), T(0), T(-1), T(-2) } / T(10); } };
template <typename T> struct GetLNLCoeffs<T, 7> { vectN_t<T, 7> operator()() const { return vectN_t<T, 7>{ T(3), T(2), T(1), T(0), T(-1), T(-2), T(-3) } / T(28); } };
template <typename T> struct GetLNLCoeffs<T, 9> { vectN_t<T, 9> operator()() const { return vectN_t<T, 9>{ T(4), T(3), T(2), T(1), T(0), T(-1), T(-2), T(-3), T(-4) } / T(60); } };
template <typename T> struct GetLNLCoeffs<T, 11> { vectN_t<T, 11> operator()() const { return vectN_t<T, 11>{ 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 <typename T, size_t N> vectN_t<T, N> GetSLNLCoeffs();
template <typename T> vectN_t<T, 7> GetSLNLCoeffs() { return vectN_t<T, 7>{ T(-22), T(67), T(58), T(0), T(-58), T(-67), T(22) } / T(252); }
template <typename T> vectN_t<T, 9> GetSLNLCoeffs() { return vectN_t<T, 9>{ T(-86), T(142), T(193), T(126), T(0), T(-126), T(-193), T(-142), T(86) } / T(1188); }
template <typename T> vectN_t<T, 11> GetSLNLCoeffs() { return vectN_t<T, 11>{ 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 <typename T, size_t N> struct GetSLNLCoeffs { vectN_t<T, N> operator()() const; };
template <typename T> struct GetSLNLCoeffs<T, 7> { vectN_t<T, 7> operator()() const { return vectN_t<T, 7>{ T(-22), T(67), T(58), T(0), T(-58), T(-67), T(22) } / T(252); } };
template <typename T> struct GetSLNLCoeffs<T, 9> { vectN_t<T, 9> operator()() const { return vectN_t<T, 9>{ T(-86), T(142), T(193), T(126), T(0), T(-126), T(-193), T(-142), T(86) } / T(1188); } };
template <typename T> struct GetSLNLCoeffs<T, 11> { vectN_t<T, 11> operator()() const { return vectN_t<T, 11>{ 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 <typename T, size_t N>
vectN_t<T, N> GetFNRCoeffs()
{
template <typename T, size_t N>
struct GetFNRCoeffs {
vectN_t<T, N> operator()() const {
constexpr const int BinCoeff = N - 2;
vectN_t<T, N> v{};
v(0) = T(1);
@ -84,65 +86,64 @@ vectN_t<T, N> GetFNRCoeffs()
v(i) = (Binomial<T>(N, i) - Binomial<T>(N, i - 1)) / std::pow(T(2), T(BinCoeff));
return v;
}
template <typename T> vectN_t<T, 3> GetFNRCoeffs() { return vectN_t<T, 3>{ T(1), T(0), T(-1) } / T(2); }
template <typename T> vectN_t<T, 4> GetFNRCoeffs() { return vectN_t<T, 4>{ T(1), T(1), T(-1), T(-1) } / T(4); }
template <typename T> vectN_t<T, 5> GetFNRCoeffs() { return vectN_t<T, 5>{ T(1), T(2), T(0), T(-2), T(-1) } / T(8); }
template <typename T> vectN_t<T, 6> GetFNRCoeffs() { return vectN_t<T, 6>{ T(1), T(3), T(2), T(-2), T(-3), T(-1) } / T(16); }
template <typename T> vectN_t<T, 7> GetFNRCoeffs() { return vectN_t<T, 7>{ T(1), T(4), T(5), T(0), T(-5), T(-4), T(-1) } / T(32); }
template <typename T> vectN_t<T, 8> GetFNRCoeffs() { return vectN_t<T, 8>{ T(1), T(5), T(9), T(5), T(-5), T(-9), T(-5), T(-1) } / T(64); }
template <typename T> vectN_t<T, 9> GetFNRCoeffs() { return vectN_t<T, 9>{ T(1), T(6), T(14), T(14), T(0), T(-14), T(-14), T(-6), T(-1) } / T(128); }
template <typename T> vectN_t<T, 10> GetFNRCoeffs() { return vectN_t<T, 10>{ T(1), T(7), T(20), T(28), T(14), T(-14), T(-28), T(-20), T(-7), T(-1) } / T(256); }
template <typename T> vectN_t<T, 11> GetFNRCoeffs() { return vectN_t<T, 11>{ 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 <typename T> struct GetFNRCoeffs<T, 3> { vectN_t<T, 3> operator()() const { return vectN_t<T, 3>{ T(1), T(0), T(-1) } / T(2); } };
template <typename T> struct GetFNRCoeffs<T, 4> { vectN_t<T, 4> operator()() const { return vectN_t<T, 4>{ T(1), T(1), T(-1), T(-1) } / T(4); } };
template <typename T> struct GetFNRCoeffs<T, 5> { vectN_t<T, 5> operator()() const { return vectN_t<T, 5>{ T(1), T(2), T(0), T(-2), T(-1) } / T(8); } };
template <typename T> struct GetFNRCoeffs<T, 6> { vectN_t<T, 6> operator()() const { return vectN_t<T, 6>{ T(1), T(3), T(2), T(-2), T(-3), T(-1) } / T(16); } };
template <typename T> struct GetFNRCoeffs<T, 7> { vectN_t<T, 7> operator()() const { return vectN_t<T, 7>{ T(1), T(4), T(5), T(0), T(-5), T(-4), T(-1) } / T(32); } };
template <typename T> struct GetFNRCoeffs<T, 8> { vectN_t<T, 8> operator()() const { return vectN_t<T, 8>{ T(1), T(5), T(9), T(5), T(-5), T(-9), T(-5), T(-1) } / T(64); } };
template <typename T> struct GetFNRCoeffs<T, 9> { vectN_t<T, 9> operator()() const { return vectN_t<T, 9>{ T(1), T(6), T(14), T(14), T(0), T(-14), T(-14), T(-6), T(-1) } / T(128); } };
template <typename T> struct GetFNRCoeffs<T, 10> { vectN_t<T, 10> operator()() const { return vectN_t<T, 10>{ T(1), T(7), T(20), T(28), T(14), T(-14), T(-28), T(-20), T(-7), T(-1) } / T(256); } };
template <typename T> struct GetFNRCoeffs<T, 11> { vectN_t<T, 11> operator()() const { return vectN_t<T, 11>{ 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 <typename T, size_t N> vectN_t<T, N> GetFHNRCoeffs();
template <typename T> vectN_t<T, 4> GetFHNRCoeffs() { return vectN_t<T, 4>{ T(2), T(-1), T(-2), T(1) } / T(2); }
template <typename T> vectN_t<T, 5> GetFHNRCoeffs() { return vectN_t<T, 5>{ T(7), T(1), T(-10), T(-1), T(3) } / T(10); }
template <typename T> vectN_t<T, 5> GetFHNRCoeffs() { return vectN_t<T, 5>{ T(16), T(1), T(-10), T(-10), T(-6), T(9) } / T(28); }
template <typename T> vectN_t<T, 6> GetFHNRCoeffs() { return vectN_t<T, 6>{ T(12), T(5), T(-8), T(-6), T(-10), T(1), T(6) } / T(28); }
template <typename T> vectN_t<T, 7> GetFHNRCoeffs() { return vectN_t<T, 7>{ T(22), T(7), T(-6), T(-11), T(-14), T(-9), T(-2), T(13) } / T(60); }
template <typename T> vectN_t<T, 8> GetFHNRCoeffs() { return vectN_t<T, 8>{ T(52), T(29), T(-14), T(-17), T(-40), T(-23), T(-26), T(11), T(28) } / T(180); }
template <typename T> vectN_t<T, 9> GetFHNRCoeffs() { return vectN_t<T, 9>{ T(56), T(26), T(-2), T(-17), T(-30), T(-30), T(-28), T(-13), T(4), T(34) } / T(220); }
template <typename T> vectN_t<T, 10> GetFHNRCoeffs() { return vectN_t<T, 10>{ 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 T, size_t N> struct GetFHNRCoeffs { vectN_t<T, N> operator()() const; };
template <typename T> struct GetFHNRCoeffs<T, 4> { vectN_t<T, 4> operator()() const { return vectN_t<T, 4>{ T(2), T(-1), T(-2), T(1) } / T(2); } };
template <typename T> struct GetFHNRCoeffs<T, 5> { vectN_t<T, 5> operator()() const { return vectN_t<T, 5>{ T(7), T(1), T(-10), T(-1), T(3) } / T(10); } };
template <typename T> struct GetFHNRCoeffs<T, 6> { vectN_t<T, 6> operator()() const { return vectN_t<T, 6>{ T(16), T(1), T(-10), T(-10), T(-6), T(9) } / T(28); } };
template <typename T> struct GetFHNRCoeffs<T, 7> { vectN_t<T, 7> operator()() const { return vectN_t<T, 7>{ T(12), T(5), T(-8), T(-6), T(-10), T(1), T(6) } / T(28); } };
template <typename T> struct GetFHNRCoeffs<T, 8> { vectN_t<T, 8> operator()() const { return vectN_t<T, 8>{ T(22), T(7), T(-6), T(-11), T(-14), T(-9), T(-2), T(13) } / T(60); } };
template <typename T> struct GetFHNRCoeffs<T, 9> { vectN_t<T, 9> operator()() const { return vectN_t<T, 9>{ T(52), T(29), T(-14), T(-17), T(-40), T(-23), T(-26), T(11), T(28) } / T(180); } };
template <typename T> struct GetFHNRCoeffs<T, 10> { vectN_t<T, 10> operator()() const { return vectN_t<T, 10>{ T(56), T(26), T(-2), T(-17), T(-30), T(-30), T(-28), T(-13), T(4), T(34) } / T(220); } };
template <typename T> struct GetFHNRCoeffs<T, 11> { vectN_t<T, 11> operator()() const { return vectN_t<T, 11>{ 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 T, size_t N, template<class, class> typename Foo> vectN_t<T, N> GetForwardISDCoeffs()
template <typename T, size_t N, typename ForwardCoeffs> vectN_t<T, N> GetForwardISDCoeffs()
{
vectN_t<T, N> v{};
const vectN_t<T, N> v0 = Foo<T, NCoeffs>();
const vectN_t<T, N> 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 <typename T, size_t N> vectN_t<T, N> GetFNRISDCoeffs() { return GetForwardISDCoeffs<T, N, GetFNRCoeffs>(); }
template <typename T, size_t N> struct GetFNRISDCoeffs { vectN_t<T, N> operator()() const { return GetForwardISDCoeffs<T, N, GetFNRCoeffs<T, N>>(); } };
// Backward Hybrid Noise-Robust differentiators for irregular space data
template <typename T, size_t N> vectN_t<T, N> GetFHNRISDCoeffs() { return GetForwardISDCoeffs<T, N, GetFHNRCoeffs>(); }
template <typename T, size_t N> struct GetFHNRISDCoeffs { vectN_t<T, N> operator()() const { return GetForwardISDCoeffs<T, N, GetFHNRCoeffs<T, N>>(); } };
// Centered Noise-Robust differentiators (tangency at 2nd order): http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/smooth-low-noise-differentiators/
template <typename T, size_t N>
vectN_t<T, N> GetCNR2Coeffs()
struct GetCNR2Coeffs {
vectN_t<T, N> operator()() const
{
static_assert(N % 2 == 1. "'N' must be odd.");
return GetFNRCoeffs<T, N>(); // Same coefficients
return GetFNRCoeffs<T, N>{}(); // Same coefficients
}
template <typename T> vectN_t<T, 5> GetCNR2Coeffs() { return vectN_t<T, 5>{ T(1), T(2), T(0), T(-2), T(-1) } / T(8); }
template <typename T> vectN_t<T, 7> GetCNR2Coeffs() { return vectN_t<T, 7>{ T(1), T(4), T(5), T(0), T(-5), T(-4), T(-1) } / T(32); }
template <typename T> vectN_t<T, 9> GetCNR2Coeffs() { return vectN_t<T, 9>{ T(1), T(6), T(14), T(14), T(0), T(-14), T(-14), T(-6), T(-1) } / T(128); }
template <typename T> vectN_t<T, 11> GetCNR2Coeffs() { return vectN_t<T, 11>{ 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 <typename T, size_t N> vectN_t<T, N> GetCNR4Coeffs();
template <typename T> vectN_t<T, 3> GetCNR4Coeffs() { return vectN_t<T, 3>{ T(-5), T(12), T(39), T(0), T(-39), T(-12), T(5) } / T(96); }
template <typename T> vectN_t<T, 4> GetCNR4Coeffs() { return vectN_t<T, 4>{ T(-2), T(-1), T(16), T(27) } / T(96); }
template <typename T> vectN_t<T, 5> GetCNR4Coeffs() { return vectN_t<T, 5>{ T(-11), T(-32), T(39), T(256), T(322) } / T(1536); }
template <typename T, size_t N> struct GetCNR4Coeffs { vectN_t<T, N> operator()() const; };
template <typename T> struct GetCNR4Coeffs<T, 3> { vectN_t<T, 3> operator()() const { return vectN_t<T, 3>{ T(-5), T(12), T(39), T(0), T(-39), T(-12), T(5) } / T(96); } };
template <typename T> struct GetCNR4Coeffs<T, 4> { vectN_t<T, 4> operator()() const { return vectN_t<T, 4>{ T(-2), T(-1), T(16), T(27) } / T(96); } };
template <typename T> struct GetCNR4Coeffs<T, 5> { vectN_t<T, 5> operator()() const { return vectN_t<T, 5>{ 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 T, size_t N, template<class, class> typename Foo> vectN_t<T, N> GetCNRISDCoeffs()
template <typename T, size_t N, typename CNRCoeffs> vectN_t<T, N> GetCNRISDCoeffs()
{
constexpr const size_t M = (N - 1) / 2;
vectN_t<T, N> v{};
const vectN_t<T, N> v0 = Foo<T, NCoeffs>();
const vectN_t<T, N> 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 T, size_t N, template<class, class> typename Foo> vectN_t<T,
}
return v(k);
}
template <typename T, size_t N> vectN_t<T, N> GetCNR2ISDCoeffs() { return GetCNRISDCoeffs<T, N, GetCNR2Coeffs>(); }
template <typename T, size_t N> vectN_t<T, N> GetCNR4ISDCoeffs() { return GetCNRISDCoeffs<T, N, GetCNR4Coeffs>(); }
template <typename T, size_t N> struct GetCNR2ISDCoeffs { vectN_t<T, N> operator()() const { return GetCNRISDCoeffs<T, N, GetCNR2Coeffs<T, N>>(); } };
template <typename T, size_t N> struct GetCNR4ISDCoeffs { vectN_t<T, N> operator()() const { return GetCNRISDCoeffs<T, N, GetCNR4Coeffs<T, N>>(); } };
/*
* Second order differentiators
@ -181,7 +182,8 @@ template <typename T, size_t N> vectN_t<T, N> GetSONRBaseCoeffs()
// Second-Order Centered Noise-Robust differentiator: http://www.holoborodko.com/pavel/downloads/NoiseRobustSecondDerivative.pdf
template <typename T, size_t N>
vectN_t<T, N> GetSOCNRCoeffs()
struct GetSOCNRCoeffs {
vectN_t<T, N> 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<T, N> GetSOCNRCoeffs()
v /= Den;
return v;
}
};
// Second-Order Backward Noise-Robust differentiator: http://www.holoborodko.com/pavel/downloads/NoiseRobustSecondDerivative.pdf
template <typename T, size_t N>
vectN_t<T, N> GetSOFNRCoeffs() { return GetSOCNRCoeffs<T, N>(); } // Coefficients are the same.
template <typename T, size_t N> struct GetSOFNRCoeffs { vectN_t<T, N> operator()() const { return GetSOCNRCoeffs<T, N>(); } }; // Coefficients are the same.
// Second-Order Centered Noise-Robust Irregular Space Data differentiator: http://www.holoborodko.com/pavel/downloads/NoiseRobustSecondDerivative.pdf
template <typename T, size_t N>
vectN_t<T, N> GetSOCNRISDCoeffs()
struct GetSOCNRISDCoeffs {
vectN_t<T, N> 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<T, N> GetSOCNRISDCoeffs()
v /= Den;
return v;
}
};
// Second-Order Backward Noise-Robust Irregular Space Data differentiator: http://www.holoborodko.com/pavel/downloads/NoiseRobustSecondDerivative.pdf
template <typename T, size_t N>
vectN_t<T, N> GetSOFNRISDCoeffs() { return GetSOCNRISDCoeffs<T, N>(); } // Same coefficients
template <typename T, size_t N> struct GetSOFNRISDCoeffs { vectN_t<T, N> operator()() const { return GetSOCNRISDCoeffs<T, N>(); } }; // Same coefficients
/*
* Differentiator Generator
*/
template <typename T, size_t N, int Order, template<class, class> typename CoeffGetter>
template <typename T, size_t N, int Order, typename CoeffGetter>
class ForwardDifferentiator : public GenericFilter<T> {
public:
ForwardDifferentiator()
: GenericFilter<T>({T(1)}, CoeffGetter<T, N>())
: GenericFilter<T>({T(1)}, CoeffGetter{}())
{}
ForwardDifferentiator(T timestep)
: GenericFilter<T>({T(1)}, CoeffGetter<T, N>() / std::pow(timestep, Order))
: GenericFilter<T>({T(1)}, CoeffGetter{}() / std::pow(timestep, Order))
{}
void setTimestep(T timestep) { setCoeffs({T(1)}, CoeffGetter<T, N>() / std::pow(timestep, Order)); }
T timestep() const noexcept { return std::pow(bCoeff()(0) / CoeffGetter<T, N>()(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 T, size_t N, int Order, template<class, class> typename CoeffGetter>
template <typename T, size_t N, int Order, typename CoeffGetter>
class CentralDifferentiator : public GenericFilter<T> {
public:
CentralDifferentiator()
: GenericFilter<T>({T(1)}, CoeffGetter<T, N>(), Type::Centered)
: GenericFilter<T>({T(1)}, CoeffGetter{}(), Type::Centered)
{}
CentralDifferentiator(T timestep)
: GenericFilter<T>({T(1)}, CoeffGetter<T, N>() / std::pow(timestep, Order))
: GenericFilter<T>({T(1)}, CoeffGetter{}() / std::pow(timestep, Order))
{}
void setTimestep(T timestep) { setCoeffs({T(1)}, CoeffGetter<T, N>() / std::pow(timestep, Order)); }
T timestep() const noexcept { return std::pow(bCoeff()(0) / CoeffGetter<T, N>()(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 T, size_t N, int Order, template<class, class> typename CoeffGetter>
template <typename T, size_t N, int Order, typename CoeffGetter>
class TVForwardDifferentiator : public TVGenericFilter<T> {
static_assert(Order >= 1);
static_assert(Order >= 1, "Order must be greater or equal to 1");
public:
TVForwardDifferentiator()
: TVGenericFilter<T>(Order, {T(1)}, CoeffGetter<T, N>())
: TVGenericFilter<T>(Order, {T(1)}, CoeffGetter{}())
{}
};
template <typename T, size_t N, int Order, template<class, class> typename CoeffGetter>
template <typename T, size_t N, int Order, typename CoeffGetter>
class TVCentralDifferentiator : public TVGenericFilter<T> {
static_assert(Order >= 1);
static_assert(Order >= 1, "Order must be greater or equal to 1");
public:
TVCentralDifferentiator()
: TVGenericFilter<T>(Order, {T(1)}, CoeffGetter<T, N>(), Type::Centered)
: TVGenericFilter<T>(Order, {T(1)}, CoeffGetter{}(), Type::Centered)
{}
};
} // namespace details
// Backward differentiators
template <typename T, size_t N> using ForwardNoiseRobustDiff = ForwardDifferentiator<T, N, 1, details::GetFNRCoeffs>;
template <typename T, size_t N> using ForwardHybridNoiseRobustDiff = ForwardDifferentiator<T, N, 1, details::GetFHNRCoeffs>;
template <typename T, size_t N> using ForwardNoiseRobustDiff = details::ForwardDifferentiator<T, N, 1, details::GetFNRCoeffs<T, N>>;
template <typename T, size_t N> using ForwardHybridNoiseRobustDiff = details::ForwardDifferentiator<T, N, 1, details::GetFHNRCoeffs<T, N>>;
// Time-Varying backward differentiators
template <typename T, size_t N> using TVForwardNoiseRobustDiff = TVForwardDifferentiator<T, N, 1, details::GetFNRISDCoeffs>;
template <typename T, size_t N> using TVForwardHybridNoiseRobustDiff = TVForwardDifferentiator<T, N, 1, details::GetFHNRISDCoeffs>;
template <typename T, size_t N> using TVForwardNoiseRobustDiff = details::TVForwardDifferentiator<T, N, 1, details::GetFNRISDCoeffs<T, N>>;
template <typename T, size_t N> using TVForwardHybridNoiseRobustDiff = details::TVForwardDifferentiator<T, N, 1, details::GetFHNRISDCoeffs<T, N>>;
// Central differentiators
template <typename T, size_t N> using CentralDiff = CentralDifferentiator<T, N, 1, details::GetCDCoeffs>;
template <typename T, size_t N> using LowNoiseLanczosDiff = CentralDifferentiator<T, N, 1, details::GetLNLCoeffs>;
template <typename T, size_t N> using SuperLowNoiseLanczosDiff = CentralDifferentiator<T, N, 1, details::GetSLNLCoeffs>;
template <typename T, size_t N> using CenteredNoiseRobust2Diff = CentralDifferentiator<T, N, 1, details::GetCNR2Coeffs>;
template <typename T, size_t N> using CenteredNoiseRobust4Diff = CentralDifferentiator<T, N, 1, details::GetCNR4Coeffs>;
template <typename T, size_t N> using CentralDiff = details::CentralDifferentiator<T, N, 1, details::GetCDCoeffs<T, N>>;
template <typename T, size_t N> using LowNoiseLanczosDiff = details::CentralDifferentiator<T, N, 1, details::GetLNLCoeffs<T, N>>;
template <typename T, size_t N> using SuperLowNoiseLanczosDiff = details::CentralDifferentiator<T, N, 1, details::GetSLNLCoeffs<T, N>>;
template <typename T, size_t N> using CenteredNoiseRobust2Diff = details::CentralDifferentiator<T, N, 1, details::GetCNR2Coeffs<T, N>>;
template <typename T, size_t N> using CenteredNoiseRobust4Diff = details::CentralDifferentiator<T, N, 1, details::GetCNR4Coeffs<T, N>>;
// Time-Varying central differentiators
template <typename T, size_t N> using TVCenteredNoiseRobust2Diff = TVCentralDifferentiator<T, N, 1, details::GetCNR2ISDCoeffs>;
template <typename T, size_t N> using TVCenteredNoiseRobust4Diff = TVCentralDifferentiator<T, N, 1, details::GetCNR4ISDCoeffs>;
template <typename T, size_t N> using TVCenteredNoiseRobust2Diff = details::TVCentralDifferentiator<T, N, 1, details::GetCNR2ISDCoeffs<T, N>>;
template <typename T, size_t N> using TVCenteredNoiseRobust4Diff = details::TVCentralDifferentiator<T, N, 1, details::GetCNR4ISDCoeffs<T, N>>;
// Second-order backward differentiators
template <typename T, size_t N> using ForwardSecondOrderDiff = ForwardDifferentiator<T, N, 2, details::GetSOFNRCoeffs>;
template <typename T, size_t N> using ForwardSecondOrderDiff = details::ForwardDifferentiator<T, N, 2, details::GetSOFNRCoeffs<T, N>>;
// Second-order Time-Varying backward differentiators
template <typename T, size_t N> using TVForwardSecondOrderDiff = TVForwardDifferentiator<T, N, 2, details::GetSOFNRISDCoeffs>;
template <typename T, size_t N> using TVForwardSecondOrderDiff = details::TVForwardDifferentiator<T, N, 2, details::GetSOFNRISDCoeffs<T, N>>;
// Second-order central differentiators
template <typename T, size_t N> using CenteredSecondOrderDiff = CentralDifferentiator<T, N, 2, details::GetSOCNRCoeffs>;
template <typename T, size_t N> using CenteredSecondOrderDiff = details::CentralDifferentiator<T, N, 2, details::GetSOCNRCoeffs<T, N>>;
// Second-order Time-Varying backward differentiators
template <typename T, size_t N> using TVCenteredSecondOrderDiff = TVCentralDifferentiator<T, N, 2, details::GetSOCNRISDCoeffs>;
template <typename T, size_t N> using TVCenteredSecondOrderDiff = details::TVCentralDifferentiator<T, N, 2, details::GetSOCNRISDCoeffs<T, N>>;
} // namespace difi

Wyświetl plik

@ -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)
addTest(ButterWorthFilterTests)
# Differentiators
addTest(differentiator_tests)

Wyświetl plik

@ -28,7 +28,7 @@
#include "difi"
#include "test_functions.h"
#include "warning_macro.h"
#include "catch2/catch.hpp"
#include <catch2/catch.hpp>
DISABLE_CONVERSION_WARNING_BEGIN

Wyświetl plik

@ -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 <catch2/catch.hpp>
TEMPLATE_TEST_CASE("Sinus central derivative", "[sin][dentral]", float, double)
{
}

Wyświetl plik

@ -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 <tuple>
#include <cmath>
#include <random>
template <typename T>
using FunctionGenerator = std::tuple<difi::vectX_t<T>, difi::vectX_t<T>, difi::vectX_t<T>>;
template <typename T>
FunctionGenerator sinGenerator(int nrSteps, T omega, T dt = 0.001)
{
using namespace difi;
std::random_device rd{};
std::mt19937 gen{rd()};
vectX_t<T> truth;
vectX_t<T> noisy;
vectX_t<T> derivative;
for (int i = 0; i < nrSteps; ++i) {
// truth
truth(i) = std::sin(2 * pi<T> * omega * i * dt);
// noisy
std::normal_distribution<T> d{truth(i), T(0.01)};
noisy(i) = truth(i) + d(gen);
// derivative
derivative(i) = 2 * pi<T> * omega * i * std::cos(2 * pi<T> * omega * i * dt);
}
return { truth, noisy, derivative };
}
template <Typename T>
FunctionGenerator polyGenerator(int nrSteps, difi::VectX_t<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<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<T> derivativeCoeffs(coeffs.size() - 1);
for (Eigen::Index i = 1; i < coeffs.size(); ++i)
derivativeCoeffs(i - 1) = i * coeffs.tail(i);
vectX_t<T> truth;
vectX_t<T> noisy;
vectX_t<T> derivative;
for (int i = 0; i < nrSteps; ++i) {
// truth
truth(i) = computePoly(coeffs, i * dt);
// noisy
std::normal_distribution<T> d{truth(i), T(0.01)};
noisy(i) = truth(i) + d(gen);
// derivative
derivative(i) = computePoly(derivativeCoeffs, i * dt);
}
return { truth, noisy, derivative };
}