]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/histogram/test/histogram_operators_test.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / histogram / test / histogram_operators_test.cpp
CommitLineData
92f5a8d4
TL
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/is_same.hpp>
8#include <boost/core/lightweight_test.hpp>
9#include <boost/core/lightweight_test_trait.hpp>
10#include <boost/histogram/axis.hpp>
11#include <boost/histogram/axis/ostream.hpp>
f67539c2 12#include <boost/histogram/detail/detect.hpp>
92f5a8d4
TL
13#include <boost/histogram/histogram.hpp>
14#include <boost/histogram/ostream.hpp>
15#include <boost/throw_exception.hpp>
16#include <string>
17#include <vector>
f67539c2 18#include "dummy_storage.hpp"
92f5a8d4
TL
19#include "std_ostream.hpp"
20#include "throw_exception.hpp"
21#include "utility_histogram.hpp"
22
23using namespace boost::histogram;
24
25template <typename Tag>
26void run_tests() {
27 // arithmetic operators
28 {
20effc67 29 auto a = make(Tag(), axis::integer<>(0, 2));
92f5a8d4 30 auto b = a;
20effc67
TL
31 a.at(-1) = 2;
32 a.at(0) = 1;
33 b.at(-1) = 1;
34 b.at(1) = 1;
35 b.at(2) = 3;
36
92f5a8d4 37 auto c = a + b;
20effc67 38 BOOST_TEST_EQ(c.at(-1), 3);
92f5a8d4
TL
39 BOOST_TEST_EQ(c.at(0), 1);
40 BOOST_TEST_EQ(c.at(1), 1);
20effc67
TL
41 BOOST_TEST_EQ(c.at(2), 3);
42
92f5a8d4 43 c += b;
20effc67 44 BOOST_TEST_EQ(c.at(-1), 4);
92f5a8d4
TL
45 BOOST_TEST_EQ(c.at(0), 1);
46 BOOST_TEST_EQ(c.at(1), 2);
20effc67
TL
47 BOOST_TEST_EQ(c.at(2), 6);
48
92f5a8d4
TL
49 auto d = a + b + c;
50 BOOST_TEST_TRAIT_SAME(decltype(d), decltype(a));
20effc67 51 BOOST_TEST_EQ(d.at(-1), 7);
92f5a8d4
TL
52 BOOST_TEST_EQ(d.at(0), 2);
53 BOOST_TEST_EQ(d.at(1), 3);
20effc67 54 BOOST_TEST_EQ(d.at(2), 9);
92f5a8d4
TL
55
56 auto d2 = d - a - b - c;
57 BOOST_TEST_TRAIT_SAME(decltype(d2), decltype(a));
20effc67 58 BOOST_TEST_EQ(d2.at(-1), 0);
92f5a8d4
TL
59 BOOST_TEST_EQ(d2.at(0), 0);
60 BOOST_TEST_EQ(d2.at(1), 0);
20effc67
TL
61 BOOST_TEST_EQ(d2.at(2), 0);
62
92f5a8d4 63 d2 -= a;
20effc67 64 BOOST_TEST_EQ(d2.at(-1), -2);
92f5a8d4
TL
65 BOOST_TEST_EQ(d2.at(0), -1);
66 BOOST_TEST_EQ(d2.at(1), 0);
20effc67 67 BOOST_TEST_EQ(d2.at(2), 0);
92f5a8d4
TL
68
69 auto d3 = d;
70 d3 *= d;
20effc67 71 BOOST_TEST_EQ(d3.at(-1), 49);
92f5a8d4
TL
72 BOOST_TEST_EQ(d3.at(0), 4);
73 BOOST_TEST_EQ(d3.at(1), 9);
20effc67
TL
74 BOOST_TEST_EQ(d3.at(2), 81);
75
92f5a8d4
TL
76 auto d4 = d3 * (1 * d); // converted return type
77 BOOST_TEST_TRAIT_FALSE((boost::core::is_same<decltype(d4), decltype(d3)>));
78 BOOST_TEST_EQ(d4.at(0), 8);
79 BOOST_TEST_EQ(d4.at(1), 27);
80 d4 /= d;
81 BOOST_TEST_EQ(d4.at(0), 4);
82 BOOST_TEST_EQ(d4.at(1), 9);
83 auto d5 = d4 / d;
84 BOOST_TEST_EQ(d5.at(0), 2);
85 BOOST_TEST_EQ(d5.at(1), 3);
86
87 auto e = 3 * a; // converted return type
88 auto f = b * 2; // converted return type
89 BOOST_TEST_TRAIT_FALSE((boost::core::is_same<decltype(e), decltype(a)>));
90 BOOST_TEST_TRAIT_FALSE((boost::core::is_same<decltype(f), decltype(a)>));
91 BOOST_TEST_EQ(e.at(0), 3);
92 BOOST_TEST_EQ(e.at(1), 0);
93 BOOST_TEST_EQ(f.at(0), 0);
94 BOOST_TEST_EQ(f.at(1), 2);
95 auto r = 1.0 * a;
96 r += b;
97 r += e;
98 BOOST_TEST_EQ(r.at(0), 4);
99 BOOST_TEST_EQ(r.at(1), 1);
100 BOOST_TEST_EQ(r, a + b + 3 * a);
101 auto s = r / 4;
102 r /= 4;
103 BOOST_TEST_EQ(r.at(0), 1);
104 BOOST_TEST_EQ(r.at(1), 0.25);
105 BOOST_TEST_EQ(r, s);
106 }
107
108 // arithmetic operators with mixed storage: unlimited vs. vector<unsigned>
109 {
110 auto ia = axis::integer<int, axis::null_type, axis::option::none_t>(0, 2);
111 auto a = make(Tag(), ia);
112 a(0, weight(2));
113 a(1, weight(2));
114 auto b = a;
115 auto c = make_s(Tag(), std::vector<int>(), ia);
116 c(0, weight(2));
117 c(1, weight(2));
118 auto a2 = a;
119 a2 += c;
120 BOOST_TEST_EQ(a2, (a + b));
121 auto a3 = a;
122 a3 *= c;
123 BOOST_TEST_EQ(a3, (a * b));
124 auto a4 = a;
125 a4 -= c;
126 BOOST_TEST_EQ(a4, (a - b));
127 auto a5 = a;
128 a5 /= c;
129 BOOST_TEST_EQ(a5, (a / b));
130 }
131
132 // arithmetic operators with mixed storage: vector<unsigned char> vs. vector<unsigned>
133 {
134 auto ia = axis::integer<int, axis::null_type, axis::option::none_t>(0, 2);
135 auto a = make_s(Tag(), std::vector<unsigned long>{}, ia);
136 auto c = make_s(Tag(), std::vector<unsigned>(), ia);
137 a(0, weight(2u));
138 a(1, weight(2u));
139 auto b = a;
140 c(0, weight(2u));
141 c(1, weight(2u));
142 auto a2 = a;
143 a2 += c;
144 BOOST_TEST_EQ(a2, (a + b));
145 auto a3 = a;
146 a3 *= c;
147 BOOST_TEST_EQ(a3, (a * b));
148 auto a4 = a;
149 a4 -= c;
150 BOOST_TEST_EQ(a4, (a - b));
151 auto a5 = a;
152 a5 /= c;
153 BOOST_TEST_EQ(a5, (a / b));
154 }
155
156 // add operators with weighted storage
157 {
158 auto ia = axis::integer<int, axis::null_type, axis::option::none_t>(0, 2);
159 auto a = make_s(Tag(), std::vector<accumulators::weighted_sum<>>(), ia);
160 auto b = make_s(Tag(), std::vector<accumulators::weighted_sum<>>(), ia);
161
162 a(0);
163 BOOST_TEST_EQ(a.at(0).variance(), 1);
164 b(weight(3), 1);
165 BOOST_TEST_EQ(b.at(1).variance(), 9);
166 auto c = a;
167 c += b;
168 BOOST_TEST_EQ(c.at(0).value(), 1);
169 BOOST_TEST_EQ(c.at(0).variance(), 1);
170 BOOST_TEST_EQ(c.at(1).value(), 3);
171 BOOST_TEST_EQ(c.at(1).variance(), 9);
172 auto d = a;
173 d += b;
174 BOOST_TEST_EQ(d.at(0).value(), 1);
175 BOOST_TEST_EQ(d.at(0).variance(), 1);
176 BOOST_TEST_EQ(d.at(1).value(), 3);
177 BOOST_TEST_EQ(d.at(1).variance(), 9);
f67539c2
TL
178
179 // add unweighted histogram
180 auto e = make_s(Tag(), std::vector<int>(), ia);
181 std::fill(e.begin(), e.end(), 2);
182
183 d += e;
184 BOOST_TEST_EQ(d.at(0).value(), 3);
185 BOOST_TEST_EQ(d.at(0).variance(), 3);
186 BOOST_TEST_EQ(d.at(1).value(), 5);
187 BOOST_TEST_EQ(d.at(1).variance(), 11);
92f5a8d4
TL
188 }
189
20effc67
TL
190 // merging add
191 {
192 using C = axis::category<int, use_default, axis::option::growth_t>;
193 using I = axis::integer<int, axis::null_type, axis::option::growth_t>;
194
195 {
196 auto empty = std::initializer_list<int>{};
197 auto a = make(Tag(), C(empty, "foo"));
198 auto b = make(Tag(), C(empty, "foo"));
199 a(2);
200 a(1);
201 b(2);
202 b(3);
203 b(4);
204 a += b;
205 BOOST_TEST_EQ(a.axis(), C({2, 1, 3, 4}, "foo"));
206 BOOST_TEST_EQ(a[0], 2);
207 BOOST_TEST_EQ(a[1], 1);
208 BOOST_TEST_EQ(a[2], 1);
209 BOOST_TEST_EQ(a[3], 1);
210 }
211
212 {
213 auto a = make(Tag(), C{1, 2}, I{4, 5});
214 auto b = make(Tag(), C{2, 3}, I{5, 6});
215
216 std::fill(a.begin(), a.end(), 1);
217 std::fill(b.begin(), b.end(), 1);
218
219 a += b;
220
221 BOOST_TEST_EQ(a.axis(0), (C{1, 2, 3}));
222 BOOST_TEST_EQ(a.axis(1), (I{4, 6}));
223 BOOST_TEST_EQ(a.at(0, 0), 1);
224 BOOST_TEST_EQ(a.at(1, 0), 1);
225 BOOST_TEST_EQ(a.at(2, 0), 0); // v=(3, 4) did not exist in a or b
226 BOOST_TEST_EQ(a.at(0, 1), 0); // v=(1, 5) did not exist in a or b
227 BOOST_TEST_EQ(a.at(1, 1), 1);
228 BOOST_TEST_EQ(a.at(2, 1), 1);
229 }
230
231 {
232 using CI = axis::category<int, use_default, axis::option::growth_t>;
233 using CS = axis::category<std::string, use_default, axis::option::growth_t>;
234
235 auto h1 = make(Tag{}, CI{}, CS{});
236 auto h2 = make(Tag{}, CI{}, CS{});
237 auto h3 = make(Tag{}, CI{}, CS{});
238
239 h1(1, "b");
240 h1(2, "a");
241 h1(1, "a");
242 h1(2, "b");
243
244 h2(2, "b");
245 h2(3, "b");
246 h2(4, "c");
247 h2(5, "c");
248
249 h3(1, "b");
250 h3(2, "a");
251 h3(1, "a");
252 h3(2, "b");
253 h3(2, "b");
254 h3(3, "b");
255 h3(4, "c");
256 h3(5, "c");
257
258 BOOST_TEST_EQ(h3, h1 + h2);
259 }
260
261 {
262 // C2 is not growing and has overflow
263 using C2 = axis::category<int>;
264 auto a = make(Tag(), C{1, 2}, C2{4, 5});
265 auto b = make(Tag(), C{1, 2}, C2{5, 6});
266
267 // axis C2 is incompatible
268 BOOST_TEST_THROWS(a += b, std::invalid_argument);
269
270 std::fill(a.begin(), a.end(), 1);
271 b = a;
272 b(3, 4);
273 a += b;
274 BOOST_TEST_EQ(a.at(0, 0), 2);
275 BOOST_TEST_EQ(a.at(1, 0), 2);
276 BOOST_TEST_EQ(a.at(2, 0), 1);
277 BOOST_TEST_EQ(a.at(0, 1), 2);
278 BOOST_TEST_EQ(a.at(1, 1), 2);
279 BOOST_TEST_EQ(a.at(2, 1), 0);
280 BOOST_TEST_EQ(a.at(0, 2), 2);
281 BOOST_TEST_EQ(a.at(1, 2), 2);
282 BOOST_TEST_EQ(a.at(2, 2), 0);
283
284 // incompatible labels
285 b.axis(0).metadata() = "foo";
286 BOOST_TEST_THROWS(a += b, std::invalid_argument);
287
288 // incompatible axis types
289 auto c = make(Tag(), C{1, 2}, I{4, 6});
290 BOOST_TEST_THROWS(a += c, std::invalid_argument);
291 }
292 }
293
92f5a8d4
TL
294 // bad operations
295 {
20effc67
TL
296 auto a = make(Tag(), axis::regular<>(2, 0, 4));
297 auto b = make(Tag(), axis::regular<>(2, 0, 2));
92f5a8d4
TL
298 BOOST_TEST_THROWS(a += b, std::invalid_argument);
299 BOOST_TEST_THROWS(a -= b, std::invalid_argument);
300 BOOST_TEST_THROWS(a *= b, std::invalid_argument);
301 BOOST_TEST_THROWS(a /= b, std::invalid_argument);
20effc67
TL
302 auto c = make(Tag(), axis::regular<>(2, 0, 2), axis::regular<>(2, 0, 4));
303 BOOST_TEST_THROWS(a += c, std::invalid_argument);
92f5a8d4 304 }
f67539c2
TL
305
306 // scaling
307 {
308 auto b = make_s(Tag{}, dummy_storage<double, true>{}, axis::integer<>(0, 1));
309 b(0);
310 BOOST_TEST_EQ(b[0], 1);
311 b *= 2; // intentionally does not do anything
312 BOOST_TEST_EQ(b[0], 1);
313
314 auto c = make_s(Tag{}, dummy_storage<double, false>{}, axis::integer<>(0, 1));
315 c(0);
316 BOOST_TEST_EQ(c[0], 1);
317 c *= 2; // this calls *= on each element
318 BOOST_TEST_EQ(c[0], 2);
319
320 using h1_t = decltype(
321 make_s(Tag{}, dummy_storage<unscaleable, false>{}, axis::integer<>(0, 1)));
322 BOOST_TEST_NOT((detail::has_operator_rmul<h1_t, double>::value));
323
324 using h2_t = decltype(
325 make_s(Tag{}, dummy_storage<unscaleable, true>{}, axis::integer<>(0, 1)));
326 BOOST_TEST_NOT((detail::has_operator_rmul<h2_t, double>::value));
327 }
92f5a8d4
TL
328}
329
330int main() {
331 run_tests<static_tag>();
332 run_tests<dynamic_tag>();
333
334 return boost::report_errors();
335}