Imported Upstream version 1.71.0
[platform/upstream/boost.git] / libs / histogram / test / internal_accumulators_test.cpp
1 // Copyright 2015-2018 Hans Dembinski
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt
5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7 #include <boost/core/lightweight_test.hpp>
8 #include <boost/histogram/accumulators/mean.hpp>
9 #include <boost/histogram/accumulators/ostream.hpp>
10 #include <boost/histogram/accumulators/sum.hpp>
11 #include <boost/histogram/accumulators/thread_safe.hpp>
12 #include <boost/histogram/accumulators/weighted_mean.hpp>
13 #include <boost/histogram/accumulators/weighted_sum.hpp>
14 #include "throw_exception.hpp"
15 #include <sstream>
16 #include "is_close.hpp"
17
18 using namespace boost::histogram;
19 using namespace std::literals;
20
21 template <class T>
22 auto str(const T& t) {
23   std::ostringstream os;
24   os << t;
25   return os.str();
26 }
27
28 int main() {
29   {
30     using w_t = accumulators::weighted_sum<double>;
31     w_t w;
32     BOOST_TEST_EQ(str(w), "weighted_sum(0, 0)"s);
33
34     BOOST_TEST_EQ(w, w_t(0));
35     BOOST_TEST_NE(w, w_t(1));
36     w = w_t(1);
37     BOOST_TEST_EQ(w.value(), 1);
38     BOOST_TEST_EQ(w.variance(), 1);
39     BOOST_TEST_EQ(w, 1);
40     BOOST_TEST_NE(w, 2);
41
42     w += 2;
43     BOOST_TEST_EQ(w.value(), 3);
44     BOOST_TEST_EQ(w.variance(), 5);
45     BOOST_TEST_EQ(w, w_t(3, 5));
46     BOOST_TEST_NE(w, w_t(3));
47
48     w += w_t(1, 2);
49     BOOST_TEST_EQ(w.value(), 4);
50     BOOST_TEST_EQ(w.variance(), 7);
51
52     // consistency: a weighted counter increased by weight 1 multiplied
53     // by 2 must be the same as a weighted counter increased by weight 2
54     w_t u(0);
55     ++u;
56     u *= 2;
57     BOOST_TEST_EQ(u, w_t(2, 4));
58
59     w_t v(0);
60     v += 2;
61     BOOST_TEST_EQ(u, v);
62
63     // conversion to RealType
64     w_t y(1, 2);
65     BOOST_TEST_NE(y, 1);
66     BOOST_TEST_EQ(static_cast<double>(y), 1);
67   }
68
69   {
70     using m_t = accumulators::mean<double>;
71     m_t a;
72     BOOST_TEST_EQ(a.count(), 0);
73
74     a(4);
75     a(7);
76     a(13);
77     a(16);
78
79     BOOST_TEST_EQ(a.count(), 4);
80     BOOST_TEST_EQ(a.value(), 10);
81     BOOST_TEST_EQ(a.variance(), 30);
82
83     BOOST_TEST_EQ(str(a), "mean(4, 10, 30)"s);
84
85     m_t b;
86     b(1e8 + 4);
87     b(1e8 + 7);
88     b(1e8 + 13);
89     b(1e8 + 16);
90
91     BOOST_TEST_EQ(b.count(), 4);
92     BOOST_TEST_EQ(b.value(), 1e8 + 10);
93     BOOST_TEST_EQ(b.variance(), 30);
94
95     auto c = a;
96     c += a; // same as feeding all samples twice
97
98     BOOST_TEST_EQ(c.count(), 8);
99     BOOST_TEST_EQ(c.value(), 10);
100     BOOST_TEST_IS_CLOSE(c.variance(), 25.714, 1e-3);
101   }
102
103   {
104     using m_t = accumulators::weighted_mean<double>;
105     m_t a;
106     BOOST_TEST_EQ(a.sum_of_weights(), 0);
107
108     a(0.5, 1);
109     a(1.0, 2);
110     a(0.5, 3);
111
112     BOOST_TEST_EQ(a.sum_of_weights(), 2);
113     BOOST_TEST_EQ(a.value(), 2);
114     BOOST_TEST_IS_CLOSE(a.variance(), 0.8, 1e-3);
115
116     BOOST_TEST_EQ(str(a), "weighted_mean(2, 2, 0.8)"s);
117
118     auto b = a;
119     b += a; // same as feeding all samples twice
120
121     BOOST_TEST_EQ(b.sum_of_weights(), 4);
122     BOOST_TEST_EQ(b.value(), 2);
123     BOOST_TEST_IS_CLOSE(b.variance(), 0.615, 1e-3);
124   }
125
126   {
127     double bad_sum = 0;
128     bad_sum += 1;
129     bad_sum += 1e100;
130     bad_sum += 1;
131     bad_sum += -1e100;
132     BOOST_TEST_EQ(bad_sum, 0); // instead of 2
133
134     accumulators::sum<double> sum;
135     ++sum;
136     BOOST_TEST_EQ(sum.large(), 1);
137     BOOST_TEST_EQ(sum.small(), 0);
138     BOOST_TEST_EQ(str(sum), "sum(1 + 0)"s);
139     sum += 1e100;
140     BOOST_TEST_EQ(str(sum), "sum(1e+100 + 1)"s);
141     ++sum;
142     BOOST_TEST_EQ(str(sum), "sum(1e+100 + 2)"s);
143     sum += -1e100;
144     BOOST_TEST_EQ(str(sum), "sum(0 + 2)"s);
145     BOOST_TEST_EQ(sum, 2); // correct answer
146     BOOST_TEST_EQ(sum.large(), 0);
147     BOOST_TEST_EQ(sum.small(), 2);
148
149     accumulators::sum<double> a(3), b(2), c(3);
150     BOOST_TEST_LT(b, c);
151     BOOST_TEST_LE(b, c);
152     BOOST_TEST_LE(a, c);
153     BOOST_TEST_GT(a, b);
154     BOOST_TEST_GE(a, b);
155     BOOST_TEST_GE(a, c);
156   }
157
158   {
159     accumulators::weighted_sum<accumulators::sum<double>> w;
160
161     ++w;
162     w += 1e100;
163     ++w;
164     w += -1e100;
165
166     BOOST_TEST_EQ(w.value(), 2);
167     BOOST_TEST_EQ(w.variance(), 2e200);
168   }
169
170   {
171     accumulators::thread_safe<int> i;
172     ++i;
173     i += 1000;
174
175     BOOST_TEST_EQ(i, 1001);
176     BOOST_TEST_EQ(str(i), "1001"s);
177   }
178
179   return boost::report_errors();
180 }