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 3
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)
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++;
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);
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);
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);
2395 m_blocks.push_back(block);
2399 assert(check_consistency());
2402 template<
typename Block,
typename Allocator>
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>
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>
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>
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>
2515 assert(pos <=
size());
2518 assert(pos <
size());
2519 assert(pos + len - 1 <
size());
2521 const size_type first_block = block_index(pos);
2522 const size_type last_block = block_index(pos + len - 1);
2523 const size_type first_bit_index = bit_index(pos);
2524 const size_type last_bit_index = bit_index(pos + len - 1);
2526 if(first_block == last_block)
2528 set_block_bits(m_blocks[first_block], first_bit_index, last_bit_index, value);
2532 size_type first_full_block = first_block;
2535 if(first_bit_index != 0)
2538 set_block_bits(m_blocks[first_block], first_bit_index, block_last_bit_index, value);
2541 if(last_bit_index != block_last_bit_index)
2544 set_block_bits(m_blocks[last_block], 0, last_bit_index, value);
2547 const block_type full_block = value ? one_block : zero_block;
2548 for(
size_type i = first_full_block; i <= last_full_block; ++i)
2550 m_blocks[i] = full_block;
2557 template<
typename Block,
typename Allocator>
2560 assert(pos <
size());
2564 m_blocks[block_index(pos)] |= bit_mask(pos);
2568 m_blocks[block_index(pos)] &=
static_cast<block_type>(~bit_mask(pos));
2574 template<
typename Block,
typename Allocator>
2577 std::fill(std::begin(m_blocks), std::end(m_blocks), one_block);
2582 template<
typename Block,
typename Allocator>
2585 return set(pos, len,
false);
2588 template<
typename Block,
typename Allocator>
2591 return set(pos,
false);
2594 template<
typename Block,
typename Allocator>
2597 std::fill(std::begin(m_blocks), std::end(m_blocks), zero_block);
2601 template<
typename Block,
typename Allocator>
2606 assert(pos <=
size());
2609 assert(pos <
size());
2610 assert(pos + len - 1 <
size());
2612 const size_type first_block = block_index(pos);
2613 const size_type last_block = block_index(pos + len - 1);
2614 const size_type first_bit_index = bit_index(pos);
2615 const size_type last_bit_index = bit_index(pos + len - 1);
2617 if(first_block == last_block)
2619 flip_block_bits(m_blocks[first_block], first_bit_index, last_bit_index);
2623 size_type first_full_block = first_block;
2626 if(first_bit_index != 0)
2629 flip_block_bits(m_blocks[first_block], first_bit_index, block_last_bit_index);
2632 if(last_bit_index != block_last_bit_index)
2635 flip_block_bits(m_blocks[last_block], 0, last_bit_index);
2638 for(
size_type i = first_full_block; i <= last_full_block; ++i)
2647 template<
typename Block,
typename Allocator>
2650 assert(pos <
size());
2651 m_blocks[block_index(pos)] ^= bit_mask(pos);
2655 template<
typename Block,
typename Allocator>
2658 std::transform(std::cbegin(m_blocks), std::cend(m_blocks), std::begin(m_blocks), std::bit_not<block_type>());
2663 template<
typename Block,
typename Allocator>
2666 assert(pos <
size());
2667 return (m_blocks[block_index(pos)] & bit_mask(pos)) != zero_block;
2670 template<
typename Block,
typename Allocator>
2673 bool const result =
test(pos);
2681 template<
typename Block,
typename Allocator>
2690 if(extra_bits_number() == 0)
2694 if(block != full_block)
2702 for(
size_type i = 0; i < m_blocks.size() - 1; ++i)
2704 if(m_blocks[i] != full_block)
2709 if(last_block() != (full_block >> unused_bits_number()))
2717 template<
typename Block,
typename Allocator>
2722 if(block != zero_block)
2730 template<
typename Block,
typename Allocator>
2736 template<
typename Block,
typename Allocator>
2745#if DYNAMIC_BITSET_CAN_USE_LIBPOPCNT
2751 for(
size_type i = 0; i < m_blocks.size() - 1; ++i)
2753 count += block_count(m_blocks[i]);
2758 const size_type extra_bits = extra_bits_number();
2761 count += block_count(block);
2765 count += block_count(block, extra_bits);
2771 template<
typename Block,
typename Allocator>
2775 assert(pos <
size());
2779 template<
typename Block,
typename Allocator>
2786 template<
typename Block,
typename Allocator>
2790 return m_bits_number;
2793 template<
typename Block,
typename Allocator>
2797 return m_blocks.size();
2800 template<
typename Block,
typename Allocator>
2806 template<
typename Block,
typename Allocator>
2813 template<
typename Block,
typename Allocator>
2816 m_blocks.reserve(blocks_required(num_bits));
2819 template<
typename Block,
typename Allocator>
2822 m_blocks.shrink_to_fit();
2825 template<
typename Block,
typename Allocator>
2829 for(
size_type i = 0; i < m_blocks.size(); ++i)
2831 if((m_blocks[i] & ~bitset.m_blocks[i]) != zero_block)
2839 template<
typename Block,
typename Allocator>
2844 bool is_proper =
false;
2845 for(
size_type i = 0; i < m_blocks.size(); ++i)
2848 const block_type& other_block = bitset.m_blocks[i];
2850 if((self_block & ~other_block) != zero_block)
2854 if((~self_block & other_block) != zero_block)
2862 template<
typename Block,
typename Allocator>
2865 const size_type min_blocks_number = std::min(m_blocks.size(), bitset.m_blocks.size());
2866 for(
size_type i = 0; i < min_blocks_number; ++i)
2868 if((m_blocks[i] & bitset.m_blocks[i]) != zero_block)
2876 template<
typename Block,
typename Allocator>
2879 for(
size_type i = 0; i < m_blocks.size(); ++i)
2881 if(m_blocks[i] != zero_block)
2883 return i *
bits_per_block + count_block_trailing_zero(m_blocks[i]);
2889 template<
typename Block,
typename Allocator>
2899 const size_type first_block = block_index(first_bit);
2900 const size_type first_bit_index = bit_index(first_bit);
2903 if(first_block_shifted != zero_block)
2905 return first_bit + count_block_trailing_zero(first_block_shifted);
2909 for(
size_type i = first_block + 1; i < m_blocks.size(); ++i)
2911 if(m_blocks[i] != zero_block)
2913 return i *
bits_per_block + count_block_trailing_zero(m_blocks[i]);
2920 template<
typename Block,
typename Allocator>
2922 noexcept(std::swap(m_blocks, other.m_blocks)))
2924 std::swap(m_blocks, other.m_blocks);
2925 std::swap(m_bits_number, other.m_bits_number);
2928 template<
typename Block,
typename Allocator>
2932 return m_blocks.get_allocator();
2935 template<
typename Block,
typename Allocator>
2936 template<
typename _CharT,
typename _Traits,
typename _Alloc>
2941 std::basic_string<_CharT, _Traits, _Alloc> str(len, zero);
2942 for(
size_type i_block = 0; i_block < m_blocks.size(); ++i_block)
2944 if(m_blocks[i_block] == zero_block)
2950 for(
size_type i_bit = 0; i_bit < limit; ++i_bit)
2952 if((m_blocks[i_block] & mask) != zero_block)
2954 _Traits::assign(str[len - (i_block *
bits_per_block + i_bit + 1)], one);
2964 template<
typename Block,
typename Allocator>
2967 if(m_bits_number == 0)
2972 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
2975 throw std::overflow_error(
"sul::dynamic_bitset::to_ulong");
2978 unsigned long result = 0;
2979 const size_type result_bits_number = std::min(ul_bits_number, m_bits_number);
2980 for(
size_type i_block = 0; i_block <= block_index(result_bits_number - 1); ++i_block)
2982 result |= (
static_cast<unsigned long>(m_blocks[i_block]) << (i_block *
bits_per_block));
2988 template<
typename Block,
typename Allocator>
2991 if(m_bits_number == 0)
2996 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
2999 throw std::overflow_error(
"sul::dynamic_bitset::to_ullong");
3002 unsigned long long result = 0;
3003 const size_type result_bits_number = std::min(ull_bits_number, m_bits_number);
3004 for(
size_type i_block = 0; i_block <= block_index(result_bits_number - 1); ++i_block)
3006 result |= (
static_cast<unsigned long long>(m_blocks[i_block]) << (i_block *
bits_per_block));
3012 template<
typename Block,
typename Allocator>
3013 template<
typename Function,
typename... Parameters>
3015 Parameters&&... parameters)
const
3017 if constexpr(!std::is_invocable_v<Function, size_t, Parameters...>)
3019 static_assert(dependent_false<Function>::value,
"Function take invalid arguments");
3023 if constexpr(std::is_same_v<std::invoke_result_t<Function, size_t, Parameters...>,
void>)
3026 while(i_bit !=
npos)
3028 std::invoke(std::forward<Function>(function), i_bit, std::forward<Parameters>(parameters)...);
3032 else if constexpr(std::is_convertible_v<std::invoke_result_t<Function, size_t, Parameters...>,
bool>)
3035 while(i_bit !=
npos)
3037 if(!std::invoke(std::forward<Function>(function), i_bit, std::forward<Parameters>(parameters)...))
3046 static_assert(dependent_false<Function>::value,
"Function have invalid return type");
3051 template<
typename Block,
typename Allocator>
3054 return m_blocks.data();
3057 template<
typename Block,
typename Allocator>
3061 return m_blocks.data();
3064 template<
typename Block_,
typename Allocator_>
3068 return (lhs.m_bits_number == rhs.m_bits_number) && (lhs.m_blocks == rhs.m_blocks);
3071 template<
typename Block_,
typename Allocator_>
3079 const size_type lhs_blocks_size = lhs.m_blocks.size();
3080 const size_type rhs_blocks_size = rhs.m_blocks.size();
3082 if(lhs_size == rhs_size)
3090 for(
size_type i = lhs_blocks_size - 1; i > 0; --i)
3092 if(lhs.m_blocks[i] != rhs.m_blocks[i])
3094 return lhs.m_blocks[i] < rhs.m_blocks[i];
3097 return lhs.m_blocks[0] < rhs.m_blocks[0];
3110 const bool rhs_longer = rhs_size > lhs_size;
3112 const size_type longest_blocks_size = std::max(lhs_blocks_size, rhs_blocks_size);
3113 const size_type shortest_blocks_size = std::min(lhs_blocks_size, rhs_blocks_size);
3114 for(
size_type i = longest_blocks_size - 1; i >= shortest_blocks_size; --i)
3116 if(longest_bitset.m_blocks[i] !=
block_type(0))
3122 for(
size_type i = shortest_blocks_size - 1; i > 0; --i)
3124 if(lhs.m_blocks[i] != rhs.m_blocks[i])
3126 return lhs.m_blocks[i] < rhs.m_blocks[i];
3129 if(lhs.m_blocks[0] != rhs.m_blocks[0])
3131 return lhs.m_blocks[0] < rhs.m_blocks[0];
3133 return lhs_size < rhs_size;
3140 template<
typename Block,
typename Allocator>
3142 dynamic_bitset<Block, Allocator>::blocks_required(size_type nbits)
noexcept
3144 return nbits / bits_per_block +
static_cast<size_type
>(nbits % bits_per_block > 0);
3147 template<
typename Block,
typename Allocator>
3149 dynamic_bitset<Block, Allocator>::block_index(size_type pos)
noexcept
3151 return pos / bits_per_block;
3154 template<
typename Block,
typename Allocator>
3156 dynamic_bitset<Block, Allocator>::bit_index(size_type pos)
noexcept
3158 return pos % bits_per_block;
3161 template<
typename Block,
typename Allocator>
3163 dynamic_bitset<Block, Allocator>::bit_mask(size_type pos)
noexcept
3165 return block_type(block_type(1) << bit_index(pos));
3168 template<
typename Block,
typename Allocator>
3170 dynamic_bitset<Block, Allocator>::bit_mask(size_type first, size_type last)
noexcept
3172 first = bit_index(first);
3173 last = bit_index(last);
3174 if(last == (block_last_bit_index))
3176 return block_type(one_block << first);
3180 return block_type(((block_type(1) << (last + 1)) - 1) ^ ((block_type(1) << first) - 1));
3184 template<
typename Block,
typename Allocator>
3185 constexpr void dynamic_bitset<Block, Allocator>::set_block_bits(block_type& block,
3192 block |= bit_mask(first, last);
3196 block &=
static_cast<block_type
>(~bit_mask(first, last));
3200 template<
typename Block,
typename Allocator>
3202 dynamic_bitset<Block, Allocator>::flip_block_bits(block_type& block, size_type first, size_type last)
noexcept
3204 block ^= bit_mask(first, last);
3207 template<
typename Block,
typename Allocator>
3209 dynamic_bitset<Block, Allocator>::block_count(
const block_type& block)
noexcept
3211#if DYNAMIC_BITSET_CAN_USE_STD_BITOPS
3212 return static_cast<size_type
>(std::popcount(block));
3214 if(block == zero_block)
3219# if DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN || DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_POPCOUNT
3220 constexpr size_t u_bits_number = std::numeric_limits<unsigned>::digits;
3221 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3222 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
3223 if constexpr(bits_per_block <= u_bits_number)
3225 return static_cast<size_type
>(__builtin_popcount(
static_cast<unsigned int>(block)));
3227 else if constexpr(bits_per_block <= ul_bits_number)
3229 return static_cast<size_type
>(__builtin_popcountl(
static_cast<unsigned long>(block)));
3231 else if constexpr(bits_per_block <= ull_bits_number)
3233 return static_cast<size_type
>(__builtin_popcountll(
static_cast<unsigned long long>(block)));
3237 size_type count = 0;
3238 block_type mask = 1;
3239 for(size_type bit_index = 0; bit_index < bits_per_block; ++bit_index)
3241 count +=
static_cast<size_type
>((block & mask) != zero_block);
3244 mask =
static_cast<block_type
>(mask << 1);
3250 template<
typename Block,
typename Allocator>
3252 dynamic_bitset<Block, Allocator>::block_count(
const block_type& block, size_type nbits)
noexcept
3254 assert(nbits <= bits_per_block);
3255#if DYNAMIC_BITSET_CAN_USE_STD_BITOPS
3256 const block_type shifted_block = block_type(block << (bits_per_block - nbits));
3257 return static_cast<size_type
>(std::popcount(shifted_block));
3259 const block_type shifted_block = block_type(block << (bits_per_block - nbits));
3260 if(shifted_block == zero_block)
3265# if DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN || DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_POPCOUNT
3266 constexpr size_t u_bits_number = std::numeric_limits<unsigned>::digits;
3267 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3268 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
3269 if constexpr(bits_per_block <= u_bits_number)
3271 return static_cast<size_type
>(__builtin_popcount(
static_cast<unsigned int>(shifted_block)));
3273 else if constexpr(bits_per_block <= ul_bits_number)
3275 return static_cast<size_type
>(__builtin_popcountl(
static_cast<unsigned long>(shifted_block)));
3277 else if constexpr(bits_per_block <= ull_bits_number)
3279 return static_cast<size_type
>(__builtin_popcountll(
static_cast<unsigned long long>(shifted_block)));
3283 size_type count = 0;
3284 block_type mask = 1;
3285 for(size_type bit_index = 0; bit_index < nbits; ++bit_index)
3287 count +=
static_cast<size_type
>((block & mask) != zero_block);
3290 mask =
static_cast<block_type
>(mask << 1);
3297 template<
typename Block,
typename Allocator>
3299 dynamic_bitset<Block, Allocator>::count_block_trailing_zero(
const block_type& block)
noexcept
3301 assert(block != zero_block);
3302#if DYNAMIC_BITSET_CAN_USE_STD_BITOPS
3303 return static_cast<size_type
>(std::countr_zero(block));
3305# if DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN || DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_CTZ
3306 constexpr size_t u_bits_number = std::numeric_limits<unsigned>::digits;
3307 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3308 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
3309 if constexpr(bits_per_block <= u_bits_number)
3311 return static_cast<size_type
>(__builtin_ctz(
static_cast<unsigned int>(block)));
3313 else if constexpr(bits_per_block <= ul_bits_number)
3315 return static_cast<size_type
>(__builtin_ctzl(
static_cast<unsigned long>(block)));
3317 else if constexpr(bits_per_block <= ull_bits_number)
3319 return static_cast<size_type
>(__builtin_ctzll(
static_cast<unsigned long long>(block)));
3322# elif DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD
3323 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3324 constexpr size_t ui64_bits_number = std::numeric_limits<unsigned __int64>::digits;
3325 if constexpr(bits_per_block <= ul_bits_number)
3327 unsigned long index = std::numeric_limits<unsigned long>::max();
3328 _BitScanForward(&index,
static_cast<unsigned long>(block));
3329 return static_cast<size_type
>(index);
3331 else if constexpr(bits_per_block <= ui64_bits_number)
3333# if DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD64
3334 unsigned long index = std::numeric_limits<unsigned long>::max();
3335 _BitScanForward64(&index,
static_cast<unsigned __int64
>(block));
3336 return static_cast<size_type
>(index);
3338 constexpr unsigned long max_ul = std::numeric_limits<unsigned long>::max();
3339 unsigned long low = block & max_ul;
3342 unsigned long index = std::numeric_limits<unsigned long>::max();
3343 _BitScanForward(&index, low);
3344 return static_cast<size_type
>(index);
3346 unsigned long high = block >> ul_bits_number;
3347 unsigned long index = std::numeric_limits<unsigned long>::max();
3348 _BitScanForward(&index, high);
3349 return static_cast<size_type
>(ul_bits_number + index);
3354 block_type mask = block_type(1);
3355 for(size_type i = 0; i < bits_per_block; ++i)
3357 if((block & mask) != zero_block)
3363 mask =
static_cast<block_type
>(mask << 1);
3370 template<
typename Block,
typename Allocator>
3371 template<
typename _CharT,
typename _Traits>
3373 dynamic_bitset<Block, Allocator>::init_from_string(std::basic_string_view<_CharT, _Traits> str,
3374 typename std::basic_string_view<_CharT, _Traits>::size_type pos,
3375 typename std::basic_string_view<_CharT, _Traits>::size_type n,
3376 [[maybe_unused]] _CharT zero,
3379 assert(pos < str.size());
3381 const size_type size = std::min(n, str.size() - pos);
3382 m_bits_number = size;
3385 m_blocks.resize(blocks_required(size));
3386 for(
size_t i = 0; i < size; ++i)
3388 const _CharT c = str[(pos + size - 1) - i];
3389 assert(c == zero || c == one);
3397 template<
typename Block,
typename Allocator>
3399 dynamic_bitset<Block, Allocator>::get_block(size_type pos)
3401 return m_blocks[block_index(pos)];
3404 template<
typename Block,
typename Allocator>
3406 dynamic_bitset<Block, Allocator>::get_block(size_type pos)
const
3408 return m_blocks[block_index(pos)];
3411 template<
typename Block,
typename Allocator>
3414 return m_blocks[m_blocks.size() - 1];
3417 template<
typename Block,
typename Allocator>
3420 return m_blocks[m_blocks.size() - 1];
3423 template<
typename Block,
typename Allocator>
3425 dynamic_bitset<Block, Allocator>::extra_bits_number() const noexcept
3427 return bit_index(m_bits_number);
3430 template<
typename Block,
typename Allocator>
3432 dynamic_bitset<Block, Allocator>::unused_bits_number() const noexcept
3434 return bits_per_block - extra_bits_number();
3437 template<
typename Block,
typename Allocator>
3438 template<
typename BinaryOperation>
3440 BinaryOperation binary_op)
3442 assert(num_blocks() == other.num_blocks());
3444 std::cbegin(m_blocks), std::cend(m_blocks), std::cbegin(other.m_blocks), std::begin(m_blocks), binary_op);
3447 template<
typename Block,
typename Allocator>
3448 template<
typename UnaryOperation>
3449 constexpr void dynamic_bitset<Block, Allocator>::apply(UnaryOperation unary_op)
3451 std::transform(std::cbegin(m_blocks), std::cend(m_blocks), std::begin(m_blocks), unary_op);
3454 template<
typename Block,
typename Allocator>
3455 constexpr void dynamic_bitset<Block, Allocator>::apply_left_shift(size_type shift)
3458 assert(shift < capacity());
3460 const size_type blocks_shift = shift / bits_per_block;
3461 const size_type bits_offset = shift % bits_per_block;
3463 if(bits_offset == 0)
3465 for(size_type i = m_blocks.size() - 1; i >= blocks_shift; --i)
3467 m_blocks[i] = m_blocks[i - blocks_shift];
3472 const size_type reverse_bits_offset = bits_per_block - bits_offset;
3473 for(size_type i = m_blocks.size() - 1; i > blocks_shift; --i)
3475 m_blocks[i] = block_type((m_blocks[i - blocks_shift] << bits_offset)
3476 | block_type(m_blocks[i - blocks_shift - 1] >> reverse_bits_offset));
3478 m_blocks[blocks_shift] = block_type(m_blocks[0] << bits_offset);
3482 std::fill(std::begin(m_blocks),
3483 std::begin(m_blocks) +
static_cast<typename decltype(m_blocks)::difference_type
>(blocks_shift),
3487 template<
typename Block,
typename Allocator>
3488 constexpr void dynamic_bitset<Block, Allocator>::apply_right_shift(size_type shift)
3491 assert(shift < capacity());
3493 const size_type blocks_shift = shift / bits_per_block;
3494 const size_type bits_offset = shift % bits_per_block;
3495 const size_type last_block_to_shift = m_blocks.size() - blocks_shift - 1;
3497 if(bits_offset == 0)
3499 for(size_type i = 0; i <= last_block_to_shift; ++i)
3501 m_blocks[i] = m_blocks[i + blocks_shift];
3506 const size_type reverse_bits_offset = bits_per_block - bits_offset;
3507 for(size_type i = 0; i < last_block_to_shift; ++i)
3509 m_blocks[i] = block_type((m_blocks[i + blocks_shift] >> bits_offset)
3510 | block_type(m_blocks[i + blocks_shift + 1] << reverse_bits_offset));
3512 m_blocks[last_block_to_shift] = block_type(m_blocks[m_blocks.size() - 1] >> bits_offset);
3516 std::fill(std::begin(m_blocks)
3517 +
static_cast<typename decltype(m_blocks)::difference_type
>(last_block_to_shift + 1),
3522 template<
typename Block,
typename Allocator>
3523 constexpr void dynamic_bitset<Block, Allocator>::sanitize()
3525 size_type shift = m_bits_number % bits_per_block;
3528 last_block() &=
static_cast<block_type
>(~(one_block << shift));
3532 template<
typename Block,
typename Allocator>
3533 constexpr bool dynamic_bitset<Block, Allocator>::check_unused_bits() const noexcept
3535 const size_type extra_bits = extra_bits_number();
3538 return (last_block() & (one_block << extra_bits)) == zero_block;
3543 template<
typename Block,
typename Allocator>
3544 constexpr bool dynamic_bitset<Block, Allocator>::check_size() const noexcept
3546 return blocks_required(size()) == m_blocks.size();
3549 template<
typename Block,
typename Allocator>
3550 constexpr bool dynamic_bitset<Block, Allocator>::check_consistency() const noexcept
3552 return check_unused_bits() && check_size();
3559 template<
typename Block,
typename Allocator>
3562 return !(lhs == rhs);
3565 template<
typename Block,
typename Allocator>
3568 return !(rhs < lhs);
3571 template<
typename Block,
typename Allocator>
3577 template<
typename Block,
typename Allocator>
3580 return !(lhs < rhs);
3583 template<
typename Block,
typename Allocator>
3588 return result &= rhs;
3591 template<
typename Block,
typename Allocator>
3596 return result |= rhs;
3599 template<
typename Block,
typename Allocator>
3604 return result ^= rhs;
3607 template<
typename Block,
typename Allocator>
3612 return result -= rhs;
3615 template<
typename _CharT,
typename _Traits,
typename Block,
typename Allocator>
3616 constexpr std::basic_ostream<_CharT, _Traits>&
operator<<(std::basic_ostream<_CharT, _Traits>& os,
3623 template<
typename _CharT,
typename _Traits,
typename Block,
typename Allocator>
3624 constexpr std::basic_istream<_CharT, _Traits>&
operator>>(std::basic_istream<_CharT, _Traits>& is,
3628 constexpr _CharT zero = _CharT(
'0');
3629 constexpr _CharT one = _CharT(
'1');
3630 typename std::basic_istream<_CharT, _Traits>::sentry s(is);
3645 else if(val == zero)
3658 if(!reverse_bitset.
empty())
3670 template<
typename Block,
typename Allocator>
3674 bitset1.swap(bitset2);
3677#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 > & set(size_type pos, size_type len, bool value)
Set the bits of the range [pos, pos + len[ to value value.
Definition dynamic_bitset.hpp:2511
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:2788
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:2671
constexpr dynamic_bitset< Block, Allocator > & set()
Set all the bits of the sul::dynamic_bitset to true.
Definition dynamic_bitset.hpp:2575
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:2921
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:3014
constexpr bool empty() const noexcept
Checks if the sul::dynamic_bitset is empty.
Definition dynamic_bitset.hpp:2801
Block block_type
Same type as Block.
Definition dynamic_bitset.hpp:187
constexpr bool any() const
Checks if any bits are set to true.
Definition dynamic_bitset.hpp:2718
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:2795
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:2826
size_t size_type
Type used to represent the size of a sul::dynamic_bitset.
Definition dynamic_bitset.hpp:180
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:2937
constexpr bool all() const
Checks if all bits are set to true.
Definition dynamic_bitset.hpp:2682
constexpr dynamic_bitset< Block, Allocator > & reset()
Reset all the bits of the sul::dynamic_bitset to false.
Definition dynamic_bitset.hpp:2595
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
Allocator allocator_type
Same type as Allocator.
Definition dynamic_bitset.hpp:194
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:2841
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:2738
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:2808
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:2965
constexpr dynamic_bitset< Block, Allocator > & flip()
Flip all the bits of the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2656
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:2891
constexpr bool test(size_type pos) const
Test the value of the bit at position pos.
Definition dynamic_bitset.hpp:2664
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:2814
constexpr void shrink_to_fit()
Requests the removal of unused capacity.
Definition dynamic_bitset.hpp:2820
constexpr bool none() const
Checks if none of the bits are set to true.
Definition dynamic_bitset.hpp:2731
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:2877
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:2863
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
bool const_reference
Const reference to a sul::dynamic_bitset bit, type bool.
Definition dynamic_bitset.hpp:440
constexpr allocator_type get_allocator() const
Gets the associated allocator.
Definition dynamic_bitset.hpp:2930
constexpr block_type * data() noexcept
Return a pointer to the underlying array serving as blocks storage.
Definition dynamic_bitset.hpp:3052
constexpr reference operator[](size_type pos)
Accesses the bit at position pos.
Definition dynamic_bitset.hpp:2773
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:2602
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:2989
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 > & reset(size_type pos, size_type len)
Reset the bits of the range [pos, pos + len[ to false.
Definition dynamic_bitset.hpp:2583
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:3578
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:3566
constexpr bool operator<(const dynamic_bitset< Block_, Allocator_ > &lhs, const dynamic_bitset< Block_, Allocator_ > &rhs)
Definition dynamic_bitset.hpp:3072
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:3572
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:3624
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:3592
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:3584
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:3608
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:3600
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:3616
constexpr bool operator==(const dynamic_bitset< Block_, Allocator_ > &lhs, const dynamic_bitset< Block_, Allocator_ > &rhs)
Definition dynamic_bitset.hpp:3065
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:3560
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:3671