Clingo
Loading...
Searching...
No Matches
index_sequence.hh
1#pragma once
2
3#include <algorithm>
4#include <cassert>
5#include <cstddef>
6#include <iterator>
7#include <utility>
8
9#include <clingo/util/small_vector.hh>
10
11namespace CppClingo::Util {
12
15
19template <class T> class index_sequence {
20 public:
22 class iterator {
23 public:
24 friend class index_sequence;
26 using iterator_category = std::forward_iterator_tag;
28 using value_type = T;
30 using difference_type = std::ptrdiff_t;
32 using reference = T;
34 using pointer = void;
35
37 iterator() = default;
38
40 auto operator*() const -> reference { return it_->second + static_cast<T>(idx_ - start_); }
41
43 auto operator++() -> iterator & {
44 ++idx_;
45 if (idx_ == it_->first) {
46 start_ = it_->first;
47 ++it_;
48 }
49 return *this;
50 }
51
53 auto operator++(int) -> iterator {
54 auto tmp = *this;
55 ++(*this);
56 return tmp;
57 }
58
60 auto operator==(const iterator &other) const -> bool { return idx_ == other.idx_; }
61
63 auto operator!=(const iterator &other) const -> bool { return !(*this == other); }
64
65 private:
66 using interval_iterator = small_vector<std::pair<size_t, T>, 1>::const_iterator;
67
68 iterator(interval_iterator it, size_t idx, size_t start) : it_{it}, idx_{idx}, start_{start} {}
69
70 interval_iterator it_;
71 size_t idx_ = 0;
72 size_t start_ = 0;
73 };
74
76 void add(T value) {
77 if (values_.empty()) {
78 values_.emplace_back(1, value);
79 } else {
80 auto &[r, s] = values_.back();
81 auto l = values_.size() > 1 ? values_[values_.size() - 2].first : size_t{0};
82 if (s + static_cast<T>(r - l) == value) {
83 ++r;
84 } else {
85 values_.emplace_back(size() + 1, value);
86 }
87 }
88 }
89
91 void assign(T s, T e) {
92 last_ = 0;
93 values_.clear();
94 if (s < e) {
95 values_.emplace_back(static_cast<size_t>(e - s), s);
96 }
97 }
98
100 [[nodiscard]] auto operator[](size_t index) const -> T {
101 assert(index < size() && last_ < values_.size());
102 auto l = last_ > 0 ? values_[last_ - 1].first : size_t{0};
103 auto r = values_[last_].first;
104 assert(l < r);
105 auto ib = index < l ? values_.begin() : values_.begin() + last_;
106 auto ie = index < r ? values_.begin() + last_ + 1 : values_.end();
107 auto it = std::upper_bound(ib, ie, index, [](auto const &a, auto const &b) { return a < b.first; });
108 last_ = static_cast<size_t>(std::distance(values_.begin(), it));
109 auto start = last_ > 0 ? values_[last_ - 1].first : size_t{0};
110 return it->second + static_cast<T>(index - start);
111 }
115 [[nodiscard]] auto find(T x) const -> size_t {
116 // NOTE: has linear complexity in the worst case:
117 // - locality could be improved
118 // - reverse mapping could be stored
119 size_t l = 0;
120 for (auto const &[r, s] : values_) {
121 auto e = s + static_cast<T>(r - l);
122 if (s <= x && x < e) {
123 return l + static_cast<size_t>(x - s);
124 }
125 l = r;
126 }
127 return size();
128 }
130 [[nodiscard]] auto size() const -> size_t { return empty() ? 0 : values_.back().first; }
132 [[nodiscard]] auto empty() const -> bool { return values_.empty(); }
134 [[nodiscard]] auto begin() const -> iterator { return {values_.cbegin(), 0, 0}; }
136 [[nodiscard]] auto end() const -> iterator { return {values_.cend(), size(), size()}; }
137
138 private:
140 size_t mutable last_ = 0;
141};
142
144
145} // namespace CppClingo::Util
Const iterator for index sequence.
Definition index_sequence.hh:22
auto operator!=(const iterator &other) const -> bool
Compare two iterators.
Definition index_sequence.hh:63
void pointer
The pointer type.
Definition index_sequence.hh:34
auto operator*() const -> reference
Get the current value.
Definition index_sequence.hh:40
std::forward_iterator_tag iterator_category
The iterator category.
Definition index_sequence.hh:26
iterator()=default
Construct an end iterator.
T value_type
The value type.
Definition index_sequence.hh:28
auto operator++() -> iterator &
Increment the iterator.
Definition index_sequence.hh:43
auto operator++(int) -> iterator
Post increment the iterator.
Definition index_sequence.hh:53
T reference
The reference type.
Definition index_sequence.hh:32
auto operator==(const iterator &other) const -> bool
Compare two iterators.
Definition index_sequence.hh:60
std::ptrdiff_t difference_type
The difference type.
Definition index_sequence.hh:30
Container to store integer sequences.
Definition index_sequence.hh:19
auto operator[](size_t index) const -> T
Get the i-th integer in the sequence.
Definition index_sequence.hh:100
void assign(T s, T e)
Set the sequence to the interval [s, e).
Definition index_sequence.hh:91
auto end() const -> iterator
Get an iterator to the end of the sequence.
Definition index_sequence.hh:136
auto find(T x) const -> size_t
Get the index of the value in the sequence.
Definition index_sequence.hh:115
auto empty() const -> bool
Check whether the sequence is empty.
Definition index_sequence.hh:132
void add(T value)
Add an integer to the sequence.
Definition index_sequence.hh:76
auto begin() const -> iterator
Get an iterator to the beginning of the sequence.
Definition index_sequence.hh:134
auto size() const -> size_t
Get the number of indices in the sequence.
Definition index_sequence.hh:130
A vector that misuses the begin, end and capacity pointers to store elements.
Definition small_vector.hh:26
auto cend() const -> const_iterator
Get a const iterator to the end of the vector.
Definition small_vector.hh:171
auto cbegin() const -> const_iterator
Get a const iterator to the beginning of the vector.
Definition small_vector.hh:154
auto begin() -> iterator
Get an iterator to the beginning of the vector.
Definition small_vector.hh:145
void emplace_back(U &&...args)
Emplace an element after the last element.
Definition small_vector.hh:285
auto end() -> iterator
Get an iterator to the end of the vector.
Definition small_vector.hh:157
auto back() -> reference
Get the last element in the vector.
Definition small_vector.hh:225
auto empty() const -> bool
Check if the vector is empty.
Definition small_vector.hh:130
auto size() const -> size_t
Get the size of the vector.
Definition small_vector.hh:122
void clear() noexcept
Clear the vector.
Definition small_vector.hh:314