From 3a6bc791ff81adf8d99befd19d4216459426c830 Mon Sep 17 00:00:00 2001 From: Vincent Samy Date: Fri, 14 Dec 2018 20:30:44 +0900 Subject: [PATCH] Almost updated all merging errors. --- include/BilinearTransform.h | 11 ++- include/Butterworth.h | 3 +- include/Butterworth.inl | 145 ----------------------------- include/Butterworth.tpp | 102 ++++++++++++++------ include/CMakeLists.txt | 2 + include/DigitalFilter.h | 9 +- include/GenericFilter.h | 6 +- include/GenericFilter.inl | 95 ------------------- include/GenericFilter.tpp | 54 +++-------- include/MovingAverage.h | 8 +- include/fratio.h | 24 ++--- tests/CMakeLists.txt | 4 +- tests/DigitalFilterTests.cpp | 33 +++---- tests/GenericFilterTests.cpp | 22 +++-- tests/MovingAverageFilterTests.cpp | 24 ++--- 15 files changed, 159 insertions(+), 383 deletions(-) delete mode 100644 include/Butterworth.inl delete mode 100644 include/GenericFilter.inl diff --git a/include/BilinearTransform.h b/include/BilinearTransform.h index daf689f..5ba8477 100644 --- a/include/BilinearTransform.h +++ b/include/BilinearTransform.h @@ -1,6 +1,7 @@ #pragma once -#include +#include "type_checks.h" +#include "typedefs.h" namespace fratio { @@ -10,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 std::vector& sPlanePoles, std::vector& zPlanePoles); + static void SToZ(SubType fs, const Eigen::VectorX& sPlanePoles, Eigen::VectorX& zPlanePoles); // Can be optimized static void ZToS(SubType fs, const T& zPlanePole, T& sPlanePole); - static void ZToS(SubType fs, const std::vector& zPlanePoles, std::vector& sPlanePoles); + static void ZToS(SubType fs, const Eigen::VectorX& zPlanePoles, Eigen::VectorX& sPlanePoles); // Can be optimized }; template @@ -23,7 +24,7 @@ void BilinearTransform::SToZ(SubType fs, const T& sPlanePole, T& zPlanePole) } template -void BilinearTransform::SToZ(SubType fs, const std::vector& sPlanePoles, std::vector& zPlanePoles) +void BilinearTransform::SToZ(SubType fs, const Eigen::VectorX& sPlanePoles, Eigen::VectorX& zPlanePoles) { assert(sPlanePoles.size() == zPlanePoles.size()); for (size_t k = 0; k < sPlanePoles.size(); ++k) @@ -38,7 +39,7 @@ void BilinearTransform::ZToS(SubType fs, const T& zPlanePole, T& sPlanePole) } template -void BilinearTransform::ZToS(SubType fs, const std::vector& zPlanePoles, std::vector& sPlanePoles) +void BilinearTransform::ZToS(SubType fs, const Eigen::VectorX& zPlanePoles, Eigen::VectorX& sPlanePoles) { assert(zPlanePoles.size() == sPlanePoles.size()); for (size_t k = 0; k < sPlanePoles.size(); ++k) diff --git a/include/Butterworth.h b/include/Butterworth.h index 7689534..d7bedf9 100644 --- a/include/Butterworth.h +++ b/include/Butterworth.h @@ -2,6 +2,7 @@ #include "GenericFilter.h" #include "typedefs.h" +#include #include namespace fratio { @@ -31,7 +32,7 @@ private: void computeDigitalRep(); void updateCoeffSize(); std::complex generateAnalogPole(T fpw, size_t k); - std::vector> generateAnalogZeros(); + Eigen::VectorX> generateAnalogZeros(); void scaleAmplitude(); private: diff --git a/include/Butterworth.inl b/include/Butterworth.inl deleted file mode 100644 index f97971d..0000000 --- a/include/Butterworth.inl +++ /dev/null @@ -1,145 +0,0 @@ -#include "BilinearTransform.h" -#include "polynome_functions.h" -#include -#include - -namespace fratio { - -template -Butterworth::Butterworth(Type type) - : m_type(type) -{ -} - -template -Butterworth::Butterworth(size_t order, T fc, T fs, Type type) - : m_type(type) -{ - initialize(order, fc, fs); -} - -template -void Butterworth::setFilterParameters(size_t order, T fc, T fs) -{ - initialize(order, fc, fs); -} - -template -void Butterworth::initialize(size_t order, T fc, T fs) -{ - if (m_fc > m_fs / 2.) { - std::stringstream ss; - ss << "The cut-off-frequency must be inferior to the sampling frequency" - << "\n Given cut-off-frequency is " << m_fc - << "\n Given sample frequency is " << m_fs; - throw std::runtime_error(ss.str()); - } - - m_order = order; - m_fc = fc; - m_fs = fs; - updateCoeffSize(); - computeDigitalRep(); -} - -template -void Butterworth::computeDigitalRep() -{ - // Continuous pre-warped frequency - T fpw = (m_fs / PI) * std::tan(PI * m_fc / m_fs); - - // Compute poles - std::complex analogPole; - std::vector> poles(m_order); - for (size_t k = 1; k <= m_order; ++k) { - analogPole = generateAnalogPole(fpw, k); - BilinearTransform>::SToZ(m_fs, analogPole, poles[k - 1]); - } - - std::vector> zeros = generateAnalogZeros(); - std::vector> a = VietaAlgo>::polyCoeffFromRoot(poles); - std::vector> b = VietaAlgo>::polyCoeffFromRoot(zeros); - for (size_t i = 0; i < m_order + 1; ++i) { - m_aCoeff[i] = a[i].real(); - m_bCoeff[i] = b[i].real(); - } - - scaleAmplitude(); - checkCoeff(m_aCoeff, m_bCoeff); -} - -template -void Butterworth::updateCoeffSize() -{ - m_aCoeff.resize(m_order + 1); - m_bCoeff.resize(m_order + 1); - resetFilter(); -} - -template -std::complex Butterworth::generateAnalogPole(T fpw, size_t k) -{ - T scaleFactor = 2 * PI * fpw; - - auto thetaK = [pi = PI, order = m_order](size_t k) -> T { - return (2 * k - 1) * pi / (2 * order); - }; - - std::complex analogPole(-std::sin(thetaK(k)), std::cos(thetaK(k))); - switch (m_type) { - case Type::HighPass: - return scaleFactor / analogPole; - - case Type::LowPass: - default: - return scaleFactor * analogPole; - } -} - -template -std::vector> Butterworth::generateAnalogZeros() -{ - switch (m_type) { - case Type::HighPass: - return std::vector>(m_order, std::complex(1)); - - case Type::LowPass: - default: - return std::vector>(m_order, std::complex(-1)); - } -} - -template -void Butterworth::scaleAmplitude() -{ - T scale = 0; - T sumB = 0; - - switch (m_type) { - case Type::HighPass: - for (size_t i = 0; i < m_order + 1; ++i) { - if (i % 2 == 0) { - scale += m_aCoeff[i]; - sumB += m_bCoeff[i]; - } else { - scale -= m_aCoeff[i]; - sumB -= m_bCoeff[i]; - } - } - break; - - case Type::LowPass: - default: - for (size_t i = 0; i < m_order + 1; ++i) { - scale += m_aCoeff[i]; - sumB += m_bCoeff[i]; - } - break; - } - - scale /= sumB; - for (auto& b : m_bCoeff) - b *= scale; -} - -} // namespace fratio \ No newline at end of file diff --git a/include/Butterworth.tpp b/include/Butterworth.tpp index 413e091..c374189 100644 --- a/include/Butterworth.tpp +++ b/include/Butterworth.tpp @@ -1,6 +1,5 @@ +#include "BilinearTransform.h" #include "polynome_functions.h" -#include -#include namespace fratio { @@ -34,7 +33,6 @@ void Butterworth::initialize(size_t order, T fc, T fs) m_order = order; m_fc = fc; m_fs = fs; - m_poles.resize(order); updateCoeffSize(); computeDigitalRep(); } @@ -42,39 +40,27 @@ void Butterworth::initialize(size_t order, T fc, T fs) template void Butterworth::computeDigitalRep() { - T pi = static_cast(M_PI); // Continuous pre-warped frequency - T fpw = (m_fs / pi) * std::tan(pi * m_fc / m_fs); - T scaleFactor = T(2) * pi * fpw; - - auto thetaK = [pi, order = m_order](size_t k) -> T { - return (T(2) * k - T(1)) * pi / (T(2) * order); - }; + T fpw = (m_fs / PI) * std::tan(PI * m_fc / m_fs); // Compute poles - std::complex scalePole; + std::complex analogPole; + Eigen::VectorX> poles(m_order); for (size_t k = 1; k <= m_order; ++k) { - scalePole = scaleFactor * std::complex(-std::sin(thetaK(k)), std::cos(thetaK(k))); - scalePole /= T(2) * m_fs; - m_poles(k - 1) = (T(1) + scalePole) / (T(1) - scalePole); + analogPole = generateAnalogPole(fpw, k); + BilinearTransform>::SToZ(m_fs, analogPole, poles[k - 1]); } - Eigen::VectorX> numPoles = Eigen::VectorX::Constant(m_order, std::complex(-1)); - Eigen::VectorX> a = VietaAlgo>::polyCoeffFromRoot(m_poles); - Eigen::VectorX> b = VietaAlgo>::polyCoeffFromRoot(numPoles); - T norm = 0; - T sumB = 0; + Eigen::VectorX> zeros = generateAnalogZeros(); + Eigen::VectorX> a = VietaAlgo>::polyCoeffFromRoot(poles); + Eigen::VectorX> b = VietaAlgo>::polyCoeffFromRoot(zeros); for (size_t i = 0; i < m_order + 1; ++i) { - m_aCoeff(i) = a(i).real(); - m_bCoeff(i) = b(i).real(); - norm += m_aCoeff(i); - sumB += m_bCoeff(i); + m_aCoeff[i] = a[i].real(); + m_bCoeff[i] = b[i].real(); } - norm /= sumB; - m_bCoeff *= norm; - - checkCoeffs(m_aCoeff, m_bCoeff); + scaleAmplitude(); + checkCoeff(m_aCoeff, m_bCoeff); } template @@ -85,4 +71,66 @@ void Butterworth::updateCoeffSize() resetFilter(); } +template +std::complex Butterworth::generateAnalogPole(T fpw, size_t k) +{ + T scaleFactor = 2 * PI * fpw; + + auto thetaK = [pi = PI, order = m_order](size_t k) -> T { + return (2 * k - 1) * pi / (2 * order); + }; + + std::complex analogPole(-std::sin(thetaK(k)), std::cos(thetaK(k))); + switch (m_type) { + case Type::HighPass: + return scaleFactor / analogPole; + + case Type::LowPass: + default: + return scaleFactor * analogPole; + } +} + +template +Eigen::VectorX> Butterworth::generateAnalogZeros() +{ + switch (m_type) { + case Type::HighPass: + return Eigen::VectorX>::Constant(m_order, std::complex(1)); + + case Type::LowPass: + default: + return Eigen::VectorX>::Constant(m_order, std::complex(-1)); + } +} + +template +void Butterworth::scaleAmplitude() +{ + T scale = 0; + T sumB = 0; + + switch (m_type) { + case Type::HighPass: + for (size_t i = 0; i < m_order + 1; ++i) { + if (i % 2 == 0) { + scale += m_aCoeff(i); + sumB += m_bCoeff(i); + } else { + scale -= m_aCoeff(i); + sumB -= m_bCoeff(i); + } + } + break; + + case Type::LowPass: + default: + scale = m_aCoeff.sum(); + sumB = m_bCoeff.sum(); + break; + } + + m_bCoeff *= scale / sumB; +} + } // namespace fratio \ No newline at end of file diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 94ab49f..0b8232c 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1,9 +1,11 @@ set(HEADERS + BilinearTransform.h Butterworth.h DigitalFilter.h GenericFilter.h MovingAverage.h polynome_functions.h + typedefs.h ) add_library(${PROJECT_NAME} INTERFACE) diff --git a/include/DigitalFilter.h b/include/DigitalFilter.h index 0aec5c1..2c4606c 100644 --- a/include/DigitalFilter.h +++ b/include/DigitalFilter.h @@ -2,7 +2,6 @@ #include "GenericFilter.h" #include "typedefs.h" -#include namespace fratio { @@ -10,10 +9,6 @@ template 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) { @@ -23,6 +18,4 @@ public: size_t bOrder() const noexcept { return m_bCoeff.size(); } }; -} // namespace fratio - -#include "DigitalFilter.tpp" \ No newline at end of file +} // namespace fratio \ No newline at end of file diff --git a/include/GenericFilter.h b/include/GenericFilter.h index 787effe..90919a4 100644 --- a/include/GenericFilter.h +++ b/include/GenericFilter.h @@ -4,7 +4,6 @@ #include "typedefs.h" #include #include -#include namespace fratio { @@ -22,9 +21,7 @@ public: bool getFilterResults(Eigen::Ref> results, const Eigen::VectorX& data); void resetFilter(); - 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; } @@ -34,8 +31,7 @@ protected: virtual ~GenericFilter() = default; void normalizeCoeffs(); - template - bool checkCoeffs(const T2& aCoeff, const T2& bCoeff); + bool checkCoeffs(const Eigen::VectorX& aCoeff, const Eigen::VectorX& bCoeff); protected: FilterStatus m_status; diff --git a/include/GenericFilter.inl b/include/GenericFilter.inl deleted file mode 100644 index b3f9490..0000000 --- a/include/GenericFilter.inl +++ /dev/null @@ -1,95 +0,0 @@ -namespace fratio { - -// Public functions - -template -T GenericFilter::stepFilter(T data) -{ - // Slide data - for (auto rit1 = m_rawData.rbegin(), rit2 = m_rawData.rbegin() + 1; rit2 != m_rawData.rend(); ++rit1, ++rit2) - *rit1 = *rit2; - for (auto rit1 = m_filteredData.rbegin(), rit2 = m_filteredData.rbegin() + 1; rit2 != m_filteredData.rend(); ++rit1, ++rit2) - *rit1 = *rit2; - - T filtData = 0.; - m_rawData[0] = data; - - for (size_t k = 0; k < m_bCoeff.size(); ++k) - filtData += m_bCoeff[k] * m_rawData[k]; - for (size_t k = 1; k < m_aCoeff.size(); ++k) - filtData -= m_aCoeff[k] * m_filteredData[k]; - - m_filteredData[0] = filtData; - - return filtData; -} - -template -std::vector GenericFilter::filter(const std::vector& data) -{ - std::vector results; - results.reserve(data.size()); - - for (T d : data) - results.emplace_back(stepFilter(d)); - - return results; -} - -template -void GenericFilter::resetFilter() -{ - m_filteredData.assign(m_aCoeff.size(), 0); - m_rawData.assign(m_bCoeff.size(), 0); -} - -template -void GenericFilter::getCoeff(std::vector& aCoeff, std::vector& bCoeff) const noexcept -{ - aCoeff = m_aCoeff; - bCoeff = m_bCoeff; -} - -// Protected functions - -template -GenericFilter::GenericFilter(const std::vector& aCoeff, const std::vector& bCoeff) - : m_aCoeff(aCoeff) - , m_bCoeff(bCoeff) - , m_filteredData(aCoeff.size(), 0) - , m_rawData(bCoeff.size(), 0) -{ - checkCoeff(aCoeff, bCoeff); - normalize(); -} - -template -void GenericFilter::normalize() -{ - T a0 = m_aCoeff.front(); - if (std::abs(a0) < 1e-8) // Divide by zero - throw std::invalid_argument("By filtering value for coefficient a0. Should be superior to 1e-8"); - - if (std::abs(a0 - 1) < 1e-8) - return; - - for (T& a : m_aCoeff) - a /= a0; - for (T& b : m_bCoeff) - b /= a0; -} - -template -void GenericFilter::checkCoeff(const std::vector& aCoeff, const std::vector& bCoeff) -{ - std::stringstream err; - if (aCoeff.size() == 0) - err << "The size of coefficient 'a' should greater than 0\n"; - if (bCoeff.size() == 0) - err << "The size of coefficient 'b' should greater than 0\n"; - - if (err.str().size() > 0) - throw std::runtime_error(err.str()); -} - -} // namespace fratio \ No newline at end of file diff --git a/include/GenericFilter.tpp b/include/GenericFilter.tpp index fb922cf..da10af7 100644 --- a/include/GenericFilter.tpp +++ b/include/GenericFilter.tpp @@ -32,10 +32,8 @@ T GenericFilter::stepFilter(const T& data) assert(m_status == FilterStatus::READY); // Slide data (can't use SIMD, but should be small) - for (auto rit1 = m_rawData.rbegin(), rit2 = m_rawData.rbegin() + 1; rit2 != m_rawData.rend(); ++rit1, ++rit2) - *rit1 = *rit2; - for (auto rit1 = m_filteredData.rbegin(), rit2 = m_filteredData.rbegin() + 1; rit2 != m_filteredData.rend(); ++rit1, ++rit2) - *rit1 = *rit2; + 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_rawData[0] = data; m_filteredData[0] = m_bCoeff.dot(m_rawData) - m_aCoeff.dot(m_filteredData); @@ -59,9 +57,8 @@ bool GenericFilter::getFilterResults(Eigen::Ref> results, c if (results.size() != data.size()) return false; - T* res = results.data(); - for (T d : data) - *(res++) = stepFilter(d); + for (Eigen::Index i = 0; i < data.size(); ++i) + results(i) = stepFilter(data(i)); return true; } @@ -74,20 +71,7 @@ void GenericFilter::resetFilter() } template -bool GenericFilter::setCoeffs(const std::vector& aCoeff, const std::vector& bCoeff) -{ - if (!checkCoeffs(aCoeff, bCoeff)) - return false; - - m_aCoeff = Eigen::Map>(aCoeff.data(), aCoeff.size()); - m_bCoeff = Eigen::Map>(bCoeff.data(), bCoeff.size()); - resetFilter(); - normalizeCoeffs(); - return true; -} - -template -void GenericFilter::setCoeffs(const Eigen::VectorX& aCoeff, const Eigen::VectorX& bCoeff) +bool GenericFilter::setCoeffs(const Eigen::VectorX& aCoeff, const Eigen::VectorX& bCoeff) { if (!checkCoeffs(aCoeff, bCoeff)) return false; @@ -99,13 +83,6 @@ void GenericFilter::setCoeffs(const Eigen::VectorX& aCoeff, const Eigen::V return true; } -template -void GenericFilter::getCoeffs(std::vector& aCoeff, std::vector& bCoeff) const -{ - aCoeff.assign(m_aCoeff.data(), m_aCoeff.data() + m_aCoeff.size()); - bCoeff.assign(m_bCoeff.data(), m_bCoeff.data() + m_bCoeff.size()); -} - template void GenericFilter::getCoeffs(Eigen::Ref> aCoeff, Eigen::Ref> bCoeff) const { @@ -122,7 +99,7 @@ GenericFilter::GenericFilter(const Eigen::VectorX& aCoeff, const Eigen::Ve , m_filteredData(aCoeff.size()) , m_rawData(bCoeff.size()) { - if(!checkCoeffs(aCoeff, bCoeff)) + if (!checkCoeffs(aCoeff, bCoeff)) return; resetFilter(); @@ -143,24 +120,21 @@ void GenericFilter::normalizeCoeffs() } template -template -bool GenericFilter::checkCoeffs(const T2& aCoeff, const T2& bCoeff) +bool GenericFilter::checkCoeffs(const Eigen::VectorX& aCoeff, const Eigen::VectorX& bCoeff) { - using namespace FilterStatus; - - m_status = NONE; + m_status = FilterStatus::NONE; if (aCoeff.size() == 0) - m_status = A_COEFF_MISSING; + m_status = FilterStatus::A_COEFF_MISSING; else if (std::abs(aCoeff[0]) < std::numeric_limits::epsilon()) - m_status = BAD_A_COEFF; + m_status = FilterStatus::BAD_A_COEFF; if (bCoeff.size() == 0) - m_status = (m_status == A_COEFF_MISSING ? ALL_COEFF_MISSING : B_COEFF_MISSING); + m_status = (m_status == FilterStatus::A_COEFF_MISSING ? FilterStatus::ALL_COEFF_MISSING : FilterStatus::B_COEFF_MISSING); - if (m_status == NONE) - m_status = READY; + if (m_status == FilterStatus::NONE) + m_status = FilterStatus::READY; - return m_status == READY; + return m_status == FilterStatus::READY; } } // namespace fratio \ No newline at end of file diff --git a/include/MovingAverage.h b/include/MovingAverage.h index 9ebcb12..b904bd7 100644 --- a/include/MovingAverage.h +++ b/include/MovingAverage.h @@ -10,13 +10,7 @@ class MovingAverage : public DigitalFilter { public: MovingAverage() = default; MovingAverage(size_t windowSize) - : 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(); } - : DigitalFilter(Eigen::VectorX::Constant(1, T(1)), Eigen::VectorX::Constant(windowSize, T(1) / windowSize))) + : DigitalFilter(Eigen::VectorX::Constant(1, T(1)), Eigen::VectorX::Constant(windowSize, T(1) / windowSize)) { } diff --git a/include/fratio.h b/include/fratio.h index 8a98c23..5e92649 100644 --- a/include/fratio.h +++ b/include/fratio.h @@ -15,18 +15,18 @@ using MovingAveraged = MovingAverage; using Butterworthf = Butterworth; using Butterworthd = Butterworth; -// Polynome helper functions -using VietaAlgof = VietaAlgo; -using VietaAlgod = VietaAlgo; -using VietaAlgoi = VietaAlgo; -using VietaAlgocf = VietaAlgo>; -using VietaAlgocd = VietaAlgo>; -using VietaAlgoci = VietaAlgo>; +// // Polynome helper functions +// using VietaAlgof = VietaAlgo; +// using VietaAlgod = VietaAlgo; +// using VietaAlgoi = VietaAlgo; +// using VietaAlgocf = VietaAlgo>; +// using VietaAlgocd = VietaAlgo>; +// using VietaAlgoci = VietaAlgo>; -// Bilinear transformation functions -using BilinearTransformf = BilinearTransform; -using BilinearTransformd = BilinearTransform; -using BilinearTransformcf = BilinearTransform>; -using BilinearTransformcd = BilinearTransform>; +// // Bilinear transformation functions +// using BilinearTransformf = BilinearTransform; +// using BilinearTransformd = BilinearTransform; +// using BilinearTransformcf = BilinearTransform>; +// using BilinearTransformcd = BilinearTransform>; } // namespace fratio \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 77902d3..c83b3ea 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(ButterWorthFilterTests) addTest(GenericFilterTests) addTest(DigitalFilterTests) addTest(MovingAverageFilterTests) -addTest(polynome_functions_tests) \ No newline at end of file +addTest(ButterWorthFilterTests) +# addTest(polynome_functions_tests) \ No newline at end of file diff --git a/tests/DigitalFilterTests.cpp b/tests/DigitalFilterTests.cpp index 71dd2d3..4ad8fc5 100644 --- a/tests/DigitalFilterTests.cpp +++ b/tests/DigitalFilterTests.cpp @@ -1,6 +1,7 @@ #define BOOST_TEST_MODULE DigitalFilterTests #include "fratio.h" +#include "typedefs.h" #include "warning_macro.h" #include @@ -8,10 +9,10 @@ DISABLE_CONVERSION_WARNING_BEGIN template struct System { - std::vector data = { 1, 2, 3, 4 }; - std::vector aCoeff = { 1, -0.99993717 }; - std::vector bCoeff = { 0.99996859, -0.99996859 }; - std::vector results = { 0.99996859, 1.999874351973491, 2.999717289867956, 3.999497407630634 }; + Eigen::VectorX data = (Eigen::VectorX(4) << 1, 2, 3, 4).finished(); + Eigen::VectorX aCoeff = (Eigen::VectorX(4) << 1, -0.99993717).finished(); + Eigen::VectorX bCoeff = (Eigen::VectorX(4) << 0.99996859, -0.99996859).finished(); + Eigen::VectorX results = (Eigen::VectorX(4) << 0.99996859, 1.999874351973491, 2.999717289867956, 3.999497407630634).finished(); }; DISABLE_CONVERSION_WARNING_END @@ -24,16 +25,16 @@ BOOST_FIXTURE_TEST_CASE(DIGITAL_FILTER_FLOAT, System) std::vector filteredData; - for (float d : data) - filteredData.push_back(df.stepFilter(d)); + 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); + BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-6f); df.resetFilter(); - filteredData = df.filter(data); - for (size_t i = 0; i < filteredData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(filteredData[i] - results[i]), 1e-6f); + 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); } BOOST_FIXTURE_TEST_CASE(DIGITAL_FILTER_DOUBLE, System) @@ -44,14 +45,14 @@ BOOST_FIXTURE_TEST_CASE(DIGITAL_FILTER_DOUBLE, System) std::vector filteredData; - for (double d : data) - filteredData.push_back(df.stepFilter(d)); + 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); + BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-14); df.resetFilter(); - filteredData = df.filter(data); - for (size_t i = 0; i < filteredData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(filteredData[i] - results[i]), 1e-14); + 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); } diff --git a/tests/GenericFilterTests.cpp b/tests/GenericFilterTests.cpp index 63f7af0..2aa6080 100644 --- a/tests/GenericFilterTests.cpp +++ b/tests/GenericFilterTests.cpp @@ -1,16 +1,22 @@ #define BOOST_TEST_MODULE GenericFilterTests #include "fratio.h" +#include "typedefs.h" #include +#include BOOST_AUTO_TEST_CASE(FilterThrows) { - BOOST_REQUIRE_THROW(fratio::DigitalFilterd({}, { 1, 2 }), std::runtime_error); - BOOST_REQUIRE_THROW(fratio::DigitalFilterd({ 1, 2 }, {}), std::runtime_error); - BOOST_REQUIRE_THROW(fratio::DigitalFilterd({ 0 }, { 1 }), std::invalid_argument); - - auto df = fratio::DigitalFilterd(); - BOOST_REQUIRE_THROW(df.setCoeff({}, { 1, 2 }), std::runtime_error); - BOOST_REQUIRE_THROW(df.setCoeff({ 1, 2 }, {}), std::runtime_error); - BOOST_REQUIRE_THROW(df.setCoeff({ 0 }, { 1 }), std::invalid_argument); + auto dfd = fratio::DigitalFilterd(Eigen::VectorXd(), Eigen::VectorXd::Constant(2, 0)); + BOOST_REQUIRE(dfd.status() == fratio::FilterStatus::A_COEFF_MISSING); + dfd = fratio::DigitalFilterd(Eigen::VectorXd::Constant(2, 1), Eigen::VectorXd()); + BOOST_REQUIRE(dfd.status() == fratio::FilterStatus::B_COEFF_MISSING); + dfd = fratio::DigitalFilterd(Eigen::VectorXd(), Eigen::VectorXd()); + BOOST_REQUIRE(dfd.status() == fratio::FilterStatus::ALL_COEFF_MISSING); + dfd = fratio::DigitalFilterd(Eigen::VectorXd::Constant(2, 0), Eigen::VectorXd::Constant(2, 0)); + BOOST_REQUIRE(dfd.status() == fratio::FilterStatus::BAD_A_COEFF); + dfd = fratio::DigitalFilterd(); + BOOST_REQUIRE(dfd.status() == fratio::FilterStatus::NONE); + dfd = fratio::DigitalFilterd(Eigen::VectorXd::Constant(2, 1), Eigen::VectorXd::Constant(2, 0)); + BOOST_REQUIRE(dfd.status() == fratio::FilterStatus::READY); } diff --git a/tests/MovingAverageFilterTests.cpp b/tests/MovingAverageFilterTests.cpp index 3c55388..d9a501e 100644 --- a/tests/MovingAverageFilterTests.cpp +++ b/tests/MovingAverageFilterTests.cpp @@ -5,39 +5,39 @@ template struct System { - std::vector data = { 1, 2, 3, 4, 5, 6 }; + Eigen::VectorX data = (Eigen::VectorX(6) << 1, 2, 3, 4, 5, 6).finished(); size_t windowSize = 4; - std::vector results = { 0.25, 0.75, 1.5, 2.5, 3.5, 4.5 }; + Eigen::VectorX results = (Eigen::VectorX(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 (float d : data) - filteredData.push_back(maf.stepFilter(d)); + 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(); - filteredData = maf.filter(data); - for (size_t i = 0; i < filteredData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(filteredData[i] - results[i]), 1e-6f); + 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); } BOOST_FIXTURE_TEST_CASE(MOVING_AVERAGE_DOUBLE, System) { auto maf = fratio::MovingAveraged(windowSize); std::vector filteredData; - for (double d : data) - filteredData.push_back(maf.stepFilter(d)); + 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(); - filteredData = maf.filter(data); - for (size_t i = 0; i < filteredData.size(); ++i) - BOOST_CHECK_SMALL(std::abs(filteredData[i] - results[i]), 1e-14); + 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); }