diff --git a/CMakeLists.txt b/CMakeLists.txt index 1fb6b98..cad5465 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,8 +29,8 @@ endif() add_compile_options("-D_USE_MATH_DEFINES") # Eigen -# set(Eigen_REQUIRED "eigen3 >= 3.3") -# search_for_eigen() +set(Eigen_REQUIRED "eigen3 >= 3.3") +search_for_eigen() add_subdirectory(include) diff --git a/include/Butterworth.h b/include/Butterworth.h index b76d687..7689534 100644 --- a/include/Butterworth.h +++ b/include/Butterworth.h @@ -1,14 +1,14 @@ #pragma once #include "GenericFilter.h" +#include "typedefs.h" #include -#include namespace fratio { // https://www.dsprelated.com/showarticle/1119.php template -class Butterworth : public GenericFilter { +class Butterworth : public DigitalFilter { public: T PI = static_cast(M_PI); @@ -39,8 +39,9 @@ private: size_t m_order; T m_fc; T m_fs; + Eigen::VectorX> m_poles; }; } // namespace fratio -#include "Butterworth.inl" \ No newline at end of file +#include "Butterworth.tpp" diff --git a/include/DigitalFilter.h b/include/DigitalFilter.h index 903f5fa..0aec5c1 100644 --- a/include/DigitalFilter.h +++ b/include/DigitalFilter.h @@ -1,6 +1,8 @@ #pragma once #include "GenericFilter.h" +#include "typedefs.h" +#include namespace fratio { @@ -9,23 +11,18 @@ class DigitalFilter : public GenericFilter { public: DigitalFilter() = default; DigitalFilter(const std::vector& aCoeff, const std::vector& bCoeff) + { + setCoeffs(aCoeff, bCoeff); + } + DigitalFilter(const Eigen::VectorX& aCoeff, const Eigen::VectorX& bCoeff) : GenericFilter(aCoeff, bCoeff) { } - void setCoeff(const std::vector& aCoeff, const std::vector& bCoeff) - { - checkCoeff(aCoeff, bCoeff); - - m_aCoeff = aCoeff; - m_bCoeff = bCoeff; - resetFilter(); - - normalize(); - } - size_t aOrder() const noexcept { return m_aCoeff.size(); } size_t bOrder() const noexcept { return m_bCoeff.size(); } }; -} // namespace fratio \ No newline at end of file +} // namespace fratio + +#include "DigitalFilter.tpp" \ No newline at end of file diff --git a/include/GenericFilter.h b/include/GenericFilter.h index 106704b..787effe 100644 --- a/include/GenericFilter.h +++ b/include/GenericFilter.h @@ -1,7 +1,9 @@ #pragma once #include "type_checks.h" +#include "typedefs.h" #include +#include #include namespace fratio { @@ -11,29 +13,40 @@ class GenericFilter { static_assert(std::is_floating_point::value && !std::is_const::value, "Only accept non-complex floating point types."); public: - T stepFilter(T data); - std::vector filter(const std::vector& data); + static std::string filterStatus(FilterStatus status); + +public: + // Careful: Only an assert check for the filter status + T stepFilter(const T& data); + Eigen::VectorX filter(const Eigen::VectorX& data); + bool getFilterResults(Eigen::Ref> results, const Eigen::VectorX& data); void resetFilter(); - void getCoeff(std::vector& aCoeff, std::vector& bCoeff) const noexcept; + bool setCoeffs(const std::vector& aCoeff, const std::vector& bCoeff); + bool setCoeffs(const Eigen::VectorX& aCoeff, const Eigen::VectorX& bCoeff); + void getCoeffs(std::vector& aCoeff, std::vector& bCoeff) const; + void getCoeffs(Eigen::Ref> aCoeff, Eigen::Ref> bCoeff) const; + FilterStatus status() const noexcept { return m_status; } protected: GenericFilter() = default; - GenericFilter(const std::vector& aCoeff, const std::vector& bCoeff); + GenericFilter(const Eigen::VectorX& aCoeff, const Eigen::VectorX& bCoeff); virtual ~GenericFilter() = default; - void checkCoeff(const std::vector& aCoeff, const std::vector& bCoeff); - void normalize(); + void normalizeCoeffs(); + template + bool checkCoeffs(const T2& aCoeff, const T2& bCoeff); protected: - std::vector m_aCoeff; - std::vector m_bCoeff; + FilterStatus m_status; + Eigen::VectorX m_aCoeff; + Eigen::VectorX m_bCoeff; private: - std::vector m_filteredData; - std::vector m_rawData; + Eigen::VectorX m_filteredData; + Eigen::VectorX m_rawData; }; } // namespace fratio -#include "GenericFilter.inl" \ No newline at end of file +#include "GenericFilter.tpp" diff --git a/include/MovingAverage.h b/include/MovingAverage.h index fb90a07..9ebcb12 100644 --- a/include/MovingAverage.h +++ b/include/MovingAverage.h @@ -1,20 +1,27 @@ #pragma once -#include "GenericFilter.h" +#include "DigitalFilter.h" +#include "typedefs.h" namespace fratio { template -class MovingAverage : public GenericFilter { +class MovingAverage : public DigitalFilter { public: MovingAverage() = default; MovingAverage(size_t windowSize) - : GenericFilter({ 1 }, std::vector(windowSize, T(1) / windowSize)) + : DigitalFilter(Eigen::VectorX::Constant(1, T(1)), Eigen::VectorX::Constant(windowSize, T(1) / windowSize))) { } - void setWindowSize(size_t windowSize) { setCoeff({ 1 }, std::vector(windowSize, 1 / windowSize)); } - size_t windowSize() const noexcept { return m_bCoeff.size(); } + void setWindowSize(size_t windowSize) { setCoeffs(Eigen::VectorX::Constant(1, T(1)), Eigen::VectorX::Constant(windowSize, T(1) / windowSize)); } + size_t windowSize() const noexcept { return bOrder(); } + : DigitalFilter(Eigen::VectorX::Constant(1, T(1)), Eigen::VectorX::Constant(windowSize, T(1) / windowSize))) + { + } + + void setWindowSize(size_t windowSize) { setCoeffs(Eigen::VectorX::Constant(1, T(1)), Eigen::VectorX::Constant(windowSize, T(1) / windowSize)); } + size_t windowSize() const noexcept { return bOrder(); } }; -} // namespace fratio \ No newline at end of file +} // namespace fratio diff --git a/include/polynome_functions.h b/include/polynome_functions.h index 8b62ac2..b19b37c 100644 --- a/include/polynome_functions.h +++ b/include/polynome_functions.h @@ -1,8 +1,8 @@ #pragma once #include "type_checks.h" +#include "typedefs.h" #include -#include namespace fratio { @@ -11,21 +11,32 @@ struct VietaAlgo { static_assert(std::is_arithmetic>::value, "This struct can only accept arithmetic types or complex."); // Vieta's computation: https://en.wikipedia.org/wiki/Vieta%27s_formulas - static std::vector polyCoeffFromRoot(const std::vector& poles); + static Eigen::VectorX polyCoeffFromRoot(const Eigen::VectorX& poles); }; template -std::vector VietaAlgo::polyCoeffFromRoot(const std::vector& poles) +Eigen::VectorX VietaAlgo::polyCoeffFromRoot(const Eigen::VectorX& poles) { - std::vector coeff(poles.size() + 1, 0); - coeff[0] = 1; + Eigen::VectorX coeffs = Eigen::VectorX::Zero(poles.size() + 1); + coeffs(0) = T(1); for (size_t i = 0; i < poles.size(); ++i) { for (size_t k = i + 1; k > 0; --k) { - coeff[k] = coeff[k] - poles[i] * coeff[k - 1]; + coeffs(k) -= poles(i) * coeffs(k - 1); } } + // Check for equation c(k) = sum(i=k-1, poles.size() : p(i)) * c(k-1), k>=1 + // size_t pSize = poles.size(); + // for (size_t k = 1; k < coeffs.size(); ++k) + // coeffs(k) -= poles.tail(pSize - (k - 1)).sum() * coeffs(k - 1); - return coeff; + // Maybe better + // T sum = poles.sum(); + // for (size_t k = 1; k < coeffs.size(); ++k) { + // coeffs(k) -= sum * coeffs(k - 1); + // sum -= poles(k - 1); + // } + + return coeffs; } -} // namespace fratio \ No newline at end of file +} // namespace fratio