From 6ab21d6145ab8c2e3e1e58602a6645601fd1aebc Mon Sep 17 00:00:00 2001 From: Vincent Samy Date: Mon, 17 Dec 2018 17:16:01 +0900 Subject: [PATCH] Digital filter test ok. --- include/BilinearTransform.h | 8 +++--- include/Butterworth.h | 6 ++--- include/Butterworth.tpp | 20 +++++++------- include/DigitalFilter.h | 3 ++- include/GenericFilter.h | 18 ++++++------- include/GenericFilter.tpp | 21 ++++++++------- include/MovingAverage.h | 4 +-- include/polynome_functions.h | 17 +++--------- include/typedefs.h | 8 ++---- tests/ButterworthFilterTests.cpp | 12 ++++----- tests/CMakeLists.txt | 6 ++--- tests/DigitalFilterTests.cpp | 43 +++++++----------------------- tests/GenericFilterTests.cpp | 2 +- tests/MovingAverageFilterTests.cpp | 31 +++++---------------- tests/polynome_functions_tests.cpp | 29 ++++++++++---------- tests/test_functions.h | 35 ++++++++++++++++++++++++ 16 files changed, 121 insertions(+), 142 deletions(-) create mode 100644 tests/test_functions.h diff --git a/include/BilinearTransform.h b/include/BilinearTransform.h index e7747cd..1603e21 100644 --- a/include/BilinearTransform.h +++ b/include/BilinearTransform.h @@ -11,9 +11,9 @@ struct BilinearTransform { static_assert(std::is_floating_point::value, "This struct can only accept floating point types (real and complex)."); static void SToZ(SubType fs, const T& sPlanePole, T& zPlanePole); - static void SToZ(SubType fs, const Eigen::VectorX& sPlanePoles, Eigen::Ref>& zPlanePoles); // Can be optimized + static void SToZ(SubType fs, const vectX_t& sPlanePoles, Eigen::Ref>& zPlanePoles); // Can be optimized static void ZToS(SubType fs, const T& zPlanePole, T& sPlanePole); - static void ZToS(SubType fs, const Eigen::VectorX& zPlanePoles, Eigen::Ref>& sPlanePoles); // Can be optimized + static void ZToS(SubType fs, const vectX_t& zPlanePoles, Eigen::Ref>& sPlanePoles); // Can be optimized }; template @@ -24,7 +24,7 @@ void BilinearTransform::SToZ(SubType fs, const T& sPlanePole, T& zPlanePole) } template -void BilinearTransform::SToZ(SubType fs, const Eigen::VectorX& sPlanePoles, Eigen::Ref>& zPlanePoles) +void BilinearTransform::SToZ(SubType fs, const vectX_t& sPlanePoles, Eigen::Ref>& zPlanePoles) { assert(sPlanePoles.size() == zPlanePoles.size()); for (Eigen::Index k = 0; k < sPlanePoles.size(); ++k) @@ -39,7 +39,7 @@ void BilinearTransform::ZToS(SubType fs, const T& zPlanePole, T& sPlanePole) } template -void BilinearTransform::ZToS(SubType fs, const Eigen::VectorX& zPlanePoles, Eigen::Ref>& sPlanePoles) +void BilinearTransform::ZToS(SubType fs, const vectX_t& zPlanePoles, Eigen::Ref>& sPlanePoles) { assert(zPlanePoles.size() == sPlanePoles.size()); for (Eigen::Index k = 0; k < sPlanePoles.size(); ++k) diff --git a/include/Butterworth.h b/include/Butterworth.h index 04e50bd..e6077c7 100644 --- a/include/Butterworth.h +++ b/include/Butterworth.h @@ -31,15 +31,15 @@ private: void initialize(int order, T fc, T fs); void computeDigitalRep(); std::complex generateAnalogPole(T fpw, int k); - Eigen::VectorX> generateAnalogZeros(); - void scaleAmplitude(Eigen::Ref> aCoeff, Eigen::Ref> bCoeff); + vectX_t> generateAnalogZeros(); + void scaleAmplitude(Eigen::Ref> aCoeff, Eigen::Ref> bCoeff); private: Type m_type; int m_order; T m_fc; T m_fs; - Eigen::VectorX> m_poles; + vectX_t> m_poles; }; } // namespace fratio diff --git a/include/Butterworth.tpp b/include/Butterworth.tpp index f442d1f..50fce90 100644 --- a/include/Butterworth.tpp +++ b/include/Butterworth.tpp @@ -55,17 +55,17 @@ void Butterworth::computeDigitalRep() // Compute poles std::complex analogPole; - Eigen::VectorX> poles(m_order); + vectX_t> poles(m_order); for (int k = 1; k <= m_order; ++k) { analogPole = generateAnalogPole(fpw, k); BilinearTransform>::SToZ(m_fs, analogPole, poles(k - 1)); } - Eigen::VectorX> zeros = generateAnalogZeros(); - Eigen::VectorX> a = VietaAlgo>::polyCoeffFromRoot(poles); - Eigen::VectorX> b = VietaAlgo>::polyCoeffFromRoot(zeros); - Eigen::VectorX aCoeff(m_order + 1); - Eigen::VectorX bCoeff(m_order + 1); + vectX_t> zeros = generateAnalogZeros(); + vectX_t> a = VietaAlgo>::polyCoeffFromRoot(poles); + vectX_t> b = VietaAlgo>::polyCoeffFromRoot(zeros); + vectX_t aCoeff(m_order + 1); + vectX_t bCoeff(m_order + 1); for (int i = 0; i < m_order + 1; ++i) { aCoeff(i) = a(i).real(); bCoeff(i) = b(i).real(); @@ -96,20 +96,20 @@ std::complex Butterworth::generateAnalogPole(T fpw, int k) } template -Eigen::VectorX> Butterworth::generateAnalogZeros() +vectX_t> Butterworth::generateAnalogZeros() { switch (m_type) { case Type::HighPass: - return Eigen::VectorX>::Constant(m_order, std::complex(1)); + return vectX_t>::Constant(m_order, std::complex(1)); case Type::LowPass: default: - return Eigen::VectorX>::Constant(m_order, std::complex(-1)); + return vectX_t>::Constant(m_order, std::complex(-1)); } } template -void Butterworth::scaleAmplitude(Eigen::Ref> aCoeff, Eigen::Ref> bCoeff) +void Butterworth::scaleAmplitude(Eigen::Ref> aCoeff, Eigen::Ref> bCoeff) { T scale = 0; T sumB = 0; diff --git a/include/DigitalFilter.h b/include/DigitalFilter.h index 2a57517..27f68dd 100644 --- a/include/DigitalFilter.h +++ b/include/DigitalFilter.h @@ -5,11 +5,12 @@ namespace fratio { +// https://www.mathworks.com/help/dsp/ug/how-is-moving-average-filter-different-from-an-fir-filter.html template class DigitalFilter : public GenericFilter { public: DigitalFilter() = default; - DigitalFilter(const Eigen::VectorX& aCoeff, const Eigen::VectorX& bCoeff) + DigitalFilter(const vectX_t& aCoeff, const vectX_t& bCoeff) : GenericFilter(aCoeff, bCoeff) { } diff --git a/include/GenericFilter.h b/include/GenericFilter.h index bcf6721..44a727d 100644 --- a/include/GenericFilter.h +++ b/include/GenericFilter.h @@ -17,34 +17,34 @@ public: 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); + vectX_t filter(const vectX_t& data); + bool getFilterResults(Eigen::Ref> results, const vectX_t& data); void resetFilter(); template bool setCoeffs(T2&& aCoeff, T2&& bCoeff); - void getCoeffs(Eigen::VectorX& aCoeff, Eigen::VectorX& bCoeff) const; + void getCoeffs(vectX_t& aCoeff, vectX_t& bCoeff) const; FilterStatus status() const noexcept { return m_status; } Eigen::Index aOrder() const noexcept { return m_aCoeff.size(); } Eigen::Index bOrder() const noexcept { return m_bCoeff.size(); } protected: GenericFilter() = default; - GenericFilter(const Eigen::VectorX& aCoeff, const Eigen::VectorX& bCoeff); + GenericFilter(const vectX_t& aCoeff, const vectX_t& bCoeff); virtual ~GenericFilter() = default; void normalizeCoeffs(); - bool checkCoeffs(const Eigen::VectorX& aCoeff, const Eigen::VectorX& bCoeff); + bool checkCoeffs(const vectX_t& aCoeff, const vectX_t& bCoeff); protected: FilterStatus m_status; private: - Eigen::VectorX m_aCoeff; - Eigen::VectorX m_bCoeff; - Eigen::VectorX m_filteredData; - Eigen::VectorX m_rawData; + vectX_t m_aCoeff; + vectX_t m_bCoeff; + vectX_t m_filteredData; + vectX_t m_rawData; }; } // namespace fratio diff --git a/include/GenericFilter.tpp b/include/GenericFilter.tpp index 1f827f4..93049da 100644 --- a/include/GenericFilter.tpp +++ b/include/GenericFilter.tpp @@ -17,7 +17,7 @@ std::string GenericFilter::filterStatus(FilterStatus status) return "Filter has none of its coefficient initialized"; case FilterStatus::A_COEFF_MISSING: return "Filter has its 'a' coefficients uninitialized"; - case FilterStatus::A_COEFF_MISSING: + case FilterStatus::B_COEFF_MISSING: return "Filter has its 'b' coefficients uninitialized"; case FilterStatus::BAD_FREQUENCY_VALUE: return "Filter has a received a frequency that is negative or equal to zero"; @@ -37,25 +37,26 @@ T GenericFilter::stepFilter(const T& data) // Slide data (can't use SIMD, but should be small) m_rawData.tail(m_rawData.size() - 1) = m_rawData.head(m_rawData.size() - 1); - m_filteredData.tail(m_rawData.size() - 1) = m_filteredData.head(m_rawData.size() - 1); + m_filteredData.tail(m_filteredData.size() - 1) = m_filteredData.head(m_filteredData.size() - 1); m_rawData[0] = data; + m_filteredData[0] = 0; m_filteredData[0] = m_bCoeff.dot(m_rawData) - m_aCoeff.dot(m_filteredData); return m_filteredData[0]; } template -Eigen::VectorX GenericFilter::filter(const Eigen::VectorX& data) +vectX_t GenericFilter::filter(const vectX_t& data) { - Eigen::VectorX results(data.size()); + vectX_t results(data.size()); if (!getFilterResults(results, data)) - return Eigen::VectorX(); + return vectX_t(); return results; } template -bool GenericFilter::getFilterResults(Eigen::Ref> results, const Eigen::VectorX& data) +bool GenericFilter::getFilterResults(Eigen::Ref> results, const vectX_t& data) { assert(m_status == FilterStatus::READY); if (results.size() != data.size()) @@ -78,7 +79,7 @@ template template bool GenericFilter::setCoeffs(T2&& aCoeff, T2&& bCoeff) { - static_assert(std::is_same_v>, "The coefficents should be of type Eigen::VectorX"); + static_assert(std::is_same_v>, "The coefficents should be of type vectX_t"); if (!checkCoeffs(aCoeff, bCoeff)) return false; @@ -91,7 +92,7 @@ bool GenericFilter::setCoeffs(T2&& aCoeff, T2&& bCoeff) } template -void GenericFilter::getCoeffs(Eigen::VectorX& aCoeff, Eigen::VectorX& bCoeff) const +void GenericFilter::getCoeffs(vectX_t& aCoeff, vectX_t& bCoeff) const { aCoeff = m_aCoeff; bCoeff = m_bCoeff; @@ -100,7 +101,7 @@ void GenericFilter::getCoeffs(Eigen::VectorX& aCoeff, Eigen::VectorX& b // Protected functions template -GenericFilter::GenericFilter(const Eigen::VectorX& aCoeff, const Eigen::VectorX& bCoeff) +GenericFilter::GenericFilter(const vectX_t& aCoeff, const vectX_t& bCoeff) : m_aCoeff(aCoeff) , m_bCoeff(bCoeff) , m_filteredData(aCoeff.size()) @@ -127,7 +128,7 @@ void GenericFilter::normalizeCoeffs() } template -bool GenericFilter::checkCoeffs(const Eigen::VectorX& aCoeff, const Eigen::VectorX& bCoeff) +bool GenericFilter::checkCoeffs(const vectX_t& aCoeff, const vectX_t& bCoeff) { m_status = FilterStatus::NONE; if (aCoeff.size() == 0) diff --git a/include/MovingAverage.h b/include/MovingAverage.h index 58dc022..77ef77a 100644 --- a/include/MovingAverage.h +++ b/include/MovingAverage.h @@ -10,7 +10,7 @@ class MovingAverage : public DigitalFilter { public: MovingAverage() = default; MovingAverage(int windowSize) - : DigitalFilter(Eigen::VectorX::Constant(1, T(1)), Eigen::VectorX::Constant(windowSize, T(1) / windowSize)) + : DigitalFilter(vectX_t::Constant(1, T(1)), vectX_t::Constant(windowSize, T(1) / windowSize)) { } @@ -21,7 +21,7 @@ public: return; } - setCoeffs(Eigen::VectorX::Constant(1, T(1)), Eigen::VectorX::Constant(windowSize, T(1) / windowSize)); + setCoeffs(vectX_t::Constant(1, T(1)), vectX_t::Constant(windowSize, T(1) / windowSize)); } int windowSize() const noexcept { return bOrder(); } }; diff --git a/include/polynome_functions.h b/include/polynome_functions.h index e087e4c..fee2fc8 100644 --- a/include/polynome_functions.h +++ b/include/polynome_functions.h @@ -11,30 +11,19 @@ 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 Eigen::VectorX polyCoeffFromRoot(const Eigen::VectorX& poles); + static vectX_t polyCoeffFromRoot(const vectX_t& poles); }; template -Eigen::VectorX VietaAlgo::polyCoeffFromRoot(const Eigen::VectorX& poles) +vectX_t VietaAlgo::polyCoeffFromRoot(const vectX_t& poles) { - Eigen::VectorX coeffs = Eigen::VectorX::Zero(poles.size() + 1); + vectX_t coeffs = vectX_t::Zero(poles.size() + 1); coeffs(0) = T(1); for (Eigen::Index i = 0; i < poles.size(); ++i) { for (Eigen::Index k = i + 1; k > 0; --k) { 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 - // Eigen::Index pSize = poles.size(); - // for (Eigen::Index k = 1; k < coeffs.size(); ++k) - // coeffs(k) -= poles.tail(pSize - (k - 1)).sum() * coeffs(k - 1); - - // Maybe better - // T sum = poles.sum(); - // for (Eigen::Index k = 1; k < coeffs.size(); ++k) { - // coeffs(k) -= sum * coeffs(k - 1); - // sum -= poles(k - 1); - // } return coeffs; } diff --git a/include/typedefs.h b/include/typedefs.h index 0f5f56e..c0cf4c5 100644 --- a/include/typedefs.h +++ b/include/typedefs.h @@ -2,14 +2,10 @@ #include -namespace Eigen { +namespace fratio { template -using VectorX = Eigen::Matrix; - -} // namespace Eigen - -namespace fratio { +using vectX_t = Eigen::Matrix; enum class FilterStatus { // Generic filter diff --git a/tests/ButterworthFilterTests.cpp b/tests/ButterworthFilterTests.cpp index cf5f36a..4c5184d 100644 --- a/tests/ButterworthFilterTests.cpp +++ b/tests/ButterworthFilterTests.cpp @@ -8,13 +8,13 @@ DISABLE_CONVERSION_WARNING_BEGIN template struct System { - Eigen::VectorX data = (Eigen::VectorX(8) << 1, 2, 3, 4, 5, 6, 7, 8).finished(); + fratio::vectX_t data = (fratio::vectX_t(8) << 1, 2, 3, 4, 5, 6, 7, 8).finished(); int order = 5; T fc = 10; T fs = 100; - Eigen::VectorX aCoeffRes = (Eigen::VectorX(6) << 1.000000000000000, -2.975422109745684, 3.806018119320413, -2.545252868330468, 0.881130075437837, -0.125430622155356).finished(); - Eigen::VectorX bCoeffRes = (Eigen::VectorX(6) << 0.001282581078961, 0.006412905394803, 0.012825810789607, 0.012825810789607, 0.006412905394803, 0.001282581078961).finished(); - Eigen::VectorX results = (Eigen::VectorX(8) << 0.001282581078961, 0.012794287652606, 0.062686244350084, 0.203933712825708, 0.502244959135609, 1.010304217144175, 1.744652693589064, 2.678087381460197).finished(); + fratio::vectX_t aCoeffRes = (fratio::vectX_t(6) << 1.000000000000000, -2.975422109745684, 3.806018119320413, -2.545252868330468, 0.881130075437837, -0.125430622155356).finished(); + fratio::vectX_t bCoeffRes = (fratio::vectX_t(6) << 0.001282581078961, 0.006412905394803, 0.012825810789607, 0.012825810789607, 0.006412905394803, 0.001282581078961).finished(); + fratio::vectX_t results = (fratio::vectX_t(8) << 0.001282581078961, 0.012794287652606, 0.062686244350084, 0.203933712825708, 0.502244959135609, 1.010304217144175, 1.744652693589064, 2.678087381460197).finished(); }; DISABLE_CONVERSION_WARNING_END @@ -24,7 +24,7 @@ BOOST_FIXTURE_TEST_CASE(BUTTERWORTH_FILTER_FLOAT, System) auto bf = fratio::Butterworthf(order, fc, fs); std::vector filteredData; - Eigen::VectorX aCoeff, bCoeff; + fratio::vectX_t aCoeff, bCoeff; bf.getCoeffs(aCoeff, bCoeff); BOOST_REQUIRE_EQUAL(aCoeff.size(), aCoeffRes.size()); @@ -63,7 +63,7 @@ BOOST_FIXTURE_TEST_CASE(BUTTERWORTH_FILTER_DOUBLE, System) auto bf = fratio::Butterworthd(order, fc, fs); std::vector filteredData; - Eigen::VectorX aCoeff, bCoeff; + fratio::vectX_t aCoeff, bCoeff; bf.getCoeffs(aCoeff, bCoeff); BOOST_REQUIRE_EQUAL(aCoeff.size(), aCoeffRes.size()); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a0ee31c..0e1f8b4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -20,8 +20,8 @@ macro(addTest testName) GENERATE_MSVC_DOT_USER_FILE(${testName}) endmacro(addTest) -# addTest(GenericFilterTests) -# addTest(polynome_functions_tests) +addTest(GenericFilterTests) +addTest(polynome_functions_tests) addTest(DigitalFilterTests) -# addTest(MovingAverageFilterTests) +addTest(MovingAverageFilterTests) # addTest(ButterWorthFilterTests) \ No newline at end of file diff --git a/tests/DigitalFilterTests.cpp b/tests/DigitalFilterTests.cpp index 2e0226f..a6f8fdc 100644 --- a/tests/DigitalFilterTests.cpp +++ b/tests/DigitalFilterTests.cpp @@ -1,6 +1,7 @@ #define BOOST_TEST_MODULE DigitalFilterTests #include "fratio" +#include "test_functions.h" #include "warning_macro.h" #include @@ -8,10 +9,10 @@ DISABLE_CONVERSION_WARNING_BEGIN template struct System { - Eigen::VectorX data = (Eigen::VectorX(4) << 1, 2, 3, 4).finished(); - Eigen::VectorX aCoeff = (Eigen::VectorX(2) << 1, -0.99993717).finished(); - Eigen::VectorX bCoeff = (Eigen::VectorX(2) << 0.99996859, -0.99996859).finished(); - Eigen::VectorX results = (Eigen::VectorX(4) << 0.99996859, 1.999874351973491, 2.999717289867956, 3.999497407630634).finished(); + fratio::vectX_t data = (fratio::vectX_t(4) << 1, 2, 3, 4).finished(); + fratio::vectX_t aCoeff = (fratio::vectX_t(2) << 1, -0.99993717).finished(); + fratio::vectX_t bCoeff = (fratio::vectX_t(2) << 0.99996859, -0.99996859).finished(); + fratio::vectX_t results = (fratio::vectX_t(4) << 0.99996859, 1.999874351973491, 2.999717289867956, 3.999497407630634).finished(); }; DISABLE_CONVERSION_WARNING_END @@ -19,39 +20,13 @@ DISABLE_CONVERSION_WARNING_END BOOST_FIXTURE_TEST_CASE(DIGITAL_FILTER_FLOAT, System) { auto df = fratio::DigitalFilterf(aCoeff, bCoeff); - BOOST_REQUIRE_EQUAL(aCoeff.size(), df.aOrder()); - BOOST_REQUIRE_EQUAL(bCoeff.size(), df.bOrder()); - - std::vector filteredData; - - for (Eigen::Index i = 0; i < data.size(); ++i) - filteredData.push_back(df.stepFilter(data(i))); - - for (size_t i = 0; i < filteredData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-6f); - - df.resetFilter(); - Eigen::VectorXf fData = df.filter(data); - for (Eigen::Index i = 0; i < fData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(fData(i) - results(i)), 1e-6f); + test_coeffs(aCoeff, bCoeff, df); + test_results(results, data, df); } BOOST_FIXTURE_TEST_CASE(DIGITAL_FILTER_DOUBLE, System) { auto df = fratio::DigitalFilterd(aCoeff, bCoeff); - BOOST_REQUIRE_EQUAL(aCoeff.size(), df.aOrder()); - BOOST_REQUIRE_EQUAL(bCoeff.size(), df.bOrder()); - - std::vector filteredData; - - for (Eigen::Index i = 0; i < data.size(); ++i) - filteredData.push_back(df.stepFilter(data(i))); - - for (size_t i = 0; i < filteredData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-14); - - df.resetFilter(); - Eigen::VectorXd fData = df.filter(data); - for (Eigen::Index i = 0; i < fData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(fData(i) - results(i)), 1e-14); + test_coeffs(aCoeff, bCoeff, df); + test_results(results, data, df); } diff --git a/tests/GenericFilterTests.cpp b/tests/GenericFilterTests.cpp index b6399dc..9eb126b 100644 --- a/tests/GenericFilterTests.cpp +++ b/tests/GenericFilterTests.cpp @@ -4,7 +4,7 @@ #include #include -BOOST_AUTO_TEST_CASE(FilterThrows) +BOOST_AUTO_TEST_CASE(FILTER_FAILURES) { auto dfd = fratio::DigitalFilterd(Eigen::VectorXd(), Eigen::VectorXd::Constant(2, 0)); BOOST_REQUIRE(dfd.status() == fratio::FilterStatus::A_COEFF_MISSING); diff --git a/tests/MovingAverageFilterTests.cpp b/tests/MovingAverageFilterTests.cpp index e11a4bd..ee85121 100644 --- a/tests/MovingAverageFilterTests.cpp +++ b/tests/MovingAverageFilterTests.cpp @@ -1,43 +1,24 @@ #define BOOST_TEST_MODULE MovingAverageFilterTests #include "fratio" +#include "test_functions.h" #include template struct System { - Eigen::VectorX data = (Eigen::VectorX(6) << 1, 2, 3, 4, 5, 6).finished(); - size_t windowSize = 4; - Eigen::VectorX results = (Eigen::VectorX(6) << 0.25, 0.75, 1.5, 2.5, 3.5, 4.5).finished(); + fratio::vectX_t data = (fratio::vectX_t(6) << 1, 2, 3, 4, 5, 6).finished(); + int windowSize = 4; + fratio::vectX_t results = (fratio::vectX_t(6) << 0.25, 0.75, 1.5, 2.5, 3.5, 4.5).finished(); }; BOOST_FIXTURE_TEST_CASE(MOVING_AVERAGE_FLOAT, System) { auto maf = fratio::MovingAveragef(windowSize); - std::vector filteredData; - for (Eigen::Index i = 0; i < data.size(); ++i) - filteredData.push_back(maf.stepFilter(data(i))); - - for (size_t i = 0; i < filteredData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-6f); - - maf.resetFilter(); - Eigen::VectorXf fData = maf.filter(data); - for (Eigen::Index i = 0; i < fData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(fData(i) - results(i)), 1e-6f); + test_results(results, data, maf); } BOOST_FIXTURE_TEST_CASE(MOVING_AVERAGE_DOUBLE, System) { auto maf = fratio::MovingAveraged(windowSize); - std::vector filteredData; - for (Eigen::Index i = 0; i < data.size(); ++i) - filteredData.push_back(maf.stepFilter(data(i))); - - for (size_t i = 0; i < filteredData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(filteredData[i] - results[i]), 1e-14); - - maf.resetFilter(); - Eigen::VectorXd fData = maf.filter(data); - for (Eigen::Index i = 0; i < fData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(fData(i) - results(i)), 1e-14); + test_results(results, data, maf); } diff --git a/tests/polynome_functions_tests.cpp b/tests/polynome_functions_tests.cpp index 783798f..38f61ff 100644 --- a/tests/polynome_functions_tests.cpp +++ b/tests/polynome_functions_tests.cpp @@ -3,33 +3,34 @@ #include "fratio" #include "warning_macro.h" #include +#include using c_int_t = std::complex; template using c_t = std::complex; struct SystemInt { - Eigen::VectorX data = (Eigen::VectorX(4) << 1, 1, 1, 1).finished(); - Eigen::VectorX results = (Eigen::VectorX(5) << 1, -4, 6, -4, 1).finished(); + fratio::vectX_t data = (fratio::vectX_t(4) << 1, 1, 1, 1).finished(); + fratio::vectX_t results = (fratio::vectX_t(5) << 1, -4, 6, -4, 1).finished(); }; struct SystemCInt { - Eigen::VectorX data = (Eigen::VectorX(4) << c_int_t{ 1, 1 }, c_int_t{ -1, 4 }, c_int_t{ 12, -3 }, c_int_t{ 5, 2 }).finished(); - Eigen::VectorX results = (Eigen::VectorX(5) << c_int_t{ 1, 0 }, c_int_t{ -17, -4 }, c_int_t{ 66, 97 }, c_int_t{ 127, -386 }, c_int_t{ -357, 153 }).finished(); + fratio::vectX_t data = (fratio::vectX_t(4) << c_int_t{ 1, 1 }, c_int_t{ -1, 4 }, c_int_t{ 12, -3 }, c_int_t{ 5, 2 }).finished(); + fratio::vectX_t results = (fratio::vectX_t(5) << c_int_t{ 1, 0 }, c_int_t{ -17, -4 }, c_int_t{ 66, 97 }, c_int_t{ 127, -386 }, c_int_t{ -357, 153 }).finished(); }; DISABLE_CONVERSION_WARNING_BEGIN template struct SystemFloat { - Eigen::VectorX data = (Eigen::VectorX(4) << 0.32, -0.0518, 41.4, 0.89).finished(); - Eigen::VectorX results = (Eigen::VectorX(5) << 1, -42.558199999999999, 48.171601999999993, -9.181098159999999, -0.610759296).finished(); + fratio::vectX_t data = (fratio::vectX_t(4) << 0.32, -0.0518, 41.4, 0.89).finished(); + fratio::vectX_t results = (fratio::vectX_t(5) << 1, -42.558199999999999, 48.171601999999993, -9.181098159999999, -0.610759296).finished(); }; template struct SystemCFloat { - Eigen::VectorX> data = (Eigen::VectorX>(4) << c_t{ 1.35, 0.2 }, c_t{ -1.5, 4.45 }, c_t{ 12.8, -3.36 }, c_t{ 5.156, 2.12 }).finished(); - Eigen::VectorX> results = (Eigen::VectorX>(5) << c_t{ 1, 0 }, c_t{ -17.806, -3.41 }, c_t{ 73.2776, 99.20074 }, c_t{ 101.857496, -444.634694 }, c_t{ -269.1458768, 388.7308864 }).finished(); + fratio::vectX_t> data = (fratio::vectX_t>(4) << c_t{ 1.35, 0.2 }, c_t{ -1.5, 4.45 }, c_t{ 12.8, -3.36 }, c_t{ 5.156, 2.12 }).finished(); + fratio::vectX_t> results = (fratio::vectX_t>(5) << c_t{ 1, 0 }, c_t{ -17.806, -3.41 }, c_t{ 73.2776, 99.20074 }, c_t{ 101.857496, -444.634694 }, c_t{ -269.1458768, 388.7308864 }).finished(); }; DISABLE_CONVERSION_WARNING_END @@ -39,7 +40,7 @@ BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_INT, SystemInt) auto res = fratio::VietaAlgoi::polyCoeffFromRoot(data); for (Eigen::Index i = 0; i < res.size(); ++i) - BOOST_CHECK_EQUAL(res(i), results(i)); + BOOST_REQUIRE_EQUAL(res(i), results(i)); } BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_FLOAT, SystemFloat) @@ -47,7 +48,7 @@ BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_FLOAT, SystemFloat) auto res = fratio::VietaAlgof::polyCoeffFromRoot(data); for (Eigen::Index i = 0; i < res.size(); ++i) - BOOST_CHECK_SMALL(std::abs(res(i) - results(i)), 1e-6f); + BOOST_REQUIRE_SMALL(std::abs(res(i) - results(i)), std::numeric_limits::epsilon() * 1000); } BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_DOUBLE, SystemFloat) @@ -55,7 +56,7 @@ BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_DOUBLE, SystemFloat) auto res = fratio::VietaAlgod::polyCoeffFromRoot(data); for (Eigen::Index i = 0; i < res.size(); ++i) - BOOST_CHECK_SMALL(std::abs(res(i) - results(i)), 1e-14); + BOOST_REQUIRE_SMALL(std::abs(res(i) - results(i)), std::numeric_limits::epsilon() * 1000); } BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_CINT, SystemCInt) @@ -63,7 +64,7 @@ BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_CINT, SystemCInt) auto res = fratio::VietaAlgoci::polyCoeffFromRoot(data); for (Eigen::Index i = 0; i < res.size(); ++i) - BOOST_CHECK_EQUAL(res(i), results(i)); + BOOST_REQUIRE_EQUAL(res(i), results(i)); } BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_CFLOAT, SystemCFloat) @@ -71,7 +72,7 @@ BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_CFLOAT, SystemCFloat) auto res = fratio::VietaAlgocf::polyCoeffFromRoot(data); for (Eigen::Index i = 0; i < res.size(); ++i) - BOOST_CHECK_SMALL(std::abs(res(i) - results(i)), 1e-4f); + BOOST_REQUIRE_SMALL(std::abs(res(i) - results(i)), std::numeric_limits::epsilon() * 1000); } BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_CDOUBLE, SystemCFloat) @@ -79,5 +80,5 @@ BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_CDOUBLE, SystemCFloat) auto res = fratio::VietaAlgocd::polyCoeffFromRoot(data); for (Eigen::Index i = 0; i < res.size(); ++i) - BOOST_CHECK_SMALL(std::abs(res(i) - results(i)), 1e-12); + BOOST_REQUIRE_SMALL(std::abs(res(i) - results(i)), std::numeric_limits::epsilon() * 1000); } diff --git a/tests/test_functions.h b/tests/test_functions.h new file mode 100644 index 0000000..b8cef7a --- /dev/null +++ b/tests/test_functions.h @@ -0,0 +1,35 @@ +#pragma once + +#include "fratio" +#include +#include + +template +void test_coeffs(const fratio::vectX_t& aCoeff, const fratio::vectX_t& bCoeff, const fratio::GenericFilter& filter) +{ + BOOST_REQUIRE_EQUAL(aCoeff.size(), filter.aOrder()); + BOOST_REQUIRE_EQUAL(bCoeff.size(), filter.bOrder()); + fratio::vectX_t faCoeff, fbCoeff; + filter.getCoeffs(faCoeff, fbCoeff); + for (Eigen::Index i = 0; i < faCoeff.size(); ++i) + BOOST_REQUIRE_SMALL(std::abs(aCoeff(i) - faCoeff(i)), std::numeric_limits::epsilon() * 2); + for (Eigen::Index i = 0; i < fbCoeff.size(); ++i) + BOOST_REQUIRE_SMALL(std::abs(bCoeff(i) - fbCoeff(i)), std::numeric_limits::epsilon() * 2); +} + +template +void test_results(const fratio::vectX_t& results, const fratio::vectX_t& data, fratio::GenericFilter& filter) +{ + fratio::vectX_t filteredData(results.size()); + + for (Eigen::Index i = 0; i < data.size(); ++i) + filteredData(i) = filter.stepFilter(data(i)); + + for (Eigen::Index i = 0; i < filteredData.size(); ++i) + BOOST_REQUIRE_SMALL(std::abs(filteredData(i) - results(i)), std::numeric_limits::epsilon() * 100); + + filter.resetFilter(); + filteredData = filter.filter(data); + for (Eigen::Index i = 0; i < filteredData.size(); ++i) + BOOST_REQUIRE_SMALL(std::abs(filteredData(i) - results(i)), std::numeric_limits::epsilon() * 100); +} \ No newline at end of file