Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/corecel/cont/detail/RangeImpl.hh was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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/RangeImpl.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <iterator>
0010 #include <type_traits>
0011 
0012 #include "corecel/Assert.hh"
0013 #include "corecel/Macros.hh"
0014 #include "corecel/data/Ldg.hh"
0015 
0016 namespace celeritas
0017 {
0018 template<class TagT, class IndexT>
0019 class OpaqueId;
0020 namespace detail
0021 {
0022 //---------------------------------------------------------------------------//
0023 template<class T, class Enable = void>
0024 struct RangeTypeTraits
0025 {
0026     static_assert(std::is_integral_v<T>,
0027                   "Only integer types can be used in a range");
0028     using value_type = T;
0029     using counter_type = T;
0030     using difference_type = std::make_signed_t<counter_type>;
0031 
0032     template<class U>
0033     using common_type = std::common_type_t<T, U>;
0034 
0035     static CELER_CONSTEXPR_FUNCTION value_type zero() { return {}; }
0036     static CELER_CONSTEXPR_FUNCTION bool is_valid(value_type) { return true; }
0037     static CELER_CONSTEXPR_FUNCTION counter_type to_counter(value_type v)
0038     {
0039         return v;
0040     }
0041     static CELER_CONSTEXPR_FUNCTION value_type to_value(counter_type c)
0042     {
0043         return c;
0044     }
0045     static CELER_CONSTEXPR_FUNCTION value_type increment(value_type v,
0046                                                          difference_type i)
0047     {
0048         v += i;
0049         return v;
0050     }
0051     static CELER_CONSTEXPR_FUNCTION value_type decrement(value_type v,
0052                                                          difference_type i)
0053     {
0054         v -= i;
0055         return v;
0056     }
0057 };
0058 
0059 template<class T, class Enable = void>
0060 struct EnumWithSize
0061 {
0062     static CELER_CONSTEXPR_FUNCTION bool is_valid(T) { return true; }
0063 };
0064 
0065 template<class T>
0066 struct EnumWithSize<T, std::enable_if_t<(T::size_ >= 0)>>
0067 {
0068     static CELER_CONSTEXPR_FUNCTION bool is_valid(T value)
0069     {
0070         return value <= T::size_;
0071     }
0072 };
0073 
0074 //! Specialization for enums with a "size_" member
0075 template<class T>
0076 struct RangeTypeTraits<T, std::enable_if_t<std::is_enum<T>::value>>
0077 {
0078     using value_type = T;
0079     using counter_type = std::underlying_type_t<T>;
0080     using difference_type = std::make_signed_t<counter_type>;
0081     template<class U>
0082     using common_type = value_type;
0083 
0084     static CELER_CONSTEXPR_FUNCTION value_type zero() { return {}; }
0085     static CELER_CONSTEXPR_FUNCTION bool is_valid(value_type v)
0086     {
0087         return EnumWithSize<T>::is_valid(v);
0088     }
0089     static CELER_CONSTEXPR_FUNCTION counter_type to_counter(value_type v)
0090     {
0091         return static_cast<counter_type>(v);
0092     }
0093     static CELER_CONSTEXPR_FUNCTION value_type to_value(counter_type c)
0094     {
0095         return static_cast<value_type>(c);
0096     }
0097     static CELER_CONSTEXPR_FUNCTION value_type increment(value_type v,
0098                                                          difference_type i)
0099     {
0100         auto temp = to_counter(v);
0101         temp += i;
0102         return to_value(temp);
0103     }
0104     static CELER_CONSTEXPR_FUNCTION value_type decrement(value_type v,
0105                                                          difference_type i)
0106     {
0107         auto temp = to_counter(v);
0108         temp -= i;
0109         return to_value(temp);
0110     }
0111 };
0112 
0113 //! Specialization for Opaque ID
0114 template<class I, class T>
0115 struct RangeTypeTraits<OpaqueId<I, T>, void>
0116 {
0117     using value_type = OpaqueId<I, T>;
0118     using counter_type = T;
0119     using difference_type = std::make_signed_t<counter_type>;
0120     template<class U>
0121     using common_type = value_type;
0122 
0123     static CELER_CONSTEXPR_FUNCTION value_type zero() { return value_type(0); }
0124     static CELER_CONSTEXPR_FUNCTION bool is_valid(value_type v)
0125     {
0126         return static_cast<bool>(v);
0127     }
0128     static CELER_CONSTEXPR_FUNCTION counter_type to_counter(value_type v)
0129     {
0130         return v.unchecked_get();
0131     }
0132     static CELER_CONSTEXPR_FUNCTION value_type to_value(difference_type c)
0133     {
0134         return static_cast<value_type>(c);
0135     }
0136     static CELER_CONSTEXPR_FUNCTION value_type increment(value_type v,
0137                                                          difference_type i)
0138     {
0139         counter_type temp = to_counter(v);
0140         temp += i;
0141         return to_value(temp);
0142     }
0143     static CELER_CONSTEXPR_FUNCTION value_type decrement(value_type v,
0144                                                          difference_type i)
0145     {
0146         counter_type temp = to_counter(v);
0147         temp -= i;
0148         return to_value(temp);
0149     }
0150 };
0151 
0152 //---------------------------------------------------------------------------//
0153 template<class T>
0154 class range_iter
0155 {
0156   public:
0157     //!@{
0158     //! \name Type aliases
0159     using TraitsT = RangeTypeTraits<T>;
0160     using value_type = T;
0161     using counter_type = typename TraitsT::counter_type;
0162     using iterator_category = std::input_iterator_tag;
0163     using difference_type = typename TraitsT::difference_type;
0164     using pointer = void;
0165     using reference = value_type;
0166     //!@}
0167 
0168   public:
0169     //// CONSTRUCTOR ////
0170 
0171     constexpr range_iter() = default;
0172 
0173     explicit CELER_CONSTEXPR_FUNCTION range_iter(value_type value)
0174         : value_(value)
0175     {
0176         CELER_EXPECT(TraitsT::is_valid(value_));
0177     }
0178 
0179     //// ACCESSORS ////
0180 
0181     CELER_CONSTEXPR_FUNCTION value_type operator*() const { return value_; }
0182     CELER_CONSTEXPR_FUNCTION value_type const* operator->() const
0183     {
0184         return &value_;
0185     }
0186 
0187     CELER_CONSTEXPR_FUNCTION value_type operator[](counter_type inc) const
0188     {
0189         return TraitsT::increment(value_, inc);
0190     }
0191 
0192     //// ARITHMETIC ////
0193 
0194     CELER_CONSTEXPR_FUNCTION range_iter& operator++()
0195     {
0196         value_ = TraitsT::increment(value_, 1);
0197         return *this;
0198     }
0199 
0200     CELER_CONSTEXPR_FUNCTION range_iter operator++(int)
0201     {
0202         auto copy = *this;
0203         value_ = TraitsT::increment(value_, 1);
0204         return copy;
0205     }
0206 
0207     CELER_CONSTEXPR_FUNCTION range_iter operator+(difference_type inc) const
0208     {
0209         return range_iter{TraitsT::increment(value_, inc)};
0210     }
0211 
0212     CELER_CONSTEXPR_FUNCTION range_iter& operator--()
0213     {
0214         value_ = TraitsT::decrement(value_, 1);
0215         return *this;
0216     }
0217 
0218     CELER_CONSTEXPR_FUNCTION range_iter operator--(int)
0219     {
0220         auto copy = *this;
0221         value_ = TraitsT::decrement(value_, 1);
0222         return copy;
0223     }
0224 
0225     CELER_CONSTEXPR_FUNCTION range_iter operator-(difference_type inc) const
0226     {
0227         return range_iter{TraitsT::decrement(value_, inc)};
0228     }
0229 
0230     CELER_CONSTEXPR_FUNCTION bool operator==(range_iter const& other) const
0231     {
0232         return value_ == other.value_;
0233     }
0234 
0235     CELER_CONSTEXPR_FUNCTION bool operator!=(range_iter const& other) const
0236     {
0237         return !(*this == other);
0238     }
0239 
0240     // Subtract two range iterators
0241     CELER_CONSTEXPR_FUNCTION friend auto operator-(range_iter a, range_iter b)
0242     {
0243         using TraitsT = RangeTypeTraits<T>;
0244         using DT = typename TraitsT::difference_type;
0245         return static_cast<DT>(TraitsT::to_counter(a.value()))
0246                - static_cast<DT>(TraitsT::to_counter(b.value()));
0247     }
0248 
0249     // Access the underlying value
0250     CELER_CEF value_type value() const& { return value_; }
0251 
0252     //! Allow loading via ldg
0253     CELER_CONSTEXPR_FUNCTION friend range_iter ldg(
0254         range_iter const* ri) noexcept
0255     {
0256         using ::celeritas::ldg;
0257         return range_iter{ldg(&ri->value_)};
0258     }
0259 
0260   protected:
0261     // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
0262     value_type value_{TraitsT::zero()};
0263 };
0264 
0265 //---------------------------------------------------------------------------//
0266 template<class T>
0267 class inf_range_iter : public range_iter<T>
0268 {
0269     using Base = range_iter<T>;
0270 
0271   public:
0272     using TraitsT = typename Base::TraitsT;
0273 
0274     explicit CELER_CONSTEXPR_FUNCTION inf_range_iter(T value) : Base(value) {}
0275     explicit CELER_CONSTEXPR_FUNCTION inf_range_iter()
0276         : inf_range_iter{TraitsT::zero()}
0277     {
0278     }
0279 
0280     CELER_CONSTEXPR_FUNCTION bool operator==(inf_range_iter const&) const
0281     {
0282         return false;
0283     }
0284 
0285     CELER_CONSTEXPR_FUNCTION bool operator!=(inf_range_iter const&) const
0286     {
0287         return true;
0288     }
0289 };
0290 
0291 //---------------------------------------------------------------------------//
0292 template<class T>
0293 class step_range_iter : public range_iter<T>
0294 {
0295     using Base = range_iter<T>;
0296 
0297   public:
0298     using TraitsT = typename Base::TraitsT;
0299     using counter_type = typename TraitsT::counter_type;
0300     using difference_type = typename TraitsT::difference_type;
0301 
0302     CELER_CONSTEXPR_FUNCTION step_range_iter(T value, counter_type step)
0303         : Base(value), step_(step)
0304     {
0305     }
0306 
0307     CELER_CONSTEXPR_FUNCTION step_range_iter& operator++()
0308     {
0309         value_ = TraitsT::increment(value_, step_);
0310         return *this;
0311     }
0312 
0313     CELER_CONSTEXPR_FUNCTION step_range_iter operator++(int)
0314     {
0315         auto copy = *this;
0316         ++*this;
0317         return copy;
0318     }
0319 
0320     CELER_CONSTEXPR_FUNCTION step_range_iter operator+(difference_type inc)
0321     {
0322         return {TraitsT::increment(value_, inc * step_)};
0323     }
0324 
0325     CELER_FUNCTION bool operator==(step_range_iter const& other) const
0326     {
0327         if constexpr (std::is_signed_v<counter_type>)
0328         {
0329             return step_ >= 0 ? !(value_ < other.value_)
0330                               : value_ < other.value_;
0331         }
0332         else
0333         {
0334             return !(value_ < other.value_);
0335         }
0336     }
0337 
0338     CELER_FUNCTION bool operator!=(step_range_iter const& other) const
0339     {
0340         return !(*this == other);
0341     }
0342 
0343     // Access the underlying step
0344     CELER_FORCEINLINE_FUNCTION counter_type step() const { return step_; }
0345 
0346   private:
0347     using Base::value_;
0348     counter_type step_;
0349 };
0350 
0351 //---------------------------------------------------------------------------//
0352 template<class T>
0353 class inf_step_range_iter : public step_range_iter<T>
0354 {
0355     using Base = step_range_iter<T>;
0356 
0357   public:
0358     using TraitsT = typename Base::TraitsT;
0359     using counter_type = typename TraitsT::counter_type;
0360 
0361     CELER_FUNCTION inf_step_range_iter(T current = TraitsT::zero(),
0362                                        counter_type step = {})
0363         : Base(current, step)
0364     {
0365     }
0366 
0367     CELER_FUNCTION bool operator==(inf_step_range_iter const&) const
0368     {
0369         return false;
0370     }
0371 
0372     CELER_FUNCTION bool operator!=(inf_step_range_iter const&) const
0373     {
0374         return true;
0375     }
0376 };
0377 
0378 //---------------------------------------------------------------------------//
0379 /*!
0380  * Proxy container for iterating over a finite range with a non-unit step
0381  */
0382 template<class T>
0383 class StepRange
0384 {
0385   public:
0386     using IterT = step_range_iter<T>;
0387     using counter_type = typename RangeTypeTraits<T>::counter_type;
0388 
0389     CELER_FUNCTION StepRange(T begin, T end, counter_type step)
0390         : begin_(begin, step), end_(end, step)
0391     {
0392     }
0393 
0394     CELER_CONSTEXPR_FUNCTION IterT begin() const { return begin_; }
0395     CELER_CONSTEXPR_FUNCTION IterT end() const { return end_; }
0396 
0397   private:
0398     IterT begin_;
0399     IterT end_;
0400 };
0401 
0402 //---------------------------------------------------------------------------//
0403 /*!
0404  * Proxy container for iterating over an infinite range with a non-unit step
0405  */
0406 template<class T>
0407 class InfStepRange
0408 {
0409   public:
0410     using IterT = inf_step_range_iter<T>;
0411     using counter_type = typename RangeTypeTraits<T>::counter_type;
0412 
0413     //! Construct from start/stop
0414     CELER_FUNCTION InfStepRange(T begin, counter_type step)
0415         : begin_(begin, step)
0416     {
0417     }
0418 
0419     CELER_CONSTEXPR_FUNCTION IterT begin() const { return begin_; }
0420     CELER_CONSTEXPR_FUNCTION IterT end() const { return IterT(); }
0421 
0422   private:
0423     IterT begin_;
0424 };
0425 
0426 }  // namespace detail
0427 }  // namespace celeritas