File indexing completed on 2025-01-30 10:03:40
0001
0002
0003
0004
0005
0006
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
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
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
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
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
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
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
0240 CELER_CONSTEXPR_FUNCTION value_type value() const { return value_; }
0241
0242 protected:
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 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
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
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
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 }
0415 }