diff --git a/Core/include/Acts/Geometry/Extent.hpp b/Core/include/Acts/Geometry/Extent.hpp index 9d650264ea3..5d22e39081a 100644 --- a/Core/include/Acts/Geometry/Extent.hpp +++ b/Core/include/Acts/Geometry/Extent.hpp @@ -13,7 +13,6 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Enumerate.hpp" -#include "Acts/Utilities/Range1D.hpp" #include "Acts/Utilities/RangeXD.hpp" #include @@ -122,17 +121,17 @@ class Extent { /// @param bValue is the binning value to be returned /// /// @return a one dimensional arrange - Range1D& range(BinningValue bValue); + auto range(BinningValue bValue) { return m_range[bValue]; } /// Return the individual 1-dimensional range /// /// @param bValue is the binning value to be returned /// /// @return a one dimensional arrange - const Range1D& range(BinningValue bValue) const; + Range1D range(BinningValue bValue) const; /// Return the N-dimension range - const RangeXD range() const; + const RangeXD& range() const; /// Return an D-dimensional sub range according to the /// the given @param binValues @@ -227,16 +226,11 @@ class Extent { std::array, binValues> m_valueHistograms; }; -inline Range1D& Acts::Extent::range(BinningValue bValue) { +inline Range1D Acts::Extent::range(BinningValue bValue) const { return m_range[bValue]; } -inline const Range1D& Acts::Extent::range( - BinningValue bValue) const { - return m_range[bValue]; -} - -inline const RangeXD Extent::range() const { +inline const RangeXD& Extent::range() const { return m_range; } diff --git a/Core/include/Acts/Utilities/DBScan.hpp b/Core/include/Acts/Utilities/DBScan.hpp index f978dde06a2..79f862ce573 100644 --- a/Core/include/Acts/Utilities/DBScan.hpp +++ b/Core/include/Acts/Utilities/DBScan.hpp @@ -159,8 +159,8 @@ class DBScan { // hypercube with a length of 2 epsilon). typename Tree::range_t range; for (std::size_t dim = 0; dim < kDims; dim++) { - range[dim] = std::make_pair(currentPoint[dim] - m_eps, - currentPoint[dim] + m_eps); + range[dim] = Range1D(currentPoint[dim] - m_eps, + currentPoint[dim] + m_eps); } // We use the KDTree to find the neighbours. // An extra cut needs to be applied to only keep the neighbours that diff --git a/Core/include/Acts/Utilities/KDTree.hpp b/Core/include/Acts/Utilities/KDTree.hpp index d78f8cf021c..ddf7e1877af 100644 --- a/Core/include/Acts/Utilities/KDTree.hpp +++ b/Core/include/Acts/Utilities/KDTree.hpp @@ -49,7 +49,7 @@ class KDTree { using value_t = Type; /// @brief The type describing a multi-dimensional orthogonal range. - using range_t = RangeXD; + using range_t = RangeXD; /// @brief The type of coordinates for points. using coordinate_t = Vector; @@ -303,7 +303,7 @@ class KDTree { range_t r; for (std::size_t j = 0; j < Dims; ++j) { - r[j] = {min_v[j], nextRepresentable(max_v[j])}; + r[j] = Range1D{min_v[j], nextRepresentable(max_v[j])}; } return r; diff --git a/Core/include/Acts/Utilities/Range1D.hpp b/Core/include/Acts/Utilities/Range1D.hpp deleted file mode 100644 index 3a9e24f7d64..00000000000 --- a/Core/include/Acts/Utilities/Range1D.hpp +++ /dev/null @@ -1,323 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2021 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include - -namespace Acts { -/// @brief A one-dimensional range between two points. -/// -/// This type describes a one-demensional range of values, designed to be used -/// in the construction of more complex multi-dimensional types. The class -/// provides functionality for growing and shrinking the range, as well as some -/// other utilities. These ranges are half-open, including the minimum but -/// excluding the maximum. -/// -/// @tparam Type The scalar type of the values contained in this range. -template -class Range1D { - public: - /// @brief Construct a new degenerate range object - /// - /// This constructor coonstructs a degenerate range object with a maximum - /// lower than the minimum. In other words, this range is empty. - Range1D() - : m_min(std::numeric_limits::lowest()), - m_max(std::numeric_limits::max()) {} - - /// @brief Construct a new range object from a lower and upper bound - /// - /// Construct a new range object given the values for the minimum and - /// maximum. Note that it is perfectly possible to construct a degenerate - /// range in this way. - /// - /// @param min The minimum value in the range (inclusive) - /// @param max The maximum value in the range (exclusive) - Range1D(Type min, Type max) : m_min(min), m_max(max) {} - - /// @brief Construct a new range object from a pair of bounds - /// - /// Construct a new range object from a pair of values, the first of which - /// is taken to be the minimum, and the second of which is taken to be the - /// maximum. - /// - /// @param p The pair of values to use as the minimum and maximum - Range1D(const std::pair& p) : m_min(p.first), m_max(p.second) {} - - /// @brief Construct a new range object from an existing range - /// - /// This simply copies the values from the existing range to the new one. - /// It's the copy constructor. - /// - /// @param o The range to copy - Range1D(const Range1D& o) : m_min(o.min()), m_max(o.max()) {} - - /// @brief Set the minimum value - /// - /// Override the minimum value of the range, regardless of what was already - /// set. - /// - /// @note If you want to shrink or expand the range, use the shrink and - /// expand methods. - /// - /// @param v The value to use as the new minimum - void setMin(const Type& v) { m_min = v; } - - /// @brief Set the maximum value - /// - /// Override the maximum value of the range, regardless of what was already - /// set. - /// - /// @note If you want to shrink or expand the range, use the shrink and - /// expand methods. - /// - /// @param v The value to use as the new maximum - void setMax(const Type& v) { m_max = v; } - - /// @brief Set the minimum and maximum value - /// - /// Override both the minimum and maximum value of the range, regardless of - /// what they were set to. - /// - /// @note If you want to shrink or expand the range, use the shrink and - /// expand methods. - /// - /// @note After this operation, the range should be exactly equal to [min, - /// max] - /// - /// @param min The new minimum value of the range - /// @param max The new maximum value of the range - void set(const Type& min, const Type& max) { - m_min = min; - m_max = max; - } - - /// @brief Shrink a range by increasing the minimum value - /// - /// Shrink the range by increasing the minimum value. If the given value is - /// smaller than the current minimum (in other words, if the proposed new - /// range would be larger than the current range), this is a no-op. - /// - /// @param v The proposed new minimum for the range - void shrinkMin(const Type& v) { m_min = std::max(m_min, v); } - - /// @brief Shrink a range by decreasing the maximum value - /// - /// Shrink the range by decreasing the maximum value. If the given value is - /// larger than the current maximum (in other words, if the proposed new - /// range would be larger than the current range), this is a no-op. - /// - /// @param v The proposed new maximum for the range - void shrinkMax(const Type& v) { m_max = std::min(m_max, v); } - - /// @brief Shrink a range on both ends - /// - /// Shrink a range by increasing the minimum value as well as decreasing the - /// maximum value. If either of the values are already smaller or larger - /// (respectively) than the proposed values, then that particular boundary of - /// the interval is not shrunk. - /// - /// @note After this operation, the range is always equal to or smaller than - /// [min, max]. - /// - /// @param min The proposed new minimum for the range - /// @param max The proposed new maximum for the range - void shrink(const Type& min, const Type& max) { - shrinkMin(min); - shrinkMax(max); - } - - /// @brief Expand a range by decreasing the minimum value - /// - /// Expand the range by decreasing the minimum value. If the given value is - /// larger than the current minimum (in other words, if the proposed new - /// range would be smaller than the current range), this is a no-op. - /// - /// @param v The proposed new minimum for the range - void expandMin(const Type& v) { m_min = std::min(m_min, v); } - - /// @brief Expand a range by increasing the maximum value - /// - /// Expand the range by increasing the maximum value. If the given value is - /// smaller than the current maximum (in other words, if the proposed new - /// range would be smaller than the current range), this is a no-op. - /// - /// @param v The proposed new maximum for the range - void expandMax(const Type& v) { m_max = std::max(m_max, v); } - - /// @brief Expand a range on both ends - /// - /// Expand a range by decreasing the minimum value as well as increasing the - /// maximum value. If either of the values are already larger or smaller - /// (respectively) than the proposed values, then that particular boundary of - /// the interval is not expanded. - /// - /// @note After this operation, the range is always equal to or larger than - /// [min, max]. - /// - /// @param min The proposed new minimum for the range - /// @param max The proposed new maximum for the range - void expand(const Type& min, const Type& max) { - expandMin(min); - expandMax(max); - } - - /// @brief Return the minimum value of the range (inclusive) - Type min(void) const { return m_min; } - - /// @brief Return the maximum value of the range (inclusive) - Type max(void) const { return m_max; } - - /// @brief Compute the size of the range - /// - /// The size of a range is defined as the difference between the minimum and - /// the maximum. For degenerate ranges, this is zero. - /// - /// @warning Due to the nature of numbers, the result of this function can be - /// somewhat ambiguous. For natural numbers, you could argue that the range - /// [n, n] has size 0 or size 1. In this case we say it has size 0. The - /// uncountable nature of the reals means this doesn't matter for them, but - /// this can be awkward when working with integers. - /// - /// @return The size of the range - Type size(void) const { - return std::max(static_cast(0), m_max - m_min); - } - - /// @brief Determine if this range is degenerate or not - /// - /// A degenerate range has a minimum higher than the maximum, and thus - /// cannot contain any values. - /// - /// @return true The range is degenerate and has size zero - /// @return false The range is not degenerate - bool degenerate(void) const { return m_min >= m_max; } - - /// @brief Determine if the range contains a given value - /// - /// A value is inside a range if and only if it is greater than the minimum - /// and smaller than the maximum. - /// - /// @param v The value to check - /// - /// @return true The value is inside the range - /// @return false The value is not inside the range - bool contains(const Type& v) const { return m_min <= v && v < m_max; } - - /// @brief Determine whether the range intersects another range - /// - /// The intersection of a range is the space where both ranges overlap. If - /// the ranges overlap at all, they are said to intersect. This operation - /// is commutative. - /// - /// @param o The other range to check - /// - /// @return true The ranges intersect - /// @return false The ranges do not intersect - bool operator&&(const Range1D& o) const { - return m_min < o.max() && o.min() < m_max; - } - - /// @brief Determine whether the range is equal to another range - /// - /// Two ranges are equal if and only if their minima and maxima are the - /// same. - /// - /// @warning This method relies on the existence of a well-defined notion - /// of equality for the underlying types. Using this method on floating - /// ranges may have unintended effecrs. - /// - /// @param o The other range to check - /// - /// @return true The ranges are equal - /// @return false The ranges are not equal - bool operator==(const Range1D& o) const { - return min() == o.min() && max() == o.max(); - } - - /// @brief Determine whether the left-hand range is a subset of the - /// right-hand range - /// - /// A range is a subset of another range if and only if all values - /// contained in the first range are also contained in the second range. - /// - /// @param o The other range to check - /// - /// @return true The left-hand range is a subset of the right-hand range - /// @return false The left-hand range is not a subset of the right-hand - /// range - bool operator<=(const Range1D& o) const { - return min() >= o.min() && max() <= o.max(); - } - - /// @brief Determine whether the left-hand range is a superset of the - /// right-hand range - /// - /// A range is a superset of another range if and only if all values - /// contained in the second range are also contained in the first range. - /// - /// @param o The other range to check - /// - /// @return true The left-hand range is a superset of thr right-hand range - /// @return false The left-hand range is not a superset of the right-hand - /// range - bool operator>=(const Range1D& o) const { - return min() <= o.min() && max() >= o.max(); - } - - /// @brief Assignment operator - /// - /// Copy the right-hand range into the left-hand range, which means setting - /// the minimum and maximum to equal the minimum and maximum of the - /// right-hand side. - /// - /// @param o The range of values to copy - /// - /// @return This range - Range1D& operator=(const Range1D& o) { - m_min = o.min(); - m_max = o.max(); - - return *this; - } - - /// @brief Compute the intersection of two ranges - /// - /// The intersection of two ranges is the range containing all values - /// contained in both ranges. If the two ranges do not intersect, the - /// intersection is a degenerate range. This operation is commutative. - /// - /// @param o The range to compute the intersection with - /// - /// @return The intersection range between the two ranges - Range1D operator&(const Range1D& o) const { - return Range1D(std::max(m_min, o.min()), std::min(m_max, o.max())); - } - - /// @brief Set the range to the intersection of itself and another range - /// - /// This is an assignment version of operator&, which updates the range on - /// which it is called to ensure that the new range is the intersection of - /// the old range and the new range. - /// - /// @param o The range to compute the intersection with - /// - /// @return This object - Range1D& operator&=(const Range1D& o) { - m_min = std::max(m_min, o.min()); - m_max = std::min(m_max, o.max()); - - return *this; - } - - private: - Type m_min, m_max; -}; -} // namespace Acts diff --git a/Core/include/Acts/Utilities/RangeXD.hpp b/Core/include/Acts/Utilities/RangeXD.hpp index 2f6acaaa56f..d614004234e 100644 --- a/Core/include/Acts/Utilities/RangeXD.hpp +++ b/Core/include/Acts/Utilities/RangeXD.hpp @@ -8,10 +8,9 @@ #pragma once -#include "Acts/Utilities/Range1D.hpp" - #include #include +#include #include #include #include @@ -29,20 +28,59 @@ namespace Acts { template typename Vector = std::array> class RangeXD { + private: + // @TODO: Replace with std::span or boost::span once available + template + struct SingleElementContainer { + Type* element; + + Type& operator[](std::size_t i) { + (void)i; + assert(i == 0); + + return *element; + } + }; + public: - /// @brief The type used to describe coordinates in our range - using coordinate_t = Vector; + RangeXD() { + for (std::size_t i = 0; i < Dims; ++i) { + min(i) = std::numeric_limits::lowest(); + max(i) = std::numeric_limits::max(); + } + } + + /// @brief Construct a range from a pair of minimum and maximum values + /// @param minima The minimum values of the range + /// @param maxima The maximum values of the range + RangeXD(Vector minima, Vector maxima) + : m_minima(minima), m_maxima(maxima) {} + + /// @brief Construct a range from a pair of single minimum and maximum values + /// @note Only available for one-dimensional ranges + /// @param minimum The minimum value of the range + /// @param maximum The maximum value of the range + template > + RangeXD(Type minimum, Type maximum) + : m_minima({minimum}), m_maxima({maximum}) {} + + /// @brief Construct a range from a pair of minimum and maximum values + /// @note Only available for one-dimensional ranges + /// @param p The pair of minimum and maximum values + template > + RangeXD(const std::pair& p) + : m_minima({p.first}), m_maxima({p.second}) {} /// @brief Determine whether this range is degenerate /// - /// A degenerate multi-dimensional range has no volume and cannot contain any - /// values. This is the case if any of its dimensions are degenerate. + /// A degenerate multi-dimensional range has no volume and cannot contain + /// any values. This is the case if any of its dimensions are degenerate. /// /// @return true The range is degenerate /// @return false The range is not degenerate - bool degenerate(void) const { + bool degenerate() const { for (std::size_t i = 0; i < Dims; ++i) { - if (m_dims[i].degenerate()) { + if (min(i) >= max(i)) { return true; } } @@ -58,9 +96,10 @@ class RangeXD { /// /// @return true The coordinate is inside the range /// @return false The coordinate is outside the range - bool contains(const coordinate_t& v) const { + template