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