|
Boost Users : |
Subject: Re: [Boost-users] Accumulators: Using data vector from Interprocess
From: Eric Niebler (eric_at_[hidden])
Date: 2008-12-23 14:19:06
Eric Niebler wrote:
>
> A moving average accumulator is an often requested
> feature. I knocked one together as a proof-of-concept during the
> accumulators review, but never polished it. You can find it in this
> message:
>
> http://lists.boost.org/Archives/boost/2007/07/124979.php
Whoops, that's a rolling average algorithm for the time series library.
The implementation for the accumulators library is considerably simpler.
I just knocked this together, but it seems to work.
///////////////////////////////////////////////////////////////////////////////
// Copyright 2008 Eric Niebler. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/circular_buffer.hpp>
#include <boost/accumulators/framework/extractor.hpp>
#include <boost/accumulators/framework/depends_on.hpp>
#include <boost/accumulators/framework/accumulator_base.hpp>
#include <boost/accumulators/framework/parameters/sample.hpp>
#include <boost/accumulators/numeric/functional.hpp>
namespace boost {
namespace accumulators {
BOOST_PARAMETER_NESTED_KEYWORD(tag, rolling_average_window_size,
window_size)
namespace impl {
template<typename Sample>
struct rolling_average_impl
: accumulator_base
{
// for boost::result_of
typedef typename numeric::functional::average<Sample,
std::size_t>::result_type result_type;
template<typename Args>
rolling_average_impl(Args const & args)
: sum_(args[sample | Sample()])
, buffer_(args[rolling_average_window_size])
{
}
rolling_average_impl(rolling_average_impl const &that)
: sum_(that.sum_)
, buffer_(that.buffer_)
{
this->buffer_.set_capacity(that.buffer_.capacity());
}
template<typename Args>
void operator ()(Args const & args)
{
this->push_back_(args[sample]);
}
result_type result(dont_care) const
{
BOOST_ASSERT(this->buffer_.size() != 0);
return numeric::average(this->sum_, this->buffer_.size());
}
private:
rolling_average_impl &operator=(rolling_average_impl const &);
void push_back_(Sample const &value)
{
if(this->buffer_.full())
{
this->sum_ -= this->buffer_[0];
}
this->sum_ += value;
this->buffer_.push_back(value);
}
Sample sum_;
circular_buffer<Sample> buffer_;
};
}
namespace tag
{
struct rolling_average
: depends_on< >
, tag::rolling_average_window_size
{
typedef accumulators::impl::rolling_average_impl< mpl::_1 > impl;
};
}
namespace extract
{
extractor<tag::rolling_average> const rolling_average = {};
}
using extract::rolling_average;
}}
#include <iostream>
#include <boost/accumulators/accumulators.hpp>
int main()
{
using namespace boost;
using namespace accumulators;
accumulator_set<double, features< tag::rolling_average > >
acc(tag::rolling_average::window_size = 5);
acc(1.);
std::cout << rolling_average(acc) << std::endl;
acc(2.);
std::cout << rolling_average(acc) << std::endl;
acc(3.);
std::cout << rolling_average(acc) << std::endl;
acc(4.);
std::cout << rolling_average(acc) << std::endl;
acc(5.);
std::cout << rolling_average(acc) << std::endl;
acc(6.);
std::cout << rolling_average(acc) << std::endl;
acc(7.);
std::cout << rolling_average(acc) << std::endl;
return 0;
}
-- Eric Niebler BoostPro Computing http://www.boostpro.com
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net