Skip to content

Commit

Permalink
Merge branch 'feature/runtime_cumulative_moving_average' into develop…
Browse files Browse the repository at this point in the history
…ment
  • Loading branch information
jwellbelove committed Jul 5, 2019
2 parents 48f2d28 + 9fbbb5c commit f908829
Show file tree
Hide file tree
Showing 4 changed files with 244 additions and 8 deletions.
152 changes: 146 additions & 6 deletions include/etl/cumulative_moving_average.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
{
}
Expand All @@ -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;
}

//*************************************************************************
Expand All @@ -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
4 changes: 2 additions & 2 deletions include/etl/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
4 changes: 4 additions & 0 deletions support/Release notes.txt
Original file line number Diff line number Diff line change
@@ -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()'
Expand Down
92 changes: 92 additions & 0 deletions test/test_cumulative_moving_average.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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);
}
};
}

0 comments on commit f908829

Please sign in to comment.