From be1f4ae844a6b1ad8025d332594c51545ca8c6b8 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Tue, 2 Jun 2026 13:57:00 +0200 Subject: [PATCH 1/9] feat: Extract `MultiAxis` from `Grid` --- .../Acts/Geometry/SurfaceArrayCreator.hpp | 1 - Core/include/Acts/Utilities/Axis.hpp | 173 +-- Core/include/Acts/Utilities/Grid.hpp | 212 +-- Core/include/Acts/Utilities/Helpers.hpp | 5 +- Core/include/Acts/Utilities/IAxis.hpp | 13 +- Core/include/Acts/Utilities/IGrid.hpp | 118 ++ Core/include/Acts/Utilities/IMultiAxis.hpp | 349 +++++ Core/include/Acts/Utilities/MultiAxis.hpp | 116 ++ .../Acts/Utilities/NeighborHoodIndices.hpp | 122 ++ Tests/UnitTests/Core/Utilities/CMakeLists.txt | 1 + Tests/UnitTests/Core/Utilities/GridTests.cpp | 7 - .../Core/Utilities/MultiAxisTests.cpp | 1211 +++++++++++++++++ 12 files changed, 2028 insertions(+), 300 deletions(-) create mode 100644 Core/include/Acts/Utilities/IGrid.hpp create mode 100644 Core/include/Acts/Utilities/IMultiAxis.hpp create mode 100644 Core/include/Acts/Utilities/MultiAxis.hpp create mode 100644 Core/include/Acts/Utilities/NeighborHoodIndices.hpp create mode 100644 Tests/UnitTests/Core/Utilities/MultiAxisTests.cpp diff --git a/Core/include/Acts/Geometry/SurfaceArrayCreator.hpp b/Core/include/Acts/Geometry/SurfaceArrayCreator.hpp index 7ac78342408..c14a3582c4b 100644 --- a/Core/include/Acts/Geometry/SurfaceArrayCreator.hpp +++ b/Core/include/Acts/Geometry/SurfaceArrayCreator.hpp @@ -20,7 +20,6 @@ #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Logger.hpp" -#include #include #include #include diff --git a/Core/include/Acts/Utilities/Axis.hpp b/Core/include/Acts/Utilities/Axis.hpp index ed2b00dcbff..03e37efd407 100644 --- a/Core/include/Acts/Utilities/Axis.hpp +++ b/Core/include/Acts/Utilities/Axis.hpp @@ -10,123 +10,21 @@ #include "Acts/Utilities/AxisDefinitions.hpp" #include "Acts/Utilities/IAxis.hpp" +#include "Acts/Utilities/NeighborHoodIndices.hpp" #include #include +#include #include namespace Acts { -// This object can be iterated to produce up to two sequences of integer -// indices, corresponding to the half-open integer ranges [begin1, end1[ and -// [begin2, end2[. -// -// The goal is to emulate the effect of enumerating a range of neighbor -// indices on an axis (which may go out of bounds and wrap around since we -// have AxisBoundaryType::Closed), inserting them into an std::vector, and -// discarding duplicates, without paying the price of duplicate removal -// and dynamic memory allocation in hot magnetic field interpolation code. -// -/// Iterable indices for neighborhood lookups with optional wrap-around. -class NeighborHoodIndices { - public: - NeighborHoodIndices() = default; - - /// Constructor for continuous range - /// @param begin Start index - /// @param end End index (exclusive) - NeighborHoodIndices(std::size_t begin, std::size_t end) - : m_begin1(begin), m_end1(end), m_begin2(end), m_end2(end) {} - - /// Constructor for wrapped range (two segments) - /// @param begin1 Start of first segment - /// @param end1 End of first segment (exclusive) - /// @param begin2 Start of second segment - /// @param end2 End of second segment (exclusive) - NeighborHoodIndices(std::size_t begin1, std::size_t end1, std::size_t begin2, - std::size_t end2) - : m_begin1(begin1), m_end1(end1), m_begin2(begin2), m_end2(end2) {} - - /// Iterator over the neighborhood index sequence. - class iterator { - public: - iterator() = default; - - /// Constructor for end iterator - /// @param current End position - explicit iterator(std::size_t current) - : m_current(current), m_wrapped(true) {} - - /// Constructor for begin iterator - /// @param begin1 Start of first segment - /// @param end1 End of first segment - /// @param begin2 Start of second segment - iterator(std::size_t begin1, std::size_t end1, std::size_t begin2) - : m_current(begin1), - m_end1(end1), - m_begin2(begin2), - m_wrapped(begin1 == begin2) {} - - /// Dereference operator - /// @return Current index - std::size_t operator*() const { return m_current; } - - /// Pre-increment operator - /// @return Reference to this iterator - iterator& operator++() { - ++m_current; - if (m_current == m_end1) { - m_current = m_begin2; - m_wrapped = true; - } - return *this; - } - - /// Equality comparison operator - /// @param it Other iterator - /// @return True if iterators are equal - bool operator==(const iterator& it) const { - return (m_current == it.m_current) && (m_wrapped == it.m_wrapped); - } - - private: - std::size_t m_current = 0, m_end1 = 0, m_begin2 = 0; - bool m_wrapped = false; - }; - - /// Get begin iterator - /// @return Iterator to first index - iterator begin() const { return iterator(m_begin1, m_end1, m_begin2); } - - /// Get end iterator - /// @return Iterator past last index - iterator end() const { return iterator(m_end2); } - - /// Get total number of indices in the sequence - /// @return Number of indices - std::size_t size() const { return (m_end1 - m_begin1) + (m_end2 - m_begin2); } - - /// Collect all indices into a vector - /// @return Vector containing all indices - std::vector collect() const { - std::vector result; - result.reserve(this->size()); - for (std::size_t idx : *this) { - result.push_back(idx); - } - return result; - } - - private: - std::size_t m_begin1 = 0, m_end1 = 0, m_begin2 = 0, m_end2 = 0; -}; - /// @brief calculate bin indices for an equidistant binning /// /// This class provides some basic functionality for calculating bin indices /// for a given equidistant binning. template -class Axis : public IAxis { +class Axis final : public IAxis { public: /// Static type identifier for this equidistant axis specialization static constexpr AxisType type = AxisType::Equidistant; @@ -163,21 +61,21 @@ class Axis : public IAxis { /// @brief returns whether the axis is equidistant /// /// @return bool is equidistant - bool isEquidistant() const final { return true; } + bool isEquidistant() const override { return true; } /// @brief returns whether the axis is variable /// /// @return bool is variable - bool isVariable() const final { return false; } + bool isVariable() const override { return false; } /// @brief returns the type of the axis /// @return @c AxisType of this axis - AxisType getType() const final { return type; } + AxisType getType() const override { return type; } /// @brief returns the boundary type set in the template param /// /// @return @c AxisBoundaryType of this axis - AxisBoundaryType getBoundaryType() const final { return bdt; } + AxisBoundaryType getBoundaryType() const override { return bdt; } /// @brief Get #size bins which neighbor the one given /// @@ -336,7 +234,7 @@ class Axis : public IAxis { /// bin with lower bound @c l and upper bound @c u. /// @note Bin indices start at @c 1. The underflow bin has the index @c 0 /// while the index nBins + 1 indicates the overflow bin . - std::size_t getBin(double x) const final { + std::size_t getBin(double x) const override { return wrapBin( static_cast(std::floor((x - getMin()) / getBinWidth()) + 1)); } @@ -344,7 +242,7 @@ class Axis : public IAxis { /// @brief get bin width /// /// @return constant width for all bins - double getBinWidth(std::size_t /*bin*/ = 0) const { return m_width; } + double getBinWidth(std::size_t /*bin*/ = 0) const override { return m_width; } /// @brief get lower bound of bin /// @@ -356,7 +254,7 @@ class Axis : public IAxis { /// /// @note Bin intervals have a closed lower bound, i.e. the lower boundary /// belongs to the bin with the given bin index. - double getBinLowerBound(std::size_t bin) const { + double getBinLowerBound(std::size_t bin) const override { return getMin() + (bin - 1) * getBinWidth(); } @@ -370,7 +268,7 @@ class Axis : public IAxis { /// /// @note Bin intervals have an open upper bound, i.e. the upper boundary /// does @b not belong to the bin with the given bin index. - double getBinUpperBound(std::size_t bin) const { + double getBinUpperBound(std::size_t bin) const override { return getMin() + bin * getBinWidth(); } @@ -381,24 +279,24 @@ class Axis : public IAxis { /// /// @pre @c bin must be a valid bin index (excluding under-/overflow bins), /// i.e. \f$1 \le \text{bin} \le \text{nBins}\f$ - double getBinCenter(std::size_t bin) const { + double getBinCenter(std::size_t bin) const override { return getMin() + (bin - 0.5) * getBinWidth(); } /// @brief get maximum of binning range /// /// @return maximum of binning range - double getMax() const final { return m_max; } + double getMax() const override { return m_max; } /// @brief get minimum of binning range /// /// @return minimum of binning range - double getMin() const final { return m_min; } + double getMin() const override { return m_min; } /// @brief get total number of bins /// /// @return total number of bins (excluding under-/overflow bins) - std::size_t getNBins() const final { return m_bins; } + std::size_t getNBins() const override { return m_bins; } /// @brief check whether value is inside axis limits /// @param x The value to check @@ -408,11 +306,11 @@ class Axis : public IAxis { /// /// @post If @c true is returned, the bin containing the given value is a /// valid bin, i.e. it is neither the underflow nor the overflow bin. - bool isInside(double x) const { return (m_min <= x) && (x < m_max); } + bool isInside(double x) const override { return (m_min <= x) && (x < m_max); } /// @brief Return a vector of bin edges /// @return Vector which contains the bin edges - std::vector getBinEdges() const final { + std::vector getBinEdges() const override { std::vector binEdges; for (std::size_t i = 1; i <= m_bins; i++) { binEdges.push_back(getBinLowerBound(i)); @@ -430,7 +328,7 @@ class Axis : public IAxis { } protected: - void toStream(std::ostream& os) const final { os << *this; } + void toStream(std::ostream& os) const override { os << *this; } private: /// minimum of binning range @@ -448,7 +346,7 @@ class Axis : public IAxis { /// This class provides some basic functionality for calculating bin indices /// for a given binning with variable bin sizes. template -class Axis : public IAxis { +class Axis final : public IAxis { public: /// Static type identifier for this variable-width axis specialization static constexpr AxisType type = AxisType::Variable; @@ -479,21 +377,21 @@ class Axis : public IAxis { /// @brief returns whether the axis is equidistante /// /// @return bool is equidistant - bool isEquidistant() const final { return false; } + bool isEquidistant() const override { return false; } /// @brief returns whether the axis is variable /// /// @return bool is variable - bool isVariable() const final { return true; } + bool isVariable() const override { return true; } /// @brief returns the type of the axis /// @return @c AxisType of this axis - AxisType getType() const final { return type; } + AxisType getType() const override { return type; } /// @brief returns the boundary type set in the template param /// /// @return @c AxisBoundaryType of this axis - AxisBoundaryType getBoundaryType() const final { return bdt; } + AxisBoundaryType getBoundaryType() const override { return bdt; } /// @brief Get #size bins which neighbor the one given /// @@ -650,7 +548,7 @@ class Axis : public IAxis { /// bin with lower bound @c l and upper bound @c u. /// @note Bin indices start at @c 1. The underflow bin has the index @c 0 /// while the index nBins + 1 indicates the overflow bin . - std::size_t getBin(double x) const final { + std::size_t getBin(double x) const override { const auto it = std::ranges::upper_bound(m_binEdges, x); return wrapBin( static_cast(std::ranges::distance(m_binEdges.begin(), it))); @@ -663,7 +561,7 @@ class Axis : public IAxis { /// /// @pre @c bin must be a valid bin index (excluding under-/overflow bins), /// i.e. \f$1 \le \text{bin} \le \text{nBins}\f$ - double getBinWidth(std::size_t bin) const { + double getBinWidth(std::size_t bin) const override { return m_binEdges.at(bin) - m_binEdges.at(bin - 1); } @@ -677,7 +575,7 @@ class Axis : public IAxis { /// /// @note Bin intervals have a closed lower bound, i.e. the lower boundary /// belongs to the bin with the given bin index. - double getBinLowerBound(std::size_t bin) const { + double getBinLowerBound(std::size_t bin) const override { return m_binEdges.at(bin - 1); } @@ -691,7 +589,9 @@ class Axis : public IAxis { /// /// @note Bin intervals have an open upper bound, i.e. the upper boundary /// does @b not belong to the bin with the given bin index. - double getBinUpperBound(std::size_t bin) const { return m_binEdges.at(bin); } + double getBinUpperBound(std::size_t bin) const override { + return m_binEdges.at(bin); + } /// @brief get bin center /// @@ -700,24 +600,24 @@ class Axis : public IAxis { /// /// @pre @c bin must be a valid bin index (excluding under-/overflow bins), /// i.e. \f$1 \le \text{bin} \le \text{nBins}\f$ - double getBinCenter(std::size_t bin) const { + double getBinCenter(std::size_t bin) const override { return 0.5 * (getBinLowerBound(bin) + getBinUpperBound(bin)); } /// @brief get maximum of binning range /// /// @return maximum of binning range - double getMax() const final { return m_binEdges.back(); } + double getMax() const override { return m_binEdges.back(); } /// @brief get minimum of binning range /// /// @return minimum of binning range - double getMin() const final { return m_binEdges.front(); } + double getMin() const override { return m_binEdges.front(); } /// @brief get total number of bins /// /// @return total number of bins (excluding under-/overflow bins) - std::size_t getNBins() const final { return m_binEdges.size() - 1; } + std::size_t getNBins() const override { return m_binEdges.size() - 1; } /// @brief check whether value is inside axis limits /// @param x The value to check @@ -727,13 +627,13 @@ class Axis : public IAxis { /// /// @post If @c true is returned, the bin containing the given value is a /// valid bin, i.e. it is neither the underflow nor the overflow bin. - bool isInside(double x) const { + bool isInside(double x) const override { return (m_binEdges.front() <= x) && (x < m_binEdges.back()); } /// @brief Return a vector of bin edges /// @return Vector which contains the bin edges - std::vector getBinEdges() const final { return m_binEdges; } + std::vector getBinEdges() const override { return m_binEdges; } friend std::ostream& operator<<(std::ostream& os, const Axis& axis) { os << "Axis("; @@ -746,10 +646,11 @@ class Axis : public IAxis { } protected: - void toStream(std::ostream& os) const final { os << *this; } + void toStream(std::ostream& os) const override { os << *this; } private: /// vector of bin edges (sorted in ascending order) std::vector m_binEdges; }; + } // namespace Acts diff --git a/Core/include/Acts/Utilities/Grid.hpp b/Core/include/Acts/Utilities/Grid.hpp index d9f3af4530c..f371f646087 100644 --- a/Core/include/Acts/Utilities/Grid.hpp +++ b/Core/include/Acts/Utilities/Grid.hpp @@ -10,7 +10,9 @@ #include "Acts/Utilities/GridIterator.hpp" #include "Acts/Utilities/IAxis.hpp" +#include "Acts/Utilities/IGrid.hpp" #include "Acts/Utilities/Interpolation.hpp" +#include "Acts/Utilities/MultiAxis.hpp" #include "Acts/Utilities/TypeTag.hpp" #include "Acts/Utilities/detail/grid_helper.hpp" #include "Acts/Utilities/detail/interpolation_impl.hpp" @@ -28,103 +30,6 @@ namespace Acts { -namespace detail { - -template -class AnyGridView; -template -class AnyGridConstView; - -} // namespace detail - -/// Base class for all grid types -class IGrid { - public: - virtual ~IGrid() = default; - - /// Get a dynamically sized vector of axis objects for inspection - /// @return a vector of axis pointers - virtual boost::container::small_vector axes() const = 0; - - /// @brief Get the number of dimensions of the grid - /// @return The number of dimensions of the grid - virtual std::size_t dimensions() const = 0; - - /// @brief Get the type of the values stored in the grid - /// @return The type of the values stored in the grid - virtual std::type_info const& valueType() const = 0; - - /// Type-erased interface to access the contents of the grid - /// - /// @note This interface has non-negligible runtime overhead due to packing - /// and unpacking from/to @c std::any and the dynamically sized index and - /// point types. **USE WITH CARE!** - /// - /// @{ - using AnyIndexType = boost::container::small_vector; - /// Type alias for dynamic point type (coordinates as vector of doubles) - using AnyPointType = boost::container::small_vector; - - /// @brief Get the lower left edge of a bin for a given set of indices - /// @param indices The indices to get the lower left edge of the bin for - /// @return The lower left edge of the bin - virtual AnyPointType lowerLeftBinEdgeAny(AnyIndexType indices) const = 0; - - /// @brief Get the upper right edge of a bin for a given set of indices - /// @param indices The indices to get the upper right edge of the bin for - /// @return The upper right edge of the bin - virtual AnyPointType upperRightBinEdgeAny(AnyIndexType indices) const = 0; - - /// @brief Get the center of a bin for a given set of indices - /// @param indices The indices to get the center of the bin for - /// @return The center of the bin - virtual AnyPointType binCenterAny(AnyIndexType indices) const = 0; - - /// @brief Get the number of local bins for a given set of indices - /// @return The number of local bins - virtual AnyIndexType numLocalBinsAny() const = 0; - - /// @} - - /// Helper to print out the grid - /// @param os the output stream - /// @param grid the grid to print - /// @return the output stream - friend std::ostream& operator<<(std::ostream& os, const IGrid& grid) { - grid.toStream(os); - return os; - } - - friend bool operator==(const IGrid& lhs, const IGrid& rhs) { - auto lhsAxes = lhs.axes(); - auto rhsAxes = rhs.axes(); - return lhsAxes.size() == rhsAxes.size() && - std::equal(lhsAxes.begin(), lhsAxes.end(), rhsAxes.begin(), - [](const IAxis* a, const IAxis* b) { return *a == *b; }); - } - - protected: - /// @param os Output stream to write grid representation to - virtual void toStream(std::ostream& os) const = 0; - - /// @brief Get the value of a bin for a given set of indices - /// @param indices The indices to get the value of the bin for - /// @return The value of the bin: the @c std::any contains a const pointer to - /// the value - virtual std::any atLocalBinsAny(AnyIndexType indices) const = 0; - - /// @brief Get the value of a bin for a given set of indices - /// @param indices The indices to get the value of the bin for - /// @return The value of the bin: the @c std::any contains a pointer to the - /// value - virtual std::any atLocalBinsAny(AnyIndexType indices) = 0; - - template - friend class AnyGridView; - template - friend class AnyGridConstView; -}; - /// @brief class for describing a regular multi-dimensional grid /// /// @tparam T type of values stored inside the bins of the grid @@ -144,6 +49,8 @@ class Grid final : public IGrid { /// number of dimensions of the grid static constexpr std::size_t DIM = sizeof...(Axes); + /// multi axis type + using multi_axis_t = MultiAxis; /// type of values stored using value_type = T; /// reference type to values stored @@ -200,6 +107,34 @@ class Grid final : public IGrid { m_values.resize(size()); } + /// @brief Constructor from const axis tuple, this will allow + /// creating a grid with a different value type from a template + /// grid object. + /// + /// @param axes + explicit Grid(const multi_axis_t& axes) : m_axes(axes) { + m_values.resize(size()); + } + + /// @brief Move constructor from axis tuple + /// @param axes + explicit Grid(multi_axis_t&& axes) : m_axes(std::move(axes)) { + m_values.resize(size()); + } + + /// @brief constructor from parameters pack of axes and type tag + /// @param axes + explicit Grid(TypeTag /*tag*/, const multi_axis_t& axes) : m_axes(axes) { + m_values.resize(size()); + } + + /// @brief constructor from parameters pack of axes and type tag + /// @param axes + explicit Grid(TypeTag /*tag*/, multi_axis_t&& axes) + : m_axes(std::move(axes)) { + m_values.resize(size()); + } + // Grid(TypeTag /*tag*/, Axes&... axes) = delete; /// @brief access value stored in bin for a given point @@ -321,7 +256,7 @@ class Grid final : public IGrid { /// @pre All local bin indices must be a valid index for the corresponding /// axis (excluding the under-/overflow bins for each axis). point_t binCenter(const index_t& localBins) const { - return detail::grid_helper::getBinCenter(localBins, m_axes); + return m_axes.getBinCenter(localBins); } AnyPointType binCenterAny(AnyIndexType indices) const override { @@ -352,7 +287,7 @@ class Grid final : public IGrid { /// @pre All local bin indices must be a valid index for the corresponding /// axis (including the under-/overflow bin for this axis). std::size_t globalBinFromLocalBins(const index_t& localBins) const { - return detail::grid_helper::getGlobalBin(localBins, m_axes); + return m_axes.getFlatIndexFromMultiIndex(localBins); } /// @brief determine global bin index of the bin with the lower left edge @@ -386,7 +321,8 @@ class Grid final : public IGrid { /// @note This could be a under-/overflow bin along one or more axes. template index_t localBinsFromPosition(const Point& point) const { - return detail::grid_helper::getLocalBinIndices(point, m_axes); + return detail::grid_helper::getLocalBinIndices(point, + m_axes.getAxesTuple()); } /// @brief determine local bin index for each axis from global bin index @@ -398,7 +334,7 @@ class Grid final : public IGrid { /// @note Local bin indices can contain under-/overflow bins along the /// corresponding axis. index_t localBinsFromGlobalBin(std::size_t bin) const { - return detail::grid_helper::getLocalBinIndices(bin, m_axes); + return m_axes.getMultiIndexFromFlatIndex(bin); } /// @brief determine local bin index of the bin with the lower left edge @@ -417,11 +353,12 @@ class Grid final : public IGrid { template index_t localBinsFromLowerLeftEdge(const Point& point) const { Point shiftedPoint; - point_t width = detail::grid_helper::getWidth(m_axes); + point_t width = detail::grid_helper::getWidth(m_axes.getAxesTuple()); for (std::size_t i = 0; i < DIM; i++) { shiftedPoint[i] = point[i] + width[i] / 2; } - return detail::grid_helper::getLocalBinIndices(shiftedPoint, m_axes); + return detail::grid_helper::getLocalBinIndices(shiftedPoint, + m_axes.getAxesTuple()); } /// @brief retrieve lower-left bin edge from set of local bin indices @@ -432,7 +369,7 @@ class Grid final : public IGrid { /// @pre @c localBins must only contain valid bin indices (excluding /// underflow bins). point_t lowerLeftBinEdge(const index_t& localBins) const { - return detail::grid_helper::getLowerLeftBinEdge(localBins, m_axes); + return m_axes.getLowerLeftBinCorner(localBins); } /// @copydoc Acts::IGrid::lowerLeftBinEdgeAny @@ -448,7 +385,7 @@ class Grid final : public IGrid { /// @pre @c localBins must only contain valid bin indices (excluding /// overflow bins). point_t upperRightBinEdge(const index_t& localBins) const { - return detail::grid_helper::getUpperRightBinEdge(localBins, m_axes); + return m_axes.getUpperRightBinCorner(localBins); } /// @copydoc Acts::IGrid::upperRightBinEdgeAny @@ -459,14 +396,16 @@ class Grid final : public IGrid { /// @brief get bin width along each specific axis /// /// @return array giving the bin width alonf all axes - point_t binWidth() const { return detail::grid_helper::getWidth(m_axes); } + point_t binWidth() const { + return detail::grid_helper::getWidth(m_axes.getAxesTuple()); + } /// @brief get number of bins along each specific axis /// /// @return array giving the number of bins along all axes /// /// @note Not including under- and overflow bins - index_t numLocalBins() const { return detail::grid_helper::getNBins(m_axes); } + index_t numLocalBins() const { return m_axes.getNBins(); } /// @copydoc Acts::IGrid::numLocalBinsAny AnyIndexType numLocalBinsAny() const override { @@ -476,12 +415,12 @@ class Grid final : public IGrid { /// @brief get the minimum value of all axes of one grid /// /// @return array returning the minima of all given axes - point_t minPosition() const { return detail::grid_helper::getMin(m_axes); } + point_t minPosition() const { return m_axes.getMinPoint(); } /// @brief get the maximum value of all axes of one grid /// /// @return array returning the maxima of all given axes - point_t maxPosition() const { return detail::grid_helper::getMax(m_axes); } + point_t maxPosition() const { return m_axes.getMaxPoint(); } /// @brief set all overflow and underflow bins to a certain value /// @@ -489,7 +428,8 @@ class Grid final : public IGrid { /// bin of the grid. /// void setExteriorBins(const value_type& value) { - for (std::size_t index : detail::grid_helper::exteriorBinIndices(m_axes)) { + for (std::size_t index : + detail::grid_helper::exteriorBinIndices(m_axes.getAxesTuple())) { at(index) = value; } } @@ -562,7 +502,7 @@ class Grid final : public IGrid { /// along any axis. template bool isInside(const Point& position) const { - return detail::grid_helper::isInside(position, m_axes); + return detail::grid_helper::isInside(position, m_axes.getAxesTuple()); } /// @brief get global bin indices for neighborhood @@ -582,7 +522,7 @@ class Grid final : public IGrid { /// \text{size}+1\f$ along each dimension. detail::GlobalNeighborHoodIndices neighborHoodIndices( const index_t& localBins, std::size_t size = 1u) const { - return detail::grid_helper::neighborHoodIndices(localBins, size, m_axes); + return m_axes.getNeighborHoodIndices(localBins, size); } /// @brief get global bin indices for neighborhood @@ -604,8 +544,7 @@ class Grid final : public IGrid { detail::GlobalNeighborHoodIndices neighborHoodIndices( const index_t& localBins, std::array, DIM>& sizePerAxis) const { - return detail::grid_helper::neighborHoodIndices(localBins, sizePerAxis, - m_axes); + return m_axes.getNeighborHoodIndices(localBins, sizePerAxis); } /// @brief total number of bins @@ -615,21 +554,7 @@ class Grid final : public IGrid { /// /// @note This number contains under-and overflow bins along all axes. std::size_t size(bool fullCounter = true) const { - index_t nBinsArray = numLocalBins(); - std::size_t current_size = 1; - // add under-and overflow bins for each axis and multiply all bins - if (fullCounter) { - for (const auto& value : nBinsArray) { - current_size *= value + 2; - } - } - // ignore under-and overflow bins for each axis and multiply all bins - else { - for (const auto& value : nBinsArray) { - current_size *= value; - } - } - return current_size; + return m_axes.getNTotalBins(fullCounter); } /// @brief Convenience function to convert the type of the grid @@ -669,15 +594,12 @@ class Grid final : public IGrid { /// @brief get the axes as a tuple /// @return Reference to the tuple containing all grid axes - const std::tuple& axesTuple() const { return m_axes; } + const std::tuple& axesTuple() const { return m_axes.getAxesTuple(); } /// @brief get the axes as an array of IAxis pointers /// @return Vector containing pointers to all grid axes boost::container::small_vector axes() const override { - boost::container::small_vector result; - auto axes = detail::grid_helper::getAxes(m_axes); - std::ranges::copy(axes, std::back_inserter(result)); - return result; + return m_axes.getAnyAxesVector(); } /// begin iterator for global bins @@ -712,13 +634,11 @@ class Grid final : public IGrid { } protected: - void toStream(std::ostream& os) const override { - printAxes(os, std::make_index_sequence()); - } + void toStream(std::ostream& os) const override { os << m_axes; } private: - /// set of axis defining the multi-dimensional grid - std::tuple m_axes; + /// multi axis for the grid + multi_axis_t m_axes; /// linear value store for each bin std::vector m_values; @@ -727,19 +647,7 @@ class Grid final : public IGrid { // doesn't make that much sense from an API design standpoint. detail::GlobalNeighborHoodIndices rawClosestPointsIndices( const index_t& localBins) const { - return detail::grid_helper::closestPointsIndices(localBins, m_axes); - } - - template - void printAxes(std::ostream& os, std::index_sequence /*s*/) const { - auto printOne = [&os, this]( - std::integral_constant) { - if constexpr (index > 0) { - os << ", "; - } - os << std::get(m_axes); - }; - (printOne(std::integral_constant()), ...); + return m_axes.getClosestPointsIndices(localBins); } static AnyIndexType toAnyIndexType(const index_t& indices) { diff --git a/Core/include/Acts/Utilities/Helpers.hpp b/Core/include/Acts/Utilities/Helpers.hpp index bda5c9a6adf..432e7b32242 100644 --- a/Core/include/Acts/Utilities/Helpers.hpp +++ b/Core/include/Acts/Utilities/Helpers.hpp @@ -114,7 +114,7 @@ std::array toArray(const std::vector& vecvals) { /// that is callable with @c Args template