]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/histogram/test/storage_adaptor_test.cpp
1 // Copyright 2015-2017 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/core/lightweight_test.hpp>
9 #include <boost/histogram/accumulators/weighted_mean.hpp>
10 #include <boost/histogram/accumulators/weighted_sum.hpp>
11 #include <boost/histogram/storage_adaptor.hpp>
12 #include <boost/histogram/unlimited_storage.hpp>
13 #include <boost/histogram/weight.hpp>
20 #include "is_close.hpp"
21 #include "throw_exception.hpp"
22 #include "utility_allocator.hpp"
24 using namespace boost::histogram
;
25 using namespace std::literals
;
28 auto str(const T
& t
) {
29 std::ostringstream os
;
36 using Storage
= storage_adaptor
<T
>;
44 BOOST_TEST_EQ(std::distance(a
.begin(), a
.end()), 2);
45 BOOST_TEST_EQ(a
.size(), 2);
46 BOOST_TEST_EQ(b
.size(), 2);
47 BOOST_TEST_EQ(c
.size(), 2);
49 Storage
d(std::move(a
));
50 BOOST_TEST_EQ(d
.size(), 2);
53 BOOST_TEST_EQ(e
.size(), 2);
56 storage_adaptor
<T
> g(t
); // tests converting ctor
57 BOOST_TEST_EQ(g
.size(), 0);
58 const auto u
= std::vector
<typename
Storage::value_type
>(3, 1);
59 Storage
h(u
); // tests converting ctor
60 BOOST_TEST_EQ(h
.size(), 3);
61 BOOST_TEST_EQ(h
[0], 1);
62 BOOST_TEST_EQ(h
[1], 1);
63 BOOST_TEST_EQ(h
[2], 1);
66 // increment, add, sub, set, reset, compare
71 const auto save
= a
[0]++;
72 BOOST_TEST_EQ(save
, 1);
73 BOOST_TEST_EQ(a
[0], 2);
75 BOOST_TEST_EQ(a
.size(), 2);
79 BOOST_TEST_EQ(a
[0], 3);
80 BOOST_TEST_EQ(a
[1], 5);
83 BOOST_TEST_EQ(a
[0], 1);
84 BOOST_TEST_EQ(a
[1], 0);
86 BOOST_TEST_EQ(a
[0], 1);
87 BOOST_TEST_EQ(a
[1], 9);
88 BOOST_TEST_LT(a
[0], 2);
89 BOOST_TEST_LT(0, a
[1]);
90 BOOST_TEST_GT(a
[1], 4);
91 BOOST_TEST_GT(3, a
[0]);
93 BOOST_TEST_EQ(a
[0], 1);
94 BOOST_TEST_EQ(a
[1], 1);
96 BOOST_TEST_EQ(a
.size(), 0);
106 BOOST_TEST(!(a
== b
));
109 BOOST_TEST_EQ(b
.size(), 1);
110 BOOST_TEST_EQ(b
[0], 1);
114 BOOST_TEST_EQ(c
.size(), 1);
115 BOOST_TEST_EQ(c
[0], 1);
124 BOOST_TEST(!(a
== b
));
126 BOOST_TEST_EQ(b
.size(), 1);
127 BOOST_TEST_EQ(b
[0], 1);
128 Storage
c(std::move(b
));
129 BOOST_TEST_EQ(c
.size(), 1);
130 BOOST_TEST_EQ(c
[0], 1);
137 BOOST_TEST_EQ(str(a
[0]), "2"s
);
141 template <typename A
, typename B
>
156 BOOST_TEST_EQ(a
[0], 1);
157 BOOST_TEST_EQ(b
[0], 1);
158 BOOST_TEST_EQ(c
[0], 2);
159 BOOST_TEST_EQ(d
[0], 3);
160 BOOST_TEST_EQ(d
[1], 5);
163 BOOST_TEST(!(a
== c
));
164 BOOST_TEST(!(a
== d
));
167 // ctor, copy, move, assign
175 BOOST_TEST_EQ(c
[0], 0);
176 BOOST_TEST_EQ(c
[1], 1);
178 BOOST_TEST_EQ(c
.size(), 0);
182 BOOST_TEST_EQ(e
[0], 0);
183 BOOST_TEST_EQ(e
[1], 1);
188 tests
<std::vector
<int>>();
189 tests
<std::array
<int, 100>>();
190 tests
<std::deque
<int>>();
191 tests
<std::map
<std::size_t, int>>();
192 tests
<std::unordered_map
<std::size_t, int>>();
194 mixed_tests
<storage_adaptor
<std::vector
<int>>,
195 storage_adaptor
<std::array
<double, 100>>>();
196 mixed_tests
<unlimited_storage
<>, storage_adaptor
<std::vector
<double>>>();
197 mixed_tests
<storage_adaptor
<std::vector
<int>>, unlimited_storage
<>>();
198 mixed_tests
<storage_adaptor
<std::vector
<int>>,
199 storage_adaptor
<std::map
<std::size_t, int>>>();
201 // special case for division of map-based storage_adaptor
203 auto a
= storage_adaptor
<std::map
<std::size_t, double>>();
206 BOOST_TEST_EQ(a
[0], 0);
209 BOOST_TEST_EQ(a
[0], 1);
210 a
[1] /= std::numeric_limits
<double>::quiet_NaN();
211 BOOST_TEST(std::isnan(static_cast<double>(a
[1])));
214 // with accumulators::weighted_sum
216 auto a
= storage_adaptor
<std::vector
<accumulators::weighted_sum
<double>>>();
221 a
[0] += accumulators::weighted_sum
<double>(1, 2);
222 BOOST_TEST_EQ(a
[0].value(), 5);
223 BOOST_TEST_EQ(a
[0].variance(), 6);
225 BOOST_TEST_EQ(a
[0].value(), 10);
226 BOOST_TEST_EQ(a
[0].variance(), 24);
229 // with accumulators::weighted_mean
231 auto a
= storage_adaptor
<std::vector
<accumulators::weighted_mean
<double>>>();
233 a
[0](/* sample */ 1);
234 a
[0](weight(2), /* sample */ 2);
236 accumulators::weighted_mean
<double> b
;
240 accumulators::weighted_mean
<double> c
;
245 BOOST_TEST_EQ(a
[0].sum_of_weights(), c
.sum_of_weights());
246 BOOST_TEST_IS_CLOSE(a
[0].value(), c
.value(), 1e-3);
247 BOOST_TEST_IS_CLOSE(a
[0].variance(), c
.variance(), 1e-3);
250 // exceeding array capacity
252 auto a
= storage_adaptor
<std::array
<int, 10>>();
253 a
.reset(10); // should not throw
254 BOOST_TEST_THROWS(a
.reset(11), std::length_error
);
255 auto b
= storage_adaptor
<std::vector
<int>>();
257 BOOST_TEST_THROWS(a
= b
, std::length_error
);
260 // test sparsity of map backend
262 tracing_allocator_db db
;
263 tracing_allocator
<char> alloc(db
);
264 using map_t
= std::map
<std::size_t, double, std::less
<std::size_t>,
265 tracing_allocator
<std::pair
<const std::size_t, double>>>;
266 using A
= storage_adaptor
<map_t
>;
268 // MSVC implementation allocates some structures for debugging
269 const auto baseline
= db
.second
;
271 BOOST_TEST_EQ(db
.first
, baseline
); // nothing allocated yet
272 // queries do not allocate
273 BOOST_TEST_EQ(a
[0], 0);
274 BOOST_TEST_EQ(a
[9], 0);
275 BOOST_TEST_EQ(db
.first
, baseline
);
276 ++a
[5]; // causes one allocation
277 const auto node
= db
.first
- baseline
;
278 BOOST_TEST_EQ(a
[5], 1);
279 a
[4] += 2; // causes one allocation
280 BOOST_TEST_EQ(a
[4], 2);
281 BOOST_TEST_EQ(db
.first
, baseline
+ 2 * node
);
282 a
[3] -= 2; // causes one allocation
283 BOOST_TEST_EQ(a
[3], -2);
284 BOOST_TEST_EQ(db
.first
, baseline
+ 3 * node
);
285 a
[2] *= 2; // no allocation
286 BOOST_TEST_EQ(db
.first
, baseline
+ 3 * node
);
287 a
[2] /= 2; // no allocation
288 BOOST_TEST_EQ(db
.first
, baseline
+ 3 * node
);
289 a
[4] = 0; // causes one deallocation
290 BOOST_TEST_EQ(db
.first
, baseline
+ 2 * node
);
292 auto b
= storage_adaptor
<std::vector
<int>>();
296 // only one new allocation for non-zero value
297 BOOST_TEST_EQ(db
.first
, baseline
+ node
);
300 return boost::report_errors();