Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:47

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     constexpr LdgIterator(LdgIterator const&) noexcept = default;
0055     CELER_CONSTEXPR_FUNCTION LdgIterator(std::nullptr_t) noexcept {}
0056     CELER_CONSTEXPR_FUNCTION explicit LdgIterator(pointer ptr) noexcept
0057         : ptr_{ptr}
0058     {
0059     }
0060     //!@}
0061 
0062     //!@{
0063     //! \name RandomAccessIterator requirements
0064     CELER_CONSTEXPR_FUNCTION reference operator*() const noexcept
0065     {
0066         return LoadPolicyT::read(ptr_);
0067     }
0068     CELER_CONSTEXPR_FUNCTION LdgIterator& operator++() noexcept
0069     {
0070         ++ptr_;
0071         return *this;
0072     }
0073     CELER_CONSTEXPR_FUNCTION void swap(LdgIterator& it) noexcept
0074     {
0075         ::celeritas::trivial_swap(ptr_, it.ptr_);
0076     }
0077     CELER_CONSTEXPR_FUNCTION LdgIterator operator++(int) noexcept
0078     {
0079         LdgIterator tmp{ptr_};
0080         ++ptr_;
0081         return tmp;
0082     }
0083     CELER_CONSTEXPR_FUNCTION pointer operator->() const noexcept
0084     {
0085         return ptr_;
0086     }
0087     CELER_CONSTEXPR_FUNCTION LdgIterator& operator--() noexcept
0088     {
0089         --ptr_;
0090         return *this;
0091     }
0092     CELER_CONSTEXPR_FUNCTION LdgIterator operator--(int) noexcept
0093     {
0094         LdgIterator tmp{ptr_};
0095         --ptr_;
0096         return tmp;
0097     }
0098     CELER_CONSTEXPR_FUNCTION LdgIterator& operator+=(difference_type n) noexcept
0099     {
0100         ptr_ += n;
0101         return *this;
0102     }
0103     CELER_CONSTEXPR_FUNCTION LdgIterator& operator-=(difference_type n) noexcept
0104     {
0105         ptr_ -= n;
0106         return *this;
0107     }
0108     CELER_CONSTEXPR_FUNCTION reference operator[](difference_type n) const noexcept
0109     {
0110         return LoadPolicyT::read(ptr_ + n);
0111     }
0112     LdgIterator& operator=(LdgIterator const&) = default;
0113     //!@}
0114 
0115     //!@{
0116     //! \name Conversion operators
0117     CELER_CONSTEXPR_FUNCTION explicit operator pointer() const noexcept
0118     {
0119         return ptr_;
0120     }
0121     CELER_CONSTEXPR_FUNCTION explicit operator bool() const noexcept
0122     {
0123         return ptr_ != nullptr;
0124     }
0125     //!@}
0126 
0127   private:
0128     pointer ptr_{nullptr};
0129 };
0130 
0131 //---------------------------------------------------------------------------//
0132 // DEDUCTION GUIDES
0133 //---------------------------------------------------------------------------//
0134 template<class T>
0135 LdgIterator(T*) -> LdgIterator<std::add_const_t<T>>;
0136 
0137 //---------------------------------------------------------------------------//
0138 // FREE FUNCTIONS
0139 //---------------------------------------------------------------------------//
0140 
0141 //!@{
0142 //! RandomAccessIterator requirements
0143 template<class T>
0144 CELER_CONSTEXPR_FUNCTION bool
0145 operator==(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept
0146 {
0147     using pointer = typename LdgIterator<T>::pointer;
0148     return static_cast<pointer>(lhs) == static_cast<pointer>(rhs);
0149 }
0150 template<class T>
0151 CELER_CONSTEXPR_FUNCTION bool
0152 operator!=(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept
0153 {
0154     return !(lhs == rhs);
0155 }
0156 template<class T>
0157 CELER_CONSTEXPR_FUNCTION bool
0158 operator==(LdgIterator<T> const& it, std::nullptr_t) noexcept
0159 {
0160     return !static_cast<bool>(it);
0161 }
0162 template<class T>
0163 CELER_CONSTEXPR_FUNCTION bool
0164 operator!=(LdgIterator<T> const& it, std::nullptr_t) noexcept
0165 {
0166     return static_cast<bool>(it);
0167 }
0168 template<class T>
0169 CELER_CONSTEXPR_FUNCTION bool
0170 operator==(std::nullptr_t, LdgIterator<T> const& it) noexcept
0171 {
0172     return !static_cast<bool>(it);
0173 }
0174 template<class T>
0175 CELER_CONSTEXPR_FUNCTION bool
0176 operator!=(std::nullptr_t, LdgIterator<T> const& it) noexcept
0177 {
0178     return static_cast<bool>(it);
0179 }
0180 template<class T>
0181 CELER_CONSTEXPR_FUNCTION bool
0182 operator<(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept
0183 {
0184     using pointer = typename LdgIterator<T>::pointer;
0185     return static_cast<pointer>(lhs) < static_cast<pointer>(rhs);
0186 }
0187 template<class T>
0188 CELER_CONSTEXPR_FUNCTION bool
0189 operator>(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept
0190 {
0191     return rhs < lhs;
0192 }
0193 template<class T>
0194 CELER_CONSTEXPR_FUNCTION bool
0195 operator<=(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept
0196 {
0197     return !(lhs > rhs);
0198 }
0199 template<class T>
0200 CELER_CONSTEXPR_FUNCTION bool
0201 operator>=(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept
0202 {
0203     return !(lhs < rhs);
0204 }
0205 template<class T>
0206 CELER_CONSTEXPR_FUNCTION LdgIterator<T>
0207 operator+(LdgIterator<T> const& it,
0208           typename LdgIterator<T>::difference_type const n) noexcept
0209 {
0210     LdgIterator tmp{it};
0211     return tmp += n;
0212 }
0213 template<class T>
0214 CELER_CONSTEXPR_FUNCTION LdgIterator<T>
0215 operator+(typename LdgIterator<T>::difference_type const n,
0216           LdgIterator<T> const& it) noexcept
0217 {
0218     return it + n;
0219 }
0220 template<class T>
0221 CELER_CONSTEXPR_FUNCTION LdgIterator<T>
0222 operator-(LdgIterator<T> const& it,
0223           typename LdgIterator<T>::difference_type const n) noexcept
0224 {
0225     LdgIterator<T> tmp{it};
0226     return tmp -= n;
0227 }
0228 template<class T>
0229 CELER_CONSTEXPR_FUNCTION auto
0230 operator-(LdgIterator<T> const& lhs, LdgIterator<T> const& rhs) noexcept ->
0231     typename LdgIterator<T>::difference_type
0232 {
0233     using pointer = typename LdgIterator<T>::pointer;
0234     return static_cast<pointer>(lhs) - static_cast<pointer>(rhs);
0235 }
0236 template<class T>
0237 CELER_CONSTEXPR_FUNCTION void
0238 swap(LdgIterator<T>& lhs, LdgIterator<T>& rhs) noexcept
0239 {
0240     return lhs.swap(rhs);
0241 }
0242 //!@}
0243 
0244 //---------------------------------------------------------------------------//
0245 /*!
0246  * Wrapper struct for specializing on types supported by LdgIterator.
0247  *
0248  * For example, Span<LdgValue<T>> specialization can internally use
0249  * LdgIterator. Specializations should refer to LdgValue<T>::value_type to
0250  * force the template instantiation of LdgValue and type-check T .
0251  */
0252 template<class T>
0253 struct LdgValue
0254 {
0255     using value_type = T;
0256     static_assert(detail::is_ldg_supported_v<T>,
0257                   "const arithmetic, OpaqueId or enum type "
0258                   "required");
0259 };
0260 
0261 //---------------------------------------------------------------------------//
0262 //! Alias for a Span iterating over values read using __ldg
0263 template<class T, std::size_t Extent = dynamic_extent>
0264 using LdgSpan = Span<LdgValue<T>, Extent>;
0265 
0266 //---------------------------------------------------------------------------//
0267 /*!
0268  * Construct an array from a fixed-size span, removing LdgValue marker.
0269  *
0270  * Note: \code make_array(Span<T,N> const&) \endcode is not reused because:
0271  * 1. Using this overload reads input data using \c __ldg
0272  * 2. \code return make_array<T, N>(s) \endcode results in segfault (gcc 11.3).
0273  *    This might be a compiler bug because temporary lifetime should be
0274  *    extended until the end of the expression and we return a copy...
0275  */
0276 template<class T, std::size_t N>
0277 CELER_CONSTEXPR_FUNCTION auto make_array(LdgSpan<T, N> const& s)
0278 {
0279     Array<std::remove_cv_t<T>, N> result{};
0280     for (std::size_t i = 0; i < N; ++i)
0281     {
0282         result[i] = s[i];
0283     }
0284     return result;
0285 }
0286 
0287 //---------------------------------------------------------------------------//
0288 }  // namespace celeritas