42 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
50 using block_type =
typename storage_type_without_cvrefpointer::value_type;
54 using size_type =
typename storage_type_without_cvrefpointer::size_type;
55 using difference_type =
typename storage_type_without_cvrefpointer::difference_type;
60 [[nodiscard]] constexpr
bool empty() const noexcept;
93 if constexpr (std::is_pointer_v<storage_type>)
105 if constexpr (std::is_pointer_v<storage_type>)
121 return std::move(m_buffer);
141 template <
std::input_iterator InputIt>
156 static constexpr
std::
size_t s_bits_per_block = sizeof(
block_type) * CHAR_BIT;
161 [[nodiscard]] constexpr
size_type count_extra_bits() const noexcept;
162 constexpr
void update_null_count(
bool old_value,
bool new_value);
173 template <typename B>
174 requires
std::
ranges::random_access_range<
std::remove_pointer_t<B>>
180 template <
typename B>
181 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
187 template <
typename B>
188 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
194 template <
typename B>
195 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 constexpr (std::is_pointer_v<storage_type>)
216 if (m_buffer ==
nullptr)
221 if (
data() ==
nullptr)
225 return !m_null_count ||
buffer().data()[block_index(pos)] & bit_mask(pos);
228 template <
typename B>
229 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
233 if (
data() ==
nullptr)
250 throw std::runtime_error(
"Cannot set a bit in a null buffer.");
255 const bool old_value = block & bit_mask(pos);
258 block |= bit_mask(pos);
264 update_null_count(old_value, value);
267 template <
typename B>
268 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
271 if constexpr (std::is_pointer_v<storage_type>)
273 if (m_buffer ==
nullptr)
281 template <
typename B>
282 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
288 template <
typename B>
289 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
295 template <
typename B>
296 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
300 swap(m_buffer, rhs.m_buffer);
301 swap(m_size, rhs.m_size);
302 swap(m_null_count, rhs.m_null_count);
305 template <
typename B>
306 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
312 template <
typename B>
313 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
319 template <
typename B>
320 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
326 template <
typename B>
327 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
333 template <
typename B>
334 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
340 template <
typename B>
341 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
347 template <
typename B>
348 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
353 throw std::out_of_range(
354 "dynamic_bitset_base::at: index out of range for dynamic_bitset_base of size"
355 + std::to_string(
size()) +
" at index " + std::to_string(pos)
361 template <
typename B>
362 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
367 throw std::out_of_range(
368 "dynamic_bitset_base::at: index out of range for dynamic_bitset_base of size"
369 + std::to_string(
size()) +
" at index " + std::to_string(pos)
375 template <
typename B>
376 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
383 template <
typename B>
384 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
388 if (
data() ==
nullptr)
395 template <
typename B>
396 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
400 return (*
this)[
size() - 1];
403 template <
typename B>
404 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
408 if (
data() ==
nullptr)
412 return (*
this)[
size() - 1];
415 template <
typename B>
416 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
418 : m_buffer(
std::move(buf))
424 template <
typename B>
425 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
427 : m_buffer(
std::move(buf))
433 template <
typename B>
434 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
437 return bits_count / s_bits_per_block +
static_cast<size_type>(bits_count % s_bits_per_block != 0);
440 template <
typename B>
441 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
442 constexpr auto dynamic_bitset_base<B>::block_index(size_type pos)
noexcept -> size_type
444 return pos / s_bits_per_block;
447 template <
typename B>
448 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
449 constexpr auto dynamic_bitset_base<B>::bit_index(size_type pos)
noexcept -> size_type
451 return pos % s_bits_per_block;
454 template <
typename B>
455 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
456 constexpr auto dynamic_bitset_base<B>::bit_mask(size_type pos)
noexcept -> block_type
458 const size_type bit = bit_index(pos);
459 return static_cast<block_type
>(block_type(1) << bit);
462 template <
typename B>
463 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
466 if constexpr (std::is_pointer_v<storage_type>)
468 if (m_buffer ==
nullptr)
479 size_t full_blocks = m_size / s_bits_per_block;
480 for (
size_t i = 0; i < full_blocks; ++i)
486 const size_t bits_count = m_size % s_bits_per_block;
489 res += std::popcount(block);
492 return static_cast<size_t>(res);
495 template <
typename B>
496 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
497 constexpr auto dynamic_bitset_base<B>::count_extra_bits() const noexcept -> size_type
499 return bit_index(size());
502 template <
typename B>
503 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
506 if (
data() ==
nullptr)
510 const size_type extra_bits = count_extra_bits();
517 template <
typename B>
518 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
519 constexpr void dynamic_bitset_base<B>::update_null_count(
bool old_value,
bool new_value)
521 if (new_value && !old_value)
525 else if (!new_value && old_value)
531 template <
typename B>
532 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
535 if ((
data() ==
nullptr) && b)
544 if (new_block_count != old_block_count)
546 if (
data() ==
nullptr)
550 buffer().resize(old_block_count, true_value);
553 buffer().resize(new_block_count, value);
556 if (b && (n > m_size))
558 const size_type extra_bits = count_extra_bits();
561 buffer().data()[old_block_count - 1] |=
static_cast<block_type>(value << extra_bits);
570 template <
typename B>
571 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
579 template <
typename B>
580 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
584 return insert(pos, 1, value);
587 template <
typename B>
588 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
594 const auto index =
static_cast<size_type>(std::distance(
cbegin(), pos));
595 if (
data() ==
nullptr && value)
602 const size_type new_size = old_size + count;
608 for (
size_type i = old_size + count - 1; i >= index + count; --i)
615 set(index + i, value);
622 template <
typename B>
623 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
624 template <std::input_iterator InputIt>
628 const auto index =
static_cast<size_type>(std::distance(
cbegin(), pos));
629 const auto count =
static_cast<size_type>(std::distance(first, last));
630 if (
data() ==
nullptr)
649 const size_type new_size = old_size + count;
655 for (
size_type i = old_size + count - 1; i >= index + count; --i)
662 set(index + i, *first++);
668 template <
typename B>
669 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
673 return insert(pos, value);
676 template <
typename B>
677 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
683 return erase(pos, pos + 1);
686 template <
typename B>
687 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
695 const auto first_index =
static_cast<size_type>(std::distance(
cbegin(), first));
696 const auto last_index =
static_cast<size_type>(std::distance(
cbegin(), last));
697 const size_type count = last_index - first_index;
699 if (
data() ==
nullptr)
714 for (
size_type i = 0; i < bit_to_move; ++i)
716 set(first_index + i,
test(last_index + i));
724 template <
typename B>
725 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
731 template <
typename B>
732 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__)