Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-31 09:41:33

0001 //------------------------------ -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file corecel/data/LdgIterator.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <cstddef>
0010 #include <iterator>
0011 #include <type_traits>
0012 
0013 #include "corecel/Macros.hh"
0014 #include "corecel/Types.hh"
0015 #include "corecel/cont/Span.hh"
0016 #include "corecel/math/Algorithms.hh"
0017 
0018 #include "detail/LdgIteratorImpl.hh"
0019 
0020 namespace celeritas
0021 {
0022 //---------------------------------------------------------------------------//
0023 /*!
0024  * Iterator for read-only device data in global memory.
0025  *
0026  * This wraps pointer accesses with the \c __ldg intrinsic to load
0027  * read-only data using texture cache.
0028  */
0029 template<class T>
0030 class LdgIterator
0031 {
0032     static_assert(detail::is_ldg_supported_v<T>,
0033                   "LdgIterator requires const arithmetic, OpaqueId or "
0034                   "enum type");
0035 
0036   private:
0037     using LoadPolicyT = detail::LdgLoader<T>;
0038 
0039   public:
0040     //!@{
0041     //! \name Type aliases
0042     using difference_type = std::ptrdiff_t;
0043     using value_type = typename LoadPolicyT::value_type;
0044     using pointer = typename LoadPolicyT::pointer;
0045     using reference = typename LoadPolicyT::reference;
0046     using iterator_category = std::random_access_iterator_tag;
0047     //!@}
0048 
0049   public:
0050     //!@{
0051     //! Construct a pointer
0052     constexpr LdgIterator() noexcept = default;
0053     CELER_CONSTEXPR_FUNCTION LdgIterator(std::nullptr_t) noexcept {}
0054     CELER_CONSTEXPR_FUNCTION explicit LdgIterator(pointer ptr) noexcept
0055         : ptr_{ptr}
0056     {
0057     }
0058     //!@}
0059 
0060     //!@{
0061     //! \name RandomAccessIterator requirements
0062     CELER_CONSTEXPR_FUNCTION reference operator*() const noexcept
0063     {
0064         return LoadPolicyT::read(ptr_);
0065     }
0066     CELER_CONSTEXPR_FUNCTION LdgIterator& operator++() noexcept
0067     {
0068         ++ptr_;
0069         return *this;
0070     }
0071     CELER_CONSTEXPR_FUNCTION void swap(LdgIterator& it) noexcept
0072     {
0073         ::celeritas::trivial_swap(ptr_, it.ptr_);
0074     }
0075     CELER_CONSTEXPR_FUNCTION LdgIterator operator++(int) noexcept
0076     {
0077         LdgIterator tmp{ptr_};
0078         ++ptr_;
0079         return tmp;
0080     }
0081     CELER_CONSTEXPR_FUNCTION pointer operator->() const noexcept
0082     {
0083         return ptr_;
0084     }
0085     CELER_CONSTEXPR_FUNCTION LdgIterator& operator--() noexcept
0086     {
0087         --ptr_;
0088         return *this;
0089     }
0090     CELER_CONSTEXPR_FUNCTION LdgIterator operator--(int) noexcept
0091     {
0092         LdgIterator tmp{ptr_};
0093         --ptr_;
0094         return tmp;
0095     }
0096     CELER_CONSTEXPR_FUNCTION LdgIterator& operator+=(difference_type n) noexcept
0097     {
0098         ptr_ += n;
0099         return *this;
0100     }
0101     CELER_CONSTEXPR_FUNCTION LdgIterator& operator-=(difference_type n) noexcept
0102     {
0103         ptr_ -= n;
0104         return *this;
0105     }
0106     CELER_CONSTEXPR_FUNCTION reference operator[](difference_type n) const noexcept
0107     {
0108         return LoadPolicyT::read(ptr_ + n);
0109     }
0110     //!@}
0111 
0112     //!@{
0113     //! \name Conversion operators
0114     CELER_CONSTEXPR_FUNCTION explicit operator pointer() const noexcept
0115     {
0116         return ptr_;
0117     }
0118     CELER_CONSTEXPR_FUNCTION explicit operator bool() const noexcept
0119     {
0120         return ptr_ != nullptr;
0121     }
0122     //!@}
0123 
0124   private:
0125     pointer ptr_{nullptr};
0126 };
0127 
0128 //---------------------------------------------------------------------------//
0129 // DEDUCTION GUIDES
0130 //---------------------------------------------------------------------------//
0131 template<class T>
0132 LdgIterator(T*) -> LdgIterator<std::add_const_t<T>>;
0133 
0134 //---------------------------------------------------------------------------//
0135 // FREE FUNCTIONS
0136 //---------------------------------------------------------------------------//
0137 
0138 //!@{
0139 //! RandomAccessIterator requirements
0140 template<class T>
0141 CELER_CONSTEXPR_FUNCTION bool
0142 operator==(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept
0143 {
0144     using pointer = typename LdgIterator<T>::pointer;
0145     return static_cast<pointer>(lhs) == static_cast<pointer>(rhs);
0146 }
0147 template<class T>
0148 CELER_CONSTEXPR_FUNCTION bool
0149 operator!=(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept
0150 {
0151     return !(lhs == rhs);
0152 }
0153 template<class T>
0154 CELER_CONSTEXPR_FUNCTION bool
0155 operator==(LdgIterator<T> const& it, std::nullptr_t) noexcept
0156 {
0157     return !static_cast<bool>(it);
0158 }
0159 template<class T>
0160 CELER_CONSTEXPR_FUNCTION bool
0161 operator!=(LdgIterator<T> const& it, std::nullptr_t) noexcept
0162 {
0163     return static_cast<bool>(it);
0164 }
0165 template<class T>
0166 CELER_CONSTEXPR_FUNCTION bool
0167 operator==(std::nullptr_t, LdgIterator<T> const& it) noexcept
0168 {
0169     return !static_cast<bool>(it);
0170 }
0171 template<class T>
0172 CELER_CONSTEXPR_FUNCTION bool
0173 operator!=(std::nullptr_t, LdgIterator<T> const& it) noexcept
0174 {
0175     return static_cast<bool>(it);
0176 }
0177 template<class T>
0178 CELER_CONSTEXPR_FUNCTION bool
0179 operator<(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept
0180 {
0181     using pointer = typename LdgIterator<T>::pointer;
0182     return static_cast<pointer>(lhs) < static_cast<pointer>(rhs);
0183 }
0184 template<class T>
0185 CELER_CONSTEXPR_FUNCTION bool
0186 operator>(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept
0187 {
0188     return rhs < lhs;
0189 }
0190 template<class T>
0191 CELER_CONSTEXPR_FUNCTION bool
0192 operator<=(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept
0193 {
0194     return !(lhs > rhs);
0195 }
0196 template<class T>
0197 CELER_CONSTEXPR_FUNCTION bool
0198 operator>=(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept
0199 {
0200     return !(lhs < rhs);
0201 }
0202 template<class T>
0203 CELER_CONSTEXPR_FUNCTION LdgIterator<T>
0204 operator+(LdgIterator<T> const& it,
0205           typename LdgIterator<T>::difference_type const n) noexcept
0206 {
0207     LdgIterator tmp{it};
0208     return tmp += n;
0209 }
0210 template<class T>
0211 CELER_CONSTEXPR_FUNCTION LdgIterator<T>
0212 operator+(typename LdgIterator<T>::difference_type const n,
0213           LdgIterator<T> const& it) noexcept
0214 {
0215     return it + n;
0216 }
0217 template<class T>
0218 CELER_CONSTEXPR_FUNCTION LdgIterator<T>
0219 operator-(LdgIterator<T> const& it,
0220           typename LdgIterator<T>::difference_type const n) noexcept
0221 {
0222     LdgIterator<T> tmp{it};
0223     return tmp -= n;
0224 }
0225 template<class T>
0226 CELER_CONSTEXPR_FUNCTION auto
0227 operator-(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept ->
0228     typename LdgIterator<T>::difference_type
0229 {
0230     using pointer = typename LdgIterator<T>::pointer;
0231     return static_cast<pointer>(lhs) - static_cast<pointer>(rhs);
0232 }
0233 template<class T>
0234 CELER_CONSTEXPR_FUNCTION void
0235 swap(LdgIterator<T>& lhs, LdgIterator<T>& rhs) noexcept
0236 {
0237     return lhs.swap(rhs);
0238 }
0239 //!@}
0240 
0241 //---------------------------------------------------------------------------//
0242 /*!
0243  * Wrapper struct for specializing on types supported by LdgIterator.
0244  *
0245  * For example, Span<LdgValue<T>> specialization can internally use
0246  * LdgIterator. Specializations should refer to LdgValue<T>::value_type to
0247  * force the template instantiation of LdgValue and type-check T .
0248  */
0249 template<class T>
0250 struct LdgValue
0251 {
0252     using value_type = T;
0253     static_assert(detail::is_ldg_supported_v<T>,
0254                   "const arithmetic, OpaqueId or enum type "
0255                   "required");
0256 };
0257 
0258 //---------------------------------------------------------------------------//
0259 //! Alias for a Span iterating over values read using __ldg
0260 template<class T, std::size_t Extent = dynamic_extent>
0261 using LdgSpan = Span<LdgValue<T>, Extent>;
0262 
0263 //---------------------------------------------------------------------------//
0264 /*!
0265  * Construct an array from a fixed-size span, removing LdgValue marker.
0266  *
0267  * Note: \code make_array(Span<T,N> const&) \endcode is not reused because:
0268  * 1. Using this overload reads input data using \c __ldg
0269  * 2. \code return make_array<T, N>(s) \endcode results in segfault (gcc 11.3).
0270  *    This might be a compiler bug because temporary lifetime should be
0271  *    extended until the end of the expression and we return a copy...
0272  */
0273 template<class T, std::size_t N>
0274 CELER_CONSTEXPR_FUNCTION auto make_array(LdgSpan<T, N> const& s)
0275 {
0276     Array<std::remove_cv_t<T>, N> result{};
0277     for (std::size_t i = 0; i < N; ++i)
0278     {
0279         result[i] = s[i];
0280     }
0281     return result;
0282 }
0283 
0284 //---------------------------------------------------------------------------//
0285 }  // namespace celeritas