17 struct size_type_selector {
18 static constexpr bool Use32Bit =
sizeof(size_t) == 4;
19 using type = std::conditional_t<Use32Bit, uint32_t, uint64_t>;
22 using difference_type =
typename size_type_selector::type;
23 using size_type =
typename size_type_selector::type;
24 using value_type = size_type;
25 using reference = size_type&;
26 using const_reference =
const size_type&;
27 using pointer = size_type*;
28 using const_pointer =
const size_type*;
30 static constexpr uint32_t BitsPerItem =
sizeof(
typename size_type_selector::type) * 8;
32 pointer m_pData =
nullptr;
33 uint32_t m_cnt = uint32_t(0);
34 uint32_t m_cap = uint32_t(0);
36 uint32_t items()
const {
37 return (m_cnt + BitsPerItem - 1) / BitsPerItem;
40 bool has_trailing_bits()
const {
41 return (m_cnt % BitsPerItem) != 0;
44 size_type last_item_mask()
const {
45 return ((size_type)1 << (m_cnt % BitsPerItem)) - 1;
48 void try_grow(uint32_t bitsWanted) {
49 uint32_t itemsOld = items();
50 if GAIA_UNLIKELY (bitsWanted >
size())
58 const uint32_t itemsNew = (m_cnt + BitsPerItem - 1) / BitsPerItem;
59 m_cap = itemsNew * BitsPerItem;
61 pointer pDataOld = m_pData;
62 m_pData = mem::AllocHelper::alloc<size_type, Allocator>(itemsNew);
64 if (pDataOld ==
nullptr) {
66 GAIA_FOR(itemsNew) m_pData[i] = 0;
69 mem::copy_elements<size_type, false>((uint8_t*)m_pData, (
const uint8_t*)pDataOld, itemsOld, 0, 0, 0);
70 GAIA_FOR2(itemsOld, itemsNew) m_pData[i] = 0;
73 mem::AllocHelper::free<Allocator>((
void*)pDataOld);
78 size_type data(uint32_t wordIdx)
const {
79 return m_pData[wordIdx];
98 dbitset(uint32_t reserveBits): m_cnt(1) {
103 mem::AllocHelper::free<Allocator>((
void*)m_pData);
108 mem::copy_elements<size_type, false>((uint8_t*)m_pData, (
const uint8_t*)other.m_pData, other.items(), 0, 0, 0);
112 GAIA_ASSERT(core::addressof(other) !=
this);
115 mem::copy_elements<size_type, false>((uint8_t*)m_pData, (
const uint8_t*)other.m_pData, other.items(), 0, 0, 0);
120 m_pData = other.m_pData;
124 other.m_pData =
nullptr;
130 GAIA_ASSERT(core::addressof(other) !=
this);
132 m_pData = other.m_pData;
136 other.m_pData =
nullptr;
142 void reserve(uint32_t bitsWanted) {
151 const uint32_t itemsOld = m_cap / BitsPerItem;
152 const uint32_t itemsNew = (bitsWanted + BitsPerItem - 1) / BitsPerItem;
153 if (itemsOld != itemsNew) {
154 auto* pDataOld = m_pData;
155 m_pData = mem::AllocHelper::alloc<size_type, Allocator>(itemsNew);
157 if (pDataOld ==
nullptr) {
159 GAIA_FOR(itemsNew) m_pData[i] = 0;
161 const uint32_t itemsOld2 = items();
163 mem::copy_elements<size_type, false>((uint8_t*)m_pData, (
const uint8_t*)pDataOld, itemsOld2, 0, 0, 0);
164 GAIA_FOR2(itemsOld2, itemsNew) m_pData[i] = 0;
167 mem::AllocHelper::free<Allocator>(pDataOld);
171 m_cap = itemsNew * BitsPerItem;
174 void resize(uint32_t bitsWanted) {
180 if (bitsWanted ==
size())
183 const uint32_t itemsOld = m_cap / BitsPerItem;
184 const uint32_t itemsNew = (bitsWanted + BitsPerItem - 1) / BitsPerItem;
185 if (itemsOld != itemsNew) {
186 auto* pDataOld = m_pData;
187 m_pData = mem::AllocHelper::alloc<size_type, Allocator>(itemsNew);
189 if (pDataOld ==
nullptr) {
191 GAIA_FOR(itemsNew) m_pData[i] = 0;
193 const uint32_t itemsOld2 = items();
195 mem::copy_elements<size_type, false>((uint8_t*)m_pData, (
const uint8_t*)pDataOld, itemsOld2, 0, 0, 0);
198 GAIA_FOR2(itemsOld2, itemsNew) m_pData[i] = 0;
201 mem::AllocHelper::free<Allocator>((
void*)pDataOld);
204 m_cap = itemsNew * BitsPerItem;
211 return iter(*
this, 0,
true);
242 GAIA_NODISCARD
bool operator[](uint32_t pos)
const {
246 GAIA_NODISCARD
bool operator==(
const dbitset& other)
const {
247 const uint32_t item_count = items();
248 GAIA_FOR(item_count) {
249 if (m_pData[i] != other.m_pData[i])
255 GAIA_NODISCARD
bool operator!=(
const dbitset& other)
const {
256 const uint32_t item_count = items();
257 GAIA_FOR(item_count) {
258 if (m_pData[i] == other.m_pData[i])
266 if GAIA_UNLIKELY (
size() == 0)
269 const auto item_count = items();
270 const auto lastItemMask = last_item_mask();
272 if (lastItemMask != 0) {
273 GAIA_FOR(item_count - 1) m_pData[i] = (size_type)-1;
274 m_pData[item_count - 1] = lastItemMask;
276 GAIA_FOR(item_count) m_pData[i] = (size_type)-1;
281 void set(uint32_t pos,
bool value =
true) {
285 m_pData[pos / BitsPerItem] |= ((size_type)1 << (pos % BitsPerItem));
287 m_pData[pos / BitsPerItem] &= ~((size_type)1 << (pos % BitsPerItem));
292 if GAIA_UNLIKELY (
size() == 0)
295 const auto item_count = items();
296 const auto lastItemMask = last_item_mask();
298 if (lastItemMask != 0) {
299 GAIA_FOR(item_count - 1) m_pData[i] = ~m_pData[i];
300 m_pData[item_count - 1] = (~m_pData[item_count - 1]) & lastItemMask;
302 GAIA_FOR(item_count + 1) m_pData[i] = ~m_pData[i];
308 GAIA_ASSERT(pos <
size());
309 m_pData[pos / BitsPerItem] ^= ((size_type)1 << (pos % BitsPerItem));
314 GAIA_ASSERT(bitFrom <= bitTo);
315 GAIA_ASSERT(bitTo <
size());
317 if GAIA_UNLIKELY (
size() == 0)
320 const uint32_t wordIdxFrom = bitFrom / BitsPerItem;
321 const uint32_t wordIdxTo = bitTo / BitsPerItem;
323 auto getMask = [](uint32_t from, uint32_t to) -> size_type {
324 const auto diff = to - from;
326 if (diff == BitsPerItem - 1)
327 return (size_type)-1;
329 return ((size_type(1) << (diff + 1)) - 1) << from;
332 if (wordIdxFrom == wordIdxTo) {
333 m_pData[wordIdxTo] ^= getMask(bitFrom % BitsPerItem, bitTo % BitsPerItem);
336 m_pData[wordIdxFrom] ^= getMask(bitFrom % BitsPerItem, BitsPerItem - 1);
338 GAIA_FOR2(wordIdxFrom + 1, wordIdxTo) m_pData[i] = ~m_pData[i];
340 m_pData[wordIdxTo] ^= getMask(0, bitTo % BitsPerItem);
348 const auto item_count = items();
349 GAIA_FOR(item_count) m_pData[i] = 0;
354 GAIA_ASSERT(pos <
size());
355 m_pData[pos / BitsPerItem] &= ~((size_type)1 << (pos % BitsPerItem));
359 GAIA_NODISCARD
bool test(uint32_t pos)
const {
360 GAIA_ASSERT(pos <
size());
361 return (m_pData[pos / BitsPerItem] & ((size_type)1 << (pos % BitsPerItem))) != 0;
365 GAIA_NODISCARD
bool all()
const {
366 const auto item_count = items() - 1;
367 const auto lastItemMask = last_item_mask();
369 GAIA_FOR(item_count) {
370 if (m_pData[i] != (size_type)-1)
374 if (has_trailing_bits())
375 return (m_pData[item_count] & lastItemMask) == lastItemMask;
377 return m_pData[item_count] == (size_type)-1;
381 GAIA_NODISCARD
bool any()
const {
382 const auto item_count = items();
383 GAIA_FOR(item_count) {
391 GAIA_NODISCARD
bool none()
const {
392 const auto item_count = items();
393 GAIA_FOR(item_count) {
401 GAIA_NODISCARD uint32_t
count()
const {
404 const auto item_count = items();
406 GAIA_MSVC_WARNING_PUSH()
407 GAIA_MSVC_WARNING_DISABLE(4244)
408 if constexpr (
sizeof(size_type) == 4) {
409 GAIA_FOR(item_count) total += GAIA_POPCNT(m_pData[i]);
411 GAIA_FOR(item_count) total += GAIA_POPCNT64(m_pData[i]);
413 GAIA_MSVC_WARNING_POP()
419 GAIA_NODISCARD
constexpr uint32_t
size()
const {
424 GAIA_NODISCARD
constexpr uint32_t
capacity()
const {