Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-27 07:24:04

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 // Project include(s).
0012 #include "detray/core/detail/container_views.hpp"
0013 #include "detray/definitions/detail/qualifiers.hpp"
0014 #include "detray/definitions/indexing.hpp"
0015 #include "detray/utils/invalid_values.hpp"
0016 #include "detray/utils/ranges.hpp"
0017 
0018 // System include(s)
0019 #include <algorithm>
0020 
0021 namespace detray::bins {
0022 
0023 /// @brief Bin with a single entry
0024 template <typename entry_t>
0025 class single : public detray::ranges::single_view<entry_t> {
0026   using base_type = detray::ranges::single_view<entry_t>;
0027 
0028  public:
0029   using entry_type = entry_t;
0030   using base_type::base_type;
0031   using base_type::operator=;
0032 
0033   /// Default constructor initializer the bin with an invalid value
0034   DETRAY_HOST_DEVICE constexpr single()
0035       : base_type{detail::invalid_value<entry_t>()} {}
0036 
0037   /// @returns the storage capacity of this bin
0038   DETRAY_HOST_DEVICE
0039   constexpr dindex capacity() noexcept { return 1u; }
0040 
0041   /// Add a new entry to the bin
0042   template <typename E = entry_t>
0043   DETRAY_HOST_DEVICE constexpr void push_back(E&& entry) noexcept {
0044     (*this).ref() = std::forward<E>(entry);
0045   }
0046 
0047   /// @returns an initialized bin in the backend storage
0048   DETRAY_HOST_DEVICE
0049   constexpr auto init(entry_t entry = detail::invalid_value<entry_t>())
0050       -> single& {
0051     (*this).ref() = entry;
0052     return *this;
0053   }
0054 
0055   /// Equality operator
0056   ///
0057   /// @param rhs the single view to compare with
0058   ///
0059   /// @returns true if the single value is equal
0060   DETRAY_HOST_DEVICE
0061   constexpr bool operator==(const single& rhs) const {
0062     return (*this).value() == rhs.value();
0063   }
0064 };
0065 
0066 /// @brief Bin that holds a collection of entries.
0067 ///
0068 /// Keeps an additional counter to track the number of entries per bin.
0069 /// The bin capacity is static.
0070 template <typename entry_t, std::size_t N>
0071 class static_array
0072     : public detray::ranges::view_interface<static_array<entry_t, N>> {
0073   using bin_view_t = detray::ranges::subrange<darray<entry_t, N>>;
0074   using const_bin_view_t = detray::ranges::subrange<const darray<entry_t, N>>;
0075   using bin_iterator_t = typename detray::ranges::iterator_t<bin_view_t>;
0076   using const_bin_iterator_t =
0077       typename detray::ranges::const_iterator_t<const_bin_view_t>;
0078 
0079  public:
0080   using entry_type = entry_t;
0081 
0082   /// Default constructor initializer the bin with an invalid value
0083   DETRAY_HOST_DEVICE constexpr static_array() { init(); };
0084   constexpr static_array(const static_array& other) = default;
0085   constexpr static_array(static_array&& other) noexcept = default;
0086   static_array& operator=(const static_array& other) noexcept = default;
0087 
0088   /// @returns view iterator over bin content in start or end position
0089   /// @{
0090   DETRAY_HOST_DEVICE bin_iterator_t begin() {
0091     bin_view_t bv{view()};
0092     return detray::ranges::begin(bv);
0093   }
0094   DETRAY_HOST_DEVICE bin_iterator_t end() {
0095     bin_view_t bv{view()};
0096     return detray::ranges::end(bv);
0097   }
0098   DETRAY_HOST_DEVICE
0099   const_bin_iterator_t begin() const { return detray::ranges::cbegin(view()); }
0100   DETRAY_HOST_DEVICE
0101   const_bin_iterator_t end() const { return detray::ranges::cend(view()); }
0102   /// @}
0103 
0104   /// @returns the number of entries in this bin - const
0105   DETRAY_HOST_DEVICE
0106   constexpr dindex size() const { return m_size; }
0107 
0108   /// The storage capacity of this bin
0109   DETRAY_HOST_DEVICE
0110   constexpr dindex capacity() const noexcept {
0111     return static_cast<dindex>(m_content.size());
0112   }
0113 
0114   /// Add a new entry to the bin
0115   template <typename E = entry_t>
0116   DETRAY_HOST_DEVICE constexpr void push_back(E&& entry) noexcept {
0117     m_content[m_size] = std::forward<E>(entry);
0118     ++m_size;
0119   }
0120 
0121   /// Initialize with a single entry filled
0122   ///
0123   /// @returns Access to the initialized bin
0124   DETRAY_HOST_DEVICE
0125   constexpr auto init(entry_t entry = detail::invalid_value<entry_t>())
0126       -> static_array& {
0127     // Initialize the storage element
0128     for (auto& e : m_content) {
0129       e = detail::invalid_value<entry_t>();
0130     }
0131 
0132     if (entry == detail::invalid_value<entry_t>()) {
0133       m_size = 0u;
0134       return *this;
0135     }
0136 
0137     // The bin has at least a capacity of 1
0138     m_content[0] = entry;
0139     m_size = 1u;
0140 
0141     return *this;
0142   }
0143 
0144   /// Initialize from an entire bin content @param content.
0145   ///
0146   /// @returns Access to the initialized bin
0147   DETRAY_HOST_DEVICE
0148   constexpr auto init(darray<entry_t, N> content) -> static_array& {
0149     m_content = content;
0150     m_size = 0u;
0151     for (const auto& entry : m_content) {
0152       if (entry != detail::invalid_value<entry_t>()) {
0153         ++m_size;
0154       }
0155     }
0156 
0157     return *this;
0158   }
0159 
0160   /// Equality operator
0161   ///
0162   /// @param rhs the bin entry to compare with
0163   ///
0164   /// @returns true if the content is equal
0165   DETRAY_HOST_DEVICE
0166   constexpr bool operator==(const static_array& rhs) const {
0167     return m_content == rhs.m_content;
0168   }
0169 
0170  private:
0171   /// @returns the subrange on the valid bin content - const
0172   DETRAY_HOST_DEVICE constexpr auto view() const {
0173     return const_bin_view_t{m_content, dindex_range{0u, m_size}};
0174   }
0175 
0176   /// @returns the subrange on the valid bin content
0177   DETRAY_HOST_DEVICE constexpr auto view() {
0178     return bin_view_t{m_content, dindex_range{0u, m_size}};
0179   }
0180 
0181   /// Number of valid elements in the bin
0182   dindex m_size{0u};
0183   /// Bin entry container
0184   darray<entry_t, N> m_content{};
0185 };
0186 
0187 /// @brief Bin that views a collection of entries it does not own.
0188 ///
0189 /// Used if the bin capacity is not static.
0190 template <typename entry_t>
0191 class dynamic_array
0192     : public detray::ranges::view_interface<dynamic_array<entry_t>> {
0193   using container_t = device_container_types::template vector_type<entry_t>;
0194   using bin_view_t = detray::ranges::subrange<container_t>;
0195   using const_bin_view_t = detray::ranges::subrange<const container_t>;
0196 
0197  public:
0198   struct data {
0199     dindex offset{0u};
0200     dindex size{0u};
0201     dindex capacity{0u};
0202 
0203     constexpr bool operator==(const data& rhs) const = default;
0204 
0205     DETRAY_HOST_DEVICE
0206     constexpr void update_offset(std::size_t shift) {
0207       offset += static_cast<dindex>(shift);
0208     }
0209   };
0210 
0211   using entry_type = entry_t;
0212   using entry_ptr_t = const entry_type*;
0213   using data_ptr_t = const data*;
0214 
0215   /// Default constructor initializer the bin with an invalid value
0216   DETRAY_HOST_DEVICE constexpr dynamic_array() { init(); };
0217 
0218   /// Construct from an externally owned container of bin content
0219   /// @param bin_storage and access to an offset, size and capacity
0220   /// in @param bin_data
0221   DETRAY_HOST_DEVICE
0222   dynamic_array(entry_type* bin_storage, data& bin_data)
0223       : m_data{&bin_data}, m_capacity{bin_data.capacity} {
0224     // Prevent null-dereference warning
0225     if (bin_storage) {
0226       m_global_storage = bin_storage + bin_data.offset;
0227     }
0228   }
0229 
0230   /// Construct from an externally owned container of bin content
0231   /// @param bin_storage and access to an offset, size and capacity
0232   /// in @param bin_data - const
0233   DETRAY_HOST_DEVICE
0234   dynamic_array(const entry_type* bin_storage, const data& bin_data)
0235       : m_data{&bin_data}, m_capacity{bin_data.capacity} {
0236     // Prevent null-dereference warning
0237     if (bin_storage) {
0238       m_global_storage = bin_storage + bin_data.offset;
0239     }
0240   }
0241 
0242   /// @returns view iterator over bin content in start or end position
0243   /// @{
0244   DETRAY_HOST_DEVICE auto begin() {
0245     bin_view_t bv{view()};
0246     return detray::ranges::begin(bv);
0247   }
0248   DETRAY_HOST_DEVICE auto end() {
0249     bin_view_t bv{view()};
0250     return detray::ranges::end(bv);
0251   }
0252   DETRAY_HOST_DEVICE
0253   auto begin() const { return detray::ranges::cbegin(view()); }
0254   DETRAY_HOST_DEVICE auto end() const { return detray::ranges::cend(view()); }
0255   /// @}
0256 
0257   /// @returns the number of entries in this bin - const
0258   DETRAY_HOST_DEVICE
0259   constexpr dindex size() const { return m_data->size; }
0260 
0261   /// The storage capacity of this bin
0262   DETRAY_HOST_DEVICE
0263   constexpr dindex capacity() const noexcept { return m_capacity; }
0264 
0265   /// Add a new entry to the bin
0266   /// @note This does not check the state of the container it points to!!!
0267   template <typename E = entry_type>
0268   DETRAY_HOST_DEVICE constexpr void push_back(E&& entry) {
0269     assert(m_capacity > 0);
0270     assert(m_data->size < m_capacity);
0271     assert(m_global_storage);
0272 
0273     if (m_data->size < m_capacity) {
0274       *(const_cast<entry_type*>(m_global_storage) + m_data->size) =
0275           std::forward<E>(entry);
0276       ++(const_cast<data*>(m_data)->size);
0277     }
0278   }
0279 
0280   /// @note The bin capacity has to be set correctly before calling this
0281   /// method
0282   /// @returns Access to an initialized bin in the backend storage
0283   DETRAY_HOST_DEVICE
0284   constexpr auto init(entry_type entry = detail::invalid_value<entry_type>())
0285       -> dynamic_array& {
0286     if (capacity() == 0u) {
0287       return *this;
0288     }
0289 
0290     // Initialize the storage element
0291     std::ranges::fill(this, detail::invalid_value<entry_type>());
0292 
0293     if (entry == detail::invalid_value<entry_type>()) {
0294       const_cast<data*>(m_data)->size = 0u;
0295       return *this;
0296     }
0297 
0298     // The bin has at least a capacity of 1
0299     this->front() = entry;
0300     const_cast<data*>(m_data)->size = 1u;
0301 
0302     return *this;
0303   }
0304 
0305   /// Initialize from an entire bin content @param content.
0306   ///
0307   /// @returns Access to the initialized bin
0308   template <typename storage_t>
0309   DETRAY_HOST_DEVICE constexpr auto init(const storage_t& content)
0310       -> dynamic_array& {
0311     const_cast<data*>(m_data)->size = 0u;
0312     for (dindex i{0u}; i < m_capacity; ++i) {
0313       if (content[i] != detail::invalid_value<entry_type>()) {
0314         const_cast<entry_type*>(m_global_storage)[i] = content[i];
0315         ++(const_cast<data*>(m_data)->size);
0316       }
0317     }
0318     return *this;
0319   }
0320 
0321   /// Equality operator
0322   ///
0323   /// @param rhs the bin to be compared with
0324   ///
0325   /// @returns true if the view is identical
0326   DETRAY_HOST_DEVICE
0327   constexpr bool operator==(const dynamic_array& rhs) const {
0328     // Check if the bin points to the same data
0329     if (m_data == rhs.m_data || *m_data == *rhs.m_data) {
0330       return true;
0331     }
0332     if (m_data->size != rhs.m_data->size) {
0333       return false;
0334     }
0335     // It could still point to different data, but the
0336     // content is the same
0337     auto this_view = view();
0338     auto rhs_view = rhs.view();
0339     // Loop over the size of the bin and compare
0340     for (dindex i{0u}; i < m_data->size; ++i) {
0341       if (this_view[i] != rhs_view[i]) {
0342         return false;
0343       }
0344     }
0345     return true;
0346   }
0347 
0348  private:
0349   /// @returns the subrange on the valid bin content - const
0350   DETRAY_HOST_DEVICE auto view() const {
0351     return const_bin_view_t{m_global_storage, m_global_storage + m_data->size};
0352   }
0353 
0354   /// @returns the subrange on the valid bin content
0355   DETRAY_HOST_DEVICE auto view() {
0356     return bin_view_t{const_cast<entry_type*>(m_global_storage),
0357                       const_cast<entry_type*>(m_global_storage) + m_data->size};
0358   }
0359 
0360   /// Pointer to the global bin storage that is not owned by this class
0361   /// Includes the offset when part of a larger collection
0362   entry_ptr_t m_global_storage{nullptr};
0363   /// Access to bin data in the global storage
0364   data_ptr_t m_data{nullptr};
0365   /// Current bin capacity
0366   dindex m_capacity{0u};
0367 };
0368 
0369 template <typename entry_t, typename data_t>
0370 dynamic_array(entry_t* bin_storage, data_t& bin_data) -> dynamic_array<entry_t>;
0371 
0372 template <typename entry_t, typename data_t>
0373 dynamic_array(const entry_t* bin_storage, const data_t& bin_data)
0374     -> dynamic_array<entry_t>;
0375 /// @}
0376 
0377 }  // namespace detray::bins