41 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
49 using block_type =
typename storage_type_without_cvrefpointer::value_type;
53 using size_type =
typename storage_type_without_cvrefpointer::size_type;
54 using difference_type =
typename storage_type_without_cvrefpointer::difference_type;
59 [[nodiscard]] constexpr
bool empty() const noexcept;
92 if constexpr (std::is_pointer_v<storage_type>)
104 if constexpr (std::is_pointer_v<storage_type>)
120 return std::move(m_buffer);
140 template <
std::input_iterator InputIt>
155 static constexpr
std::
size_t s_bits_per_block = sizeof(
block_type) * CHAR_BIT;
160 [[nodiscard]] constexpr
size_type count_extra_bits() const noexcept;
161 constexpr
void update_null_count(
bool old_value,
bool new_value);
172 template <typename B>
173 requires
std::
ranges::random_access_range<
std::remove_pointer_t<B>>
179 template <
typename B>
180 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
186 template <
typename B>
187 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
193 template <
typename B>
194 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
202 template <
typename B>
203 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
209 template <
typename B>
210 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
214 if (
data() ==
nullptr)
218 return !m_null_count ||
buffer().data()[block_index(pos)] & bit_mask(pos);
221 template <
typename B>
222 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
228 const bool old_value = block & bit_mask(pos);
231 block |= bit_mask(pos);
237 update_null_count(old_value, value);
240 template <
typename B>
241 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
247 template <
typename B>
248 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
254 template <
typename B>
255 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
261 template <
typename B>
262 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
266 swap(m_buffer, rhs.m_buffer);
267 swap(m_size, rhs.m_size);
268 swap(m_null_count, rhs.m_null_count);
271 template <
typename B>
272 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
278 template <
typename B>
279 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
283 return iterator(
this, block,
size() % s_bits_per_block);
286 template <
typename B>
287 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
293 template <
typename B>
294 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
300 template <
typename B>
301 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
307 template <
typename B>
308 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
315 template <
typename B>
316 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
321 throw std::out_of_range(
322 "dynamic_bitset_base::at: index out of range for dynamic_bitset_base of size"
323 + std::to_string(
size()) +
" at index " + std::to_string(pos)
329 template <
typename B>
330 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
335 throw std::out_of_range(
336 "dynamic_bitset_base::at: index out of range for dynamic_bitset_base of size"
337 + std::to_string(
size()) +
" at index " + std::to_string(pos)
343 template <
typename B>
344 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
351 template <
typename B>
352 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
356 if (
data() ==
nullptr)
363 template <
typename B>
364 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
368 return (*
this)[
size() - 1];
371 template <
typename B>
372 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
376 if (
data() ==
nullptr)
380 return (*
this)[
size() - 1];
383 template <
typename B>
384 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
386 : m_buffer(
std::move(buf))
392 template <
typename B>
393 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
395 : m_buffer(
std::move(buf))
401 template <
typename B>
402 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
405 return bits_count / s_bits_per_block +
static_cast<size_type>(bits_count % s_bits_per_block != 0);
408 template <
typename B>
409 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
410 constexpr auto dynamic_bitset_base<B>::block_index(size_type pos)
noexcept -> size_type
412 return pos / s_bits_per_block;
415 template <
typename B>
416 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
417 constexpr auto dynamic_bitset_base<B>::bit_index(size_type pos)
noexcept -> size_type
419 return pos % s_bits_per_block;
422 template <
typename B>
423 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
424 constexpr auto dynamic_bitset_base<B>::bit_mask(size_type pos)
noexcept -> block_type
426 const size_type bit = bit_index(pos);
427 return static_cast<block_type
>(block_type(1) << bit);
430 template <
typename B>
431 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
434 if (
data() ==
nullptr)
444 size_t full_blocks = m_size / s_bits_per_block;
445 for (
size_t i = 0; i < full_blocks; ++i)
451 const size_t bits_count = m_size % s_bits_per_block;
454 res += std::popcount(block);
457 return static_cast<size_t>(res);
460 template <
typename B>
461 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
462 constexpr auto dynamic_bitset_base<B>::count_extra_bits() const noexcept -> size_type
464 return bit_index(size());
467 template <
typename B>
468 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
471 if (
data() ==
nullptr)
475 const size_type extra_bits = count_extra_bits();
482 template <
typename B>
483 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
484 constexpr void dynamic_bitset_base<B>::update_null_count(
bool old_value,
bool new_value)
486 if (new_value && !old_value)
490 else if (!new_value && old_value)
496 template <
typename B>
497 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
504 if (new_block_count != old_block_count)
506 buffer().resize(new_block_count, value);
511 const size_type extra_bits = count_extra_bits();
514 buffer().data()[old_block_count - 1] |=
static_cast<block_type>(value << extra_bits);
523 template <
typename B>
524 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
532 template <
typename B>
533 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
537 return insert(pos, 1, value);
540 template <
typename B>
541 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
548 const auto index =
static_cast<size_type>(std::distance(
cbegin(), pos));
550 const size_type new_size = old_size + count;
556 for (
size_type i = old_size + count - 1; i >= index + count; --i)
563 set(index + i, value);
566 auto block =
data() + block_index(index);
567 return iterator(
this, block, bit_index(index));
570 template <
typename B>
571 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
572 template <std::input_iterator InputIt>
579 const auto index =
static_cast<size_type>(std::distance(
cbegin(), pos));
582 const size_type new_size = old_size + count;
588 for (
size_type i = old_size + count - 1; i >= index + count; --i)
595 set(index + i, *first++);
598 auto block =
data() + block_index(index);
599 return iterator(
this, block, bit_index(index));
602 template <
typename B>
603 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
607 return insert(pos, value);
610 template <
typename B>
611 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
617 return erase(pos, pos + 1);
620 template <
typename B>
621 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
630 const auto first_index =
static_cast<size_type>(std::distance(
cbegin(), first));
640 const auto last_index =
static_cast<size_type>(std::distance(
cbegin(), last));
641 const size_type count = last_index - first_index;
644 for (
size_type i = 0; i < bit_to_move; ++i)
646 set(first_index + i,
test(last_index + i));
651 auto block =
data() + block_index(first_index);
652 return iterator(
this, block, bit_index(first_index));
655 template <
typename B>
656 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
662 template <
typename B>
663 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
Iterator used to iterate over the bits of a dynamic bitset as if they were addressable values.
Reference proxy used by the bitset_iterator class to make it possible to assign a bit of a bitset as ...
typename storage_type_without_cvrefpointer::value_type block_type
bitset_reference< self_type > reference
constexpr ~dynamic_bitset_base()=default
bitset_iterator< self_type, false > iterator
constexpr iterator insert(const_iterator pos, value_type value)
constexpr const_iterator cbegin() const
constexpr void clear() noexcept
size_type count_non_null() const noexcept
constexpr void push_back(value_type value)
constexpr iterator erase(const_iterator pos)
constexpr reference front()
typename storage_type_without_cvrefpointer::size_type size_type
constexpr bool empty() const noexcept
constexpr reference back()
constexpr void zero_unused_bits()
constexpr iterator emplace(const_iterator pos, value_type value)
dynamic_bitset_base< buffer< T > * > self_type
storage_type extract_storage() noexcept
constexpr const_reference at(size_type pos) const
constexpr iterator begin()
constexpr bool test(size_type pos) const
constexpr void resize(size_type n, value_type b=false)
constexpr size_type null_count() const noexcept
bitset_iterator< self_type, true > const_iterator
std::remove_pointer_t< std::remove_cvref_t< storage_type > > storage_type_without_cvrefpointer
static constexpr size_type compute_block_count(size_type bits_count) noexcept
constexpr size_type size() const noexcept
constexpr void pop_back()
constexpr dynamic_bitset_base(dynamic_bitset_base &&) noexcept=default
constexpr void set(size_type pos, value_type value)
typename storage_type_without_cvrefpointer::difference_type difference_type
constexpr size_type block_count() const noexcept
constexpr const storage_type_without_cvrefpointer & buffer() const noexcept
constexpr reference operator[](size_type i)
constexpr dynamic_bitset_base(storage_type buffer, size_type size, size_type null_count)
constexpr dynamic_bitset_base(const dynamic_bitset_base &)=default
constexpr void swap(self_type &) noexcept
constexpr block_type * data() noexcept
constexpr dynamic_bitset_base(storage_type buffer, size_type size)
constexpr const_iterator cend() const
constexpr storage_type_without_cvrefpointer & buffer() noexcept
typename base_type::block_type block_type
typename base_type::storage_type storage_type
#define SPARROW_ASSERT_TRUE(expr__)