CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
DynamicBitSet.hpp
Go to the documentation of this file.
1//
2// CeresEngine - A game development framework
3//
4// Created by Rogiel Sulzbach.
5// Copyright (c) 2018-2022 Rogiel Sulzbach. All rights reserved.
6//
7
8#pragma once
9
11
14
15#include <cassert>
16#include <cstdint>
17#include <vector>
18
19namespace CeresEngine {
20
22 explicit DynamicBitSetIteratorBase(const size_t i) noexcept : index(i) {}
23 void inc() { ++index; }
24 void dec() { --index; }
25 bool operator==(const DynamicBitSetIteratorBase& other) const { return index == other.index; }
26 bool operator!=(const DynamicBitSetIteratorBase& other) const { return index != other.index; }
27
29 size_t index;
30 };
31
40 template<typename Buffer = Vector<uint32_t>> class DynamicBitSet {
41 public:
43 using word_type = typename buffer_type::value_type;
44 static_assert(std::is_unsigned<word_type>::value, "word_type must be unsigned");
45 using allocator_type = typename buffer_type::allocator_type;
47 using buffer_size_type = typename buffer_type::size_type;
48 static constexpr uint8_t bits_per_word = sizeof(word_type) * 8;
49
52 : mBuffer(word_size(size), value, alloc), mSize(size) {}
53
54 // copy and move
55 DynamicBitSet(const DynamicBitSet& x) = default;
57
58 DynamicBitSet(DynamicBitSet&& x) noexcept : mBuffer(std::move(x.mBuffer)), mSize(x.mSize) { x.mSize = 0; }
60 mBuffer = std::move(x.mBuffer);
61 mSize = x.mSize;
62 x.mSize = 0;
63 return *this;
64 }
65
66 // access
70 [[nodiscard]] const word_type* data() const noexcept { return mBuffer.data(); }
71 [[nodiscard]] bool empty() const noexcept { return mBuffer.empty(); }
72 [[nodiscard]] size_t byte_size() const noexcept { return (mSize + 7) / 8; }
73 [[nodiscard]] const buffer_type& buffer() const { return mBuffer; }
74
76 [[nodiscard]] bool test(const size_type i) const noexcept { return mBuffer[word_index(i)] & word_mask(i); }
77
80 if(empty()) {
81 return false;
82 }
83 auto it = mBuffer.begin();
84 auto endit = it + mSize / bits_per_word;
85 for(; it != endit; ++it) {
86 if(*it != ~word_type(0)) {
87 return false;
88 }
89 }
90 if(endit != mBuffer.end()) {
92 if((mBuffer.back() & mask) != mask) {
93 return false;
94 }
95 }
96 return true;
97 }
98
101 if(empty()) {
102 return false;
103 }
104 auto it = mBuffer.begin();
105 auto endit = it + mSize / bits_per_word;
106 for(; it != endit; ++it) {
107 if(*it != 0) {
108 return true;
109 }
110 }
111 if(endit != mBuffer.end()) {
113 if(mBuffer.back() & mask) {
114 return true;
115 }
116 }
117 return false;
118 }
119
121 [[nodiscard]] bool none() const noexcept { return !any(); }
122
123 // modifiers
124 // set bit to true
125 void set(const size_type i) { mBuffer[word_index(i)] |= word_mask(i); }
126 // set bit to false
128 // set bit to value
129 void set(const size_type i, const bool b) {
130 if(b) {
131 set(i);
132 } else {
133 reset(i);
134 }
135 }
136 // flip bit
137 void flip(const size_type i) { mBuffer[word_index(i)] ^= word_mask(i); }
138
139 // size modifiers
141 void resize(const size_type size) {
142 const auto pad = mSize % bits_per_word;
143 if(pad) {
144 // clear the tail of the buf with zeroes in case they remain from previous ops
145 mBuffer.back() &= word_mask(pad) - 1;
146 }
147 mSize = size;
149 }
150 void push_back(const bool b) {
151 resize(mSize + 1);
152 set(mSize - 1, b);
153 }
154
155 void assign(const buffer_type& buf) {
156 mBuffer = buf;
158 }
159
160 void append(const DynamicBitSet& other) {
161 if(other.empty()) {
162 return;
163 }
164
165 const auto pad = mSize % bits_per_word;
166 if(pad == 0) {
167 // lucky
168 mBuffer.insert(mBuffer.end(), other.mBuffer.begin(), other.mBuffer.end());
169 mSize += other.size();
170 return;
171 }
172
173 auto back_buf_index = mBuffer.size() - 1;
174 resize(mSize + other.mSize);
175 auto myi = mBuffer.begin() + back_buf_index;
176 for(size_t i = 0; i < other.mBuffer.size(); ++i) {
177 auto cur = other.mBuffer[i];
178 *myi |= cur << pad;
179 ++myi;
180 if(myi == mBuffer.end()) {
181 break;
182 }
183 *myi = cur >> (bits_per_word - pad);
184 }
185 }
186
187 // vector-like
188 struct bitref {
190 [[nodiscard]] bool test() const { return word & mask; }
191 void set() { word |= mask; }
192 void reset() { word &= ~mask; }
193 void flip() { word ^= mask; }
194 void set(const bool b) {
195 if(b) {
196 set();
197 } else {
198 reset();
199 }
200 }
201 [[nodiscard]] operator bool() const { return test(); }
202 bitref operator=(const bool b) {
203 set(b);
204 return *this;
205 }
206
207 private:
210 };
211
212 [[nodiscard]] bool operator[](const size_type i) const { return test(i); }
214
218 inc();
219 return *this;
220 }
222 auto ret = *this;
223 inc();
224 return ret;
225 }
227 dec();
228 return *this;
229 }
231 auto ret = *this;
232 dec();
233 return ret;
234 }
235 friend iterator operator+(iterator a, ptrdiff_t b) { return iterator(a.bitset, a.index + b); }
236 friend iterator operator-(iterator a, ptrdiff_t b) { return iterator(a.bitset, a.index - b); }
237 bool operator*() const { return bitset.test(index); }
239
241 };
242
247 inc();
248 return *this;
249 }
251 auto ret = *this;
252 inc();
253 return ret;
254 }
256 dec();
257 return *this;
258 }
260 auto ret = *this;
261 dec();
262 return ret;
263 }
266 bool operator*() const { return bitset.test(index); }
267
269 };
270
271 [[nodiscard]] iterator begin() { return iterator(*this, 0); }
272 [[nodiscard]] iterator end() { return iterator(*this, mSize); }
273
274 [[nodiscard]] const_iterator begin() const { return const_iterator(*this, 0); }
275 [[nodiscard]] const_iterator end() const { return const_iterator(*this, mSize); }
276
277 void copy(iterator from, iterator to, const_iterator source) {
278 while(from.index % bits_per_word) {
279 // copy single bits until we reach a word boundary of our bitset
280 if(from == to) {
281 return;
282 }
283 *from++ = *source++;
284 }
285
286 const auto pad = source.index % bits_per_word;
287 auto own_windex = word_index(from.index);
288 auto src_windex = word_index(source.index);
289 auto& src = source.bitset.mBuffer;
290 // for each whole word of our bitset
291 while(to - from >= bits_per_word) {
292 mBuffer[own_windex] = src[src_windex] >> pad;
293 if(pad) {
294 // there is padding so there must be at least one more element in the source
295 mBuffer[own_windex] |= src[src_windex + 1] << (bits_per_word - pad);
296 }
297 ++own_windex;
298 ++src_windex;
299 from.index += bits_per_word;
300 }
301
302 if(from == to) {
303 return; // we finished on a word boundary
304 }
305
306 // now what remains is some bits from source that need to be splicet onto our last element
307 const auto rpad = to.index % bits_per_word;
308 mBuffer[own_windex] = ((src[src_windex] >> pad) & (word_mask(rpad) - 1)) | (mBuffer[own_windex] & ~(word_mask(rpad) - 1));
309 }
310
311 // static ops
312
314 static constexpr buffer_size_type word_size(const size_type size) noexcept { return (size + bits_per_word - 1) / bits_per_word; }
315
317 static constexpr buffer_size_type word_index(const size_type i) noexcept { return i / bits_per_word; }
318
320 static constexpr uint8_t bit_index(const size_type i) noexcept { return uint8_t(i % bits_per_word); }
321
323 static constexpr word_type word_mask(const size_type index) noexcept { return word_type(1) << bit_index(index); }
324
325 private:
327 size_type mSize; // doesn't need to be divisible by bits_per_word
328 };
329
331 template<size_t N, typename RawAllocator = DefaultAllocator> using SmallDynamicBitSet = DynamicBitSet<SmallVector<UInt32, N, RawAllocator>>;
332
333} // namespace CeresEngine
Represents a secure buffer i.e.
Definition Buffer.hpp:28
Iterator end() noexcept
Gets a iterator that points to the end of the buffer.
Definition Buffer.hpp:148
Iterator begin() noexcept
Gets a iterator that points to the begining of the buffer.
Definition Buffer.hpp:144
Byte * data() noexcept
Gets a pointer to the raws buffer data.
Definition Buffer.hpp:107
void reserve(size_t newCapacity) noexcept
Reservers at least newCapacity bytes in the buffer.
size_t size() const noexcept
Gets the number of bytes currently allocated in the buffer.
Definition Buffer.hpp:123
void resize(size_t newSize) noexcept
Resizes the buffer to be able to store up-to "newSize" bytes.
size_t mSize
The buffer size.
Definition Buffer.hpp:41
bool empty() const noexcept
Checks if the buffer is currently empty (i.e.
Definition Buffer.hpp:131
The DynamicBitSet, which similar to BitSet, but does not have the size in its type.
Definition DynamicBitSet.hpp:40
static constexpr word_type word_mask(const size_type index) noexcept
Mask representing a mask for a given bit within its word.
Definition DynamicBitSet.hpp:323
static constexpr buffer_size_type word_index(const size_type i) noexcept
Index of a word in buffer for a given bit index.
Definition DynamicBitSet.hpp:317
void reset(const size_type i)
Definition DynamicBitSet.hpp:127
void set(const size_type i, const bool b)
Definition DynamicBitSet.hpp:129
buffer_size_type word_size() const noexcept
Definition DynamicBitSet.hpp:68
word_type * data() noexcept
Definition DynamicBitSet.hpp:69
iterator end()
Definition DynamicBitSet.hpp:272
DynamicBitSet(DynamicBitSet &&x) noexcept
Definition DynamicBitSet.hpp:58
void assign(const buffer_type &buf)
Definition DynamicBitSet.hpp:155
bool all() const noexcept
All bits true?
Definition DynamicBitSet.hpp:79
bool any() const noexcept
Any bits true?
Definition DynamicBitSet.hpp:100
typename buffer_type::value_type word_type
Definition DynamicBitSet.hpp:43
buffer_type mBuffer
Definition DynamicBitSet.hpp:326
bool none() const noexcept
No bits true?
Definition DynamicBitSet.hpp:121
bool operator[](const size_type i) const
Definition DynamicBitSet.hpp:212
typename buffer_type::allocator_type allocator_type
Definition DynamicBitSet.hpp:45
DynamicBitSet & operator=(const DynamicBitSet &x)=default
bool empty() const noexcept
Definition DynamicBitSet.hpp:71
const_iterator begin() const
Definition DynamicBitSet.hpp:274
size_t byte_size() const noexcept
Definition DynamicBitSet.hpp:72
void flip(const size_type i)
Definition DynamicBitSet.hpp:137
size_type mSize
Definition DynamicBitSet.hpp:327
bitref operator[](const size_type i)
Definition DynamicBitSet.hpp:213
void set(const size_type i)
Definition DynamicBitSet.hpp:125
iterator begin()
Definition DynamicBitSet.hpp:271
const buffer_type & buffer() const
Definition DynamicBitSet.hpp:73
void append(const DynamicBitSet &other)
Definition DynamicBitSet.hpp:160
bool test(const size_type i) const noexcept
Test single bit.
Definition DynamicBitSet.hpp:76
DynamicBitSet(const size_type size, word_type value=0, const allocator_type &alloc=allocator_type())
Definition DynamicBitSet.hpp:51
void resize(const size_type size)
Definition DynamicBitSet.hpp:141
DynamicBitSet(const allocator_type &alloc=allocator_type()) noexcept
Definition DynamicBitSet.hpp:50
static constexpr uint8_t bit_index(const size_type i) noexcept
Index of a bit within its word.
Definition DynamicBitSet.hpp:320
const_iterator end() const
Definition DynamicBitSet.hpp:275
DynamicBitSet(const DynamicBitSet &x)=default
void reserve(const size_type size)
Definition DynamicBitSet.hpp:140
void copy(iterator from, iterator to, const_iterator source)
Definition DynamicBitSet.hpp:277
void push_back(const bool b)
Definition DynamicBitSet.hpp:150
DynamicBitSet & operator=(DynamicBitSet &&x) noexcept
Definition DynamicBitSet.hpp:59
static constexpr uint8_t bits_per_word
Definition DynamicBitSet.hpp:48
static constexpr buffer_size_type word_size(const size_type size) noexcept
Required word size for a given bit size.
Definition DynamicBitSet.hpp:314
size_t size_type
Definition DynamicBitSet.hpp:46
const word_type * data() const noexcept
Definition DynamicBitSet.hpp:70
size_type size() const noexcept
Definition DynamicBitSet.hpp:67
typename buffer_type::size_type buffer_size_type
Definition DynamicBitSet.hpp:47
Definition Application.hpp:19
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
Definition DynamicBitSet.hpp:188
word_type & word
Definition DynamicBitSet.hpp:208
bool test() const
Definition DynamicBitSet.hpp:190
void reset()
Definition DynamicBitSet.hpp:192
const word_type mask
Definition DynamicBitSet.hpp:209
void set(const bool b)
Definition DynamicBitSet.hpp:194
void flip()
Definition DynamicBitSet.hpp:193
bitref operator=(const bool b)
Definition DynamicBitSet.hpp:202
bitref(word_type &w, word_type m)
Definition DynamicBitSet.hpp:189
void set()
Definition DynamicBitSet.hpp:191
Definition DynamicBitSet.hpp:243
const_iterator operator--(int)
Definition DynamicBitSet.hpp:259
const DynamicBitSet & bitset
Definition DynamicBitSet.hpp:268
const_iterator(const DynamicBitSet &b, const size_t i)
Definition DynamicBitSet.hpp:244
friend const_iterator operator-(const_iterator a, ptrdiff_t b)
Definition DynamicBitSet.hpp:265
const_iterator & operator--()
Definition DynamicBitSet.hpp:255
bool operator*() const
Definition DynamicBitSet.hpp:266
const_iterator(iterator i)
Definition DynamicBitSet.hpp:245
friend const_iterator operator+(const_iterator a, ptrdiff_t b)
Definition DynamicBitSet.hpp:264
const_iterator & operator++()
Definition DynamicBitSet.hpp:246
const_iterator operator++(int)
Definition DynamicBitSet.hpp:250
Definition DynamicBitSet.hpp:215
iterator operator++(int)
Definition DynamicBitSet.hpp:221
iterator(DynamicBitSet &b, const size_t i)
Definition DynamicBitSet.hpp:216
iterator operator--(int)
Definition DynamicBitSet.hpp:230
iterator & operator++()
Definition DynamicBitSet.hpp:217
DynamicBitSet & bitset
Definition DynamicBitSet.hpp:240
friend iterator operator+(iterator a, ptrdiff_t b)
Definition DynamicBitSet.hpp:235
bool operator*() const
Definition DynamicBitSet.hpp:237
bitref operator*()
Definition DynamicBitSet.hpp:238
friend iterator operator-(iterator a, ptrdiff_t b)
Definition DynamicBitSet.hpp:236
iterator & operator--()
Definition DynamicBitSet.hpp:226
Definition DynamicBitSet.hpp:21
void inc()
Definition DynamicBitSet.hpp:23
void dec()
Definition DynamicBitSet.hpp:24
bool operator==(const DynamicBitSetIteratorBase &other) const
Definition DynamicBitSet.hpp:25
size_t index
Definition DynamicBitSet.hpp:29
bool operator!=(const DynamicBitSetIteratorBase &other) const
Definition DynamicBitSet.hpp:26
DynamicBitSetIteratorBase(const size_t i) noexcept
Definition DynamicBitSet.hpp:22
friend ptrdiff_t operator-(const DynamicBitSetIteratorBase &a, const DynamicBitSetIteratorBase &b)
Definition DynamicBitSet.hpp:28