Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-22 08:25:32

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Utilities/Axis.hpp"
0012 #include "Acts/Utilities/AxisDefinitions.hpp"
0013 #include "Acts/Utilities/Grid.hpp"
0014 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0015 
0016 #include <array>
0017 #include <cstddef>
0018 #include <set>
0019 #include <tuple>
0020 #include <utility>
0021 #include <vector>
0022 
0023 using namespace Acts;
0024 using namespace Acts::detail;
0025 
0026 namespace ActsTests {
0027 
0028 BOOST_AUTO_TEST_SUITE(UtilitiesSuite)
0029 
0030 BOOST_AUTO_TEST_CASE(grid_test_1d_equidistant) {
0031   using Point = std::array<double, 1>;
0032   using indices = std::array<std::size_t, 1>;
0033 
0034   const Axis a(0.0, 4.0, 4u);
0035   Grid g(Type<double>, a);
0036 
0037   // test general properties
0038   BOOST_CHECK_EQUAL(g.size(), 6u);
0039   BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 4u);
0040 
0041   // global bin index
0042   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-0.3}), 0u);
0043   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-0.}), 1u);
0044   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.}), 1u);
0045   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.7}), 1u);
0046   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1}), 2u);
0047   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1.2}), 2u);
0048   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2.}), 3u);
0049   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2.7}), 3u);
0050   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3.}), 4u);
0051   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3.9999}), 4u);
0052   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{4.}), 5u);
0053   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{4.98}), 5u);
0054 
0055   // global bin index -> local bin indices
0056   BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices{0});
0057   BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices{1});
0058   BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices{2});
0059   BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices{3});
0060   BOOST_CHECK(g.localBinsFromGlobalBin(4) == indices{4});
0061   BOOST_CHECK(g.localBinsFromGlobalBin(5) == indices{5});
0062 
0063   // local bin indices -> global bin index
0064   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0}), 0u);
0065   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1}), 1u);
0066   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2}), 2u);
0067   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3}), 3u);
0068   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({4}), 4u);
0069   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({5}), 5u);
0070 
0071   BOOST_CHECK(g.localBinsFromGlobalBin(g.globalBinFromPosition(Point{2.7})) ==
0072               indices{3});
0073 
0074   // inside checks
0075   BOOST_CHECK(!g.isInside(Point{-2.}));
0076   BOOST_CHECK(g.isInside(Point{0.}));
0077   BOOST_CHECK(g.isInside(Point{2.5}));
0078   BOOST_CHECK(!g.isInside(Point{4.}));
0079   BOOST_CHECK(!g.isInside(Point{6.}));
0080 
0081   // test some bin centers
0082   CHECK_CLOSE_ABS(g.binCenter({1}), Point{0.5}, 1e-6);
0083   CHECK_CLOSE_ABS(g.binCenter({2}), Point{1.5}, 1e-6);
0084   CHECK_CLOSE_ABS(g.binCenter({3}), Point{2.5}, 1e-6);
0085   CHECK_CLOSE_ABS(g.binCenter({4}), Point{3.5}, 1e-6);
0086 
0087   // test some lower-left bin edges
0088   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1}), Point{0.}, 1e-6);
0089   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({2}), Point{1.}, 1e-6);
0090   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({3}), Point{2.}, 1e-6);
0091   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({4}), Point{3.}, 1e-6);
0092 
0093   // test some upper right-bin edges
0094   CHECK_CLOSE_ABS(g.upperRightBinEdge({1}), Point{1.}, 1e-6);
0095   CHECK_CLOSE_ABS(g.upperRightBinEdge({2}), Point{2.}, 1e-6);
0096   CHECK_CLOSE_ABS(g.upperRightBinEdge({3}), Point{3.}, 1e-6);
0097   CHECK_CLOSE_ABS(g.upperRightBinEdge({4}), Point{4.}, 1e-6);
0098 
0099   // initialize grid
0100   for (std::size_t bin = 0; bin < g.size(); ++bin) {
0101     g.at(bin) = bin;
0102   }
0103 
0104   // consistency of access
0105   const Point point{0.7};
0106   const std::size_t globalBin = g.globalBinFromPosition(point);
0107   const indices localBins = g.localBinsFromGlobalBin(globalBin);
0108 
0109   BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
0110   BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
0111 }
0112 
0113 BOOST_AUTO_TEST_CASE(grid_test_2d_equidistant) {
0114   using Point = std::array<double, 2>;
0115   using indices = std::array<std::size_t, 2>;
0116 
0117   const Axis a(0.0, 4.0, 4u);
0118   const Axis b(0.0, 3.0, 3u);
0119   Grid g(Type<double>, a, b);
0120 
0121   // test general properties
0122   BOOST_CHECK_EQUAL(g.size(), 30u);
0123   BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 4u);
0124   BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 3u);
0125 
0126   // global bin index
0127   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-1, -1}), 0u);
0128   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-1, 0}), 1u);
0129   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-1, 1}), 2u);
0130   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-1, 2}), 3u);
0131   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-1, 3}), 4u);
0132   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, -1}), 5u);
0133   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0}), 6u);
0134   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 1}), 7u);
0135   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 2}), 8u);
0136   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 3}), 9u);
0137   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, -1}), 10u);
0138   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0}), 11u);
0139   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 1}), 12u);
0140   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 2}), 13u);
0141   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 3}), 14u);
0142   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, -1}), 15u);
0143   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 0}), 16u);
0144   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 1}), 17u);
0145   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 2}), 18u);
0146   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 3}), 19u);
0147   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3, -1}), 20u);
0148   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3, 0}), 21u);
0149   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3, 1}), 22u);
0150   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3, 2}), 23u);
0151   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3, 3}), 24u);
0152   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{4, -1}), 25u);
0153   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{4, 0}), 26u);
0154   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{4, 1}), 27u);
0155   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{4, 2}), 28u);
0156   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{4, 3}), 29u);
0157 
0158   // test some arbitrary points
0159   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1.2, 0.3}), 11u);
0160   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2.2, 3.3}), 19u);
0161   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.9, 1.8}), 7u);
0162   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3.7, 3.1}), 24u);
0163   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1.4, 2.3}), 13u);
0164   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-3, 3}), 4u);
0165   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{8, 1}), 27u);
0166   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, -3}), 10u);
0167   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3, 11}), 24u);
0168   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-2, -3}), 0u);
0169   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-2, 7}), 04u);
0170   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{12, -1}), 25u);
0171   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{12, 11}), 29u);
0172 
0173   // global bin index -> local bin indices
0174   BOOST_CHECK((g.localBinsFromGlobalBin(0) == indices{0, 0}));
0175   BOOST_CHECK((g.localBinsFromGlobalBin(1) == indices{0, 1}));
0176   BOOST_CHECK((g.localBinsFromGlobalBin(2) == indices{0, 2}));
0177   BOOST_CHECK((g.localBinsFromGlobalBin(3) == indices{0, 3}));
0178   BOOST_CHECK((g.localBinsFromGlobalBin(4) == indices{0, 4}));
0179   BOOST_CHECK((g.localBinsFromGlobalBin(5) == indices{1, 0}));
0180   BOOST_CHECK((g.localBinsFromGlobalBin(6) == indices{1, 1}));
0181   BOOST_CHECK((g.localBinsFromGlobalBin(7) == indices{1, 2}));
0182   BOOST_CHECK((g.localBinsFromGlobalBin(8) == indices{1, 3}));
0183   BOOST_CHECK((g.localBinsFromGlobalBin(9) == indices{1, 4}));
0184   BOOST_CHECK((g.localBinsFromGlobalBin(10) == indices{2, 0}));
0185   BOOST_CHECK((g.localBinsFromGlobalBin(11) == indices{2, 1}));
0186   BOOST_CHECK((g.localBinsFromGlobalBin(12) == indices{2, 2}));
0187   BOOST_CHECK((g.localBinsFromGlobalBin(13) == indices{2, 3}));
0188   BOOST_CHECK((g.localBinsFromGlobalBin(14) == indices{2, 4}));
0189   BOOST_CHECK((g.localBinsFromGlobalBin(15) == indices{3, 0}));
0190   BOOST_CHECK((g.localBinsFromGlobalBin(16) == indices{3, 1}));
0191   BOOST_CHECK((g.localBinsFromGlobalBin(17) == indices{3, 2}));
0192   BOOST_CHECK((g.localBinsFromGlobalBin(18) == indices{3, 3}));
0193   BOOST_CHECK((g.localBinsFromGlobalBin(19) == indices{3, 4}));
0194   BOOST_CHECK((g.localBinsFromGlobalBin(20) == indices{4, 0}));
0195   BOOST_CHECK((g.localBinsFromGlobalBin(21) == indices{4, 1}));
0196   BOOST_CHECK((g.localBinsFromGlobalBin(22) == indices{4, 2}));
0197   BOOST_CHECK((g.localBinsFromGlobalBin(23) == indices{4, 3}));
0198   BOOST_CHECK((g.localBinsFromGlobalBin(24) == indices{4, 4}));
0199   BOOST_CHECK((g.localBinsFromGlobalBin(25) == indices{5, 0}));
0200   BOOST_CHECK((g.localBinsFromGlobalBin(26) == indices{5, 1}));
0201   BOOST_CHECK((g.localBinsFromGlobalBin(27) == indices{5, 2}));
0202   BOOST_CHECK((g.localBinsFromGlobalBin(28) == indices{5, 3}));
0203   BOOST_CHECK((g.localBinsFromGlobalBin(29) == indices{5, 4}));
0204 
0205   // local bin indices -> global bin index
0206   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 0}), 0u);
0207   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 1}), 1u);
0208   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 2}), 2u);
0209   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 3}), 3u);
0210   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 4}), 4u);
0211   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 0}), 5u);
0212   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 1}), 6u);
0213   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 2}), 7u);
0214   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 3}), 8u);
0215   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 4}), 9u);
0216   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 0}), 10u);
0217   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 1}), 11u);
0218   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 2}), 12u);
0219   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 3}), 13u);
0220   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 4}), 14u);
0221   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 0}), 15u);
0222   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 1}), 16u);
0223   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 2}), 17u);
0224   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 3}), 18u);
0225   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 4}), 19u);
0226   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({4, 0}), 20u);
0227   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({4, 1}), 21u);
0228   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({4, 2}), 22u);
0229   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({4, 3}), 23u);
0230   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({4, 4}), 24u);
0231   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({5, 0}), 25u);
0232   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({5, 1}), 26u);
0233   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({5, 2}), 27u);
0234   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({5, 3}), 28u);
0235   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({5, 4}), 29u);
0236 
0237   BOOST_CHECK((g.localBinsFromGlobalBin(
0238                    g.globalBinFromPosition(Point{1.2, 0.7})) == indices{2, 1}));
0239 
0240   // inside checks
0241   BOOST_CHECK(!g.isInside(Point{-2., -1}));
0242   BOOST_CHECK(!g.isInside(Point{-2., 1.}));
0243   BOOST_CHECK(!g.isInside(Point{-2., 5.}));
0244   BOOST_CHECK(!g.isInside(Point{1., -1.}));
0245   BOOST_CHECK(!g.isInside(Point{6., -1.}));
0246   BOOST_CHECK(g.isInside(Point{0.5, 1.3}));
0247   BOOST_CHECK(!g.isInside(Point{4., -1.}));
0248   BOOST_CHECK(!g.isInside(Point{4., 0.3}));
0249   BOOST_CHECK(!g.isInside(Point{4., 3.}));
0250   BOOST_CHECK(!g.isInside(Point{-1., 3.}));
0251   BOOST_CHECK(!g.isInside(Point{2., 3.}));
0252   BOOST_CHECK(!g.isInside(Point{5., 3.}));
0253 
0254   // test some bin centers
0255   CHECK_CLOSE_ABS(g.binCenter({1, 1}), (Point{0.5, 0.5}), 1e-6);
0256   CHECK_CLOSE_ABS(g.binCenter({2, 3}), (Point{1.5, 2.5}), 1e-6);
0257   CHECK_CLOSE_ABS(g.binCenter({3, 1}), (Point{2.5, 0.5}), 1e-6);
0258   CHECK_CLOSE_ABS(g.binCenter({4, 2}), (Point{3.5, 1.5}), 1e-6);
0259 
0260   // test some lower-left bin edges
0261   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 1}), (Point{0., 0.}), 1e-6);
0262   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({2, 3}), (Point{1., 2.}), 1e-6);
0263   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({3, 1}), (Point{2., 0.}), 1e-6);
0264   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({4, 2}), (Point{3., 1.}), 1e-6);
0265 
0266   // test some upper right-bin edges
0267   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 1}), (Point{1., 1.}), 1e-6);
0268   CHECK_CLOSE_ABS(g.upperRightBinEdge({2, 3}), (Point{2., 3.}), 1e-6);
0269   CHECK_CLOSE_ABS(g.upperRightBinEdge({3, 1}), (Point{3., 1.}), 1e-6);
0270   CHECK_CLOSE_ABS(g.upperRightBinEdge({4, 2}), (Point{4., 2.}), 1e-6);
0271 
0272   // initialize grid
0273   for (std::size_t bin = 0; bin < g.size(); ++bin) {
0274     g.at(bin) = bin;
0275   }
0276 
0277   // consistency of access
0278   const Point point{0.7, 1.3};
0279   const std::size_t globalBin = g.globalBinFromPosition(point);
0280   const indices localBins = g.localBinsFromGlobalBin(globalBin);
0281 
0282   BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
0283   BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
0284 }
0285 
0286 BOOST_AUTO_TEST_CASE(grid_test_3d_equidistant) {
0287   using Point = std::array<double, 3>;
0288   using indices = std::array<std::size_t, 3>;
0289 
0290   const Axis a(0.0, 2.0, 2u);
0291   const Axis b(0.0, 3.0, 3u);
0292   const Axis c(0.0, 2.0, 2u);
0293   Grid g(Type<double>, a, b, c);
0294 
0295   // test general properties
0296   BOOST_CHECK_EQUAL(g.size(), 80u);
0297   BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 2u);
0298   BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 3u);
0299   BOOST_CHECK_EQUAL(g.numLocalBins().at(2), 2u);
0300 
0301   // test grid points
0302   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0, 0}), 25u);
0303   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0, 1}), 26u);
0304   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0, 2}), 27u);
0305   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 1, 0}), 29u);
0306   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 1, 1}), 30u);
0307   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 1, 2}), 31u);
0308   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 2, 0}), 33u);
0309   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 2, 1}), 34u);
0310   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 2, 2}), 35u);
0311   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 3, 0}), 37u);
0312   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 3, 1}), 38u);
0313   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 3, 2}), 39u);
0314   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0, 0}), 45u);
0315   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0, 1}), 46u);
0316   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0, 2}), 47u);
0317   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 1, 0}), 49u);
0318   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 1, 1}), 50u);
0319   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 1, 2}), 51u);
0320   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 2, 0}), 53u);
0321   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 2, 1}), 54u);
0322   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 2, 2}), 55u);
0323   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 3, 0}), 57u);
0324   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 3, 1}), 58u);
0325   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 3, 2}), 59u);
0326   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 0, 0}), 65u);
0327   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 0, 1}), 66u);
0328   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 0, 2}), 67u);
0329   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 1, 0}), 69u);
0330   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 1, 1}), 70u);
0331   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 1, 2}), 71u);
0332   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 2, 0}), 73u);
0333   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 2, 1}), 74u);
0334   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 2, 2}), 75u);
0335   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 3, 0}), 77u);
0336   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 3, 1}), 78u);
0337   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, 3, 2}), 79u);
0338 
0339   // global bin index -> local bin indices
0340   BOOST_CHECK((g.localBinsFromGlobalBin(0) == indices{0, 0, 0}));
0341   BOOST_CHECK((g.localBinsFromGlobalBin(1) == indices{0, 0, 1}));
0342   BOOST_CHECK((g.localBinsFromGlobalBin(2) == indices{0, 0, 2}));
0343   BOOST_CHECK((g.localBinsFromGlobalBin(3) == indices{0, 0, 3}));
0344   BOOST_CHECK((g.localBinsFromGlobalBin(4) == indices{0, 1, 0}));
0345   BOOST_CHECK((g.localBinsFromGlobalBin(5) == indices{0, 1, 1}));
0346   BOOST_CHECK((g.localBinsFromGlobalBin(6) == indices{0, 1, 2}));
0347   BOOST_CHECK((g.localBinsFromGlobalBin(7) == indices{0, 1, 3}));
0348   BOOST_CHECK((g.localBinsFromGlobalBin(24) == indices{1, 1, 0}));
0349   BOOST_CHECK((g.localBinsFromGlobalBin(25) == indices{1, 1, 1}));
0350   BOOST_CHECK((g.localBinsFromGlobalBin(26) == indices{1, 1, 2}));
0351   BOOST_CHECK((g.localBinsFromGlobalBin(27) == indices{1, 1, 3}));
0352   BOOST_CHECK((g.localBinsFromGlobalBin(52) == indices{2, 3, 0}));
0353   BOOST_CHECK((g.localBinsFromGlobalBin(53) == indices{2, 3, 1}));
0354   BOOST_CHECK((g.localBinsFromGlobalBin(54) == indices{2, 3, 2}));
0355   BOOST_CHECK((g.localBinsFromGlobalBin(55) == indices{2, 3, 3}));
0356   BOOST_CHECK((g.localBinsFromGlobalBin(60) == indices{3, 0, 0}));
0357   BOOST_CHECK((g.localBinsFromGlobalBin(61) == indices{3, 0, 1}));
0358   BOOST_CHECK((g.localBinsFromGlobalBin(62) == indices{3, 0, 2}));
0359   BOOST_CHECK((g.localBinsFromGlobalBin(63) == indices{3, 0, 3}));
0360   BOOST_CHECK((g.localBinsFromGlobalBin(76) == indices{3, 4, 0}));
0361   BOOST_CHECK((g.localBinsFromGlobalBin(77) == indices{3, 4, 1}));
0362   BOOST_CHECK((g.localBinsFromGlobalBin(78) == indices{3, 4, 2}));
0363   BOOST_CHECK((g.localBinsFromGlobalBin(79) == indices{3, 4, 3}));
0364 
0365   // local bin indices -> global bin index
0366   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 0, 0}), 0u);
0367   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 0, 1}), 1u);
0368   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 0, 2}), 2u);
0369   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 0, 3}), 3u);
0370   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 1, 0}), 4u);
0371   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 1, 1}), 5u);
0372   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 1, 2}), 6u);
0373   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 1, 3}), 7u);
0374   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 1, 0}), 24u);
0375   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 1, 1}), 25u);
0376   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 1, 2}), 26u);
0377   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 1, 3}), 27u);
0378   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 3, 0}), 52u);
0379   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 3, 1}), 53u);
0380   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 3, 2}), 54u);
0381   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 3, 3}), 55u);
0382   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 0, 0}), 60u);
0383   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 0, 1}), 61u);
0384   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 0, 2}), 62u);
0385   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 0, 3}), 63u);
0386   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 4, 0}), 76u);
0387   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 4, 1}), 77u);
0388   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 4, 2}), 78u);
0389   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 4, 3}), 79u);
0390 
0391   BOOST_CHECK((g.localBinsFromGlobalBin(g.globalBinFromPosition(
0392                    Point{1.2, 0.7, 1.4})) == indices{2, 1, 2}));
0393 
0394   // inside checks
0395   BOOST_CHECK(!g.isInside(Point{-2., -1, -2}));
0396   BOOST_CHECK(!g.isInside(Point{-2., 1., 0.}));
0397   BOOST_CHECK(!g.isInside(Point{-2., 5., -1}));
0398   BOOST_CHECK(!g.isInside(Point{1., -1., 1.}));
0399   BOOST_CHECK(!g.isInside(Point{6., -1., 4.}));
0400   BOOST_CHECK(g.isInside(Point{0.5, 1.3, 1.7}));
0401   BOOST_CHECK(!g.isInside(Point{2., -1., -0.4}));
0402   BOOST_CHECK(!g.isInside(Point{2., 0.3, 3.4}));
0403   BOOST_CHECK(!g.isInside(Point{2., 3., 0.8}));
0404   BOOST_CHECK(!g.isInside(Point{-1., 3., 5.}));
0405   BOOST_CHECK(!g.isInside(Point{2., 3., -1.}));
0406   BOOST_CHECK(!g.isInside(Point{5., 3., 0.5}));
0407 
0408   // test some bin centers
0409   CHECK_CLOSE_ABS(g.binCenter({1, 1, 1}), Point({0.5, 0.5, 0.5}), 1e-6);
0410   CHECK_CLOSE_ABS(g.binCenter({2, 3, 2}), Point({1.5, 2.5, 1.5}), 1e-6);
0411   CHECK_CLOSE_ABS(g.binCenter({1, 1, 2}), Point({0.5, 0.5, 1.5}), 1e-6);
0412   CHECK_CLOSE_ABS(g.binCenter({2, 2, 1}), Point({1.5, 1.5, 0.5}), 1e-6);
0413 
0414   // test some lower-left bin edges
0415   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 1, 1}), Point({0., 0., 0.}), 1e-6);
0416   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({2, 3, 2}), Point({1., 2., 1.}), 1e-6);
0417   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 1, 2}), Point({0., 0., 1.}), 1e-6);
0418   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({2, 2, 1}), Point({1., 1., 0.}), 1e-6);
0419 
0420   // test some upper right-bin edges
0421   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 1, 1}), Point({1., 1., 1.}), 1e-6);
0422   CHECK_CLOSE_ABS(g.upperRightBinEdge({2, 3, 2}), Point({2., 3., 2.}), 1e-6);
0423   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 1, 2}), Point({1., 1., 2.}), 1e-6);
0424   CHECK_CLOSE_ABS(g.upperRightBinEdge({2, 2, 1}), Point({2., 2., 1.}), 1e-6);
0425 
0426   // initialize grid
0427   for (std::size_t bin = 0; bin < g.size(); ++bin) {
0428     g.at(bin) = bin;
0429   }
0430 
0431   // consistency of access
0432   const Point point{0.7, 2.3, 1.3};
0433   const std::size_t globalBin = g.globalBinFromPosition(point);
0434   const indices localBins = g.localBinsFromGlobalBin(globalBin);
0435 
0436   BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
0437   BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
0438 }
0439 
0440 BOOST_AUTO_TEST_CASE(grid_test_1d_variable) {
0441   using Point = std::array<double, 1>;
0442   using indices = std::array<std::size_t, 1>;
0443 
0444   const Axis a({0.0, 1.0, 4.0});
0445   Grid g(Type<double>, a);
0446 
0447   // test general properties
0448   BOOST_CHECK_EQUAL(g.size(), 4u);
0449   BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 2u);
0450 
0451   // global bin index
0452   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-0.3}), 0u);
0453   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.}), 1u);
0454   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.7}), 1u);
0455   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1}), 2u);
0456   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1.2}), 2u);
0457   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2.7}), 2u);
0458   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{4.}), 3u);
0459   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{4.98}), 3u);
0460 
0461   // global bin index -> local bin indices
0462   BOOST_CHECK(g.localBinsFromGlobalBin(0) == indices{0});
0463   BOOST_CHECK(g.localBinsFromGlobalBin(1) == indices{1});
0464   BOOST_CHECK(g.localBinsFromGlobalBin(2) == indices{2});
0465   BOOST_CHECK(g.localBinsFromGlobalBin(3) == indices{3});
0466 
0467   // local bin indices -> global bin index
0468   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0}), 0u);
0469   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1}), 1u);
0470   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2}), 2u);
0471   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3}), 3u);
0472 
0473   BOOST_CHECK(g.localBinsFromGlobalBin(g.globalBinFromPosition(Point{0.8})) ==
0474               indices{1});
0475 
0476   // inside checks
0477   BOOST_CHECK(!g.isInside(Point{-2.}));
0478   BOOST_CHECK(g.isInside(Point{0.}));
0479   BOOST_CHECK(g.isInside(Point{2.5}));
0480   BOOST_CHECK(!g.isInside(Point{4.}));
0481   BOOST_CHECK(!g.isInside(Point{6.}));
0482 
0483   // test some bin centers
0484   CHECK_CLOSE_ABS(g.binCenter({1}), Point{0.5}, 1e-6);
0485   CHECK_CLOSE_ABS(g.binCenter({2}), Point{2.5}, 1e-6);
0486 
0487   // test some lower-left bin edges
0488   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1}), Point{0.}, 1e-6);
0489   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({2}), Point{1.}, 1e-6);
0490 
0491   // test some upper right-bin edges
0492   CHECK_CLOSE_ABS(g.upperRightBinEdge({1}), Point{1.}, 1e-6);
0493   CHECK_CLOSE_ABS(g.upperRightBinEdge({2}), Point{4.}, 1e-6);
0494 
0495   // initialize grid
0496   for (std::size_t bin = 0; bin < g.size(); ++bin) {
0497     g.at(bin) = bin;
0498   }
0499 
0500   // consistency of access
0501   const Point point{0.7};
0502   const std::size_t globalBin = g.globalBinFromPosition(point);
0503   const indices localBins = g.localBinsFromGlobalBin(globalBin);
0504 
0505   BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
0506   BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
0507 }
0508 
0509 BOOST_AUTO_TEST_CASE(grid_test_2d_variable) {
0510   using Point = std::array<double, 2>;
0511   using indices = std::array<std::size_t, 2>;
0512 
0513   const Axis a({0.0, 0.5, 3.0});
0514   const Axis b({0.0, 1.0, 4.0});
0515   Grid g(Type<double>, a, b);
0516 
0517   // test general properties
0518   BOOST_CHECK_EQUAL(g.size(), 16u);
0519   BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 2u);
0520   BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 2u);
0521 
0522   // test grid points
0523   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0}), 5u);
0524   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 1}), 6u);
0525   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 4}), 7u);
0526   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.5, 0}), 9u);
0527   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.5, 1}), 10u);
0528   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.5, 4}), 11u);
0529   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3, 0}), 13u);
0530   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3, 1}), 14u);
0531   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3, 4}), 15u);
0532 
0533   // test some arbitrary points
0534   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.3, 1.2}), 6u);
0535   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3.3, 2.2}), 14u);
0536   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1.8, 0.9}), 9u);
0537   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{3.1, 0.7}), 13u);
0538   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2.3, 1.4}), 10u);
0539   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{2, -3}), 8u);
0540   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 8}), 11u);
0541   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-3, 1}), 2u);
0542   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{11, 3}), 14u);
0543   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-3, -2}), 0u);
0544   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{7, -2}), 12u);
0545   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-1, 12}), 3u);
0546   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{11, 12}), 15u);
0547 
0548   // global bin index -> local bin indices
0549   BOOST_CHECK((g.localBinsFromGlobalBin(0) == indices{0, 0}));
0550   BOOST_CHECK((g.localBinsFromGlobalBin(1) == indices{0, 1}));
0551   BOOST_CHECK((g.localBinsFromGlobalBin(2) == indices{0, 2}));
0552   BOOST_CHECK((g.localBinsFromGlobalBin(3) == indices{0, 3}));
0553   BOOST_CHECK((g.localBinsFromGlobalBin(4) == indices{1, 0}));
0554   BOOST_CHECK((g.localBinsFromGlobalBin(5) == indices{1, 1}));
0555   BOOST_CHECK((g.localBinsFromGlobalBin(6) == indices{1, 2}));
0556   BOOST_CHECK((g.localBinsFromGlobalBin(7) == indices{1, 3}));
0557   BOOST_CHECK((g.localBinsFromGlobalBin(8) == indices{2, 0}));
0558   BOOST_CHECK((g.localBinsFromGlobalBin(9) == indices{2, 1}));
0559   BOOST_CHECK((g.localBinsFromGlobalBin(10) == indices{2, 2}));
0560   BOOST_CHECK((g.localBinsFromGlobalBin(11) == indices{2, 3}));
0561   BOOST_CHECK((g.localBinsFromGlobalBin(12) == indices{3, 0}));
0562   BOOST_CHECK((g.localBinsFromGlobalBin(13) == indices{3, 1}));
0563   BOOST_CHECK((g.localBinsFromGlobalBin(14) == indices{3, 2}));
0564   BOOST_CHECK((g.localBinsFromGlobalBin(15) == indices{3, 3}));
0565 
0566   // local bin indices -> global bin index
0567   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 0}), 0u);
0568   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 1}), 1u);
0569   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 2}), 2u);
0570   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 3}), 3u);
0571   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 0}), 4u);
0572   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 1}), 5u);
0573   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 2}), 6u);
0574   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 3}), 7u);
0575   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 0}), 8u);
0576   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 1}), 9u);
0577   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 2}), 10u);
0578   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 3}), 11u);
0579   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 0}), 12u);
0580   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 1}), 13u);
0581   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 2}), 14u);
0582   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 3}), 15u);
0583 
0584   BOOST_CHECK((g.localBinsFromGlobalBin(
0585                    g.globalBinFromPosition(Point{3.2, 1.8})) == indices{3, 2}));
0586 
0587   // inside checks
0588   BOOST_CHECK(!g.isInside(Point{-2., -1}));
0589   BOOST_CHECK(!g.isInside(Point{-2., 1.}));
0590   BOOST_CHECK(!g.isInside(Point{-2., 5.}));
0591   BOOST_CHECK(!g.isInside(Point{1., -1.}));
0592   BOOST_CHECK(!g.isInside(Point{6., -1.}));
0593   BOOST_CHECK(g.isInside(Point{0.5, 1.3}));
0594   BOOST_CHECK(!g.isInside(Point{3., -1.}));
0595   BOOST_CHECK(!g.isInside(Point{3., 0.3}));
0596   BOOST_CHECK(!g.isInside(Point{3., 4.}));
0597   BOOST_CHECK(!g.isInside(Point{-1., 4.}));
0598   BOOST_CHECK(!g.isInside(Point{2., 4.}));
0599   BOOST_CHECK(!g.isInside(Point{5., 4.}));
0600 
0601   // test some bin centers
0602   CHECK_CLOSE_ABS(g.binCenter({1, 1}), (Point{0.25, 0.5}), 1e-6);
0603   CHECK_CLOSE_ABS(g.binCenter({2, 1}), (Point{1.75, 0.5}), 1e-6);
0604   CHECK_CLOSE_ABS(g.binCenter({1, 2}), (Point{0.25, 2.5}), 1e-6);
0605   CHECK_CLOSE_ABS(g.binCenter({2, 2}), (Point{1.75, 2.5}), 1e-6);
0606 
0607   // test some lower-left bin edges
0608   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 1}), (Point{0., 0.}), 1e-6);
0609   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({2, 1}), (Point{0.5, 0.}), 1e-6);
0610   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 2}), (Point{0., 1.}), 1e-6);
0611   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({2, 2}), (Point{0.5, 1.}), 1e-6);
0612 
0613   // test some upper right-bin edges
0614   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 1}), (Point{0.5, 1.}), 1e-6);
0615   CHECK_CLOSE_ABS(g.upperRightBinEdge({2, 1}), (Point{3., 1.}), 1e-6);
0616   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 2}), (Point{0.5, 4.}), 1e-6);
0617   CHECK_CLOSE_ABS(g.upperRightBinEdge({2, 2}), (Point{3., 4.}), 1e-6);
0618 
0619   // initialize grid
0620   for (std::size_t bin = 0; bin < g.size(); ++bin) {
0621     g.at(bin) = bin;
0622   }
0623 
0624   // consistency of access
0625   const Point point{0.7, 1.3};
0626   const std::size_t globalBin = g.globalBinFromPosition(point);
0627   const indices localBins = g.localBinsFromGlobalBin(globalBin);
0628 
0629   BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
0630   BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
0631 }
0632 
0633 BOOST_AUTO_TEST_CASE(grid_test_3d_variable) {
0634   using Point = std::array<double, 3>;
0635   using indices = std::array<std::size_t, 3>;
0636 
0637   const Axis a({0.0, 1.0});
0638   const Axis b({0.0, 0.5, 3.0});
0639   const Axis c({0.0, 0.5, 3.0, 3.3});
0640   Grid g(Type<double>, a, b, c);
0641 
0642   // test general properties
0643   BOOST_CHECK_EQUAL(g.size(), 60u);
0644   BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 1u);
0645   BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 2u);
0646   BOOST_CHECK_EQUAL(g.numLocalBins().at(2), 3u);
0647 
0648   // test grid points
0649   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0, 0}), 26u);
0650   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0, 0}), 46u);
0651   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0.5, 0}), 31u);
0652   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0.5, 0}), 51u);
0653   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 3, 0}), 36u);
0654   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 3, 0}), 56u);
0655   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0, 0.5}), 27u);
0656   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0, 0.5}), 47u);
0657   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0.5, 0.5}), 32u);
0658   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0.5, 0.5}), 52u);
0659   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 3, 0.5}), 37u);
0660   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 3, 0.5}), 57u);
0661   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0, 3}), 28u);
0662   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0, 3}), 48u);
0663   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0.5, 3}), 33u);
0664   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0.5, 3}), 53u);
0665   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 3, 3}), 38u);
0666   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 3, 3}), 58u);
0667   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0, 3.3}), 29u);
0668   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0, 3.3}), 49u);
0669   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0.5, 3.3}), 34u);
0670   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0.5, 3.3}), 54u);
0671   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 3, 3.3}), 39u);
0672   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 3, 3.3}), 59u);
0673 
0674   // global bin index -> local bin indices
0675   BOOST_CHECK((g.localBinsFromGlobalBin(0) == indices{0, 0, 0}));
0676   BOOST_CHECK((g.localBinsFromGlobalBin(1) == indices{0, 0, 1}));
0677   BOOST_CHECK((g.localBinsFromGlobalBin(2) == indices{0, 0, 2}));
0678   BOOST_CHECK((g.localBinsFromGlobalBin(3) == indices{0, 0, 3}));
0679   BOOST_CHECK((g.localBinsFromGlobalBin(4) == indices{0, 0, 4}));
0680   BOOST_CHECK((g.localBinsFromGlobalBin(5) == indices{0, 1, 0}));
0681   BOOST_CHECK((g.localBinsFromGlobalBin(21) == indices{1, 0, 1}));
0682   BOOST_CHECK((g.localBinsFromGlobalBin(22) == indices{1, 0, 2}));
0683   BOOST_CHECK((g.localBinsFromGlobalBin(23) == indices{1, 0, 3}));
0684   BOOST_CHECK((g.localBinsFromGlobalBin(24) == indices{1, 0, 4}));
0685   BOOST_CHECK((g.localBinsFromGlobalBin(25) == indices{1, 1, 0}));
0686   BOOST_CHECK((g.localBinsFromGlobalBin(26) == indices{1, 1, 1}));
0687   BOOST_CHECK((g.localBinsFromGlobalBin(57) == indices{2, 3, 2}));
0688   BOOST_CHECK((g.localBinsFromGlobalBin(58) == indices{2, 3, 3}));
0689   BOOST_CHECK((g.localBinsFromGlobalBin(59) == indices{2, 3, 4}));
0690 
0691   // local bin indices -> global bin index
0692   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 0, 0}), 0u);
0693   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 0, 0}), 20u);
0694   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 0, 0}), 40u);
0695   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 1, 0}), 5u);
0696   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 1, 0}), 25u);
0697   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 1, 0}), 45u);
0698   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 3, 1}), 16u);
0699   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 3, 1}), 36u);
0700   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 3, 1}), 56u);
0701   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 0, 2}), 2u);
0702   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 0, 2}), 22u);
0703   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 0, 2}), 42u);
0704   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 3, 4}), 19u);
0705   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 3, 4}), 39u);
0706   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 3, 4}), 59u);
0707 
0708   BOOST_CHECK((g.localBinsFromGlobalBin(g.globalBinFromPosition(
0709                    Point{1.8, 0.7, 3.2})) == indices{2, 2, 3}));
0710 
0711   // inside checks
0712   BOOST_CHECK(!g.isInside(Point{-2., -1, -2}));
0713   BOOST_CHECK(!g.isInside(Point{-2., 1., 0.}));
0714   BOOST_CHECK(!g.isInside(Point{-2., 5., -1}));
0715   BOOST_CHECK(!g.isInside(Point{1., -1., 1.}));
0716   BOOST_CHECK(!g.isInside(Point{6., -1., 4.}));
0717   BOOST_CHECK(g.isInside(Point{0.5, 1.3, 1.7}));
0718   BOOST_CHECK(!g.isInside(Point{1., -1., -0.4}));
0719   BOOST_CHECK(!g.isInside(Point{1., 0.3, 3.4}));
0720   BOOST_CHECK(!g.isInside(Point{1., 3., 0.8}));
0721   BOOST_CHECK(!g.isInside(Point{-1., 3., 5.}));
0722   BOOST_CHECK(!g.isInside(Point{2., 3., -1.}));
0723   BOOST_CHECK(!g.isInside(Point{5., 3., 0.5}));
0724 
0725   // test some bin centers
0726   CHECK_CLOSE_ABS(g.binCenter({1, 1, 1}), (Point{0.5, 0.25, 0.25}), 1e-6);
0727   CHECK_CLOSE_ABS(g.binCenter({1, 1, 2}), (Point{0.5, 0.25, 1.75}), 1e-6);
0728   CHECK_CLOSE_ABS(g.binCenter({1, 1, 3}), (Point{0.5, 0.25, 3.15}), 1e-6);
0729   CHECK_CLOSE_ABS(g.binCenter({1, 2, 1}), (Point{0.5, 1.75, 0.25}), 1e-6);
0730   CHECK_CLOSE_ABS(g.binCenter({1, 2, 2}), (Point{0.5, 1.75, 1.75}), 1e-6);
0731   CHECK_CLOSE_ABS(g.binCenter({1, 2, 3}), (Point{0.5, 1.75, 3.15}), 1e-6);
0732 
0733   // test some lower-left bin edges
0734   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 1, 1}), (Point{0., 0., 0.}), 1e-6);
0735   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 1, 2}), (Point{0., 0., 0.5}), 1e-6);
0736   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 1, 3}), (Point{0., 0., 3.}), 1e-6);
0737   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 2, 1}), (Point{0., 0.5, 0.}), 1e-6);
0738   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 2, 2}), (Point{0., 0.5, 0.5}), 1e-6);
0739   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 2, 3}), (Point{0., 0.5, 3.}), 1e-6);
0740 
0741   // test some upper right-bin edges
0742   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 1, 1}), (Point{1., 0.5, 0.5}), 1e-6);
0743   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 1, 2}), (Point{1., 0.5, 3.}), 1e-6);
0744   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 1, 3}), (Point{1., 0.5, 3.3}), 1e-6);
0745   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 2, 1}), (Point{1., 3., 0.5}), 1e-6);
0746   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 2, 2}), (Point{1., 3., 3.}), 1e-6);
0747   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 2, 3}), (Point{1., 3., 3.3}), 1e-6);
0748 
0749   // initialize grid
0750   for (std::size_t bin = 0; bin < g.size(); ++bin) {
0751     g.at(bin) = bin;
0752   }
0753 
0754   // consistency of access
0755   const Point point{0.7, 1.3, 3.7};
0756   const std::size_t globalBin = g.globalBinFromPosition(point);
0757   const indices localBins = g.localBinsFromGlobalBin(globalBin);
0758 
0759   BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
0760   BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
0761 }
0762 
0763 BOOST_AUTO_TEST_CASE(grid_test_2d_mixed) {
0764   using Point = std::array<double, 2>;
0765   using indices = std::array<std::size_t, 2>;
0766 
0767   const Axis a(0.0, 1.0, 4u);
0768   const Axis b({0.0, 0.5, 3.0});
0769   Grid g(Type<double>, a, b);
0770 
0771   // test general properties
0772   BOOST_CHECK_EQUAL(g.size(), 24u);
0773   BOOST_CHECK_EQUAL(g.numLocalBins().at(0), 4u);
0774   BOOST_CHECK_EQUAL(g.numLocalBins().at(1), 2u);
0775 
0776   // test grid points
0777   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0}), 5u);
0778   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.25, 0}), 9u);
0779   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.5, 0}), 13u);
0780   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.75, 0}), 17u);
0781   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0}), 21u);
0782   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 0.5}), 6u);
0783   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.25, 0.5}), 10u);
0784   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.5, 0.5}), 14u);
0785   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.75, 0.5}), 18u);
0786   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 0.5}), 22u);
0787   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0, 3}), 7u);
0788   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.25, 3}), 11u);
0789   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.5, 3}), 15u);
0790   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.75, 3}), 19u);
0791   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1, 3}), 23u);
0792 
0793   // test some arbitrary points
0794   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{1.2, 0.3}), 21u);
0795   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.2, 1.3}), 6u);
0796   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.9, 1.8}), 18u);
0797   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.7, 2.1}), 14u);
0798   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.4, 0.3}), 9u);
0799   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-3, 2}), 2u);
0800   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{8, 1}), 22u);
0801   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.1, -3}), 4u);
0802   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{0.8, 11}), 19u);
0803   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-2, -3}), 0u);
0804   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{-2, 7}), 3u);
0805   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{12, -1}), 20u);
0806   BOOST_CHECK_EQUAL(g.globalBinFromPosition(Point{12, 11}), 23u);
0807 
0808   // global bin index -> local bin indices
0809   BOOST_CHECK((g.localBinsFromGlobalBin(0) == indices{0, 0}));
0810   BOOST_CHECK((g.localBinsFromGlobalBin(1) == indices{0, 1}));
0811   BOOST_CHECK((g.localBinsFromGlobalBin(2) == indices{0, 2}));
0812   BOOST_CHECK((g.localBinsFromGlobalBin(3) == indices{0, 3}));
0813   BOOST_CHECK((g.localBinsFromGlobalBin(4) == indices{1, 0}));
0814   BOOST_CHECK((g.localBinsFromGlobalBin(5) == indices{1, 1}));
0815   BOOST_CHECK((g.localBinsFromGlobalBin(6) == indices{1, 2}));
0816   BOOST_CHECK((g.localBinsFromGlobalBin(7) == indices{1, 3}));
0817   BOOST_CHECK((g.localBinsFromGlobalBin(8) == indices{2, 0}));
0818   BOOST_CHECK((g.localBinsFromGlobalBin(9) == indices{2, 1}));
0819   BOOST_CHECK((g.localBinsFromGlobalBin(10) == indices{2, 2}));
0820   BOOST_CHECK((g.localBinsFromGlobalBin(11) == indices{2, 3}));
0821   BOOST_CHECK((g.localBinsFromGlobalBin(12) == indices{3, 0}));
0822   BOOST_CHECK((g.localBinsFromGlobalBin(13) == indices{3, 1}));
0823   BOOST_CHECK((g.localBinsFromGlobalBin(14) == indices{3, 2}));
0824   BOOST_CHECK((g.localBinsFromGlobalBin(15) == indices{3, 3}));
0825   BOOST_CHECK((g.localBinsFromGlobalBin(16) == indices{4, 0}));
0826   BOOST_CHECK((g.localBinsFromGlobalBin(17) == indices{4, 1}));
0827   BOOST_CHECK((g.localBinsFromGlobalBin(18) == indices{4, 2}));
0828   BOOST_CHECK((g.localBinsFromGlobalBin(19) == indices{4, 3}));
0829   BOOST_CHECK((g.localBinsFromGlobalBin(20) == indices{5, 0}));
0830   BOOST_CHECK((g.localBinsFromGlobalBin(21) == indices{5, 1}));
0831   BOOST_CHECK((g.localBinsFromGlobalBin(22) == indices{5, 2}));
0832   BOOST_CHECK((g.localBinsFromGlobalBin(23) == indices{5, 3}));
0833 
0834   // local bin indices -> global bin index
0835   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 0}), 0u);
0836   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 1}), 1u);
0837   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 2}), 2u);
0838   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({0, 3}), 3u);
0839   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 0}), 4u);
0840   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 1}), 5u);
0841   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 2}), 6u);
0842   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({1, 3}), 7u);
0843   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 0}), 8u);
0844   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 1}), 9u);
0845   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 2}), 10u);
0846   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({2, 3}), 11u);
0847   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 0}), 12u);
0848   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 1}), 13u);
0849   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 2}), 14u);
0850   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({3, 3}), 15u);
0851   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({4, 0}), 16u);
0852   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({4, 1}), 17u);
0853   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({4, 2}), 18u);
0854   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({4, 3}), 19u);
0855   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({5, 0}), 20u);
0856   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({5, 1}), 21u);
0857   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({5, 2}), 22u);
0858   BOOST_CHECK_EQUAL(g.globalBinFromLocalBins({5, 3}), 23u);
0859 
0860   BOOST_CHECK((g.localBinsFromGlobalBin(
0861                    g.globalBinFromPosition(Point{1.1, 1.7})) == indices{5, 2}));
0862 
0863   // inside checks
0864   BOOST_CHECK(!g.isInside(Point{-2., -1}));
0865   BOOST_CHECK(!g.isInside(Point{-2., 1.}));
0866   BOOST_CHECK(!g.isInside(Point{-2., 5.}));
0867   BOOST_CHECK(!g.isInside(Point{0.1, -1.}));
0868   BOOST_CHECK(!g.isInside(Point{6., -1.}));
0869   BOOST_CHECK(g.isInside(Point{0.5, 1.3}));
0870   BOOST_CHECK(!g.isInside(Point{1., -1.}));
0871   BOOST_CHECK(!g.isInside(Point{1., 0.3}));
0872   BOOST_CHECK(!g.isInside(Point{1., 3.}));
0873   BOOST_CHECK(!g.isInside(Point{-1., 3.}));
0874   BOOST_CHECK(!g.isInside(Point{0.2, 3.}));
0875   BOOST_CHECK(!g.isInside(Point{5., 3.}));
0876 
0877   // test some bin centers
0878   CHECK_CLOSE_ABS(g.binCenter({1, 1}), (Point{0.125, 0.25}), 1e-6);
0879   CHECK_CLOSE_ABS(g.binCenter({1, 2}), (Point{0.125, 1.75}), 1e-6);
0880   CHECK_CLOSE_ABS(g.binCenter({2, 1}), (Point{0.375, 0.25}), 1e-6);
0881   CHECK_CLOSE_ABS(g.binCenter({2, 2}), (Point{0.375, 1.75}), 1e-6);
0882   CHECK_CLOSE_ABS(g.binCenter({3, 1}), (Point{0.625, 0.25}), 1e-6);
0883   CHECK_CLOSE_ABS(g.binCenter({3, 2}), (Point{0.625, 1.75}), 1e-6);
0884   CHECK_CLOSE_ABS(g.binCenter({4, 1}), (Point{0.875, 0.25}), 1e-6);
0885   CHECK_CLOSE_ABS(g.binCenter({4, 2}), (Point{0.875, 1.75}), 1e-6);
0886 
0887   // test some lower-left bin edges
0888   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 1}), (Point{0., 0.}), 1e-6);
0889   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({1, 2}), (Point{0., 0.5}), 1e-6);
0890   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({2, 1}), (Point{0.25, 0.}), 1e-6);
0891   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({2, 2}), (Point{0.25, 0.5}), 1e-6);
0892   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({3, 1}), (Point{0.5, 0.}), 1e-6);
0893   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({3, 2}), (Point{0.5, 0.5}), 1e-6);
0894   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({4, 1}), (Point{0.75, 0.}), 1e-6);
0895   CHECK_CLOSE_ABS(g.lowerLeftBinEdge({4, 2}), (Point{0.75, 0.5}), 1e-6);
0896 
0897   // test some upper-right bin edges
0898   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 1}), (Point{0.25, 0.5}), 1e-6);
0899   CHECK_CLOSE_ABS(g.upperRightBinEdge({1, 2}), (Point{0.25, 3.}), 1e-6);
0900   CHECK_CLOSE_ABS(g.upperRightBinEdge({2, 1}), (Point{0.5, 0.5}), 1e-6);
0901   CHECK_CLOSE_ABS(g.upperRightBinEdge({2, 2}), (Point{0.5, 3.}), 1e-6);
0902   CHECK_CLOSE_ABS(g.upperRightBinEdge({3, 1}), (Point{0.75, 0.5}), 1e-6);
0903   CHECK_CLOSE_ABS(g.upperRightBinEdge({3, 2}), (Point{0.75, 3.}), 1e-6);
0904   CHECK_CLOSE_ABS(g.upperRightBinEdge({4, 1}), (Point{1., 0.5}), 1e-6);
0905   CHECK_CLOSE_ABS(g.upperRightBinEdge({4, 2}), (Point{1., 3.}), 1e-6);
0906 
0907   // initialize grid
0908   for (std::size_t bin = 0; bin < g.size(); ++bin) {
0909     g.at(bin) = bin;
0910   }
0911 
0912   // consistency of access
0913   const Point point{1.3, 3.7};
0914   const std::size_t globalBin = g.globalBinFromPosition(point);
0915   const indices localBins = g.localBinsFromGlobalBin(globalBin);
0916 
0917   BOOST_CHECK_EQUAL(g.atPosition(point), g.at(globalBin));
0918   BOOST_CHECK_EQUAL(g.atPosition(point), g.atLocalBins(localBins));
0919 }
0920 
0921 BOOST_AUTO_TEST_CASE(grid_test_2d_mixed_at) {
0922   using Point = std::array<double, 2>;
0923 
0924   const Axis a(0.0, 6.0, 4u);
0925   const Axis b({0.0, 1.5, 3.0});
0926   Grid g(Type<double>, a, b);
0927 
0928   // initialize the grid
0929   g.atPosition(Point({{0, 0}})) = 0.;
0930   g.atPosition(Point({{1.5, 0}})) = 1.;
0931   g.atPosition(Point({{3, 0}})) = 2.;
0932   g.atPosition(Point({{4.5, 0}})) = 3.;
0933   g.atPosition(Point({{6, 0}})) = 4.;
0934   g.atPosition(Point({{0, 1.5}})) = 5.;
0935   g.atPosition(Point({{1.5, 1.5}})) = 6.;
0936   g.atPosition(Point({{3, 1.5}})) = 7.;
0937   g.atPosition(Point({{4.5, 1.5}})) = 8.;
0938   g.atPosition(Point({{6, 1.5}})) = 9.;
0939   g.atPosition(Point({{0, 3}})) = 10.;
0940   g.atPosition(Point({{1.5, 3}})) = 11.;
0941   g.atPosition(Point({{3, 3}})) = 12.;
0942   g.atPosition(Point({{4.5, 3}})) = 13.;
0943   g.atPosition(Point({{6, 3}})) = 14.;
0944 
0945   // test general properties
0946   BOOST_CHECK_EQUAL(g.size(), 24u);
0947 
0948   // test some arbitrary points
0949   BOOST_CHECK_EQUAL(g.atPosition(Point({{1.2, 0.3}})), 0.);
0950   BOOST_CHECK_EQUAL(g.atPosition(Point({{2.2, 1.3}})), 1.);
0951   BOOST_CHECK_EQUAL(g.atPosition(Point({{4.9, 1.8}})), 8.);
0952   BOOST_CHECK_EQUAL(g.atPosition(Point({{3.7, 2.1}})), 7.);
0953   BOOST_CHECK_EQUAL(g.atPosition(Point({{0.4, 2.3}})), 5.);
0954 }
0955 
0956 BOOST_AUTO_TEST_CASE(grid_interpolation) {
0957   using Point = std::array<double, 3>;
0958 
0959   const Axis a(1.0, 3.0, 2u);
0960   const Axis b(1.0, 5.0, 2u);
0961   const Axis c(1.0, 7.0, 2u);
0962   Grid g(Type<double>, a, b, c);
0963 
0964   g.atPosition(Point{1., 1., 1.}) = 10.;
0965   g.atPosition(Point{2., 1., 1.}) = 20.;
0966   g.atPosition(Point{1., 3., 1.}) = 30.;
0967   g.atPosition(Point{2., 3., 1.}) = 40.;
0968   g.atPosition(Point{1., 1., 4.}) = 50.;
0969   g.atPosition(Point{2., 1., 4.}) = 60.;
0970   g.atPosition(Point{1., 3., 4.}) = 70.;
0971   g.atPosition(Point{2., 3., 4.}) = 80.;
0972 
0973   CHECK_CLOSE_REL(g.interpolate(Point{1., 1., 1.}), 10., 1e-6);
0974   CHECK_CLOSE_REL(g.interpolate(Point{2., 1., 1.}), 20., 1e-6);
0975   CHECK_CLOSE_REL(g.interpolate(Point{1., 3., 1.}), 30., 1e-6);
0976   CHECK_CLOSE_REL(g.interpolate(Point{2., 3., 1.}), 40., 1e-6);
0977   CHECK_CLOSE_REL(g.interpolate(Point{1., 1., 4.}), 50., 1e-6);
0978   CHECK_CLOSE_REL(g.interpolate(Point{2., 1., 4.}), 60., 1e-6);
0979   CHECK_CLOSE_REL(g.interpolate(Point{1., 3., 4.}), 70., 1e-6);
0980   CHECK_CLOSE_REL(g.interpolate(Point{2., 3., 4.}), 80., 1e-6);
0981   CHECK_CLOSE_REL(g.interpolate(Point{1.5, 1., 1.}), 15., 1e-6);
0982   CHECK_CLOSE_REL(g.interpolate(Point{1.5, 3., 1.}), 35., 1e-6);
0983   CHECK_CLOSE_REL(g.interpolate(Point{1., 2., 1.}), 20., 1e-6);
0984   CHECK_CLOSE_REL(g.interpolate(Point{2., 2., 1.}), 30., 1e-6);
0985   CHECK_CLOSE_REL(g.interpolate(Point{1.5, 1., 4.}), 55., 1e-6);
0986   CHECK_CLOSE_REL(g.interpolate(Point{1.5, 3., 4.}), 75., 1e-6);
0987   CHECK_CLOSE_REL(g.interpolate(Point{1., 2., 4.}), 60., 1e-6);
0988   CHECK_CLOSE_REL(g.interpolate(Point{2., 2., 4.}), 70., 1e-6);
0989   CHECK_CLOSE_REL(g.interpolate(Point{1., 1., 2.5}), 30., 1e-6);
0990   CHECK_CLOSE_REL(g.interpolate(Point{1., 3., 2.5}), 50., 1e-6);
0991   CHECK_CLOSE_REL(g.interpolate(Point{2., 1., 2.5}), 40., 1e-6);
0992   CHECK_CLOSE_REL(g.interpolate(Point{2., 3., 2.5}), 60., 1e-6);
0993   CHECK_CLOSE_REL(g.interpolate(Point{1.5, 2., 2.5}), 360. / 8, 1e-6);
0994   CHECK_CLOSE_REL(g.interpolate(Point{1.3, 2.1, 1.6}), 32., 1e-6);
0995   CHECK_CLOSE_REL(g.interpolate(Point{2., 3., 4.}), 80., 1e-6);
0996 }
0997 
0998 BOOST_AUTO_TEST_CASE(neighborhood) {
0999   using bins_t = std::vector<std::size_t>;
1000 
1001   const Axis a(0.0, 1.0, 10u);
1002   const Axis b(0.0, 1.0, 10u);
1003   const Axis c(0.0, 1.0, 10u);
1004   const Grid g1(Type<double>, a);
1005   const Grid g2(Type<double>, a, b);
1006   const Grid g3(Type<double>, a, b, c);
1007 
1008   // 1D case
1009   BOOST_CHECK((g1.neighborHoodIndices({0}, 1).collectVector() == bins_t{0, 1}));
1010   BOOST_CHECK(
1011       (g1.neighborHoodIndices({0}, 2).collectVector() == bins_t{0, 1, 2}));
1012   BOOST_CHECK(
1013       (g1.neighborHoodIndices({1}, 1).collectVector() == bins_t{0, 1, 2}));
1014   BOOST_CHECK((g1.neighborHoodIndices({1}, 3).collectVector() ==
1015                bins_t{0, 1, 2, 3, 4}));
1016   BOOST_CHECK((g1.neighborHoodIndices({4}, 2).collectVector() ==
1017                bins_t{2, 3, 4, 5, 6}));
1018   BOOST_CHECK((g1.neighborHoodIndices({9}, 2).collectVector() ==
1019                bins_t{7, 8, 9, 10, 11}));
1020   BOOST_CHECK((g1.neighborHoodIndices({10}, 2).collectVector() ==
1021                bins_t{8, 9, 10, 11}));
1022   BOOST_CHECK(
1023       (g1.neighborHoodIndices({11}, 2).collectVector() == bins_t{9, 10, 11}));
1024 
1025   // 2D case
1026   BOOST_CHECK((g2.neighborHoodIndices({0, 0}, 1).collectVector() ==
1027                bins_t{0, 1, 12, 13}));
1028   BOOST_CHECK((g2.neighborHoodIndices({0, 1}, 1).collectVector() ==
1029                bins_t{0, 1, 2, 12, 13, 14}));
1030   BOOST_CHECK((g2.neighborHoodIndices({1, 0}, 1).collectVector() ==
1031                bins_t{0, 1, 12, 13, 24, 25}));
1032   BOOST_CHECK((g2.neighborHoodIndices({1, 1}, 1).collectVector() ==
1033                bins_t{0, 1, 2, 12, 13, 14, 24, 25, 26}));
1034   BOOST_CHECK((g2.neighborHoodIndices({5, 5}, 1).collectVector() ==
1035                bins_t{52, 53, 54, 64, 65, 66, 76, 77, 78}));
1036   BOOST_CHECK((g2.neighborHoodIndices({9, 10}, 2).collectVector() ==
1037                bins_t{92,  93,  94,  95,  104, 105, 106, 107, 116, 117,
1038                       118, 119, 128, 129, 130, 131, 140, 141, 142, 143}));
1039 
1040   // 3D case
1041   BOOST_CHECK((g3.neighborHoodIndices({0, 0, 0}, 1).collectVector() ==
1042                bins_t({0, 1, 12, 13, 144, 145, 156, 157})));
1043   BOOST_CHECK((g3.neighborHoodIndices({0, 0, 1}, 1).collectVector() ==
1044                bins_t({0, 1, 2, 12, 13, 14, 144, 145, 146, 156, 157, 158})));
1045   BOOST_CHECK((g3.neighborHoodIndices({0, 1, 0}, 1).collectVector() ==
1046                bins_t({0, 1, 12, 13, 24, 25, 144, 145, 156, 157, 168, 169})));
1047   BOOST_CHECK((g3.neighborHoodIndices({1, 0, 0}, 1).collectVector() ==
1048                bins_t({0, 1, 12, 13, 144, 145, 156, 157, 288, 289, 300, 301})));
1049   BOOST_CHECK((g3.neighborHoodIndices({0, 1, 1}, 1).collectVector() ==
1050                bins_t({0, 1, 2, 12, 13, 14, 24, 25, 26, 144, 145, 146, 156, 157,
1051                        158, 168, 169, 170})));
1052   BOOST_CHECK((g3.neighborHoodIndices({1, 1, 1}, 1).collectVector() ==
1053                bins_t({0,   1,   2,   12,  13,  14,  24,  25,  26,
1054                        144, 145, 146, 156, 157, 158, 168, 169, 170,
1055                        288, 289, 290, 300, 301, 302, 312, 313, 314})));
1056   BOOST_CHECK((g3.neighborHoodIndices({11, 10, 9}, 1).collectVector() ==
1057                bins_t({1556, 1557, 1558, 1568, 1569, 1570, 1580, 1581, 1582,
1058                        1700, 1701, 1702, 1712, 1713, 1714, 1724, 1725, 1726})));
1059 
1060   // Neighbors array
1061   std::array<std::pair<int, int>, 1> a1;
1062   a1.at(0) = std::make_pair<int, int>(-1, 1);
1063   BOOST_CHECK(
1064       (g1.neighborHoodIndices({0}, a1).collectVector() == bins_t{0, 1}));
1065   BOOST_CHECK(
1066       (g1.neighborHoodIndices({2}, a1).collectVector() == bins_t{1, 2, 3}));
1067 
1068   a1.at(0) = std::make_pair<int, int>(2, 3);
1069   BOOST_CHECK(
1070       (g1.neighborHoodIndices({2}, a1).collectVector() == bins_t{4, 5}));
1071 
1072   a1.at(0) = std::make_pair<int, int>(-2, -1);
1073   BOOST_CHECK(
1074       (g1.neighborHoodIndices({2}, a1).collectVector() == bins_t{0, 1}));
1075 
1076   a1.at(0) = std::make_pair<int, int>(-3, -1);
1077   BOOST_CHECK(
1078       (g1.neighborHoodIndices({2}, a1).collectVector() == bins_t{0, 1}));
1079 
1080   const Axis d(AxisClosed, 0.0, 1.0, 10u);
1081   const Grid g1Cl(Type<double>, d);
1082 
1083   // underflow, makes no sense
1084   BOOST_CHECK(g1Cl.neighborHoodIndices({0}, 1).collectVector().empty());
1085   // overflow, makes no sense
1086   BOOST_CHECK(g1Cl.neighborHoodIndices({11}, 1).collectVector().empty());
1087   // overflow, makes no sense
1088   BOOST_CHECK(
1089       (g1Cl.neighborHoodIndices({1}, 1).collectVector() == bins_t{10, 1, 2}));
1090   // overflow, makes no sense
1091   BOOST_CHECK(
1092       (g1Cl.neighborHoodIndices({5}, 1).collectVector() == bins_t{4, 5, 6}));
1093 
1094   const Axis f(AxisClosed, 0.0, 1.0, 5u);
1095   const Axis e(AxisClosed, 0.0, 1.0, 5u);
1096   const Grid g2Cl(Type<double>, e, f);
1097 
1098   BOOST_CHECK((g2Cl.neighborHoodIndices({3, 3}, 1).collectVector() ==
1099                bins_t{16, 17, 18, 23, 24, 25, 30, 31, 32}));
1100   BOOST_CHECK((g2Cl.neighborHoodIndices({1, 1}, 1).collectVector() ==
1101                bins_t{40, 36, 37, 12, 8, 9, 19, 15, 16}));
1102   BOOST_CHECK((g2Cl.neighborHoodIndices({1, 5}, 1).collectVector() ==
1103                bins_t{39, 40, 36, 11, 12, 8, 18, 19, 15}));
1104   BOOST_CHECK((g2Cl.neighborHoodIndices({5, 1}, 1).collectVector() ==
1105                bins_t{33, 29, 30, 40, 36, 37, 12, 8, 9}));
1106   BOOST_CHECK((g2Cl.neighborHoodIndices({5, 5}, 1).collectVector() ==
1107                bins_t{32, 33, 29, 39, 40, 36, 11, 12, 8}));
1108 
1109   BOOST_CHECK((g2Cl.neighborHoodIndices({3, 3}, 2).collectVector() ==
1110                bins_t{8,  9,  10, 11, 12, 15, 16, 17, 18, 19, 22, 23, 24,
1111                       25, 26, 29, 30, 31, 32, 33, 36, 37, 38, 39, 40}));
1112   BOOST_CHECK((g2Cl.neighborHoodIndices({1, 1}, 2).collectVector() ==
1113                bins_t{32, 33, 29, 30, 31, 39, 40, 36, 37, 38, 11, 12, 8,
1114                       9,  10, 18, 19, 15, 16, 17, 25, 26, 22, 23, 24}));
1115   BOOST_CHECK((g2Cl.neighborHoodIndices({1, 5}, 2).collectVector() ==
1116                bins_t{31, 32, 33, 29, 30, 38, 39, 40, 36, 37, 10, 11, 12,
1117                       8,  9,  17, 18, 19, 15, 16, 24, 25, 26, 22, 23}));
1118   BOOST_CHECK((g2Cl.neighborHoodIndices({5, 1}, 2).collectVector() ==
1119                bins_t{25, 26, 22, 23, 24, 32, 33, 29, 30, 31, 39, 40, 36,
1120                       37, 38, 11, 12, 8,  9,  10, 18, 19, 15, 16, 17}));
1121   BOOST_CHECK((g2Cl.neighborHoodIndices({5, 5}, 2).collectVector() ==
1122                bins_t{24, 25, 26, 22, 23, 31, 32, 33, 29, 30, 38, 39, 40,
1123                       36, 37, 10, 11, 12, 8,  9,  17, 18, 19, 15, 16}));
1124 
1125   std::array<std::pair<int, int>, 2> a2;
1126   // only 2 bins left of requested bin (not including the requested bin)
1127   a2.at(0) = std::make_pair<int, int>(-2, -1);
1128   // one bin left of requested bin, the requested bin itself and 2 bins right of
1129   // requested bin
1130   a2.at(1) = std::make_pair<int, int>(-1, 2);
1131   std::set<std::size_t> returnedBins;
1132 
1133   auto returnedBinsVec = g2Cl.neighborHoodIndices({3, 2}, a2).collectVector();
1134   returnedBins.insert(returnedBinsVec.begin(), returnedBinsVec.end());
1135   std::set<std::size_t> expectedBins{8, 9, 10, 11, 15, 16, 17, 18};
1136   BOOST_CHECK(returnedBins == expectedBins);
1137 
1138   returnedBinsVec = g2Cl.neighborHoodIndices({1, 5}, a2).collectVector();
1139   returnedBins.clear();
1140   returnedBins.insert(returnedBinsVec.begin(), returnedBinsVec.end());
1141   expectedBins = {29, 30, 32, 33, 36, 37, 39, 40};
1142   BOOST_CHECK(returnedBins == expectedBins);
1143 
1144   a2.at(0) = {-6, 7};
1145   a2.at(1) = {0, 0};
1146   returnedBinsVec = g2Cl.neighborHoodIndices({1, 5}, a2).collectVector();
1147   returnedBins.clear();
1148   returnedBins.insert(returnedBinsVec.begin(), returnedBinsVec.end());
1149   expectedBins = {12, 19, 26, 33, 40};
1150   BOOST_CHECK(returnedBins == expectedBins);
1151 
1152   // @TODO 3D test would be nice, but should essentially not be a problem if
1153   // 2D works.
1154 
1155   // clang-format off
1156   /*
1157    *       1   2    3    4    5
1158    *   |------------------------|
1159    * 1 |  8 |  9 | 10 | 11 | 12 |
1160    *   |----|----|----|----|----|
1161    * 2 | 15 | 16 | 17 | 18 | 19 |
1162    *   |----|----|----|----|----|
1163    * 3 | 22 | 23 | 24 | 25 | 26 |
1164    *   |----|----|----|----|----|
1165    * 4 | 29 | 30 | 31 | 32 | 33 |
1166    *   |----|----|----|----|----|
1167    * 5 | 36 | 37 | 38 | 39 | 40 |
1168    *   |------------------------|
1169    */
1170   // clang-format on
1171 }
1172 
1173 BOOST_AUTO_TEST_CASE(closestPoints) {
1174   using Point = std::array<double, 3>;
1175   using bins_t = std::vector<std::size_t>;
1176 
1177   const Axis a(0.0, 1.0, 10u);
1178   const Axis b(0.0, 1.0, 5u);
1179   const Axis c(0.0, 1.0, 3u);
1180   const Grid g1(Type<double>, a);
1181   const Grid g2(Type<double>, a, b);
1182   const Grid g3(Type<double>, a, b, c);
1183 
1184   // 1D case
1185   BOOST_CHECK(
1186       (g1.closestPointsIndices(Point{0.52}).collectVector() == bins_t{6, 7}));
1187   BOOST_CHECK(
1188       (g1.closestPointsIndices(Point{0.98}).collectVector() == bins_t{10, 11}));
1189 
1190   // 2D case
1191   BOOST_CHECK((g2.closestPointsIndices(Point{0.52, 0.08}).collectVector() ==
1192                bins_t{43, 44, 50, 51}));
1193   BOOST_CHECK((g2.closestPointsIndices(Point{0.05, 0.08}).collectVector() ==
1194                bins_t{8, 9, 15, 16}));
1195 
1196   // 3D case
1197   BOOST_CHECK(
1198       (g3.closestPointsIndices(Point{0.23, 0.13, 0.61}).collectVector() ==
1199        bins_t{112, 113, 117, 118, 147, 148, 152, 153}));
1200   BOOST_CHECK(
1201       (g3.closestPointsIndices(Point{0.52, 0.35, 0.71}).collectVector() ==
1202        bins_t{223, 224, 228, 229, 258, 259, 263, 264}));
1203 
1204   using EAxisClosed = Axis<AxisType::Equidistant, AxisBoundaryType::Closed>;
1205   using Grid1Cl_t = Grid<double, EAxisClosed>;
1206   using Grid2Cl_t = Grid<double, EAxisClosed, EAxisClosed>;
1207   // using Grid3Cl_t = Grid<double, EAxisClosed, EAxisClosed, EAxisClosed>;
1208   const EAxisClosed aCl(0.0, 1.0, 10u);
1209   const EAxisClosed bCl(0.0, 1.0, 5u);
1210   // EAxisClosed   cCl(0.0, 1.0, 3u);
1211   const Grid1Cl_t g1Cl(aCl);
1212   const Grid2Cl_t g2Cl(aCl, bCl);
1213 
1214   // 1D case
1215   BOOST_CHECK(
1216       (g1Cl.closestPointsIndices(Point{0.52}).collectVector() == bins_t{6, 7}));
1217   BOOST_CHECK((g1Cl.closestPointsIndices(Point{0.98}).collectVector() ==
1218                bins_t{10, 1}));
1219 
1220   // 2D case
1221   BOOST_CHECK((g2Cl.closestPointsIndices(Point{0.52, 0.08}).collectVector() ==
1222                bins_t{43, 44, 50, 51}));
1223   BOOST_CHECK((g2Cl.closestPointsIndices(Point{0.52, 0.68}).collectVector() ==
1224                bins_t{46, 47, 53, 54}));
1225   BOOST_CHECK((g2Cl.closestPointsIndices(Point{0.52, 0.88}).collectVector() ==
1226                bins_t{47, 43, 54, 50}));
1227   BOOST_CHECK((g2Cl.closestPointsIndices(Point{0.05, 0.08}).collectVector() ==
1228                bins_t{8, 9, 15, 16}));
1229   BOOST_CHECK((g2Cl.closestPointsIndices(Point{0.9, 0.95}).collectVector() ==
1230                bins_t{75, 71, 12, 8}));
1231 
1232   // @TODO: 3D checks would also be nice
1233 
1234   const Axis aOp(AxisBound, 0.0, 1.0, 10u);
1235   const Axis bOp(AxisBound, 0.0, 1.0, 5u);
1236   const Grid g1Op(Type<double>, aOp);
1237   const Grid g2Op(Type<double>, aOp, bOp);
1238 
1239   // 1D case
1240   BOOST_CHECK(
1241       (g1Op.closestPointsIndices(Point{0.52}).collectVector() == bins_t{6, 7}));
1242   BOOST_CHECK(
1243       (g1Op.closestPointsIndices(Point{0.98}).collectVector() == bins_t{10}));
1244   BOOST_CHECK((g1Op.closestPointsIndices(Point{0.88}).collectVector() ==
1245                bins_t{9, 10}));
1246 
1247   // 2D case
1248   BOOST_CHECK((g2Op.closestPointsIndices(Point{0.52, 0.08}).collectVector() ==
1249                bins_t{43, 44, 50, 51}));
1250   BOOST_CHECK((g2Op.closestPointsIndices(Point{0.52, 0.68}).collectVector() ==
1251                bins_t{46, 47, 53, 54}));
1252   BOOST_CHECK((g2Op.closestPointsIndices(Point{0.52, 0.88}).collectVector() ==
1253                bins_t{47, 54}));
1254   BOOST_CHECK((g2Op.closestPointsIndices(Point{0.05, 0.1}).collectVector() ==
1255                bins_t{8, 9, 15, 16}));
1256   BOOST_CHECK((g2Op.closestPointsIndices(Point{0.95, 0.95}).collectVector() ==
1257                bins_t{75}));
1258 
1259   // @TODO: 3D checks would also be nice
1260 
1261   // clang-format off
1262   /*
1263    *       1    2    3    4    5
1264    *    |------------------------|
1265    *  1 |  8 |  9 | 10 | 11 | 12 |
1266    *    |----|----|----|----|----|
1267    *  2 | 15 | 16 | 17 | 18 | 19 |
1268    *    |----|----|----|----|----|
1269    *  3 | 22 | 23 | 24 | 25 | 26 |
1270    *    |----|----|----|----|----|
1271    *  4 | 29 | 30 | 31 | 32 | 33 |
1272    *    |----|----|----|----|----|
1273    *  5 | 36 | 37 | 38 | 39 | 40 |
1274    *    |------------------------|
1275    *  6 | 43 | 44 | 45 | 46 | 47 |
1276    *    |------------------------|
1277    *  7 | 50 | 51 | 52 | 53 | 54 |
1278    *    |------------------------|
1279    *  8 | 57 | 58 | 59 | 60 | 61 |
1280    *    |------------------------|
1281    *  9 | 64 | 65 | 66 | 67 | 68 |
1282    *    |------------------------|
1283    * 10 | 71 | 72 | 73 | 74 | 75 |
1284    *    |------------------------|
1285    * 77   78   79   80   81   82   83
1286    */
1287   // clang-format on
1288 }
1289 
1290 BOOST_AUTO_TEST_CASE(grid_type_conversion) {
1291   // Type conversion test
1292   using Grid2Int =
1293       Grid<int, Axis<AxisType::Equidistant>, Axis<AxisType::Variable>>;
1294 
1295   const Axis a(0.0, 1.0, 10u);
1296   const Axis b({0., 1.2, 2.3, 3.4, 4.5, 5.6});
1297   const Grid g2(Type<double>, a, b);
1298   const decltype(g2) g2Copy(g2.axesTuple());
1299 
1300   static_assert(std::same_as<decltype(g2), decltype(g2Copy)>);
1301 
1302   auto g2ConvertedInt = g2Copy.convertType<int>();
1303   static_assert(std::same_as<decltype(g2ConvertedInt), Grid2Int>);
1304 }
1305 
1306 BOOST_AUTO_TEST_CASE(grid_full_conversion) {
1307   // The converter class
1308   struct DoubleToInt {
1309     // Declare a value type
1310     using value_type = int;
1311     // the conversion operator
1312     int operator()(double d) { return static_cast<int>(d); }
1313   };
1314 
1315   // Grid conversion test
1316   const Axis a(0.0, 1.0, 2u);
1317   Grid g1(Type<double>, a);
1318 
1319   using Point = std::array<double, 1>;
1320   g1.atPosition(Point{0.3}) = 1.1;
1321   g1.atPosition(Point{0.6}) = 2.4;
1322 
1323   DoubleToInt d2i;
1324 
1325   auto g1ConvertedInt = g1.convertGrid(d2i);
1326   BOOST_CHECK_EQUAL(g1ConvertedInt.atPosition(Point{0.3}), 1);
1327   BOOST_CHECK_EQUAL(g1ConvertedInt.atPosition(Point{0.6}), 2);
1328 }
1329 
1330 BOOST_AUTO_TEST_CASE(Output) {
1331   const Axis a{AxisOpen, 0.0, 1.0, 10u};
1332   const Axis b{AxisBound, {1, 2, 3}};
1333 
1334   const Grid g(Type<double>, a, b);
1335 
1336   std::stringstream ss;
1337   ss << g;
1338   BOOST_CHECK_EQUAL(ss.str(),
1339                     "Axis<Equidistant, Open>(0, 1, 10, Undefined), "
1340                     "Axis<Variable, Bound>({1, 2, 3}, Undefined)");
1341 
1342   const IGrid& ig = g;
1343 
1344   ss.str("");
1345 
1346   ss << ig;
1347 
1348   BOOST_CHECK_EQUAL(ss.str(),
1349                     "Axis<Equidistant, Open>(0, 1, 10, Undefined), "
1350                     "Axis<Variable, Bound>({1, 2, 3}, Undefined)");
1351 }
1352 
1353 BOOST_AUTO_TEST_CASE(Equality) {
1354   const Axis a{AxisOpen, 0.0, 1.0, 10u};
1355   const Axis b{AxisBound, {1, 2, 3}};
1356   const Axis c{AxisClosed, {1, 2, 5}};
1357 
1358   const Grid ab{Type<double>, a, b};
1359   const Grid ac{Type<double>, a, c};
1360 
1361   BOOST_CHECK_EQUAL(ab, ab);
1362   BOOST_CHECK_EQUAL(ac, ac);
1363   BOOST_CHECK_NE(ab, ac);
1364 
1365   const IGrid& iab = ab;
1366   const IGrid& iac = ac;
1367 
1368   BOOST_CHECK_EQUAL(iab, iab);
1369   BOOST_CHECK_EQUAL(iac, iac);
1370 }
1371 
1372 BOOST_AUTO_TEST_SUITE_END()
1373 
1374 }  // namespace ActsTests