1// (C) Copyright Pieter Bastiaan Ober 2014.
2// Use, modification and distribution are subject to the
3// Boost Software License, Version 1.0. (See accompanying file
4// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#include <boost/test/unit_test.hpp>
7#include <boost/test/tools/floating_point_comparison.hpp>
8#include <boost/mpl/assert.hpp>
9#include <boost/type_traits/is_same.hpp>
10#include <boost/accumulators/accumulators.hpp>
11#include <boost/accumulators/statistics/stats.hpp>
12#include <sstream>
13#include <boost/archive/text_oarchive.hpp>
14#include <boost/archive/text_iarchive.hpp>
15#include <boost/accumulators/statistics/rolling_variance.hpp>
16
17using namespace boost;
18using namespace unit_test;
19using namespace accumulators;
20
21template<typename T>
22void assert_is_double(T const &)
23{
24 BOOST_MPL_ASSERT((is_same<T, double>));
25}
26
27/*
28REFERENCE VALUES PROVIDED BY OCTAVE:
29
30x=[1.2 2.3 3.4 4.5 0.4 2.2 7.1 4.0]
31
32v1_2 = var(x(1:2))
33v1_3 = var(x(1:3))
34v1_4 = var(x(1:4))
35v2_5 = var(x(2:5))
36v3_6 = var(x(3:6))
37v4_7 = var(x(4:7))
38v5_8 = var(x(5:8))
39
40GIVES:
41
42v1_2 = 0.605000000000000
43v1_3 = 1.21000000000000
44v1_4 = 2.01666666666667
45v2_5 = 3.05666666666667
46v3_6 = 3.08250000000000
47v4_7 = 8.41666666666667
48v5_8 = 8.16250000000000
49*/
50
51///////////////////////////////////////////////////////////////////////////////
52// rolling_variance_test_impl
53// implements a test for window_size = 4
54
55size_t window_size = 4;
56
57template<typename accumulator_set_type>
58void rolling_variance_test_impl(accumulator_set_type& acc)
59{
60 // Window contains x(1), value is zero
61 acc(1.2);
62 BOOST_CHECK_CLOSE(rolling_variance(acc),0.0,1e-10);
63
64 // Window contains x(1)...x(2)
65 acc(2.3);
66 BOOST_CHECK_CLOSE(rolling_variance(acc),0.605,1e-10);
67
68 // Window contains x(1)...x(3)
69 acc(3.4);
70 BOOST_CHECK_CLOSE(rolling_variance(acc),1.21,1e-10);
71
72 // Window contains x(1)...x(4)
73 acc(4.5);
74 BOOST_CHECK_CLOSE(rolling_variance(acc),2.01666666666667,1e-10);
75
76 // Window contains x(2)...x(5)
77 acc(0.4);
78 BOOST_CHECK_CLOSE(rolling_variance(acc),3.05666666666667,1e-10);
79
80 // Window contains x(3)...x(6)
81 acc(2.2);
82 BOOST_CHECK_CLOSE(rolling_variance(acc),3.08250000000000,1e-10);
83
84 // Window contains x(4)...x(7)
85 acc(7.1);
86 BOOST_CHECK_CLOSE(rolling_variance(acc),8.41666666666667,1e-10);
87
88 // Window contains x(5)...x(8)
89 acc(4.0);
90 BOOST_CHECK_CLOSE(rolling_variance(acc),8.16250000000000,1e-10);
91
92 assert_is_double(rolling_variance(acc));
93}
94
95///////////////////////////////////////////////////////////////////////////////
96// test_rolling_variance
97//
98void test_rolling_variance()
99{
100 // tag::rolling_window::window_size
101 accumulator_set<double, stats<tag::immediate_rolling_variance> >
102 acc_immediate_rolling_variance(tag::immediate_rolling_variance::window_size = window_size);
103
104 accumulator_set<double, stats<tag::immediate_rolling_variance, tag::rolling_mean> >
105 acc_immediate_rolling_variance2(tag::immediate_rolling_variance::window_size = window_size);
106
107 accumulator_set<double, stats<tag::rolling_variance(immediate)> >
108 acc_immediate_rolling_variance3(tag::immediate_rolling_variance::window_size = window_size);
109
110 accumulator_set<double, stats<tag::lazy_rolling_variance> >
111 acc_lazy_rolling_variance(tag::lazy_rolling_variance::window_size = window_size);
112
113 accumulator_set<double, stats<tag::rolling_variance(lazy)> >
114 acc_lazy_rolling_variance2(tag::immediate_rolling_variance::window_size = window_size);
115
116 accumulator_set<double, stats<tag::rolling_variance> >
117 acc_default_rolling_variance(tag::rolling_variance::window_size = window_size);
118
119 //// test the different implementations
120 rolling_variance_test_impl(acc&: acc_immediate_rolling_variance);
121 rolling_variance_test_impl(acc&: acc_immediate_rolling_variance2);
122 rolling_variance_test_impl(acc&: acc_immediate_rolling_variance3);
123 rolling_variance_test_impl(acc&: acc_lazy_rolling_variance);
124 rolling_variance_test_impl(acc&: acc_lazy_rolling_variance2);
125 rolling_variance_test_impl(acc&: acc_default_rolling_variance);
126
127 //// test that the default implementation is the 'immediate' computation
128 BOOST_REQUIRE(sizeof(acc_lazy_rolling_variance) != sizeof(acc_immediate_rolling_variance));
129 BOOST_CHECK (sizeof(acc_default_rolling_variance) == sizeof(acc_immediate_rolling_variance));
130
131 //// test the equivalence of the different ways to indicate a feature
132 BOOST_CHECK (sizeof(acc_immediate_rolling_variance) == sizeof(acc_immediate_rolling_variance2));
133 BOOST_CHECK (sizeof(acc_immediate_rolling_variance) == sizeof(acc_immediate_rolling_variance3));
134 BOOST_CHECK (sizeof(acc_lazy_rolling_variance) == sizeof(acc_lazy_rolling_variance2));
135}
136
137///////////////////////////////////////////////////////////////////////////////
138// test_persistency_impl
139//
140template<typename accumulator_set_type>
141void test_persistency_impl(accumulator_set_type& acc)
142{
143 std::stringstream ss;
144 {
145 acc(1.2);
146 acc(2.3);
147 acc(3.4);
148 acc(4.5);
149 acc(0.4);
150 acc(2.2);
151 acc(7.1);
152 acc(4.0);
153 BOOST_CHECK_CLOSE(rolling_variance(acc),8.16250000000000,1e-10);
154 boost::archive::text_oarchive oa(ss);
155 acc.serialize(oa, 0);
156 }
157 accumulator_set_type other_acc = acc;
158 boost::archive::text_iarchive ia(ss);
159 other_acc.serialize(ia, 0);
160 BOOST_CHECK_CLOSE(rolling_variance(acc),8.16250000000000,1e-10);
161
162}
163
164///////////////////////////////////////////////////////////////////////////////
165// test_persistency
166//
167void test_persistency()
168{
169 // tag::rolling_window::window_size
170 accumulator_set<double, stats<tag::immediate_rolling_variance> >
171 acc_immediate_rolling_variance(tag::immediate_rolling_variance::window_size = window_size);
172
173 accumulator_set<double, stats<tag::immediate_rolling_variance, tag::rolling_mean> >
174 acc_immediate_rolling_variance2(tag::immediate_rolling_variance::window_size = window_size);
175
176 accumulator_set<double, stats<tag::rolling_variance(immediate)> >
177 acc_immediate_rolling_variance3(tag::immediate_rolling_variance::window_size = window_size);
178
179 accumulator_set<double, stats<tag::lazy_rolling_variance> >
180 acc_lazy_rolling_variance(tag::lazy_rolling_variance::window_size = window_size);
181
182 accumulator_set<double, stats<tag::rolling_variance(lazy)> >
183 acc_lazy_rolling_variance2(tag::immediate_rolling_variance::window_size = window_size);
184
185 accumulator_set<double, stats<tag::rolling_variance> >
186 acc_default_rolling_variance(tag::rolling_variance::window_size = window_size);
187
188 //// test the different implementations
189 test_persistency_impl(acc&: acc_immediate_rolling_variance);
190 test_persistency_impl(acc&: acc_immediate_rolling_variance2);
191 test_persistency_impl(acc&: acc_immediate_rolling_variance3);
192 test_persistency_impl(acc&: acc_lazy_rolling_variance);
193 test_persistency_impl(acc&: acc_lazy_rolling_variance2);
194 test_persistency_impl(acc&: acc_default_rolling_variance);
195}
196
197///////////////////////////////////////////////////////////////////////////////
198// init_unit_test_suite
199//
200test_suite* init_unit_test_suite( int argc, char* argv[] )
201{
202 test_suite *test = BOOST_TEST_SUITE("rolling variance test");
203
204 test->add(BOOST_TEST_CASE(&test_rolling_variance));
205 test->add(BOOST_TEST_CASE(&test_persistency));
206
207 return test;
208}
209

source code of boost/libs/accumulators/test/rolling_variance.cpp