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#include <boost/serialization/split_free.hpp>
25
26namespace boost { namespace serialization {
27
28// implement serialization for boost::circular_buffer
29template <class Archive, class T>
30void save(Archive& ar, const circular_buffer<T>& b, const unsigned int /* version */)
31{
32 typename circular_buffer<T>::size_type size = b.size();
33 ar << b.capacity();
34 ar << size;
35 const typename circular_buffer<T>::const_array_range one = b.array_one();
36 const typename circular_buffer<T>::const_array_range two = b.array_two();
37 ar.save_binary(one.first, one.second*sizeof(T));
38 ar.save_binary(two.first, two.second*sizeof(T));
39}
40
41template <class Archive, class T>
42void load(Archive& ar, circular_buffer<T>& b, const unsigned int /* version */)
43{
44 typename circular_buffer<T>::capacity_type capacity;
45 typename circular_buffer<T>::size_type size;
46 ar >> capacity;
47 b.set_capacity(capacity);
48 ar >> size;
49 b.clear();
50 const typename circular_buffer<T>::pointer buff = new T[size*sizeof(T)];
51 ar.load_binary(buff, size*sizeof(T));
52 b.insert(b.begin(), buff, buff+size);
53 delete[] buff;
54}
55
56template<class Archive, class T>
57inline void serialize(Archive & ar, circular_buffer<T>& b, const unsigned int version)
58{
59 split_free(ar, b, version);
60}
61
62} } // end namespace boost::serialization
63
64namespace boost { namespace accumulators
65{
66
67///////////////////////////////////////////////////////////////////////////////
68// tag::rolling_window::size named parameter
69BOOST_PARAMETER_NESTED_KEYWORD(tag, rolling_window_size, window_size)
70
71BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window_size)
72
73namespace impl
74{
75 ///////////////////////////////////////////////////////////////////////////////
76 // rolling_window_plus1_impl
77 // stores the latest N+1 samples, where N is specified at construction time
78 // with the rolling_window_size named parameter
79 template<typename Sample>
80 struct rolling_window_plus1_impl
81 : accumulator_base
82 {
83 typedef typename circular_buffer<Sample>::const_iterator const_iterator;
84 typedef iterator_range<const_iterator> result_type;
85
86 template<typename Args>
87 rolling_window_plus1_impl(Args const & args)
88 : buffer_(args[rolling_window_size] + 1)
89 {}
90
91 #if BOOST_VERSION < 103600
92 // Before Boost 1.36, copying a circular buffer didn't copy
93 // it's capacity, and we need that behavior.
94 rolling_window_plus1_impl(rolling_window_plus1_impl const &that)
95 : buffer_(that.buffer_)
96 {
97 this->buffer_.set_capacity(that.buffer_.capacity());
98 }
99
100 rolling_window_plus1_impl &operator =(rolling_window_plus1_impl const &that)
101 {
102 this->buffer_ = that.buffer_;
103 this->buffer_.set_capacity(that.buffer_.capacity());
104 }
105 #endif
106
107 template<typename Args>
108 void operator ()(Args const &args)
109 {
110 this->buffer_.push_back(args[sample]);
111 }
112
113 bool full() const
114 {
115 return this->buffer_.full();
116 }
117
118 // The result of a shifted rolling window is the range including
119 // everything except the most recently added element.
120 result_type result(dont_care) const
121 {
122 return result_type(this->buffer_.begin(), this->buffer_.end());
123 }
124
125 template<class Archive>
126 void serialize(Archive & ar, const unsigned int version)
127 {
128 ar & buffer_;
129 }
130
131 private:
132 circular_buffer<Sample> buffer_;
133 };
134
135 template<typename Args>
136 bool is_rolling_window_plus1_full(Args const &args)
137 {
138 return find_accumulator<tag::rolling_window_plus1>(args[accumulator]).full();
139 }
140
141 ///////////////////////////////////////////////////////////////////////////////
142 // rolling_window_impl
143 // stores the latest N samples, where N is specified at construction type
144 // with the rolling_window_size named parameter
145 template<typename Sample>
146 struct rolling_window_impl
147 : accumulator_base
148 {
149 typedef typename circular_buffer<Sample>::const_iterator const_iterator;
150 typedef iterator_range<const_iterator> result_type;
151
152 rolling_window_impl(dont_care)
153 {}
154
155 template<typename Args>
156 result_type result(Args const &args) const
157 {
158 return rolling_window_plus1(args).advance_begin(is_rolling_window_plus1_full(args));
159 }
160
161 // serialization is done by accumulators it depends on
162 template<class Archive>
163 void serialize(Archive & ar, const unsigned int file_version) {}
164 };
165
166} // namespace impl
167
168///////////////////////////////////////////////////////////////////////////////
169// tag::rolling_window_plus1
170// tag::rolling_window
171//
172namespace tag
173{
174 struct rolling_window_plus1
175 : depends_on<>
176 , tag::rolling_window_size
177 {
178 /// INTERNAL ONLY
179 ///
180 typedef accumulators::impl::rolling_window_plus1_impl< mpl::_1 > impl;
181
182 #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
183 /// tag::rolling_window::size named parameter
184 static boost::parameter::keyword<tag::rolling_window_size> const window_size;
185 #endif
186 };
187
188 struct rolling_window
189 : depends_on< rolling_window_plus1 >
190 {
191 /// INTERNAL ONLY
192 ///
193 typedef accumulators::impl::rolling_window_impl< mpl::_1 > impl;
194
195 #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
196 /// tag::rolling_window::size named parameter
197 static boost::parameter::keyword<tag::rolling_window_size> const window_size;
198 #endif
199 };
200
201} // namespace tag
202
203///////////////////////////////////////////////////////////////////////////////
204// extract::rolling_window_plus1
205// extract::rolling_window
206//
207namespace extract
208{
209 extractor<tag::rolling_window_plus1> const rolling_window_plus1 = {};
210 extractor<tag::rolling_window> const rolling_window = {};
211
212 BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window_plus1)
213 BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window)
214}
215
216using extract::rolling_window_plus1;
217using extract::rolling_window;
218
219}} // namespace boost::accumulators
220
221#endif
222

source code of boost/libs/accumulators/include/boost/accumulators/statistics/rolling_window.hpp