diff --git a/include/GenericFilter.tpp b/include/GenericFilter.tpp index 93049da..8a57d88 100644 --- a/include/GenericFilter.tpp +++ b/include/GenericFilter.tpp @@ -36,8 +36,10 @@ T GenericFilter::stepFilter(const T& data) assert(m_status == FilterStatus::READY); // 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_filteredData.size() - 1) = m_filteredData.head(m_filteredData.size() - 1); + for (Eigen::Index i = m_rawData.size() - 1; i > 0; --i) + m_rawData(i) = m_rawData(i - 1); + for (Eigen::Index i = m_filteredData.size() - 1; i > 0; --i) + m_filteredData(i) = m_filteredData(i - 1); m_rawData[0] = data; m_filteredData[0] = 0; diff --git a/tests/ButterworthFilterTests.cpp b/tests/ButterworthFilterTests.cpp index 4c5184d..0bef719 100644 --- a/tests/ButterworthFilterTests.cpp +++ b/tests/ButterworthFilterTests.cpp @@ -1,6 +1,7 @@ #define BOOST_TEST_MODULE ButterworthFilterTests #include "fratio" +#include "test_functions.h" #include "warning_macro.h" #include @@ -12,87 +13,46 @@ struct System { int order = 5; T fc = 10; T fs = 100; - 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(); + // LP + fratio::vectX_t lpACoeffRes = (fratio::vectX_t(6) << 1, -2.975422109745684, 3.806018119320413, -2.545252868330468, 0.881130075437837, -0.125430622155356).finished(); + fratio::vectX_t lpBCoeffRes = (fratio::vectX_t(6) << 0.001282581078961, 0.006412905394803, 0.012825810789607, 0.012825810789607, 0.006412905394803, 0.001282581078961).finished(); + fratio::vectX_t lpResults = (fratio::vectX_t(8) << 0.001282581078961, 0.012794287652606, 0.062686244350084, 0.203933712825708, 0.502244959135609, 1.010304217144175, 1.744652693589064, 2.678087381460197).finished(); + // HP + fratio::vectX_t hpACoeffRes = (fratio::vectX_t(6) << 1, -2.975422109745683, 3.806018119320411, -2.545252868330467, 0.8811300754378368, -0.1254306221553557).finished(); + fratio::vectX_t hpBCoeffRes = (fratio::vectX_t(6) << 0.3541641810934298, -1.770820905467149, 3.541641810934299, -3.541641810934299, 1.770820905467149, -0.3541641810934298).finished(); + fratio::vectX_t hpResults = (fratio::vectX_t(8) << 0.3541641810934298, -0.008704608374924483, -0.3113626313910076, -0.3460321436983160, -0.1787600153274098, 0.04471440201428267, 0.2059279258827846, 0.2533941579793959).finished(); }; DISABLE_CONVERSION_WARNING_END -BOOST_FIXTURE_TEST_CASE(BUTTERWORTH_FILTER_FLOAT, System) +BOOST_FIXTURE_TEST_CASE(BUTTERWORTH_LP_FILTER_FLOAT, System) { auto bf = fratio::Butterworthf(order, fc, fs); - - std::vector filteredData; - fratio::vectX_t aCoeff, bCoeff; - bf.getCoeffs(aCoeff, bCoeff); - - BOOST_REQUIRE_EQUAL(aCoeff.size(), aCoeffRes.size()); - BOOST_REQUIRE_EQUAL(bCoeff.size(), bCoeffRes.size()); - BOOST_REQUIRE_EQUAL(aCoeff.size(), bCoeffRes.size()); - - for (Eigen::Index i = 0; i < aCoeff.size(); ++i) { - BOOST_CHECK_SMALL(std::abs(aCoeff(i) - aCoeffRes(i)), 1e-6f); - BOOST_CHECK_SMALL(std::abs(bCoeff(i) - bCoeffRes(i)), 1e-6f); - } - - for (Eigen::Index i = 0; i < data.size(); ++i) - filteredData.push_back(bf.stepFilter(data(i))); - - for (size_t i = 0; i < filteredData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-6f); - - bf.resetFilter(); - Eigen::VectorXf fData = bf.filter(data); - for (Eigen::Index i = 0; i < fData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(fData(i) - results(i)), 1e-6f); - - auto bf2 = fratio::Butterworthf(); - - bf2.setFilterParameters(order, fc, fs); - filteredData.clear(); - for (Eigen::Index i = 0; i < data.size(); ++i) - filteredData.push_back(bf2.stepFilter(data(i))); - - for (size_t i = 0; i < filteredData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-6f); + BOOST_REQUIRE_EQUAL(bf.aOrder(), bf.bOrder()); + test_coeffs(lpACoeffRes, lpBCoeffRes, bf); + test_results(lpResults, data, bf); } -BOOST_FIXTURE_TEST_CASE(BUTTERWORTH_FILTER_DOUBLE, System) +BOOST_FIXTURE_TEST_CASE(BUTTERWORTH_LP_FILTER_DOUBLE, System) { auto bf = fratio::Butterworthd(order, fc, fs); - - std::vector filteredData; - fratio::vectX_t aCoeff, bCoeff; - bf.getCoeffs(aCoeff, bCoeff); - - BOOST_REQUIRE_EQUAL(aCoeff.size(), aCoeffRes.size()); - BOOST_REQUIRE_EQUAL(bCoeff.size(), bCoeffRes.size()); - BOOST_REQUIRE_EQUAL(aCoeff.size(), bCoeffRes.size()); - - for (Eigen::Index i = 0; i < aCoeff.size(); ++i) { - BOOST_CHECK_SMALL(std::abs(aCoeff(i) - aCoeffRes(i)), 1e-14); - BOOST_CHECK_SMALL(std::abs(bCoeff(i) - bCoeffRes(i)), 1e-14); - } - - for (Eigen::Index i = 0; i < data.size(); ++i) - filteredData.push_back(bf.stepFilter(data(i))); - - for (size_t i = 0; i < filteredData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-14); - - bf.resetFilter(); - Eigen::VectorXd fData = bf.filter(data); - for (Eigen::Index i = 0; i < fData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(fData(i) - results(i)), 1e-14); - - auto bf2 = fratio::Butterworthd(); - - bf2.setFilterParameters(order, fc, fs); - filteredData.clear(); - for (Eigen::Index i = 0; i < data.size(); ++i) - filteredData.push_back(bf2.stepFilter(data(i))); - - for (size_t i = 0; i < filteredData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-14); + BOOST_REQUIRE_EQUAL(bf.aOrder(), bf.bOrder()); + test_coeffs(lpACoeffRes, lpBCoeffRes, bf); + test_results(lpResults, data, bf); +} + +BOOST_FIXTURE_TEST_CASE(BUTTERWORTH_HP_FILTER_FLOAT, System) +{ + auto bf = fratio::Butterworthf(order, fc, fs, fratio::Butterworthf::Type::HighPass); + BOOST_REQUIRE_EQUAL(bf.aOrder(), bf.bOrder()); + test_coeffs(hpACoeffRes, hpBCoeffRes, bf); + test_results(hpResults, data, bf); +} + +BOOST_FIXTURE_TEST_CASE(BUTTERWORTH_HP_FILTER_DOUBLE, System) +{ + auto bf = fratio::Butterworthd(order, fc, fs, fratio::Butterworthd::Type::HighPass); + BOOST_REQUIRE_EQUAL(bf.aOrder(), bf.bOrder()); + test_coeffs(hpACoeffRes, hpBCoeffRes, bf); + test_results(hpResults, data, bf); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0e1f8b4..fb4fda6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -24,4 +24,4 @@ addTest(GenericFilterTests) addTest(polynome_functions_tests) addTest(DigitalFilterTests) addTest(MovingAverageFilterTests) -# addTest(ButterWorthFilterTests) \ No newline at end of file +addTest(ButterWorthFilterTests) \ No newline at end of file diff --git a/tests/test_functions.h b/tests/test_functions.h index b8cef7a..fc0df01 100644 --- a/tests/test_functions.h +++ b/tests/test_functions.h @@ -12,9 +12,9 @@ void test_coeffs(const fratio::vectX_t& aCoeff, const fratio::vectX_t& bCo 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); + BOOST_REQUIRE_SMALL(std::abs(aCoeff(i) - faCoeff(i)), std::numeric_limits::epsilon() * 10); for (Eigen::Index i = 0; i < fbCoeff.size(); ++i) - BOOST_REQUIRE_SMALL(std::abs(bCoeff(i) - fbCoeff(i)), std::numeric_limits::epsilon() * 2); + BOOST_REQUIRE_SMALL(std::abs(bCoeff(i) - fbCoeff(i)), std::numeric_limits::epsilon() * 10); } template @@ -26,10 +26,10 @@ void test_results(const fratio::vectX_t& results, const fratio::vectX_t& d 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); + BOOST_REQUIRE_SMALL(std::abs(filteredData(i) - results(i)), std::numeric_limits::epsilon() * 1000); 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); + BOOST_REQUIRE_SMALL(std::abs(filteredData(i) - results(i)), std::numeric_limits::epsilon() * 1000); } \ No newline at end of file