ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GridTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file GridTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-2018 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include <boost/test/unit_test.hpp>
10 
11 #include <chrono>
12 #include <random>
13 
17 
18 namespace Acts {
19 
20 using namespace detail;
21 
22 namespace Test {
23 
24 BOOST_AUTO_TEST_CASE(grid_test_1d_equidistant) {
25  using Point = std::array<double, 1>;
26  using indices = std::array<size_t, 1>;
27  EquidistantAxis a(0.0, 4.0, 4u);
28  Grid<double, EquidistantAxis> g(std::make_tuple(std::move(a)));
29 
30  // test general properties
31  BOOST_CHECK_EQUAL(g.size(), 6u);
32  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 4u);
33 
34  // global bin index
35  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-0.3}})), 0u);
36  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-0.}})), 1u);
37  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.}})), 1u);
38  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.7}})), 1u);
39  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1}})), 2u);
40  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1.2}})), 2u);
41  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2.}})), 3u);
42  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2.7}})), 3u);
43  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3.}})), 4u);
44  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3.9999}})), 4u);
45  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4.}})), 5u);
46  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4.98}})), 5u);
47 
48  // global bin index -> local bin indices
49  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0}}));
50  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{1}}));
51  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{2}}));
52  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{3}}));
53  BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices({{4}}));
54  BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices({{5}}));
55 
56  // local bin indices -> global bin index
57  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0}}), 0u);
58  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1}}), 1u);
59  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2}}), 2u);
60  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3}}), 3u);
61  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4}}), 4u);
62  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5}}), 5u);
63 
64  BOOST_CHECK(g.localBinsFromGlobalBin(
65  g.globalBinFromPosition(Point({{2.7}}))) == indices({{3}}));
66 
67  // inside checks
68  BOOST_CHECK(not g.isInside(Point({{-2.}})));
69  BOOST_CHECK(g.isInside(Point({{0.}})));
70  BOOST_CHECK(g.isInside(Point({{2.5}})));
71  BOOST_CHECK(not g.isInside(Point({{4.}})));
72  BOOST_CHECK(not g.isInside(Point({{6.}})));
73 
74  // test some bin centers
75  CHECK_CLOSE_ABS(g.binCenter({{1}}), Point({{0.5}}), 1e-6);
76  CHECK_CLOSE_ABS(g.binCenter({{2}}), Point({{1.5}}), 1e-6);
77  CHECK_CLOSE_ABS(g.binCenter({{3}}), Point({{2.5}}), 1e-6);
78  CHECK_CLOSE_ABS(g.binCenter({{4}}), Point({{3.5}}), 1e-6);
79 
80  // test some lower-left bin edges
81  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1}}), Point({{0.}}), 1e-6);
82  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2}}), Point({{1.}}), 1e-6);
83  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{3}}), Point({{2.}}), 1e-6);
84  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{4}}), Point({{3.}}), 1e-6);
85 
86  // test some upper right-bin edges
87  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1}}), Point({{1.}}), 1e-6);
88  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2}}), Point({{2.}}), 1e-6);
89  CHECK_CLOSE_ABS(g.upperRightBinEdge({{3}}), Point({{3.}}), 1e-6);
90  CHECK_CLOSE_ABS(g.upperRightBinEdge({{4}}), Point({{4.}}), 1e-6);
91 
92  // initialize grid
93  for (size_t bin = 0; bin < g.size(); ++bin) {
94  g.at(bin) = bin;
95  }
96 
97  // consistency of access
98  const auto& point = Point({{0.7}});
99  size_t globalBin = g.globalBinFromPosition(point);
100  indices localBins = g.localBinsFromGlobalBin(globalBin);
101 
102  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
103  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
104 }
105 
106 BOOST_AUTO_TEST_CASE(grid_test_2d_equidistant) {
107  using Point = std::array<double, 2>;
108  using indices = std::array<size_t, 2>;
109  EquidistantAxis a(0.0, 4.0, 4u);
110  EquidistantAxis b(0.0, 3.0, 3u);
112  std::make_tuple(std::move(a), std::move(b)));
113 
114  // test general properties
115  BOOST_CHECK_EQUAL(g.size(), 30u);
116  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 4u);
117  BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 3u);
118 
119  // global bin index
120  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-1, -1}})), 0u);
121  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-1, 0}})), 1u);
122  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-1, 1}})), 2u);
123  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-1, 2}})), 3u);
124  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-1, 3}})), 4u);
125  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, -1}})), 5u);
126  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0}})), 6u);
127  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 1}})), 7u);
128  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 2}})), 8u);
129  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3}})), 9u);
130  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, -1}})), 10u);
131  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0}})), 11u);
132  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 1}})), 12u);
133  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 2}})), 13u);
134  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3}})), 14u);
135  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, -1}})), 15u);
136  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 0}})), 16u);
137  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 1}})), 17u);
138  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 2}})), 18u);
139  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 3}})), 19u);
140  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, -1}})), 20u);
141  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 0}})), 21u);
142  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 1}})), 22u);
143  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 2}})), 23u);
144  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 3}})), 24u);
145  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4, -1}})), 25u);
146  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4, 0}})), 26u);
147  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4, 1}})), 27u);
148  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4, 2}})), 28u);
149  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4, 3}})), 29u);
150 
151  // test some arbitrary points
152  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1.2, 0.3}})), 11u);
153  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2.2, 3.3}})), 19u);
154  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.9, 1.8}})), 7u);
155  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3.7, 3.1}})), 24u);
156  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1.4, 2.3}})), 13u);
157  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-3, 3}})), 4u);
158  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{8, 1}})), 27u);
159  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, -3}})), 10u);
160  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 11}})), 24u);
161  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-2, -3}})), 0u);
162  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-2, 7}})), 04u);
163  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{12, -1}})), 25u);
164  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{12, 11}})), 29u);
165 
166  // global bin index -> local bin indices
167  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0, 0}}));
168  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{0, 1}}));
169  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{0, 2}}));
170  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{0, 3}}));
171  BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices({{0, 4}}));
172  BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices({{1, 0}}));
173  BOOST_CHECK(g.localBinsFromGlobalBin(6) == indices({{1, 1}}));
174  BOOST_CHECK(g.localBinsFromGlobalBin(7) == indices({{1, 2}}));
175  BOOST_CHECK(g.localBinsFromGlobalBin(8) == indices({{1, 3}}));
176  BOOST_CHECK(g.localBinsFromGlobalBin(9) == indices({{1, 4}}));
177  BOOST_CHECK(g.localBinsFromGlobalBin(10) == indices({{2, 0}}));
178  BOOST_CHECK(g.localBinsFromGlobalBin(11) == indices({{2, 1}}));
179  BOOST_CHECK(g.localBinsFromGlobalBin(12) == indices({{2, 2}}));
180  BOOST_CHECK(g.localBinsFromGlobalBin(13) == indices({{2, 3}}));
181  BOOST_CHECK(g.localBinsFromGlobalBin(14) == indices({{2, 4}}));
182  BOOST_CHECK(g.localBinsFromGlobalBin(15) == indices({{3, 0}}));
183  BOOST_CHECK(g.localBinsFromGlobalBin(16) == indices({{3, 1}}));
184  BOOST_CHECK(g.localBinsFromGlobalBin(17) == indices({{3, 2}}));
185  BOOST_CHECK(g.localBinsFromGlobalBin(18) == indices({{3, 3}}));
186  BOOST_CHECK(g.localBinsFromGlobalBin(19) == indices({{3, 4}}));
187  BOOST_CHECK(g.localBinsFromGlobalBin(20) == indices({{4, 0}}));
188  BOOST_CHECK(g.localBinsFromGlobalBin(21) == indices({{4, 1}}));
189  BOOST_CHECK(g.localBinsFromGlobalBin(22) == indices({{4, 2}}));
190  BOOST_CHECK(g.localBinsFromGlobalBin(23) == indices({{4, 3}}));
191  BOOST_CHECK(g.localBinsFromGlobalBin(24) == indices({{4, 4}}));
192  BOOST_CHECK(g.localBinsFromGlobalBin(25) == indices({{5, 0}}));
193  BOOST_CHECK(g.localBinsFromGlobalBin(26) == indices({{5, 1}}));
194  BOOST_CHECK(g.localBinsFromGlobalBin(27) == indices({{5, 2}}));
195  BOOST_CHECK(g.localBinsFromGlobalBin(28) == indices({{5, 3}}));
196  BOOST_CHECK(g.localBinsFromGlobalBin(29) == indices({{5, 4}}));
197 
198  // local bin indices -> global bin index
199  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0}}), 0u);
200  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1}}), 1u);
201  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 2}}), 2u);
202  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 3}}), 3u);
203  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 4}}), 4u);
204  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 0}}), 5u);
205  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1}}), 6u);
206  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 2}}), 7u);
207  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 3}}), 8u);
208  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 4}}), 9u);
209  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 0}}), 10u);
210  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 1}}), 11u);
211  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 2}}), 12u);
212  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3}}), 13u);
213  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 4}}), 14u);
214  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0}}), 15u);
215  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 1}}), 16u);
216  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 2}}), 17u);
217  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 3}}), 18u);
218  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 4}}), 19u);
219  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 0}}), 20u);
220  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 1}}), 21u);
221  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 2}}), 22u);
222  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 3}}), 23u);
223  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 4}}), 24u);
224  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 0}}), 25u);
225  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 1}}), 26u);
226  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 2}}), 27u);
227  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 3}}), 28u);
228  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 4}}), 29u);
229 
230  BOOST_CHECK(g.localBinsFromGlobalBin(g.globalBinFromPosition(
231  Point({{1.2, 0.7}}))) == indices({{2, 1}}));
232 
233  // inside checks
234  BOOST_CHECK(not g.isInside(Point({{-2., -1}})));
235  BOOST_CHECK(not g.isInside(Point({{-2., 1.}})));
236  BOOST_CHECK(not g.isInside(Point({{-2., 5.}})));
237  BOOST_CHECK(not g.isInside(Point({{1., -1.}})));
238  BOOST_CHECK(not g.isInside(Point({{6., -1.}})));
239  BOOST_CHECK(g.isInside(Point({{0.5, 1.3}})));
240  BOOST_CHECK(not g.isInside(Point({{4., -1.}})));
241  BOOST_CHECK(not g.isInside(Point({{4., 0.3}})));
242  BOOST_CHECK(not g.isInside(Point({{4., 3.}})));
243  BOOST_CHECK(not g.isInside(Point({{-1., 3.}})));
244  BOOST_CHECK(not g.isInside(Point({{2., 3.}})));
245  BOOST_CHECK(not g.isInside(Point({{5., 3.}})));
246 
247  // test some bin centers
248  CHECK_CLOSE_ABS(g.binCenter({{1, 1}}), Point({{0.5, 0.5}}), 1e-6);
249  CHECK_CLOSE_ABS(g.binCenter({{2, 3}}), Point({{1.5, 2.5}}), 1e-6);
250  CHECK_CLOSE_ABS(g.binCenter({{3, 1}}), Point({{2.5, 0.5}}), 1e-6);
251  CHECK_CLOSE_ABS(g.binCenter({{4, 2}}), Point({{3.5, 1.5}}), 1e-6);
252 
253  // test some lower-left bin edges
254  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1}}), Point({{0., 0.}}), 1e-6);
255  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 3}}), Point({{1., 2.}}), 1e-6);
256  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{3, 1}}), Point({{2., 0.}}), 1e-6);
257  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{4, 2}}), Point({{3., 1.}}), 1e-6);
258 
259  // test some upper right-bin edges
260  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1}}), Point({{1., 1.}}), 1e-6);
261  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 3}}), Point({{2., 3.}}), 1e-6);
262  CHECK_CLOSE_ABS(g.upperRightBinEdge({{3, 1}}), Point({{3., 1.}}), 1e-6);
263  CHECK_CLOSE_ABS(g.upperRightBinEdge({{4, 2}}), Point({{4., 2.}}), 1e-6);
264 
265  // initialize grid
266  for (size_t bin = 0; bin < g.size(); ++bin) {
267  g.at(bin) = bin;
268  }
269 
270  // consistency of access
271  const auto& point = Point({{0.7, 1.3}});
272  size_t globalBin = g.globalBinFromPosition(point);
273  indices localBins = g.localBinsFromGlobalBin(globalBin);
274 
275  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
276  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
277 }
278 
279 BOOST_AUTO_TEST_CASE(grid_test_3d_equidistant) {
280  using Point = std::array<double, 3>;
281  using indices = std::array<size_t, 3>;
282  EquidistantAxis a(0.0, 2.0, 2u);
283  EquidistantAxis b(0.0, 3.0, 3u);
284  EquidistantAxis c(0.0, 2.0, 2u);
286  std::make_tuple(std::move(a), std::move(b), std::move(c)));
287 
288  // test general properties
289  BOOST_CHECK_EQUAL(g.size(), 80u);
290  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 2u);
291  BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 3u);
292  BOOST_CHECK_EQUAL(g.numLocalBins().at(2), 2u);
293 
294  // test grid points
295  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 0}})), 25u);
296  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 1}})), 26u);
297  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 2}})), 27u);
298  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 1, 0}})), 29u);
299  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 1, 1}})), 30u);
300  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 1, 2}})), 31u);
301  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 2, 0}})), 33u);
302  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 2, 1}})), 34u);
303  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 2, 2}})), 35u);
304  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 0}})), 37u);
305  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 1}})), 38u);
306  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 2}})), 39u);
307  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 0}})), 45u);
308  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 1}})), 46u);
309  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 2}})), 47u);
310  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 1, 0}})), 49u);
311  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 1, 1}})), 50u);
312  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 1, 2}})), 51u);
313  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 2, 0}})), 53u);
314  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 2, 1}})), 54u);
315  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 2, 2}})), 55u);
316  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 0}})), 57u);
317  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 1}})), 58u);
318  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 2}})), 59u);
319  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 0, 0}})), 65u);
320  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 0, 1}})), 66u);
321  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 0, 2}})), 67u);
322  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 1, 0}})), 69u);
323  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 1, 1}})), 70u);
324  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 1, 2}})), 71u);
325  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 2, 0}})), 73u);
326  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 2, 1}})), 74u);
327  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 2, 2}})), 75u);
328  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 3, 0}})), 77u);
329  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 3, 1}})), 78u);
330  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, 3, 2}})), 79u);
331 
332  // global bin index -> local bin indices
333  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0, 0, 0}}));
334  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{0, 0, 1}}));
335  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{0, 0, 2}}));
336  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{0, 0, 3}}));
337  BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices({{0, 1, 0}}));
338  BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices({{0, 1, 1}}));
339  BOOST_CHECK(g.localBinsFromGlobalBin(6) == indices({{0, 1, 2}}));
340  BOOST_CHECK(g.localBinsFromGlobalBin(7) == indices({{0, 1, 3}}));
341  BOOST_CHECK(g.localBinsFromGlobalBin(24) == indices({{1, 1, 0}}));
342  BOOST_CHECK(g.localBinsFromGlobalBin(25) == indices({{1, 1, 1}}));
343  BOOST_CHECK(g.localBinsFromGlobalBin(26) == indices({{1, 1, 2}}));
344  BOOST_CHECK(g.localBinsFromGlobalBin(27) == indices({{1, 1, 3}}));
345  BOOST_CHECK(g.localBinsFromGlobalBin(52) == indices({{2, 3, 0}}));
346  BOOST_CHECK(g.localBinsFromGlobalBin(53) == indices({{2, 3, 1}}));
347  BOOST_CHECK(g.localBinsFromGlobalBin(54) == indices({{2, 3, 2}}));
348  BOOST_CHECK(g.localBinsFromGlobalBin(55) == indices({{2, 3, 3}}));
349  BOOST_CHECK(g.localBinsFromGlobalBin(60) == indices({{3, 0, 0}}));
350  BOOST_CHECK(g.localBinsFromGlobalBin(61) == indices({{3, 0, 1}}));
351  BOOST_CHECK(g.localBinsFromGlobalBin(62) == indices({{3, 0, 2}}));
352  BOOST_CHECK(g.localBinsFromGlobalBin(63) == indices({{3, 0, 3}}));
353  BOOST_CHECK(g.localBinsFromGlobalBin(76) == indices({{3, 4, 0}}));
354  BOOST_CHECK(g.localBinsFromGlobalBin(77) == indices({{3, 4, 1}}));
355  BOOST_CHECK(g.localBinsFromGlobalBin(78) == indices({{3, 4, 2}}));
356  BOOST_CHECK(g.localBinsFromGlobalBin(79) == indices({{3, 4, 3}}));
357 
358  // local bin indices -> global bin index
359  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0, 0}}), 0u);
360  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0, 1}}), 1u);
361  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0, 2}}), 2u);
362  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0, 3}}), 3u);
363  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1, 0}}), 4u);
364  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1, 1}}), 5u);
365  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1, 2}}), 6u);
366  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1, 3}}), 7u);
367  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1, 0}}), 24u);
368  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1, 1}}), 25u);
369  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1, 2}}), 26u);
370  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1, 3}}), 27u);
371  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3, 0}}), 52u);
372  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3, 1}}), 53u);
373  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3, 2}}), 54u);
374  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3, 3}}), 55u);
375  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0, 0}}), 60u);
376  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0, 1}}), 61u);
377  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0, 2}}), 62u);
378  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0, 3}}), 63u);
379  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 4, 0}}), 76u);
380  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 4, 1}}), 77u);
381  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 4, 2}}), 78u);
382  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 4, 3}}), 79u);
383 
384  BOOST_CHECK(g.localBinsFromGlobalBin(g.globalBinFromPosition(
385  Point({{1.2, 0.7, 1.4}}))) == indices({{2, 1, 2}}));
386 
387  // inside checks
388  BOOST_CHECK(not g.isInside(Point({{-2., -1, -2}})));
389  BOOST_CHECK(not g.isInside(Point({{-2., 1., 0.}})));
390  BOOST_CHECK(not g.isInside(Point({{-2., 5., -1}})));
391  BOOST_CHECK(not g.isInside(Point({{1., -1., 1.}})));
392  BOOST_CHECK(not g.isInside(Point({{6., -1., 4.}})));
393  BOOST_CHECK(g.isInside(Point({{0.5, 1.3, 1.7}})));
394  BOOST_CHECK(not g.isInside(Point({{2., -1., -0.4}})));
395  BOOST_CHECK(not g.isInside(Point({{2., 0.3, 3.4}})));
396  BOOST_CHECK(not g.isInside(Point({{2., 3., 0.8}})));
397  BOOST_CHECK(not g.isInside(Point({{-1., 3., 5.}})));
398  BOOST_CHECK(not g.isInside(Point({{2., 3., -1.}})));
399  BOOST_CHECK(not g.isInside(Point({{5., 3., 0.5}})));
400 
401  // test some bin centers
402  CHECK_CLOSE_ABS(g.binCenter({{1, 1, 1}}), Point({{0.5, 0.5, 0.5}}), 1e-6);
403  CHECK_CLOSE_ABS(g.binCenter({{2, 3, 2}}), Point({{1.5, 2.5, 1.5}}), 1e-6);
404  CHECK_CLOSE_ABS(g.binCenter({{1, 1, 2}}), Point({{0.5, 0.5, 1.5}}), 1e-6);
405  CHECK_CLOSE_ABS(g.binCenter({{2, 2, 1}}), Point({{1.5, 1.5, 0.5}}), 1e-6);
406 
407  // test some lower-left bin edges
408  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1, 1}}), Point({{0., 0., 0.}}), 1e-6);
409  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 3, 2}}), Point({{1., 2., 1.}}), 1e-6);
410  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1, 2}}), Point({{0., 0., 1.}}), 1e-6);
411  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 2, 1}}), Point({{1., 1., 0.}}), 1e-6);
412 
413  // test some upper right-bin edges
414  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1, 1}}), Point({{1., 1., 1.}}),
415  1e-6);
416  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 3, 2}}), Point({{2., 3., 2.}}),
417  1e-6);
418  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1, 2}}), Point({{1., 1., 2.}}),
419  1e-6);
420  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 2, 1}}), Point({{2., 2., 1.}}),
421  1e-6);
422 
423  // initialize grid
424  for (size_t bin = 0; bin < g.size(); ++bin) {
425  g.at(bin) = bin;
426  }
427 
428  // consistency of access
429  const auto& point = Point({{0.7, 2.3, 1.3}});
430  size_t globalBin = g.globalBinFromPosition(point);
431  indices localBins = g.localBinsFromGlobalBin(globalBin);
432 
433  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
434  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
435 }
436 
437 BOOST_AUTO_TEST_CASE(grid_test_1d_variable) {
438  using Point = std::array<double, 1>;
439  using indices = std::array<size_t, 1>;
440  VariableAxis a({0.0, 1.0, 4.0});
441  Grid<double, VariableAxis> g(std::make_tuple(std::move(a)));
442 
443  // test general properties
444  BOOST_CHECK_EQUAL(g.size(), 4u);
445  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 2u);
446 
447  // global bin index
448  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-0.3}})), 0u);
449  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.}})), 1u);
450  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.7}})), 1u);
451  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1}})), 2u);
452  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1.2}})), 2u);
453  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2.7}})), 2u);
454  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4.}})), 3u);
455  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{4.98}})), 3u);
456 
457  // global bin index -> local bin indices
458  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0}}));
459  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{1}}));
460  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{2}}));
461  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{3}}));
462 
463  // local bin indices -> global bin index
464  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0}}), 0u);
465  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1}}), 1u);
466  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2}}), 2u);
467  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3}}), 3u);
468 
469  BOOST_CHECK(g.localBinsFromGlobalBin(
470  g.globalBinFromPosition(Point({{0.8}}))) == indices({{1}}));
471 
472  // inside checks
473  BOOST_CHECK(not g.isInside(Point({{-2.}})));
474  BOOST_CHECK(g.isInside(Point({{0.}})));
475  BOOST_CHECK(g.isInside(Point({{2.5}})));
476  BOOST_CHECK(not g.isInside(Point({{4.}})));
477  BOOST_CHECK(not g.isInside(Point({{6.}})));
478 
479  // test some bin centers
480  CHECK_CLOSE_ABS(g.binCenter({{1}}), Point({{0.5}}), 1e-6);
481  CHECK_CLOSE_ABS(g.binCenter({{2}}), Point({{2.5}}), 1e-6);
482 
483  // test some lower-left bin edges
484  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1}}), Point({{0.}}), 1e-6);
485  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2}}), Point({{1.}}), 1e-6);
486 
487  // test some upper right-bin edges
488  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1}}), Point({{1.}}), 1e-6);
489  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2}}), Point({{4.}}), 1e-6);
490 
491  // initialize grid
492  for (size_t bin = 0; bin < g.size(); ++bin) {
493  g.at(bin) = bin;
494  }
495 
496  // consistency of access
497  const auto& point = Point({{0.7}});
498  size_t globalBin = g.globalBinFromPosition(point);
499  indices localBins = g.localBinsFromGlobalBin(globalBin);
500 
501  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
502  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
503 }
504 
505 BOOST_AUTO_TEST_CASE(grid_test_2d_variable) {
506  using Point = std::array<double, 2>;
507  using indices = std::array<size_t, 2>;
508  VariableAxis a({0.0, 0.5, 3.0});
509  VariableAxis b({0.0, 1.0, 4.0});
511  std::make_tuple(std::move(a), std::move(b)));
512 
513  // test general properties
514  BOOST_CHECK_EQUAL(g.size(), 16u);
515  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 2u);
516  BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 2u);
517 
518  // test grid points
519  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0}})), 5u);
520  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 1}})), 6u);
521  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 4}})), 7u);
522  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.5, 0}})), 9u);
523  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.5, 1}})), 10u);
524  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.5, 4}})), 11u);
525  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 0}})), 13u);
526  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 1}})), 14u);
527  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3, 4}})), 15u);
528 
529  // test some arbitrary points
530  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.3, 1.2}})), 6u);
531  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3.3, 2.2}})), 14u);
532  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1.8, 0.9}})), 9u);
533  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{3.1, 0.7}})), 13u);
534  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2.3, 1.4}})), 10u);
535  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{2, -3}})), 8u);
536  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 8}})), 11u);
537  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-3, 1}})), 2u);
538  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{11, 3}})), 14u);
539  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-3, -2}})), 0u);
540  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{7, -2}})), 12u);
541  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-1, 12}})), 3u);
542  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{11, 12}})), 15u);
543 
544  // global bin index -> local bin indices
545  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0, 0}}));
546  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{0, 1}}));
547  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{0, 2}}));
548  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{0, 3}}));
549  BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices({{1, 0}}));
550  BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices({{1, 1}}));
551  BOOST_CHECK(g.localBinsFromGlobalBin(6) == indices({{1, 2}}));
552  BOOST_CHECK(g.localBinsFromGlobalBin(7) == indices({{1, 3}}));
553  BOOST_CHECK(g.localBinsFromGlobalBin(8) == indices({{2, 0}}));
554  BOOST_CHECK(g.localBinsFromGlobalBin(9) == indices({{2, 1}}));
555  BOOST_CHECK(g.localBinsFromGlobalBin(10) == indices({{2, 2}}));
556  BOOST_CHECK(g.localBinsFromGlobalBin(11) == indices({{2, 3}}));
557  BOOST_CHECK(g.localBinsFromGlobalBin(12) == indices({{3, 0}}));
558  BOOST_CHECK(g.localBinsFromGlobalBin(13) == indices({{3, 1}}));
559  BOOST_CHECK(g.localBinsFromGlobalBin(14) == indices({{3, 2}}));
560  BOOST_CHECK(g.localBinsFromGlobalBin(15) == indices({{3, 3}}));
561 
562  // local bin indices -> global bin index
563  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0}}), 0u);
564  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1}}), 1u);
565  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 2}}), 2u);
566  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 3}}), 3u);
567  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 0}}), 4u);
568  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1}}), 5u);
569  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 2}}), 6u);
570  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 3}}), 7u);
571  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 0}}), 8u);
572  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 1}}), 9u);
573  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 2}}), 10u);
574  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3}}), 11u);
575  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0}}), 12u);
576  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 1}}), 13u);
577  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 2}}), 14u);
578  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 3}}), 15u);
579 
580  BOOST_CHECK(g.localBinsFromGlobalBin(g.globalBinFromPosition(
581  Point({{3.2, 1.8}}))) == indices({{3, 2}}));
582 
583  // inside checks
584  BOOST_CHECK(not g.isInside(Point({{-2., -1}})));
585  BOOST_CHECK(not g.isInside(Point({{-2., 1.}})));
586  BOOST_CHECK(not g.isInside(Point({{-2., 5.}})));
587  BOOST_CHECK(not g.isInside(Point({{1., -1.}})));
588  BOOST_CHECK(not g.isInside(Point({{6., -1.}})));
589  BOOST_CHECK(g.isInside(Point({{0.5, 1.3}})));
590  BOOST_CHECK(not g.isInside(Point({{3., -1.}})));
591  BOOST_CHECK(not g.isInside(Point({{3., 0.3}})));
592  BOOST_CHECK(not g.isInside(Point({{3., 4.}})));
593  BOOST_CHECK(not g.isInside(Point({{-1., 4.}})));
594  BOOST_CHECK(not g.isInside(Point({{2., 4.}})));
595  BOOST_CHECK(not g.isInside(Point({{5., 4.}})));
596 
597  // test some bin centers
598  CHECK_CLOSE_ABS(g.binCenter({{1, 1}}), Point({{0.25, 0.5}}), 1e-6);
599  CHECK_CLOSE_ABS(g.binCenter({{2, 1}}), Point({{1.75, 0.5}}), 1e-6);
600  CHECK_CLOSE_ABS(g.binCenter({{1, 2}}), Point({{0.25, 2.5}}), 1e-6);
601  CHECK_CLOSE_ABS(g.binCenter({{2, 2}}), Point({{1.75, 2.5}}), 1e-6);
602 
603  // test some lower-left bin edges
604  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1}}), Point({{0., 0.}}), 1e-6);
605  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 1}}), Point({{0.5, 0.}}), 1e-6);
606  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 2}}), Point({{0., 1.}}), 1e-6);
607  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 2}}), Point({{0.5, 1.}}), 1e-6);
608 
609  // test some upper right-bin edges
610  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1}}), Point({{0.5, 1.}}), 1e-6);
611  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 1}}), Point({{3., 1.}}), 1e-6);
612  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 2}}), Point({{0.5, 4.}}), 1e-6);
613  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 2}}), Point({{3., 4.}}), 1e-6);
614 
615  // initialize grid
616  for (size_t bin = 0; bin < g.size(); ++bin) {
617  g.at(bin) = bin;
618  }
619 
620  // consistency of access
621  const auto& point = Point({{0.7, 1.3}});
622  size_t globalBin = g.globalBinFromPosition(point);
623  indices localBins = g.localBinsFromGlobalBin(globalBin);
624 
625  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
626  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
627 }
628 
629 BOOST_AUTO_TEST_CASE(grid_test_3d_variable) {
630  using Point = std::array<double, 3>;
631  using indices = std::array<size_t, 3>;
632  VariableAxis a({0.0, 1.0});
633  VariableAxis b({0.0, 0.5, 3.0});
634  VariableAxis c({0.0, 0.5, 3.0, 3.3});
636  std::make_tuple(std::move(a), std::move(b), std::move(c)));
637 
638  // test general properties
639  BOOST_CHECK_EQUAL(g.size(), 60u);
640  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 1u);
641  BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 2u);
642  BOOST_CHECK_EQUAL(g.numLocalBins().at(2), 3u);
643 
644  // test grid points
645  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 0}})), 26u);
646  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 0}})), 46u);
647  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0.5, 0}})), 31u);
648  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0.5, 0}})), 51u);
649  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 0}})), 36u);
650  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 0}})), 56u);
651  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 0.5}})), 27u);
652  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 0.5}})), 47u);
653  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0.5, 0.5}})), 32u);
654  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0.5, 0.5}})), 52u);
655  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 0.5}})), 37u);
656  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 0.5}})), 57u);
657  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 3}})), 28u);
658  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 3}})), 48u);
659  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0.5, 3}})), 33u);
660  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0.5, 3}})), 53u);
661  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 3}})), 38u);
662  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 3}})), 58u);
663  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0, 3.3}})), 29u);
664  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0, 3.3}})), 49u);
665  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0.5, 3.3}})), 34u);
666  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0.5, 3.3}})), 54u);
667  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3, 3.3}})), 39u);
668  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3, 3.3}})), 59u);
669 
670  // global bin index -> local bin indices
671  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0, 0, 0}}));
672  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{0, 0, 1}}));
673  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{0, 0, 2}}));
674  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{0, 0, 3}}));
675  BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices({{0, 0, 4}}));
676  BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices({{0, 1, 0}}));
677  BOOST_CHECK(g.localBinsFromGlobalBin(21) == indices({{1, 0, 1}}));
678  BOOST_CHECK(g.localBinsFromGlobalBin(22) == indices({{1, 0, 2}}));
679  BOOST_CHECK(g.localBinsFromGlobalBin(23) == indices({{1, 0, 3}}));
680  BOOST_CHECK(g.localBinsFromGlobalBin(24) == indices({{1, 0, 4}}));
681  BOOST_CHECK(g.localBinsFromGlobalBin(25) == indices({{1, 1, 0}}));
682  BOOST_CHECK(g.localBinsFromGlobalBin(26) == indices({{1, 1, 1}}));
683  BOOST_CHECK(g.localBinsFromGlobalBin(57) == indices({{2, 3, 2}}));
684  BOOST_CHECK(g.localBinsFromGlobalBin(58) == indices({{2, 3, 3}}));
685  BOOST_CHECK(g.localBinsFromGlobalBin(59) == indices({{2, 3, 4}}));
686 
687  // local bin indices -> global bin index
688  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0, 0}}), 0u);
689  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 0, 0}}), 20u);
690  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 0, 0}}), 40u);
691  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1, 0}}), 5u);
692  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1, 0}}), 25u);
693  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 1, 0}}), 45u);
694  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 3, 1}}), 16u);
695  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 3, 1}}), 36u);
696  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3, 1}}), 56u);
697  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0, 2}}), 2u);
698  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 0, 2}}), 22u);
699  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 0, 2}}), 42u);
700  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 3, 4}}), 19u);
701  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 3, 4}}), 39u);
702  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3, 4}}), 59u);
703 
704  BOOST_CHECK(g.localBinsFromGlobalBin(g.globalBinFromPosition(
705  Point({{1.8, 0.7, 3.2}}))) == indices({{2, 2, 3}}));
706 
707  // inside checks
708  BOOST_CHECK(not g.isInside(Point({{-2., -1, -2}})));
709  BOOST_CHECK(not g.isInside(Point({{-2., 1., 0.}})));
710  BOOST_CHECK(not g.isInside(Point({{-2., 5., -1}})));
711  BOOST_CHECK(not g.isInside(Point({{1., -1., 1.}})));
712  BOOST_CHECK(not g.isInside(Point({{6., -1., 4.}})));
713  BOOST_CHECK(g.isInside(Point({{0.5, 1.3, 1.7}})));
714  BOOST_CHECK(not g.isInside(Point({{1., -1., -0.4}})));
715  BOOST_CHECK(not g.isInside(Point({{1., 0.3, 3.4}})));
716  BOOST_CHECK(not g.isInside(Point({{1., 3., 0.8}})));
717  BOOST_CHECK(not g.isInside(Point({{-1., 3., 5.}})));
718  BOOST_CHECK(not g.isInside(Point({{2., 3., -1.}})));
719  BOOST_CHECK(not g.isInside(Point({{5., 3., 0.5}})));
720 
721  // test some bin centers
722  CHECK_CLOSE_ABS(g.binCenter({{1, 1, 1}}), Point({{0.5, 0.25, 0.25}}), 1e-6);
723  CHECK_CLOSE_ABS(g.binCenter({{1, 1, 2}}), Point({{0.5, 0.25, 1.75}}), 1e-6);
724  CHECK_CLOSE_ABS(g.binCenter({{1, 1, 3}}), Point({{0.5, 0.25, 3.15}}), 1e-6);
725  CHECK_CLOSE_ABS(g.binCenter({{1, 2, 1}}), Point({{0.5, 1.75, 0.25}}), 1e-6);
726  CHECK_CLOSE_ABS(g.binCenter({{1, 2, 2}}), Point({{0.5, 1.75, 1.75}}), 1e-6);
727  CHECK_CLOSE_ABS(g.binCenter({{1, 2, 3}}), Point({{0.5, 1.75, 3.15}}), 1e-6);
728 
729  // test some lower-left bin edges
730  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1, 1}}), Point({{0., 0., 0.}}), 1e-6);
731  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1, 2}}), Point({{0., 0., 0.5}}),
732  1e-6);
733  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1, 3}}), Point({{0., 0., 3.}}), 1e-6);
734  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 2, 1}}), Point({{0., 0.5, 0.}}),
735  1e-6);
736  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 2, 2}}), Point({{0., 0.5, 0.5}}),
737  1e-6);
738  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 2, 3}}), Point({{0., 0.5, 3.}}),
739  1e-6);
740 
741  // test some upper right-bin edges
742  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1, 1}}), Point({{1., 0.5, 0.5}}),
743  1e-6);
744  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1, 2}}), Point({{1., 0.5, 3.}}),
745  1e-6);
746  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1, 3}}), Point({{1., 0.5, 3.3}}),
747  1e-6);
748  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 2, 1}}), Point({{1., 3., 0.5}}),
749  1e-6);
750  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 2, 2}}), Point({{1., 3., 3.}}),
751  1e-6);
752  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 2, 3}}), Point({{1., 3., 3.3}}),
753  1e-6);
754 
755  // initialize grid
756  for (size_t bin = 0; bin < g.size(); ++bin) {
757  g.at(bin) = bin;
758  }
759 
760  // consistency of access
761  const auto& point = Point({{0.7, 1.3, 3.7}});
762  size_t globalBin = g.globalBinFromPosition(point);
763  indices localBins = g.localBinsFromGlobalBin(globalBin);
764 
765  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
766  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
767 }
768 
769 BOOST_AUTO_TEST_CASE(grid_test_2d_mixed) {
770  using Point = std::array<double, 2>;
771  using indices = std::array<size_t, 2>;
772  EquidistantAxis a(0.0, 1.0, 4u);
773  VariableAxis b({0.0, 0.5, 3.0});
775  std::make_tuple(std::move(a), std::move(b)));
776 
777  // test general properties
778  BOOST_CHECK_EQUAL(g.size(), 24u);
779  BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 4u);
780  BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 2u);
781 
782  // test grid points
783  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0}})), 5u);
784  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.25, 0}})), 9u);
785  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.5, 0}})), 13u);
786  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.75, 0}})), 17u);
787  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0}})), 21u);
788  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 0.5}})), 6u);
789  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.25, 0.5}})), 10u);
790  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.5, 0.5}})), 14u);
791  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.75, 0.5}})), 18u);
792  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 0.5}})), 22u);
793  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0, 3}})), 7u);
794  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.25, 3}})), 11u);
795  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.5, 3}})), 15u);
796  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.75, 3}})), 19u);
797  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1, 3}})), 23u);
798 
799  // test some arbitrary points
800  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{1.2, 0.3}})), 21u);
801  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.2, 1.3}})), 6u);
802  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.9, 1.8}})), 18u);
803  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.7, 2.1}})), 14u);
804  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.4, 0.3}})), 9u);
805  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-3, 2}})), 2u);
806  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{8, 1}})), 22u);
807  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.1, -3}})), 4u);
808  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{0.8, 11}})), 19u);
809  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-2, -3}})), 0u);
810  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{-2, 7}})), 3u);
811  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{12, -1}})), 20u);
812  BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point({{12, 11}})), 23u);
813 
814  // global bin index -> local bin indices
815  using indices = std::array<size_t, 2>;
816  BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices({{0, 0}}));
817  BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices({{0, 1}}));
818  BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices({{0, 2}}));
819  BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices({{0, 3}}));
820  BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices({{1, 0}}));
821  BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices({{1, 1}}));
822  BOOST_CHECK(g.localBinsFromGlobalBin(6) == indices({{1, 2}}));
823  BOOST_CHECK(g.localBinsFromGlobalBin(7) == indices({{1, 3}}));
824  BOOST_CHECK(g.localBinsFromGlobalBin(8) == indices({{2, 0}}));
825  BOOST_CHECK(g.localBinsFromGlobalBin(9) == indices({{2, 1}}));
826  BOOST_CHECK(g.localBinsFromGlobalBin(10) == indices({{2, 2}}));
827  BOOST_CHECK(g.localBinsFromGlobalBin(11) == indices({{2, 3}}));
828  BOOST_CHECK(g.localBinsFromGlobalBin(12) == indices({{3, 0}}));
829  BOOST_CHECK(g.localBinsFromGlobalBin(13) == indices({{3, 1}}));
830  BOOST_CHECK(g.localBinsFromGlobalBin(14) == indices({{3, 2}}));
831  BOOST_CHECK(g.localBinsFromGlobalBin(15) == indices({{3, 3}}));
832  BOOST_CHECK(g.localBinsFromGlobalBin(16) == indices({{4, 0}}));
833  BOOST_CHECK(g.localBinsFromGlobalBin(17) == indices({{4, 1}}));
834  BOOST_CHECK(g.localBinsFromGlobalBin(18) == indices({{4, 2}}));
835  BOOST_CHECK(g.localBinsFromGlobalBin(19) == indices({{4, 3}}));
836  BOOST_CHECK(g.localBinsFromGlobalBin(20) == indices({{5, 0}}));
837  BOOST_CHECK(g.localBinsFromGlobalBin(21) == indices({{5, 1}}));
838  BOOST_CHECK(g.localBinsFromGlobalBin(22) == indices({{5, 2}}));
839  BOOST_CHECK(g.localBinsFromGlobalBin(23) == indices({{5, 3}}));
840 
841  // local bin indices -> global bin index
842  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 0}}), 0u);
843  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 1}}), 1u);
844  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 2}}), 2u);
845  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{0, 3}}), 3u);
846  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 0}}), 4u);
847  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 1}}), 5u);
848  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 2}}), 6u);
849  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{1, 3}}), 7u);
850  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 0}}), 8u);
851  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 1}}), 9u);
852  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 2}}), 10u);
853  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{2, 3}}), 11u);
854  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 0}}), 12u);
855  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 1}}), 13u);
856  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 2}}), 14u);
857  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{3, 3}}), 15u);
858  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 0}}), 16u);
859  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 1}}), 17u);
860  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 2}}), 18u);
861  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{4, 3}}), 19u);
862  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 0}}), 20u);
863  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 1}}), 21u);
864  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 2}}), 22u);
865  BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({{5, 3}}), 23u);
866 
867  BOOST_CHECK(g.localBinsFromGlobalBin(g.globalBinFromPosition(
868  Point({{1.1, 1.7}}))) == indices({{5, 2}}));
869 
870  // inside checks
871  BOOST_CHECK(not g.isInside(Point({{-2., -1}})));
872  BOOST_CHECK(not g.isInside(Point({{-2., 1.}})));
873  BOOST_CHECK(not g.isInside(Point({{-2., 5.}})));
874  BOOST_CHECK(not g.isInside(Point({{0.1, -1.}})));
875  BOOST_CHECK(not g.isInside(Point({{6., -1.}})));
876  BOOST_CHECK(g.isInside(Point({{0.5, 1.3}})));
877  BOOST_CHECK(not g.isInside(Point({{1., -1.}})));
878  BOOST_CHECK(not g.isInside(Point({{1., 0.3}})));
879  BOOST_CHECK(not g.isInside(Point({{1., 3.}})));
880  BOOST_CHECK(not g.isInside(Point({{-1., 3.}})));
881  BOOST_CHECK(not g.isInside(Point({{0.2, 3.}})));
882  BOOST_CHECK(not g.isInside(Point({{5., 3.}})));
883 
884  // test some bin centers
885  CHECK_CLOSE_ABS(g.binCenter({{1, 1}}), Point({{0.125, 0.25}}), 1e-6);
886  CHECK_CLOSE_ABS(g.binCenter({{1, 2}}), Point({{0.125, 1.75}}), 1e-6);
887  CHECK_CLOSE_ABS(g.binCenter({{2, 1}}), Point({{0.375, 0.25}}), 1e-6);
888  CHECK_CLOSE_ABS(g.binCenter({{2, 2}}), Point({{0.375, 1.75}}), 1e-6);
889  CHECK_CLOSE_ABS(g.binCenter({{3, 1}}), Point({{0.625, 0.25}}), 1e-6);
890  CHECK_CLOSE_ABS(g.binCenter({{3, 2}}), Point({{0.625, 1.75}}), 1e-6);
891  CHECK_CLOSE_ABS(g.binCenter({{4, 1}}), Point({{0.875, 0.25}}), 1e-6);
892  CHECK_CLOSE_ABS(g.binCenter({{4, 2}}), Point({{0.875, 1.75}}), 1e-6);
893 
894  // test some lower-left bin edges
895  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 1}}), Point({{0., 0.}}), 1e-6);
896  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{1, 2}}), Point({{0., 0.5}}), 1e-6);
897  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 1}}), Point({{0.25, 0.}}), 1e-6);
898  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{2, 2}}), Point({{0.25, 0.5}}), 1e-6);
899  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{3, 1}}), Point({{0.5, 0.}}), 1e-6);
900  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{3, 2}}), Point({{0.5, 0.5}}), 1e-6);
901  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{4, 1}}), Point({{0.75, 0.}}), 1e-6);
902  CHECK_CLOSE_ABS(g.lowerLeftBinEdge({{4, 2}}), Point({{0.75, 0.5}}), 1e-6);
903 
904  // test some upper-right bin edges
905  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 1}}), Point({{0.25, 0.5}}), 1e-6);
906  CHECK_CLOSE_ABS(g.upperRightBinEdge({{1, 2}}), Point({{0.25, 3.}}), 1e-6);
907  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 1}}), Point({{0.5, 0.5}}), 1e-6);
908  CHECK_CLOSE_ABS(g.upperRightBinEdge({{2, 2}}), Point({{0.5, 3.}}), 1e-6);
909  CHECK_CLOSE_ABS(g.upperRightBinEdge({{3, 1}}), Point({{0.75, 0.5}}), 1e-6);
910  CHECK_CLOSE_ABS(g.upperRightBinEdge({{3, 2}}), Point({{0.75, 3.}}), 1e-6);
911  CHECK_CLOSE_ABS(g.upperRightBinEdge({{4, 1}}), Point({{1., 0.5}}), 1e-6);
912  CHECK_CLOSE_ABS(g.upperRightBinEdge({{4, 2}}), Point({{1., 3.}}), 1e-6);
913 
914  // initialize grid
915  for (size_t bin = 0; bin < g.size(); ++bin) {
916  g.at(bin) = bin;
917  }
918 
919  // consistency of access
920  const auto& point = Point({{1.3, 3.7}});
921  size_t globalBin = g.globalBinFromPosition(point);
922  indices localBins = g.localBinsFromGlobalBin(globalBin);
923 
924  BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
925  BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
926 }
927 
928 BOOST_AUTO_TEST_CASE(grid_test_2d_mixed_at) {
929  EquidistantAxis a(0.0, 6.0, 4u);
930  VariableAxis b({0.0, 1.5, 3.0});
932  std::make_tuple(std::move(a), std::move(b)));
933 
934  // initialize the grid
935  using Point = std::array<double, 2>;
936  g.atPosition(Point({{0, 0}})) = 0.;
937  g.atPosition(Point({{1.5, 0}})) = 1.;
938  g.atPosition(Point({{3, 0}})) = 2.;
939  g.atPosition(Point({{4.5, 0}})) = 3.;
940  g.atPosition(Point({{6, 0}})) = 4.;
941  g.atPosition(Point({{0, 1.5}})) = 5.;
942  g.atPosition(Point({{1.5, 1.5}})) = 6.;
943  g.atPosition(Point({{3, 1.5}})) = 7.;
944  g.atPosition(Point({{4.5, 1.5}})) = 8.;
945  g.atPosition(Point({{6, 1.5}})) = 9.;
946  g.atPosition(Point({{0, 3}})) = 10.;
947  g.atPosition(Point({{1.5, 3}})) = 11.;
948  g.atPosition(Point({{3, 3}})) = 12.;
949  g.atPosition(Point({{4.5, 3}})) = 13.;
950  g.atPosition(Point({{6, 3}})) = 14.;
951 
952  // test general properties
953  BOOST_CHECK_EQUAL(g.size(), 24u);
954 
955  // test some arbitrary points
956  BOOST_CHECK_EQUAL(g.atPosition(Point({{1.2, 0.3}})), 0.);
957  BOOST_CHECK_EQUAL(g.atPosition(Point({{2.2, 1.3}})), 1.);
958  BOOST_CHECK_EQUAL(g.atPosition(Point({{4.9, 1.8}})), 8.);
959  BOOST_CHECK_EQUAL(g.atPosition(Point({{3.7, 2.1}})), 7.);
960  BOOST_CHECK_EQUAL(g.atPosition(Point({{0.4, 2.3}})), 5.);
961 }
962 
963 BOOST_AUTO_TEST_CASE(grid_interpolation) {
964  using Point = std::array<double, 3>;
965  EquidistantAxis a(1.0, 3.0, 2u);
966  EquidistantAxis b(1.0, 5.0, 2u);
967  EquidistantAxis c(1.0, 7.0, 2u);
969  std::make_tuple(std::move(a), std::move(b), std::move(c)));
970 
971  g.atPosition(Point({{1., 1., 1.}})) = 10.;
972  g.atPosition(Point({{2., 1., 1.}})) = 20.;
973  g.atPosition(Point({{1., 3., 1.}})) = 30.;
974  g.atPosition(Point({{2., 3., 1.}})) = 40.;
975  g.atPosition(Point({{1., 1., 4.}})) = 50.;
976  g.atPosition(Point({{2., 1., 4.}})) = 60.;
977  g.atPosition(Point({{1., 3., 4.}})) = 70.;
978  g.atPosition(Point({{2., 3., 4.}})) = 80.;
979 
980  CHECK_CLOSE_REL(g.interpolate(Point({{1., 1., 1.}})), 10., 1e-6);
981  CHECK_CLOSE_REL(g.interpolate(Point({{2., 1., 1.}})), 20., 1e-6);
982  CHECK_CLOSE_REL(g.interpolate(Point({{1., 3., 1.}})), 30., 1e-6);
983  CHECK_CLOSE_REL(g.interpolate(Point({{2., 3., 1.}})), 40., 1e-6);
984  CHECK_CLOSE_REL(g.interpolate(Point({{1., 1., 4.}})), 50., 1e-6);
985  CHECK_CLOSE_REL(g.interpolate(Point({{2., 1., 4.}})), 60., 1e-6);
986  CHECK_CLOSE_REL(g.interpolate(Point({{1., 3., 4.}})), 70., 1e-6);
987  CHECK_CLOSE_REL(g.interpolate(Point({{2., 3., 4.}})), 80., 1e-6);
988  CHECK_CLOSE_REL(g.interpolate(Point({{1.5, 1., 1.}})), 15., 1e-6);
989  CHECK_CLOSE_REL(g.interpolate(Point({{1.5, 3., 1.}})), 35., 1e-6);
990  CHECK_CLOSE_REL(g.interpolate(Point({{1., 2., 1.}})), 20., 1e-6);
991  CHECK_CLOSE_REL(g.interpolate(Point({{2., 2., 1.}})), 30., 1e-6);
992  CHECK_CLOSE_REL(g.interpolate(Point({{1.5, 1., 4.}})), 55., 1e-6);
993  CHECK_CLOSE_REL(g.interpolate(Point({{1.5, 3., 4.}})), 75., 1e-6);
994  CHECK_CLOSE_REL(g.interpolate(Point({{1., 2., 4.}})), 60., 1e-6);
995  CHECK_CLOSE_REL(g.interpolate(Point({{2., 2., 4.}})), 70., 1e-6);
996  CHECK_CLOSE_REL(g.interpolate(Point({{1., 1., 2.5}})), 30., 1e-6);
997  CHECK_CLOSE_REL(g.interpolate(Point({{1., 3., 2.5}})), 50., 1e-6);
998  CHECK_CLOSE_REL(g.interpolate(Point({{2., 1., 2.5}})), 40., 1e-6);
999  CHECK_CLOSE_REL(g.interpolate(Point({{2., 3., 2.5}})), 60., 1e-6);
1000  CHECK_CLOSE_REL(g.interpolate(Point({{1.5, 2., 2.5}})), 360. / 8, 1e-6);
1001  CHECK_CLOSE_REL(g.interpolate(Point({{1.3, 2.1, 1.6}})), 32., 1e-6);
1002  CHECK_CLOSE_REL(g.interpolate(Point({{2., 3., 4.}})), 80., 1e-6);
1003 }
1004 
1005 BOOST_AUTO_TEST_CASE(neighborhood) {
1006  using bins_t = std::vector<size_t>;
1007  using EAxis = EquidistantAxis;
1008  using Grid1_t = Grid<double, EAxis>;
1009  using Grid2_t = Grid<double, EAxis, EAxis>;
1010  using Grid3_t = Grid<double, EAxis, EAxis, EAxis>;
1011 
1012  EAxis a(0.0, 1.0, 10u);
1013  EAxis b(0.0, 1.0, 10u);
1014  EAxis c(0.0, 1.0, 10u);
1015  Grid1_t g1(std::make_tuple(a));
1016  Grid2_t g2(std::make_tuple(a, b));
1017  Grid3_t g3(std::make_tuple(std::move(a), std::move(b), std::move(c)));
1018 
1019  // clang-format off
1020  // 1D case
1021  BOOST_CHECK(g1.neighborHoodIndices({{0}}, 1).collect()
1022  == bins_t({0, 1}));
1023  BOOST_CHECK(g1.neighborHoodIndices({{0}}, 2).collect()
1024  == bins_t({0, 1, 2}));
1025  BOOST_CHECK(g1.neighborHoodIndices({{1}}, 1).collect()
1026  == bins_t({0, 1, 2}));
1027  BOOST_CHECK(g1.neighborHoodIndices({{1}}, 3).collect()
1028  == bins_t({0, 1, 2, 3, 4}));
1029  BOOST_CHECK(g1.neighborHoodIndices({{4}}, 2).collect()
1030  == bins_t({2, 3, 4, 5, 6}));
1031  BOOST_CHECK(g1.neighborHoodIndices({{9}}, 2).collect()
1032  == bins_t({7, 8, 9, 10, 11}));
1033  BOOST_CHECK(g1.neighborHoodIndices({{10}}, 2).collect()
1034  == bins_t({8, 9, 10, 11}));
1035  BOOST_CHECK(g1.neighborHoodIndices({{11}}, 2).collect()
1036  == bins_t({9, 10, 11}));
1037 
1038  // 2D case
1039  BOOST_CHECK(g2.neighborHoodIndices({{0, 0}}, 1).collect()
1040  == bins_t({0, 1, 12, 13}));
1041  BOOST_CHECK(g2.neighborHoodIndices({{0, 1}}, 1).collect()
1042  == bins_t({0, 1, 2, 12, 13, 14}));
1043  BOOST_CHECK(g2.neighborHoodIndices({{1, 0}}, 1).collect()
1044  == bins_t({0, 1, 12, 13, 24, 25}));
1045  BOOST_CHECK(g2.neighborHoodIndices({{1, 1}}, 1).collect()
1046  == bins_t({0, 1, 2, 12, 13, 14, 24, 25, 26}));
1047  BOOST_CHECK(g2.neighborHoodIndices({{5, 5}}, 1).collect()
1048  == bins_t({52, 53, 54, 64, 65, 66, 76, 77, 78}));
1049  BOOST_CHECK(g2.neighborHoodIndices({{9, 10}}, 2).collect()
1050  == bins_t({92, 93, 94, 95, 104, 105, 106, 107, 116, 117, 118,
1051  119, 128, 129, 130, 131, 140, 141, 142, 143}));
1052 
1053  // 3D case
1054  BOOST_CHECK(g3.neighborHoodIndices({{0, 0, 0}}, 1).collect()
1055  == bins_t({0, 1, 12, 13, 144, 145, 156, 157}));
1056  BOOST_CHECK(g3.neighborHoodIndices({{0, 0, 1}}, 1).collect()
1057  == bins_t({0, 1, 2, 12, 13, 14, 144, 145, 146, 156, 157, 158}));
1058  BOOST_CHECK(g3.neighborHoodIndices({{0, 1, 0}}, 1).collect()
1059  == bins_t({0, 1, 12, 13, 24, 25, 144, 145, 156, 157, 168, 169}));
1060  BOOST_CHECK(g3.neighborHoodIndices({{1, 0, 0}}, 1).collect()
1061  == bins_t({0, 1, 12, 13, 144, 145, 156, 157, 288, 289, 300, 301}));
1062  BOOST_CHECK(g3.neighborHoodIndices({{0, 1, 1}}, 1).collect()
1063  == bins_t({0, 1, 2, 12, 13, 14, 24, 25, 26, 144, 145, 146,
1064  156, 157, 158, 168, 169, 170}));
1065  BOOST_CHECK(g3.neighborHoodIndices({{1, 1, 1}}, 1).collect()
1066  == bins_t({0, 1, 2, 12, 13, 14, 24, 25, 26, 144, 145, 146,
1067  156, 157, 158, 168, 169, 170, 288, 289, 290, 300,
1068  301, 302, 312, 313, 314}));
1069  BOOST_CHECK(g3.neighborHoodIndices({{11, 10, 9}}, 1).collect()
1070  == bins_t({1556, 1557, 1558, 1568, 1569, 1570, 1580, 1581,
1071  1582, 1700, 1701, 1702, 1712, 1713, 1714, 1724,
1072  1725, 1726}));
1073  // clang-format on
1074 
1076  using Grid1Closed_t = Grid<double, EAxisClosed>;
1077  EAxisClosed d(0.0, 1.0, 10u);
1078 
1079  Grid1Closed_t g1Cl(std::make_tuple(std::move(d)));
1080  BOOST_CHECK(g1Cl.neighborHoodIndices({{0}}, 1).collect() ==
1081  bins_t({})); // underflow, makes no sense
1082  BOOST_CHECK(g1Cl.neighborHoodIndices({{11}}, 1).collect() ==
1083  bins_t({})); // overflow, makes no sense
1084  BOOST_CHECK(g1Cl.neighborHoodIndices({{1}}, 1).collect() ==
1085  bins_t({10, 1, 2})); // overflow, makes no sense
1086  BOOST_CHECK(g1Cl.neighborHoodIndices({{5}}, 1).collect() ==
1087  bins_t({4, 5, 6})); // overflow, makes no sense
1088 
1089  using Grid2Closed_t = Grid<double, EAxisClosed, EAxisClosed>;
1090  // typedef Grid<double, EAxisClosed, EAxisClosed, EAxisClosed>
1091  // Grid3Closed_t;
1092  EAxisClosed e(0.0, 1.0, 5u);
1093  EAxisClosed f(0.0, 1.0, 5u);
1094  EAxisClosed g(0.0, 1.0, 5u);
1095  Grid2Closed_t g2Cl(std::make_tuple(std::move(e), std::move(f)));
1096  BOOST_CHECK(g2Cl.neighborHoodIndices({{3, 3}}, 1).collect() ==
1097  bins_t({16, 17, 18, 23, 24, 25, 30, 31, 32}));
1098  BOOST_CHECK(g2Cl.neighborHoodIndices({{1, 1}}, 1).collect() ==
1099  bins_t({40, 36, 37, 12, 8, 9, 19, 15, 16}));
1100  BOOST_CHECK(g2Cl.neighborHoodIndices({{1, 5}}, 1).collect() ==
1101  bins_t({39, 40, 36, 11, 12, 8, 18, 19, 15}));
1102  BOOST_CHECK(g2Cl.neighborHoodIndices({{5, 1}}, 1).collect() ==
1103  bins_t({33, 29, 30, 40, 36, 37, 12, 8, 9}));
1104  BOOST_CHECK(g2Cl.neighborHoodIndices({{5, 5}}, 1).collect() ==
1105  bins_t({32, 33, 29, 39, 40, 36, 11, 12, 8}));
1106 
1107  BOOST_CHECK(g2Cl.neighborHoodIndices({{3, 3}}, 2).collect() ==
1108  bins_t({8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 22, 23, 24,
1109  25, 26, 29, 30, 31, 32, 33, 36, 37, 38, 39, 40}));
1110  BOOST_CHECK(g2Cl.neighborHoodIndices({{1, 1}}, 2).collect() ==
1111  bins_t({32, 33, 29, 30, 31, 39, 40, 36, 37, 38, 11, 12, 8,
1112  9, 10, 18, 19, 15, 16, 17, 25, 26, 22, 23, 24}));
1113  BOOST_CHECK(g2Cl.neighborHoodIndices({{1, 5}}, 2).collect() ==
1114  bins_t({31, 32, 33, 29, 30, 38, 39, 40, 36, 37, 10, 11, 12,
1115  8, 9, 17, 18, 19, 15, 16, 24, 25, 26, 22, 23}));
1116  BOOST_CHECK(g2Cl.neighborHoodIndices({{5, 1}}, 2).collect() ==
1117  bins_t({25, 26, 22, 23, 24, 32, 33, 29, 30, 31, 39, 40, 36,
1118  37, 38, 11, 12, 8, 9, 10, 18, 19, 15, 16, 17}));
1119  BOOST_CHECK(g2Cl.neighborHoodIndices({{5, 5}}, 2).collect() ==
1120  bins_t({24, 25, 26, 22, 23, 31, 32, 33, 29, 30, 38, 39, 40,
1121  36, 37, 10, 11, 12, 8, 9, 17, 18, 19, 15, 16}));
1122 
1123  // @TODO 3D test would be nice, but should essentially not be a problem if
1124  // 2D works.
1125 
1126  // clang-format off
1127  /*
1128  * 1 2 3 4 5
1129  * |------------------------|
1130  * 1 | 8 | 9 | 10 | 11 | 12 |
1131  * |----|----|----|----|----|
1132  * 2 | 15 | 16 | 17 | 18 | 19 |
1133  * |----|----|----|----|----|
1134  * 3 | 22 | 23 | 24 | 25 | 26 |
1135  * |----|----|----|----|----|
1136  * 4 | 29 | 30 | 31 | 32 | 33 |
1137  * |----|----|----|----|----|
1138  * 5 | 36 | 37 | 38 | 39 | 40 |
1139  * |------------------------|
1140  */
1141  // clang-format on
1142 }
1143 
1144 BOOST_AUTO_TEST_CASE(closestPoints) {
1145  using Point = std::array<double, 3>;
1146  using bins_t = std::vector<size_t>;
1147  using EAxis = EquidistantAxis;
1148  using Grid1_t = Grid<double, EAxis>;
1149  using Grid2_t = Grid<double, EAxis, EAxis>;
1150  using Grid3_t = Grid<double, EAxis, EAxis, EAxis>;
1151 
1152  EAxis a(0.0, 1.0, 10u);
1153  EAxis b(0.0, 1.0, 5u);
1154  EAxis c(0.0, 1.0, 3u);
1155  Grid1_t g1(std::make_tuple(a));
1156  Grid2_t g2(std::make_tuple(a, b));
1157  Grid3_t g3(std::make_tuple(std::move(a), std::move(b), std::move(c)));
1158 
1159  // clang-format off
1160  // 1D case
1161  BOOST_CHECK(g1.closestPointsIndices(Point({{0.52}})).collect()
1162  == bins_t({6, 7}));
1163  BOOST_CHECK(g1.closestPointsIndices(Point({{0.98}})).collect()
1164  == bins_t({10, 11}));
1165 
1166  // 2D case
1167  BOOST_CHECK(g2.closestPointsIndices(Point({{0.52, 0.08}})).collect()
1168  == bins_t({43, 44, 50, 51}));
1169  BOOST_CHECK(g2.closestPointsIndices(Point({{0.05, 0.08}})).collect()
1170  == bins_t({8, 9, 15, 16}));
1171 
1172  // 3D case
1173  BOOST_CHECK(g3.closestPointsIndices(Point({{0.23, 0.13, 0.61}})).collect()
1174  == bins_t({112, 113, 117, 118, 147, 148, 152, 153}));
1175  BOOST_CHECK(g3.closestPointsIndices(Point({{0.52, 0.35, 0.71}})).collect()
1176  == bins_t({223, 224, 228, 229, 258, 259, 263, 264}));
1177 
1179  using Grid1Cl_t = Grid<double, EAxisClosed>;
1180  using Grid2Cl_t = Grid<double, EAxisClosed, EAxisClosed>;
1181  //using Grid3Cl_t = Grid<double, EAxisClosed, EAxisClosed, EAxisClosed>;
1182  EAxisClosed aCl(0.0, 1.0, 10u);
1183  EAxisClosed bCl(0.0, 1.0, 5u);
1184  EAxisClosed cCl(0.0, 1.0, 3u);
1185  Grid1Cl_t g1Cl(std::make_tuple(aCl));
1186  Grid2Cl_t g2Cl(std::make_tuple(std::move(aCl), std::move(bCl)));
1187 
1188  // 1D case
1189  BOOST_CHECK(g1Cl.closestPointsIndices(Point({{0.52}})).collect()
1190  == bins_t({6, 7}));
1191  BOOST_CHECK(g1Cl.closestPointsIndices(Point({{0.98}})).collect()
1192  == bins_t({10, 1}));
1193 
1194  // 2D case
1195  BOOST_CHECK(g2Cl.closestPointsIndices(Point({{0.52, 0.08}})).collect()
1196  == bins_t({43, 44, 50, 51}));
1197  BOOST_CHECK(g2Cl.closestPointsIndices(Point({{0.52, 0.68}})).collect()
1198  == bins_t({46, 47, 53, 54}));
1199  BOOST_CHECK(g2Cl.closestPointsIndices(Point({{0.52, 0.88}})).collect()
1200  == bins_t({47, 43, 54, 50}));
1201  BOOST_CHECK(g2Cl.closestPointsIndices(Point({{0.05, 0.08}})).collect()
1202  == bins_t({8, 9, 15, 16}));
1203  BOOST_CHECK(g2Cl.closestPointsIndices(Point({{0.9, 0.95}})).collect()
1204  == bins_t({75, 71, 12, 8}));
1205 
1206  // @TODO: 3D checks would also be nice
1207 
1209  using Grid1Op_t = Grid<double, EAxisOpen>;
1210  using Grid2Op_t = Grid<double, EAxisOpen, EAxisOpen>;
1211  //using Grid3Op_t = Grid<double, EAxisOpen, EAxisOpen, EAxisOpen>;
1212 
1213  EAxisOpen aOp(0.0, 1.0, 10u);
1214  EAxisOpen bOp(0.0, 1.0, 5u);
1215  EAxisOpen cOp(0.0, 1.0, 3u);
1216  Grid1Op_t g1Op(std::make_tuple(aOp));
1217  Grid2Op_t g2Op(std::make_tuple(std::move(aOp), std::move(bOp)));
1218 
1219  // 1D case
1220  BOOST_CHECK(g1Op.closestPointsIndices(Point({{0.52}})).collect()
1221  == bins_t({6, 7}));
1222  BOOST_CHECK(g1Op.closestPointsIndices(Point({{0.98}})).collect()
1223  == bins_t({10}));
1224  BOOST_CHECK(g1Op.closestPointsIndices(Point({{0.88}})).collect()
1225  == bins_t({9, 10}));
1226 
1227  // 2D case
1228  BOOST_CHECK(g2Op.closestPointsIndices(Point({{0.52, 0.08}})).collect()
1229  == bins_t({43, 44, 50, 51}));
1230  BOOST_CHECK(g2Op.closestPointsIndices(Point({{0.52, 0.68}})).collect()
1231  == bins_t({46, 47, 53, 54}));
1232  BOOST_CHECK(g2Op.closestPointsIndices(Point({{0.52, 0.88}})).collect()
1233  == bins_t({47, 54}));
1234  BOOST_CHECK(g2Op.closestPointsIndices(Point({{0.05, 0.1}})).collect()
1235  == bins_t({8, 9, 15, 16}));
1236  BOOST_CHECK(g2Op.closestPointsIndices(Point({{0.95, 0.95}})).collect()
1237  == bins_t({75}));
1238 
1239  // @TODO: 3D checks would also be nice
1240 
1241  /*
1242  * 1 2 3 4 5
1243  * |------------------------|
1244  * 1 | 8 | 9 | 10 | 11 | 12 |
1245  * |----|----|----|----|----|
1246  * 2 | 15 | 16 | 17 | 18 | 19 |
1247  * |----|----|----|----|----|
1248  * 3 | 22 | 23 | 24 | 25 | 26 |
1249  * |----|----|----|----|----|
1250  * 4 | 29 | 30 | 31 | 32 | 33 |
1251  * |----|----|----|----|----|
1252  * 5 | 36 | 37 | 38 | 39 | 40 |
1253  * |------------------------|
1254  * 6 | 43 | 44 | 45 | 46 | 47 |
1255  * |------------------------|
1256  * 7 | 50 | 51 | 52 | 53 | 54 |
1257  * |------------------------|
1258  * 8 | 57 | 58 | 59 | 60 | 61 |
1259  * |------------------------|
1260  * 9 | 64 | 65 | 66 | 67 | 68 |
1261  * |------------------------|
1262  * 10 | 71 | 72 | 73 | 74 | 75 |
1263  * |------------------------|
1264  * 77 78 79 80 81 82 83
1265  */
1266 
1267  // clang-format on
1268 }
1269 
1270 } // namespace Test
1271 
1272 } // namespace Acts