Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
bitset.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstdint>
5#include <type_traits>
6
7#include "gaia/cnt/bitset_iterator.h"
8
9namespace gaia {
10 namespace cnt {
13 template <uint32_t NBits>
14 class bitset {
15 public:
17 static constexpr uint32_t BitCount = NBits;
18 static_assert(NBits > 0);
19
20 private:
21 template <bool Use32Bit>
22 struct size_type_selector {
23 using type = std::conditional_t<Use32Bit, uint32_t, uint64_t>;
24 };
25
26 public:
28 static constexpr uint32_t BitsPerItem = (NBits / 64) > 0 ? 64 : 32;
30 static constexpr uint32_t Items = (NBits + BitsPerItem - 1) / BitsPerItem;
31
33 using size_type = typename size_type_selector<BitsPerItem == 32>::type;
34
35 private:
36 static constexpr bool HasTrailingBits = (NBits % BitsPerItem) != 0;
37 static constexpr size_type LastItemMask = ((size_type)1 << (NBits % BitsPerItem)) - 1;
38
39 size_type m_data[Items]{};
40
43 return m_data[wordIdx];
44 }
45
46 public:
56 friend iter;
57 friend iter_inv;
58 friend iter_rev;
59 friend iter_rev_inv;
61
64 constexpr size_type* data() {
65 return &m_data[0];
66 }
67
70 constexpr const size_type* data() const {
71 return &m_data[0];
72 }
73
76 GAIA_NODISCARD constexpr uint32_t items() const {
77 return Items;
78 }
79
82 constexpr iter begin() const {
83 return iter(*this, 0, true);
84 }
85
88 constexpr iter end() const {
89 return iter(*this, NBits, false);
90 }
91
94 constexpr iter_rev rbegin() const {
95 return iter_rev(*this, NBits, false);
96 }
97
100 constexpr iter_rev rend() const {
101 return iter_rev(*this, 0, true);
102 }
103
106 constexpr iter_inv ibegin() const {
107 return iter_inv(*this, 0, true);
108 }
109
112 constexpr iter_inv iend() const {
113 return iter_inv(*this, NBits, false);
114 }
115
118 constexpr iter_rev_inv ribegin() const {
119 return iter_rev_inv(*this, NBits, false);
120 }
121
124 constexpr iter_rev_inv riend() const {
125 return iter_rev_inv(*this, 0, true);
126 }
127
131 GAIA_NODISCARD constexpr bool operator[](uint32_t pos) const {
132 return test(pos);
133 }
134
138 GAIA_NODISCARD constexpr bool operator==(const bitset& other) const {
139 GAIA_FOR(Items) {
140 if (m_data[i] != other.m_data[i])
141 return false;
142 }
143 return true;
144 }
145
149 GAIA_NODISCARD constexpr bool operator!=(const bitset& other) const {
150 GAIA_FOR(Items) {
151 if (m_data[i] == other.m_data[i])
152 return false;
153 }
154 return true;
155 }
156
158 constexpr void set() {
159 if constexpr (HasTrailingBits) {
160 GAIA_FOR(Items - 1) m_data[i] = (size_type)-1;
161 m_data[Items - 1] = LastItemMask;
162 } else {
163 GAIA_FOR(Items) m_data[i] = (size_type)-1;
164 }
165 }
166
170 constexpr void set(uint32_t pos, bool value = true) {
171 GAIA_ASSERT(pos < NBits);
172 if (value)
173 m_data[pos / BitsPerItem] |= ((size_type)1 << (pos % BitsPerItem));
174 else
175 m_data[pos / BitsPerItem] &= ~((size_type)1 << (pos % BitsPerItem));
176 }
177
180 constexpr bitset& flip() {
181 if constexpr (HasTrailingBits) {
182 GAIA_FOR(Items - 1) m_data[i] = ~m_data[i];
183 m_data[Items - 1] = (~m_data[Items - 1]) & LastItemMask;
184 } else {
185 GAIA_FOR(Items) m_data[i] = ~m_data[i];
186 }
187 return *this;
188 }
189
192 constexpr void flip(uint32_t pos) {
193 GAIA_ASSERT(pos < NBits);
194 const auto wordIdx = pos / BitsPerItem;
195 const auto bitIdx = pos % BitsPerItem;
196 m_data[wordIdx] ^= ((size_type)1 << bitIdx);
197 }
198
204 GAIA_ASSERT(bitFrom <= bitTo);
205 GAIA_ASSERT(bitTo < size());
206
207 // The following can't happen because we always have at least 1 bit
208 // if GAIA_UNLIKELY (size() == 0)
209 // return *this;
210
213
214 auto getMask = [](uint32_t from, uint32_t to) -> size_type {
215 const auto diff = to - from;
216 // Set all bits when asking for the full range
217 if (diff == BitsPerItem - 1)
218 return (size_type)-1;
219
220 return ((size_type(1) << (diff + 1)) - 1) << from;
221 };
222
223 if (wordIdxFrom == wordIdxTo) {
225 } else {
226 // First word
228 // Middle
229 GAIA_FOR2(wordIdxFrom + 1, wordIdxTo) m_data[i] = ~m_data[i];
230 // Last word
231 m_data[wordIdxTo] ^= getMask(0, bitTo % BitsPerItem);
232 }
233
234 return *this;
235 }
236
238 constexpr void reset() {
239 GAIA_FOR(Items) m_data[i] = 0;
240 }
241
244 constexpr void reset(uint32_t pos) {
245 GAIA_ASSERT(pos < NBits);
246 m_data[pos / BitsPerItem] &= ~((size_type)1 << (pos % BitsPerItem));
247 }
248
252 GAIA_NODISCARD constexpr bool test(uint32_t pos) const {
253 GAIA_ASSERT(pos < NBits);
254 return (m_data[pos / BitsPerItem] & ((size_type)1 << (pos % BitsPerItem))) != 0;
255 }
256
259 GAIA_NODISCARD constexpr bool all() const {
260 if constexpr (HasTrailingBits) {
261 GAIA_FOR(Items - 1) {
262 if (m_data[i] != (size_type)-1)
263 return false;
264 }
265 return (m_data[Items - 1] & LastItemMask) == LastItemMask;
266 } else {
267 GAIA_FOR(Items) {
268 if (m_data[i] != (size_type)-1)
269 return false;
270 }
271 return true;
272 }
273 }
274
277 GAIA_NODISCARD constexpr bool any() const {
278 GAIA_FOR(Items) {
279 if (m_data[i] != 0)
280 return true;
281 }
282 return false;
283 }
284
287 GAIA_NODISCARD constexpr bool none() const {
288 GAIA_FOR(Items) {
289 if (m_data[i] != 0)
290 return false;
291 }
292 return true;
293 }
294
297 GAIA_NODISCARD uint32_t count() const {
298 uint32_t total = 0;
299
300 GAIA_MSVC_WARNING_PUSH()
301 GAIA_MSVC_WARNING_DISABLE(4244)
302 if constexpr (sizeof(size_type) == 4) {
303 GAIA_FOR(Items) total += GAIA_POPCNT(m_data[i]);
304 } else {
305 GAIA_FOR(Items) total += GAIA_POPCNT64(m_data[i]);
306 }
307 GAIA_MSVC_WARNING_POP()
308
309 return total;
310 }
311
314 GAIA_NODISCARD constexpr uint32_t size() const {
315 return NBits;
316 }
317 };
318 } // namespace cnt
319} // namespace gaia
Fixed-size bit set.
Definition bitset.h:14
constexpr iter end() const
Returns the forward set-bit sentinel.
Definition bitset.h:88
typename size_type_selector< BitsPerItem==32 >::type size_type
Unsigned backing-word type.
Definition bitset.h:33
constexpr iter begin() const
Returns an iterator to the first set bit.
Definition bitset.h:82
static constexpr uint32_t BitCount
Number of addressable bits.
Definition bitset.h:17
const_iterator_inverse< bitset > iter_inv
Forward iterator over unset bit indices.
Definition bitset.h:50
constexpr iter_inv iend() const
Returns the forward unset-bit sentinel.
Definition bitset.h:112
GAIA_NODISCARD constexpr bool operator[](uint32_t pos) const
Tests a bit.
Definition bitset.h:131
GAIA_NODISCARD constexpr bool all() const
Checks if all bits are set.
Definition bitset.h:259
static constexpr uint32_t BitsPerItem
Number of bits stored in each backing word.
Definition bitset.h:28
constexpr size_type * data()
Returns the mutable backing-word storage.
Definition bitset.h:64
constexpr void reset()
Unsets all bits.
Definition bitset.h:238
constexpr iter_rev_inv riend() const
Returns the reverse unset-bit sentinel.
Definition bitset.h:124
constexpr iter_inv ibegin() const
Returns an iterator to the first unset bit.
Definition bitset.h:106
GAIA_NODISCARD constexpr bool none() const
Checks if all bits are reset.
Definition bitset.h:287
GAIA_NODISCARD constexpr bool test(uint32_t pos) const
Returns the value of one bit.
Definition bitset.h:252
static constexpr uint32_t Items
Number of backing words.
Definition bitset.h:30
GAIA_NODISCARD uint32_t count() const
Returns the number of set bits.
Definition bitset.h:297
constexpr void reset(uint32_t pos)
Unsets one bit.
Definition bitset.h:244
GAIA_NODISCARD constexpr bool operator!=(const bitset &other) const
Compares two bit sets for inequality.
Definition bitset.h:149
constexpr iter_rev rbegin() const
Returns an iterator to the last set bit.
Definition bitset.h:94
constexpr void set(uint32_t pos, bool value=true)
Sets the bit at the given position.
Definition bitset.h:170
constexpr bitset & flip(uint32_t bitFrom, uint32_t bitTo)
Flips an inclusive range of bits.
Definition bitset.h:203
constexpr const size_type * data() const
Returns the immutable backing-word storage.
Definition bitset.h:70
GAIA_NODISCARD constexpr uint32_t size() const
Returns the number of bits the bitset can hold.
Definition bitset.h:314
GAIA_NODISCARD constexpr bool any() const
Checks if any bit is set.
Definition bitset.h:277
GAIA_NODISCARD constexpr bool operator==(const bitset &other) const
Compares two bit sets for equality.
Definition bitset.h:138
const_reverse_iterator< bitset > iter_rev
Reverse iterator over set bit indices.
Definition bitset.h:52
const_reverse_inverse_iterator< bitset > iter_rev_inv
Reverse iterator over unset bit indices.
Definition bitset.h:54
constexpr iter_rev_inv ribegin() const
Returns an iterator to the last unset bit.
Definition bitset.h:118
constexpr void set()
Sets all bits.
Definition bitset.h:158
const_iterator< bitset > iter
Forward iterator over set bit indices.
Definition bitset.h:48
constexpr iter_rev rend() const
Returns the reverse set-bit sentinel.
Definition bitset.h:100
GAIA_NODISCARD constexpr uint32_t items() const
Returns the number of words used by the bitset internally.
Definition bitset.h:76
constexpr bitset & flip()
Flips all bits.
Definition bitset.h:180
constexpr void flip(uint32_t pos)
Flips one bit.
Definition bitset.h:192
Array with variable size of elements of type.
Definition darray_impl.h:27