]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/histogram/test/axis_variant_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/lightweight_test.hpp>
8 #include <boost/core/lightweight_test_trait.hpp>
9 #include <boost/histogram/axis.hpp>
10 #include <boost/histogram/axis/ostream.hpp>
11 #include <boost/histogram/detail/type_name.hpp>
13 #include <type_traits>
15 #include "std_ostream.hpp"
16 #include "throw_exception.hpp"
17 #include "utility_allocator.hpp"
18 #include "utility_axis.hpp"
19 #include "utility_str.hpp"
22 using namespace boost::histogram
;
23 namespace tr
= axis::transform
;
26 (void)axis::variant
<>{};
30 using meta_type
= std::vector
<int>;
32 axis::variant
<axis::integer
<double>, axis::category
<std::string
, meta_type
>>;
33 auto a
= variant_type
{axis::integer
<double>(0, 2, "foo")};
34 BOOST_TEST_EQ(a
.index(-10), -1);
35 BOOST_TEST_EQ(a
.index(-1), -1);
36 BOOST_TEST_EQ(a
.index(0), 0);
37 BOOST_TEST_EQ(a
.index(0.5), 0);
38 BOOST_TEST_EQ(a
.index(1), 1);
39 BOOST_TEST_EQ(a
.index(2), 2);
40 BOOST_TEST_EQ(a
.index(10), 2);
41 BOOST_TEST_EQ(a
.bin(-1).lower(), -std::numeric_limits
<double>::infinity());
42 BOOST_TEST_EQ(a
.bin(a
.size()).upper(), std::numeric_limits
<double>::infinity());
43 BOOST_TEST_EQ(a
.bin(-10).lower(), -std::numeric_limits
<double>::infinity());
44 BOOST_TEST_EQ(a
.bin(a
.size() + 10).upper(), std::numeric_limits
<double>::infinity());
45 BOOST_TEST_EQ(a
.metadata(), "foo");
47 BOOST_TEST_EQ(static_cast<const variant_type
&>(a
).metadata(), "bar");
48 BOOST_TEST_EQ(a
.options(), axis::option::underflow
| axis::option::overflow
);
50 a
= axis::category
<std::string
, meta_type
>({"A", "B"}, {1, 2, 3});
51 BOOST_TEST_EQ(a
.index("A"), 0);
52 BOOST_TEST_EQ(a
.index("B"), 1);
53 BOOST_TEST_THROWS(a
.metadata(), std::runtime_error
);
54 BOOST_TEST_THROWS(static_cast<const variant_type
&>(a
).metadata(), std::runtime_error
);
55 BOOST_TEST_EQ(a
.options(), axis::option::overflow_t::value
);
58 // axis::variant with pointers
60 using A
= axis::integer
<>;
61 using B
= axis::regular
<>;
62 auto a
= A(1, 5, "foo");
63 auto b
= B(3, 1, 5, "bar");
64 axis::variant
<A
*, B
*> r1(&a
);
66 BOOST_TEST_NE(r1
, A(2, 4));
68 BOOST_TEST_EQ(r1
.size(), 4);
69 BOOST_TEST_EQ(r1
.value(0), 1);
70 BOOST_TEST_EQ(r1
.metadata(), a
.metadata());
71 BOOST_TEST_EQ(r1
.options(), a
.options());
72 // change original through r1
73 r1
.metadata() = "bar";
74 BOOST_TEST_EQ(a
.metadata(), "bar");
78 axis::variant
<const A
*, const B
*> r2(static_cast<const B
*>(&b
));
80 BOOST_TEST_NE(r2
, B(4, 1, 5));
82 BOOST_TEST_EQ(r2
.size(), 3);
83 BOOST_TEST_EQ(r2
.value(0), 1);
84 BOOST_TEST_EQ(r2
.metadata(), "bar");
85 r2
.metadata() = "baz"; // change original through r2
86 BOOST_TEST_EQ(b
.metadata(), "baz");
89 // axis::variant copyable
91 axis::variant
<axis::regular
<>> a1(axis::regular
<>(2, -1, 1));
92 axis::variant
<axis::regular
<>> a2(a1
);
93 BOOST_TEST_EQ(a1
, a2
);
94 axis::variant
<axis::regular
<>> a3
;
95 BOOST_TEST_NE(a3
, a1
);
97 BOOST_TEST_EQ(a3
, a1
);
98 axis::variant
<axis::regular
<>> a4(axis::regular
<>(3, -2, 2));
99 axis::variant
<axis::regular
<>, axis::integer
<>> a5(a4
);
100 BOOST_TEST_EQ(a4
, a5
);
101 axis::variant
<axis::regular
<>> a6
;
103 BOOST_TEST_EQ(a6
, a1
);
104 axis::variant
<axis::regular
<>, axis::integer
<>> a7(axis::integer
<>(0, 2));
105 BOOST_TEST_THROWS(axis::variant
<axis::regular
<>> a8(a7
), std::runtime_error
);
106 BOOST_TEST_THROWS(a4
= a7
, std::runtime_error
);
109 // axis::variant movable
111 axis::variant
<axis::regular
<>> a(axis::regular
<>(2, -1, 1));
112 axis::variant
<axis::regular
<>> r(a
);
113 axis::variant
<axis::regular
<>> b(std::move(a
));
115 axis::variant
<axis::regular
<>> c
;
121 // axis::variant streamable
123 auto test
= [](auto&& a
, const char* ref
) {
124 using T
= std::decay_t
<decltype(a
)>;
125 axis::variant
<T
> axis(std::move(a
));
126 BOOST_TEST_CSTR_EQ(str(axis
).c_str(), ref
);
129 test(axis::regular
<>{2, -1, 1, "foo"},
130 "regular(2, -1, 1, metadata=\"foo\", options=underflow | overflow)");
132 test(axis::boolean
<>{"bar"}, "boolean(metadata=\"bar\")");
134 struct user_defined
{};
135 const auto ref
= "integer(-1, 1, metadata=" + detail::type_name
<user_defined
>() +
137 test(axis::integer
<int, user_defined
, axis::option::none_t
>(-1, 1), ref
.c_str());
140 // bin_type operator<<
142 auto test
= [](auto&& a
, const char* ref
) {
143 using T
= std::decay_t
<decltype(a
)>;
144 axis::variant
<T
> axis(std::move(a
));
145 BOOST_TEST_CSTR_EQ(str(axis
.bin(0)).c_str(), ref
);
148 test(axis::regular
<>(2, 1, 2), "[1, 1.5)");
149 test(axis::category
<>({1, 2}), "1");
152 // axis::variant operator==
156 axis::variant
<axis::regular
<>, axis::regular
<double, axis::transform::pow
>,
157 axis::category
<>, axis::integer
<>, axis::boolean
<>>;
158 std::vector
<variant
> axes
;
159 axes
.push_back(axis::regular
<>{2, -1, 1});
160 axes
.push_back(axis::regular
<double, tr::pow
>{tr::pow
{0.5}, 2, 1, 4});
161 axes
.push_back(axis::category
<>{A
, B
, C
});
162 axes
.push_back(axis::integer
<>{-1, 1});
163 axes
.push_back(axis::boolean
<>{});
164 for (const auto& a
: axes
) {
165 BOOST_TEST_NE(a
, variant
{});
166 BOOST_TEST_EQ(a
, variant(a
));
168 BOOST_TEST_NE(axes
, std::vector
<variant
>{});
169 BOOST_TEST(axes
== std::vector
<variant
>(axes
));
172 // axis::variant with axis that has incompatible bin type
174 auto a
= axis::variant
<axis::category
<std::string
>>{
175 axis::category
<std::string
>{"A", "B", "C"}};
176 BOOST_TEST_THROWS(a
.bin(0), std::runtime_error
);
177 auto b
= axis::variant
<axis::category
<int>>{axis::category
<int>{2, 1, 3}};
178 BOOST_TEST_EQ(b
.bin(0), 2);
179 BOOST_TEST_EQ(b
.bin(0).lower(),
180 b
.bin(0).upper()); // lower == upper for bin without interval
183 // axis::variant support for user-defined axis types
185 struct minimal_axis
{
186 int index(int x
) const { return x
% 2; }
187 int size() const { return 2; }
190 axis::variant
<minimal_axis
, axis::category
<std::string
>> axis
;
191 BOOST_TEST_EQ(axis
.index(0), 0);
192 BOOST_TEST_EQ(axis
.index(9), 1);
193 BOOST_TEST_EQ(axis
.size(), 2);
194 BOOST_TEST_EQ(axis
.metadata(), axis::null_type
{});
195 BOOST_TEST_EQ(str(axis
), detail::type_name
<minimal_axis
>());
196 BOOST_TEST_THROWS(axis
.value(0), std::runtime_error
);
198 axis
= axis::category
<std::string
>({"A", "B"}, "category");
199 BOOST_TEST_EQ(axis
.index("B"), 1);
200 BOOST_TEST_THROWS(axis
.value(0), std::runtime_error
);
203 // vector of axes with custom allocators
205 using M
= std::vector
<char, tracing_allocator
<char>>;
206 using T1
= axis::regular
<double, tr::id
, M
>;
207 using T2
= axis::integer
<int, axis::null_type
>;
208 using T3
= axis::category
<long, axis::null_type
, axis::option::overflow_t
,
209 tracing_allocator
<long>>;
210 using axis_type
= axis::variant
<T1
, T2
, T3
>; // no heap allocation
211 using axes_type
= std::vector
<axis_type
, tracing_allocator
<axis_type
>>;
213 tracing_allocator_db db
;
215 auto a
= tracing_allocator
<char>(db
);
218 axes
.emplace_back(T1(1, 0, 1, M(3, 'c', a
)));
219 axes
.emplace_back(T2(0, 4));
220 axes
.emplace_back(T3({1, 2, 3, 4, 5}, {}, a
));
222 // 3 axis::variant objects
223 BOOST_TEST_EQ(db
.at
<axis_type
>().first
, 0);
224 BOOST_TEST_EQ(db
.at
<axis_type
>().second
, 3);
227 BOOST_TEST_EQ(db
.at
<char>().first
, 0);
228 BOOST_TEST_EQ(db
.at
<char>().second
, 3);
230 // T3 allocates storage for long array
231 BOOST_TEST_EQ(db
.at
<long>().first
, 0);
232 BOOST_TEST_EQ(db
.at
<long>().second
, 5);
235 // testing pass-through versions of get
237 axis::regular
<> a(10, 0, 1);
238 axis::integer
<> b(0, 3);
239 const auto& ta
= axis::get
<axis::regular
<>>(a
);
240 BOOST_TEST_EQ(ta
, a
);
241 const auto* tb
= axis::get_if
<axis::integer
<>>(&b
);
242 BOOST_TEST_EQ(tb
, &b
);
243 const auto* tc
= axis::get_if
<axis::regular
<>>(&b
);
244 BOOST_TEST_EQ(tc
, nullptr);
248 test_axis_iterator(axis::variant
<axis::regular
<>>(axis::regular
<>(5, 0, 1)), 0, 5);
250 return boost::report_errors();