Added runtime sample size specialisations to etl::cumulative_moving_average

This commit is contained in:
John Wellbelove 2019-07-05 13:49:38 +01:00
parent 48f2d28b98
commit 9fbbb5cc19
4 changed files with 244 additions and 8 deletions

View File

@ -112,6 +112,78 @@ namespace etl
T average; ///< The current cumulative average.
};
//***************************************************************************
/// Cumulative Moving Average
/// For integral types.
/// \tparam T The sample value type.
/// \tparam SCALING The scaling factor applied to samples. Default = 1.
//***************************************************************************
template <typename T, const size_t SCALING_>
class cumulative_moving_average<T, 0, SCALING_, true, false>
{
typedef typename etl::conditional<etl::is_signed<T>::value, int32_t, uint32_t>::type scale_t;
typedef typename etl::conditional<etl::is_signed<T>::value, int32_t, uint32_t>::type sample_t;
static const scale_t SCALE = static_cast<scale_t>(SCALING_);
public:
static const size_t SCALING = SCALING_; ///< The sample scaling factor.
//*************************************************************************
/// Constructor
/// \param initial_value The initial value for the average.
//*************************************************************************
cumulative_moving_average(const T initial_value, const size_t sample_size)
: average(initial_value * SCALE)
, samples(sample_size)
{
}
//*************************************************************************
/// Clears the average.
/// \param initial_value The initial value for the average.
//*************************************************************************
void clear(const T initial_value)
{
average = (initial_value * SCALE);
}
//*************************************************************************
/// Sets the sample size.
/// \param sample_size The new sample size.
//*************************************************************************
void set_sample_size(const size_t sample_size)
{
samples = sample_t(sample_size);
}
//*************************************************************************
/// Adds a new sample to the average.
/// \param new_value The value to add.
//*************************************************************************
void add(T new_value)
{
average *= samples;
average += SCALE * new_value;
average /= samples + sample_t(1);
}
//*************************************************************************
/// Gets the current cumulative average.
/// \return The current average.
//*************************************************************************
T value() const
{
return average;
}
private:
T average; ///< The current cumulative average.
sample_t samples; ///< The nuimber of samples to average over.
};
//***************************************************************************
/// Cumulative Moving Average
/// For floating point types.
@ -130,8 +202,8 @@ namespace etl
/// \param initial_value The initial value for the average.
//*************************************************************************
cumulative_moving_average(const T initial_value)
: sample_size(T(SAMPLE_SIZE_)),
sample_size_plus_1(T(SAMPLE_SIZE_ + 1)),
: samples(T(SAMPLE_SIZE_)),
samples_plus_1(T(SAMPLE_SIZE_ + 1U)),
average(initial_value)
{
}
@ -151,9 +223,9 @@ namespace etl
//*************************************************************************
void add(const T new_value)
{
average *= sample_size;
average *= samples;
average += new_value;
average /= sample_size_plus_1;
average /= samples_plus_1;
}
//*************************************************************************
@ -167,10 +239,78 @@ namespace etl
private:
const T sample_size; ///< The sample size to average over.
const T sample_size_plus_1; ///< One greater than the sample size.
const T samples; ///< The sample size to average over.
const T samples_plus_1; ///< One greater than the sample size.
T average; ///< The current cumulative average.
};
//***************************************************************************
/// Cumulative Moving Average
/// For floating point types.
/// \tparam T The sample value type.
/// \tparam SAMPLE_SIZE The number of samples to average over.
//***************************************************************************
template <typename T>
class cumulative_moving_average<T, 0U, 1U, false, true>
{
public:
//*************************************************************************
/// Constructor
/// \param initial_value The initial value for the average.
//*************************************************************************
cumulative_moving_average(const T initial_value, const size_t sample_size)
: samples(T(sample_size)),
samples_plus_1(T(sample_size + 1U)),
average(initial_value)
{
}
//*************************************************************************
/// Clears the average.
/// \param initial_value The initial value for the average.
//*************************************************************************
void clear(const T initial_value)
{
average = initial_value;
}
//*************************************************************************
/// Sets the sample size.
/// \param sample_size The new sample size.
//*************************************************************************
void set_sample_size(const size_t sample_size)
{
samples = T(sample_size);
samples_plus_1 = samples + T(1);
}
//*************************************************************************
/// Adds a new sample to the average.
/// \param new_value The value to add.
//*************************************************************************
void add(const T new_value)
{
average *= samples;
average += new_value;
average /= samples_plus_1;
}
//*************************************************************************
/// Gets the current cumulative average.
/// \return The current average.
//*************************************************************************
T value() const
{
return average;
}
private:
T samples; ///< The sample size to average over.
T samples_plus_1; ///< One greater than the sample size.
T average; ///< The current cumulative average.
};
}
#endif

