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
0002
0003
0004
0005
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
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
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
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
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
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
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
0239 CELER_CONSTEXPR_FUNCTION value_type value() const { return value_; }
0240
0241 protected:
0242
0243 value_type value_;
0244 };
0245
0246
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
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
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
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
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 }
0417 }