kopia lustrzana https://github.com/vsamy/DiFipp
Compilation pass.
rodzic
3a6bc791ff
commit
d55ee89a7d
|
@ -11,9 +11,9 @@ struct BilinearTransform {
|
|||
static_assert(std::is_floating_point<SubType>::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<T>& sPlanePoles, Eigen::VectorX<T>& zPlanePoles); // Can be optimized
|
||||
static void SToZ(SubType fs, const Eigen::VectorX<T>& sPlanePoles, Eigen::Ref<Eigen::VectorX<T>>& zPlanePoles); // Can be optimized
|
||||
static void ZToS(SubType fs, const T& zPlanePole, T& sPlanePole);
|
||||
static void ZToS(SubType fs, const Eigen::VectorX<T>& zPlanePoles, Eigen::VectorX<T>& sPlanePoles); // Can be optimized
|
||||
static void ZToS(SubType fs, const Eigen::VectorX<T>& zPlanePoles, Eigen::Ref<Eigen::VectorX<T>>& sPlanePoles); // Can be optimized
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -24,11 +24,11 @@ void BilinearTransform<T>::SToZ(SubType fs, const T& sPlanePole, T& zPlanePole)
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void BilinearTransform<T>::SToZ(SubType fs, const Eigen::VectorX<T>& sPlanePoles, Eigen::VectorX<T>& zPlanePoles)
|
||||
void BilinearTransform<T>::SToZ(SubType fs, const Eigen::VectorX<T>& sPlanePoles, Eigen::Ref<Eigen::VectorX<T>>& zPlanePoles)
|
||||
{
|
||||
assert(sPlanePoles.size() == zPlanePoles.size());
|
||||
for (size_t k = 0; k < sPlanePoles.size(); ++k)
|
||||
SToZ(fs, sPlanePoles[k], zPlanePoles[k]);
|
||||
for (Eigen::Index k = 0; k < sPlanePoles.size(); ++k)
|
||||
SToZ(fs, sPlanePoles(k), zPlanePoles(k));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -39,11 +39,11 @@ void BilinearTransform<T>::ZToS(SubType fs, const T& zPlanePole, T& sPlanePole)
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void BilinearTransform<T>::ZToS(SubType fs, const Eigen::VectorX<T>& zPlanePoles, Eigen::VectorX<T>& sPlanePoles)
|
||||
void BilinearTransform<T>::ZToS(SubType fs, const Eigen::VectorX<T>& zPlanePoles, Eigen::Ref<Eigen::VectorX<T>>& sPlanePoles)
|
||||
{
|
||||
assert(zPlanePoles.size() == sPlanePoles.size());
|
||||
for (size_t k = 0; k < sPlanePoles.size(); ++k)
|
||||
ZToS(fs, zPlanePoles[k], sPlanePoles[k]);
|
||||
for (Eigen::Index k = 0; k < sPlanePoles.size(); ++k)
|
||||
ZToS(fs, zPlanePoles(k), sPlanePoles(k));
|
||||
}
|
||||
|
||||
} // namespace fratio
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "GenericFilter.h"
|
||||
#include "DigitalFilter.h"
|
||||
#include "typedefs.h"
|
||||
#include <cmath>
|
||||
#include <complex>
|
||||
|
@ -23,21 +23,20 @@ public:
|
|||
// static double minimumRequiredFrequency(...);
|
||||
public:
|
||||
Butterworth(Type type = Type::LowPass);
|
||||
Butterworth(size_t order, T fc, T fs, Type type = Type::LowPass);
|
||||
Butterworth(int order, T fc, T fs, Type type = Type::LowPass);
|
||||
|
||||
void setFilterParameters(size_t order, T fc, T fs);
|
||||
void setFilterParameters(int order, T fc, T fs);
|
||||
|
||||
private:
|
||||
void initialize(size_t order, T fc, T fs);
|
||||
void initialize(int order, T fc, T fs);
|
||||
void computeDigitalRep();
|
||||
void updateCoeffSize();
|
||||
std::complex<T> generateAnalogPole(T fpw, size_t k);
|
||||
std::complex<T> generateAnalogPole(T fpw, int k);
|
||||
Eigen::VectorX<std::complex<T>> generateAnalogZeros();
|
||||
void scaleAmplitude();
|
||||
void scaleAmplitude(Eigen::Ref<Eigen::VectorX<T>> aCoeff, Eigen::Ref<Eigen::VectorX<T>> bCoeff);
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
size_t m_order;
|
||||
int m_order;
|
||||
T m_fc;
|
||||
T m_fs;
|
||||
Eigen::VectorX<std::complex<T>> m_poles;
|
||||
|
|
|
@ -10,21 +10,31 @@ Butterworth<T>::Butterworth(Type type)
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
Butterworth<T>::Butterworth(size_t order, T fc, T fs, Type type)
|
||||
Butterworth<T>::Butterworth(int order, T fc, T fs, Type type)
|
||||
: m_type(type)
|
||||
{
|
||||
initialize(order, fc, fs);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Butterworth<T>::setFilterParameters(size_t order, T fc, T fs)
|
||||
void Butterworth<T>::setFilterParameters(int order, T fc, T fs)
|
||||
{
|
||||
initialize(order, fc, fs);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Butterworth<T>::initialize(size_t order, T fc, T fs)
|
||||
void Butterworth<T>::initialize(int order, T fc, T fs)
|
||||
{
|
||||
if (order <= 0) {
|
||||
m_status = FilterStatus::BAD_ORDER_SIZE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fc <= 0 || fs <= 0) {
|
||||
m_status = FilterStatus::BAD_FREQUENCY_VALUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_fc > m_fs / 2.) {
|
||||
m_status = FilterStatus::BAD_CUTOFF_FREQUENCY;
|
||||
return;
|
||||
|
@ -33,8 +43,8 @@ void Butterworth<T>::initialize(size_t order, T fc, T fs)
|
|||
m_order = order;
|
||||
m_fc = fc;
|
||||
m_fs = fs;
|
||||
updateCoeffSize();
|
||||
computeDigitalRep();
|
||||
resetFilter();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -46,37 +56,31 @@ void Butterworth<T>::computeDigitalRep()
|
|||
// Compute poles
|
||||
std::complex<T> analogPole;
|
||||
Eigen::VectorX<std::complex<T>> poles(m_order);
|
||||
for (size_t k = 1; k <= m_order; ++k) {
|
||||
for (int k = 1; k <= m_order; ++k) {
|
||||
analogPole = generateAnalogPole(fpw, k);
|
||||
BilinearTransform<std::complex<T>>::SToZ(m_fs, analogPole, poles[k - 1]);
|
||||
BilinearTransform<std::complex<T>>::SToZ(m_fs, analogPole, poles(k - 1));
|
||||
}
|
||||
|
||||
Eigen::VectorX<std::complex<T>> zeros = generateAnalogZeros();
|
||||
Eigen::VectorX<std::complex<T>> a = VietaAlgo<std::complex<T>>::polyCoeffFromRoot(poles);
|
||||
Eigen::VectorX<std::complex<T>> b = VietaAlgo<std::complex<T>>::polyCoeffFromRoot(zeros);
|
||||
for (size_t i = 0; i < m_order + 1; ++i) {
|
||||
m_aCoeff[i] = a[i].real();
|
||||
m_bCoeff[i] = b[i].real();
|
||||
Eigen::VectorX<T> aCoeff(m_order + 1);
|
||||
Eigen::VectorX<T> bCoeff(m_order + 1);
|
||||
for (int i = 0; i < m_order + 1; ++i) {
|
||||
aCoeff(i) = a(i).real();
|
||||
bCoeff(i) = b(i).real();
|
||||
}
|
||||
|
||||
scaleAmplitude();
|
||||
checkCoeff(m_aCoeff, m_bCoeff);
|
||||
scaleAmplitude(aCoeff, bCoeff);
|
||||
setCoeffs(std::move(aCoeff), std::move(bCoeff));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Butterworth<T>::updateCoeffSize()
|
||||
{
|
||||
m_aCoeff.resize(m_order + 1);
|
||||
m_bCoeff.resize(m_order + 1);
|
||||
resetFilter();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::complex<T> Butterworth<T>::generateAnalogPole(T fpw, size_t k)
|
||||
std::complex<T> Butterworth<T>::generateAnalogPole(T fpw, int k)
|
||||
{
|
||||
T scaleFactor = 2 * PI * fpw;
|
||||
|
||||
auto thetaK = [pi = PI, order = m_order](size_t k) -> T {
|
||||
auto thetaK = [pi = PI, order = m_order](int k) -> T {
|
||||
return (2 * k - 1) * pi / (2 * order);
|
||||
};
|
||||
|
||||
|
@ -105,32 +109,32 @@ Eigen::VectorX<std::complex<T>> Butterworth<T>::generateAnalogZeros()
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void Butterworth<T>::scaleAmplitude()
|
||||
void Butterworth<T>::scaleAmplitude(Eigen::Ref<Eigen::VectorX<T>> aCoeff, Eigen::Ref<Eigen::VectorX<T>> bCoeff)
|
||||
{
|
||||
T scale = 0;
|
||||
T sumB = 0;
|
||||
|
||||
switch (m_type) {
|
||||
case Type::HighPass:
|
||||
for (size_t i = 0; i < m_order + 1; ++i) {
|
||||
for (int i = 0; i < m_order + 1; ++i) {
|
||||
if (i % 2 == 0) {
|
||||
scale += m_aCoeff(i);
|
||||
sumB += m_bCoeff(i);
|
||||
scale += aCoeff(i);
|
||||
sumB += bCoeff(i);
|
||||
} else {
|
||||
scale -= m_aCoeff(i);
|
||||
sumB -= m_bCoeff(i);
|
||||
scale -= aCoeff(i);
|
||||
sumB -= bCoeff(i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Type::LowPass:
|
||||
default:
|
||||
scale = m_aCoeff.sum();
|
||||
sumB = m_bCoeff.sum();
|
||||
scale = aCoeff.sum();
|
||||
sumB = bCoeff.sum();
|
||||
break;
|
||||
}
|
||||
|
||||
m_bCoeff *= scale / sumB;
|
||||
bCoeff *= scale / sumB;
|
||||
}
|
||||
|
||||
} // namespace fratio
|
|
@ -13,9 +13,6 @@ public:
|
|||
: GenericFilter<T>(aCoeff, bCoeff)
|
||||
{
|
||||
}
|
||||
|
||||
size_t aOrder() const noexcept { return m_aCoeff.size(); }
|
||||
size_t bOrder() const noexcept { return m_bCoeff.size(); }
|
||||
};
|
||||
|
||||
} // namespace fratio
|
|
@ -16,14 +16,18 @@ public:
|
|||
|
||||
public:
|
||||
// Careful: Only an assert check for the filter status
|
||||
T stepFilter(const T& data);
|
||||
T stepFilter(const T& data);
|
||||
Eigen::VectorX<T> filter(const Eigen::VectorX<T>& data);
|
||||
bool getFilterResults(Eigen::Ref<Eigen::VectorX<T>> results, const Eigen::VectorX<T>& data);
|
||||
void resetFilter();
|
||||
|
||||
bool setCoeffs(const Eigen::VectorX<T>& aCoeff, const Eigen::VectorX<T>& bCoeff);
|
||||
void getCoeffs(Eigen::Ref<Eigen::VectorX<T>> aCoeff, Eigen::Ref<Eigen::VectorX<T>> bCoeff) const;
|
||||
template <typename T2>
|
||||
bool setCoeffs(T2&& aCoeff, T2&& bCoeff);
|
||||
|
||||
void getCoeffs(Eigen::VectorX<T>& aCoeff, Eigen::VectorX<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;
|
||||
|
@ -35,10 +39,10 @@ protected:
|
|||
|
||||
protected:
|
||||
FilterStatus m_status;
|
||||
Eigen::VectorX<T> m_aCoeff;
|
||||
Eigen::VectorX<T> m_bCoeff;
|
||||
|
||||
private:
|
||||
Eigen::VectorX<T> m_aCoeff;
|
||||
Eigen::VectorX<T> m_bCoeff;
|
||||
Eigen::VectorX<T> m_filteredData;
|
||||
Eigen::VectorX<T> m_rawData;
|
||||
};
|
||||
|
|
|
@ -11,12 +11,16 @@ std::string GenericFilter<T>::filterStatus(FilterStatus status)
|
|||
return "Filter is uninitialized";
|
||||
case FilterStatus::READY:
|
||||
return "Filter is ready to be used";
|
||||
case FilterStatus::BAD_ORDER_SIZE:
|
||||
return "You try to initialize the filter with an order inferior or equal to 0 (window size for the moving average)";
|
||||
case FilterStatus::ALL_COEFF_MISSING:
|
||||
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:
|
||||
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";
|
||||
case FilterStatus::BAD_CUTOFF_FREQUENCY:
|
||||
return "Filter has a received a bad cut-off frequency. It must be inferior to the sampling frequency";
|
||||
default:
|
||||
|
@ -71,8 +75,11 @@ void GenericFilter<T>::resetFilter()
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
bool GenericFilter<T>::setCoeffs(const Eigen::VectorX<T>& aCoeff, const Eigen::VectorX<T>& bCoeff)
|
||||
template <typename T2>
|
||||
bool GenericFilter<T>::setCoeffs(T2&& aCoeff, T2&& bCoeff)
|
||||
{
|
||||
static_assert(std::is_same_v<T2, Eigen::VectorX<T>>, "The coefficents should be of type Eigen::VectorX<T>");
|
||||
|
||||
if (!checkCoeffs(aCoeff, bCoeff))
|
||||
return false;
|
||||
|
||||
|
@ -84,7 +91,7 @@ bool GenericFilter<T>::setCoeffs(const Eigen::VectorX<T>& aCoeff, const Eigen::V
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void GenericFilter<T>::getCoeffs(Eigen::Ref<Eigen::VectorX<T>> aCoeff, Eigen::Ref<Eigen::VectorX<T>> bCoeff) const
|
||||
void GenericFilter<T>::getCoeffs(Eigen::VectorX<T>& aCoeff, Eigen::VectorX<T>& bCoeff) const
|
||||
{
|
||||
aCoeff = m_aCoeff;
|
||||
bCoeff = m_bCoeff;
|
||||
|
|
|
@ -9,13 +9,21 @@ template <typename T>
|
|||
class MovingAverage : public DigitalFilter<T> {
|
||||
public:
|
||||
MovingAverage() = default;
|
||||
MovingAverage(size_t windowSize)
|
||||
MovingAverage(int windowSize)
|
||||
: DigitalFilter<T>(Eigen::VectorX<T>::Constant(1, T(1)), Eigen::VectorX<T>::Constant(windowSize, T(1) / windowSize))
|
||||
{
|
||||
}
|
||||
|
||||
void setWindowSize(size_t windowSize) { setCoeffs(Eigen::VectorX<T>::Constant(1, T(1)), Eigen::VectorX<T>::Constant(windowSize, T(1) / windowSize)); }
|
||||
size_t windowSize() const noexcept { return bOrder(); }
|
||||
void setWindowSize(int windowSize)
|
||||
{
|
||||
if (windowSize <= 0) {
|
||||
m_status = FilterStatus::BAD_ORDER_SIZE;
|
||||
return;
|
||||
}
|
||||
|
||||
setCoeffs(Eigen::VectorX<T>::Constant(1, T(1)), Eigen::VectorX<T>::Constant(windowSize, T(1) / windowSize));
|
||||
}
|
||||
int windowSize() const noexcept { return bOrder(); }
|
||||
};
|
||||
|
||||
} // namespace fratio
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
// #include "BilinearTransform.h"
|
||||
#include "Butterworth.h"
|
||||
#include "DigitalFilter.h"
|
||||
#include "GenericFilter.h"
|
||||
#include "MovingAverage.h"
|
||||
#include "polynome_functions.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
namespace fratio {
|
||||
|
||||
// Filters
|
||||
using DigitalFilterf = DigitalFilter<float>;
|
||||
using DigitalFilterd = DigitalFilter<double>;
|
||||
using MovingAveragef = MovingAverage<float>;
|
||||
using MovingAveraged = MovingAverage<double>;
|
||||
using Butterworthf = Butterworth<float>;
|
||||
using Butterworthd = Butterworth<double>;
|
||||
|
||||
// Polynome helper functions
|
||||
using VietaAlgof = VietaAlgo<float>;
|
||||
using VietaAlgod = VietaAlgo<double>;
|
||||
using VietaAlgoi = VietaAlgo<int>;
|
||||
using VietaAlgocf = VietaAlgo<std::complex<float>>;
|
||||
using VietaAlgocd = VietaAlgo<std::complex<double>>;
|
||||
using VietaAlgoci = VietaAlgo<std::complex<int>>;
|
||||
|
||||
// Bilinear transformation functions
|
||||
using BilinearTransformf = BilinearTransform<float>;
|
||||
using BilinearTransformd = BilinearTransform<double>;
|
||||
using BilinearTransformcf = BilinearTransform<std::complex<float>>;
|
||||
using BilinearTransformcd = BilinearTransform<std::complex<double>>;
|
||||
|
||||
} // namespace fratio
|
|
@ -1,32 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "Butterworth.h"
|
||||
#include "DigitalFilter.h"
|
||||
#include "MovingAverage.h"
|
||||
#include "polynome_functions.h"
|
||||
|
||||
namespace fratio {
|
||||
|
||||
// Filters
|
||||
using DigitalFilterf = DigitalFilter<float>;
|
||||
using DigitalFilterd = DigitalFilter<double>;
|
||||
using MovingAveragef = MovingAverage<float>;
|
||||
using MovingAveraged = MovingAverage<double>;
|
||||
using Butterworthf = Butterworth<float>;
|
||||
using Butterworthd = Butterworth<double>;
|
||||
|
||||
// // Polynome helper functions
|
||||
// using VietaAlgof = VietaAlgo<float>;
|
||||
// using VietaAlgod = VietaAlgo<double>;
|
||||
// using VietaAlgoi = VietaAlgo<int>;
|
||||
// using VietaAlgocf = VietaAlgo<std::complex<float>>;
|
||||
// using VietaAlgocd = VietaAlgo<std::complex<double>>;
|
||||
// using VietaAlgoci = VietaAlgo<std::complex<int>>;
|
||||
|
||||
// // Bilinear transformation functions
|
||||
// using BilinearTransformf = BilinearTransform<float>;
|
||||
// using BilinearTransformd = BilinearTransform<double>;
|
||||
// using BilinearTransformcf = BilinearTransform<std::complex<float>>;
|
||||
// using BilinearTransformcd = BilinearTransform<std::complex<double>>;
|
||||
|
||||
} // namespace fratio
|
|
@ -19,22 +19,22 @@ Eigen::VectorX<T> VietaAlgo<T>::polyCoeffFromRoot(const Eigen::VectorX<T>& poles
|
|||
{
|
||||
Eigen::VectorX<T> coeffs = Eigen::VectorX<T>::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) {
|
||||
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
|
||||
// size_t pSize = poles.size();
|
||||
// for (size_t k = 1; k < coeffs.size(); ++k)
|
||||
// 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 (size_t k = 1; k < coeffs.size(); ++k) {
|
||||
// for (Eigen::Index k = 1; k < coeffs.size(); ++k) {
|
||||
// coeffs(k) -= sum * coeffs(k - 1);
|
||||
// sum -= poles(k - 1);
|
||||
// }
|
||||
// }
|
||||
|
||||
return coeffs;
|
||||
}
|
||||
|
|
|
@ -15,12 +15,14 @@ enum class FilterStatus {
|
|||
// Generic filter
|
||||
NONE,
|
||||
READY,
|
||||
BAD_ORDER_SIZE,
|
||||
BAD_A_COEFF,
|
||||
A_COEFF_MISSING,
|
||||
B_COEFF_MISSING,
|
||||
ALL_COEFF_MISSING = A_COEFF_MISSING | B_COEFF_MISSING,
|
||||
|
||||
// Butterworth filter
|
||||
BAD_FREQUENCY_VALUE,
|
||||
BAD_CUTOFF_FREQUENCY
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#define BOOST_TEST_MODULE ButterworthFilterTests
|
||||
|
||||
#include "fratio.h"
|
||||
#include "fratio"
|
||||
#include "warning_macro.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
|
@ -8,13 +8,13 @@ DISABLE_CONVERSION_WARNING_BEGIN
|
|||
|
||||
template <typename T>
|
||||
struct System {
|
||||
std::vector<T> data = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
size_t order = 5;
|
||||
Eigen::VectorX<T> data = (Eigen::VectorX<T>(8) << 1, 2, 3, 4, 5, 6, 7, 8).finished();
|
||||
int order = 5;
|
||||
T fc = 10;
|
||||
T fs = 100;
|
||||
std::vector<T> aCoeffRes = { 1.000000000000000, -2.975422109745684, 3.806018119320413, -2.545252868330468, 0.881130075437837, -0.125430622155356 };
|
||||
std::vector<T> bCoeffRes = { 0.001282581078961, 0.006412905394803, 0.012825810789607, 0.012825810789607, 0.006412905394803, 0.001282581078961 };
|
||||
std::vector<T> results = { 0.001282581078961, 0.012794287652606, 0.062686244350084, 0.203933712825708, 0.502244959135609, 1.010304217144175, 1.744652693589064, 2.678087381460197 };
|
||||
Eigen::VectorX<T> aCoeffRes = (Eigen::VectorX<T>(6) << 1.000000000000000, -2.975422109745684, 3.806018119320413, -2.545252868330468, 0.881130075437837, -0.125430622155356).finished();
|
||||
Eigen::VectorX<T> bCoeffRes = (Eigen::VectorX<T>(6) << 0.001282581078961, 0.006412905394803, 0.012825810789607, 0.012825810789607, 0.006412905394803, 0.001282581078961).finished();
|
||||
Eigen::VectorX<T> results = (Eigen::VectorX<T>(8) << 0.001282581078961, 0.012794287652606, 0.062686244350084, 0.203933712825708, 0.502244959135609, 1.010304217144175, 1.744652693589064, 2.678087381460197).finished();
|
||||
};
|
||||
|
||||
DISABLE_CONVERSION_WARNING_END
|
||||
|
@ -23,74 +23,76 @@ BOOST_FIXTURE_TEST_CASE(BUTTERWORTH_FILTER_FLOAT, System<float>)
|
|||
{
|
||||
auto bf = fratio::Butterworthf(order, fc, fs);
|
||||
|
||||
std::vector<float> aCoeff, bCoeff, filteredData;
|
||||
bf.getCoeff(aCoeff, bCoeff);
|
||||
std::vector<float> filteredData;
|
||||
Eigen::VectorX<float> 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 (size_t i = 0; i < aCoeff.size(); ++i) {
|
||||
BOOST_CHECK_SMALL(std::abs(aCoeff[i] - aCoeffRes[i]), 1e-4f);
|
||||
BOOST_CHECK_SMALL(std::abs(bCoeff[i] - bCoeffRes[i]), 1e-4f);
|
||||
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 (float d : data)
|
||||
filteredData.push_back(bf.stepFilter(d));
|
||||
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-4f);
|
||||
BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-6f);
|
||||
|
||||
bf.resetFilter();
|
||||
filteredData = bf.filter(data);
|
||||
for (size_t i = 0; i < filteredData.size(); ++i)
|
||||
BOOST_CHECK_SMALL(std::abs(filteredData[i] - results[i]), 1e-4f);
|
||||
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.resize(0);
|
||||
for (float d : data)
|
||||
filteredData.push_back(bf2.stepFilter(d));
|
||||
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-4f);
|
||||
BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-6f);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(BUTTERWORTH_FILTER_DOUBLE, System<double>)
|
||||
{
|
||||
auto bf = fratio::Butterworthd(order, fc, fs);
|
||||
|
||||
std::vector<double> aCoeff, bCoeff, filteredData;
|
||||
bf.getCoeff(aCoeff, bCoeff);
|
||||
std::vector<double> filteredData;
|
||||
Eigen::VectorX<double> 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 (size_t 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 < 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 (double d : data)
|
||||
filteredData.push_back(bf.stepFilter(d));
|
||||
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);
|
||||
BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-14);
|
||||
|
||||
bf.resetFilter();
|
||||
filteredData = bf.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 = 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.resize(0);
|
||||
for (double d : data)
|
||||
filteredData.push_back(bf2.stepFilter(d));
|
||||
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_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-14);
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ macro(addTest testName)
|
|||
GENERATE_MSVC_DOT_USER_FILE(${testName})
|
||||
endmacro(addTest)
|
||||
|
||||
addTest(GenericFilterTests)
|
||||
# addTest(GenericFilterTests)
|
||||
# addTest(polynome_functions_tests)
|
||||
addTest(DigitalFilterTests)
|
||||
addTest(MovingAverageFilterTests)
|
||||
addTest(ButterWorthFilterTests)
|
||||
# addTest(polynome_functions_tests)
|
||||
# addTest(MovingAverageFilterTests)
|
||||
# addTest(ButterWorthFilterTests)
|
|
@ -1,7 +1,6 @@
|
|||
#define BOOST_TEST_MODULE DigitalFilterTests
|
||||
|
||||
#include "fratio.h"
|
||||
#include "typedefs.h"
|
||||
#include "fratio"
|
||||
#include "warning_macro.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
|
@ -10,8 +9,8 @@ DISABLE_CONVERSION_WARNING_BEGIN
|
|||
template <typename T>
|
||||
struct System {
|
||||
Eigen::VectorX<T> data = (Eigen::VectorX<T>(4) << 1, 2, 3, 4).finished();
|
||||
Eigen::VectorX<T> aCoeff = (Eigen::VectorX<T>(4) << 1, -0.99993717).finished();
|
||||
Eigen::VectorX<T> bCoeff = (Eigen::VectorX<T>(4) << 0.99996859, -0.99996859).finished();
|
||||
Eigen::VectorX<T> aCoeff = (Eigen::VectorX<T>(2) << 1, -0.99993717).finished();
|
||||
Eigen::VectorX<T> bCoeff = (Eigen::VectorX<T>(2) << 0.99996859, -0.99996859).finished();
|
||||
Eigen::VectorX<T> results = (Eigen::VectorX<T>(4) << 0.99996859, 1.999874351973491, 2.999717289867956, 3.999497407630634).finished();
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#define BOOST_TEST_MODULE GenericFilterTests
|
||||
|
||||
#include "fratio.h"
|
||||
#include "typedefs.h"
|
||||
#include "fratio"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <vector>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#define BOOST_TEST_MODULE MovingAverageFilterTests
|
||||
|
||||
#include "fratio.h"
|
||||
#include "fratio"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
template <typename T>
|
||||
|
@ -18,7 +18,7 @@ BOOST_FIXTURE_TEST_CASE(MOVING_AVERAGE_FLOAT, System<float>)
|
|||
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);
|
||||
BOOST_CHECK_SMALL(std::abs(filteredData[i] - results(i)), 1e-6f);
|
||||
|
||||
maf.resetFilter();
|
||||
Eigen::VectorXf fData = maf.filter(data);
|
||||
|
|
|
@ -1,31 +1,35 @@
|
|||
#define BOOST_TEST_MODULE polynome_functions_tests
|
||||
|
||||
#include "fratio.h"
|
||||
#include "fratio"
|
||||
#include "warning_macro.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using c_int_t = std::complex<int>;
|
||||
template <typename T>
|
||||
using c_t = std::complex<T>;
|
||||
|
||||
struct SystemInt {
|
||||
std::vector<int> data = { 1, 1, 1, 1 };
|
||||
std::vector<int> results = { 1, -4, 6, -4, 1 };
|
||||
Eigen::VectorX<int> data = (Eigen::VectorX<int>(4) << 1, 1, 1, 1).finished();
|
||||
Eigen::VectorX<int> results = (Eigen::VectorX<int>(5) << 1, -4, 6, -4, 1).finished();
|
||||
};
|
||||
|
||||
struct SystemCInt {
|
||||
std::vector<std::complex<int>> data = { { 1, 1 }, { -1, 4 }, { 12, -3 }, { 5, 2 } };
|
||||
std::vector<std::complex<int>> results = { { 1, 0 }, { -17, -4 }, { 66, 97 }, { 127, -386 }, { -357, 153 } };
|
||||
Eigen::VectorX<c_int_t> data = (Eigen::VectorX<c_int_t>(4) << c_int_t{ 1, 1 }, c_int_t{ -1, 4 }, c_int_t{ 12, -3 }, c_int_t{ 5, 2 }).finished();
|
||||
Eigen::VectorX<c_int_t> results = (Eigen::VectorX<c_int_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 <typename T>
|
||||
struct SystemFloat {
|
||||
std::vector<T> data = { 0.32, -0.0518, 41.4, 0.89 };
|
||||
std::vector<T> results = { 1, -42.558199999999999, 48.171601999999993, -9.181098159999999, -0.610759296 };
|
||||
Eigen::VectorX<T> data = (Eigen::VectorX<T>(4) << 0.32, -0.0518, 41.4, 0.89).finished();
|
||||
Eigen::VectorX<T> results = (Eigen::VectorX<T>(5) << 1, -42.558199999999999, 48.171601999999993, -9.181098159999999, -0.610759296).finished();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct SystemCFloat {
|
||||
std::vector<std::complex<T>> data = { { 1.35, 0.2 }, { -1.5, 4.45 }, { 12.8, -3.36 }, { 5.156, 2.12 } };
|
||||
std::vector<std::complex<T>> results = { { 1, 0 }, { -17.806, -3.41 }, { 73.2776, 99.20074 }, { 101.857496, -444.634694 }, { -269.1458768, 388.7308864 } };
|
||||
Eigen::VectorX<c_t<T>> data = (Eigen::VectorX<c_t<T>>(4) << c_t<T>{ 1.35, 0.2 }, c_t<T>{ -1.5, 4.45 }, c_t<T>{ 12.8, -3.36 }, c_t<T>{ 5.156, 2.12 }).finished();
|
||||
Eigen::VectorX<c_t<T>> results = (Eigen::VectorX<c_t<T>>(5) << c_t<T>{ 1, 0 }, c_t<T>{ -17.806, -3.41 }, c_t<T>{ 73.2776, 99.20074 }, c_t<T>{ 101.857496, -444.634694 }, c_t<T>{ -269.1458768, 388.7308864 }).finished();
|
||||
};
|
||||
|
||||
DISABLE_CONVERSION_WARNING_END
|
||||
|
@ -34,46 +38,46 @@ BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_INT, SystemInt)
|
|||
{
|
||||
auto res = fratio::VietaAlgoi::polyCoeffFromRoot(data);
|
||||
|
||||
for (size_t i = 0; i < res.size(); ++i)
|
||||
BOOST_CHECK_EQUAL(res[i], results[i]);
|
||||
for (Eigen::Index i = 0; i < res.size(); ++i)
|
||||
BOOST_CHECK_EQUAL(res(i), results(i));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_FLOAT, SystemFloat<float>)
|
||||
{
|
||||
auto res = fratio::VietaAlgof::polyCoeffFromRoot(data);
|
||||
|
||||
for (size_t i = 0; i < res.size(); ++i)
|
||||
BOOST_CHECK_SMALL(std::abs(res[i] - results[i]), 1e-6f);
|
||||
for (Eigen::Index i = 0; i < res.size(); ++i)
|
||||
BOOST_CHECK_SMALL(std::abs(res(i) - results(i)), 1e-6f);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_DOUBLE, SystemFloat<double>)
|
||||
{
|
||||
auto res = fratio::VietaAlgod::polyCoeffFromRoot(data);
|
||||
|
||||
for (size_t i = 0; i < res.size(); ++i)
|
||||
BOOST_CHECK_SMALL(std::abs(res[i] - results[i]), 1e-14);
|
||||
for (Eigen::Index i = 0; i < res.size(); ++i)
|
||||
BOOST_CHECK_SMALL(std::abs(res(i) - results(i)), 1e-14);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_CINT, SystemCInt)
|
||||
{
|
||||
auto res = fratio::VietaAlgoci::polyCoeffFromRoot(data);
|
||||
|
||||
for (size_t i = 0; i < res.size(); ++i)
|
||||
BOOST_CHECK_EQUAL(res[i], results[i]);
|
||||
for (Eigen::Index i = 0; i < res.size(); ++i)
|
||||
BOOST_CHECK_EQUAL(res(i), results(i));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_CFLOAT, SystemCFloat<float>)
|
||||
{
|
||||
auto res = fratio::VietaAlgocf::polyCoeffFromRoot(data);
|
||||
|
||||
for (size_t i = 0; i < res.size(); ++i)
|
||||
BOOST_CHECK_SMALL(std::abs(res[i] - results[i]), 1e-4f);
|
||||
for (Eigen::Index i = 0; i < res.size(); ++i)
|
||||
BOOST_CHECK_SMALL(std::abs(res(i) - results(i)), 1e-4f);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(POLYNOME_FUNCTION_CDOUBLE, SystemCFloat<double>)
|
||||
{
|
||||
auto res = fratio::VietaAlgocd::polyCoeffFromRoot(data);
|
||||
|
||||
for (size_t i = 0; i < res.size(); ++i)
|
||||
BOOST_CHECK_SMALL(std::abs(res[i] - results[i]), 1e-12);
|
||||
for (Eigen::Index i = 0; i < res.size(); ++i)
|
||||
BOOST_CHECK_SMALL(std::abs(res(i) - results(i)), 1e-12);
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue