]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/histogram/test/storage_adaptor_test.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / histogram / test / storage_adaptor_test.cpp
CommitLineData
92f5a8d4
TL
1// Copyright 2015-2017 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/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>
14#include <cmath>
15#include <deque>
16#include <limits>
17#include <map>
18#include <sstream>
19#include <vector>
20#include "is_close.hpp"
21#include "throw_exception.hpp"
22#include "utility_allocator.hpp"
23
24using namespace boost::histogram;
25using namespace std::literals;
26
27template <class T>
28auto str(const T& t) {
29 std::ostringstream os;
30 os << t;
31 return os.str();
32}
33
34template <typename T>
35void tests() {
36 using Storage = storage_adaptor<T>;
37 // ctor, copy, move
38 {
39 Storage a;
40 a.reset(2);
41 Storage b(a);
42 Storage c;
43 c = a;
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);
48
49 Storage d(std::move(a));
50 BOOST_TEST_EQ(d.size(), 2);
51 Storage e;
52 e = std::move(d);
53 BOOST_TEST_EQ(e.size(), 2);
54
55 const auto t = T();
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);
64 }
65
66 // increment, add, sub, set, reset, compare
67 {
68 Storage a;
69 a.reset(1);
70 ++a[0];
71 const auto save = a[0]++;
72 BOOST_TEST_EQ(save, 1);
73 BOOST_TEST_EQ(a[0], 2);
74 a.reset(2);
75 BOOST_TEST_EQ(a.size(), 2);
76 ++a[0];
77 a[0] += 2;
78 a[1] += 5;
79 BOOST_TEST_EQ(a[0], 3);
80 BOOST_TEST_EQ(a[1], 5);
81 a[0] -= 2;
82 a[1] -= 5;
83 BOOST_TEST_EQ(a[0], 1);
84 BOOST_TEST_EQ(a[1], 0);
85 a[1] = 9;
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]);
92 a[1] = a[0];
93 BOOST_TEST_EQ(a[0], 1);
94 BOOST_TEST_EQ(a[1], 1);
95 a.reset(0);
96 BOOST_TEST_EQ(a.size(), 0);
97 }
98
99 // copy
100 {
101 Storage a;
102 a.reset(1);
103 ++a[0];
104 Storage b;
105 b.reset(2);
106 BOOST_TEST(!(a == b));
107 b = a;
108 BOOST_TEST(a == b);
109 BOOST_TEST_EQ(b.size(), 1);
110 BOOST_TEST_EQ(b[0], 1);
111
112 Storage c(a);
113 BOOST_TEST(a == c);
114 BOOST_TEST_EQ(c.size(), 1);
115 BOOST_TEST_EQ(c[0], 1);
116 }
117
118 // move
119 {
120 Storage a;
121 a.reset(1);
122 ++a[0];
123 Storage b;
124 BOOST_TEST(!(a == b));
125 b = std::move(a);
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);
131 }
132
133 {
134 Storage a;
135 a.reset(1);
136 a[0] += 2;
137 BOOST_TEST_EQ(str(a[0]), "2"s);
138 }
139}
140
141template <typename A, typename B>
142void mixed_tests() {
143 // comparison
144 {
145 A a, b;
146 a.reset(1);
147 b.reset(1);
148 B c, d;
149 c.reset(1);
150 d.reset(2);
151 ++a[0];
152 ++b[0];
153 c[0] += 2;
154 d[0] = 3;
155 d[1] = 5;
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);
161 BOOST_TEST(a == a);
162 BOOST_TEST(a == b);
163 BOOST_TEST(!(a == c));
164 BOOST_TEST(!(a == d));
165 }
166
167 // ctor, copy, move, assign
168 {
169 A a;
170 a.reset(2);
171 ++a[1];
172 B b(a);
173 B c;
174 c = a;
175 BOOST_TEST_EQ(c[0], 0);
176 BOOST_TEST_EQ(c[1], 1);
177 c = A();
178 BOOST_TEST_EQ(c.size(), 0);
179 B d(std::move(a));
180 B e;
181 e = std::move(d);
182 BOOST_TEST_EQ(e[0], 0);
183 BOOST_TEST_EQ(e[1], 1);
184 }
185}
186
187int main() {
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>>();
193
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>>>();
200
201 // special case for division of map-based storage_adaptor
202 {
203 auto a = storage_adaptor<std::map<std::size_t, double>>();
204 a.reset(2);
205 a[0] /= 2;
206 BOOST_TEST_EQ(a[0], 0);
207 a[0] = 2;
208 a[0] /= 2;
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])));
212 }
213
214 // with accumulators::weighted_sum
215 {
216 auto a = storage_adaptor<std::vector<accumulators::weighted_sum<double>>>();
217 a.reset(1);
218 ++a[0];
219 a[0] += 1;
220 a[0] += 2;
f67539c2 221 a[0] += accumulators::weighted_sum<double>(1, 2);
92f5a8d4
TL
222 BOOST_TEST_EQ(a[0].value(), 5);
223 BOOST_TEST_EQ(a[0].variance(), 6);
224 a[0] *= 2;
225 BOOST_TEST_EQ(a[0].value(), 10);
226 BOOST_TEST_EQ(a[0].variance(), 24);
227 }
228
229 // with accumulators::weighted_mean
230 {
231 auto a = storage_adaptor<std::vector<accumulators::weighted_mean<double>>>();
232 a.reset(1);
233 a[0](/* sample */ 1);
234 a[0](weight(2), /* sample */ 2);
1e59de90
TL
235
236 accumulators::weighted_mean<double> b;
237 b(weight(3), 3);
238 a[0] += b;
239
240 accumulators::weighted_mean<double> c;
241 c(weight(1), 1);
242 c(weight(2), 2);
243 c(weight(3), 3);
244
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);
92f5a8d4
TL
248 }
249
250 // exceeding array capacity
251 {
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>>();
256 b.reset(11);
257 BOOST_TEST_THROWS(a = b, std::length_error);
258 }
259
260 // test sparsity of map backend
261 {
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>;
267 auto a = A(alloc);
268 // MSVC implementation allocates some structures for debugging
269 const auto baseline = db.second;
270 a.reset(10);
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);
291
292 auto b = storage_adaptor<std::vector<int>>();
293 b.reset(5);
294 ++b[2];
295 a = b;
296 // only one new allocation for non-zero value
297 BOOST_TEST_EQ(db.first, baseline + node);
298 }
299
300 return boost::report_errors();
301}