]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/histogram/test/histogram_test.cpp
1 // Copyright 2015-2018 Hans Dembinski
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)
7 #include <boost/core/ignore_unused.hpp>
8 #include <boost/core/lightweight_test.hpp>
9 #include <boost/histogram/accumulators.hpp>
10 #include <boost/histogram/accumulators/ostream.hpp>
11 #include <boost/histogram/algorithm/sum.hpp>
12 #include <boost/histogram/axis.hpp>
13 #include <boost/histogram/axis/ostream.hpp>
14 #include <boost/histogram/histogram.hpp>
15 #include <boost/histogram/literals.hpp>
16 #include <boost/histogram/make_histogram.hpp>
17 #include <boost/histogram/ostream.hpp>
23 #include "is_close.hpp"
24 #include "std_ostream.hpp"
25 #include "throw_exception.hpp"
26 #include "utility_allocator.hpp"
27 #include "utility_axis.hpp"
28 #include "utility_histogram.hpp"
30 using namespace boost::histogram
;
31 using namespace boost::histogram::literals
; // to get _c suffix
33 template <class A
, class S
>
34 void pass_histogram(boost::histogram::histogram
<A
, S
>& h
) {
35 BOOST_TEST_EQ(h
.at(0), 0);
36 BOOST_TEST_EQ(h
.at(1), 1);
37 BOOST_TEST_EQ(h
.at(2), 0);
38 BOOST_TEST_EQ(h
.axis(0_c
), axis::integer
<>(0, 3));
45 auto h
= make(Tag(), axis::regular
<>{3, -1, 1});
46 BOOST_TEST_EQ(h
.rank(), 1);
47 BOOST_TEST_EQ(h
.size(), 5);
48 BOOST_TEST_EQ(h
.axis(0_c
).size(), 3);
49 BOOST_TEST_EQ(h
.axis().size(), 3);
50 auto h2
= make_s(Tag(), std::vector
<unsigned>(), axis::regular
<>{3, -1, 1});
56 auto h
= make(Tag(), axis::regular
<>{3, -1, 1}, axis::integer
<>{-1, 2},
57 axis::circular
<>{2, 0, 360}, axis::variable
<>{-1, 0, 1},
58 axis::category
<>{{3, 1, 2}});
59 BOOST_TEST_EQ(h
.rank(), 5);
60 BOOST_TEST_EQ(h
.size(), 5 * 5 * 3 * 4 * 4);
61 auto h2
= make_s(Tag(), std::vector
<unsigned>(), axis::regular
<>{3, -1, 1},
62 axis::integer
<>{-1, 2}, axis::circular
<>{2, 0, 360},
63 axis::variable
<>{-1, 0, 1}, axis::category
<>{{3, 1, 2}});
69 auto h
= make(Tag(), axis::integer
<>{0, 2}, axis::integer
<>{0, 3});
71 auto h2
= decltype(h
)(h
);
74 histogram
<std::tuple
<axis::integer
<>, axis::integer
<>>, dense_storage
<double>>(h
);
80 auto h
= make(Tag(), axis::integer
<>(0, 1), axis::integer
<>(0, 2));
82 auto h2
= decltype(h
)();
87 histogram
<std::tuple
<axis::integer
<>, axis::integer
<>>, dense_storage
<double>>();
94 auto h
= make(Tag(), axis::integer
<>(0, 1), axis::integer
<>(0, 2));
97 decltype(h
) h2(std::move(h
));
98 BOOST_TEST_EQ(algorithm::sum(h
), 0);
99 BOOST_TEST_EQ(h
.size(), 0);
100 BOOST_TEST_EQ(h2
, href
);
103 BOOST_TEST_EQ(algorithm::sum(h2
), 0);
104 BOOST_TEST_EQ(h2
.size(), 0);
105 BOOST_TEST_EQ(h3
, href
);
110 auto a
= make(Tag(), axis::integer
<double>(1, 2, "foo"));
111 BOOST_TEST_EQ(a
.axis().size(), 1);
112 BOOST_TEST_EQ(a
.axis().bin(0).lower(), 1);
113 BOOST_TEST_EQ(a
.axis().bin(0).upper(), 2);
114 BOOST_TEST_EQ(a
.axis().metadata(), "foo");
115 unsafe_access::axis(a
, 0).metadata() = "bar";
116 BOOST_TEST_EQ(a
.axis().metadata(), "bar");
118 auto b
= make(Tag(), axis::integer
<double>(1, 2, "foo"), axis::integer
<>(1, 3));
120 // check static access
121 BOOST_TEST_EQ(b
.axis(0_c
).size(), 1);
122 BOOST_TEST_EQ(b
.axis(0_c
).bin(0).lower(), 1);
123 BOOST_TEST_EQ(b
.axis(0_c
).bin(0).upper(), 2);
124 BOOST_TEST_EQ(b
.axis(1_c
).size(), 2);
125 BOOST_TEST_EQ(b
.axis(1_c
).bin(0), 1);
126 BOOST_TEST_EQ(b
.axis(1_c
).bin(1), 2);
127 unsafe_access::axis(b
, 1_c
).metadata() = "bar";
128 BOOST_TEST_EQ(b
.axis(0_c
).metadata(), "foo");
129 BOOST_TEST_EQ(b
.axis(1_c
).metadata(), "bar");
131 // check dynamic access
132 BOOST_TEST_EQ(b
.axis(0).size(), 1);
133 BOOST_TEST_EQ(b
.axis(0).bin(0).lower(), 1);
134 BOOST_TEST_EQ(b
.axis(0).bin(0).upper(), 2);
135 BOOST_TEST_EQ(b
.axis(1).size(), 2);
136 BOOST_TEST_EQ(b
.axis(1).bin(0), 1);
137 BOOST_TEST_EQ(b
.axis(1).bin(1), 2);
138 BOOST_TEST_EQ(b
.axis(0).metadata(), "foo");
139 BOOST_TEST_EQ(b
.axis(1).metadata(), "bar");
140 unsafe_access::axis(b
, 0).metadata() = "baz";
141 BOOST_TEST_EQ(b
.axis(0).metadata(), "baz");
143 auto c
= make(Tag(), axis::category
<>({1, 2}));
144 BOOST_TEST_EQ(c
.axis().size(), 2);
145 unsafe_access::axis(c
, 0).metadata() = "foo";
146 BOOST_TEST_EQ(c
.axis().metadata(), "foo");
147 // need to cast here for this to work with Tag == dynamic_tag, too
148 const auto& ca
= axis::get
<axis::category
<>>(c
.axis());
149 BOOST_TEST_EQ(ca
.bin(0), 1);
150 const auto& ca2
= axis::get
<axis::category
<>>(c
.axis(0));
151 BOOST_TEST_EQ(&ca2
, &ca
);
156 auto a
= make(Tag(), axis::integer
<>(0, 2));
157 auto b
= make(Tag(), axis::integer
<>(0, 2), axis::integer
<>(0, 3));
160 auto c
= make(Tag(), axis::integer
<>(0, 2));
165 auto d
= make(Tag(), axis::regular
<>(2, 0, 1));
181 auto h
= make(Tag(), axis::integer
<int, axis::null_type
>{0, 2});
184 BOOST_TEST(i
== h
.begin() + 1); // +1 because of underflow
186 BOOST_TEST(i
== h
.begin()); // underflow
188 BOOST_TEST(i
== h
.end() - 1); // overflow
190 BOOST_TEST_EQ(h
.rank(), 1);
191 BOOST_TEST_EQ(h
.axis().size(), 2);
192 BOOST_TEST_EQ(algorithm::sum(h
), 4);
194 BOOST_TEST_EQ(h
.at(-1), 1);
195 BOOST_TEST_EQ(h
.at(0), 2);
196 BOOST_TEST_EQ(h
.at(1), 0);
197 BOOST_TEST_EQ(h
.at(2), 1);
202 auto h
= make(Tag(), axis::integer
<int, axis::null_type
, axis::option::none_t
>(0, 2));
205 BOOST_TEST(i
== h
.begin());
207 BOOST_TEST(i
== h
.end());
209 BOOST_TEST(i
== h
.end());
211 BOOST_TEST_EQ(h
.rank(), 1);
212 BOOST_TEST_EQ(h
.axis().size(), 2);
213 BOOST_TEST_EQ(algorithm::sum(h
), 2);
215 BOOST_TEST_EQ(h
.at(0), 2);
216 BOOST_TEST_EQ(h
.at(1), 0);
221 auto h
= make(Tag(), axis::category
<>({1, 2}));
227 BOOST_TEST_EQ(h
.rank(), 1);
228 BOOST_TEST_EQ(h
.axis().size(), 2);
229 BOOST_TEST_EQ(algorithm::sum(h
), 4);
231 BOOST_TEST_EQ(h
.at(0), 1);
232 BOOST_TEST_EQ(h
.at(1), 1);
233 BOOST_TEST_EQ(h
.at(2), 2); // overflow bin
238 auto h
= make_s(Tag(), weight_storage(), axis::integer
<>(0, 2));
245 BOOST_TEST_EQ(algorithm::sum(h
).value(), 5.5);
246 BOOST_TEST_EQ(algorithm::sum(h
).variance(), 7.25);
248 BOOST_TEST_EQ(h
[-1].value(), 1);
249 BOOST_TEST_EQ(h
[-1].variance(), 1);
250 BOOST_TEST_EQ(h
[0].value(), 1.5);
251 BOOST_TEST_EQ(h
[0].variance(), 1.25);
252 BOOST_TEST_EQ(h
[1].value(), 1);
253 BOOST_TEST_EQ(h
[1].variance(), 1);
254 BOOST_TEST_EQ(h
[2].value(), 2);
255 BOOST_TEST_EQ(h
[2].variance(), 4);
260 auto h
= make_s(Tag(), profile_storage(), axis::integer
<>(0, 2));
269 BOOST_TEST_EQ(h
[0].count(), 3);
270 BOOST_TEST_EQ(h
[0].value(), 2);
271 BOOST_TEST_EQ(h
[0].variance(), 1);
272 BOOST_TEST_EQ(h
[1].count(), 3);
273 BOOST_TEST_EQ(h
[1].value(), 5);
274 BOOST_TEST_EQ(h
[1].variance(), 1);
277 // 1D weighted profile
279 auto h
= make_s(Tag(), weighted_profile_storage(), axis::integer
<>(0, 2));
284 h(0, weight(2), sample(3));
285 h(0, sample(5), weight(2));
287 h(weight(2), 1, sample(1));
288 h(sample(2), 1, weight(2));
290 h(weight(2), sample(3), 1);
291 h(sample(4), weight(2), 1);
293 BOOST_TEST_EQ(h
[0].sum_of_weights(), 6);
294 BOOST_TEST_EQ(h
[0].value(), 3);
295 BOOST_TEST_EQ(h
[1].sum_of_weights(), 8);
296 BOOST_TEST_EQ(h
[1].value(), 2.5);
301 auto h
= make(Tag(), axis::integer
<>(-1, 1),
302 axis::integer
<int, axis::null_type
, axis::option::none_t
>(-1, 2));
308 BOOST_TEST_EQ(h
.rank(), 2);
309 BOOST_TEST_EQ(h
.axis(0_c
).size(), 2);
310 BOOST_TEST_EQ(h
.axis(1_c
).size(), 3);
311 BOOST_TEST_EQ(algorithm::sum(h
), 3);
313 BOOST_TEST_EQ(h
.at(-1, 0), 0);
314 BOOST_TEST_EQ(h
.at(-1, 1), 1);
315 BOOST_TEST_EQ(h
.at(-1, 2), 0);
317 BOOST_TEST_EQ(h
.at(0, 0), 1);
318 BOOST_TEST_EQ(h
.at(0, 1), 1);
319 BOOST_TEST_EQ(h
.at(0, 2), 0);
321 BOOST_TEST_EQ(h
.at(1, 0), 0);
322 BOOST_TEST_EQ(h
.at(1, 1), 0);
323 BOOST_TEST_EQ(h
.at(1, 2), 0);
325 BOOST_TEST_EQ(h
.at(2, 0), 0);
326 BOOST_TEST_EQ(h
.at(2, 1), 0);
327 BOOST_TEST_EQ(h
.at(2, 2), 0);
332 auto h
= make_s(Tag(), weight_storage(), axis::integer
<>(-1, 1),
333 axis::integer
<int, axis::null_type
, axis::option::none_t
>(-1, 2));
335 h(weight(10), -1, -1); // -> 0, 0
336 h(weight(5), -1, -10); // is ignored
337 h(weight(7), -10, 0); // -> -1, 1
339 BOOST_TEST_EQ(algorithm::sum(h
).value(), 18);
340 BOOST_TEST_EQ(algorithm::sum(h
).variance(), 150);
342 BOOST_TEST_EQ(h
.at(-1, 0).value(), 0);
343 BOOST_TEST_EQ(h
.at(-1, 1).value(), 7);
344 BOOST_TEST_EQ(h
.at(-1, 2).value(), 0);
346 BOOST_TEST_EQ(h
.at(0, 0).value(), 10);
347 BOOST_TEST_EQ(h
.at(0, 1).value(), 1);
348 BOOST_TEST_EQ(h
.at(0, 2).value(), 0);
350 BOOST_TEST_EQ(h
.at(1, 0).value(), 0);
351 BOOST_TEST_EQ(h
.at(1, 1).value(), 0);
352 BOOST_TEST_EQ(h
.at(1, 2).value(), 0);
354 BOOST_TEST_EQ(h
.at(2, 0).value(), 0);
355 BOOST_TEST_EQ(h
.at(2, 1).value(), 0);
356 BOOST_TEST_EQ(h
.at(2, 2).value(), 0);
358 BOOST_TEST_EQ(h
.at(-1, 0).variance(), 0);
359 BOOST_TEST_EQ(h
.at(-1, 1).variance(), 49);
360 BOOST_TEST_EQ(h
.at(-1, 2).variance(), 0);
362 BOOST_TEST_EQ(h
.at(0, 0).variance(), 100);
363 BOOST_TEST_EQ(h
.at(0, 1).variance(), 1);
364 BOOST_TEST_EQ(h
.at(0, 2).variance(), 0);
366 BOOST_TEST_EQ(h
.at(1, 0).variance(), 0);
367 BOOST_TEST_EQ(h
.at(1, 1).variance(), 0);
368 BOOST_TEST_EQ(h
.at(1, 2).variance(), 0);
370 BOOST_TEST_EQ(h
.at(2, 0).variance(), 0);
371 BOOST_TEST_EQ(h
.at(2, 1).variance(), 0);
372 BOOST_TEST_EQ(h
.at(2, 2).variance(), 0);
377 auto h
= make_s(Tag(), weight_storage(), axis::integer
<>(0, 3), axis::integer
<>(0, 4),
378 axis::integer
<>(0, 5));
379 for (auto i
= 0; i
< h
.axis(0_c
).size(); ++i
)
380 for (auto j
= 0; j
< h
.axis(1_c
).size(); ++j
)
381 for (auto k
= 0; k
< h
.axis(2_c
).size(); ++k
) h(i
, j
, k
, weight(i
+ j
+ k
));
383 for (auto i
= 0; i
< h
.axis(0_c
).size(); ++i
) {
384 for (auto j
= 0; j
< h
.axis(1_c
).size(); ++j
) {
385 for (auto k
= 0; k
< h
.axis(2_c
).size(); ++k
) {
386 BOOST_TEST_EQ(h
.at(i
, j
, k
).value(), i
+ j
+ k
);
387 BOOST_TEST_EQ(h
.at(i
, j
, k
).variance(), (i
+ j
+ k
) * (i
+ j
+ k
));
395 auto v
= std::vector
<int>{0, 1, 2};
396 auto h
= std::for_each(v
.begin(), v
.end(), make(Tag(), axis::integer
<>(0, 3)));
397 BOOST_TEST_EQ(h
.at(0), 1);
398 BOOST_TEST_EQ(h
.at(1), 1);
399 BOOST_TEST_EQ(h
.at(2), 1);
400 BOOST_TEST_EQ(algorithm::sum(h
), 3);
402 auto a
= std::vector
<double>();
403 // walks over all bins, including underflow and overflow
404 std::partial_sum(h
.begin(), h
.end(), std::back_inserter(a
));
405 BOOST_TEST_EQ(a
.size(), 5);
406 BOOST_TEST_EQ(a
[0], 0);
407 BOOST_TEST_EQ(a
[1], 1);
408 BOOST_TEST_EQ(a
[2], 2);
409 BOOST_TEST_EQ(a
[3], 3);
410 BOOST_TEST_EQ(a
[4], 3);
415 auto h
= make(Tag(), axis::integer
<int, axis::null_type
, axis::option::none_t
>(0, 2));
418 BOOST_TEST_EQ(h
.at(0), 1);
419 BOOST_TEST_EQ(h
.at(1), 1);
420 BOOST_TEST_EQ(algorithm::sum(h
), 2);
422 BOOST_TEST_EQ(h
.at(0), 0);
423 BOOST_TEST_EQ(h
.at(1), 0);
424 BOOST_TEST_EQ(algorithm::sum(h
), 0);
427 // using containers for input and output
429 auto h
= make(Tag(), axis::integer
<>(0, 2), axis::integer
<double>(2, 4));
431 h(std::make_tuple(0, 2.0));
432 h(std::make_tuple(1, 3.0));
434 auto i00
= std::make_tuple(0, 0);
435 auto i11
= std::make_tuple(1, 1);
438 BOOST_TEST_EQ(h
.at(i00
), 1);
439 BOOST_TEST_EQ(h
[i00
], 1);
440 BOOST_TEST_EQ(h
[i11
], 1);
444 BOOST_TEST_EQ(h
.at(j11
), 1);
445 BOOST_TEST_EQ(h
[j11
], 1);
446 int j111
[] = {1, 1, 1};
448 BOOST_TEST_THROWS((void)h
.at(j111
), std::invalid_argument
);
451 BOOST_TEST_THROWS((void)h
.at(j13
), std::out_of_range
);
454 h(std::make_tuple(weight(2), 0, 2.0));
455 h(std::make_tuple(1, 3.0, weight(2)));
457 BOOST_TEST_EQ(h
.at(i00
), 3);
458 BOOST_TEST_EQ(h
[i00
], 3);
460 // test special case of 1-dimensional histogram, which should unpack
461 // 1-dimensional tuple normally, but forward larger tuples to the axis
462 auto h1
= make(Tag(), axis::integer
<>(0, 2));
463 h1(std::make_tuple(0)); // as if one had passed 0 directly
464 BOOST_TEST_EQ(h1
.at(std::make_tuple(0)), 1); // as if one had passed 0 directly
469 auto h
= make(Tag(), axis::integer
<>(0, 1), axis::integer
<>(0, 1));
470 BOOST_TEST_THROWS(h
.at(0, 2), std::out_of_range
);
471 BOOST_TEST_THROWS(h
.at(std::make_tuple(2, 0)), std::out_of_range
);
474 // pass histogram to function
476 auto h
= make(Tag(), axis::integer
<>(0, 3));
483 tracing_allocator_db db
;
485 tracing_allocator
<char> a(db
);
486 auto h
= make_s(Tag(), std::vector
<int, tracing_allocator
<int>>(a
),
487 axis::integer
<>(0, 1000));
491 // int allocation for std::vector
492 BOOST_TEST_EQ(db
.at
<int>().first
, 0);
493 BOOST_TEST_EQ(db
.at
<int>().second
, 1002);
495 if (Tag()) { // axis::variant allocation, only for dynamic histogram
496 using T
= axis::variant
<axis::integer
<>>;
497 BOOST_TEST_EQ(db
.at
<T
>().first
, 0);
498 // may be zero if vector uses small-vector-optimisation
499 BOOST_TEST_LE(db
.at
<T
>().second
, 1);
505 run_tests
<static_tag
>();
506 run_tests
<dynamic_tag
>();
508 return boost::report_errors();