File indexing completed on 2025-01-18 09:10:52
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().setVolume(1).value() <
0136 GeometryIdentifier().setVolume(1).setBoundary(1).value(),
0137 "Incompatible GeometryIdentifier hierarchy");
0138 static_assert(GeometryIdentifier().setBoundary(1).value() <
0139 GeometryIdentifier().setBoundary(1).setLayer(1).value(),
0140 "Incompatible GeometryIdentifier hierarchy");
0141 static_assert(GeometryIdentifier().setLayer(1).value() <
0142 GeometryIdentifier().setLayer(1).setApproach(1).value(),
0143 "Incompatible GeometryIdentifier hierarchy");
0144 static_assert(GeometryIdentifier().setApproach(1).value() <
0145 GeometryIdentifier().setApproach(1).setSensitive(1).value(),
0146 "Incompatible GeometryIdentifier hierarchy");
0147
0148 using Identifier = GeometryIdentifier::Value;
0149
0150
0151 std::vector<Identifier> m_ids;
0152
0153 std::vector<Identifier> m_masks;
0154 std::vector<Value> m_values;
0155
0156
0157 static constexpr Identifier makeLeadingLevelsMask(GeometryIdentifier id) {
0158
0159 auto allSet = GeometryIdentifier(~GeometryIdentifier::Value{0u});
0160
0161 if (id.sensitive() != 0u) {
0162
0163 return allSet.setExtra(0u).value();
0164 }
0165 if (id.approach() != 0u) {
0166 return allSet.setExtra(0u).setSensitive(0u).value();
0167 }
0168 if (id.layer() != 0u) {
0169 return allSet.setExtra(0u).setSensitive(0u).setApproach(0u).value();
0170 }
0171 if (id.boundary() != 0u) {
0172 return allSet.setExtra(0u)
0173 .setSensitive(0u)
0174 .setApproach(0u)
0175 .setLayer(0u)
0176 .value();
0177 }
0178 if (id.volume() != 0u) {
0179 return allSet.setExtra(0u)
0180 .setSensitive(0u)
0181 .setApproach(0u)
0182 .setLayer(0u)
0183 .setBoundary(0u)
0184 .value();
0185 }
0186
0187 return Identifier{0u};
0188 }
0189
0190
0191 static constexpr Identifier makeHighestLevelMask() {
0192 return makeLeadingLevelsMask(GeometryIdentifier(0u).setVolume(1u));
0193 }
0194
0195
0196 static constexpr bool equalWithinMask(Identifier lhs, Identifier rhs,
0197 Identifier mask) {
0198 return (lhs & mask) == (rhs & mask);
0199 }
0200
0201
0202 static void sortAndCheckDuplicates(std::vector<InputElement>& elements);
0203
0204
0205
0206
0207
0208 void fill(const std::vector<InputElement>& elements);
0209 };
0210
0211
0212
0213 template <typename value_t>
0214 inline GeometryHierarchyMap<value_t>::GeometryHierarchyMap(
0215 std::vector<InputElement> elements) {
0216 sortAndCheckDuplicates(elements);
0217 fill(elements);
0218 }
0219
0220 template <typename value_t>
0221 inline GeometryHierarchyMap<value_t>::GeometryHierarchyMap(
0222 std::initializer_list<InputElement> elements)
0223 : GeometryHierarchyMap(
0224 std::vector<InputElement>(elements.begin(), elements.end())) {}
0225
0226 template <typename value_t>
0227 inline void GeometryHierarchyMap<value_t>::sortAndCheckDuplicates(
0228 std::vector<InputElement>& elements) {
0229
0230 std::ranges::sort(elements, [=](const auto& lhs, const auto& rhs) {
0231 return lhs.first < rhs.first;
0232 });
0233
0234
0235 auto dup = std::ranges::adjacent_find(
0236 elements,
0237 [](const auto& lhs, const auto& rhs) { return lhs.first == rhs.first; });
0238
0239 if (dup != elements.end()) {
0240 throw std::invalid_argument("Input elements contain duplicates");
0241 }
0242 }
0243
0244 template <typename value_t>
0245 inline void GeometryHierarchyMap<value_t>::fill(
0246 const std::vector<InputElement>& elements) {
0247 m_ids.clear();
0248 m_masks.clear();
0249 m_values.clear();
0250
0251 m_ids.reserve(elements.size());
0252 m_masks.reserve(elements.size());
0253 m_values.reserve(elements.size());
0254
0255 for (const auto& element : elements) {
0256 m_ids.push_back(element.first.value());
0257 m_masks.push_back(makeLeadingLevelsMask(element.first.value()));
0258 m_values.push_back(std::move(element.second));
0259 }
0260 }
0261
0262 template <typename value_t>
0263 inline auto GeometryHierarchyMap<value_t>::find(
0264 const GeometryIdentifier& id) const -> Iterator {
0265 assert((m_ids.size() == m_values.size()) &&
0266 "Inconsistent container state: #ids != # values");
0267 assert((m_masks.size() == m_values.size()) &&
0268 "Inconsistent container state: #masks != #values");
0269
0270
0271
0272
0273
0274 const auto it = std::upper_bound(m_ids.begin(), m_ids.end(), id.value());
0275 auto i = std::distance(m_ids.begin(), it);
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287 while (0 < i) {
0288
0289 --i;
0290
0291
0292
0293
0294
0295
0296 if (!equalWithinMask(id.value(), m_ids[i], makeHighestLevelMask())) {
0297
0298 if (m_ids.front() == Identifier{0u}) {
0299 return begin();
0300 } else {
0301 return end();
0302 }
0303 }
0304
0305
0306
0307
0308 if (equalWithinMask(id.value(), m_ids[i], m_masks[i])) {
0309 return std::next(begin(), i);
0310 }
0311 }
0312
0313
0314 return end();
0315 }
0316
0317 template <typename value_t>
0318 inline auto GeometryHierarchyMap<value_t>::contains(
0319 const GeometryIdentifier& id) const -> bool {
0320 return this->find(id) != this->end();
0321 }
0322
0323 }