67 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
75 std::remove_cvref_t<storage_type>>;
76 using block_type =
typename storage_type_without_cvrefpointer::value_type;
81 using size_type =
typename storage_type_without_cvrefpointer::size_type;
83 using difference_type =
typename storage_type_without_cvrefpointer::difference_type;
101 [[nodiscard]] constexpr
bool empty() const noexcept;
288 if constexpr (std::is_pointer_v<storage_type>)
305 if constexpr (std::is_pointer_v<storage_type>)
334 return std::move(m_buffer);
423 template <
std::input_iterator InputIt>
502 static constexpr
std::
size_t s_bits_per_block = sizeof(
block_type) * CHAR_BIT;
530 [[nodiscard]] constexpr
size_type count_extra_bits() const noexcept;
538 constexpr
void update_null_count(
bool old_value,
bool new_value);
549 template <typename B>
550 requires
std::
ranges::random_access_range<
std::remove_pointer_t<B>>
556 template <
typename B>
557 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
563 template <
typename B>
564 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
570 template <
typename B>
571 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
578 template <
typename B>
579 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
585 template <
typename B>
586 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
590 if constexpr (std::is_pointer_v<storage_type>)
592 if (m_buffer ==
nullptr)
597 if (
data() ==
nullptr)
601 return !m_null_count ||
buffer().data()[block_index(pos)] & bit_mask(pos);
604 template <
typename B>
605 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
609 if (
data() ==
nullptr)
626 throw std::runtime_error(
"Cannot set a bit in a null buffer.");
631 const bool old_value = block & bit_mask(pos);
634 block |= bit_mask(pos);
640 update_null_count(old_value, value);
643 template <
typename B>
644 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
647 if constexpr (std::is_pointer_v<storage_type>)
649 if (m_buffer ==
nullptr)
657 template <
typename B>
658 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
664 template <
typename B>
665 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
671 template <
typename B>
672 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
676 swap(m_buffer, rhs.m_buffer);
677 swap(m_size, rhs.m_size);
678 swap(m_null_count, rhs.m_null_count);
681 template <
typename B>
682 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
688 template <
typename B>
689 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
695 template <
typename B>
696 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
702 template <
typename B>
703 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
709 template <
typename B>
710 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
716 template <
typename B>
717 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
723 template <
typename B>
724 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
729 throw std::out_of_range(
730 "dynamic_bitset_base::at: index out of range for dynamic_bitset_base of size"
731 + std::to_string(
size()) +
" at index " + std::to_string(pos)
737 template <
typename B>
738 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
743 throw std::out_of_range(
744 "dynamic_bitset_base::at: index out of range for dynamic_bitset_base of size"
745 + std::to_string(
size()) +
" at index " + std::to_string(pos)
751 template <
typename B>
752 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
759 template <
typename B>
760 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
764 if (
data() ==
nullptr)
771 template <
typename B>
772 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
776 return (*
this)[
size() - 1];
779 template <
typename B>
780 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
784 if (
data() ==
nullptr)
788 return (*
this)[
size() - 1];
791 template <
typename B>
792 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
794 : m_buffer(
std::move(buf))
800 template <
typename B>
801 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
803 : m_buffer(
std::move(buf))
809 template <
typename B>
810 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
813 return bits_count / s_bits_per_block +
static_cast<size_type>(bits_count % s_bits_per_block != 0);
816 template <
typename B>
817 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
818 constexpr auto dynamic_bitset_base<B>::block_index(size_type pos)
noexcept -> size_type
820 return pos / s_bits_per_block;
823 template <
typename B>
824 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
825 constexpr auto dynamic_bitset_base<B>::bit_index(size_type pos)
noexcept -> size_type
827 return pos % s_bits_per_block;
830 template <
typename B>
831 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
832 constexpr auto dynamic_bitset_base<B>::bit_mask(size_type pos)
noexcept -> block_type
834 const size_type bit = bit_index(pos);
835 return static_cast<block_type
>(block_type(1) << bit);
838 template <
typename B>
839 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
842 if constexpr (std::is_pointer_v<storage_type>)
844 if (m_buffer ==
nullptr)
855 size_t full_blocks = m_size / s_bits_per_block;
856 for (
size_t i = 0; i < full_blocks; ++i)
862 const size_t bits_count = m_size % s_bits_per_block;
865 res += std::popcount(block);
868 return static_cast<size_t>(res);
871 template <
typename B>
872 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
873 constexpr auto dynamic_bitset_base<B>::count_extra_bits() const noexcept -> size_type
875 return bit_index(size());
878 template <
typename B>
879 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
882 if (
data() ==
nullptr)
886 const size_type extra_bits = count_extra_bits();
893 template <
typename B>
894 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
895 constexpr void dynamic_bitset_base<B>::update_null_count(
bool old_value,
bool new_value)
897 if (new_value && !old_value)
901 else if (!new_value && old_value)
907 template <
typename B>
908 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
911 if ((
data() ==
nullptr) && b)
920 if (new_block_count != old_block_count)
922 if (
data() ==
nullptr)
926 buffer().resize(old_block_count, true_value);
929 buffer().resize(new_block_count, value);
932 if (b && (n > m_size))
934 const size_type extra_bits = count_extra_bits();
937 buffer().data()[old_block_count - 1] |=
static_cast<block_type>(value << extra_bits);
946 template <
typename B>
947 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
955 template <
typename B>
956 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
960 return insert(pos, 1, value);
963 template <
typename B>
964 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
970 const auto index =
static_cast<size_type>(std::distance(
cbegin(), pos));
971 if (
data() ==
nullptr && value)
978 const size_type new_size = old_size + count;
984 for (
size_type i = old_size + count - 1; i >= index + count; --i)
991 set(index + i, value);
998 template <
typename B>
999 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
1000 template <std::input_iterator InputIt>
1004 const auto index =
static_cast<size_type>(std::distance(
cbegin(), pos));
1005 const auto count =
static_cast<size_type>(std::distance(first, last));
1006 if (
data() ==
nullptr)
1025 const size_type new_size = old_size + count;
1031 for (
size_type i = old_size + count - 1; i >= index + count; --i)
1038 set(index + i, *first++);
1044 template <
typename B>
1045 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
1049 return insert(pos, value);
1052 template <
typename B>
1053 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
1059 return erase(pos, pos + 1);
1062 template <
typename B>
1063 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
1071 const auto first_index =
static_cast<size_type>(std::distance(
cbegin(), first));
1072 const auto last_index =
static_cast<size_type>(std::distance(
cbegin(), last));
1073 const size_type count = last_index - first_index;
1075 if (
data() ==
nullptr)
1090 for (
size_type i = 0; i < bit_to_move; ++i)
1092 set(first_index + i,
test(last_index + i));
1097 return iterator(
this, first_index);
1100 template <
typename B>
1101 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
1107 template <
typename B>
1108 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.
A proxy reference class that provides mutable access to individual bits in a bitset.
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()
std::remove_pointer_t< std::remove_cvref_t< storage_type > > storage_type_without_cvrefpointer
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
Extracts the underlying storage (move operation).
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
static constexpr size_type compute_block_count(size_type bits_count) noexcept
Computes the number of blocks needed to store the specified number of bits.
constexpr size_type size() const noexcept
Returns the number of bits in the bitset.
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)
Accesses a bit without bounds checking.
constexpr dynamic_bitset_base(storage_type buffer, size_type size, size_type null_count)
Constructs a bitset with the given storage, size, and null count.
constexpr dynamic_bitset_base(const dynamic_bitset_base &)=default
constexpr block_type * data() noexcept
constexpr void swap(self_type &rhs) noexcept
constexpr dynamic_bitset_base(storage_type buffer, size_type size)
Constructs a bitset with the given storage and size.
constexpr const_iterator cend() const
constexpr storage_type_without_cvrefpointer & buffer() noexcept
Returns a mutable reference to the underlying buffer.
#define SPARROW_ASSERT_TRUE(expr__)