Skip to content

Commit

Permalink
Fix #11437: correct immediate_rolling_mean
Browse files Browse the repository at this point in the history
Corrects the immediate_rolling_mean calculation for unsigned
int, so that when a value lower than the previous value is added,
underflow does not occur.

Includes new regression test for this behavior.
  • Loading branch information
oliness committed Feb 6, 2018
1 parent b133840 commit 5ff527e
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
10 changes: 8 additions & 2 deletions include/boost/accumulators/statistics/rolling_mean.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,18 @@ namespace boost { namespace accumulators
{
if(is_rolling_window_plus1_full(args))
{
mean_ += numeric::fdiv(args[sample]-rolling_window_plus1(args).front(),rolling_count(args));
if (rolling_window_plus1(args).front() > args[sample])
mean_ -= numeric::fdiv(rolling_window_plus1(args).front()-args[sample],rolling_count(args));
else if (rolling_window_plus1(args).front() < args[sample])
mean_ += numeric::fdiv(args[sample]-rolling_window_plus1(args).front(),rolling_count(args));
}
else
{
result_type prev_mean = mean_;
mean_ += numeric::fdiv(args[sample]-prev_mean,rolling_count(args));
if (prev_mean > args[sample])
mean_ -= numeric::fdiv(prev_mean-args[sample],rolling_count(args));
else if (prev_mean < args[sample])
mean_ += numeric::fdiv(args[sample]-prev_mean,rolling_count(args));
}
}

Expand Down
36 changes: 36 additions & 0 deletions test/rolling_mean.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,34 @@ test_rolling_mean_test_impl(accumulator_set_type& acc)
assert_is_double(rolling_mean(acc));
}

template<typename accumulator_set_type>
void
test_rolling_mean_unsigned_test_impl(accumulator_set_type& acc)
{
acc(7U);
BOOST_CHECK_CLOSE(7., rolling_mean(acc), 1e-5);

acc(6U);
BOOST_CHECK_CLOSE(6.5, rolling_mean(acc), 1e-5);

acc(5U);
BOOST_CHECK_CLOSE(6., rolling_mean(acc), 1e-5);

acc(4U);
BOOST_CHECK_CLOSE(5.5, rolling_mean(acc), 1e-5);

acc(3U);
BOOST_CHECK_CLOSE(5., rolling_mean(acc), 1e-5);

acc(2U);
BOOST_CHECK_CLOSE(4., rolling_mean(acc), 1e-5);

acc(1U);
BOOST_CHECK_CLOSE(3., rolling_mean(acc), 1e-5);

assert_is_double(rolling_mean(acc));
}

///////////////////////////////////////////////////////////////////////////////
// test_rolling_mean
void test_rolling_mean()
Expand Down Expand Up @@ -97,6 +125,14 @@ void test_rolling_mean()
BOOST_CHECK (sizeof(acc_lazy_rolling_mean) == sizeof(acc_lazy_rolling_mean3));
BOOST_CHECK (sizeof(acc_immediate_rolling_mean) == sizeof(acc_immediate_rolling_mean2));
BOOST_CHECK (sizeof(acc_immediate_rolling_mean) == sizeof(acc_immediate_rolling_mean3));

//// test unsigned int with both implementations
accumulator_set<unsigned int,stats<tag::immediate_rolling_mean> >
acc_immediate_rolling_mean4(tag::immediate_rolling_mean::window_size = window_size),
acc_immediate_rolling_mean5(tag::immediate_rolling_mean::window_size = window_size, sample = 0);

test_rolling_mean_unsigned_test_impl(acc_immediate_rolling_mean4);
test_rolling_mean_unsigned_test_impl(acc_immediate_rolling_mean5);
}

///////////////////////////////////////////////////////////////////////////////
Expand Down

0 comments on commit 5ff527e

Please sign in to comment.