Environment: VS 2013, Boost 1.58
I've written something that presents a more friendly interface to Boost's accumulator, which can be used to project a sum over a window, and calculate the actual rolling mean over the window. During a push to get to VS 2013 as our main compiler, one of the unit tests for this class started failing. Peeling off the layers, I've narrowed it down to this minimal example:
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
namespace ba = boost::accumulators;
namespace bt = ba::tag;
typedef ba::accumulator_set < uint32_t, ba::stats <bt::rolling_mean > > MeanAccumulator;
int main() {
MeanAccumulator acc(bt::rolling_window::window_size = 5u);
for (uint32_t i : { 3, 2, 1, 0 }) {
acc(i);
std::cout << i << " actualMean: " << std::fixed << boost::accumulators::rolling_mean(acc) << "\n";
}
}
On the final pass of the loop, I don't get the expected mean value (1.5), but instead get a crazy high value (1431655766.333333).
This code executes correctly in VS 2008 with Boost 1.49 (with C++11 vector initialization replaced, obviously), but fails in VS 2012 and VS 2013 with Boost 1.58. I'm at a loss to explain this failure and thus can't fix it.
Other interesting points:
It seems to be a Boost bug, but wanted to verify that I'm not doing something stupid before reporting the bug or attempting to build Boost 1.59. Thanks in advance!
EDIT: Thanks for the responses, as this does appear to be a Boost bug. The associated Boost ticket is here.. It's an issue related to unsigned integers with accumulators. Specifically, if a value added to the accumulator after the window is full is strictly less than all values in the window already, the rolling_mean call will return an invalid result.
There is a workaround, which is to not use unsigned integers with accumulators. This solves my problem, so thanks for the help!
There's obviously a bug lurking there, possibly in the compiler, but more likely in the library, as I've been able to reproduce this on GCC:
Live On Coliru
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
namespace ba = boost::accumulators;
namespace bt = ba::tag;
typedef ba::accumulator_set < uint32_t, ba::stats <bt::rolling_mean > > MeanAccumulator;
int main() {
MeanAccumulator acc(bt::rolling_window::window_size = 5u);
for (uint32_t i : { 252, 189, 248, 154, 620, 885, 939, 196 }) {
acc(i);
std::cout << i << " actualMean: " << std::fixed << boost::accumulators::rolling_mean(acc) << "\n";
}
}
Prints
g++-5.2 -std=c++1y -O2 -Wall -pedantic main.cpp && ./a.out
252 actualMean: 252.000000
189 actualMean: 220.500000
248 actualMean: 229.666667
154 actualMean: 210.750000
620 actualMean: 292.600000
885 actualMean: 419.200000
939 actualMean: 569.200000
196 actualMean: 858994018.000000
Now the problem appears to be related to the choice of unsigned
sample type`: changing it to signed removes the symptom: Live On Coliru
In short: I'd report this at the boost mailing list or Trac: https://svn.boost.org/trac/boost/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With