File indexing completed on 2026-04-08 07:46:52
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Utilities/Axis.hpp"
0012 #include "Acts/Utilities/IAxis.hpp"
0013
0014 #include <array>
0015 #include <set>
0016 #include <tuple>
0017 #include <utility>
0018
0019 #include <boost/container/small_vector.hpp>
0020
0021 namespace Acts::detail {
0022
0023 template <typename T>
0024 constexpr T ipow(T num, unsigned int pow) {
0025 return (pow >= sizeof(unsigned int) * 8) ? 0
0026 : pow == 0 ? 1
0027 : num * ipow(num, pow - 1);
0028 }
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 template <std::size_t DIM>
0039 class GlobalNeighborHoodIndices {
0040 public:
0041
0042
0043
0044 GlobalNeighborHoodIndices(
0045 std::array<NeighborHoodIndices, DIM>& neighborIndices,
0046 const std::array<std::size_t, DIM>& nBinsArray)
0047 : m_localIndices(neighborIndices) {
0048 if (DIM == 1) {
0049 return;
0050 }
0051 std::size_t globalStride = 1;
0052 for (long i = DIM - 2; i >= 0; --i) {
0053 globalStride *= (nBinsArray[i + 1] + 2);
0054 m_globalStrides[i] = globalStride;
0055 }
0056 }
0057
0058 class iterator {
0059 public:
0060 using iterator_category = std::forward_iterator_tag;
0061 using value_type = std::size_t;
0062 using difference_type = std::ptrdiff_t;
0063 using pointer = std::size_t*;
0064 using reference = std::size_t&;
0065
0066 iterator() = default;
0067
0068 iterator(const GlobalNeighborHoodIndices& parent,
0069 std::array<NeighborHoodIndices::iterator, DIM>&& localIndicesIter)
0070 : m_localIndicesIter(std::move(localIndicesIter)), m_parent(&parent) {}
0071
0072 std::size_t operator*() const {
0073 std::size_t globalIndex = *m_localIndicesIter[DIM - 1];
0074 if (DIM == 1) {
0075 return globalIndex;
0076 }
0077 for (std::size_t i = 0; i < DIM - 1; ++i) {
0078 globalIndex += m_parent->m_globalStrides[i] * (*m_localIndicesIter[i]);
0079 }
0080 return globalIndex;
0081 }
0082
0083 iterator& operator++() {
0084 const auto& localIndices = m_parent->m_localIndices;
0085
0086
0087
0088
0089 for (long i = DIM - 1; i > 0; --i) {
0090 ++m_localIndicesIter[i];
0091 if (m_localIndicesIter[i] != localIndices[i].end()) {
0092 return *this;
0093 }
0094 m_localIndicesIter[i] = localIndices[i].begin();
0095 }
0096
0097
0098
0099 ++m_localIndicesIter[0];
0100 return *this;
0101 }
0102
0103 iterator operator++(int) {
0104 iterator tmp = *this;
0105 ++(*this);
0106 return tmp;
0107 }
0108
0109 bool isEqual(const iterator& b) const {
0110 if (b.m_parent == nullptr) {
0111 return m_localIndicesIter[0] == m_parent->m_localIndices[0].end();
0112 } else {
0113 return m_localIndicesIter == b.m_localIndicesIter;
0114 }
0115 }
0116
0117 friend bool operator==(const iterator& a, const iterator& b) {
0118 return a.isEqual(b);
0119 }
0120
0121 private:
0122 std::array<NeighborHoodIndices::iterator, DIM> m_localIndicesIter;
0123 const GlobalNeighborHoodIndices* m_parent = nullptr;
0124 };
0125
0126 iterator begin() const {
0127 std::array<NeighborHoodIndices::iterator, DIM> localIndicesIter{};
0128 for (std::size_t i = 0; i < DIM; ++i) {
0129 localIndicesIter[i] = m_localIndices[i].begin();
0130 }
0131 return iterator(*this, std::move(localIndicesIter));
0132 }
0133
0134 iterator end() const { return iterator(); }
0135
0136
0137 std::size_t size() const {
0138 std::size_t result = m_localIndices[0].size();
0139 for (std::size_t i = 1; i < DIM; ++i) {
0140 result *= m_localIndices[i].size();
0141 }
0142 return result;
0143 }
0144
0145
0146 auto collect() const {
0147 boost::container::small_vector<std::size_t, ipow(3, DIM)> result;
0148 result.reserve(this->size());
0149 for (std::size_t idx : *this) {
0150 result.push_back(idx);
0151 }
0152 return result;
0153 }
0154
0155 std::vector<std::size_t> collectVector() const {
0156 auto result = collect();
0157 return {result.begin(), result.end()};
0158 }
0159
0160 private:
0161 std::array<NeighborHoodIndices, DIM> m_localIndices{};
0162 std::array<std::size_t, DIM - 1> m_globalStrides{};
0163 };
0164
0165
0166
0167
0168
0169 template <std::size_t N>
0170 struct grid_helper_impl;
0171
0172 template <std::size_t N>
0173 struct grid_helper_impl {
0174 template <class... Axes>
0175 static void getBinCenter(
0176 std::array<double, sizeof...(Axes)>& center,
0177 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0178 const std::tuple<Axes...>& axes) {
0179 center.at(N) = std::get<N>(axes).getBinCenter(localIndices.at(N));
0180 grid_helper_impl<N - 1>::getBinCenter(center, localIndices, axes);
0181 }
0182
0183 template <class... Axes>
0184 static void getGlobalBin(
0185 const std::array<std::size_t, sizeof...(Axes)>& localBins,
0186 const std::tuple<Axes...>& axes, std::size_t& bin, std::size_t& area) {
0187 const auto& thisAxis = std::get<N>(axes);
0188 bin += area * localBins.at(N);
0189
0190 area *= (thisAxis.getNBins() + 2);
0191 grid_helper_impl<N - 1>::getGlobalBin(localBins, axes, bin, area);
0192 }
0193
0194 template <class Point, class... Axes>
0195 static void getLocalBinIndices(
0196 const Point& point, const std::tuple<Axes...>& axes,
0197 std::array<std::size_t, sizeof...(Axes)>& indices) {
0198 const auto& thisAxis = std::get<N>(axes);
0199 indices.at(N) = static_cast<std::size_t>(thisAxis.getBin(point[N]));
0200 grid_helper_impl<N - 1>::getLocalBinIndices(point, axes, indices);
0201 }
0202
0203 template <class... Axes>
0204 static void getLocalBinIndices(
0205 std::size_t& bin, const std::tuple<Axes...>& axes, std::size_t& area,
0206 std::array<std::size_t, sizeof...(Axes)>& indices) {
0207 const auto& thisAxis = std::get<N>(axes);
0208
0209 std::size_t new_area = area * (thisAxis.getNBins() + 2);
0210 grid_helper_impl<N - 1>::getLocalBinIndices(bin, axes, new_area, indices);
0211 indices.at(N) = bin / area;
0212 bin %= area;
0213 }
0214
0215 template <class... Axes>
0216 static void getLowerLeftBinEdge(
0217 std::array<double, sizeof...(Axes)>& llEdge,
0218 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0219 const std::tuple<Axes...>& axes) {
0220 llEdge.at(N) = std::get<N>(axes).getBinLowerBound(localIndices.at(N));
0221 grid_helper_impl<N - 1>::getLowerLeftBinEdge(llEdge, localIndices, axes);
0222 }
0223
0224 template <class... Axes>
0225 static void getLowerLeftBinIndices(
0226 std::array<std::size_t, sizeof...(Axes)>& localIndices,
0227 const std::tuple<Axes...>& axes) {
0228 localIndices.at(N) = std::get<N>(axes).wrapBin(localIndices.at(N) - 1);
0229 grid_helper_impl<N - 1>::getLowerLeftBinIndices(localIndices, axes);
0230 }
0231
0232 template <class... Axes>
0233 static void getNBins(const std::tuple<Axes...>& axes,
0234 std::array<std::size_t, sizeof...(Axes)>& nBinsArray) {
0235
0236 nBinsArray[N] = std::get<N>(axes).getNBins();
0237 grid_helper_impl<N - 1>::getNBins(axes, nBinsArray);
0238 }
0239
0240 template <class... Axes>
0241 static void getAxes(const std::tuple<Axes...>& axes,
0242 std::array<const IAxis*, sizeof...(Axes)>& axesArr) {
0243 axesArr[N] = static_cast<const IAxis*>(&std::get<N>(axes));
0244 grid_helper_impl<N - 1>::getAxes(axes, axesArr);
0245 }
0246
0247 template <class... Axes>
0248 static void getUpperRightBinEdge(
0249 std::array<double, sizeof...(Axes)>& urEdge,
0250 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0251 const std::tuple<Axes...>& axes) {
0252 urEdge.at(N) = std::get<N>(axes).getBinUpperBound(localIndices.at(N));
0253 grid_helper_impl<N - 1>::getUpperRightBinEdge(urEdge, localIndices, axes);
0254 }
0255
0256 template <class... Axes>
0257 static void getUpperRightBinIndices(
0258 std::array<std::size_t, sizeof...(Axes)>& localIndices,
0259 const std::tuple<Axes...>& axes) {
0260 localIndices.at(N) = std::get<N>(axes).wrapBin(localIndices.at(N) + 1);
0261 grid_helper_impl<N - 1>::getUpperRightBinIndices(localIndices, axes);
0262 }
0263
0264 template <class... Axes>
0265 static void getMin(const std::tuple<Axes...>& axes,
0266 std::array<double, sizeof...(Axes)>& minArray) {
0267 minArray[N] = std::get<N>(axes).getMin();
0268 grid_helper_impl<N - 1>::getMin(axes, minArray);
0269 }
0270
0271 template <class... Axes>
0272 static void getMax(const std::tuple<Axes...>& axes,
0273 std::array<double, sizeof...(Axes)>& maxArray) {
0274 maxArray[N] = std::get<N>(axes).getMax();
0275 grid_helper_impl<N - 1>::getMax(axes, maxArray);
0276 }
0277
0278 template <class... Axes>
0279 static void getWidth(const std::tuple<Axes...>& axes,
0280 std::array<double, sizeof...(Axes)>& widthArray) {
0281 widthArray[N] = std::get<N>(axes).getBinWidth();
0282 grid_helper_impl<N - 1>::getWidth(axes, widthArray);
0283 }
0284
0285 template <class Point, class... Axes>
0286 static bool isInside(const Point& position, const std::tuple<Axes...>& axes) {
0287 bool insideThisAxis = std::get<N>(axes).isInside(position[N]);
0288 return insideThisAxis && grid_helper_impl<N - 1>::isInside(position, axes);
0289 }
0290
0291 template <class... Axes>
0292 static void neighborHoodIndices(
0293 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0294 std::pair<int, int> sizes, const std::tuple<Axes...>& axes,
0295 std::array<NeighborHoodIndices, sizeof...(Axes)>& neighborIndices) {
0296
0297 std::size_t locIdx = localIndices.at(N);
0298 NeighborHoodIndices locNeighbors =
0299 std::get<N>(axes).neighborHoodIndices(locIdx, sizes);
0300 neighborIndices.at(N) = locNeighbors;
0301
0302 grid_helper_impl<N - 1>::neighborHoodIndices(localIndices, sizes, axes,
0303 neighborIndices);
0304 }
0305
0306 template <class... Axes>
0307 static void neighborHoodIndices(
0308 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0309 std::array<std::pair<int, int>, sizeof...(Axes)> sizes,
0310 const std::tuple<Axes...>& axes,
0311 std::array<NeighborHoodIndices, sizeof...(Axes)>& neighborIndices) {
0312
0313 std::size_t locIdx = localIndices.at(N);
0314 NeighborHoodIndices locNeighbors =
0315 std::get<N>(axes).neighborHoodIndices(locIdx, sizes.at(N));
0316 neighborIndices.at(N) = locNeighbors;
0317
0318 grid_helper_impl<N - 1>::neighborHoodIndices(localIndices, sizes, axes,
0319 neighborIndices);
0320 }
0321
0322 template <class... Axes>
0323 static void exteriorBinIndices(std::array<std::size_t, sizeof...(Axes)>& idx,
0324 std::array<bool, sizeof...(Axes)> isExterior,
0325 std::set<std::size_t>& combinations,
0326 const std::tuple<Axes...>& axes) {
0327
0328 for (std::size_t i = 0; i < std::get<N>(axes).getNBins() + 2; ++i) {
0329 idx.at(N) = i;
0330 isExterior.at(N) = (i == 0) || (i == std::get<N>(axes).getNBins() + 1);
0331
0332 grid_helper_impl<N - 1>::exteriorBinIndices(idx, isExterior, combinations,
0333 axes);
0334 }
0335 }
0336 };
0337
0338 template <>
0339 struct grid_helper_impl<0u> {
0340 template <class... Axes>
0341 static void getBinCenter(
0342 std::array<double, sizeof...(Axes)>& center,
0343 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0344 const std::tuple<Axes...>& axes) {
0345 center.at(0u) = std::get<0u>(axes).getBinCenter(localIndices.at(0u));
0346 }
0347
0348 template <class... Axes>
0349 static void getGlobalBin(
0350 const std::array<std::size_t, sizeof...(Axes)>& localBins,
0351 const std::tuple<Axes...>& , std::size_t& bin,
0352 std::size_t& area) {
0353 bin += area * localBins.at(0u);
0354 }
0355
0356 template <class Point, class... Axes>
0357 static void getLocalBinIndices(
0358 const Point& point, const std::tuple<Axes...>& axes,
0359 std::array<std::size_t, sizeof...(Axes)>& indices) {
0360 const auto& thisAxis = std::get<0u>(axes);
0361 indices.at(0u) = thisAxis.getBin(point[0u]);
0362 }
0363
0364 template <class... Axes>
0365 static void getLocalBinIndices(
0366 std::size_t& bin, const std::tuple<Axes...>& , std::size_t& area,
0367 std::array<std::size_t, sizeof...(Axes)>& indices) {
0368
0369 indices.at(0u) = bin / area;
0370 bin %= area;
0371 }
0372
0373 template <class... Axes>
0374 static void getLowerLeftBinEdge(
0375 std::array<double, sizeof...(Axes)>& llEdge,
0376 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0377 const std::tuple<Axes...>& axes) {
0378 llEdge.at(0u) = std::get<0u>(axes).getBinLowerBound(localIndices.at(0u));
0379 }
0380
0381 template <class... Axes>
0382 static void getLowerLeftBinIndices(
0383 std::array<std::size_t, sizeof...(Axes)>& localIndices,
0384 const std::tuple<Axes...>& axes) {
0385 localIndices.at(0u) = std::get<0u>(axes).wrapBin(localIndices.at(0u) - 1);
0386 }
0387
0388 template <class... Axes>
0389 static void getNBins(const std::tuple<Axes...>& axes,
0390 std::array<std::size_t, sizeof...(Axes)>& nBinsArray) {
0391
0392 nBinsArray[0u] = std::get<0u>(axes).getNBins();
0393 }
0394
0395 template <class... Axes>
0396 static void getAxes(const std::tuple<Axes...>& axes,
0397 std::array<const IAxis*, sizeof...(Axes)>& axesArr) {
0398 axesArr[0u] = static_cast<const IAxis*>(&std::get<0u>(axes));
0399 }
0400
0401 template <class... Axes>
0402 static void getUpperRightBinEdge(
0403 std::array<double, sizeof...(Axes)>& urEdge,
0404 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0405 const std::tuple<Axes...>& axes) {
0406 urEdge.at(0u) = std::get<0u>(axes).getBinUpperBound(localIndices.at(0u));
0407 }
0408
0409 template <class... Axes>
0410 static void getUpperRightBinIndices(
0411 std::array<std::size_t, sizeof...(Axes)>& localIndices,
0412 const std::tuple<Axes...>& axes) {
0413 localIndices.at(0u) = std::get<0u>(axes).wrapBin(localIndices.at(0u) + 1);
0414 }
0415
0416 template <class... Axes>
0417 static void getMin(const std::tuple<Axes...>& axes,
0418 std::array<double, sizeof...(Axes)>& minArray) {
0419 minArray[0u] = std::get<0u>(axes).getMin();
0420 }
0421
0422 template <class... Axes>
0423 static void getMax(const std::tuple<Axes...>& axes,
0424 std::array<double, sizeof...(Axes)>& maxArray) {
0425 maxArray[0u] = std::get<0u>(axes).getMax();
0426 }
0427
0428 template <class... Axes>
0429 static void getWidth(const std::tuple<Axes...>& axes,
0430 std::array<double, sizeof...(Axes)>& widthArray) {
0431 widthArray[0u] = std::get<0u>(axes).getBinWidth();
0432 }
0433
0434 template <class Point, class... Axes>
0435 static bool isInside(const Point& position, const std::tuple<Axes...>& axes) {
0436 return std::get<0u>(axes).isInside(position[0u]);
0437 }
0438
0439 template <class... Axes>
0440 static void neighborHoodIndices(
0441 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0442 std::pair<int, int> sizes, const std::tuple<Axes...>& axes,
0443 std::array<NeighborHoodIndices, sizeof...(Axes)>& neighborIndices) {
0444
0445 std::size_t locIdx = localIndices.at(0u);
0446 NeighborHoodIndices locNeighbors =
0447 std::get<0u>(axes).neighborHoodIndices(locIdx, sizes);
0448 neighborIndices.at(0u) = locNeighbors;
0449 }
0450
0451 template <class... Axes>
0452 static void neighborHoodIndices(
0453 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0454 std::array<std::pair<int, int>, sizeof...(Axes)> sizes,
0455 const std::tuple<Axes...>& axes,
0456 std::array<NeighborHoodIndices, sizeof...(Axes)>& neighborIndices) {
0457
0458 std::size_t locIdx = localIndices.at(0u);
0459 NeighborHoodIndices locNeighbors =
0460 std::get<0u>(axes).neighborHoodIndices(locIdx, sizes.at(0u));
0461 neighborIndices.at(0u) = locNeighbors;
0462 }
0463
0464 template <class... Axes>
0465 static void exteriorBinIndices(std::array<std::size_t, sizeof...(Axes)>& idx,
0466 std::array<bool, sizeof...(Axes)> isExterior,
0467 std::set<std::size_t>& combinations,
0468 const std::tuple<Axes...>& axes) {
0469
0470 auto recordExteriorBin = [&](std::size_t i) {
0471 idx.at(0u) = i;
0472
0473 std::size_t bin = 0, area = 1;
0474 grid_helper_impl<sizeof...(Axes) - 1>::getGlobalBin(idx, axes, bin, area);
0475 combinations.insert(bin);
0476 };
0477
0478
0479 for (std::size_t i :
0480 {static_cast<std::size_t>(0), std::get<0u>(axes).getNBins() + 1}) {
0481 recordExteriorBin(i);
0482 }
0483
0484
0485 bool otherAxisExterior = false;
0486 for (std::size_t N = 1; N < sizeof...(Axes); ++N) {
0487 otherAxisExterior = otherAxisExterior | isExterior[N];
0488 }
0489 if (!otherAxisExterior) {
0490 return;
0491 }
0492
0493
0494 for (std::size_t i = 1; i <= std::get<0u>(axes).getNBins(); ++i) {
0495 recordExteriorBin(i);
0496 }
0497 }
0498 };
0499
0500
0501
0502 struct grid_helper {
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514 template <class... Axes>
0515 static GlobalNeighborHoodIndices<sizeof...(Axes)> closestPointsIndices(
0516 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0517 const std::tuple<Axes...>& axes) {
0518
0519 return neighborHoodIndices(localIndices, std::make_pair(0, 1), axes);
0520 }
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531 template <class... Axes>
0532 static std::array<double, sizeof...(Axes)> getBinCenter(
0533 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0534 const std::tuple<Axes...>& axes) {
0535 std::array<double, sizeof...(Axes)> center{};
0536 grid_helper_impl<sizeof...(Axes) - 1>::getBinCenter(center, localIndices,
0537 axes);
0538
0539 return center;
0540 }
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552 template <class... Axes>
0553 static std::size_t getGlobalBin(
0554 const std::array<std::size_t, sizeof...(Axes)>& localBins,
0555 const std::tuple<Axes...>& axes) {
0556 std::size_t area = 1;
0557 std::size_t bin = 0;
0558
0559 grid_helper_impl<sizeof...(Axes) - 1>::getGlobalBin(localBins, axes, bin,
0560 area);
0561
0562 return bin;
0563 }
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579 template <class Point, class... Axes>
0580 static std::array<std::size_t, sizeof...(Axes)> getLocalBinIndices(
0581 const Point& point, const std::tuple<Axes...>& axes) {
0582 std::array<std::size_t, sizeof...(Axes)> indices{};
0583
0584 grid_helper_impl<sizeof...(Axes) - 1>::getLocalBinIndices(point, axes,
0585 indices);
0586
0587 return indices;
0588 }
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600 template <class... Axes>
0601 static std::array<std::size_t, sizeof...(Axes)> getLocalBinIndices(
0602 std::size_t bin, const std::tuple<Axes...>& axes) {
0603 std::size_t area = 1;
0604 std::array<std::size_t, sizeof...(Axes)> indices{};
0605
0606 grid_helper_impl<sizeof...(Axes) - 1>::getLocalBinIndices(bin, axes, area,
0607 indices);
0608
0609 return indices;
0610 }
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621 template <class... Axes>
0622 static std::array<double, sizeof...(Axes)> getLowerLeftBinEdge(
0623 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0624 const std::tuple<Axes...>& axes) {
0625 std::array<double, sizeof...(Axes)> llEdge{};
0626 grid_helper_impl<sizeof...(Axes) - 1>::getLowerLeftBinEdge(
0627 llEdge, localIndices, axes);
0628
0629 return llEdge;
0630 }
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645 template <class... Axes>
0646 static std::array<std::size_t, sizeof...(Axes)> getLowerLeftBinIndices(
0647 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0648 const std::tuple<Axes...>& axes) {
0649 auto llIndices = localIndices;
0650 grid_helper_impl<sizeof...(Axes) - 1>::getLowerLeftBinIndices(llIndices,
0651 axes);
0652
0653 return llIndices;
0654 }
0655
0656
0657
0658
0659
0660
0661
0662
0663
0664 template <class... Axes>
0665 static std::array<std::size_t, sizeof...(Axes)> getNBins(
0666 const std::tuple<Axes...>& axes) {
0667 std::array<std::size_t, sizeof...(Axes)> nBinsArray{};
0668 grid_helper_impl<sizeof...(Axes) - 1>::getNBins(axes, nBinsArray);
0669 return nBinsArray;
0670 }
0671
0672
0673
0674
0675
0676
0677
0678 template <class... Axes>
0679 static std::array<const IAxis*, sizeof...(Axes)> getAxes(
0680 const std::tuple<Axes...>& axes) {
0681 std::array<const IAxis*, sizeof...(Axes)> arr{};
0682 grid_helper_impl<sizeof...(Axes) - 1>::getAxes(axes, arr);
0683 return arr;
0684 }
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695 template <class... Axes>
0696 static std::array<double, sizeof...(Axes)> getUpperRightBinEdge(
0697 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0698 const std::tuple<Axes...>& axes) {
0699 std::array<double, sizeof...(Axes)> urEdge{};
0700 grid_helper_impl<sizeof...(Axes) - 1>::getUpperRightBinEdge(
0701 urEdge, localIndices, axes);
0702
0703 return urEdge;
0704 }
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719 template <class... Axes>
0720 static std::array<std::size_t, sizeof...(Axes)> getUpperRightBinIndices(
0721 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0722 const std::tuple<Axes...>& axes) {
0723 auto urIndices = localIndices;
0724 grid_helper_impl<sizeof...(Axes) - 1>::getUpperRightBinIndices(urIndices,
0725 axes);
0726
0727 return urIndices;
0728 }
0729
0730
0731
0732
0733
0734
0735 template <class... Axes>
0736 static std::array<double, sizeof...(Axes)> getMin(
0737 const std::tuple<Axes...>& axes) {
0738 std::array<double, sizeof...(Axes)> minArray{};
0739 grid_helper_impl<sizeof...(Axes) - 1>::getMin(axes, minArray);
0740 return minArray;
0741 }
0742
0743
0744
0745
0746
0747
0748 template <class... Axes>
0749 static std::array<double, sizeof...(Axes)> getMax(
0750 const std::tuple<Axes...>& axes) {
0751 std::array<double, sizeof...(Axes)> maxArray{};
0752 grid_helper_impl<sizeof...(Axes) - 1>::getMax(axes, maxArray);
0753 return maxArray;
0754 }
0755
0756
0757
0758
0759
0760
0761 template <class... Axes>
0762 static std::array<double, sizeof...(Axes)> getWidth(
0763 const std::tuple<Axes...>& axes) {
0764 std::array<double, sizeof...(Axes)> widthArray{};
0765 grid_helper_impl<sizeof...(Axes) - 1>::getWidth(axes, widthArray);
0766 return widthArray;
0767 }
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789 template <class... Axes>
0790 static GlobalNeighborHoodIndices<sizeof...(Axes)> neighborHoodIndices(
0791 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0792 std::pair<std::size_t, std::size_t> sizes,
0793 const std::tuple<Axes...>& axes) {
0794
0795 std::array<NeighborHoodIndices, sizeof...(Axes)> neighborIndices{};
0796
0797 grid_helper_impl<sizeof...(Axes) - 1>::neighborHoodIndices(
0798 localIndices, sizes, axes, neighborIndices);
0799
0800
0801 std::array<std::size_t, sizeof...(Axes)> nBinsArray = getNBins(axes);
0802
0803
0804 return GlobalNeighborHoodIndices(neighborIndices, nBinsArray);
0805 }
0806
0807 template <class... Axes>
0808 static GlobalNeighborHoodIndices<sizeof...(Axes)> neighborHoodIndices(
0809 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0810 std::size_t size, const std::tuple<Axes...>& axes) {
0811 return neighborHoodIndices(
0812 localIndices, std::make_pair(-static_cast<int>(size), size), axes);
0813 }
0814
0815
0816
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836 template <class... Axes>
0837 static GlobalNeighborHoodIndices<sizeof...(Axes)> neighborHoodIndices(
0838 const std::array<std::size_t, sizeof...(Axes)>& localIndices,
0839 std::array<std::pair<int, int>, sizeof...(Axes)>& sizes,
0840 const std::tuple<Axes...>& axes) {
0841
0842 std::array<NeighborHoodIndices, sizeof...(Axes)> neighborIndices{};
0843
0844 grid_helper_impl<sizeof...(Axes) - 1>::neighborHoodIndices(
0845 localIndices, sizes, axes, neighborIndices);
0846
0847
0848 std::array<std::size_t, sizeof...(Axes)> nBinsArray = getNBins(axes);
0849
0850
0851 return GlobalNeighborHoodIndices(neighborIndices, nBinsArray);
0852 }
0853
0854
0855
0856
0857
0858
0859 template <class... Axes>
0860 static std::set<std::size_t> exteriorBinIndices(
0861 const std::tuple<Axes...>& axes) {
0862 std::array<std::size_t, sizeof...(Axes)> idx{};
0863 std::array<bool, sizeof...(Axes)> isExterior{};
0864 std::set<std::size_t> combinations;
0865 grid_helper_impl<sizeof...(Axes) - 1>::exteriorBinIndices(
0866 idx, isExterior, combinations, axes);
0867
0868 return combinations;
0869 }
0870
0871
0872
0873
0874
0875
0876
0877
0878
0879
0880
0881
0882
0883
0884 template <class Point, class... Axes>
0885 static bool isInside(const Point& position, const std::tuple<Axes...>& axes) {
0886 constexpr std::size_t MAX = sizeof...(Axes) - 1;
0887 return grid_helper_impl<MAX>::isInside(position, axes);
0888 }
0889 };
0890
0891 }