]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/histogram/test/histogram_fill_test.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / histogram / test / histogram_fill_test.cpp
1 // Copyright 2019 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 <array>
8 #include <boost/config.hpp>
9 #include <boost/core/lightweight_test.hpp>
10 #include <boost/histogram/accumulators.hpp>
11 #include <boost/histogram/accumulators/ostream.hpp>
12 #include <boost/histogram/algorithm/sum.hpp>
13 #include <boost/histogram/axis/category.hpp>
14 #include <boost/histogram/axis/integer.hpp>
15 #include <boost/histogram/axis/ostream.hpp>
16 #include <boost/histogram/histogram.hpp>
17 #include <boost/histogram/literals.hpp>
18 #include <boost/histogram/make_histogram.hpp>
19 #include <boost/histogram/ostream.hpp>
20 #include <boost/histogram/storage_adaptor.hpp>
21 #include <boost/variant2/variant.hpp>
22 #include <random>
23 #include <sstream>
24 #include <stdexcept>
25 #include <tuple>
26 #include <utility>
27 #include <vector>
28 #include "throw_exception.hpp"
29 #include "utility_histogram.hpp"
30
31 using namespace boost::histogram;
32 using namespace boost::histogram::algorithm;
33 using namespace boost::histogram::literals; // to get _c suffix
34 using boost::variant2::variant;
35
36 constexpr auto ndata = 1 << 16; // should be larger than index buffer in fill_n
37
38 using in = axis::integer<int, axis::null_type>;
39 using in0 = axis::integer<int, axis::null_type, axis::option::none_t>;
40 using ing = axis::integer<double, axis::null_type,
41 decltype(axis::option::growth | axis::option::underflow |
42 axis::option::overflow)>;
43 using cs = axis::category<std::string, axis::null_type>;
44 using csg = axis::category<std::string, axis::null_type, axis::option::growth_t>;
45
46 struct axis2d {
47 auto size() const { return axis::index_type{2}; }
48
49 auto index(const std::tuple<double, double>& xy) const {
50 const auto x = std::get<0>(xy);
51 const auto y = std::get<1>(xy);
52 const auto r = std::sqrt(x * x + y * y);
53 return std::min(static_cast<axis::index_type>(r), size());
54 }
55
56 friend std::ostream& operator<<(std::ostream& os, const axis2d&) {
57 os << "axis2d()";
58 return os;
59 }
60 };
61
62 template <class Tag>
63 void run_tests(const std::vector<int>& x, const std::vector<int>& y,
64 const std::vector<double>& w) {
65
66 // 1D simple A
67 {
68 auto h = make(Tag(), in{1, 3});
69 auto h2 = h;
70 for (auto&& xi : x) h(xi);
71 // uses 1D specialization
72 h2.fill(x);
73 BOOST_TEST_EQ(h, h2);
74 }
75
76 // 1D simple B
77 {
78 auto h = make(Tag(), in{1, 3});
79 auto h2 = h;
80 for (auto&& xi : x) h(xi);
81 // uses generic form
82 const auto vx = {x};
83 h2.fill(vx);
84 BOOST_TEST_EQ(h, h2);
85 }
86
87 // 1D simple C
88 {
89 auto h = make(Tag(), in{1, 3});
90 auto h2 = h;
91 h(1);
92 for (auto&& xi : x) h(xi);
93 // uses variant
94 variant<int, std::vector<int>, std::string> v[1];
95 v[0] = 1;
96 h2.fill(v);
97 v[0] = x;
98 h2.fill(v);
99 BOOST_TEST_EQ(h, h2);
100 }
101
102 // 1D bad arguments
103 {
104 auto h = make(Tag(), in{1, 3});
105
106 int bad1[2][4];
107 (void)bad1;
108 BOOST_TEST_THROWS(h.fill(bad1), std::invalid_argument);
109
110 std::vector<std::array<int, 4>> bad2;
111 (void)bad2;
112 BOOST_TEST_THROWS(h.fill(bad2), std::invalid_argument);
113 }
114
115 // 1D with category axis
116 {
117 auto h = make(Tag(), cs{"A", "B"});
118 auto h2 = h;
119
120 const auto s = {"A", "B", "C"};
121 for (auto&& si : s) h(si);
122 h2.fill(s);
123
124 variant<int, std::string, std::vector<std::string>> v[1];
125 h("B");
126 v[0] = "B";
127 h2.fill(v);
128
129 v[0] = std::vector<std::string>(s.begin(), s.end());
130 for (auto&& si : s) h(si);
131 h2.fill(v);
132
133 BOOST_TEST_EQ(h, h2);
134 }
135
136 // 1D weight
137 {
138 auto h = make(Tag(), in{1, 3});
139 auto h2 = h;
140
141 for (auto&& xi : x) h(weight(2), xi);
142 h2.fill(weight(2), x);
143
144 for (unsigned i = 0; i < ndata; ++i) h(weight(w[i]), x[i]);
145 h2.fill(weight(w), x);
146
147 BOOST_TEST_EQ(h, h2);
148
149 auto w2 = {1};
150 (void)w2;
151 BOOST_TEST_THROWS(h2.fill(x, weight(w2)), std::invalid_argument);
152 }
153
154 // 2D simple
155 {
156 auto h = make(Tag(), in{1, 3}, in0{1, 5});
157 auto h2 = h;
158
159 for (int i = 0; i < ndata; ++i) h(x[i], y[i]);
160 const auto xy = {x, y};
161 h2.fill(xy);
162
163 BOOST_TEST_EQ(h, h2);
164
165 // wrong rank
166 BOOST_TEST_THROWS(h.fill(x), std::invalid_argument);
167
168 // not rectangular
169 std::array<std::vector<int>, 2> bad = {{std::vector<int>(1), std::vector<int>(2)}};
170 (void)bad;
171 BOOST_TEST_THROWS(h2.fill(bad), std::invalid_argument);
172 }
173
174 // 2D variant and weight
175 {
176 auto h = make(Tag(), in{1, 3}, in0{1, 5});
177
178 using V = variant<int, std::vector<int>, std::string>;
179 V xy[2];
180
181 {
182 xy[0] = 3;
183 xy[1] = y;
184 auto h1 = h;
185 auto h2 = h;
186 for (auto&& vi : y) h1(3, vi);
187 h2.fill(xy);
188 BOOST_TEST_EQ(h1, h2);
189 }
190
191 {
192 xy[0] = x;
193 xy[1] = 3;
194 auto h1 = h;
195 auto h2 = h;
196 for (auto&& vi : x) h1(vi, 3);
197 h2.fill(xy);
198 BOOST_TEST_EQ(h1, h2);
199 }
200
201 {
202 xy[0] = 3;
203 xy[1] = y;
204 auto h1 = h;
205 auto h2 = h;
206 for (auto&& vi : y) h1(3, vi, weight(2));
207 h2.fill(xy, weight(2));
208 BOOST_TEST_EQ(h1, h2);
209 }
210
211 {
212 xy[0] = 3;
213 xy[1] = y;
214 auto h1 = h;
215 auto h2 = h;
216 for (unsigned i = 0; i < ndata; ++i) h1(3, y[i], weight(w[i]));
217 h2.fill(xy, weight(w));
218 BOOST_TEST_EQ(sum(h1), sum(h2));
219 BOOST_TEST_EQ(h1, h2);
220 }
221 }
222
223 // 1D growing
224 {
225 auto h = make(Tag(), ing());
226 auto h2 = h;
227 for (const auto& xi : x) h(xi);
228 h2.fill(x);
229 BOOST_TEST_EQ(h, h2);
230 }
231
232 // 2D growing A
233 {
234 auto h = make(Tag(), in(1, 3), ing());
235 auto h2 = h;
236 for (unsigned i = 0; i < ndata; ++i) h(x[i], y[i]);
237 const auto xy = {x, y};
238 h2.fill(xy);
239 BOOST_TEST_EQ(h, h2);
240 }
241
242 // 2D growing B
243 {
244 auto h = make(Tag(), ing(), ing());
245 auto h2 = h;
246 for (unsigned i = 0; i < ndata; ++i) h(x[i], y[i]);
247 const auto xy = {x, y};
248 h2.fill(xy);
249 BOOST_TEST_EQ(h, h2);
250 }
251
252 // 2D growing with weights A
253 {
254 auto h = make(Tag(), in(1, 3), ing());
255 auto h2 = h;
256 for (unsigned i = 0; i < ndata; ++i) h(x[i], y[i], weight(w[i]));
257 const auto xy = {x, y};
258 h2.fill(xy, weight(w));
259 BOOST_TEST_EQ(h, h2);
260 }
261
262 // 2D growing with weights B
263 {
264 auto h = make(Tag(), ing(), ing());
265 auto h2 = h;
266 for (unsigned i = 0; i < ndata; ++i) h(x[i], y[i], weight(2));
267 const auto xy = {x, y};
268 h2.fill(xy, weight(2));
269 BOOST_TEST_EQ(h, h2);
270 }
271
272 // 2D growing and variant
273 {
274 auto h = make(Tag(), csg{}, in{1, 2});
275 auto h2 = h;
276
277 h("foo", 1);
278 h("foo", 2);
279
280 using V = variant<std::string, std::vector<std::string>, int, std::vector<int>>;
281 const auto xy = {V("foo"), V(std::vector<int>{1, 2})};
282 h2.fill(xy);
283
284 BOOST_TEST_EQ(h, h2);
285
286 const auto bad = {V(std::vector<std::string>(1, "foo")), V(std::vector<int>{1, 2})};
287 (void)bad;
288 BOOST_TEST_THROWS(h.fill(bad), std::invalid_argument);
289 }
290
291 // 1D profile with samples
292 {
293 auto h = make_s(Tag(), profile_storage(), in(1, 3));
294 auto h2 = h;
295
296 for (unsigned i = 0; i < ndata; ++i) h(x[i], sample(w[i]));
297 for (unsigned i = 0; i < ndata; ++i) h(x[i], sample(w[i]), weight(w[i]));
298 for (unsigned i = 0; i < ndata; ++i) h(x[i], sample(2), weight(w[i]));
299 for (unsigned i = 0; i < ndata; ++i) h(x[i], sample(w[i]), weight(2));
300
301 h2.fill(x, sample(w));
302 h2.fill(x, sample(w), weight(w));
303 h2.fill(x, sample(2), weight(w));
304 h2.fill(x, sample(w), weight(2));
305
306 BOOST_TEST_EQ(h, h2);
307 }
308
309 // 2D weighted profile with samples and weights
310 {
311 auto h = make_s(Tag(), weighted_profile_storage(), in(1, 3), in0(1, 3));
312 auto h2 = h;
313
314 for (unsigned i = 0; i < ndata; ++i) h(x[i], 3, sample(w[i]), weight(w[i]));
315 for (unsigned i = 0; i < ndata; ++i) h(x[i], 3, sample(2), weight(w[i]));
316 for (unsigned i = 0; i < ndata; ++i) h(x[i], 3, sample(w[i]), weight(2));
317
318 using V = variant<int, std::vector<int>>;
319 std::array<V, 2> xy;
320 xy[0] = x;
321 xy[1] = 3;
322 h2.fill(xy, sample(w), weight(w));
323 h2.fill(xy, sample(2), weight(w));
324 h2.fill(xy, sample(w), weight(2));
325
326 BOOST_TEST_EQ(h, h2);
327 }
328
329 // axis2d
330 {
331 auto h = make(Tag(), axis2d{});
332 auto h2 = h;
333
334 std::vector<std::tuple<double, double>> xy;
335 xy.reserve(ndata);
336 for (unsigned i = 0; i < ndata; ++i) xy.emplace_back(x[i], y[i]);
337
338 for (auto&& xyi : xy) h(xyi);
339 h2.fill(xy);
340
341 BOOST_TEST_EQ(h, h2);
342 }
343 }
344
345 int main() {
346 std::mt19937 gen(1);
347 std::normal_distribution<> id(0, 2);
348 std::vector<int> x(ndata), y(ndata);
349 auto generator = [&] { return static_cast<int>(id(gen)); };
350 std::generate(x.begin(), x.end(), generator);
351 std::generate(y.begin(), y.end(), generator);
352 std::vector<double> w(ndata);
353 // must be all positive
354 std::generate(w.begin(), w.end(), [&] { return 0.5 + std::abs(id(gen)); });
355
356 run_tests<static_tag>(x, y, w);
357 run_tests<dynamic_tag>(x, y, w);
358
359 return boost::report_errors();
360 }