Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:03:40

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/cont/detail/RangeImpl.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include <iterator>
0011 #include <type_traits>
0012 #include <utility>
0013 
0014 #include "corecel/Assert.hh"
0015 #include "corecel/Macros.hh"
0016 #include "corecel/OpaqueId.hh"
0017 
0018 namespace celeritas
0019 {
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 = typename std::common_type<T, U>::type;
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, typename std::enable_if<T::size_ >= 0>::type>
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, typename std::enable_if<std::is_enum<T>::value>::type>
0077 {
0078     using value_type = T;
0079     using counter_type = typename std::underlying_type<T>::type;
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     CELER_FORCEINLINE_FUNCTION range_iter(value_type value) : value_(value)
0172     {
0173         CELER_EXPECT(TraitsT::is_valid(value_));
0174     }
0175 
0176     CELER_CONSTEXPR_FUNCTION range_iter() : value_(TraitsT::zero()) {}
0177 
0178     //// ACCESSORS ////
0179 
0180     CELER_CONSTEXPR_FUNCTION value_type operator*() const { return value_; }
0181     CELER_CONSTEXPR_FUNCTION value_type const* operator->() const
0182     {
0183         return &value_;
0184     }
0185 
0186     CELER_CONSTEXPR_FUNCTION value_type operator[](counter_type inc) const
0187     {
0188         return TraitsT::increment(value_, inc);
0189     }
0190 
0191     //// ARITHMETIC ////
0192 
0193     CELER_CONSTEXPR_FUNCTION range_iter& operator++()
0194     {
0195         value_ = TraitsT::increment(value_, 1);
0196         return *this;
0197     }
0198 
0199     CELER_CONSTEXPR_FUNCTION range_iter operator++(int)
0200     {
0201         auto copy = *this;
0202         value_ = TraitsT::increment(value_, 1);
0203         return copy;
0204     }
0205 
0206     CELER_CONSTEXPR_FUNCTION range_iter operator+(difference_type inc) const
0207     {
0208         return {TraitsT::increment(value_, inc)};
0209     }
0210 
0211     CELER_CONSTEXPR_FUNCTION range_iter& operator--()
0212     {
0213         value_ = TraitsT::decrement(value_, 1);
0214         return *this;
0215     }
0216 
0217     CELER_CONSTEXPR_FUNCTION range_iter operator--(int)
0218     {
0219         auto copy = *this;
0220         value_ = TraitsT::decrement(value_, 1);
0221         return copy;
0222     }
0223 
0224     CELER_CONSTEXPR_FUNCTION range_iter operator-(difference_type inc) const
0225     {
0226         return {TraitsT::decrement(value_, inc)};
0227     }
0228 
0229     CELER_CONSTEXPR_FUNCTION bool operator==(range_iter const& other) const
0230     {
0231         return value_ == other.value_;
0232     }
0233 
0234     CELER_CONSTEXPR_FUNCTION bool operator!=(range_iter const& other) const
0235     {
0236         return !(*this == other);
0237     }
0238 
0239     // Access the underlying value
0240     CELER_CONSTEXPR_FUNCTION value_type value() const { return value_; }
0241 
0242   protected:
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     template<class U = counter_type>
0316     CELER_FUNCTION typename std::enable_if_t<std::is_signed<U>::value, bool>
0317     operator==(step_range_iter const& other) const
0318     {
0319         return step_ >= 0 ? !(value_ < other.value_) : value_ < other.value_;
0320     }
0321 
0322     template<class U = counter_type>
0323     CELER_FUNCTION typename std::enable_if_t<std::is_unsigned<U>::value, bool>
0324     operator==(step_range_iter const& other) const
0325     {
0326         return !(value_ < other.value_);
0327     }
0328 
0329     CELER_FUNCTION bool operator!=(step_range_iter const& other) const
0330     {
0331         return !(*this == other);
0332     }
0333 
0334   private:
0335     using Base::value_;
0336     counter_type step_;
0337 };
0338 
0339 //---------------------------------------------------------------------------//
0340 template<class T>
0341 class inf_step_range_iter : public step_range_iter<T>
0342 {
0343     using Base = step_range_iter<T>;
0344 
0345   public:
0346     using TraitsT = typename Base::TraitsT;
0347     using counter_type = typename TraitsT::counter_type;
0348 
0349     CELER_FUNCTION
0350     inf_step_range_iter(T current = TraitsT::zero(), counter_type step = {})
0351         : Base(current, step)
0352     {
0353     }
0354 
0355     CELER_FUNCTION bool operator==(inf_step_range_iter const&) const
0356     {
0357         return false;
0358     }
0359 
0360     CELER_FUNCTION bool operator!=(inf_step_range_iter const&) const
0361     {
0362         return true;
0363     }
0364 };
0365 
0366 //---------------------------------------------------------------------------//
0367 /*!
0368  * Proxy container for iterating over a finite range with a non-unit step
0369  */
0370 template<class T>
0371 class StepRange
0372 {
0373   public:
0374     using IterT = step_range_iter<T>;
0375     using counter_type = typename RangeTypeTraits<T>::counter_type;
0376 
0377     CELER_FUNCTION StepRange(T begin, T end, counter_type step)
0378         : begin_(begin, step), end_(end, step)
0379     {
0380     }
0381 
0382     CELER_CONSTEXPR_FUNCTION IterT begin() const { return begin_; }
0383     CELER_CONSTEXPR_FUNCTION IterT end() const { return end_; }
0384 
0385   private:
0386     IterT begin_;
0387     IterT end_;
0388 };
0389 
0390 //---------------------------------------------------------------------------//
0391 /*!
0392  * Proxy container for iterating over an infinite range with a non-unit step
0393  */
0394 template<class T>
0395 class InfStepRange
0396 {
0397   public:
0398     using IterT = inf_step_range_iter<T>;
0399     using counter_type = typename RangeTypeTraits<T>::counter_type;
0400 
0401     //! Construct from start/stop
0402     CELER_FUNCTION InfStepRange(T begin, counter_type step)
0403         : begin_(begin, step)
0404     {
0405     }
0406 
0407     CELER_CONSTEXPR_FUNCTION IterT begin() const { return begin_; }
0408     CELER_CONSTEXPR_FUNCTION IterT end() const { return IterT(); }
0409 
0410   private:
0411     IterT begin_;
0412 };
0413 
0414 }  // namespace detail
0415 }  // namespace celeritas