Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 2020-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/OpaqueId.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include <cstddef>
0011 #include <functional>
0012 #include <type_traits>
0013 
0014 #include "Assert.hh"
0015 #include "Macros.hh"
0016 #include "Types.hh"
0017 
0018 namespace celeritas
0019 {
0020 //---------------------------------------------------------------------------//
0021 /*!
0022  * Type-safe index for accessing an array or collection of data.
0023  *
0024  * \tparam ValueT Type of each item in the array.
0025  * \tparam SizeT Integer index
0026  *
0027  * This allows type-safe, read-only indexing/access for a class. The value is
0028  * "true" if it"s assigned, "false" if invalid.
0029  */
0030 template<class ValueT, class SizeT = ::celeritas::size_type>
0031 class OpaqueId
0032 {
0033     static_assert(std::is_unsigned_v<SizeT> && !std::is_same_v<SizeT, bool>,
0034                   "SizeT must be unsigned.");
0035 
0036   public:
0037     //!@{
0038     //! \name Type aliases
0039     using value_type = ValueT;
0040     using size_type = SizeT;
0041     //!@}
0042 
0043   public:
0044     //! Default to invalid state
0045     CELER_CONSTEXPR_FUNCTION OpaqueId() : value_(OpaqueId::invalid_value()) {}
0046 
0047     //! Construct explicitly with stored value
0048     explicit CELER_CONSTEXPR_FUNCTION OpaqueId(size_type index) : value_(index)
0049     {
0050     }
0051 
0052     //! Whether this ID is in a valid (assigned) state
0053     explicit CELER_CONSTEXPR_FUNCTION operator bool() const
0054     {
0055         return value_ != invalid_value();
0056     }
0057 
0058     //! Pre-increment of the ID
0059     CELER_FUNCTION OpaqueId& operator++()
0060     {
0061         CELER_EXPECT(*this);
0062         value_ += 1;
0063         return *this;
0064     }
0065 
0066     //! Post-increment of the ID
0067     CELER_FUNCTION OpaqueId operator++(int)
0068     {
0069         OpaqueId old{*this};
0070         ++*this;
0071         return old;
0072     }
0073 
0074     //! Pre-decrement of the ID
0075     CELER_FUNCTION OpaqueId& operator--()
0076     {
0077         CELER_EXPECT(*this && value_ > 0);
0078         value_ -= 1;
0079         return *this;
0080     }
0081 
0082     //! Post-decrement of the ID
0083     CELER_FUNCTION OpaqueId operator--(int)
0084     {
0085         OpaqueId old{*this};
0086         --*this;
0087         return old;
0088     }
0089 
0090     //! Get the ID's value
0091     CELER_FORCEINLINE_FUNCTION size_type get() const
0092     {
0093         CELER_EXPECT(*this);
0094         return value_;
0095     }
0096 
0097     //! Get the value without checking for validity (atypical)
0098     CELER_CONSTEXPR_FUNCTION size_type unchecked_get() const { return value_; }
0099 
0100     //! Access the underlying data for more efficient loading from memory
0101     CELER_CONSTEXPR_FUNCTION size_type const* data() const { return &value_; }
0102 
0103   private:
0104     size_type value_;
0105 
0106     //// IMPLEMENTATION FUNCTIONS ////
0107 
0108     //! Value indicating the ID is not assigned
0109     static CELER_CONSTEXPR_FUNCTION size_type invalid_value()
0110     {
0111         return static_cast<size_type>(-1);
0112     }
0113 };
0114 
0115 //---------------------------------------------------------------------------//
0116 // FREE FUNCTIONS
0117 //---------------------------------------------------------------------------//
0118 #define CELER_DEFINE_OPAQUEID_CMP(TOKEN)                             \
0119     template<class V, class S>                                       \
0120     CELER_CONSTEXPR_FUNCTION bool operator TOKEN(OpaqueId<V, S> lhs, \
0121                                                  OpaqueId<V, S> rhs) \
0122     {                                                                \
0123         return lhs.unchecked_get() TOKEN rhs.unchecked_get();        \
0124     }
0125 
0126 //!@{
0127 //! Comparison for OpaqueId
0128 CELER_DEFINE_OPAQUEID_CMP(==)
0129 CELER_DEFINE_OPAQUEID_CMP(!=)
0130 CELER_DEFINE_OPAQUEID_CMP(<)
0131 CELER_DEFINE_OPAQUEID_CMP(>)
0132 CELER_DEFINE_OPAQUEID_CMP(<=)
0133 CELER_DEFINE_OPAQUEID_CMP(>=)
0134 //!@}
0135 
0136 #undef CELER_DEFINE_OPAQUEID_CMP
0137 
0138 //---------------------------------------------------------------------------//
0139 //! Allow less-than comparison with *integer* for container comparison
0140 template<class V, class S, class U>
0141 CELER_CONSTEXPR_FUNCTION bool operator<(OpaqueId<V, S> lhs, U rhs)
0142 {
0143     // Cast to RHS
0144     return lhs && (U(lhs.unchecked_get()) < rhs);
0145 }
0146 
0147 //---------------------------------------------------------------------------//
0148 //! Allow less-than-equal comparison with *integer* for container comparison
0149 template<class V, class S, class U>
0150 CELER_CONSTEXPR_FUNCTION bool operator<=(OpaqueId<V, S> lhs, U rhs)
0151 {
0152     // Cast to RHS
0153     return lhs && (U(lhs.unchecked_get()) <= rhs);
0154 }
0155 
0156 //---------------------------------------------------------------------------//
0157 //! Get the distance between two opaque IDs
0158 template<class V, class S>
0159 inline CELER_FUNCTION S operator-(OpaqueId<V, S> self, OpaqueId<V, S> other)
0160 {
0161     CELER_EXPECT(self);
0162     CELER_EXPECT(other);
0163     return self.unchecked_get() - other.unchecked_get();
0164 }
0165 
0166 //---------------------------------------------------------------------------//
0167 //! Increment an opaque ID by an offset
0168 template<class V, class S>
0169 inline CELER_FUNCTION OpaqueId<V, S>
0170 operator+(OpaqueId<V, S> id, std::make_signed_t<S> offset)
0171 {
0172     CELER_EXPECT(id);
0173     CELER_EXPECT(offset >= 0 || static_cast<S>(-offset) <= id.unchecked_get());
0174     return OpaqueId<V, S>{id.unchecked_get() + static_cast<S>(offset)};
0175 }
0176 
0177 //---------------------------------------------------------------------------//
0178 //! Decrement an opaque ID by an offset
0179 template<class V, class S>
0180 inline CELER_FUNCTION OpaqueId<V, S>
0181 operator-(OpaqueId<V, S> id, std::make_signed_t<S> offset)
0182 {
0183     CELER_EXPECT(id);
0184     CELER_EXPECT(offset <= 0 || static_cast<S>(offset) <= id.unchecked_get());
0185     return OpaqueId<V, S>{id.unchecked_get() - static_cast<S>(offset)};
0186 }
0187 
0188 //---------------------------------------------------------------------------//
0189 }  // namespace celeritas
0190 
0191 //---------------------------------------------------------------------------//
0192 //! \cond
0193 namespace std
0194 {
0195 //! Specialization for std::hash for unordered storage.
0196 template<class V, class S>
0197 struct hash<celeritas::OpaqueId<V, S>>
0198 {
0199     std::size_t operator()(celeritas::OpaqueId<V, S> const& id) const noexcept
0200     {
0201         return std::hash<S>()(id.unchecked_get());
0202     }
0203 };
0204 }  // namespace std
0205 //! \endcond