]>
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.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>
28 #include "throw_exception.hpp"
29 #include "utility_histogram.hpp"
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
;
36 constexpr auto ndata
= 1 << 16; // should be larger than index buffer in fill_n
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
>;
47 auto size() const { return axis::index_type
{2}; }
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());
56 friend std::ostream
& operator<<(std::ostream
& os
, const axis2d
&) {
63 void run_tests(const std::vector
<int>& x
, const std::vector
<int>& y
,
64 const std::vector
<double>& w
) {
68 auto h
= make(Tag(), in
{1, 3});
70 for (auto&& xi
: x
) h(xi
);
71 // uses 1D specialization
78 auto h
= make(Tag(), in
{1, 3});
80 for (auto&& xi
: x
) h(xi
);
89 auto h
= make(Tag(), in
{1, 3});
92 for (auto&& xi
: x
) h(xi
);
94 variant
<int, std::vector
<int>, std::string
> v
[1];
104 auto h
= make(Tag(), in
{1, 3});
108 BOOST_TEST_THROWS(h
.fill(bad1
), std::invalid_argument
);
110 std::vector
<std::array
<int, 4>> bad2
;
112 BOOST_TEST_THROWS(h
.fill(bad2
), std::invalid_argument
);
115 // 1D with category axis
117 auto h
= make(Tag(), cs
{"A", "B"});
120 const auto s
= {"A", "B", "C"};
121 for (auto&& si
: s
) h(si
);
124 variant
<int, std::string
, std::vector
<std::string
>> v
[1];
129 v
[0] = std::vector
<std::string
>(s
.begin(), s
.end());
130 for (auto&& si
: s
) h(si
);
133 BOOST_TEST_EQ(h
, h2
);
138 auto h
= make(Tag(), in
{1, 3});
141 for (auto&& xi
: x
) h(weight(2), xi
);
142 h2
.fill(weight(2), x
);
144 for (unsigned i
= 0; i
< ndata
; ++i
) h(weight(w
[i
]), x
[i
]);
145 h2
.fill(weight(w
), x
);
147 BOOST_TEST_EQ(h
, h2
);
151 BOOST_TEST_THROWS(h2
.fill(x
, weight(w2
)), std::invalid_argument
);
156 auto h
= make(Tag(), in
{1, 3}, in0
{1, 5});
159 for (int i
= 0; i
< ndata
; ++i
) h(x
[i
], y
[i
]);
160 const auto xy
= {x
, y
};
163 BOOST_TEST_EQ(h
, h2
);
166 BOOST_TEST_THROWS(h
.fill(x
), std::invalid_argument
);
169 std::array
<std::vector
<int>, 2> bad
= {{std::vector
<int>(1), std::vector
<int>(2)}};
171 BOOST_TEST_THROWS(h2
.fill(bad
), std::invalid_argument
);
174 // 2D variant and weight
176 auto h
= make(Tag(), in
{1, 3}, in0
{1, 5});
178 using V
= variant
<int, std::vector
<int>, std::string
>;
186 for (auto&& vi
: y
) h1(3, vi
);
188 BOOST_TEST_EQ(h1
, h2
);
196 for (auto&& vi
: x
) h1(vi
, 3);
198 BOOST_TEST_EQ(h1
, h2
);
206 for (auto&& vi
: y
) h1(3, vi
, weight(2));
207 h2
.fill(xy
, weight(2));
208 BOOST_TEST_EQ(h1
, h2
);
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
);
225 auto h
= make(Tag(), ing());
227 for (const auto& xi
: x
) h(xi
);
229 BOOST_TEST_EQ(h
, h2
);
234 auto h
= make(Tag(), in(1, 3), ing());
236 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], y
[i
]);
237 const auto xy
= {x
, y
};
239 BOOST_TEST_EQ(h
, h2
);
244 auto h
= make(Tag(), ing(), ing());
246 for (unsigned i
= 0; i
< ndata
; ++i
) h(x
[i
], y
[i
]);
247 const auto xy
= {x
, y
};
249 BOOST_TEST_EQ(h
, h2
);
252 // 2D growing with weights A
254 auto h
= make(Tag(), in(1, 3), ing());
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
);
262 // 2D growing with weights B
264 auto h
= make(Tag(), ing(), ing());
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
);
272 // 2D growing and variant
274 auto h
= make(Tag(), csg
{}, in
{1, 2});
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})};
284 BOOST_TEST_EQ(h
, h2
);
286 const auto bad
= {V(std::vector
<std::string
>(1, "foo")), V(std::vector
<int>{1, 2})};
288 BOOST_TEST_THROWS(h
.fill(bad
), std::invalid_argument
);
291 // 1D profile with samples
293 auto h
= make_s(Tag(), profile_storage(), in(1, 3));
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));
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));
306 BOOST_TEST_EQ(h
, h2
);
309 // 2D weighted profile with samples and weights
311 auto h
= make_s(Tag(), weighted_profile_storage(), in(1, 3), in0(1, 3));
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));
318 using V
= variant
<int, std::vector
<int>>;
322 h2
.fill(xy
, sample(w
), weight(w
));
323 h2
.fill(xy
, sample(2), weight(w
));
324 h2
.fill(xy
, sample(w
), weight(2));
326 BOOST_TEST_EQ(h
, h2
);
331 auto h
= make(Tag(), axis2d
{});
334 std::vector
<std::tuple
<double, double>> xy
;
336 for (unsigned i
= 0; i
< ndata
; ++i
) xy
.emplace_back(x
[i
], y
[i
]);
338 for (auto&& xyi
: xy
) h(xyi
);
341 BOOST_TEST_EQ(h
, h2
);
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
)); });
356 run_tests
<static_tag
>(x
, y
, w
);
357 run_tests
<dynamic_tag
>(x
, y
, w
);
359 return boost::report_errors();