8#ifndef SUL_DYNAMIC_BITSET_HPP
9#define SUL_DYNAMIC_BITSET_HPP
16#define SUL_DYNAMIC_BITSET_VERSION_MAJOR 1
23#define SUL_DYNAMIC_BITSET_VERSION_MINOR 3
30#define SUL_DYNAMIC_BITSET_VERSION_PATCH 1
59#if !defined(DYNAMIC_BITSET_NO_LIBPOPCNT)
61# if __has_include(<libpopcnt.h>)
62# include <libpopcnt.h>
63# define DYNAMIC_BITSET_CAN_USE_LIBPOPCNT true
66#if !defined(DYNAMIC_BITSET_CAN_USE_LIBPOPCNT)
67# define DYNAMIC_BITSET_CAN_USE_LIBPOPCNT false
71#if !defined(DYNAMIC_BITSET_NO_STD_BITOPS)
73# if __has_include(<bit>)
75# ifdef __cpp_lib_bitops
76# define DYNAMIC_BITSET_CAN_USE_STD_BITOPS true
80#if !defined(DYNAMIC_BITSET_CAN_USE_STD_BITOPS)
81# define DYNAMIC_BITSET_CAN_USE_STD_BITOPS false
89#if !DYNAMIC_BITSET_CAN_USE_STD_BITOPS && !defined(DYNAMIC_BITSET_NO_COMPILER_BUILTIN)
90# if defined(__clang__)
94# if __has_builtin(__builtin_popcount) && __has_builtin(__builtin_popcountl) \
95 && __has_builtin(__builtin_popcountll)
96# define DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_POPCOUNT true
98# if __has_builtin(__builtin_ctz) && __has_builtin(__builtin_ctzl) && __has_builtin(__builtin_ctzll)
99# define DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_CTZ true
102# elif defined(__GNUC__)
104# define DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN true
105# elif defined(_MSC_VER)
109# if defined(_M_IX86) || defined(_M_ARM) || defined(_M_X64) || defined(_M_ARM64)
111# pragma intrinsic(_BitScanForward)
112# define DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD true
114# if(defined(_M_X64) || defined(_M_ARM64)) \
115 && !defined(DYNAMIC_BITSET_NO_MSVC_BUILTIN_BITSCANFORWARD64)
116# pragma intrinsic(_BitScanForward64)
117# define DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD64 true
121#if !defined(DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_POPCOUNT)
122# define DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_POPCOUNT false
124#if !defined(DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_CTZ)
125# define DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_CTZ false
127#if !defined(DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN)
128# define DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN false
130#if !defined(DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD)
131# define DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD false
133#if !defined(DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD64)
134# define DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD64 false
136#if !defined(DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN)
137# define DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN false
140#ifndef DYNAMIC_BITSET_NO_NAMESPACE
169 template<
typename Block =
unsigned long long,
typename Allocator = std::allocator<Block>>
172 static_assert(std::is_unsigned<Block>::value,
"Block is not an unsigned integral type");
366 [[nodiscard]] constexpr
bool operator~() const;
375 [[nodiscard]] constexpr operator
bool() const;
382 constexpr
void operator&() = delete;
501 unsigned long long init_val = 0,
546 template<typename _CharT, typename _Traits>
548 std::basic_string_view<_CharT, _Traits> str,
549 typename std::basic_string_view<_CharT, _Traits>::
size_type pos = 0,
550 typename std::basic_string_view<_CharT, _Traits>::
size_type n = std::basic_string_view<_CharT, _Traits>::
npos,
551 _CharT zero = _CharT('0'),
552 _CharT one = _CharT('1'),
581 template<typename _CharT, typename _Traits, typename _Alloc>
582 constexpr explicit
dynamic_bitset(const std::basic_string<_CharT, _Traits, _Alloc>& str,
583 typename std::basic_string<_CharT, _Traits, _Alloc>::
size_type pos = 0,
584 typename std::basic_string<_CharT, _Traits, _Alloc>::
size_type n =
585 std::basic_string<_CharT, _Traits, _Alloc>::
npos,
586 _CharT zero = _CharT('0'),
587 _CharT one = _CharT('1'),
615 template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
618 typename std::basic_string<_CharT>::
size_type pos = 0,
619 typename std::basic_string<_CharT>::
size_type n = std::basic_string<_CharT>::
npos,
620 _CharT zero = _CharT('0'),
621 _CharT one = _CharT('1'),
660 constexpr
void clear();
729 template<typename BlockInputIterator>
730 constexpr
void append(BlockInputIterator first, BlockInputIterator last);
894 [[nodiscard]] constexpr
dynamic_bitset<Block, Allocator> operator~() const;
1087 [[nodiscard]] constexpr
bool all() const;
1102 [[nodiscard]] constexpr
bool any() const;
1117 [[nodiscard]] constexpr
bool none() const;
1202 [[nodiscard]] constexpr
bool empty() const noexcept;
1414 template<typename _CharT =
char,
1415 typename _Traits = std::char_traits<_CharT>,
1416 typename _Alloc = std::allocator<_CharT>>
1417 [[nodiscard]] constexpr std::basic_string<_CharT, _Traits, _Alloc>
to_string(_CharT zero = _CharT('0'),
1418 _CharT one = _CharT('1')) const;
1435 [[nodiscard]] constexpr
unsigned long to_ulong() const;
1452 [[nodiscard]] constexpr
unsigned long long to_ullong() const;
1481 template<typename Function, typename... Parameters>
1482 constexpr
void iterate_bits_on(Function&& function, Parameters&&... parameters) const;
1571 template<typename Block_, typename Allocator_>
1572 friend constexpr
bool operator==(const
dynamic_bitset<Block_, Allocator_>& lhs,
1621 template<typename Block_, typename Allocator_>
1622 friend constexpr
bool operator<(const
dynamic_bitset<Block_, Allocator_>& lhs,
1626 template<typename T>
1627 struct dependent_false : public std::false_type
1631 std::vector<Block, Allocator> m_blocks;
1646 static constexpr void
1655 template<typename _CharT, typename _Traits>
1656 constexpr
void init_from_string(std::basic_string_view<_CharT, _Traits> str,
1657 typename std::basic_string_view<_CharT, _Traits>::
size_type pos,
1658 typename std::basic_string_view<_CharT, _Traits>::
size_type n,
1668 constexpr
size_type extra_bits_number() const noexcept;
1670 constexpr
size_type unused_bits_number() const noexcept;
1672 template<typename BinaryOperation>
1673 constexpr
void apply(const
dynamic_bitset<Block, Allocator>& other, BinaryOperation binary_op);
1674 template<typename UnaryOperation>
1675 constexpr
void apply(UnaryOperation unary_op);
1676 constexpr
void apply_left_shift(
size_type shift);
1677 constexpr
void apply_right_shift(
size_type shift);
1680 constexpr
void sanitize();
1683 constexpr
bool check_unused_bits() const noexcept;
1684 constexpr
bool check_size() const noexcept;
1685 constexpr
bool check_consistency() const noexcept;
1690 template<typename integral_type, typename = std::enable_if_t<std::is_integral_v<integral_type>>>
1720 template<typename Block, typename Allocator>
1747 template<typename Block, typename Allocator>
1775 template<typename Block, typename Allocator>
1803 template<typename Block, typename Allocator>
1835 template<typename Block, typename Allocator>
1868 template<typename Block, typename Allocator>
1901 template<typename Block, typename Allocator>
1934 template<typename Block, typename Allocator>
1963 template<typename _CharT, typename _Traits, typename Block, typename Allocator>
1964 constexpr std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& os,
1995 template<typename _CharT, typename _Traits, typename Block, typename Allocator>
1996 constexpr std::basic_istream<_CharT, _Traits>& operator>>(std::basic_istream<_CharT, _Traits>& is,
2020 template<typename Block, typename Allocator>
2022 dynamic_bitset<Block, Allocator>& bitset2) noexcept(noexcept(bitset1.
swap(bitset2)));
2028 template<typename Block, typename Allocator>
2031 : m_block(bitset.get_block(bit_pos))
2036 template<
typename Block,
typename Allocator>
2044 template<
typename Block,
typename Allocator>
2052 template<
typename Block,
typename Allocator>
2060 template<
typename Block,
typename Allocator>
2071 template<
typename Block,
typename Allocator>
2082 template<
typename Block,
typename Allocator>
2093 template<
typename Block,
typename Allocator>
2104 template<
typename Block,
typename Allocator>
2107 return (m_block & m_mask) == zero_block;
2110 template<
typename Block,
typename Allocator>
2113 return (m_block & m_mask) != zero_block;
2116 template<
typename Block,
typename Allocator>
2123 template<
typename Block,
typename Allocator>
2130 template<
typename Block,
typename Allocator>
2137 template<
typename Block,
typename Allocator>
2156 template<
typename Block,
typename Allocator>
2158 : m_blocks(allocator)
2163 template<
typename Block,
typename Allocator>
2165 unsigned long long init_val,
2167 : m_blocks(blocks_required(nbits), allocator)
2168 , m_bits_number(nbits)
2170 if(nbits == 0 || init_val == 0)
2175 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
2176 constexpr size_t init_val_required_blocks = ull_bits_number /
bits_per_block;
2177 if constexpr(init_val_required_blocks == 1)
2179 m_blocks[0] = init_val;
2183 const unsigned long long block_mask =
static_cast<unsigned long long>(one_block);
2184 const size_t blocks_to_init = std::min(m_blocks.size(), init_val_required_blocks);
2185 for(
size_t i = 0; i < blocks_to_init; ++i)
2193 template<
typename Block,
typename Allocator>
2196 : m_blocks(allocator)
2202 template<
typename Block,
typename Allocator>
2203 template<
typename _CharT,
typename _Traits>
2205 std::basic_string_view<_CharT, _Traits> str,
2206 typename std::basic_string_view<_CharT, _Traits>::size_type pos,
2207 typename std::basic_string_view<_CharT, _Traits>::size_type n,
2211 : m_blocks(allocator)
2214 assert(pos < str.size());
2215 init_from_string(str, pos, n, zero, one);
2218 template<
typename Block,
typename Allocator>
2219 template<
typename _CharT,
typename _Traits,
typename _Alloc>
2221 const std::basic_string<_CharT, _Traits, _Alloc>& str,
2222 typename std::basic_string<_CharT, _Traits, _Alloc>::size_type pos,
2223 typename std::basic_string<_CharT, _Traits, _Alloc>::size_type n,
2227 : m_blocks(allocator)
2230 assert(pos < str.size());
2231 init_from_string(std::basic_string_view<_CharT, _Traits>(str), pos, n, zero, one);
2234 template<
typename Block,
typename Allocator>
2235 template<
typename _CharT,
typename _Traits>
2237 typename std::basic_string<_CharT>::size_type pos,
2238 typename std::basic_string<_CharT>::size_type n,
2242 : m_blocks(allocator)
2245 init_from_string(std::basic_string_view<_CharT, _Traits>(str), pos, n, zero, one);
2248 template<
typename Block,
typename Allocator>
2251 if(nbits == m_bits_number)
2256 const size_type old_num_blocks = num_blocks();
2257 const size_type new_num_blocks = blocks_required(nbits);
2259 const block_type init_value = value ? one_block : zero_block;
2260 if(new_num_blocks != old_num_blocks)
2262 m_blocks.resize(new_num_blocks, init_value);
2265 if(value && nbits > m_bits_number && old_num_blocks > 0)
2268 const size_type extra_bits = extra_bits_number();
2271 m_blocks[old_num_blocks - 1] |=
static_cast<block_type>(init_value << extra_bits);
2275 m_bits_number = nbits;
2277 assert(check_consistency());
2280 template<
typename Block,
typename Allocator>
2287 template<
typename Block,
typename Allocator>
2290 const size_type new_last_bit = m_bits_number++;
2291 if(m_bits_number <= m_blocks.size() * bits_per_block)
2295 set(new_last_bit, value);
2302 assert(
operator[](new_last_bit) == value);
2303 assert(check_consistency());
2306 template<
typename Block,
typename Allocator>
2315 if(m_blocks.size() > blocks_required(m_bits_number))
2317 m_blocks.pop_back();
2319 assert(extra_bits_number() == 0);
2325 assert(check_consistency());
2328 template<
typename Block,
typename Allocator>
2331 const size_type extra_bits = extra_bits_number();
2334 m_blocks.push_back(block);
2338 last_block() |=
static_cast<block_type>(block << extra_bits);
2339 m_blocks.push_back(
block_type(block >> (bits_per_block - extra_bits)));
2342 m_bits_number += bits_per_block;
2343 assert(check_consistency());
2346 template<
typename Block,
typename Allocator>
2349 if(blocks.size() == 0)
2354 append(std::cbegin(blocks), std::cend(blocks));
2357 template<
typename Block,
typename Allocator>
2358 template<
typename BlockInputIterator>
2367 if constexpr(std::is_same_v<typename std::iterator_traits<BlockInputIterator>::iterator_category,
2368 std::random_access_iterator_tag>)
2370 assert(std::distance(first, last) > 0);
2371 m_blocks.reserve(m_blocks.size() +
static_cast<size_type>(std::distance(first, last)));
2374 const size_type extra_bits = extra_bits_number();
2375 const size_type unused_bits = unused_bits_number();
2378 auto pos = m_blocks.insert(std::end(m_blocks), first, last);
2379 assert(std::distance(pos, std::end(m_blocks)) > 0);
2380 m_bits_number +=
static_cast<size_type>(std::distance(pos, std::end(m_blocks))) * bits_per_block;
2384 last_block() |=
static_cast<block_type>(*first << extra_bits);
2387 while(first != last)
2389 block |=
static_cast<block_type>(*first << extra_bits);
2390 m_blocks.push_back(block);
2391 m_bits_number += bits_per_block;
2395 m_blocks.push_back(block);
2396 m_bits_number += bits_per_block;
2399 assert(check_consistency());
2402 template<
typename Block,
typename Allocator>
2406 assert(size() == rhs.
size());
2408 for(
size_type i = 0; i < m_blocks.size(); ++i)
2410 m_blocks[i] &= rhs.m_blocks[i];
2415 template<
typename Block,
typename Allocator>
2419 assert(size() == rhs.
size());
2421 for(
size_type i = 0; i < m_blocks.size(); ++i)
2423 m_blocks[i] |= rhs.m_blocks[i];
2428 template<
typename Block,
typename Allocator>
2432 assert(size() == rhs.
size());
2434 for(
size_type i = 0; i < m_blocks.size(); ++i)
2436 m_blocks[i] ^= rhs.m_blocks[i];
2441 template<
typename Block,
typename Allocator>
2445 assert(size() == rhs.
size());
2447 for(
size_type i = 0; i < m_blocks.size(); ++i)
2449 m_blocks[i] &=
static_cast<block_type>(~rhs.m_blocks[i]);
2454 template<
typename Block,
typename Allocator>
2459 if(shift >= m_bits_number)
2465 apply_left_shift(shift);
2472 template<
typename Block,
typename Allocator>
2477 if(shift >= m_bits_number)
2483 apply_right_shift(shift);
2489 template<
typename Block,
typename Allocator>
2495 template<
typename Block,
typename Allocator>
2501 template<
typename Block,
typename Allocator>
2509 template<
typename Block,
typename Allocator>
2513 assert(pos < size());
2518 assert(pos + len - 1 < size());
2520 const size_type first_block = block_index(pos);
2521 const size_type last_block = block_index(pos + len - 1);
2522 const size_type first_bit_index = bit_index(pos);
2523 const size_type last_bit_index = bit_index(pos + len - 1);
2525 if(first_block == last_block)
2527 set_block_bits(m_blocks[first_block], first_bit_index, last_bit_index, value);
2531 size_type first_full_block = first_block;
2534 if(first_bit_index != 0)
2537 set_block_bits(m_blocks[first_block], first_bit_index, block_last_bit_index, value);
2540 if(last_bit_index != block_last_bit_index)
2543 set_block_bits(m_blocks[last_block], 0, last_bit_index, value);
2546 const block_type full_block = value ? one_block : zero_block;
2547 for(
size_type i = first_full_block; i <= last_full_block; ++i)
2549 m_blocks[i] = full_block;
2556 template<
typename Block,
typename Allocator>
2559 assert(pos < size());
2563 m_blocks[block_index(pos)] |= bit_mask(pos);
2567 m_blocks[block_index(pos)] &=
static_cast<block_type>(~bit_mask(pos));
2573 template<
typename Block,
typename Allocator>
2576 std::fill(std::begin(m_blocks), std::end(m_blocks), one_block);
2581 template<
typename Block,
typename Allocator>
2584 return set(pos, len,
false);
2587 template<
typename Block,
typename Allocator>
2590 return set(pos,
false);
2593 template<
typename Block,
typename Allocator>
2596 std::fill(std::begin(m_blocks), std::end(m_blocks), zero_block);
2600 template<
typename Block,
typename Allocator>
2603 assert(pos < size());
2608 assert(pos + len - 1 < size());
2610 const size_type first_block = block_index(pos);
2611 const size_type last_block = block_index(pos + len - 1);
2612 const size_type first_bit_index = bit_index(pos);
2613 const size_type last_bit_index = bit_index(pos + len - 1);
2615 if(first_block == last_block)
2617 flip_block_bits(m_blocks[first_block], first_bit_index, last_bit_index);
2621 size_type first_full_block = first_block;
2624 if(first_bit_index != 0)
2627 flip_block_bits(m_blocks[first_block], first_bit_index, block_last_bit_index);
2630 if(last_bit_index != block_last_bit_index)
2633 flip_block_bits(m_blocks[last_block], 0, last_bit_index);
2636 for(
size_type i = first_full_block; i <= last_full_block; ++i)
2645 template<
typename Block,
typename Allocator>
2648 assert(pos < size());
2649 m_blocks[block_index(pos)] ^= bit_mask(pos);
2653 template<
typename Block,
typename Allocator>
2656 std::transform(std::cbegin(m_blocks), std::cend(m_blocks), std::begin(m_blocks), std::bit_not<block_type>());
2661 template<
typename Block,
typename Allocator>
2664 assert(pos < size());
2665 return (m_blocks[block_index(pos)] & bit_mask(pos)) != zero_block;
2668 template<
typename Block,
typename Allocator>
2671 bool const result = test(pos);
2679 template<
typename Block,
typename Allocator>
2688 if(extra_bits_number() == 0)
2692 if(block != full_block)
2700 for(
size_type i = 0; i < m_blocks.size() - 1; ++i)
2702 if(m_blocks[i] != full_block)
2707 if(last_block() != (full_block >> unused_bits_number()))
2715 template<
typename Block,
typename Allocator>
2720 if(block != zero_block)
2728 template<
typename Block,
typename Allocator>
2734 template<
typename Block,
typename Allocator>
2743#if DYNAMIC_BITSET_CAN_USE_LIBPOPCNT
2749 for(
size_type i = 0; i < m_blocks.size() - 1; ++i)
2751 count += block_count(m_blocks[i]);
2756 const size_type extra_bits = extra_bits_number();
2759 count += block_count(block);
2763 count += block_count(block, extra_bits);
2769 template<
typename Block,
typename Allocator>
2773 assert(pos < size());
2777 template<
typename Block,
typename Allocator>
2784 template<
typename Block,
typename Allocator>
2788 return m_bits_number;
2791 template<
typename Block,
typename Allocator>
2795 return m_blocks.size();
2798 template<
typename Block,
typename Allocator>
2804 template<
typename Block,
typename Allocator>
2808 return m_blocks.capacity() * bits_per_block;
2811 template<
typename Block,
typename Allocator>
2814 m_blocks.reserve(blocks_required(num_bits));
2817 template<
typename Block,
typename Allocator>
2820 m_blocks.shrink_to_fit();
2823 template<
typename Block,
typename Allocator>
2826 assert(size() == bitset.
size());
2827 for(
size_type i = 0; i < m_blocks.size(); ++i)
2829 if((m_blocks[i] & ~bitset.m_blocks[i]) != zero_block)
2837 template<
typename Block,
typename Allocator>
2841 assert(size() == bitset.
size());
2842 bool is_proper =
false;
2843 for(
size_type i = 0; i < m_blocks.size(); ++i)
2846 const block_type& other_block = bitset.m_blocks[i];
2848 if((self_block & ~other_block) != zero_block)
2852 if((~self_block & other_block) != zero_block)
2860 template<
typename Block,
typename Allocator>
2863 const size_type min_blocks_number = std::min(m_blocks.size(), bitset.m_blocks.size());
2864 for(
size_type i = 0; i < min_blocks_number; ++i)
2866 if((m_blocks[i] & bitset.m_blocks[i]) != zero_block)
2874 template<
typename Block,
typename Allocator>
2877 for(
size_type i = 0; i < m_blocks.size(); ++i)
2879 if(m_blocks[i] != zero_block)
2881 return i * bits_per_block + count_block_trailing_zero(m_blocks[i]);
2887 template<
typename Block,
typename Allocator>
2891 if(empty() || prev >= (size() - 1))
2897 const size_type first_block = block_index(first_bit);
2898 const size_type first_bit_index = bit_index(first_bit);
2901 if(first_block_shifted != zero_block)
2903 return first_bit + count_block_trailing_zero(first_block_shifted);
2907 for(
size_type i = first_block + 1; i < m_blocks.size(); ++i)
2909 if(m_blocks[i] != zero_block)
2911 return i * bits_per_block + count_block_trailing_zero(m_blocks[i]);
2918 template<
typename Block,
typename Allocator>
2920 noexcept(std::swap(m_blocks, other.m_blocks)))
2922 std::swap(m_blocks, other.m_blocks);
2923 std::swap(m_bits_number, other.m_bits_number);
2926 template<
typename Block,
typename Allocator>
2930 return m_blocks.get_allocator();
2933 template<
typename Block,
typename Allocator>
2934 template<
typename _CharT,
typename _Traits,
typename _Alloc>
2939 std::basic_string<_CharT, _Traits, _Alloc> str(len, zero);
2940 for(
size_type i_block = 0; i_block < m_blocks.size(); ++i_block)
2942 if(m_blocks[i_block] == zero_block)
2947 const size_type limit = i_block * bits_per_block < len ? len - i_block * bits_per_block : bits_per_block;
2948 for(
size_type i_bit = 0; i_bit < limit; ++i_bit)
2950 if((m_blocks[i_block] & mask) != zero_block)
2952 _Traits::assign(str[len - (i_block * bits_per_block + i_bit + 1)], one);
2962 template<
typename Block,
typename Allocator>
2965 if(m_bits_number == 0)
2970 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
2971 if(find_next(ul_bits_number - 1) != npos)
2973 throw std::overflow_error(
"sul::dynamic_bitset::to_ulong");
2976 unsigned long result = 0;
2977 const size_type result_bits_number = std::min(ul_bits_number, m_bits_number);
2978 for(
size_type i_block = 0; i_block <= block_index(result_bits_number - 1); ++i_block)
2980 result |= (
static_cast<unsigned long>(m_blocks[i_block]) << (i_block * bits_per_block));
2986 template<
typename Block,
typename Allocator>
2989 if(m_bits_number == 0)
2994 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
2995 if(find_next(ull_bits_number - 1) != npos)
2997 throw std::overflow_error(
"sul::dynamic_bitset::to_ullong");
3000 unsigned long long result = 0;
3001 const size_type result_bits_number = std::min(ull_bits_number, m_bits_number);
3002 for(
size_type i_block = 0; i_block <= block_index(result_bits_number - 1); ++i_block)
3004 result |= (
static_cast<unsigned long long>(m_blocks[i_block]) << (i_block * bits_per_block));
3010 template<
typename Block,
typename Allocator>
3011 template<
typename Function,
typename... Parameters>
3013 Parameters&&... parameters)
const
3015 if constexpr(!std::is_invocable_v<Function, size_t, Parameters...>)
3017 static_assert(dependent_false<Function>::value,
"Function take invalid arguments");
3021 if constexpr(std::is_same_v<std::invoke_result_t<Function, size_t, Parameters...>,
void>)
3024 while(i_bit != npos)
3026 std::invoke(std::forward<Function>(function), i_bit, std::forward<Parameters>(parameters)...);
3027 i_bit = find_next(i_bit);
3030 else if constexpr(std::is_convertible_v<std::invoke_result_t<Function, size_t, Parameters...>,
bool>)
3033 while(i_bit != npos)
3035 if(!std::invoke(std::forward<Function>(function), i_bit, std::forward<Parameters>(parameters)...))
3039 i_bit = find_next(i_bit);
3044 static_assert(dependent_false<Function>::value,
"Function have invalid return type");
3049 template<
typename Block,
typename Allocator>
3052 return m_blocks.data();
3055 template<
typename Block,
typename Allocator>
3059 return m_blocks.data();
3062 template<
typename Block_,
typename Allocator_>
3066 return (lhs.m_bits_number == rhs.m_bits_number) && (lhs.m_blocks == rhs.m_blocks);
3069 template<
typename Block_,
typename Allocator_>
3077 const size_type lhs_blocks_size = lhs.m_blocks.size();
3078 const size_type rhs_blocks_size = rhs.m_blocks.size();
3080 if(lhs_size == rhs_size)
3088 for(
size_type i = lhs_blocks_size - 1; i > 0; --i)
3090 if(lhs.m_blocks[i] != rhs.m_blocks[i])
3092 return lhs.m_blocks[i] < rhs.m_blocks[i];
3095 return lhs.m_blocks[0] < rhs.m_blocks[0];
3108 const bool rhs_longer = rhs_size > lhs_size;
3110 const size_type longest_blocks_size = std::max(lhs_blocks_size, rhs_blocks_size);
3111 const size_type shortest_blocks_size = std::min(lhs_blocks_size, rhs_blocks_size);
3112 for(
size_type i = longest_blocks_size - 1; i >= shortest_blocks_size; --i)
3114 if(longest_bitset.m_blocks[i] !=
block_type(0))
3120 for(
size_type i = shortest_blocks_size - 1; i > 0; --i)
3122 if(lhs.m_blocks[i] != rhs.m_blocks[i])
3124 return lhs.m_blocks[i] < rhs.m_blocks[i];
3127 if(lhs.m_blocks[0] != rhs.m_blocks[0])
3129 return lhs.m_blocks[0] < rhs.m_blocks[0];
3131 return lhs_size < rhs_size;
3138 template<
typename Block,
typename Allocator>
3142 return nbits / bits_per_block +
static_cast<size_type
>(nbits % bits_per_block > 0);
3145 template<
typename Block,
typename Allocator>
3147 dynamic_bitset<Block, Allocator>::block_index(size_type pos)
noexcept
3149 return pos / bits_per_block;
3152 template<
typename Block,
typename Allocator>
3154 dynamic_bitset<Block, Allocator>::bit_index(size_type pos)
noexcept
3156 return pos % bits_per_block;
3159 template<
typename Block,
typename Allocator>
3161 dynamic_bitset<Block, Allocator>::bit_mask(size_type pos)
noexcept
3163 return block_type(block_type(1) << bit_index(pos));
3166 template<
typename Block,
typename Allocator>
3168 dynamic_bitset<Block, Allocator>::bit_mask(size_type first, size_type last)
noexcept
3170 first = bit_index(first);
3171 last = bit_index(last);
3172 if(last == (block_last_bit_index))
3174 return block_type(one_block << first);
3178 return block_type(((block_type(1) << (last + 1)) - 1) ^ ((block_type(1) << first) - 1));
3182 template<
typename Block,
typename Allocator>
3183 constexpr void dynamic_bitset<Block, Allocator>::set_block_bits(block_type& block,
3190 block |= bit_mask(first, last);
3194 block &=
static_cast<block_type
>(~bit_mask(first, last));
3198 template<
typename Block,
typename Allocator>
3200 dynamic_bitset<Block, Allocator>::flip_block_bits(block_type& block, size_type first, size_type last)
noexcept
3202 block ^= bit_mask(first, last);
3205 template<
typename Block,
typename Allocator>
3207 dynamic_bitset<Block, Allocator>::block_count(
const block_type& block)
noexcept
3209#if DYNAMIC_BITSET_CAN_USE_STD_BITOPS
3210 return static_cast<size_type
>(std::popcount(block));
3212 if(block == zero_block)
3217# if DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN || DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_POPCOUNT
3218 constexpr size_t u_bits_number = std::numeric_limits<unsigned>::digits;
3219 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3220 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
3221 if constexpr(bits_per_block <= u_bits_number)
3223 return static_cast<size_type
>(__builtin_popcount(
static_cast<unsigned int>(block)));
3225 else if constexpr(bits_per_block <= ul_bits_number)
3227 return static_cast<size_type
>(__builtin_popcountl(
static_cast<unsigned long>(block)));
3229 else if constexpr(bits_per_block <= ull_bits_number)
3231 return static_cast<size_type
>(__builtin_popcountll(
static_cast<unsigned long long>(block)));
3235 size_type count = 0;
3236 block_type mask = 1;
3237 for(size_type bit_index = 0; bit_index < bits_per_block; ++bit_index)
3239 count +=
static_cast<size_type
>((block & mask) != zero_block);
3242 mask =
static_cast<block_type
>(mask << 1);
3248 template<
typename Block,
typename Allocator>
3250 dynamic_bitset<Block, Allocator>::block_count(
const block_type& block, size_type nbits)
noexcept
3252 assert(nbits <= bits_per_block);
3253#if DYNAMIC_BITSET_CAN_USE_STD_BITOPS
3254 const block_type shifted_block = block_type(block << (bits_per_block - nbits));
3255 return static_cast<size_type
>(std::popcount(shifted_block));
3257 const block_type shifted_block = block_type(block << (bits_per_block - nbits));
3258 if(shifted_block == zero_block)
3263# if DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN || DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_POPCOUNT
3264 constexpr size_t u_bits_number = std::numeric_limits<unsigned>::digits;
3265 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3266 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
3267 if constexpr(bits_per_block <= u_bits_number)
3269 return static_cast<size_type
>(__builtin_popcount(
static_cast<unsigned int>(shifted_block)));
3271 else if constexpr(bits_per_block <= ul_bits_number)
3273 return static_cast<size_type
>(__builtin_popcountl(
static_cast<unsigned long>(shifted_block)));
3275 else if constexpr(bits_per_block <= ull_bits_number)
3277 return static_cast<size_type
>(__builtin_popcountll(
static_cast<unsigned long long>(shifted_block)));
3281 size_type count = 0;
3282 block_type mask = 1;
3283 for(size_type bit_index = 0; bit_index < nbits; ++bit_index)
3285 count +=
static_cast<size_type
>((block & mask) != zero_block);
3288 mask =
static_cast<block_type
>(mask << 1);
3295 template<
typename Block,
typename Allocator>
3297 dynamic_bitset<Block, Allocator>::count_block_trailing_zero(
const block_type& block)
noexcept
3299 assert(block != zero_block);
3300#if DYNAMIC_BITSET_CAN_USE_STD_BITOPS
3301 return static_cast<size_type
>(std::countr_zero(block));
3303# if DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN || DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_CTZ
3304 constexpr size_t u_bits_number = std::numeric_limits<unsigned>::digits;
3305 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3306 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
3307 if constexpr(bits_per_block <= u_bits_number)
3309 return static_cast<size_type
>(__builtin_ctz(
static_cast<unsigned int>(block)));
3311 else if constexpr(bits_per_block <= ul_bits_number)
3313 return static_cast<size_type
>(__builtin_ctzl(
static_cast<unsigned long>(block)));
3315 else if constexpr(bits_per_block <= ull_bits_number)
3317 return static_cast<size_type
>(__builtin_ctzll(
static_cast<unsigned long long>(block)));
3320# elif DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD
3321 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3322 constexpr size_t ui64_bits_number = std::numeric_limits<unsigned __int64>::digits;
3323 if constexpr(bits_per_block <= ul_bits_number)
3325 unsigned long index = std::numeric_limits<unsigned long>::max();
3326 _BitScanForward(&index,
static_cast<unsigned long>(block));
3327 return static_cast<size_type
>(index);
3329 else if constexpr(bits_per_block <= ui64_bits_number)
3331# if DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD64
3332 unsigned long index = std::numeric_limits<unsigned long>::max();
3333 _BitScanForward64(&index,
static_cast<unsigned __int64
>(block));
3334 return static_cast<size_type
>(index);
3336 constexpr unsigned long max_ul = std::numeric_limits<unsigned long>::max();
3337 unsigned long low = block & max_ul;
3340 unsigned long index = std::numeric_limits<unsigned long>::max();
3341 _BitScanForward(&index, low);
3342 return static_cast<size_type
>(index);
3344 unsigned long high = block >> ul_bits_number;
3345 unsigned long index = std::numeric_limits<unsigned long>::max();
3346 _BitScanForward(&index, high);
3347 return static_cast<size_type
>(ul_bits_number + index);
3352 block_type mask = block_type(1);
3353 for(size_type i = 0; i < bits_per_block; ++i)
3355 if((block & mask) != zero_block)
3361 mask =
static_cast<block_type
>(mask << 1);
3368 template<
typename Block,
typename Allocator>
3369 template<
typename _CharT,
typename _Traits>
3371 dynamic_bitset<Block, Allocator>::init_from_string(std::basic_string_view<_CharT, _Traits> str,
3372 typename std::basic_string_view<_CharT, _Traits>::size_type pos,
3373 typename std::basic_string_view<_CharT, _Traits>::size_type n,
3374 [[maybe_unused]] _CharT zero,
3377 assert(pos < str.size());
3379 const size_type size = std::min(n, str.size() - pos);
3380 m_bits_number = size;
3383 m_blocks.resize(blocks_required(size));
3384 for(
size_t i = 0; i < size; ++i)
3386 const _CharT c = str[(pos + size - 1) - i];
3387 assert(c == zero || c == one);
3395 template<
typename Block,
typename Allocator>
3397 dynamic_bitset<Block, Allocator>::get_block(size_type pos)
3399 return m_blocks[block_index(pos)];
3402 template<
typename Block,
typename Allocator>
3404 dynamic_bitset<Block, Allocator>::get_block(size_type pos)
const
3406 return m_blocks[block_index(pos)];
3409 template<
typename Block,
typename Allocator>
3412 return m_blocks[m_blocks.size() - 1];
3415 template<
typename Block,
typename Allocator>
3418 return m_blocks[m_blocks.size() - 1];
3421 template<
typename Block,
typename Allocator>
3423 dynamic_bitset<Block, Allocator>::extra_bits_number() const noexcept
3425 return bit_index(m_bits_number);
3428 template<
typename Block,
typename Allocator>
3430 dynamic_bitset<Block, Allocator>::unused_bits_number() const noexcept
3432 return bits_per_block - extra_bits_number();
3435 template<
typename Block,
typename Allocator>
3436 template<
typename BinaryOperation>
3437 constexpr void dynamic_bitset<Block, Allocator>::apply(
const dynamic_bitset<Block, Allocator>& other,
3438 BinaryOperation binary_op)
3440 assert(num_blocks() == other.num_blocks());
3442 std::cbegin(m_blocks), std::cend(m_blocks), std::cbegin(other.m_blocks), std::begin(m_blocks), binary_op);
3445 template<
typename Block,
typename Allocator>
3446 template<
typename UnaryOperation>
3447 constexpr void dynamic_bitset<Block, Allocator>::apply(UnaryOperation unary_op)
3449 std::transform(std::cbegin(m_blocks), std::cend(m_blocks), std::begin(m_blocks), unary_op);
3452 template<
typename Block,
typename Allocator>
3453 constexpr void dynamic_bitset<Block, Allocator>::apply_left_shift(size_type shift)
3456 assert(shift < capacity());
3458 const size_type blocks_shift = shift / bits_per_block;
3459 const size_type bits_offset = shift % bits_per_block;
3461 if(bits_offset == 0)
3463 for(size_type i = m_blocks.size() - 1; i >= blocks_shift; --i)
3465 m_blocks[i] = m_blocks[i - blocks_shift];
3470 const size_type reverse_bits_offset = bits_per_block - bits_offset;
3471 for(size_type i = m_blocks.size() - 1; i > blocks_shift; --i)
3473 m_blocks[i] = block_type((m_blocks[i - blocks_shift] << bits_offset)
3474 | block_type(m_blocks[i - blocks_shift - 1] >> reverse_bits_offset));
3476 m_blocks[blocks_shift] = block_type(m_blocks[0] << bits_offset);
3480 std::fill(std::begin(m_blocks),
3481 std::begin(m_blocks) +
static_cast<typename decltype(m_blocks)::difference_type
>(blocks_shift),
3485 template<
typename Block,
typename Allocator>
3486 constexpr void dynamic_bitset<Block, Allocator>::apply_right_shift(size_type shift)
3489 assert(shift < capacity());
3491 const size_type blocks_shift = shift / bits_per_block;
3492 const size_type bits_offset = shift % bits_per_block;
3493 const size_type last_block_to_shift = m_blocks.size() - blocks_shift - 1;
3495 if(bits_offset == 0)
3497 for(size_type i = 0; i <= last_block_to_shift; ++i)
3499 m_blocks[i] = m_blocks[i + blocks_shift];
3504 const size_type reverse_bits_offset = bits_per_block - bits_offset;
3505 for(size_type i = 0; i < last_block_to_shift; ++i)
3507 m_blocks[i] = block_type((m_blocks[i + blocks_shift] >> bits_offset)
3508 | block_type(m_blocks[i + blocks_shift + 1] << reverse_bits_offset));
3510 m_blocks[last_block_to_shift] = block_type(m_blocks[m_blocks.size() - 1] >> bits_offset);
3514 std::fill(std::begin(m_blocks)
3515 +
static_cast<typename decltype(m_blocks)::difference_type
>(last_block_to_shift + 1),
3520 template<
typename Block,
typename Allocator>
3521 constexpr void dynamic_bitset<Block, Allocator>::sanitize()
3523 size_type shift = m_bits_number % bits_per_block;
3526 last_block() &=
static_cast<block_type
>(~(one_block << shift));
3530 template<
typename Block,
typename Allocator>
3531 constexpr bool dynamic_bitset<Block, Allocator>::check_unused_bits() const noexcept
3533 const size_type extra_bits = extra_bits_number();
3536 return (last_block() & (one_block << extra_bits)) == zero_block;
3541 template<
typename Block,
typename Allocator>
3542 constexpr bool dynamic_bitset<Block, Allocator>::check_size() const noexcept
3544 return blocks_required(size()) == m_blocks.size();
3547 template<
typename Block,
typename Allocator>
3548 constexpr bool dynamic_bitset<Block, Allocator>::check_consistency() const noexcept
3550 return check_unused_bits() && check_size();
3557 template<
typename Block,
typename Allocator>
3560 return !(lhs == rhs);
3563 template<
typename Block,
typename Allocator>
3566 return !(rhs < lhs);
3569 template<
typename Block,
typename Allocator>
3575 template<
typename Block,
typename Allocator>
3578 return !(lhs < rhs);
3581 template<
typename Block,
typename Allocator>
3586 return result &= rhs;
3589 template<
typename Block,
typename Allocator>
3594 return result |= rhs;
3597 template<
typename Block,
typename Allocator>
3602 return result ^= rhs;
3605 template<
typename Block,
typename Allocator>
3610 return result -= rhs;
3613 template<
typename _CharT,
typename _Traits,
typename Block,
typename Allocator>
3614 constexpr std::basic_ostream<_CharT, _Traits>&
operator<<(std::basic_ostream<_CharT, _Traits>& os,
3618 return os << bitset.template to_string<_CharT, _Traits>();
3621 template<
typename _CharT,
typename _Traits,
typename Block,
typename Allocator>
3622 constexpr std::basic_istream<_CharT, _Traits>&
operator>>(std::basic_istream<_CharT, _Traits>& is,
3626 constexpr _CharT zero = _CharT(
'0');
3627 constexpr _CharT one = _CharT(
'1');
3628 typename std::basic_istream<_CharT, _Traits>::sentry s(is);
3643 else if(val == zero)
3656 if(!reverse_bitset.
empty())
3668 template<
typename Block,
typename Allocator>
3672 bitset1.swap(bitset2);
3675#ifndef DYNAMIC_BITSET_NO_NAMESPACE
Reference to a sul::dynamic_bitset bit.
Definition dynamic_bitset.hpp:221
constexpr reference & reset()
Reset the referenced bit to false.
Definition dynamic_bitset.hpp:2124
constexpr reference & operator-=(bool v)
Apply binary difference to the referenced bit and a value, and assign the result to the referenced bi...
Definition dynamic_bitset.hpp:2095
constexpr reference & assign(bool v)
Assign the value v to the referenced bit.
Definition dynamic_bitset.hpp:2139
constexpr reference(dynamic_bitset< Block, Allocator > &bitset, size_type bit_pos)
Constructs a reference to a bit from a sul::dynamic_bitset and a bit position.
Definition dynamic_bitset.hpp:2029
constexpr reference & operator|=(bool v)
Apply binary operator OR to the referenced bit and a value, and assign the result to the referenced b...
Definition dynamic_bitset.hpp:2073
constexpr reference(const reference &) noexcept=default
Copy constructor.
constexpr reference(reference &&) noexcept=default
Move constructor.
constexpr reference & operator&=(bool v)
Apply binary operator AND to the referenced bit and a value, and assign the result to the referenced ...
Definition dynamic_bitset.hpp:2062
constexpr bool operator~() const
Return the result of applying unary NOT operator.
Definition dynamic_bitset.hpp:2105
constexpr reference & operator=(bool v)
Assign a value to the referenced bit.
Definition dynamic_bitset.hpp:2038
constexpr reference & flip()
Flip the referenced bit.
Definition dynamic_bitset.hpp:2131
constexpr reference & set()
Set the referenced bit to true.
Definition dynamic_bitset.hpp:2117
constexpr reference & operator^=(bool v)
Apply binary operator XOR to the referenced bit and a value, and assign the result to the referenced ...
Definition dynamic_bitset.hpp:2084
Dynamic bitset.
Definition dynamic_bitset.hpp:171
constexpr dynamic_bitset< Block, Allocator > & operator<<=(size_type shift)
Performs binary shift left of shift bits.
Definition dynamic_bitset.hpp:2455
constexpr size_type size() const noexcept
Give the number of bits of the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2786
constexpr dynamic_bitset< Block, Allocator > & operator^=(const dynamic_bitset< Block, Allocator > &rhs)
Sets the bits to the result of binary XOR on corresponding pairs of bits of *this and rhs.
Definition dynamic_bitset.hpp:2430
constexpr void push_back(bool value)
Add a new bit with the value value at the end of the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2288
constexpr bool test_set(size_type pos, bool value=true)
Test the value of the bit at position pos and set it to true or value value.
Definition dynamic_bitset.hpp:2669
constexpr dynamic_bitset< Block, Allocator > & set()
Set all the bits of the sul::dynamic_bitset to true.
Definition dynamic_bitset.hpp:2574
Block block_type
Same type as Block.
Definition dynamic_bitset.hpp:187
constexpr void swap(dynamic_bitset< Block, Allocator > &other) noexcept(noexcept(std::swap(m_blocks, other.m_blocks)))
Exchanges the bits of this sul::dynamic_bitset with those of other.
Definition dynamic_bitset.hpp:2919
constexpr void iterate_bits_on(Function &&function, Parameters &&... parameters) const
Iterate on the sul::dynamic_bitset and call function with the position of the bits on.
Definition dynamic_bitset.hpp:3012
constexpr bool empty() const noexcept
Checks if the sul::dynamic_bitset is empty.
Definition dynamic_bitset.hpp:2799
constexpr bool any() const
Checks if any bits are set to true.
Definition dynamic_bitset.hpp:2716
constexpr dynamic_bitset< Block, Allocator > operator<<(size_type shift) const
Performs binary shift right of shift bits.
Definition dynamic_bitset.hpp:2490
constexpr void clear()
Clears the sul::dynamic_bitset, resize it to 0.
Definition dynamic_bitset.hpp:2281
constexpr size_type num_blocks() const noexcept
Give the number of blocks used by the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2793
constexpr bool is_subset_of(const dynamic_bitset< Block, Allocator > &bitset) const
Determines if this sul::dynamic_bitset is a subset of bitset.
Definition dynamic_bitset.hpp:2824
constexpr std::basic_string< _CharT, _Traits, _Alloc > to_string(_CharT zero=_CharT('0'), _CharT one=_CharT('1')) const
Generate a string representation of the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2935
constexpr bool all() const
Checks if all bits are set to true.
Definition dynamic_bitset.hpp:2680
constexpr dynamic_bitset< Block, Allocator > & reset()
Reset all the bits of the sul::dynamic_bitset to false.
Definition dynamic_bitset.hpp:2594
constexpr dynamic_bitset< Block, Allocator > & operator&=(const dynamic_bitset< Block, Allocator > &rhs)
Sets the bits to the result of binary AND on corresponding pairs of bits of *this and rhs.
Definition dynamic_bitset.hpp:2404
constexpr bool is_proper_subset_of(const dynamic_bitset< Block, Allocator > &bitset) const
Determines if this sul::dynamic_bitset is a proper subset of bitset.
Definition dynamic_bitset.hpp:2839
constexpr dynamic_bitset< Block, Allocator > & operator-=(const dynamic_bitset< Block, Allocator > &rhs)
Sets the bits to the result of the binary difference between the bits of *this and rhs.
Definition dynamic_bitset.hpp:2443
constexpr size_type count() const noexcept
Count the number of bits set to true.
Definition dynamic_bitset.hpp:2736
size_t size_type
Type used to represent the size of a sul::dynamic_bitset.
Definition dynamic_bitset.hpp:180
constexpr dynamic_bitset(const dynamic_bitset< Block, Allocator > &other)=default
Copy constructor.
constexpr size_type capacity() const noexcept
Give the number of bits that the sul::dynamic_bitset has currently allocated space for.
Definition dynamic_bitset.hpp:2806
constexpr dynamic_bitset< Block, Allocator > & operator|=(const dynamic_bitset< Block, Allocator > &rhs)
Sets the bits to the result of binary OR on corresponding pairs of bits of *this and rhs.
Definition dynamic_bitset.hpp:2417
constexpr unsigned long to_ulong() const
Converts the contents of the bitset to an unsigned long integer.
Definition dynamic_bitset.hpp:2963
bool const_reference
Const reference to a sul::dynamic_bitset bit, type bool.
Definition dynamic_bitset.hpp:440
constexpr dynamic_bitset< Block, Allocator > & flip()
Flip all the bits of the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2654
constexpr size_type find_next(size_type prev) const
Find the position of the first bit set in the range [prev + 1, size()[ of the sul::dynamic_bitset sta...
Definition dynamic_bitset.hpp:2889
constexpr bool test(size_type pos) const
Test the value of the bit at position pos.
Definition dynamic_bitset.hpp:2662
constexpr void reserve(size_type num_bits)
Increase the capacity of the sul::dynamic_bitset to a value that's greater or equal to num_bits.
Definition dynamic_bitset.hpp:2812
constexpr void shrink_to_fit()
Requests the removal of unused capacity.
Definition dynamic_bitset.hpp:2818
constexpr bool none() const
Checks if none of the bits are set to true.
Definition dynamic_bitset.hpp:2729
constexpr size_type find_first() const
Find the position of the first bit set in the sul::dynamic_bitset starting from the least-significant...
Definition dynamic_bitset.hpp:2875
static constexpr size_type bits_per_block
Number of bits that can be stored in a block.
Definition dynamic_bitset.hpp:201
constexpr bool intersects(const dynamic_bitset< Block, Allocator > &bitset) const
Determines if this sul::dynamic_bitset and bitset intersect.
Definition dynamic_bitset.hpp:2861
Allocator allocator_type
Same type as Allocator.
Definition dynamic_bitset.hpp:194
constexpr void append(block_type block)
Append a block of bits block at the end of the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2329
constexpr allocator_type get_allocator() const
Gets the associated allocator.
Definition dynamic_bitset.hpp:2928
constexpr block_type * data() noexcept
Return a pointer to the underlying array serving as blocks storage.
Definition dynamic_bitset.hpp:3050
constexpr reference operator[](size_type pos)
Accesses the bit at position pos.
Definition dynamic_bitset.hpp:2771
constexpr dynamic_bitset< Block, Allocator > & flip(size_type pos, size_type len)
Flip the bits of the range [pos, pos + len[.
Definition dynamic_bitset.hpp:2601
static constexpr size_type npos
Maximum value of size_type, returned for invalid positions.
Definition dynamic_bitset.hpp:208
constexpr void pop_back()
Remove the last bit of the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2307
constexpr void resize(size_type nbits, bool value=false)
Resize the sul::dynamic_bitset to contain nbits bits.
Definition dynamic_bitset.hpp:2249
constexpr dynamic_bitset< Block, Allocator > operator~() const
Performs a unary NOT on all bits.
Definition dynamic_bitset.hpp:2502
constexpr unsigned long long to_ullong() const
Converts the contents of the bitset to an unsigned long long integer.
Definition dynamic_bitset.hpp:2987
constexpr dynamic_bitset< Block, Allocator > operator>>(size_type shift) const
Performs binary shift left of shift bits.
Definition dynamic_bitset.hpp:2496
constexpr dynamic_bitset< Block, Allocator > & operator>>=(size_type shift)
Performs binary shift right of shift bits.
Definition dynamic_bitset.hpp:2473
Simple Useful Libraries.
Definition dynamic_bitset.hpp:147
constexpr bool operator>=(const dynamic_bitset< Block, Allocator > &lhs, const dynamic_bitset< Block, Allocator > &rhs)
Test if lhs is "greater than or equal to" rhs. The comparison of the two sul::dynamic_bitset is first...
Definition dynamic_bitset.hpp:3576
constexpr bool operator<=(const dynamic_bitset< Block, Allocator > &lhs, const dynamic_bitset< Block, Allocator > &rhs)
Test if lhs is "less than or equal to" rhs. The comparison of the two sul::dynamic_bitset is first on...
Definition dynamic_bitset.hpp:3564
constexpr bool operator<(const dynamic_bitset< Block_, Allocator_ > &lhs, const dynamic_bitset< Block_, Allocator_ > &rhs)
Definition dynamic_bitset.hpp:3070
constexpr bool operator>(const dynamic_bitset< Block, Allocator > &lhs, const dynamic_bitset< Block, Allocator > &rhs)
Test if lhs is "greater than" rhs. The comparison of the two sul::dynamic_bitset is first on numbers ...
Definition dynamic_bitset.hpp:3570
constexpr std::basic_istream< _CharT, _Traits > & operator>>(std::basic_istream< _CharT, _Traits > &is, dynamic_bitset< Block, Allocator > &bitset)
Extract a sul::dynamic_bitset from a character stream using its string representation.
Definition dynamic_bitset.hpp:3622
constexpr dynamic_bitset< Block, Allocator > operator|(const dynamic_bitset< Block, Allocator > &lhs, const dynamic_bitset< Block, Allocator > &rhs)
Performs binary OR on corresponding pairs of bits of lhs and rhs.
Definition dynamic_bitset.hpp:3590
constexpr dynamic_bitset< Block, Allocator > operator&(const dynamic_bitset< Block, Allocator > &lhs, const dynamic_bitset< Block, Allocator > &rhs)
Performs binary AND on corresponding pairs of bits of lhs and rhs.
Definition dynamic_bitset.hpp:3582
constexpr dynamic_bitset< Block, Allocator > operator-(const dynamic_bitset< Block, Allocator > &lhs, const dynamic_bitset< Block, Allocator > &rhs)
Performs binary difference between bits of lhs and rhs.
Definition dynamic_bitset.hpp:3606
constexpr dynamic_bitset< Block, Allocator > operator^(const dynamic_bitset< Block, Allocator > &lhs, const dynamic_bitset< Block, Allocator > &rhs)
Performs binary XOR on corresponding pairs of bits of lhs and rhs.
Definition dynamic_bitset.hpp:3598
constexpr std::basic_ostream< _CharT, _Traits > & operator<<(std::basic_ostream< _CharT, _Traits > &os, const dynamic_bitset< Block, Allocator > &bitset)
Insert a string representation of this sul::dynamic_bitset to a character stream.
Definition dynamic_bitset.hpp:3614
constexpr bool operator==(const dynamic_bitset< Block_, Allocator_ > &lhs, const dynamic_bitset< Block_, Allocator_ > &rhs)
Definition dynamic_bitset.hpp:3063
constexpr bool operator!=(const dynamic_bitset< Block, Allocator > &lhs, const dynamic_bitset< Block, Allocator > &rhs)
Test if two sul::dynamic_bitset content are different.
Definition dynamic_bitset.hpp:3558
constexpr void swap(dynamic_bitset< Block, Allocator > &bitset1, dynamic_bitset< Block, Allocator > &bitset2) noexcept(noexcept(bitset1.swap(bitset2)))
Exchange the content of bitset1 and bitset2.
Definition dynamic_bitset.hpp:3669