1 /////////////////////////////////////////////////////////////////////////////// 2 // rolling_window.hpp 3 // 4 // Copyright 2008 Eric Niebler. Distributed under the Boost 5 // Software License, Version 1.0. (See accompanying file 6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 8 #ifndef BOOST_ACCUMULATORS_STATISTICS_ROLLING_WINDOW_HPP_EAN_26_12_2008 9 #define BOOST_ACCUMULATORS_STATISTICS_ROLLING_WINDOW_HPP_EAN_26_12_2008 10 11 #include <cstddef> 12 #include <boost/version.hpp> 13 #include <boost/assert.hpp> 14 #include <boost/circular_buffer.hpp> 15 #include <boost/range/iterator_range.hpp> 16 #include <boost/accumulators/accumulators_fwd.hpp> 17 #include <boost/accumulators/framework/extractor.hpp> 18 #include <boost/accumulators/framework/depends_on.hpp> 19 #include <boost/accumulators/framework/accumulator_base.hpp> 20 #include <boost/accumulators/framework/parameters/sample.hpp> 21 #include <boost/accumulators/framework/parameters/accumulator.hpp> 22 #include <boost/accumulators/numeric/functional.hpp> 23 #include <boost/accumulators/statistics_fwd.hpp> 24 25 namespace boost { namespace accumulators 26 { 27 28 /////////////////////////////////////////////////////////////////////////////// 29 // tag::rolling_window::size named parameter 30 BOOST_PARAMETER_NESTED_KEYWORD(tag, rolling_window_size, window_size) 31 32 BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window_size) 33 34 namespace impl 35 { 36 /////////////////////////////////////////////////////////////////////////////// 37 // rolling_window_plus1_impl 38 // stores the latest N+1 samples, where N is specified at construction time 39 // with the rolling_window_size named parameter 40 template<typename Sample> 41 struct rolling_window_plus1_impl 42 : accumulator_base 43 { 44 typedef typename circular_buffer<Sample>::const_iterator const_iterator; 45 typedef iterator_range<const_iterator> result_type; 46 47 template<typename Args> rolling_window_plus1_implboost::accumulators::impl::rolling_window_plus1_impl48 rolling_window_plus1_impl(Args const & args) 49 : buffer_(args[rolling_window_size] + 1) 50 {} 51 52 #if BOOST_VERSION < 103600 53 // Before Boost 1.36, copying a circular buffer didn't copy 54 // it's capacity, and we need that behavior. rolling_window_plus1_implboost::accumulators::impl::rolling_window_plus1_impl55 rolling_window_plus1_impl(rolling_window_plus1_impl const &that) 56 : buffer_(that.buffer_) 57 { 58 this->buffer_.set_capacity(that.buffer_.capacity()); 59 } 60 operator =boost::accumulators::impl::rolling_window_plus1_impl61 rolling_window_plus1_impl &operator =(rolling_window_plus1_impl const &that) 62 { 63 this->buffer_ = that.buffer_; 64 this->buffer_.set_capacity(that.buffer_.capacity()); 65 } 66 #endif 67 68 template<typename Args> operator ()boost::accumulators::impl::rolling_window_plus1_impl69 void operator ()(Args const &args) 70 { 71 this->buffer_.push_back(args[sample]); 72 } 73 fullboost::accumulators::impl::rolling_window_plus1_impl74 bool full() const 75 { 76 return this->buffer_.full(); 77 } 78 79 // The result of a shifted rolling window is the range including 80 // everything except the most recently added element. resultboost::accumulators::impl::rolling_window_plus1_impl81 result_type result(dont_care) const 82 { 83 return result_type(this->buffer_.begin(), this->buffer_.end()); 84 } 85 86 private: 87 circular_buffer<Sample> buffer_; 88 }; 89 90 template<typename Args> is_rolling_window_plus1_full(Args const & args)91 bool is_rolling_window_plus1_full(Args const &args) 92 { 93 return find_accumulator<tag::rolling_window_plus1>(args[accumulator]).full(); 94 } 95 96 /////////////////////////////////////////////////////////////////////////////// 97 // rolling_window_impl 98 // stores the latest N samples, where N is specified at construction type 99 // with the rolling_window_size named parameter 100 template<typename Sample> 101 struct rolling_window_impl 102 : accumulator_base 103 { 104 typedef typename circular_buffer<Sample>::const_iterator const_iterator; 105 typedef iterator_range<const_iterator> result_type; 106 rolling_window_implboost::accumulators::impl::rolling_window_impl107 rolling_window_impl(dont_care) 108 {} 109 110 template<typename Args> resultboost::accumulators::impl::rolling_window_impl111 result_type result(Args const &args) const 112 { 113 return rolling_window_plus1(args).advance_begin(is_rolling_window_plus1_full(args)); 114 } 115 }; 116 117 } // namespace impl 118 119 /////////////////////////////////////////////////////////////////////////////// 120 // tag::rolling_window_plus1 121 // tag::rolling_window 122 // 123 namespace tag 124 { 125 struct rolling_window_plus1 126 : depends_on<> 127 , tag::rolling_window_size 128 { 129 /// INTERNAL ONLY 130 /// 131 typedef accumulators::impl::rolling_window_plus1_impl< mpl::_1 > impl; 132 133 #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED 134 /// tag::rolling_window::size named parameter 135 static boost::parameter::keyword<tag::rolling_window_size> const window_size; 136 #endif 137 }; 138 139 struct rolling_window 140 : depends_on< rolling_window_plus1 > 141 { 142 /// INTERNAL ONLY 143 /// 144 typedef accumulators::impl::rolling_window_impl< mpl::_1 > impl; 145 146 #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED 147 /// tag::rolling_window::size named parameter 148 static boost::parameter::keyword<tag::rolling_window_size> const window_size; 149 #endif 150 }; 151 152 } // namespace tag 153 154 /////////////////////////////////////////////////////////////////////////////// 155 // extract::rolling_window_plus1 156 // extract::rolling_window 157 // 158 namespace extract 159 { 160 extractor<tag::rolling_window_plus1> const rolling_window_plus1 = {}; 161 extractor<tag::rolling_window> const rolling_window = {}; 162 163 BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window_plus1) 164 BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window) 165 } 166 167 using extract::rolling_window_plus1; 168 using extract::rolling_window; 169 170 }} // namespace boost::accumulators 171 172 #endif 173