File indexing completed on 2025-11-03 09:14:28
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 #pragma once
0010 
0011 #include "Acts/Geometry/GeometryIdentifier.hpp"
0012 
0013 #include <algorithm>
0014 #include <cassert>
0015 #include <initializer_list>
0016 #include <iterator>
0017 #include <stdexcept>
0018 #include <utility>
0019 #include <vector>
0020 
0021 namespace Acts {
0022 
0023 
0024 
0025 
0026 
0027 
0028 
0029 
0030 
0031 
0032 
0033 
0034 
0035 
0036 
0037 
0038 
0039 
0040 
0041 
0042 
0043 
0044 
0045 
0046 
0047 
0048 
0049 
0050 
0051 
0052 
0053 
0054 
0055 
0056 
0057 
0058 
0059 
0060 
0061 template <typename value_t>
0062 class GeometryHierarchyMap {
0063  public:
0064   
0065   using InputElement = typename std::pair<GeometryIdentifier, value_t>;
0066   using Iterator = typename std::vector<value_t>::const_iterator;
0067   using Value = value_t;
0068 
0069   
0070   
0071   
0072   GeometryHierarchyMap(std::vector<InputElement> elements);
0073 
0074   
0075   
0076   
0077   GeometryHierarchyMap(std::initializer_list<InputElement> elements);
0078 
0079   
0080   GeometryHierarchyMap() = default;
0081   GeometryHierarchyMap(const GeometryHierarchyMap&) = default;
0082   GeometryHierarchyMap(GeometryHierarchyMap&&) noexcept = default;
0083   ~GeometryHierarchyMap() = default;
0084   GeometryHierarchyMap& operator=(const GeometryHierarchyMap&) = default;
0085   GeometryHierarchyMap& operator=(GeometryHierarchyMap&&) noexcept = default;
0086 
0087   
0088   Iterator begin() const { return m_values.begin(); }
0089 
0090   
0091   Iterator end() const { return m_values.end(); }
0092 
0093   
0094   bool empty() const { return m_values.empty(); }
0095 
0096   
0097   std::size_t size() const { return m_values.size(); }
0098 
0099   
0100   
0101   
0102   GeometryIdentifier idAt(std::size_t index) const { return m_ids.at(index); }
0103 
0104   
0105   
0106   
0107   const Value& valueAt(std::size_t index) const { return m_values.at(index); }
0108 
0109   
0110   
0111   
0112   
0113   
0114   
0115   
0116   
0117   
0118   Iterator find(const GeometryIdentifier& id) const;
0119 
0120   
0121   
0122   
0123   
0124   
0125   
0126   
0127   
0128   
0129   bool contains(const GeometryIdentifier& id) const;
0130 
0131  private:
0132   
0133   
0134   
0135   static_assert(GeometryIdentifier().withVolume(1).value() <
0136                     GeometryIdentifier().withVolume(1).withBoundary(1).value(),
0137                 "Incompatible GeometryIdentifier hierarchy");
0138   static_assert(GeometryIdentifier().withBoundary(1).value() <
0139                     GeometryIdentifier().withBoundary(1).withLayer(1).value(),
0140                 "Incompatible GeometryIdentifier hierarchy");
0141   static_assert(GeometryIdentifier().withLayer(1).value() <
0142                     GeometryIdentifier().withLayer(1).withApproach(1).value(),
0143                 "Incompatible GeometryIdentifier hierarchy");
0144   static_assert(
0145       GeometryIdentifier().withApproach(1).value() <
0146           GeometryIdentifier().withApproach(1).withSensitive(1).value(),
0147       "Incompatible GeometryIdentifier hierarchy");
0148 
0149   using Identifier = GeometryIdentifier::Value;
0150 
0151   
0152   std::vector<Identifier> m_ids;
0153   
0154   std::vector<Identifier> m_masks;
0155   std::vector<Value> m_values;
0156 
0157   
0158   static constexpr Identifier makeLeadingLevelsMask(GeometryIdentifier id) {
0159     
0160     const auto allSet = GeometryIdentifier(~GeometryIdentifier::Value{0u});
0161     
0162     if (id.sensitive() != 0u) {
0163       
0164       return allSet.withExtra(0u).value();
0165     }
0166     if (id.approach() != 0u) {
0167       return allSet.withExtra(0u).withSensitive(0u).value();
0168     }
0169     if (id.layer() != 0u) {
0170       return allSet.withExtra(0u).withSensitive(0u).withApproach(0u).value();
0171     }
0172     if (id.boundary() != 0u) {
0173       return allSet.withExtra(0u)
0174           .withSensitive(0u)
0175           .withApproach(0u)
0176           .withLayer(0u)
0177           .value();
0178     }
0179     if (id.volume() != 0u) {
0180       return allSet.withExtra(0u)
0181           .withSensitive(0u)
0182           .withApproach(0u)
0183           .withLayer(0u)
0184           .withBoundary(0u)
0185           .value();
0186     }
0187     
0188     return Identifier{0u};
0189   }
0190 
0191   
0192   static constexpr Identifier makeHighestLevelMask() {
0193     return makeLeadingLevelsMask(GeometryIdentifier(0u).withVolume(1u));
0194   }
0195 
0196   
0197   static constexpr bool equalWithinMask(Identifier lhs, Identifier rhs,
0198                                         Identifier mask) {
0199     return (lhs & mask) == (rhs & mask);
0200   }
0201 
0202   
0203   static void sortAndCheckDuplicates(std::vector<InputElement>& elements);
0204 
0205   
0206   
0207   
0208   
0209   void fill(const std::vector<InputElement>& elements);
0210 };
0211 
0212 
0213 
0214 template <typename value_t>
0215 inline GeometryHierarchyMap<value_t>::GeometryHierarchyMap(
0216     std::vector<InputElement> elements) {
0217   sortAndCheckDuplicates(elements);
0218   fill(elements);
0219 }
0220 
0221 template <typename value_t>
0222 inline GeometryHierarchyMap<value_t>::GeometryHierarchyMap(
0223     std::initializer_list<InputElement> elements)
0224     : GeometryHierarchyMap(
0225           std::vector<InputElement>(elements.begin(), elements.end())) {}
0226 
0227 template <typename value_t>
0228 inline void GeometryHierarchyMap<value_t>::sortAndCheckDuplicates(
0229     std::vector<InputElement>& elements) {
0230   
0231   std::ranges::sort(elements, [=](const auto& lhs, const auto& rhs) {
0232     return lhs.first < rhs.first;
0233   });
0234 
0235   
0236   auto dup = std::ranges::adjacent_find(
0237       elements,
0238       [](const auto& lhs, const auto& rhs) { return lhs.first == rhs.first; });
0239 
0240   if (dup != elements.end()) {
0241     throw std::invalid_argument("Input elements contain duplicates");
0242   }
0243 }
0244 
0245 template <typename value_t>
0246 inline void GeometryHierarchyMap<value_t>::fill(
0247     const std::vector<InputElement>& elements) {
0248   m_ids.clear();
0249   m_masks.clear();
0250   m_values.clear();
0251 
0252   m_ids.reserve(elements.size());
0253   m_masks.reserve(elements.size());
0254   m_values.reserve(elements.size());
0255 
0256   for (const auto& element : elements) {
0257     m_ids.push_back(element.first.value());
0258     m_masks.push_back(makeLeadingLevelsMask(element.first.value()));
0259     m_values.push_back(std::move(element.second));
0260   }
0261 }
0262 
0263 template <typename value_t>
0264 inline auto GeometryHierarchyMap<value_t>::find(
0265     const GeometryIdentifier& id) const -> Iterator {
0266   assert((m_ids.size() == m_values.size()) &&
0267          "Inconsistent container state: #ids != # values");
0268   assert((m_masks.size() == m_values.size()) &&
0269          "Inconsistent container state: #masks != #values");
0270 
0271   
0272   
0273   
0274   
0275   const auto it = std::upper_bound(m_ids.begin(), m_ids.end(), id.value());
0276   auto i = std::distance(m_ids.begin(), it);
0277 
0278   
0279   
0280   
0281   
0282   
0283   
0284   
0285   
0286   
0287   
0288   while (0 < i) {
0289     
0290     --i;
0291 
0292     
0293     
0294     
0295     
0296     
0297     if (!equalWithinMask(id.value(), m_ids[i], makeHighestLevelMask())) {
0298       
0299       if (m_ids.front() == Identifier{0u}) {
0300         return begin();
0301       } else {
0302         return end();
0303       }
0304     }
0305 
0306     
0307     
0308     
0309     if (equalWithinMask(id.value(), m_ids[i], m_masks[i])) {
0310       return std::next(begin(), i);
0311     }
0312   }
0313 
0314   
0315   return end();
0316 }
0317 
0318 template <typename value_t>
0319 inline auto GeometryHierarchyMap<value_t>::contains(
0320     const GeometryIdentifier& id) const -> bool {
0321   return this->find(id) != this->end();
0322 }
0323 
0324 }