rolling_window.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. namespace boost { namespace accumulators
  23. {
  24. ///////////////////////////////////////////////////////////////////////////////
  25. // tag::rolling_window::size named parameter
  26. BOOST_PARAMETER_NESTED_KEYWORD(tag, rolling_window_size, window_size)
  27. BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window_size)
  28. namespace impl
  29. {
  30. ///////////////////////////////////////////////////////////////////////////////
  31. // rolling_window_plus1_impl
  32. // stores the latest N+1 samples, where N is specified at construction time
  33. // with the rolling_window_size named parameter
  34. template<typename Sample>
  35. struct rolling_window_plus1_impl
  36. : accumulator_base
  37. {
  38. typedef typename circular_buffer<Sample>::const_iterator const_iterator;
  39. typedef iterator_range<const_iterator> result_type;
  40. template<typename Args>
  41. rolling_window_plus1_impl(Args const & args)
  42. : buffer_(args[rolling_window_size] + 1)
  43. {}
  44. #if BOOST_VERSION < 103600
  45. // Before Boost 1.36, copying a circular buffer didn't copy
  46. // it's capacity, and we need that behavior.
  47. rolling_window_plus1_impl(rolling_window_plus1_impl const &that)
  48. : buffer_(that.buffer_)
  49. {
  50. this->buffer_.set_capacity(that.buffer_.capacity());
  51. }
  52. rolling_window_plus1_impl &operator =(rolling_window_plus1_impl const &that)
  53. {
  54. this->buffer_ = that.buffer_;
  55. this->buffer_.set_capacity(that.buffer_.capacity());
  56. }
  57. #endif
  58. template<typename Args>
  59. void operator ()(Args const &args)
  60. {
  61. this->buffer_.push_back(args[sample]);
  62. }
  63. bool full() const
  64. {
  65. return this->buffer_.full();
  66. }
  67. // The result of a shifted rolling window is the range including
  68. // everything except the most recently added element.
  69. result_type result(dont_care) const
  70. {
  71. return result_type(this->buffer_.begin(), this->buffer_.end());
  72. }
  73. private:
  74. circular_buffer<Sample> buffer_;
  75. };
  76. template<typename Args>
  77. bool is_rolling_window_plus1_full(Args const &args)
  78. {
  79. return find_accumulator<tag::rolling_window_plus1>(args[accumulator]).full();
  80. }
  81. ///////////////////////////////////////////////////////////////////////////////
  82. // rolling_window_impl
  83. // stores the latest N samples, where N is specified at construction type
  84. // with the rolling_window_size named parameter
  85. template<typename Sample>
  86. struct rolling_window_impl
  87. : accumulator_base
  88. {
  89. typedef typename circular_buffer<Sample>::const_iterator const_iterator;
  90. typedef iterator_range<const_iterator> result_type;
  91. rolling_window_impl(dont_care)
  92. {}
  93. template<typename Args>
  94. result_type result(Args const &args) const
  95. {
  96. return rolling_window_plus1(args).advance_begin(is_rolling_window_plus1_full(args));
  97. }
  98. };
  99. } // namespace impl
  100. ///////////////////////////////////////////////////////////////////////////////
  101. // tag::rolling_window_plus1
  102. // tag::rolling_window
  103. //
  104. namespace tag
  105. {
  106. struct rolling_window_plus1
  107. : depends_on<>
  108. , tag::rolling_window_size
  109. {
  110. /// INTERNAL ONLY
  111. ///
  112. typedef accumulators::impl::rolling_window_plus1_impl< mpl::_1 > impl;
  113. #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
  114. /// tag::rolling_window::size named parameter
  115. static boost::parameter::keyword<tag::rolling_window_size> const window_size;
  116. #endif
  117. };
  118. struct rolling_window
  119. : depends_on< rolling_window_plus1 >
  120. {
  121. /// INTERNAL ONLY
  122. ///
  123. typedef accumulators::impl::rolling_window_impl< mpl::_1 > impl;
  124. #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
  125. /// tag::rolling_window::size named parameter
  126. static boost::parameter::keyword<tag::rolling_window_size> const window_size;
  127. #endif
  128. };
  129. } // namespace tag
  130. ///////////////////////////////////////////////////////////////////////////////
  131. // extract::rolling_window_plus1
  132. // extract::rolling_window
  133. //
  134. namespace extract
  135. {
  136. extractor<tag::rolling_window_plus1> const rolling_window_plus1 = {};
  137. extractor<tag::rolling_window> const rolling_window = {};
  138. BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window_plus1)
  139. BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window)
  140. }
  141. using extract::rolling_window_plus1;
  142. using extract::rolling_window;
  143. }} // namespace boost::accumulators
  144. #endif