$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
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://listarchives.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