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 0
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) \
99 && __has_builtin(__builtin_ctzll)
100# define DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_CTZ true
103# elif defined(__GNUC__)
105# define DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN true
106# elif defined(_MSC_VER)
110# if defined(_M_IX86) || defined(_M_ARM) || defined(_M_X64) || defined(_M_ARM64)
112# pragma intrinsic(_BitScanForward)
113# define DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD true
115# if(defined(_M_X64) || defined(_M_ARM64)) \
116 && !defined(DYNAMIC_BITSET_NO_MSVC_BUILTIN_BITSCANFORWARD64)
117# pragma intrinsic(_BitScanForward64)
118# define DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD64 true
122#if !defined(DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_POPCOUNT)
123# define DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_POPCOUNT false
125#if !defined(DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_CTZ)
126# define DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_CTZ false
128#if !defined(DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN)
129# define DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN false
131#if !defined(DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD)
132# define DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD false
134#if !defined(DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD64)
135# define DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD64 false
137#if !defined(DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN)
138# define DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN false
141#ifndef DYNAMIC_BITSET_NO_NAMESPACE
170template<
typename Block =
unsigned long long,
typename Allocator = std::allocator<Block>>
173 static_assert(std::is_unsigned<Block>::value,
"Block is not an unsigned integral type");
367 [[nodiscard]] constexpr
bool operator~() const;
376 [[nodiscard]] constexpr operator
bool() const;
383 constexpr
void operator&() = delete;
503 unsigned long long init_val = 0,
548 template<typename _CharT, typename _Traits>
550 std::basic_string_view<_CharT, _Traits> str,
551 typename std::basic_string_view<_CharT, _Traits>::
size_type pos = 0,
552 typename std::basic_string_view<_CharT, _Traits>::
size_type n =
553 std::basic_string_view<_CharT, _Traits>::
npos,
554 _CharT zero = _CharT('0'),
555 _CharT one = _CharT('1'),
584 template<typename _CharT, typename _Traits, typename _Alloc>
586 const std::basic_string<_CharT, _Traits, _Alloc>& str,
587 typename std::basic_string<_CharT, _Traits, _Alloc>::
size_type pos = 0,
588 typename std::basic_string<_CharT, _Traits, _Alloc>::
size_type n =
589 std::basic_string<_CharT, _Traits, _Alloc>::
npos,
590 _CharT zero = _CharT('0'),
591 _CharT one = _CharT('1'),
619 template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
622 typename std::basic_string<_CharT>::
size_type pos = 0,
623 typename std::basic_string<_CharT>::
size_type n = std::basic_string<_CharT>::
npos,
624 _CharT zero = _CharT('0'),
625 _CharT one = _CharT('1'),
664 constexpr
void clear();
733 template<typename BlockInputIterator>
734 constexpr
void append(BlockInputIterator first, BlockInputIterator last);
902 [[nodiscard]] constexpr
dynamic_bitset<Block, Allocator> operator~() const;
1095 [[nodiscard]] constexpr
bool all() const;
1110 [[nodiscard]] constexpr
bool any() const;
1125 [[nodiscard]] constexpr
bool none() const;
1210 [[nodiscard]] constexpr
bool empty() const noexcept;
1422 template<typename _CharT =
char,
1423 typename _Traits = std::char_traits<_CharT>,
1424 typename _Alloc = std::allocator<_CharT>>
1425 [[nodiscard]] constexpr std::basic_string<_CharT, _Traits, _Alloc>
to_string(
1426 _CharT zero = _CharT('0'),
1427 _CharT one = _CharT('1')) const;
1444 [[nodiscard]] constexpr
unsigned long to_ulong() const;
1461 [[nodiscard]] constexpr
unsigned long long to_ullong() const;
1490 template<typename Function, typename... Parameters>
1491 constexpr
void iterate_bits_on(Function&& function, Parameters&&... parameters) const;
1580 template<typename Block_, typename Allocator_>
1581 friend constexpr
bool operator==(const
dynamic_bitset<Block_, Allocator_>& lhs,
1630 template<typename Block_, typename Allocator_>
1631 friend constexpr
bool operator<(const
dynamic_bitset<Block_, Allocator_>& lhs,
1635 template<typename T>
1636 struct dependent_false : public std::false_type
1640 std::vector<Block, Allocator> m_blocks;
1655 static constexpr void set_block_bits(
block_type& block,
1658 bool val =
true) noexcept;
1659 static constexpr
void flip_block_bits(
block_type& block,
1668 template<typename _CharT, typename _Traits>
1669 constexpr
void init_from_string(std::basic_string_view<_CharT, _Traits> str,
1670 typename std::basic_string_view<_CharT, _Traits>::
size_type pos,
1671 typename std::basic_string_view<_CharT, _Traits>::
size_type n,
1681 constexpr
size_type extra_bits_number() const noexcept;
1683 constexpr
size_type unused_bits_number() const noexcept;
1685 template<typename BinaryOperation>
1686 constexpr
void apply(const
dynamic_bitset<Block, Allocator>& other, BinaryOperation binary_op);
1687 template<typename UnaryOperation>
1688 constexpr
void apply(UnaryOperation unary_op);
1689 constexpr
void apply_left_shift(
size_type shift);
1690 constexpr
void apply_right_shift(
size_type shift);
1693 constexpr
void sanitize();
1696 constexpr
bool check_unused_bits() const noexcept;
1697 constexpr
bool check_size() const noexcept;
1698 constexpr
bool check_consistency() const noexcept;
1703template<typename integral_type, typename = std::enable_if_t<std::is_integral_v<integral_type>>>
1733template<typename Block, typename Allocator>
1734constexpr
bool operator!=(const
dynamic_bitset<Block, Allocator>& lhs,
1761template<typename Block, typename Allocator>
1762constexpr
bool operator<=(const
dynamic_bitset<Block, Allocator>& lhs,
1790template<typename Block, typename Allocator>
1791constexpr
bool operator>(const
dynamic_bitset<Block, Allocator>& lhs,
1819template<typename Block, typename Allocator>
1820constexpr
bool operator>=(const
dynamic_bitset<Block, Allocator>& lhs,
1852template<typename Block, typename Allocator>
1885template<typename Block, typename Allocator>
1918template<typename Block, typename Allocator>
1951template<typename Block, typename Allocator>
1980template<typename _CharT, typename _Traits, typename Block, typename Allocator>
1981constexpr std::basic_ostream<_CharT, _Traits>& operator<<(
1982 std::basic_ostream<_CharT, _Traits>& os,
2013template<typename _CharT, typename _Traits, typename Block, typename Allocator>
2014constexpr std::basic_istream<_CharT, _Traits>& operator>>(std::basic_istream<_CharT, _Traits>& is,
2038template<typename Block, typename Allocator>
2046template<typename Block, typename Allocator>
2050 : m_block(bitset.get_block(bit_pos)), m_mask(
dynamic_bitset<Block, Allocator>::bit_mask(bit_pos))
2054template<
typename Block,
typename Allocator>
2062template<
typename Block,
typename Allocator>
2070template<
typename Block,
typename Allocator>
2078template<
typename Block,
typename Allocator>
2089template<
typename Block,
typename Allocator>
2100template<
typename Block,
typename Allocator>
2111template<
typename Block,
typename Allocator>
2122template<
typename Block,
typename Allocator>
2125 return (m_block & m_mask) == zero_block;
2128template<
typename Block,
typename Allocator>
2131 return (m_block & m_mask) != zero_block;
2134template<
typename Block,
typename Allocator>
2142template<
typename Block,
typename Allocator>
2150template<
typename Block,
typename Allocator>
2158template<
typename Block,
typename Allocator>
2177template<
typename Block,
typename Allocator>
2179 : m_blocks(allocator), m_bits_number(0)
2183template<
typename Block,
typename Allocator>
2185 unsigned long long init_val,
2187 : m_blocks(blocks_required(nbits), allocator), m_bits_number(nbits)
2189 if(nbits == 0 || init_val == 0)
2194 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
2195 constexpr size_t init_val_required_blocks = ull_bits_number /
bits_per_block;
2196 if constexpr(init_val_required_blocks == 1)
2198 m_blocks[0] = init_val;
2202 const unsigned long long block_mask =
static_cast<unsigned long long>(one_block);
2203 const size_t blocks_to_init = std::min(m_blocks.size(), init_val_required_blocks);
2204 for(
size_t i = 0; i < blocks_to_init; ++i)
2212template<
typename Block,
typename Allocator>
2214 std::initializer_list<block_type> init_vals,
2216 : m_blocks(allocator), m_bits_number(0)
2221template<
typename Block,
typename Allocator>
2222template<
typename _CharT,
typename _Traits>
2224 std::basic_string_view<_CharT, _Traits> str,
2225 typename std::basic_string_view<_CharT, _Traits>::size_type pos,
2226 typename std::basic_string_view<_CharT, _Traits>::size_type n,
2230 : m_blocks(allocator), m_bits_number(0)
2232 assert(pos < str.size());
2233 init_from_string(str, pos, n, zero, one);
2236template<
typename Block,
typename Allocator>
2237template<
typename _CharT,
typename _Traits,
typename _Alloc>
2239 const std::basic_string<_CharT, _Traits, _Alloc>& str,
2240 typename std::basic_string<_CharT, _Traits, _Alloc>::size_type pos,
2241 typename std::basic_string<_CharT, _Traits, _Alloc>::size_type n,
2245 : m_blocks(allocator), m_bits_number(0)
2247 assert(pos < str.size());
2248 init_from_string(std::basic_string_view<_CharT, _Traits>(str), pos, n, zero, one);
2251template<
typename Block,
typename Allocator>
2252template<
typename _CharT,
typename _Traits>
2255 typename std::basic_string<_CharT>::size_type pos,
2256 typename std::basic_string<_CharT>::size_type n,
2260 : m_blocks(allocator), m_bits_number(0)
2262 init_from_string(std::basic_string_view<_CharT, _Traits>(str), pos, n, zero, one);
2265template<
typename Block,
typename Allocator>
2268 if(nbits == m_bits_number)
2273 const size_type old_num_blocks = num_blocks();
2274 const size_type new_num_blocks = blocks_required(nbits);
2276 const block_type init_value = value ? one_block : zero_block;
2277 if(new_num_blocks != old_num_blocks)
2279 m_blocks.resize(new_num_blocks, init_value);
2282 if(value && nbits > m_bits_number && old_num_blocks > 0)
2285 const size_type extra_bits = extra_bits_number();
2288 m_blocks[old_num_blocks - 1] |=
static_cast<block_type>(init_value << extra_bits);
2292 m_bits_number = nbits;
2294 assert(check_consistency());
2297template<
typename Block,
typename Allocator>
2304template<
typename Block,
typename Allocator>
2307 const size_type new_last_bit = m_bits_number++;
2308 if(m_bits_number <= m_blocks.size() * bits_per_block)
2312 set(new_last_bit, value);
2319 assert(
operator[](new_last_bit) == value);
2320 assert(check_consistency());
2323template<
typename Block,
typename Allocator>
2332 if(m_blocks.size() > blocks_required(m_bits_number))
2334 m_blocks.pop_back();
2336 assert(extra_bits_number() == 0);
2342 assert(check_consistency());
2345template<
typename Block,
typename Allocator>
2348 const size_type extra_bits = extra_bits_number();
2351 m_blocks.push_back(block);
2355 last_block() |=
static_cast<block_type>(block << extra_bits);
2356 m_blocks.push_back(
block_type(block >> (bits_per_block - extra_bits)));
2359 m_bits_number += bits_per_block;
2360 assert(check_consistency());
2363template<
typename Block,
typename Allocator>
2366 if(blocks.size() == 0)
2371 append(std::cbegin(blocks), std::cend(blocks));
2374template<
typename Block,
typename Allocator>
2375template<
typename BlockInputIterator>
2377 BlockInputIterator last)
2385 if constexpr(std::is_same_v<
2386 typename std::iterator_traits<BlockInputIterator>::iterator_category,
2387 std::random_access_iterator_tag>)
2389 assert(std::distance(first, last) > 0);
2390 m_blocks.reserve(m_blocks.size() +
static_cast<size_type>(std::distance(first, last)));
2393 const size_type extra_bits = extra_bits_number();
2394 const size_type unused_bits = unused_bits_number();
2397 auto pos = m_blocks.insert(std::end(m_blocks), first, last);
2398 assert(std::distance(pos, std::end(m_blocks)) > 0);
2400 static_cast<size_type>(std::distance(pos, std::end(m_blocks))) * bits_per_block;
2404 last_block() |=
static_cast<block_type>(*first << extra_bits);
2407 while(first != last)
2409 block |=
static_cast<block_type>(*first << extra_bits);
2410 m_blocks.push_back(block);
2411 m_bits_number += bits_per_block;
2415 m_blocks.push_back(block);
2416 m_bits_number += bits_per_block;
2419 assert(check_consistency());
2421template<
typename Block,
typename Allocator>
2425 assert(size() == rhs.
size());
2427 for(
size_type i = 0; i < m_blocks.size(); ++i)
2429 m_blocks[i] &= rhs.m_blocks[i];
2434template<
typename Block,
typename Allocator>
2438 assert(size() == rhs.
size());
2440 for(
size_type i = 0; i < m_blocks.size(); ++i)
2442 m_blocks[i] |= rhs.m_blocks[i];
2447template<
typename Block,
typename Allocator>
2451 assert(size() == rhs.
size());
2453 for(
size_type i = 0; i < m_blocks.size(); ++i)
2455 m_blocks[i] ^= rhs.m_blocks[i];
2460template<
typename Block,
typename Allocator>
2464 assert(size() == rhs.
size());
2466 for(
size_type i = 0; i < m_blocks.size(); ++i)
2468 m_blocks[i] &=
static_cast<block_type>(~rhs.m_blocks[i]);
2473template<
typename Block,
typename Allocator>
2479 if(shift >= m_bits_number)
2485 apply_left_shift(shift);
2492template<
typename Block,
typename Allocator>
2498 if(shift >= m_bits_number)
2504 apply_right_shift(shift);
2510template<
typename Block,
typename Allocator>
2517template<
typename Block,
typename Allocator>
2524template<
typename Block,
typename Allocator>
2532template<
typename Block,
typename Allocator>
2580template<
typename Block,
typename Allocator>
2588 m_blocks[block_index(
pos)] |= bit_mask(
pos);
2598template<
typename Block,
typename Allocator>
2601 std::fill(std::begin(m_blocks), std::end(m_blocks), one_block);
2606template<
typename Block,
typename Allocator>
2613template<
typename Block,
typename Allocator>
2619template<
typename Block,
typename Allocator>
2622 std::fill(std::begin(m_blocks), std::end(m_blocks), zero_block);
2626template<
typename Block,
typename Allocator>
2672template<
typename Block,
typename Allocator>
2676 m_blocks[block_index(
pos)] ^= bit_mask(
pos);
2680template<
typename Block,
typename Allocator>
2684 std::cbegin(m_blocks), std::cend(m_blocks), std::begin(m_blocks), std::bit_not<block_type>());
2689template<
typename Block,
typename Allocator>
2693 return (m_blocks[block_index(
pos)] & bit_mask(
pos)) != zero_block;
2696template<
typename Block,
typename Allocator>
2707template<
typename Block,
typename Allocator>
2716 if(extra_bits_number() == 0)
2735 if(last_block() != (
full_block >> unused_bits_number()))
2743template<
typename Block,
typename Allocator>
2748 if(
block != zero_block)
2756template<
typename Block,
typename Allocator>
2762template<
typename Block,
typename Allocator>
2772#if DYNAMIC_BITSET_CAN_USE_LIBPOPCNT
2781 count += block_count(m_blocks[
i]);
2789 count += block_count(
block);
2799template<
typename Block,
typename Allocator>
2807template<
typename Block,
typename Allocator>
2815template<
typename Block,
typename Allocator>
2820 return m_bits_number;
2823template<
typename Block,
typename Allocator>
2827 return m_blocks.
size();
2830template<
typename Block,
typename Allocator>
2836template<
typename Block,
typename Allocator>
2841 return m_blocks.
capacity() * bits_per_block;
2844template<
typename Block,
typename Allocator>
2850template<
typename Block,
typename Allocator>
2856template<
typename Block,
typename Allocator>
2863 if((m_blocks[
i] & ~
bitset.m_blocks[
i]) != zero_block)
2871template<
typename Block,
typename Allocator>
2894template<
typename Block,
typename Allocator>
2901 if((m_blocks[
i] &
bitset.m_blocks[
i]) != zero_block)
2909template<
typename Block,
typename Allocator>
2915 if(m_blocks[
i] != zero_block)
2923template<
typename Block,
typename Allocator>
2945 if(m_blocks[
i] != zero_block)
2954template<
typename Block,
typename Allocator>
2957 std::swap(m_blocks,
other.m_blocks);
2958 std::swap(m_bits_number,
other.m_bits_number);
2961template<
typename Block,
typename Allocator>
2969template<
typename Block,
typename Allocator>
2970template<
typename _CharT,
typename _Traits,
typename _Alloc>
2976 std::basic_string<_CharT, _Traits, _Alloc>
str(
len,
zero);
2979 if(m_blocks[
i_block] == zero_block)
2999template<
typename Block,
typename Allocator>
3002 if(m_bits_number == 0)
3007 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3010 throw std::overflow_error(
"sul::dynamic_bitset::to_ulong");
3013 unsigned long result = 0;
3023template<
typename Block,
typename Allocator>
3026 if(m_bits_number == 0)
3031 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
3034 throw std::overflow_error(
"sul::dynamic_bitset::to_ullong");
3037 unsigned long long result = 0;
3048template<
typename Block,
typename Allocator>
3055 static_assert(dependent_false<Function>::value,
"Function take invalid arguments");
3085 static_assert(dependent_false<Function>::value,
"Function have invalid return type");
3090template<
typename Block,
typename Allocator>
3094 return m_blocks.
data();
3097template<
typename Block,
typename Allocator>
3102 return m_blocks.
data();
3105template<
typename Block_,
typename Allocator_>
3109 return (
lhs.m_bits_number ==
rhs.m_bits_number) && (
lhs.m_blocks ==
rhs.m_blocks);
3112template<
typename Block_,
typename Allocator_>
3133 if(
lhs.m_blocks[
i] !=
rhs.m_blocks[
i])
3135 return lhs.m_blocks[
i] <
rhs.m_blocks[
i];
3138 return lhs.m_blocks[0] <
rhs.m_blocks[0];
3165 if(
lhs.m_blocks[
i] !=
rhs.m_blocks[
i])
3167 return lhs.m_blocks[
i] <
rhs.m_blocks[
i];
3170 if(
lhs.m_blocks[0] !=
rhs.m_blocks[0])
3172 return lhs.m_blocks[0] <
rhs.m_blocks[0];
3181template<
typename Block,
typename Allocator>
3185 return nbits / bits_per_block +
static_cast<size_type
>(
nbits % bits_per_block > 0);
3188template<
typename Block,
typename Allocator>
3192 return pos / bits_per_block;
3195template<
typename Block,
typename Allocator>
3199 return pos % bits_per_block;
3202template<
typename Block,
typename Allocator>
3206 return block_type(block_type(1) << bit_index(pos));
3209template<
typename Block,
typename Allocator>
3211 bit_mask(size_type first, size_type last)
noexcept
3213 first = bit_index(first);
3214 last = bit_index(last);
3215 if(last == (block_last_bit_index))
3217 return block_type(one_block << first);
3221 return block_type(((block_type(1) << (last + 1)) - 1) ^ ((block_type(1) << first) - 1));
3225template<
typename Block,
typename Allocator>
3226constexpr void dynamic_bitset<Block, Allocator>::set_block_bits(block_type& block,
3233 block |= bit_mask(first, last);
3237 block &=
static_cast<block_type
>(~bit_mask(first, last));
3241template<
typename Block,
typename Allocator>
3242constexpr void dynamic_bitset<Block, Allocator>::flip_block_bits(block_type& block,
3244 size_type last)
noexcept
3246 block ^= bit_mask(first, last);
3249template<
typename Block,
typename Allocator>
3253#if DYNAMIC_BITSET_CAN_USE_STD_BITOPS
3254 return static_cast<size_type
>(std::popcount(block));
3256 if(block == zero_block)
3261# if DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN || DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_POPCOUNT
3262 constexpr size_t u_bits_number = std::numeric_limits<unsigned>::digits;
3263 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3264 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
3265 if constexpr(bits_per_block <= u_bits_number)
3267 return static_cast<size_type
>(__builtin_popcount(
static_cast<unsigned int>(block)));
3269 else if constexpr(bits_per_block <= ul_bits_number)
3271 return static_cast<size_type
>(__builtin_popcountl(
static_cast<unsigned long>(block)));
3273 else if constexpr(bits_per_block <= ull_bits_number)
3275 return static_cast<size_type
>(__builtin_popcountll(
static_cast<unsigned long long>(block)));
3279 size_type count = 0;
3280 block_type mask = 1;
3281 for(size_type bit_index = 0; bit_index < bits_per_block; ++bit_index)
3283 count +=
static_cast<size_type
>((block & mask) != zero_block);
3285 mask =
static_cast<block_type
>(mask << 1);
3291template<
typename Block,
typename Allocator>
3293 block_count(
const block_type& block, size_type nbits)
noexcept
3295 assert(nbits <= bits_per_block);
3296#if DYNAMIC_BITSET_CAN_USE_STD_BITOPS
3297 const block_type shifted_block = block_type(block << (bits_per_block - nbits));
3298 return static_cast<size_type
>(std::popcount(shifted_block));
3300 const block_type shifted_block = block_type(block << (bits_per_block - nbits));
3301 if(shifted_block == zero_block)
3306# if DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN || DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_POPCOUNT
3307 constexpr size_t u_bits_number = std::numeric_limits<unsigned>::digits;
3308 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3309 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
3310 if constexpr(bits_per_block <= u_bits_number)
3312 return static_cast<size_type
>(__builtin_popcount(
static_cast<unsigned int>(shifted_block)));
3314 else if constexpr(bits_per_block <= ul_bits_number)
3316 return static_cast<size_type
>(
3317 __builtin_popcountl(
static_cast<unsigned long>(shifted_block)));
3319 else if constexpr(bits_per_block <= ull_bits_number)
3321 return static_cast<size_type
>(
3322 __builtin_popcountll(
static_cast<unsigned long long>(shifted_block)));
3326 size_type count = 0;
3327 block_type mask = 1;
3328 for(size_type bit_index = 0; bit_index < nbits; ++bit_index)
3330 count +=
static_cast<size_type
>((block & mask) != zero_block);
3332 mask =
static_cast<block_type
>(mask << 1);
3339template<
typename Block,
typename Allocator>
3343 assert(block != zero_block);
3344#if DYNAMIC_BITSET_CAN_USE_STD_BITOPS
3345 return static_cast<size_type
>(std::countr_zero(block));
3347# if DYNAMIC_BITSET_CAN_USE_GCC_BUILTIN || DYNAMIC_BITSET_CAN_USE_CLANG_BUILTIN_CTZ
3348 constexpr size_t u_bits_number = std::numeric_limits<unsigned>::digits;
3349 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3350 constexpr size_t ull_bits_number = std::numeric_limits<unsigned long long>::digits;
3351 if constexpr(bits_per_block <= u_bits_number)
3353 return static_cast<size_type
>(__builtin_ctz(
static_cast<unsigned int>(block)));
3355 else if constexpr(bits_per_block <= ul_bits_number)
3357 return static_cast<size_type
>(__builtin_ctzl(
static_cast<unsigned long>(block)));
3359 else if constexpr(bits_per_block <= ull_bits_number)
3361 return static_cast<size_type
>(__builtin_ctzll(
static_cast<unsigned long long>(block)));
3364# elif DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD
3365 constexpr size_t ul_bits_number = std::numeric_limits<unsigned long>::digits;
3366 constexpr size_t ui64_bits_number = std::numeric_limits<unsigned __int64>::digits;
3367 if constexpr(bits_per_block <= ul_bits_number)
3369 unsigned long index = std::numeric_limits<unsigned long>::max();
3370 _BitScanForward(&index,
static_cast<unsigned long>(block));
3371 return static_cast<size_type
>(index);
3373 else if constexpr(bits_per_block <= ui64_bits_number)
3375# if DYNAMIC_BITSET_CAN_USE_MSVC_BUILTIN_BITSCANFORWARD64
3376 unsigned long index = std::numeric_limits<unsigned long>::max();
3377 _BitScanForward64(&index,
static_cast<unsigned __int64
>(block));
3378 return static_cast<size_type
>(index);
3380 constexpr unsigned long max_ul = std::numeric_limits<unsigned long>::max();
3381 unsigned long low = block & max_ul;
3384 unsigned long index = std::numeric_limits<unsigned long>::max();
3385 _BitScanForward(&index, low);
3386 return static_cast<size_type
>(index);
3388 unsigned long high = block >> ul_bits_number;
3389 unsigned long index = std::numeric_limits<unsigned long>::max();
3390 _BitScanForward(&index, high);
3391 return static_cast<size_type
>(ul_bits_number + index);
3396 block_type mask = block_type(1);
3397 for(size_type i = 0; i < bits_per_block; ++i)
3399 if((block & mask) != zero_block)
3404 mask =
static_cast<block_type
>(mask << 1);
3411template<
typename Block,
typename Allocator>
3412template<
typename _CharT,
typename _Traits>
3413constexpr void dynamic_bitset<Block, Allocator>::init_from_string(
3414 std::basic_string_view<_CharT, _Traits> str,
3415 typename std::basic_string_view<_CharT, _Traits>::size_type pos,
3416 typename std::basic_string_view<_CharT, _Traits>::size_type n,
3417 [[maybe_unused]] _CharT zero,
3423 m_bits_number =
size;
3427 for(
size_t i = 0;
i <
size; ++
i)
3438template<
typename Block,
typename Allocator>
3442 return m_blocks[block_index(
pos)];
3445template<
typename Block,
typename Allocator>
3448 Allocator>::get_block(size_type pos)
const
3450 return m_blocks[block_index(pos)];
3453template<
typename Block,
typename Allocator>
3457 return m_blocks[m_blocks.size() - 1];
3460template<
typename Block,
typename Allocator>
3464 return m_blocks[m_blocks.size() - 1];
3467template<
typename Block,
typename Allocator>
3471 return bit_index(m_bits_number);
3474template<
typename Block,
typename Allocator>
3481template<
typename Block,
typename Allocator>
3482template<
typename BinaryOperation>
3483constexpr void dynamic_bitset<Block, Allocator>::apply(
3484 const dynamic_bitset<Block, Allocator>& other,
3485 BinaryOperation binary_op)
3488 std::transform(std::cbegin(m_blocks),
3489 std::cend(m_blocks),
3490 std::cbegin(
other.m_blocks),
3491 std::begin(m_blocks),
3495template<
typename Block,
typename Allocator>
3496template<
typename UnaryOperation>
3497constexpr void dynamic_bitset<Block, Allocator>::apply(UnaryOperation unary_op)
3499 std::transform(std::cbegin(m_blocks), std::cend(m_blocks), std::begin(m_blocks),
unary_op);
3502template<
typename Block,
typename Allocator>
3503constexpr void dynamic_bitset<Block, Allocator>::apply_left_shift(size_type shift)
3531 std::fill(std::begin(m_blocks),
3532 std::begin(m_blocks)
3537template<
typename Block,
typename Allocator>
3538constexpr void dynamic_bitset<Block, Allocator>::apply_right_shift(size_type shift)
3568 std::begin(m_blocks)
3574template<
typename Block,
typename Allocator>
3575constexpr void dynamic_bitset<Block, Allocator>::sanitize()
3584template<
typename Block,
typename Allocator>
3585constexpr bool dynamic_bitset<Block, Allocator>::check_unused_bits() const noexcept
3590 return (last_block() & (one_block <<
extra_bits)) == zero_block;
3595template<
typename Block,
typename Allocator>
3596constexpr bool dynamic_bitset<Block, Allocator>::check_size() const noexcept
3598 return blocks_required(
size()) == m_blocks.
size();
3601template<
typename Block,
typename Allocator>
3602constexpr bool dynamic_bitset<Block, Allocator>::check_consistency() const noexcept
3604 return check_unused_bits() && check_size();
3611template<
typename Block,
typename Allocator>
3618template<
typename Block,
typename Allocator>
3625template<
typename Block,
typename Allocator>
3632template<
typename Block,
typename Allocator>
3639template<
typename Block,
typename Allocator>
3647template<
typename Block,
typename Allocator>
3655template<
typename Block,
typename Allocator>
3663template<
typename Block,
typename Allocator>
3671template<
typename _CharT,
typename _Traits,
typename Block,
typename Allocator>
3673 std::basic_ostream<_CharT, _Traits>&
os,
3680template<
typename _CharT,
typename _Traits,
typename Block,
typename Allocator>
3681constexpr std::basic_istream<_CharT, _Traits>&
operator>>(std::basic_istream<_CharT, _Traits>&
is,
3687 typename std::basic_istream<_CharT, _Traits>::sentry
s(
is);
3729template<
typename Block,
typename Allocator>
3736#ifndef DYNAMIC_BITSET_NO_NAMESPACE
Reference to a sul::dynamic_bitset bit.
Definition dynamic_bitset.hpp:222
constexpr reference & reset()
Reset the referenced bit to false.
Definition dynamic_bitset.hpp:2144
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:2113
constexpr reference & assign(bool v)
Assign the value v to the referenced bit.
Definition dynamic_bitset.hpp:2160
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:2047
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:2091
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:2080
constexpr bool operator~() const
Return the result of applying unary NOT operator.
Definition dynamic_bitset.hpp:2123
constexpr reference & operator=(bool v)
Assign a value to the referenced bit.
Definition dynamic_bitset.hpp:2056
constexpr reference & flip()
Flip the referenced bit.
Definition dynamic_bitset.hpp:2152
constexpr reference & set()
Set the referenced bit to true.
Definition dynamic_bitset.hpp:2136
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:2102
Dynamic bitset.
Definition dynamic_bitset.hpp:172
constexpr dynamic_bitset< Block, Allocator > & operator<<=(size_type shift)
Performs binary shift left of shift bits.
Definition dynamic_bitset.hpp:2474
constexpr size_type size() const noexcept
Give the number of bits of the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2817
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:2448
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:2305
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:2697
constexpr dynamic_bitset< Block, Allocator > & set()
Set all the bits of the sul::dynamic_bitset to true.
Definition dynamic_bitset.hpp:2599
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:3050
constexpr bool empty() const noexcept
Checks if the sul::dynamic_bitset is empty.
Definition dynamic_bitset.hpp:2831
Block block_type
Same type as Block.
Definition dynamic_bitset.hpp:188
constexpr bool any() const
Checks if any bits are set to true.
Definition dynamic_bitset.hpp:2744
constexpr dynamic_bitset< Block, Allocator > operator<<(size_type shift) const
Performs binary shift right of shift bits.
Definition dynamic_bitset.hpp:2511
constexpr void clear()
Clears the sul::dynamic_bitset, resize it to 0.
Definition dynamic_bitset.hpp:2298
constexpr size_type num_blocks() const noexcept
Give the number of blocks used by the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2825
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:2857
size_t size_type
Type used to represent the size of a sul::dynamic_bitset.
Definition dynamic_bitset.hpp:181
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:2971
constexpr bool all() const
Checks if all bits are set to true.
Definition dynamic_bitset.hpp:2708
constexpr dynamic_bitset< Block, Allocator > & reset()
Reset all the bits of the sul::dynamic_bitset to false.
Definition dynamic_bitset.hpp:2620
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:2422
Allocator allocator_type
Same type as Allocator.
Definition dynamic_bitset.hpp:195
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:2872
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:2461
constexpr void swap(dynamic_bitset< Block, Allocator > &other)
Exchanges the bits of this sul::dynamic_bitset with those of other.
Definition dynamic_bitset.hpp:2955
constexpr size_type count() const noexcept
Count the number of bits set to true.
Definition dynamic_bitset.hpp:2764
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:2838
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:2435
constexpr unsigned long to_ulong() const
Converts the contents of the bitset to an unsigned long integer.
Definition dynamic_bitset.hpp:3000
constexpr dynamic_bitset< Block, Allocator > & flip()
Flip all the bits of the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2681
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:2925
constexpr bool test(size_type pos) const
Test the value of the bit at position pos.
Definition dynamic_bitset.hpp:2690
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:2845
constexpr void shrink_to_fit()
Requests the removal of unused capacity.
Definition dynamic_bitset.hpp:2851
constexpr bool none() const
Checks if none of the bits are set to true.
Definition dynamic_bitset.hpp:2757
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:2911
static constexpr size_type bits_per_block
Number of bits that can be stored in a block.
Definition dynamic_bitset.hpp:202
constexpr bool intersects(const dynamic_bitset< Block, Allocator > &bitset) const
Determines if this sul::dynamic_bitset and bitset intersect.
Definition dynamic_bitset.hpp:2895
constexpr void append(block_type block)
Append a block of bits block at the end of the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2346
bool const_reference
Const reference to a sul::dynamic_bitset bit, type bool.
Definition dynamic_bitset.hpp:441
constexpr allocator_type get_allocator() const
Gets the associated allocator.
Definition dynamic_bitset.hpp:2964
constexpr block_type * data() noexcept
Return a pointer to the underlying array serving as blocks storage.
Definition dynamic_bitset.hpp:3092
constexpr reference operator[](size_type pos)
Accesses the bit at position pos.
Definition dynamic_bitset.hpp:2801
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:2627
static constexpr size_type npos
Maximum value of size_type, returned for invalid positions.
Definition dynamic_bitset.hpp:209
constexpr void pop_back()
Remove the last bit of the sul::dynamic_bitset.
Definition dynamic_bitset.hpp:2324
constexpr void resize(size_type nbits, bool value=false)
Resize the sul::dynamic_bitset to contain nbits bits.
Definition dynamic_bitset.hpp:2266
constexpr dynamic_bitset< Block, Allocator > operator~() const
Performs a unary NOT on all bits.
Definition dynamic_bitset.hpp:2525
constexpr unsigned long long to_ullong() const
Converts the contents of the bitset to an unsigned long long integer.
Definition dynamic_bitset.hpp:3024
constexpr dynamic_bitset< Block, Allocator > operator>>(size_type shift) const
Performs binary shift left of shift bits.
Definition dynamic_bitset.hpp:2518
constexpr dynamic_bitset< Block, Allocator > & operator>>=(size_type shift)
Performs binary shift right of shift bits.
Definition dynamic_bitset.hpp:2493
Simple Useful Libraries.
Definition dynamic_bitset.hpp:148
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:3633
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:3619
constexpr bool operator<(const dynamic_bitset< Block_, Allocator_ > &lhs, const dynamic_bitset< Block_, Allocator_ > &rhs)
Definition dynamic_bitset.hpp:3113
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:3626
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:3681
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:3648
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:3640
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:3664
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:3656
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:3672
constexpr void swap(dynamic_bitset< Block, Allocator > &bitset1, dynamic_bitset< Block, Allocator > &bitset2)
Exchange the content of bitset1 and bitset2.
Definition dynamic_bitset.hpp:3730
constexpr bool operator==(const dynamic_bitset< Block_, Allocator_ > &lhs, const dynamic_bitset< Block_, Allocator_ > &rhs)
Definition dynamic_bitset.hpp:3106
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:3612