View File

@ -38,8 +38,8 @@ SOFTWARE.
///\ingroup utilities
#define ETL_VERSION_MAJOR 14
#define ETL_VERSION_MINOR 27
#define ETL_VERSION_PATCH 1
#define ETL_VERSION_MINOR 28
#define ETL_VERSION_PATCH 0
#define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) ETL_STRINGIFY(ETL_VERSION_MINOR) ETL_STRINGIFY(ETL_VERSION_PATCH)
#define ETL_VERSION_W ETL_WIDE_STRING(ETL_CONCAT(ETL_CONCAT(ETL_VERSION_MAJOR, ETL_VERSION_MINOR), ETL_VERSION_PATCH))

View File

@ -1,3 +1,7 @@
===============================================================================
14.28.0
Added runtime sample size specialisations to etl::cumulative_moving_average.
===============================================================================
14.27.1
Removed ETL_IF_CONSTEXPR from etl::message_timer 'tick()'

View File

@ -101,6 +101,75 @@ namespace
CHECK_EQUAL(280U, cma.value());
}
//*************************************************************************
TEST(integral_signed_average_positive_runtime_sample_size)
{
typedef etl::cumulative_moving_average<int, 0U, SCALING> CMA;
CMA cma(0, SAMPLE_SIZE * 2U);
CHECK_EQUAL(0, cma.value());
cma.set_sample_size(SAMPLE_SIZE);
cma.add(9);
cma.add(1);
cma.add(8);
cma.add(2);
cma.add(7);
cma.add(3);
cma.add(6);
cma.add(4);
cma.add(5);
CHECK_EQUAL(280, cma.value());
}
//*************************************************************************
TEST(integral_signed_average_negative_runtime_sample_size)
{
typedef etl::cumulative_moving_average<int, 0U, SCALING> CMA;
CMA cma(0, SAMPLE_SIZE * 2U);
CHECK_EQUAL(0, cma.value());
cma.set_sample_size(SAMPLE_SIZE);
cma.add(-9);
cma.add(-1);
cma.add(-8);
cma.add(-2);
cma.add(-7);
cma.add(-3);
cma.add(-6);
cma.add(-4);
cma.add(-5);
CHECK_EQUAL(-280, cma.value());
}
//*************************************************************************
TEST(integral_unsigned_average_positive_runtime_sample_size)
{
typedef etl::cumulative_moving_average<unsigned int, 0U, SCALING> CMA;
CMA cma(0U, SAMPLE_SIZE * 2U);
CHECK_EQUAL(0U, cma.value());
cma.set_sample_size(SAMPLE_SIZE);
cma.add(9U);
cma.add(1U);
cma.add(8U);
cma.add(2U);
cma.add(7U);
cma.add(3U);
cma.add(6U);
cma.add(4U);
cma.add(5U);
CHECK_EQUAL(280U, cma.value());
}
//*************************************************************************
TEST(floating_point_average)
{
@ -121,5 +190,28 @@ namespace
CHECK_CLOSE(2.82, cma.value(), 0.01);
}
//*************************************************************************
TEST(floating_point_average_runtime_sample_size)
{
typedef etl::cumulative_moving_average<double, 0U> CMA;
CMA cma(0, SAMPLE_SIZE * 2);
CHECK_EQUAL(0.0, cma.value());
cma.set_sample_size(SAMPLE_SIZE);
cma.add(9.0);
cma.add(1.0);
cma.add(8.0);
cma.add(2.0);
cma.add(7.0);
cma.add(3.0);
cma.add(6.0);
cma.add(4.0);
cma.add(5.0);
CHECK_CLOSE(2.82, cma.value(), 0.01);
}
};
}