rolling_window.hpp 7.1 KB

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