File indexing completed on 2025-09-16 08:52:39
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
0244 value_type value_;
0245 };
0246
0247
0248 template<class T>
0249 CELER_CONSTEXPR_FUNCTION auto operator-(range_iter<T> a, range_iter<T> b)
0250 {
0251 using TraitsT = RangeTypeTraits<T>;
0252 using DT = typename TraitsT::difference_type;
0253 return static_cast<DT>(TraitsT::to_counter(a.value()))
0254 - static_cast<DT>(TraitsT::to_counter(b.value()));
0255 }
0256
0257
0258 template<class T>
0259 class inf_range_iter : public range_iter<T>
0260 {
0261 using Base = range_iter<T>;
0262
0263 public:
0264 using TraitsT = typename Base::TraitsT;
0265
0266 CELER_CONSTEXPR_FUNCTION inf_range_iter(T value = TraitsT::zero())
0267 : Base(value)
0268 {
0269 }
0270
0271 CELER_CONSTEXPR_FUNCTION bool operator==(inf_range_iter const&) const
0272 {
0273 return false;
0274 }
0275
0276 CELER_CONSTEXPR_FUNCTION bool operator!=(inf_range_iter const&) const
0277 {
0278 return true;
0279 }
0280 };
0281
0282
0283 template<class T>
0284 class step_range_iter : public range_iter<T>
0285 {
0286 using Base = range_iter<T>;
0287
0288 public:
0289 using TraitsT = typename Base::TraitsT;
0290 using counter_type = typename TraitsT::counter_type;
0291 using difference_type = typename TraitsT::difference_type;
0292
0293 CELER_CONSTEXPR_FUNCTION step_range_iter(T value, counter_type step)
0294 : Base(value), step_(step)
0295 {
0296 }
0297
0298 CELER_CONSTEXPR_FUNCTION step_range_iter& operator++()
0299 {
0300 value_ = TraitsT::increment(value_, step_);
0301 return *this;
0302 }
0303
0304 CELER_CONSTEXPR_FUNCTION step_range_iter operator++(int)
0305 {
0306 auto copy = *this;
0307 ++*this;
0308 return copy;
0309 }
0310
0311 CELER_CONSTEXPR_FUNCTION step_range_iter operator+(difference_type inc)
0312 {
0313 return {TraitsT::increment(value_, inc * step_)};
0314 }
0315
0316 template<class U = counter_type>
0317 CELER_FUNCTION typename std::enable_if_t<std::is_signed<U>::value, bool>
0318 operator==(step_range_iter const& other) const
0319 {
0320 return step_ >= 0 ? !(value_ < other.value_) : value_ < other.value_;
0321 }
0322
0323 template<class U = counter_type>
0324 CELER_FUNCTION typename std::enable_if_t<std::is_unsigned<U>::value, bool>
0325 operator==(step_range_iter const& other) const
0326 {
0327 return !(value_ < other.value_);
0328 }
0329
0330 CELER_FUNCTION bool operator!=(step_range_iter const& other) const
0331 {
0332 return !(*this == other);
0333 }
0334
0335 private:
0336 using Base::value_;
0337 counter_type step_;
0338 };
0339
0340
0341 template<class T>
0342 class inf_step_range_iter : public step_range_iter<T>
0343 {
0344 using Base = step_range_iter<T>;
0345
0346 public:
0347 using TraitsT = typename Base::TraitsT;
0348 using counter_type = typename TraitsT::counter_type;
0349
0350 CELER_FUNCTION
0351 inf_step_range_iter(T current = TraitsT::zero(), counter_type step = {})
0352 : Base(current, step)
0353 {
0354 }
0355
0356 CELER_FUNCTION bool operator==(inf_step_range_iter const&) const
0357 {
0358 return false;
0359 }
0360
0361 CELER_FUNCTION bool operator!=(inf_step_range_iter const&) const
0362 {
0363 return true;
0364 }
0365 };
0366
0367
0368
0369
0370
0371 template<class T>
0372 class StepRange
0373 {
0374 public:
0375 using IterT = step_range_iter<T>;
0376 using counter_type = typename RangeTypeTraits<T>::counter_type;
0377
0378 CELER_FUNCTION StepRange(T begin, T end, counter_type step)
0379 : begin_(begin, step), end_(end, step)
0380 {
0381 }
0382
0383 CELER_CONSTEXPR_FUNCTION IterT begin() const { return begin_; }
0384 CELER_CONSTEXPR_FUNCTION IterT end() const { return end_; }
0385
0386 private:
0387 IterT begin_;
0388 IterT end_;
0389 };
0390
0391
0392
0393
0394
0395 template<class T>
0396 class InfStepRange
0397 {
0398 public:
0399 using IterT = inf_step_range_iter<T>;
0400 using counter_type = typename RangeTypeTraits<T>::counter_type;
0401
0402
0403 CELER_FUNCTION InfStepRange(T begin, counter_type step)
0404 : begin_(begin, step)
0405 {
0406 }
0407
0408 CELER_CONSTEXPR_FUNCTION IterT begin() const { return begin_; }
0409 CELER_CONSTEXPR_FUNCTION IterT end() const { return IterT(); }
0410
0411 private:
0412 IterT begin_;
0413 };
0414
0415 }
0416 }