Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:09:38

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