]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/histogram/test/histogram_fill_test.cpp
1 // Copyright 2019 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)
8 #include <boost/config.hpp>
9 #include <boost/core/lightweight_test.hpp>
10 #include <boost/histogram/accumulators/mean.hpp>
11 #include <boost/histogram/accumulators/ostream.hpp>
12 #include <boost/histogram/accumulators/weighted_mean.hpp>
13 #include <boost/histogram/algorithm/sum.hpp>
14 #include <boost/histogram/axis/category.hpp>
15 #include <boost/histogram/axis/integer.hpp>
16 #include <boost/histogram/axis/ostream.hpp>
17 #include <boost/histogram/axis/regular.hpp>
18 #include <boost/histogram/axis/variant.hpp>
19 #include <boost/histogram/histogram.hpp>
20 #include <boost/histogram/literals.hpp>
21 #include <boost/histogram/make_histogram.hpp>
22 #include <boost/histogram/ostream.hpp>
23 #include <boost/histogram/storage_adaptor.hpp>
24 #include <boost/variant2/variant.hpp>
31 #include "throw_exception.hpp"
32 #include "utility_histogram.hpp"
34 using namespace boost::histogram
;
35 using namespace boost::histogram::algorithm
;
36 using namespace boost::histogram::literals
; // to get _c suffix
37 using boost::variant2::variant
;
39 constexpr auto ndata
= 1 << 16; // should be larger than index buffer in fill_n
41 using in
= axis::integer
<int, axis::null_type
>;
42 using in0
= axis::integer
<int, axis::null_type
, axis::option::none_t
>;
43 using ing
= axis::integer
<double, axis::null_type
,
44 decltype(axis::option::growth
| axis::option::underflow
|
45 axis::option::overflow
)>;
46 using cs
= axis::category
<std::string
, axis::null_type
>;
47 using csg
= axis::category
<std::string
, axis::null_type
, axis::option::growth_t
>;
50 auto size() const { return axis::index_type
{2}; }
52 auto index(const std::tuple
<double, double>& xy
) const {
53 const auto x
= std::get
<0>(xy
);
54 const auto y
= std::get
<1>(xy
);
55 const auto r
= std::sqrt(x
* x
+ y
* y
);
56 return std::min(static_cast<axis::index_type
>(r
), size());
59 friend std::ostream
& operator<<(std::ostream
& os
, const axis2d
&) {
66 void run_tests(const std::vector
<int>& x
, const std::vector
<int>& y
,
67 const std::vector
<double>& w
) {
71 auto h
= make(Tag(), in
{1, 3});
73 for (auto&& xi
: x
) h(xi
);
74 // uses 1D specialization
81 auto h
= make(Tag(), in
{1, 3});
83 for (auto&& xi
: x
) h(xi
);
92 auto h
= make(Tag(), in
{1, 3});
95 for (auto&& xi
: x
) h(xi
);
97 variant
<int, std::vector
<int>, std::string
> v
[1];
102 BOOST_TEST_EQ(h
, h2
);
107 auto h
= make(Tag(), in
{1, 3});
111 BOOST_TEST_THROWS(h
.fill(bad1
), std::invalid_argument
);
113 std::vector
<std::array
<int, 4>> bad2
;
115 BOOST_TEST_THROWS(h
.fill(bad2
), std::invalid_argument
);
118 // 1D with category axis
120 auto h
= make(Tag(), cs
{"A", "B"});
123 const auto s
= {"A", "B", "C"};
124 for (auto&& si
: s
) h(si
);
127 variant
<int, std::string
, std::vector
<std::string
>> v
[1];
132 v
[0] = std::vector
<std::string
>(s
.begin(), s
.end());
133 for (auto&& si
: s
) h(si
);
136 BOOST_TEST_EQ(h
, h2
);
141 auto h
= make(Tag(), in
{1, 3});
144 for (auto&& xi
: x
) h(weight(2), xi
);
145 h2
.fill(weight(2), x
);
147 for (unsigned i
= 0; i
< ndata
; ++i
) h(weight(w
[i
]), x
[i
]);
148 h2
.fill(weight(w
), x
);
150 BOOST_TEST_EQ(h
, h2
);
154 BOOST_TEST_THROWS(h2
.fill(x
, weight(w2
)), std::invalid_argument
);
159 auto h
= make(Tag(), in
{1, 3}, in0
{1, 5});
162 for (int i
= 0; i
< ndata
; ++i
) h(x
[i
], y
[i
]);
163 const auto xy
= {x
, y
};
166 BOOST_TEST_EQ(h
, h2
);
169 BOOST_TEST_THROWS(h
.fill(x
), std::invalid_argument
);
172 std::array
<std::vector
<int>, 2> bad
= {{std::vector
<int>(1), std::vector
<int>(2)}};
174 BOOST_TEST_THROWS(h2
.fill(bad
), std::invalid_argument
);
177 // 2D variant and weight
179 auto h
= make(Tag(), in
{1, 3}, in0
{1, 5});
181 using V
= variant
<int, std::vector
<int>, std::string
>;
189 for (auto&& vi
: y
) h1(3, vi
);
191 BOOST_TEST_EQ(h1
, h2
);
199 for (auto&& vi
: x
) h1(vi
, 3);
201 BOOST_TEST_EQ(h1
, h2
);
209 for (auto&& vi
: y
) h1(3, vi
, weight(2));
210 h2
.fill(xy
, weight(2));
211 BOOST_TEST_EQ(h1
, h2
);
219 for (unsigned i
= 0; i
< ndata
; ++i
) h1(3, y
[i
], weight(w
[i
]));
220 h2
.fill(xy
, weight(w
));
221 BOOST_TEST_EQ(sum(h1
), sum(h2
));
222 BOOST_TEST_EQ(h1
, h2
);
228 auto h
= make(Tag(), ing());
230 for (const auto& xi
: x
) h(xi
);
232 BOOST_TEST_EQ(h
, h2
);
237 auto h
= make(Tag(), in(1, 3), ing());
239 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], y
[i
]);
240 const auto xy
= {x
, y
};
242 BOOST_TEST_EQ(h
, h2
);
247 auto h
= make(Tag(), ing(), ing());
249 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], y
[i
]);
250 const auto xy
= {x
, y
};
252 BOOST_TEST_EQ(h
, h2
);
255 // 2D growing with weights A
257 auto h
= make(Tag(), in(1, 3), ing());
259 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], y
[i
], weight(w
[i
]));
260 const auto xy
= {x
, y
};
261 h2
.fill(xy
, weight(w
));
262 BOOST_TEST_EQ(h
, h2
);
265 // 2D growing with weights B
267 auto h
= make(Tag(), ing(), ing());
269 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], y
[i
], weight(2));
270 const auto xy
= {x
, y
};
271 h2
.fill(xy
, weight(2));
272 BOOST_TEST_EQ(h
, h2
);
275 // 2D growing and variant
277 auto h
= make(Tag(), csg
{}, in
{1, 2});
283 using V
= variant
<std::string
, std::vector
<std::string
>, int, std::vector
<int>>;
284 const auto xy
= {V("foo"), V(std::vector
<int>{1, 2})};
287 BOOST_TEST_EQ(h
, h2
);
289 const auto bad
= {V(std::vector
<std::string
>(1, "foo")), V(std::vector
<int>{1, 2})};
291 BOOST_TEST_THROWS(h
.fill(bad
), std::invalid_argument
);
294 // 1D profile with samples
296 auto h
= make_s(Tag(), profile_storage(), in(1, 3));
299 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], sample(w
[i
]));
300 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], sample(w
[i
]), weight(w
[i
]));
301 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], sample(2), weight(w
[i
]));
302 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], sample(w
[i
]), weight(2));
304 h2
.fill(x
, sample(w
));
305 h2
.fill(x
, sample(w
), weight(w
));
306 h2
.fill(x
, sample(2), weight(w
));
307 h2
.fill(x
, sample(w
), weight(2));
309 BOOST_TEST_EQ(h
, h2
);
312 // 2D weighted profile with samples and weights
314 auto h
= make_s(Tag(), weighted_profile_storage(), in(1, 3), in0(1, 3));
317 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], 3, sample(w
[i
]), weight(w
[i
]));
318 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], 3, sample(2), weight(w
[i
]));
319 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], 3, sample(w
[i
]), weight(2));
321 using V
= variant
<int, std::vector
<int>>;
325 h2
.fill(xy
, sample(w
), weight(w
));
326 h2
.fill(xy
, sample(2), weight(w
));
327 h2
.fill(xy
, sample(w
), weight(2));
329 BOOST_TEST_EQ(h
, h2
);
334 auto h
= make(Tag(), axis2d
{});
337 std::vector
<std::tuple
<double, double>> xy
;
339 for (unsigned i
= 0; i
< ndata
; ++i
) xy
.emplace_back(x
[i
], y
[i
]);
341 for (auto&& xyi
: xy
) h(xyi
);
344 BOOST_TEST_EQ(h
, h2
);
350 std::normal_distribution
<> id(0, 2);
351 std::vector
<int> x(ndata
), y(ndata
);
352 auto generator
= [&] { return static_cast<int>(id(gen
)); };
353 std::generate(x
.begin(), x
.end(), generator
);
354 std::generate(y
.begin(), y
.end(), generator
);
355 std::vector
<double> w(ndata
);
356 // must be all positive
357 std::generate(w
.begin(), w
.end(), [&] { return 0.5 + std::abs(id(gen
)); });
359 run_tests
<static_tag
>(x
, y
, w
);
360 run_tests
<dynamic_tag
>(x
, y
, w
);
362 return boost::report_errors();