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;
864 ~static_cast<block_type>(~
static_cast<block_type>(0) << bits_count)
867 res += std::popcount(block);
870 return static_cast<size_t>(res);
873 template <
typename B>
874 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
875 constexpr auto dynamic_bitset_base<B>::count_extra_bits() const noexcept -> size_type
877 return bit_index(size());
880 template <
typename B>
881 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
884 if (
data() ==
nullptr)
888 const size_type extra_bits = count_extra_bits();
895 template <
typename B>
896 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
897 constexpr void dynamic_bitset_base<B>::update_null_count(
bool old_value,
bool new_value)
899 if (new_value && !old_value)
903 else if (!new_value && old_value)
909 template <
typename B>
910 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
913 if ((
data() ==
nullptr) && b)
922 if (new_block_count != old_block_count)
924 if (
data() ==
nullptr)
928 buffer().resize(old_block_count, true_value);
931 buffer().resize(new_block_count, value);
934 if (b && (n > m_size))
936 const size_type extra_bits = count_extra_bits();
939 buffer().data()[old_block_count - 1] |=
static_cast<block_type>(value << extra_bits);
948 template <
typename B>
949 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
957 template <
typename B>
958 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
962 return insert(pos, 1, value);
965 template <
typename B>
966 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
972 const auto index =
static_cast<size_type>(std::distance(
cbegin(), pos));
973 if (
data() ==
nullptr && value)
980 const size_type new_size = old_size + count;
986 for (
size_type i = old_size + count - 1; i >= index + count; --i)
993 set(index + i, value);
1000 template <
typename B>
1001 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
1002 template <std::input_iterator InputIt>
1006 const auto index =
static_cast<size_type>(std::distance(
cbegin(), pos));
1007 const auto count =
static_cast<size_type>(std::distance(first, last));
1008 if (
data() ==
nullptr)
1027 const size_type new_size = old_size + count;
1033 for (
size_type i = old_size + count - 1; i >= index + count; --i)
1040 set(index + i, *first++);
1046 template <
typename B>
1047 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
1051 return insert(pos, value);
1054 template <
typename B>
1055 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
1061 return erase(pos, pos + 1);
1064 template <
typename B>
1065 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
1073 const auto first_index =
static_cast<size_type>(std::distance(
cbegin(), first));
1074 const auto last_index =
static_cast<size_type>(std::distance(
cbegin(), last));
1075 const size_type count = last_index - first_index;
1077 if (
data() ==
nullptr)
1092 for (
size_type i = 0; i < bit_to_move; ++i)
1094 set(first_index + i,
test(last_index + i));
1099 return iterator(
this, first_index);
1102 template <
typename B>
1103 requires std::ranges::random_access_range<std::remove_pointer_t<B>>
1109 template <
typename B>
1110 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__)