Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-26 09:34:32

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/cont/detail/LdgSpanImpl.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <iterator>
0010 #include <type_traits>
0011 
0012 #include "corecel/Macros.hh"
0013 #include "corecel/data/Ldg.hh"
0014 
0015 namespace celeritas
0016 {
0017 namespace detail
0018 {
0019 //---------------------------------------------------------------------------//
0020 /*!
0021  * Wrapper that loads data safely via \c ldg on conversion.
0022  * \tparam T value type (must be const) being accessed
0023  *
0024  * This class mirrors \c std::reference_wrapper, storing a pointer to a const
0025  * object and provides an implicit conversion to the value type.
0026  * However, the value being wrapped \em must be a const reference, and the
0027  * return is a \c value rather than a reference .
0028  *
0029  * The \c __ldg intrinsic is invoked during the implicit load, so client code
0030  * can bind the wrapper to an ordinary value variable transparently.
0031  */
0032 template<class T>
0033 class LdgWrapper
0034 {
0035     static_assert(std::is_const_v<T>);
0036 
0037   public:
0038     //!@{
0039     //! \name Type aliases
0040     using type = std::remove_const_t<T>;
0041     //!@}
0042 
0043   public:
0044     //! Construct from a const reference to the target
0045     CELER_CEF LdgWrapper(T& ref) noexcept : ptr_{&ref} {}
0046 
0047     //! Load the referenced value using __ldg
0048     CELER_CEF type get() const noexcept
0049     {
0050         using ::celeritas::ldg;
0051         return ldg(ptr_);
0052     }
0053 
0054     //! Implicit conversion: load via __ldg
0055     CELER_CEF operator type() const noexcept { return this->get(); }
0056 
0057     //!@{
0058     /*!
0059      * Comparison operators against the underlying type or another wrapper.
0060      *
0061      * Defined here so template \c operator== (e.g. \c OpaqueId) are found via
0062      * ADL without requiring implicit conversion during deduction.
0063      * The \c LdgWrapper vs \c LdgWrapper overloads prevent ambiguity when
0064      * both arguments are wrappers (e.g., \c std::equal over two LdgSpans).
0065      */
0066     CELER_CEF friend bool operator==(LdgWrapper a, LdgWrapper b) noexcept
0067     {
0068         return a.get() == b.get();
0069     }
0070     CELER_CEF friend bool operator==(LdgWrapper a, type b) noexcept
0071     {
0072         return a.get() == b;
0073     }
0074     CELER_CEF friend bool operator==(type a, LdgWrapper b) noexcept
0075     {
0076         return a == b.get();
0077     }
0078     CELER_CEF friend bool operator!=(LdgWrapper a, LdgWrapper b) noexcept
0079     {
0080         return a.get() != b.get();
0081     }
0082     CELER_CEF friend bool operator!=(LdgWrapper a, type b) noexcept
0083     {
0084         return a.get() != b;
0085     }
0086     CELER_CEF friend bool operator!=(type a, LdgWrapper b) noexcept
0087     {
0088         return a != b.get();
0089     }
0090     //!@}
0091 
0092   private:
0093     // Const pointer to global device data
0094     T* ptr_;
0095 };
0096 
0097 //---------------------------------------------------------------------------//
0098 /*!
0099  * Proxy iterator that constructs a LdgWrapper when dereferenced.
0100  * \tparam T value type being accessed
0101  *
0102  * See \c ldg .
0103  */
0104 template<class T>
0105 class LdgIterator
0106 {
0107     static_assert(std::is_const_v<T>);
0108 
0109   public:
0110     //!@{
0111     //! \name Type aliases
0112     using difference_type = std::ptrdiff_t;
0113     using value_type = std::remove_const_t<T>;
0114     using pointer = T*;
0115     using reference = LdgWrapper<T>;
0116     using iterator_category = std::random_access_iterator_tag;
0117     //!@}
0118 
0119   public:
0120     //!@{
0121     //! Construct a pointer
0122     constexpr LdgIterator() noexcept = default;
0123     CELER_CONSTEXPR_FUNCTION LdgIterator(std::nullptr_t) noexcept {}
0124     CELER_CONSTEXPR_FUNCTION explicit LdgIterator(pointer ptr) noexcept
0125         : ptr_{ptr}
0126     {
0127     }
0128     //!@}
0129 
0130     //!@{
0131     //! \name RandomAccessIterator requirements
0132     CELER_CONSTEXPR_FUNCTION reference operator*() const noexcept
0133     {
0134         return LdgWrapper<T>{*ptr_};
0135     }
0136     CELER_CONSTEXPR_FUNCTION LdgIterator& operator++() noexcept
0137     {
0138         ++ptr_;
0139         return *this;
0140     }
0141     CELER_CONSTEXPR_FUNCTION LdgIterator operator++(int) noexcept
0142     {
0143         LdgIterator tmp{ptr_};
0144         ++ptr_;
0145         return tmp;
0146     }
0147     CELER_CONSTEXPR_FUNCTION pointer operator->() const noexcept
0148     {
0149         return ptr_;
0150     }
0151     CELER_CONSTEXPR_FUNCTION LdgIterator& operator--() noexcept
0152     {
0153         --ptr_;
0154         return *this;
0155     }
0156     CELER_CONSTEXPR_FUNCTION LdgIterator operator--(int) noexcept
0157     {
0158         LdgIterator tmp{ptr_};
0159         --ptr_;
0160         return tmp;
0161     }
0162     CELER_CONSTEXPR_FUNCTION LdgIterator& operator+=(difference_type n) noexcept
0163     {
0164         ptr_ += n;
0165         return *this;
0166     }
0167     CELER_CONSTEXPR_FUNCTION LdgIterator& operator-=(difference_type n) noexcept
0168     {
0169         ptr_ -= n;
0170         return *this;
0171     }
0172     CELER_CONSTEXPR_FUNCTION reference operator[](
0173         difference_type n) const noexcept
0174     {
0175         return LdgWrapper<T>{*(ptr_ + n)};
0176     }
0177     //!@}
0178 
0179     //!@{
0180     //! \name Conversion operators
0181     CELER_CONSTEXPR_FUNCTION explicit operator pointer() const noexcept
0182     {
0183         return ptr_;
0184     }
0185     CELER_CONSTEXPR_FUNCTION explicit operator bool() const noexcept
0186     {
0187         return ptr_ != nullptr;
0188     }
0189     //!@}
0190 
0191     //!@{
0192     //! RandomAccessIterator requirements
0193     CELER_CONSTEXPR_FUNCTION friend bool operator==(
0194         LdgIterator const& lhs, LdgIterator const& rhs) noexcept
0195     {
0196         return static_cast<pointer>(lhs) == static_cast<pointer>(rhs);
0197     }
0198     CELER_CONSTEXPR_FUNCTION friend bool operator!=(
0199         LdgIterator const& lhs, LdgIterator const& rhs) noexcept
0200     {
0201         return !(lhs == rhs);
0202     }
0203     CELER_CONSTEXPR_FUNCTION friend bool operator==(LdgIterator const& it,
0204                                                     std::nullptr_t) noexcept
0205     {
0206         return !static_cast<bool>(it);
0207     }
0208     CELER_CONSTEXPR_FUNCTION friend bool operator!=(LdgIterator const& it,
0209                                                     std::nullptr_t) noexcept
0210     {
0211         return static_cast<bool>(it);
0212     }
0213     CELER_CONSTEXPR_FUNCTION friend bool operator==(
0214         std::nullptr_t, LdgIterator const& it) noexcept
0215     {
0216         return !static_cast<bool>(it);
0217     }
0218     CELER_CONSTEXPR_FUNCTION friend bool operator!=(
0219         std::nullptr_t, LdgIterator const& it) noexcept
0220     {
0221         return static_cast<bool>(it);
0222     }
0223     CELER_CONSTEXPR_FUNCTION friend bool operator<(
0224         LdgIterator const& lhs, LdgIterator const& rhs) noexcept
0225     {
0226         return static_cast<pointer>(lhs) < static_cast<pointer>(rhs);
0227     }
0228     CELER_CONSTEXPR_FUNCTION friend bool operator>(
0229         LdgIterator const& lhs, LdgIterator const& rhs) noexcept
0230     {
0231         return rhs < lhs;
0232     }
0233     CELER_CONSTEXPR_FUNCTION friend bool operator<=(
0234         LdgIterator const& lhs, LdgIterator const& rhs) noexcept
0235     {
0236         return !(lhs > rhs);
0237     }
0238     CELER_CONSTEXPR_FUNCTION friend bool operator>=(
0239         LdgIterator const& lhs, LdgIterator const& rhs) noexcept
0240     {
0241         return !(lhs < rhs);
0242     }
0243     CELER_CONSTEXPR_FUNCTION friend LdgIterator operator+(
0244         LdgIterator const& it, difference_type const n) noexcept
0245     {
0246         return LdgIterator{it} += n;
0247     }
0248     CELER_CONSTEXPR_FUNCTION friend LdgIterator operator+(
0249         difference_type const n, LdgIterator const& it) noexcept
0250     {
0251         return it + n;
0252     }
0253     CELER_CONSTEXPR_FUNCTION friend LdgIterator operator-(
0254         LdgIterator const& it, difference_type const n) noexcept
0255     {
0256         return LdgIterator{it} -= n;
0257     }
0258     CELER_CONSTEXPR_FUNCTION friend difference_type operator-(
0259         LdgIterator const& lhs, LdgIterator const& rhs) noexcept
0260     {
0261         return static_cast<pointer>(lhs) - static_cast<pointer>(rhs);
0262     }
0263     //!@}
0264 
0265   private:
0266     pointer ptr_{nullptr};
0267 };
0268 
0269 //---------------------------------------------------------------------------//
0270 // DEDUCTION GUIDES
0271 //---------------------------------------------------------------------------//
0272 template<class T>
0273 CELER_CTAD_FUNCTION LdgWrapper(T&) -> LdgWrapper<std::add_const_t<T>>;
0274 
0275 template<class T>
0276 CELER_CTAD_FUNCTION LdgIterator(T*) -> LdgIterator<std::add_const_t<T>>;
0277 
0278 //---------------------------------------------------------------------------//
0279 //! Get the item that's wrapped
0280 
0281 template<class T>
0282 CELER_CONSTEXPR_FUNCTION T remove_ldg_wrapper(LdgWrapper<T const> val)
0283 {
0284     return val.get();
0285 }
0286 
0287 //---------------------------------------------------------------------------//
0288 }  // namespace detail
0289 }  // namespace celeritas