Clingo
Loading...
Searching...
No Matches
index_sequence.hh
1#pragma once
2
3#include <algorithm>
4#include <tuple>
5#include <vector>
6
7namespace CppClingo::Util {
8
11
15template <class T> class index_sequence {
16 public:
18 class iterator {
19 public:
21 using iterator_category = std::forward_iterator_tag;
23 using value_type = T;
25 using difference_type = std::ptrdiff_t;
27 using reference = T;
29 using pointer = void;
30
32 iterator() = default;
33
35 auto operator*() const -> reference { return std::get<2>(*it_) + static_cast<T>(idx_); }
36
38 auto operator++() -> iterator & {
39 ++idx_;
40 if (idx_ == std::get<1>(*it_)) {
41 ++it_;
42 }
43 return *this;
44 }
45
47 auto operator++(int) -> iterator {
48 auto tmp = *this;
49 ++(*this);
50 return tmp;
51 }
52
54 auto operator==(const iterator &other) const -> bool { return idx_ == other.idx_; }
55
57 auto operator!=(const iterator &other) const -> bool { return !(*this == other); }
58
59 private:
60 using interval_iterator = std::vector<std::tuple<size_t, size_t, T>>::const_iterator;
61
62 iterator(interval_iterator it, size_t idx) : it_{it}, idx_{idx} {}
63
64 interval_iterator it_;
65 size_t idx_ = 0;
66 };
67
69 void add(T value) {
70 if (values_.empty()) {
71 values_.emplace_back(0, 1, value);
72 } else {
73 auto &[l, r, y] = values_.back();
74 if (static_cast<T>(r) + y == value) {
75 ++r;
76 } else {
77 values_.emplace_back(size(), size() + 1, value - static_cast<T>(size()));
78 }
79 }
80 }
81
83 void assign(T l, T r) {
84 values_.clear();
85 if (l < r) {
86 values_.emplace_back(0, static_cast<size_t>(r - l), l);
87 }
88 }
89
91 [[nodiscard]] auto operator[](size_t index) const -> T {
92 assert(index < size() && last_ < values_.size());
93 auto const &[l, r, y] = values_[last_];
94 assert(l < r);
95 auto ib = index < l ? values_.begin() : values_.begin() + last_;
96 auto ie = index < r ? values_.begin() + last_ + 1 : values_.end();
97 auto it = std::upper_bound(ib, ie, index, [](auto const &a, auto const &b) { return a < std::get<1>(b); });
98 last_ = static_cast<size_t>(std::distance(values_.begin(), it));
99 return static_cast<T>(index) + std::get<2>(*it);
100 }
102 [[nodiscard]] auto find(T value) const -> size_t {
103 // TODO: has linear complexity in the worst case:
104 // - locality could be improved
105 // - reverse mapping could be stored
106 for (auto const &[l, r, y] : values_) {
107 auto i = static_cast<size_t>(value - y);
108 if (y <= value && l <= i && i < r) {
109 return i;
110 }
111 }
112 return size();
113 }
115 [[nodiscard]] auto size() const -> size_t { return empty() ? 0 : std::get<1>(values_.back()); }
117 [[nodiscard]] auto empty() const -> bool { return values_.empty(); }
119 [[nodiscard]] auto begin() const -> iterator { return {values_.cbegin(), 0}; }
121 [[nodiscard]] auto end() const -> iterator { return {values_.cend(), size()}; }
122
123 private:
124 std::vector<std::tuple<size_t, size_t, T>> values_;
125 size_t mutable last_ = 0;
126};
127
129
130} // namespace CppClingo::Util
Const iterator for index sequence.
Definition index_sequence.hh:18
auto operator!=(const iterator &other) const -> bool
Compare two iterators.
Definition index_sequence.hh:57
void pointer
The pointer type.
Definition index_sequence.hh:29
auto operator*() const -> reference
Get the current value.
Definition index_sequence.hh:35
std::forward_iterator_tag iterator_category
The iterator category.
Definition index_sequence.hh:21
iterator()=default
Construct an end iterator.
T value_type
The value type.
Definition index_sequence.hh:23
auto operator++() -> iterator &
Increment the iterator.
Definition index_sequence.hh:38
auto operator++(int) -> iterator
Post increment the iterator.
Definition index_sequence.hh:47
T reference
The reference type.
Definition index_sequence.hh:27
auto operator==(const iterator &other) const -> bool
Compare two iterators.
Definition index_sequence.hh:54
std::ptrdiff_t difference_type
The difference type.
Definition index_sequence.hh:25
Container to store integer sequences.
Definition index_sequence.hh:15
auto operator[](size_t index) const -> T
Get the i-th integer in the sequence.
Definition index_sequence.hh:91
auto end() const -> iterator
Get an iterator to the end of the sequence.
Definition index_sequence.hh:121
auto empty() const -> bool
Check whether the sequence is empty.
Definition index_sequence.hh:117
void assign(T l, T r)
Set the sequence to the interval [l,r-1].
Definition index_sequence.hh:83
void add(T value)
Add an integer to the sequence.
Definition index_sequence.hh:69
auto begin() const -> iterator
Get an iterator to the beginning of the sequence.
Definition index_sequence.hh:119
auto size() const -> size_t
Get the number of indices in the sequence.
Definition index_sequence.hh:115
auto find(T value) const -> size_t
Check if the sequence contains an element.
Definition index_sequence.hh:102