diff --git a/doc/accumulators.qbk b/doc/accumulators.qbk index 7e6d1f4..0cb3455 100644 --- a/doc/accumulators.qbk +++ b/doc/accumulators.qbk @@ -2077,6 +2077,109 @@ The rolling count is the current number of elements in the rolling window. [endsect] +[section:rolling_max rolling_max] + +The rolling max is the max of the last /N/ samples. + +[variablelist + [[Result Type] [``_sample_type_``]] + [[Depends On] [`lazy_rolling_max` depends on `rolling_window` \n + `immediate_rolling_max` depends on `sorted_rolling_window`]] + [[Variants] [`lazy_rolling_max` (a.k.a. `rolling_max(lazy)`) \n + `immediate_rolling_max` (a.k.a. `rolling_max(immediate)`)]] + [[Initialization Parameters] [`tag::rolling_window::window_size`]] + [[Accumulator Parameters] [['none]]] + [[Extractor Parameters] [['none]]] + [[Accumulator Complexity] [`lazy_rolling_max` is O(1) \n + `immediate_rolling_max` is O(log N), where N is the window size]] + [[Extractor Complexity] [`lazy_rolling_max` is O(N), where N is the window size \n + `immediate_rolling_max` is O(1)]] +] + +[*Header] +[def _ROLLING_MAX_HPP_ [headerref boost/accumulators/statistics/rolling_max.hpp]] + + #include <_ROLLING_MAX_HPP_> + +[*Example] + + accumulator_set > acc(tag::rolling_window::window_size = 3); + + acc(1); + BOOST_CHECK_EQUAL(1, rolling_max(acc)); + + acc(2); + BOOST_CHECK_EQUAL(2, rolling_max(acc)); + + acc(3); + BOOST_CHECK_EQUAL(3, rolling_max(acc)); + + acc(1); + BOOST_CHECK_EQUAL(3, rolling_max(acc)); + + acc(-1); + BOOST_CHECK_EQUAL(1, rolling_max(acc)); + + acc(0); + BOOST_CHECK_EQUAL(1, rolling_max(acc)); + +[*See also] + +* [classref boost::accumulators::impl::lazy_rolling_max_impl [^lazy_rolling_max_impl]] +* [classref boost::accumulators::impl::immediate_rolling_max_impl [^immediate_rolling_max_impl]] + +[endsect] + +[section:rolling_min rolling_min] + +The rolling min is the min of the last /N/ samples. + +[variablelist + [[Result Type] [``_sample_type_``]] + [[Depends On] [`lazy_rolling_min` depends on `rolling_window` \n + `immediate_rolling_min` depends on `sorted_rolling_window`]] + [[Variants] [`lazy_rolling_min` (a.k.a. `rolling_min(lazy)`) \n + `immediate_rolling_min` (a.k.a. `rolling_min(immediate)`)]] + [[Initialization Parameters] [`tag::rolling_window::window_size`]] + [[Accumulator Parameters] [['none]]] + [[Extractor Parameters] [['none]]] + [[Accumulator Complexity] [`lazy_rolling_min` is O(1) \n + `immediate_rolling_min` is O(log N), where N is the window size]] + [[Extractor Complexity] [`lazy_rolling_min` is O(N), where N is the window size \n + `immediate_rolling_min` is O(1)]] +] + +[*Header] +[def _ROLLING_MIN_HPP_ [headerref boost/accumulators/statistics/rolling_min.hpp]] + + #include <_ROLLING_MIN_HPP_> + +[*Example] + + accumulator_set > acc(tag::rolling_window::window_size = 3); + + acc(1); + BOOST_CHECK_EQUAL(1, rolling_min(acc)); + + acc(2); + BOOST_CHECK_EQUAL(1, rolling_min(acc)); + + acc(3); + BOOST_CHECK_EQUAL(1, rolling_min(acc)); + + acc(4); + BOOST_CHECK_EQUAL(2, rolling_min(acc)); + + acc(-1); + BOOST_CHECK_EQUAL(-1, rolling_min(acc)); + +[*See also] + +* [classref boost::accumulators::impl::lazy_rolling_min_impl [^lazy_rolling_min_impl]] +* [classref boost::accumulators::impl::immediate_rolling_min_impl [^immediate_rolling_min_impl]] + +[endsect] + [section:rolling_sum rolling_sum] The rolling sum is the sum of the last /N/ samples. diff --git a/include/boost/accumulators/statistics/rolling_max.hpp b/include/boost/accumulators/statistics/rolling_max.hpp new file mode 100644 index 0000000..c3b57b7 --- /dev/null +++ b/include/boost/accumulators/statistics/rolling_max.hpp @@ -0,0 +1,163 @@ +/////////////////////////////////////////////////////////////////////////////// +// rolling_max.hpp +// +// Copyright 2018 Quentin Chateau. 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) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_ROLLING_MAX_HPP_QC_20_12_2018 +#define BOOST_ACCUMULATORS_STATISTICS_ROLLING_MAX_HPP_QC_20_12_2018 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // immediate_rolling_max_impl + // max is calculated on insersion using a sorted_rolling_window + template + struct immediate_rolling_max_impl + : accumulator_base + { + // for boost::result_of + typedef Sample result_type; + + immediate_rolling_max_impl(dont_care) + { + } + + template + result_type result(Args const &args) const + { + if (sorted_rolling_window(args).empty()) + { + return numeric::as_min(Sample()); + } + return sorted_rolling_window(args).back(); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // lazy_rolling_max_impl + // max is calculated on extraction by iterating the rolling window + template + struct lazy_rolling_max_impl + : accumulator_base + { + // for boost::result_of + typedef Sample result_type; + + lazy_rolling_max_impl(dont_care) + { + } + + template + result_type result(Args const &args) const + { + if (rolling_window(args).empty()) + { + return numeric::as_min(Sample()); + } + return *max_element(rolling_window(args).begin(), rolling_window(args).end()); + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::immediate_rolling_max +// tag::lazy_rolling_max +// tag::rolling_max +// +namespace tag +{ + struct immediate_rolling_max + : depends_on< sorted_rolling_window > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::immediate_rolling_max_impl impl; + +#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::window_size named parameter + static boost::parameter::keyword const window_size; +#endif + }; + + struct lazy_rolling_max + : depends_on< rolling_window > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::lazy_rolling_max_impl impl; + +#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::window_size named parameter + static boost::parameter::keyword const window_size; +#endif + }; + + // make lazy_rolling_max the default implementation + struct rolling_max : lazy_rolling_max {}; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::rolling_max +// +namespace extract +{ + extractor const immediate_rolling_max = {}; + extractor const lazy_rolling_max = {}; + extractor const rolling_max = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(immediate_rolling_max) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(lazy_rolling_max) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_max) +} + +using extract::immediate_rolling_max; +using extract::lazy_rolling_max; +using extract::rolling_max; + +// rolling_max(lazy) -> lazy_rolling_max +template<> +struct as_feature +{ + typedef tag::lazy_rolling_max type; +}; + +// rolling_max(immediate) -> immediate_rolling_max +template<> +struct as_feature +{ + typedef tag::immediate_rolling_max type; +}; + +// for the purposes of feature-based dependency resolution, +// immediate_rolling_max provides the same feature as rolling_max +template<> +struct feature_of + : feature_of +{ +}; + +// for the purposes of feature-based dependency resolution, +// lazy_rolling_max provides the same feature as rolling_max +template<> +struct feature_of + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/include/boost/accumulators/statistics/rolling_min.hpp b/include/boost/accumulators/statistics/rolling_min.hpp new file mode 100644 index 0000000..c4fa4e0 --- /dev/null +++ b/include/boost/accumulators/statistics/rolling_min.hpp @@ -0,0 +1,163 @@ +/////////////////////////////////////////////////////////////////////////////// +// rolling_min.hpp +// +// Copyright 2018 Quentin Chateau. 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) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_ROLLING_MIN_HPP_QC_20_12_2018 +#define BOOST_ACCUMULATORS_STATISTICS_ROLLING_MIN_HPP_QC_20_12_2018 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // immediate_rolling_min_impl + // min is calculated on insersion using a sorted_rolling_window + template + struct immediate_rolling_min_impl + : accumulator_base + { + // for boost::result_of + typedef Sample result_type; + + immediate_rolling_min_impl(dont_care) + { + } + + template + result_type result(Args const &args) const + { + if (sorted_rolling_window(args).empty()) + { + return numeric::as_max(Sample()); + } + return sorted_rolling_window(args).front(); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // lazy_rolling_min_impl + // min is calculated on extraction by iterating the rolling window + template + struct lazy_rolling_min_impl + : accumulator_base + { + // for boost::result_of + typedef Sample result_type; + + lazy_rolling_min_impl(dont_care) + { + } + + template + result_type result(Args const &args) const + { + if (rolling_window(args).empty()) + { + return numeric::as_max(Sample()); + } + return *min_element(rolling_window(args).begin(), rolling_window(args).end()); + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::immediate_rolling_min +// tag::lazy_rolling_min +// tag::rolling_min +// +namespace tag +{ + struct immediate_rolling_min + : depends_on< sorted_rolling_window > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::immediate_rolling_min_impl impl; + +#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::window_size named parameter + static boost::parameter::keyword const window_size; +#endif + }; + + struct lazy_rolling_min + : depends_on< rolling_window > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::lazy_rolling_min_impl impl; + +#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::window_size named parameter + static boost::parameter::keyword const window_size; +#endif + }; + + // make lazy_rolling_min the default implementation + struct rolling_min : lazy_rolling_min {}; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::rolling_min +// +namespace extract +{ + extractor const immediate_rolling_min = {}; + extractor const lazy_rolling_min = {}; + extractor const rolling_min = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(immediate_rolling_min) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(lazy_rolling_min) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_min) +} + +using extract::immediate_rolling_min; +using extract::lazy_rolling_min; +using extract::rolling_min; + +// rolling_min(lazy) -> lazy_rolling_min +template<> +struct as_feature +{ + typedef tag::lazy_rolling_min type; +}; + +// rolling_min(immediate) -> immediate_rolling_min +template<> +struct as_feature +{ + typedef tag::immediate_rolling_min type; +}; + +// for the purposes of feature-based dependency resolution, +// immediate_rolling_min provides the same feature as rolling_min +template<> +struct feature_of + : feature_of +{ +}; + +// for the purposes of feature-based dependency resolution, +// lazy_rolling_min provides the same feature as rolling_min +template<> +struct feature_of + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/include/boost/accumulators/statistics/rolling_window.hpp b/include/boost/accumulators/statistics/rolling_window.hpp index a43ecdf..9e4045c 100644 --- a/include/boost/accumulators/statistics/rolling_window.hpp +++ b/include/boost/accumulators/statistics/rolling_window.hpp @@ -138,6 +138,43 @@ namespace impl return find_accumulator(args[accumulator]).full(); } +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::rolling_window_plus1 +// +namespace tag +{ + struct rolling_window_plus1 + : depends_on<> + , tag::rolling_window_size + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::rolling_window_plus1_impl< mpl::_1 > impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::size named parameter + static boost::parameter::keyword const window_size; + #endif + }; + +} // namespace tag + +/////////////////////////////////////////////////////////////////////////////// +// extract::rolling_window_plus1 +// +namespace extract +{ + extractor const rolling_window_plus1 = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window_plus1) +} + +using extract::rolling_window_plus1; + +namespace impl +{ /////////////////////////////////////////////////////////////////////////////// // rolling_window_impl // stores the latest N samples, where N is specified at construction type @@ -166,25 +203,10 @@ namespace impl } // namespace impl /////////////////////////////////////////////////////////////////////////////// -// tag::rolling_window_plus1 // tag::rolling_window // namespace tag { - struct rolling_window_plus1 - : depends_on<> - , tag::rolling_window_size - { - /// INTERNAL ONLY - /// - typedef accumulators::impl::rolling_window_plus1_impl< mpl::_1 > impl; - - #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED - /// tag::rolling_window::size named parameter - static boost::parameter::keyword const window_size; - #endif - }; - struct rolling_window : depends_on< rolling_window_plus1 > { @@ -201,19 +223,15 @@ namespace tag } // namespace tag /////////////////////////////////////////////////////////////////////////////// -// extract::rolling_window_plus1 // extract::rolling_window // namespace extract { - extractor const rolling_window_plus1 = {}; extractor const rolling_window = {}; - BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window_plus1) BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window) } -using extract::rolling_window_plus1; using extract::rolling_window; }} // namespace boost::accumulators diff --git a/include/boost/accumulators/statistics/sorted_rolling_window.hpp b/include/boost/accumulators/statistics/sorted_rolling_window.hpp new file mode 100644 index 0000000..56e7638 --- /dev/null +++ b/include/boost/accumulators/statistics/sorted_rolling_window.hpp @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////// +// sorted_rolling_window.hpp +// +// Copyright 2018 Quentin Chateau. 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) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_SORTED_ROLLING_WINDOW_HPP_QC_20_12_2018 +#define BOOST_ACCUMULATORS_STATISTICS_SORTED_ROLLING_WINDOW_HPP_QC_20_12_2018 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // sorted_rolling_window + // stores the latest N samples, where N is specified at construction time + // with the rolling_window_size named parameter. samples are sorted + // on insersion + template + struct sorted_rolling_window_impl + : accumulator_base + { + typedef typename container::multiset::const_iterator const_iterator; + typedef iterator_range result_type; + + template + sorted_rolling_window_impl(Args const &) + {} + + template + void operator ()(Args const &args) + { + if(is_rolling_window_plus1_full(args)) + { + const_iterator it = this->sorted_buffer_.find(rolling_window_plus1(args).front()); + this->sorted_buffer_.erase(it); + } + this->sorted_buffer_.insert(args[sample]); + } + + result_type result(dont_care) const + { + return result_type(this->sorted_buffer_.begin(), this->sorted_buffer_.end()); + } + + private: + container::multiset sorted_buffer_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::sorted_rolling_window +// +namespace tag +{ + struct sorted_rolling_window + : depends_on< rolling_window_plus1 > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::sorted_rolling_window_impl< mpl::_1 > impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::sorted_rolling_window::size named parameter + static boost::parameter::keyword const window_size; + #endif + }; + +} // namespace tag + +/////////////////////////////////////////////////////////////////////////////// +// extract::sorted_rolling_window +// +namespace extract +{ + extractor const sorted_rolling_window = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(sorted_rolling_window) +} + +using extract::sorted_rolling_window; + +}} // namespace boost::accumulators + +#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6d2dbf0..e98f2fd 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -48,10 +48,13 @@ alias accumulators_regular_tests [ run reference.cpp ] [ run rolling_count.cpp ] [ run rolling_sum.cpp ] + [ run rolling_max.cpp ] [ run rolling_mean.cpp ] + [ run rolling_min.cpp ] [ run rolling_variance.cpp ] [ run rolling_moment.cpp ] [ run skewness.cpp ] + [ run sorted_rolling_window.cpp ] [ run sum.cpp ] [ run sum_kahan.cpp ] [ run tail.cpp ] diff --git a/test/rolling_max.cpp b/test/rolling_max.cpp new file mode 100644 index 0000000..720560a --- /dev/null +++ b/test/rolling_max.cpp @@ -0,0 +1,80 @@ +// (C) Copyright Quentin Chateau 2018. +// Use, modification and distribution are subject to 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 +#include +#include +#include +#include + +using namespace boost; +using namespace unit_test; +using namespace accumulators; +using namespace container; + +size_t window_size = 3; + +/////////////////////////////////////////////////////////////////////////////// +// test_impl +// +template +void test_impl(Accumulator& acc) +{ + BOOST_CHECK_EQUAL(numeric::as_min(int()), rolling_max(acc)); + + acc(1); + BOOST_CHECK_EQUAL(1, rolling_max(acc)); + + acc(3); + BOOST_CHECK_EQUAL(3, rolling_max(acc)); + + acc(5); + BOOST_CHECK_EQUAL(5, rolling_max(acc)); + + acc(7); + BOOST_CHECK_EQUAL(7, rolling_max(acc)); + + acc(6); + BOOST_CHECK_EQUAL(7, rolling_max(acc)); + + acc(1); + BOOST_CHECK_EQUAL(7, rolling_max(acc)); + + acc(3); + BOOST_CHECK_EQUAL(6, rolling_max(acc)); + + acc(2); + BOOST_CHECK_EQUAL(3, rolling_max(acc)); +} + +void test_rolling_max() +{ + accumulator_set > acc_default(tag::rolling_window::window_size = window_size); + test_impl(acc_default); + + accumulator_set > acc_lazy(tag::rolling_window::window_size = window_size); + test_impl(acc_lazy); + + accumulator_set > acc_lazy2(tag::rolling_window::window_size = window_size); + test_impl(acc_lazy2); + + accumulator_set > acc_immediate(tag::rolling_window::window_size = window_size); + test_impl(acc_immediate); + + accumulator_set > acc_immediate2(tag::rolling_window::window_size = window_size); + test_impl(acc_immediate2); +} + +/////////////////////////////////////////////////////////////////////////////// +// init_unit_test_suite +// +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite *test = BOOST_TEST_SUITE("rolling max test"); + + test->add(BOOST_TEST_CASE(&test_rolling_max)); + + return test; +} diff --git a/test/rolling_min.cpp b/test/rolling_min.cpp new file mode 100644 index 0000000..8e522a8 --- /dev/null +++ b/test/rolling_min.cpp @@ -0,0 +1,77 @@ +// (C) Copyright Quentin Chateau 2018. +// Use, modification and distribution are subject to 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 +#include +#include +#include +#include + +using namespace boost; +using namespace unit_test; +using namespace accumulators; +using namespace container; + +size_t window_size = 3; + +/////////////////////////////////////////////////////////////////////////////// +// test_impl +// +template +void test_impl(Accumulator& acc) +{ + BOOST_CHECK_EQUAL(numeric::as_max(int()), rolling_min(acc)); + + acc(1); + BOOST_CHECK_EQUAL(1, rolling_min(acc)); + + acc(3); + BOOST_CHECK_EQUAL(1, rolling_min(acc)); + + acc(5); + BOOST_CHECK_EQUAL(1, rolling_min(acc)); + + acc(7); + BOOST_CHECK_EQUAL(3, rolling_min(acc)); + + acc(6); + BOOST_CHECK_EQUAL(5, rolling_min(acc)); + + acc(7); + BOOST_CHECK_EQUAL(6, rolling_min(acc)); + + acc(1); + BOOST_CHECK_EQUAL(1, rolling_min(acc)); +} + +void test_rolling_min() +{ + accumulator_set > acc_default(tag::rolling_window::window_size = window_size); + test_impl(acc_default); + + accumulator_set > acc_lazy(tag::rolling_window::window_size = window_size); + test_impl(acc_lazy); + + accumulator_set > acc_lazy2(tag::rolling_window::window_size = window_size); + test_impl(acc_lazy2); + + accumulator_set > acc_immediate(tag::rolling_window::window_size = window_size); + test_impl(acc_immediate); + + accumulator_set > acc_immediate2(tag::rolling_window::window_size = window_size); + test_impl(acc_immediate2); +} + +/////////////////////////////////////////////////////////////////////////////// +// init_unit_test_suite +// +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite *test = BOOST_TEST_SUITE("rolling min test"); + + test->add(BOOST_TEST_CASE(&test_rolling_min)); + + return test; +} diff --git a/test/sorted_rolling_window.cpp b/test/sorted_rolling_window.cpp new file mode 100644 index 0000000..c07e4f5 --- /dev/null +++ b/test/sorted_rolling_window.cpp @@ -0,0 +1,68 @@ +// (C) Copyright Quentin Chateau 2018. +// Use, modification and distribution are subject to 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 +#include +#include +#include +#include + +using namespace boost; +using namespace unit_test; +using namespace accumulators; +using namespace container; + +typedef accumulator_set > SortedAccumulator; + +/////////////////////////////////////////////////////////////////////////////// +// check_equal +// +void check_equal(const multiset& expected, const SortedAccumulator& acc) +{ + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), sorted_rolling_window(acc).begin(), sorted_rolling_window(acc).end()); +} + +/////////////////////////////////////////////////////////////////////////////// +// test_stat +// +void test_stat() +{ + SortedAccumulator acc(tag::rolling_window::window_size = 3); + + check_equal({}, acc); + + acc(1); + check_equal({1}, acc); + + acc(3); + check_equal({1, 3}, acc); + + acc(5); + check_equal({1, 3, 5}, acc); + + acc(7); + check_equal({3, 5, 7}, acc); + + acc(6); + check_equal({5, 6, 7}, acc); + + acc(7); + check_equal({6, 7, 7}, acc); + + acc(1); + check_equal({1, 6, 7}, acc); +} + +/////////////////////////////////////////////////////////////////////////////// +// init_unit_test_suite +// +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite *test = BOOST_TEST_SUITE("sorted rolling window test"); + + test->add(BOOST_TEST_CASE(&test_stat)); + + return test; +}