Coverage Report

Created: 2026-04-29 19:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/util/bitset.h
Line
Count
Source
1
// Copyright (c) The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#ifndef BITCOIN_UTIL_BITSET_H
6
#define BITCOIN_UTIL_BITSET_H
7
8
#include <util/check.h>
9
#include <util/overflow.h>
10
11
#include <array>
12
#include <bit>
13
#include <cstdint>
14
#include <limits>
15
#include <type_traits>
16
17
/* This file provides data types similar to std::bitset, but adds the following functionality:
18
 *
19
 * - Efficient iteration over all set bits (compatible with range-based for loops).
20
 * - Efficient search for the first and last set bit (First() and Last()).
21
 * - Efficient set subtraction: (a - b) implements "a and not b".
22
 * - Efficient non-strict subset/superset testing: IsSubsetOf() and IsSupersetOf().
23
 * - Efficient set overlap testing: a.Overlaps(b)
24
 * - Efficient construction of set containing 0..N-1 (S::Fill).
25
 * - Efficient construction of a single set (S::Singleton).
26
 * - Construction from initializer lists.
27
 *
28
 * Other differences:
29
 * - BitSet<N> is a bitset that supports at least N elements, but may support more (Size() reports
30
 *   the actual number). Because the actual number is unpredictable, there are no operations that
31
 *   affect all positions (like std::bitset's operator~, flip(), or all()).
32
 * - Various other unimplemented features.
33
 */
34
35
namespace bitset_detail {
36
37
/** Count the number of bits set in an unsigned integer type. */
38
template<typename I>
39
unsigned inline constexpr PopCount(I v)
40
345M
{
41
345M
    static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
42
345M
    constexpr auto BITS = std::numeric_limits<I>::digits;
43
    // Algorithms from https://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation.
44
    // These seem to be faster than std::popcount when compiling for non-SSE4 on x86_64.
45
345M
    if constexpr (BITS <= 32) {
46
314M
        v -= (v >> 1) & 0x55555555;
47
314M
        v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
48
314M
        v = (v + (v >> 4)) & 0x0f0f0f0f;
49
314M
        if constexpr (BITS > 8) v += v >> 8;
50
314M
        if constexpr (BITS > 16) v += v >> 16;
51
314M
        return v & 0x3f;
52
314M
    } else {
53
30.6M
        static_assert(BITS <= 64);
54
30.6M
        v -= (v >> 1) & 0x5555555555555555;
55
30.6M
        v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333);
56
30.6M
        v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f;
57
30.6M
        return (v * uint64_t{0x0101010101010101}) >> 56;
58
30.6M
    }
59
345M
}
unsigned int bitset_detail::PopCount<unsigned long>(unsigned long)
Line
Count
Source
40
30.6M
{
41
30.6M
    static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
42
30.6M
    constexpr auto BITS = std::numeric_limits<I>::digits;
43
    // Algorithms from https://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation.
44
    // These seem to be faster than std::popcount when compiling for non-SSE4 on x86_64.
45
    if constexpr (BITS <= 32) {
46
        v -= (v >> 1) & 0x55555555;
47
        v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
48
        v = (v + (v >> 4)) & 0x0f0f0f0f;
49
        if constexpr (BITS > 8) v += v >> 8;
50
        if constexpr (BITS > 16) v += v >> 16;
51
        return v & 0x3f;
52
30.6M
    } else {
53
30.6M
        static_assert(BITS <= 64);
54
30.6M
        v -= (v >> 1) & 0x5555555555555555;
55
30.6M
        v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333);
56
30.6M
        v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f;
57
30.6M
        return (v * uint64_t{0x0101010101010101}) >> 56;
58
30.6M
    }
59
30.6M
}
unsigned int bitset_detail::PopCount<unsigned int>(unsigned int)
Line
Count
Source
40
62.8M
{
41
62.8M
    static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
42
62.8M
    constexpr auto BITS = std::numeric_limits<I>::digits;
43
    // Algorithms from https://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation.
44
    // These seem to be faster than std::popcount when compiling for non-SSE4 on x86_64.
45
62.8M
    if constexpr (BITS <= 32) {
46
62.8M
        v -= (v >> 1) & 0x55555555;
47
62.8M
        v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
48
62.8M
        v = (v + (v >> 4)) & 0x0f0f0f0f;
49
62.8M
        if constexpr (BITS > 8) v += v >> 8;
50
62.8M
        if constexpr (BITS > 16) v += v >> 16;
51
62.8M
        return v & 0x3f;
52
    } else {
53
        static_assert(BITS <= 64);
54
        v -= (v >> 1) & 0x5555555555555555;
55
        v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333);
56
        v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f;
57
        return (v * uint64_t{0x0101010101010101}) >> 56;
58
    }
59
62.8M
}
unsigned int bitset_detail::PopCount<unsigned char>(unsigned char)
Line
Count
Source
40
251M
{
41
251M
    static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
42
251M
    constexpr auto BITS = std::numeric_limits<I>::digits;
43
    // Algorithms from https://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation.
44
    // These seem to be faster than std::popcount when compiling for non-SSE4 on x86_64.
45
251M
    if constexpr (BITS <= 32) {
46
251M
        v -= (v >> 1) & 0x55555555;
47
251M
        v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
48
251M
        v = (v + (v >> 4)) & 0x0f0f0f0f;
49
        if constexpr (BITS > 8) v += v >> 8;
50
        if constexpr (BITS > 16) v += v >> 16;
51
251M
        return v & 0x3f;
52
    } else {
53
        static_assert(BITS <= 64);
54
        v -= (v >> 1) & 0x5555555555555555;
55
        v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333);
56
        v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f;
57
        return (v * uint64_t{0x0101010101010101}) >> 56;
58
    }
59
251M
}
60
61
/** A bitset implementation backed by a single integer of type I. */
62
template<typename I>
63
class IntBitSet
64
{
65
    // Only binary, unsigned, integer, types allowed.
66
    static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
67
    /** The maximum number of bits this bitset supports. */
68
    static constexpr unsigned MAX_SIZE = std::numeric_limits<I>::digits;
69
    /** Integer whose bits represent this bitset. */
70
    I m_val;
71
    /** Internal constructor with a given integer as contents. */
72
32.0M
    IntBitSet(I val) noexcept : m_val{val} {}
bitset_detail::IntBitSet<unsigned long>::IntBitSet(unsigned long)
Line
Count
Source
72
26.6M
    IntBitSet(I val) noexcept : m_val{val} {}
bitset_detail::IntBitSet<unsigned int>::IntBitSet(unsigned int)
Line
Count
Source
72
5.38M
    IntBitSet(I val) noexcept : m_val{val} {}
73
    /** Dummy type to return using end(). Only used for comparing with Iterator. */
74
    class IteratorEnd
75
    {
76
        friend class IntBitSet;
77
        constexpr IteratorEnd() = default;
78
    public:
79
        constexpr IteratorEnd(const IteratorEnd&) = default;
80
    };
81
    /** Iterator type returned by begin(), which efficiently iterates all 1 positions. */
82
    class Iterator
83
    {
84
        friend class IntBitSet;
85
        I m_val; /**< The original integer's remaining bits. */
86
        unsigned m_pos; /** Last reported 1 position (if m_pos != 0). */
87
65.6M
        constexpr Iterator(I val) noexcept : m_val(val), m_pos(0)
88
65.6M
        {
89
65.6M
            if (m_val != 0) m_pos = std::countr_zero(m_val);
90
65.6M
        }
bitset_detail::IntBitSet<unsigned long>::Iterator::Iterator(unsigned long)
Line
Count
Source
87
54.7M
        constexpr Iterator(I val) noexcept : m_val(val), m_pos(0)
88
54.7M
        {
89
54.7M
            if (m_val != 0) m_pos = std::countr_zero(m_val);
90
54.7M
        }
bitset_detail::IntBitSet<unsigned int>::Iterator::Iterator(unsigned int)
Line
Count
Source
87
10.9M
        constexpr Iterator(I val) noexcept : m_val(val), m_pos(0)
88
10.9M
        {
89
10.9M
            if (m_val != 0) m_pos = std::countr_zero(m_val);
90
10.9M
        }
91
    public:
92
        /** Do not allow external code to construct an Iterator. */
93
        Iterator() = delete;
94
        // Copying is allowed.
95
        constexpr Iterator(const Iterator&) noexcept = default;
96
        constexpr Iterator& operator=(const Iterator&) noexcept = default;
97
        /** Test whether we are done (can only compare with IteratorEnd). */
98
        constexpr friend bool operator==(const Iterator& a, const IteratorEnd&) noexcept
99
204M
        {
100
204M
            return a.m_val == 0;
101
204M
        }
bitset_detail::operator==(bitset_detail::IntBitSet<unsigned long>::Iterator const&, bitset_detail::IntBitSet<unsigned long>::IteratorEnd const&)
Line
Count
Source
99
172M
        {
100
172M
            return a.m_val == 0;
101
172M
        }
bitset_detail::operator==(bitset_detail::IntBitSet<unsigned int>::Iterator const&, bitset_detail::IntBitSet<unsigned int>::IteratorEnd const&)
Line
Count
Source
99
31.5M
        {
100
31.5M
            return a.m_val == 0;
101
31.5M
        }
102
        /** Progress to the next 1 bit (only if != IteratorEnd). */
103
        constexpr Iterator& operator++() noexcept
104
139M
        {
105
139M
            Assume(m_val != 0);
106
139M
            m_val &= m_val - I{1U};
107
139M
            if (m_val != 0) m_pos = std::countr_zero(m_val);
108
139M
            return *this;
109
139M
        }
bitset_detail::IntBitSet<unsigned long>::Iterator::operator++()
Line
Count
Source
104
118M
        {
105
118M
            Assume(m_val != 0);
106
118M
            m_val &= m_val - I{1U};
107
118M
            if (m_val != 0) m_pos = std::countr_zero(m_val);
108
118M
            return *this;
109
118M
        }
bitset_detail::IntBitSet<unsigned int>::Iterator::operator++()
Line
Count
Source
104
20.7M
        {
105
20.7M
            Assume(m_val != 0);
106
20.7M
            m_val &= m_val - I{1U};
107
20.7M
            if (m_val != 0) m_pos = std::countr_zero(m_val);
108
20.7M
            return *this;
109
20.7M
        }
110
        /** Get the current bit position (only if != IteratorEnd). */
111
        constexpr unsigned operator*() const noexcept
112
144M
        {
113
144M
            Assume(m_val != 0);
114
144M
            return m_pos;
115
144M
        }
bitset_detail::IntBitSet<unsigned long>::Iterator::operator*() const
Line
Count
Source
112
122M
        {
113
122M
            Assume(m_val != 0);
114
122M
            return m_pos;
115
122M
        }
bitset_detail::IntBitSet<unsigned int>::Iterator::operator*() const
Line
Count
Source
112
21.9M
        {
113
21.9M
            Assume(m_val != 0);
114
21.9M
            return m_pos;
115
21.9M
        }
116
    };
117
118
public:
119
    /** Construct an all-zero bitset. */
120
14.5M
    constexpr IntBitSet() noexcept : m_val{0} {}
bitset_detail::IntBitSet<unsigned int>::IntBitSet()
Line
Count
Source
120
3.11M
    constexpr IntBitSet() noexcept : m_val{0} {}
bitset_detail::IntBitSet<unsigned long>::IntBitSet()
Line
Count
Source
120
11.4M
    constexpr IntBitSet() noexcept : m_val{0} {}
121
    /** Copy construct a bitset. */
122
    constexpr IntBitSet(const IntBitSet&) noexcept = default;
123
    /** Construct from a list of values. */
124
11
    constexpr IntBitSet(std::initializer_list<unsigned> ilist) noexcept : m_val(0)
125
11
    {
126
14
        for (auto pos : ilist) Set(pos);
127
11
    }
128
    /** Copy assign a bitset. */
129
    constexpr IntBitSet& operator=(const IntBitSet&) noexcept = default;
130
    /** Assign from a list of positions (which will be made true, all others false). */
131
    constexpr IntBitSet& operator=(std::initializer_list<unsigned> ilist) noexcept
132
    {
133
        m_val = 0;
134
        for (auto pos : ilist) Set(pos);
135
        return *this;
136
    }
137
    /** Construct a bitset with the singleton i. */
138
    static constexpr IntBitSet Singleton(unsigned i) noexcept
139
4.79M
    {
140
4.79M
        Assume(i < MAX_SIZE);
141
4.79M
        return IntBitSet(I(1U) << i);
142
4.79M
    }
bitset_detail::IntBitSet<unsigned long>::Singleton(unsigned int)
Line
Count
Source
139
3.90M
    {
140
3.90M
        Assume(i < MAX_SIZE);
141
3.90M
        return IntBitSet(I(1U) << i);
142
3.90M
    }
bitset_detail::IntBitSet<unsigned int>::Singleton(unsigned int)
Line
Count
Source
139
882k
    {
140
882k
        Assume(i < MAX_SIZE);
141
882k
        return IntBitSet(I(1U) << i);
142
882k
    }
143
    /** Construct a bitset with bits 0..count-1 (inclusive) set to 1. */
144
    static constexpr IntBitSet Fill(unsigned count) noexcept
145
148k
    {
146
148k
        IntBitSet ret;
147
148k
        Assume(count <= MAX_SIZE);
148
148k
        if (count) ret.m_val = I(~I{0}) >> (MAX_SIZE - count);
149
148k
        return ret;
150
148k
    }
bitset_detail::IntBitSet<unsigned long>::Fill(unsigned int)
Line
Count
Source
145
119k
    {
146
119k
        IntBitSet ret;
147
119k
        Assume(count <= MAX_SIZE);
148
119k
        if (count) ret.m_val = I(~I{0}) >> (MAX_SIZE - count);
149
119k
        return ret;
150
119k
    }
bitset_detail::IntBitSet<unsigned int>::Fill(unsigned int)
Line
Count
Source
145
29.2k
    {
146
29.2k
        IntBitSet ret;
147
29.2k
        Assume(count <= MAX_SIZE);
148
29.2k
        if (count) ret.m_val = I(~I{0}) >> (MAX_SIZE - count);
149
29.2k
        return ret;
150
29.2k
    }
151
    /** Set a bit to 1. */
152
    constexpr void Set(unsigned pos) noexcept
153
19.2M
    {
154
19.2M
        Assume(pos < MAX_SIZE);
155
19.2M
        m_val |= I{1U} << pos;
156
19.2M
    }
bitset_detail::IntBitSet<unsigned int>::Set(unsigned int)
Line
Count
Source
153
3.33M
    {
154
3.33M
        Assume(pos < MAX_SIZE);
155
3.33M
        m_val |= I{1U} << pos;
156
3.33M
    }
bitset_detail::IntBitSet<unsigned long>::Set(unsigned int)
Line
Count
Source
153
15.8M
    {
154
15.8M
        Assume(pos < MAX_SIZE);
155
15.8M
        m_val |= I{1U} << pos;
156
15.8M
    }
157
    /** Set a bit to the specified value. */
158
    constexpr void Set(unsigned pos, bool val) noexcept
159
    {
160
        Assume(pos < MAX_SIZE);
161
        m_val = (m_val & ~I(I{1U} << pos)) | (I(val) << pos);
162
    }
163
    /** Set a bit to 0. */
164
    constexpr void Reset(unsigned pos) noexcept
165
5.97M
    {
166
5.97M
        Assume(pos < MAX_SIZE);
167
5.97M
        m_val &= ~I(I{1U} << pos);
168
5.97M
    }
bitset_detail::IntBitSet<unsigned long>::Reset(unsigned int)
Line
Count
Source
165
4.70M
    {
166
4.70M
        Assume(pos < MAX_SIZE);
167
4.70M
        m_val &= ~I(I{1U} << pos);
168
4.70M
    }
bitset_detail::IntBitSet<unsigned int>::Reset(unsigned int)
Line
Count
Source
165
1.27M
    {
166
1.27M
        Assume(pos < MAX_SIZE);
167
1.27M
        m_val &= ~I(I{1U} << pos);
168
1.27M
    }
169
    /** Retrieve a bit at the given position. */
170
    constexpr bool operator[](unsigned pos) const noexcept
171
65.9M
    {
172
65.9M
        Assume(pos < MAX_SIZE);
173
65.9M
        return (m_val >> pos) & 1U;
174
65.9M
    }
bitset_detail::IntBitSet<unsigned long>::operator[](unsigned int) const
Line
Count
Source
171
54.8M
    {
172
54.8M
        Assume(pos < MAX_SIZE);
173
54.8M
        return (m_val >> pos) & 1U;
174
54.8M
    }
bitset_detail::IntBitSet<unsigned int>::operator[](unsigned int) const
Line
Count
Source
171
11.0M
    {
172
11.0M
        Assume(pos < MAX_SIZE);
173
11.0M
        return (m_val >> pos) & 1U;
174
11.0M
    }
175
    /** Compute the number of 1 bits in the bitset. */
176
37.4M
    constexpr unsigned Count() const noexcept { return PopCount(m_val); }
bitset_detail::IntBitSet<unsigned long>::Count() const
Line
Count
Source
176
30.6M
    constexpr unsigned Count() const noexcept { return PopCount(m_val); }
bitset_detail::IntBitSet<unsigned int>::Count() const
Line
Count
Source
176
6.79M
    constexpr unsigned Count() const noexcept { return PopCount(m_val); }
177
    /** Return the number of bits that this object holds. */
178
109k
    static constexpr unsigned Size() noexcept { return MAX_SIZE; }
bitset_detail::IntBitSet<unsigned long>::Size()
Line
Count
Source
178
83.4k
    static constexpr unsigned Size() noexcept { return MAX_SIZE; }
bitset_detail::IntBitSet<unsigned int>::Size()
Line
Count
Source
178
25.6k
    static constexpr unsigned Size() noexcept { return MAX_SIZE; }
179
    /** Check if all bits are 0. */
180
14.2M
    constexpr bool None() const noexcept { return m_val == 0; }
bitset_detail::IntBitSet<unsigned long>::None() const
Line
Count
Source
180
12.0M
    constexpr bool None() const noexcept { return m_val == 0; }
bitset_detail::IntBitSet<unsigned int>::None() const
Line
Count
Source
180
2.21M
    constexpr bool None() const noexcept { return m_val == 0; }
181
    /** Check if any bits are 1. */
182
13.8M
    constexpr bool Any() const noexcept { return !None(); }
bitset_detail::IntBitSet<unsigned long>::Any() const
Line
Count
Source
182
11.6M
    constexpr bool Any() const noexcept { return !None(); }
bitset_detail::IntBitSet<unsigned int>::Any() const
Line
Count
Source
182
2.19M
    constexpr bool Any() const noexcept { return !None(); }
183
    /** Return an object that iterates over all 1 bits (++ and * only allowed when != end()). */
184
65.6M
    constexpr Iterator begin() const noexcept { return Iterator(m_val); }
bitset_detail::IntBitSet<unsigned long>::begin() const
Line
Count
Source
184
54.7M
    constexpr Iterator begin() const noexcept { return Iterator(m_val); }
bitset_detail::IntBitSet<unsigned int>::begin() const
Line
Count
Source
184
10.9M
    constexpr Iterator begin() const noexcept { return Iterator(m_val); }
185
    /** Return a dummy object to compare Iterators with. */
186
66.8M
    constexpr IteratorEnd end() const noexcept { return IteratorEnd(); }
bitset_detail::IntBitSet<unsigned long>::end() const
Line
Count
Source
186
55.6M
    constexpr IteratorEnd end() const noexcept { return IteratorEnd(); }
bitset_detail::IntBitSet<unsigned int>::end() const
Line
Count
Source
186
11.2M
    constexpr IteratorEnd end() const noexcept { return IteratorEnd(); }
187
    /** Find the first element (requires Any()). */
188
    constexpr unsigned First() const noexcept
189
11.3M
    {
190
11.3M
        Assume(m_val != 0);
191
11.3M
        return std::countr_zero(m_val);
192
11.3M
    }
bitset_detail::IntBitSet<unsigned long>::First() const
Line
Count
Source
189
9.59M
    {
190
9.59M
        Assume(m_val != 0);
191
9.59M
        return std::countr_zero(m_val);
192
9.59M
    }
bitset_detail::IntBitSet<unsigned int>::First() const
Line
Count
Source
189
1.72M
    {
190
1.72M
        Assume(m_val != 0);
191
1.72M
        return std::countr_zero(m_val);
192
1.72M
    }
193
    /** Find the last element (requires Any()). */
194
    constexpr unsigned Last() const noexcept
195
1.07k
    {
196
1.07k
        Assume(m_val != 0);
197
1.07k
        return std::bit_width(m_val) - 1;
198
1.07k
    }
bitset_detail::IntBitSet<unsigned long>::Last() const
Line
Count
Source
195
681
    {
196
681
        Assume(m_val != 0);
197
681
        return std::bit_width(m_val) - 1;
198
681
    }
bitset_detail::IntBitSet<unsigned int>::Last() const
Line
Count
Source
195
393
    {
196
393
        Assume(m_val != 0);
197
393
        return std::bit_width(m_val) - 1;
198
393
    }
199
    /** Set this object's bits to be the binary AND between respective bits from this and a. */
200
38.6M
    constexpr IntBitSet& operator|=(const IntBitSet& a) noexcept { m_val |= a.m_val; return *this; }
bitset_detail::IntBitSet<unsigned long>::operator|=(bitset_detail::IntBitSet<unsigned long> const&)
Line
Count
Source
200
33.3M
    constexpr IntBitSet& operator|=(const IntBitSet& a) noexcept { m_val |= a.m_val; return *this; }
bitset_detail::IntBitSet<unsigned int>::operator|=(bitset_detail::IntBitSet<unsigned int> const&)
Line
Count
Source
200
5.29M
    constexpr IntBitSet& operator|=(const IntBitSet& a) noexcept { m_val |= a.m_val; return *this; }
201
    /** Set this object's bits to be the binary OR between respective bits from this and a. */
202
467k
    constexpr IntBitSet& operator&=(const IntBitSet& a) noexcept { m_val &= a.m_val; return *this; }
bitset_detail::IntBitSet<unsigned int>::operator&=(bitset_detail::IntBitSet<unsigned int> const&)
Line
Count
Source
202
58
    constexpr IntBitSet& operator&=(const IntBitSet& a) noexcept { m_val &= a.m_val; return *this; }
bitset_detail::IntBitSet<unsigned long>::operator&=(bitset_detail::IntBitSet<unsigned long> const&)
Line
Count
Source
202
467k
    constexpr IntBitSet& operator&=(const IntBitSet& a) noexcept { m_val &= a.m_val; return *this; }
203
    /** Set this object's bits to be the binary AND NOT between respective bits from this and a. */
204
26.6M
    constexpr IntBitSet& operator-=(const IntBitSet& a) noexcept { m_val &= ~a.m_val; return *this; }
bitset_detail::IntBitSet<unsigned long>::operator-=(bitset_detail::IntBitSet<unsigned long> const&)
Line
Count
Source
204
22.5M
    constexpr IntBitSet& operator-=(const IntBitSet& a) noexcept { m_val &= ~a.m_val; return *this; }
bitset_detail::IntBitSet<unsigned int>::operator-=(bitset_detail::IntBitSet<unsigned int> const&)
Line
Count
Source
204
4.12M
    constexpr IntBitSet& operator-=(const IntBitSet& a) noexcept { m_val &= ~a.m_val; return *this; }
205
    /** Set this object's bits to be the binary XOR between respective bits from this as a. */
206
    constexpr IntBitSet& operator^=(const IntBitSet& a) noexcept { m_val ^= a.m_val; return *this; }
207
    /** Check if the intersection between two sets is non-empty. */
208
13.2M
    constexpr bool Overlaps(const IntBitSet& a) const noexcept { return m_val & a.m_val; }
bitset_detail::IntBitSet<unsigned long>::Overlaps(bitset_detail::IntBitSet<unsigned long> const&) const
Line
Count
Source
208
11.1M
    constexpr bool Overlaps(const IntBitSet& a) const noexcept { return m_val & a.m_val; }
bitset_detail::IntBitSet<unsigned int>::Overlaps(bitset_detail::IntBitSet<unsigned int> const&) const
Line
Count
Source
208
2.12M
    constexpr bool Overlaps(const IntBitSet& a) const noexcept { return m_val & a.m_val; }
209
    /** Return an object with the binary AND between respective bits from a and b. */
210
20.9M
    friend constexpr IntBitSet operator&(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & b.m_val); }
bitset_detail::operator&(bitset_detail::IntBitSet<unsigned long> const&, bitset_detail::IntBitSet<unsigned long> const&)
Line
Count
Source
210
17.7M
    friend constexpr IntBitSet operator&(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & b.m_val); }
bitset_detail::operator&(bitset_detail::IntBitSet<unsigned int> const&, bitset_detail::IntBitSet<unsigned int> const&)
Line
Count
Source
210
3.25M
    friend constexpr IntBitSet operator&(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & b.m_val); }
211
    /** Return an object with the binary OR between respective bits from a and b. */
212
    friend constexpr IntBitSet operator|(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val | b.m_val); }
213
    /** Return an object with the binary AND NOT between respective bits from a and b. */
214
6.28M
    friend constexpr IntBitSet operator-(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & ~b.m_val); }
bitset_detail::operator-(bitset_detail::IntBitSet<unsigned long> const&, bitset_detail::IntBitSet<unsigned long> const&)
Line
Count
Source
214
5.03M
    friend constexpr IntBitSet operator-(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & ~b.m_val); }
bitset_detail::operator-(bitset_detail::IntBitSet<unsigned int> const&, bitset_detail::IntBitSet<unsigned int> const&)
Line
Count
Source
214
1.24M
    friend constexpr IntBitSet operator-(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val & ~b.m_val); }
215
    /** Return an object with the binary XOR between respective bits from a and b. */
216
    friend constexpr IntBitSet operator^(const IntBitSet& a, const IntBitSet& b) noexcept { return I(a.m_val ^ b.m_val); }
217
    /** Check if bitset a and bitset b are identical. */
218
2.70M
    friend constexpr bool operator==(const IntBitSet& a, const IntBitSet& b) noexcept = default;
bitset_detail::operator==(bitset_detail::IntBitSet<unsigned long> const&, bitset_detail::IntBitSet<unsigned long> const&)
Line
Count
Source
218
2.25M
    friend constexpr bool operator==(const IntBitSet& a, const IntBitSet& b) noexcept = default;
bitset_detail::operator==(bitset_detail::IntBitSet<unsigned int> const&, bitset_detail::IntBitSet<unsigned int> const&)
Line
Count
Source
218
447k
    friend constexpr bool operator==(const IntBitSet& a, const IntBitSet& b) noexcept = default;
219
    /** Check if bitset a is a superset of bitset b (= every 1 bit in b is also in a). */
220
288k
    constexpr bool IsSupersetOf(const IntBitSet& a) const noexcept { return (a.m_val & ~m_val) == 0; }
bitset_detail::IntBitSet<unsigned long>::IsSupersetOf(bitset_detail::IntBitSet<unsigned long> const&) const
Line
Count
Source
220
277k
    constexpr bool IsSupersetOf(const IntBitSet& a) const noexcept { return (a.m_val & ~m_val) == 0; }
bitset_detail::IntBitSet<unsigned int>::IsSupersetOf(bitset_detail::IntBitSet<unsigned int> const&) const
Line
Count
Source
220
10.2k
    constexpr bool IsSupersetOf(const IntBitSet& a) const noexcept { return (a.m_val & ~m_val) == 0; }
221
    /** Check if bitset a is a subset of bitset b (= every 1 bit in a is also in b). */
222
6.00M
    constexpr bool IsSubsetOf(const IntBitSet& a) const noexcept { return (m_val & ~a.m_val) == 0; }
bitset_detail::IntBitSet<unsigned long>::IsSubsetOf(bitset_detail::IntBitSet<unsigned long> const&) const
Line
Count
Source
222
5.27M
    constexpr bool IsSubsetOf(const IntBitSet& a) const noexcept { return (m_val & ~a.m_val) == 0; }
bitset_detail::IntBitSet<unsigned int>::IsSubsetOf(bitset_detail::IntBitSet<unsigned int> const&) const
Line
Count
Source
222
723k
    constexpr bool IsSubsetOf(const IntBitSet& a) const noexcept { return (m_val & ~a.m_val) == 0; }
223
    /** Swap two bitsets. */
224
    friend constexpr void swap(IntBitSet& a, IntBitSet& b) noexcept { std::swap(a.m_val, b.m_val); }
225
};
226
227
/** A bitset implementation backed by N integers of type I. */
228
template<typename I, unsigned N>
229
class MultiIntBitSet
230
{
231
    // Only binary, unsigned, integer, types allowed.
232
    static_assert(std::is_integral_v<I> && std::is_unsigned_v<I> && std::numeric_limits<I>::radix == 2);
233
    // Cannot be empty.
234
    static_assert(N > 0);
235
    /** The number of bits per integer. */
236
    static constexpr unsigned LIMB_BITS = std::numeric_limits<I>::digits;
237
    /** Number of elements this set type supports. */
238
    static constexpr unsigned MAX_SIZE = LIMB_BITS * N;
239
    // No overflow allowed here.
240
    static_assert(MAX_SIZE / LIMB_BITS == N);
241
    /** Array whose member integers store the bits of the set. */
242
    std::array<I, N> m_val;
243
    /** Dummy type to return using end(). Only used for comparing with Iterator. */
244
    class IteratorEnd
245
    {
246
        friend class MultiIntBitSet;
247
        constexpr IteratorEnd() = default;
248
    public:
249
        constexpr IteratorEnd(const IteratorEnd&) = default;
250
    };
251
    /** Iterator type returned by begin(), which efficiently iterates all 1 positions. */
252
    class Iterator
253
    {
254
        friend class MultiIntBitSet;
255
        const std::array<I, N>* m_ptr; /**< Pointer to array to fetch bits from. */
256
        I m_val; /**< The remaining bits of (*m_ptr)[m_idx]. */
257
        unsigned m_pos; /**< The last reported position. */
258
        unsigned m_idx; /**< The index in *m_ptr currently being iterated over. */
259
113M
        constexpr Iterator(const std::array<I, N>& ref) noexcept : m_ptr(&ref), m_idx(0)
260
113M
        {
261
352M
            do {
262
352M
                m_val = (*m_ptr)[m_idx];
263
352M
                if (m_val) {
264
67.1M
                    m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
265
67.1M
                    break;
266
67.1M
                }
267
285M
                ++m_idx;
268
285M
            } while(m_idx < N);
269
113M
        }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::Iterator::Iterator(std::array<unsigned int, 2ul> const&)
Line
Count
Source
259
51.2M
        constexpr Iterator(const std::array<I, N>& ref) noexcept : m_ptr(&ref), m_idx(0)
260
51.2M
        {
261
77.6M
            do {
262
77.6M
                m_val = (*m_ptr)[m_idx];
263
77.6M
                if (m_val) {
264
30.1M
                    m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
265
30.1M
                    break;
266
30.1M
                }
267
47.4M
                ++m_idx;
268
47.4M
            } while(m_idx < N);
269
51.2M
        }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Iterator::Iterator(std::array<unsigned char, 8ul> const&)
Line
Count
Source
259
51.2M
        constexpr Iterator(const std::array<I, N>& ref) noexcept : m_ptr(&ref), m_idx(0)
260
51.2M
        {
261
247M
            do {
262
247M
                m_val = (*m_ptr)[m_idx];
263
247M
                if (m_val) {
264
30.1M
                    m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
265
30.1M
                    break;
266
30.1M
                }
267
217M
                ++m_idx;
268
217M
            } while(m_idx < N);
269
51.2M
        }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Iterator::Iterator(std::array<unsigned char, 4ul> const&)
Line
Count
Source
259
10.9M
        constexpr Iterator(const std::array<I, N>& ref) noexcept : m_ptr(&ref), m_idx(0)
260
10.9M
        {
261
26.8M
            do {
262
26.8M
                m_val = (*m_ptr)[m_idx];
263
26.8M
                if (m_val) {
264
6.84M
                    m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
265
6.84M
                    break;
266
6.84M
                }
267
20.0M
                ++m_idx;
268
20.0M
            } while(m_idx < N);
269
10.9M
        }
270
271
    public:
272
        /** Do not allow external code to construct an Iterator. */
273
        Iterator() = delete;
274
        // Copying is allowed.
275
        constexpr Iterator(const Iterator&) noexcept = default;
276
        constexpr Iterator& operator=(const Iterator&) noexcept = default;
277
        /** Test whether we are done (can only compare with IteratorEnd). */
278
        friend constexpr bool operator==(const Iterator& a, const IteratorEnd&) noexcept
279
351M
        {
280
351M
            return a.m_idx == N;
281
351M
        }
bitset_detail::operator==(bitset_detail::MultiIntBitSet<unsigned int, 2u>::Iterator const&, bitset_detail::MultiIntBitSet<unsigned int, 2u>::IteratorEnd const&)
Line
Count
Source
279
160M
        {
280
160M
            return a.m_idx == N;
281
160M
        }
bitset_detail::operator==(bitset_detail::MultiIntBitSet<unsigned char, 8u>::Iterator const&, bitset_detail::MultiIntBitSet<unsigned char, 8u>::IteratorEnd const&)
Line
Count
Source
279
159M
        {
280
159M
            return a.m_idx == N;
281
159M
        }
bitset_detail::operator==(bitset_detail::MultiIntBitSet<unsigned char, 4u>::Iterator const&, bitset_detail::MultiIntBitSet<unsigned char, 4u>::IteratorEnd const&)
Line
Count
Source
279
31.5M
        {
280
31.5M
            return a.m_idx == N;
281
31.5M
        }
282
        /** Progress to the next 1 bit (only if != IteratorEnd). */
283
        constexpr Iterator& operator++() noexcept
284
238M
        {
285
238M
            Assume(m_idx < N);
286
238M
            m_val &= m_val - I{1U};
287
238M
            if (m_val == 0) {
288
244M
                while (true) {
289
244M
                    ++m_idx;
290
244M
                    if (m_idx == N) break;
291
184M
                    m_val = (*m_ptr)[m_idx];
292
184M
                    if (m_val) {
293
33.2M
                        m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
294
33.2M
                        break;
295
33.2M
                    }
296
184M
                }
297
145M
            } else {
298
145M
                m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
299
145M
            }
300
238M
            return *this;
301
238M
        }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::Iterator::operator++()
Line
Count
Source
284
109M
        {
285
109M
            Assume(m_idx < N);
286
109M
            m_val &= m_val - I{1U};
287
109M
            if (m_val == 0) {
288
49.6M
                while (true) {
289
49.6M
                    ++m_idx;
290
49.6M
                    if (m_idx == N) break;
291
22.4M
                    m_val = (*m_ptr)[m_idx];
292
22.4M
                    if (m_val) {
293
6.13M
                        m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
294
6.13M
                        break;
295
6.13M
                    }
296
22.4M
                }
297
76.3M
            } else {
298
76.3M
                m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
299
76.3M
            }
300
109M
            return *this;
301
109M
        }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Iterator::operator++()
Line
Count
Source
284
108M
        {
285
108M
            Assume(m_idx < N);
286
108M
            m_val &= m_val - I{1U};
287
108M
            if (m_val == 0) {
288
174M
                while (true) {
289
174M
                    ++m_idx;
290
174M
                    if (m_idx == N) break;
291
147M
                    m_val = (*m_ptr)[m_idx];
292
147M
                    if (m_val) {
293
24.2M
                        m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
294
24.2M
                        break;
295
24.2M
                    }
296
147M
                }
297
57.1M
            } else {
298
57.1M
                m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
299
57.1M
            }
300
108M
            return *this;
301
108M
        }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Iterator::operator++()
Line
Count
Source
284
20.7M
        {
285
20.7M
            Assume(m_idx < N);
286
20.7M
            m_val &= m_val - I{1U};
287
20.7M
            if (m_val == 0) {
288
20.9M
                while (true) {
289
20.9M
                    ++m_idx;
290
20.9M
                    if (m_idx == N) break;
291
15.0M
                    m_val = (*m_ptr)[m_idx];
292
15.0M
                    if (m_val) {
293
2.82M
                        m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
294
2.82M
                        break;
295
2.82M
                    }
296
15.0M
                }
297
11.9M
            } else {
298
11.9M
                m_pos = std::countr_zero(m_val) + m_idx * LIMB_BITS;
299
11.9M
            }
300
20.7M
            return *this;
301
20.7M
        }
302
        /** Get the current bit position (only if != IteratorEnd). */
303
        constexpr unsigned operator*() const noexcept
304
247M
        {
305
247M
            Assume(m_idx < N);
306
247M
            return m_pos;
307
247M
        }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::Iterator::operator*() const
Line
Count
Source
304
113M
        {
305
113M
            Assume(m_idx < N);
306
113M
            return m_pos;
307
113M
        }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Iterator::operator*() const
Line
Count
Source
304
112M
        {
305
112M
            Assume(m_idx < N);
306
112M
            return m_pos;
307
112M
        }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Iterator::operator*() const
Line
Count
Source
304
21.8M
        {
305
21.8M
            Assume(m_idx < N);
306
21.8M
            return m_pos;
307
21.8M
        }
308
    };
309
310
public:
311
    /** Construct an all-zero bitset. */
312
74.8M
    constexpr MultiIntBitSet() noexcept : m_val{} {}
bitset_detail::MultiIntBitSet<unsigned int, 2u>::MultiIntBitSet()
Line
Count
Source
312
33.1M
    constexpr MultiIntBitSet() noexcept : m_val{} {}
bitset_detail::MultiIntBitSet<unsigned char, 8u>::MultiIntBitSet()
Line
Count
Source
312
33.1M
    constexpr MultiIntBitSet() noexcept : m_val{} {}
bitset_detail::MultiIntBitSet<unsigned char, 4u>::MultiIntBitSet()
Line
Count
Source
312
8.53M
    constexpr MultiIntBitSet() noexcept : m_val{} {}
313
    /** Copy construct a bitset. */
314
    constexpr MultiIntBitSet(const MultiIntBitSet&) noexcept = default;
315
    /** Copy assign a bitset. */
316
    constexpr MultiIntBitSet& operator=(const MultiIntBitSet&) noexcept = default;
317
    /** Set a bit to 1. */
318
    void constexpr Set(unsigned pos) noexcept
319
32.6M
    {
320
32.6M
        Assume(pos < MAX_SIZE);
321
32.6M
        m_val[pos / LIMB_BITS] |= I{1U} << (pos % LIMB_BITS);
322
32.6M
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::Set(unsigned int)
Line
Count
Source
319
14.6M
    {
320
14.6M
        Assume(pos < MAX_SIZE);
321
14.6M
        m_val[pos / LIMB_BITS] |= I{1U} << (pos % LIMB_BITS);
322
14.6M
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Set(unsigned int)
Line
Count
Source
319
14.6M
    {
320
14.6M
        Assume(pos < MAX_SIZE);
321
14.6M
        m_val[pos / LIMB_BITS] |= I{1U} << (pos % LIMB_BITS);
322
14.6M
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Set(unsigned int)
Line
Count
Source
319
3.33M
    {
320
3.33M
        Assume(pos < MAX_SIZE);
321
3.33M
        m_val[pos / LIMB_BITS] |= I{1U} << (pos % LIMB_BITS);
322
3.33M
    }
323
    /** Set a bit to the specified value. */
324
    void constexpr Set(unsigned pos, bool val) noexcept
325
    {
326
        Assume(pos < MAX_SIZE);
327
        m_val[pos / LIMB_BITS] = (m_val[pos / LIMB_BITS] & ~I(I{1U} << (pos % LIMB_BITS))) |
328
                                 (I{val} << (pos % LIMB_BITS));
329
    }
330
    /** Construct a bitset from a list of values. */
331
    constexpr MultiIntBitSet(std::initializer_list<unsigned> ilist) noexcept : m_val{}
332
    {
333
        for (auto pos : ilist) Set(pos);
334
    }
335
    /** Set a bitset to a list of values. */
336
    constexpr MultiIntBitSet& operator=(std::initializer_list<unsigned> ilist) noexcept
337
    {
338
        m_val.fill(0);
339
        for (auto pos : ilist) Set(pos);
340
        return *this;
341
    }
342
    /** Set a bit to 0. */
343
    void constexpr Reset(unsigned pos) noexcept
344
10.1M
    {
345
10.1M
        Assume(pos < MAX_SIZE);
346
10.1M
        m_val[pos / LIMB_BITS] &= ~I(I{1U} << (pos % LIMB_BITS));
347
10.1M
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::Reset(unsigned int)
Line
Count
Source
344
4.43M
    {
345
4.43M
        Assume(pos < MAX_SIZE);
346
4.43M
        m_val[pos / LIMB_BITS] &= ~I(I{1U} << (pos % LIMB_BITS));
347
4.43M
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Reset(unsigned int)
Line
Count
Source
344
4.43M
    {
345
4.43M
        Assume(pos < MAX_SIZE);
346
4.43M
        m_val[pos / LIMB_BITS] &= ~I(I{1U} << (pos % LIMB_BITS));
347
4.43M
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Reset(unsigned int)
Line
Count
Source
344
1.27M
    {
345
1.27M
        Assume(pos < MAX_SIZE);
346
1.27M
        m_val[pos / LIMB_BITS] &= ~I(I{1U} << (pos % LIMB_BITS));
347
1.27M
    }
348
    /** Retrieve a bit at the given position. */
349
    bool constexpr operator[](unsigned pos) const noexcept
350
111M
    {
351
111M
        Assume(pos < MAX_SIZE);
352
111M
        return (m_val[pos / LIMB_BITS] >> (pos % LIMB_BITS)) & 1U;
353
111M
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::operator[](unsigned int) const
Line
Count
Source
350
50.6M
    {
351
50.6M
        Assume(pos < MAX_SIZE);
352
50.6M
        return (m_val[pos / LIMB_BITS] >> (pos % LIMB_BITS)) & 1U;
353
50.6M
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::operator[](unsigned int) const
Line
Count
Source
350
49.5M
    {
351
49.5M
        Assume(pos < MAX_SIZE);
352
49.5M
        return (m_val[pos / LIMB_BITS] >> (pos % LIMB_BITS)) & 1U;
353
49.5M
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::operator[](unsigned int) const
Line
Count
Source
350
10.9M
    {
351
10.9M
        Assume(pos < MAX_SIZE);
352
10.9M
        return (m_val[pos / LIMB_BITS] >> (pos % LIMB_BITS)) & 1U;
353
10.9M
    }
354
    /** Construct a bitset with the singleton pos. */
355
    static constexpr MultiIntBitSet Singleton(unsigned pos) noexcept
356
6.72M
    {
357
6.72M
        Assume(pos < MAX_SIZE);
358
6.72M
        MultiIntBitSet ret;
359
6.72M
        ret.m_val[pos / LIMB_BITS] = I{1U} << (pos % LIMB_BITS);
360
6.72M
        return ret;
361
6.72M
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::Singleton(unsigned int)
Line
Count
Source
356
2.92M
    {
357
2.92M
        Assume(pos < MAX_SIZE);
358
2.92M
        MultiIntBitSet ret;
359
2.92M
        ret.m_val[pos / LIMB_BITS] = I{1U} << (pos % LIMB_BITS);
360
2.92M
        return ret;
361
2.92M
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Singleton(unsigned int)
Line
Count
Source
356
2.92M
    {
357
2.92M
        Assume(pos < MAX_SIZE);
358
2.92M
        MultiIntBitSet ret;
359
2.92M
        ret.m_val[pos / LIMB_BITS] = I{1U} << (pos % LIMB_BITS);
360
2.92M
        return ret;
361
2.92M
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Singleton(unsigned int)
Line
Count
Source
356
882k
    {
357
882k
        Assume(pos < MAX_SIZE);
358
882k
        MultiIntBitSet ret;
359
882k
        ret.m_val[pos / LIMB_BITS] = I{1U} << (pos % LIMB_BITS);
360
882k
        return ret;
361
882k
    }
362
    /** Construct a bitset with bits 0..count-1 (inclusive) set to 1. */
363
    static constexpr MultiIntBitSet Fill(unsigned count) noexcept
364
147k
    {
365
147k
        Assume(count <= MAX_SIZE);
366
147k
        MultiIntBitSet ret;
367
147k
        if (count) {
368
146k
            unsigned i = 0;
369
379k
            while (count > LIMB_BITS) {
370
233k
                ret.m_val[i++] = I(~I{0});
371
233k
                count -= LIMB_BITS;
372
233k
            }
373
146k
            ret.m_val[i] = I(~I{0}) >> (LIMB_BITS - count);
374
146k
        }
375
147k
        return ret;
376
147k
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::Fill(unsigned int)
Line
Count
Source
364
59.2k
    {
365
59.2k
        Assume(count <= MAX_SIZE);
366
59.2k
        MultiIntBitSet ret;
367
59.2k
        if (count) {
368
58.8k
            unsigned i = 0;
369
82.1k
            while (count > LIMB_BITS) {
370
23.3k
                ret.m_val[i++] = I(~I{0});
371
23.3k
                count -= LIMB_BITS;
372
23.3k
            }
373
58.8k
            ret.m_val[i] = I(~I{0}) >> (LIMB_BITS - count);
374
58.8k
        }
375
59.2k
        return ret;
376
59.2k
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Fill(unsigned int)
Line
Count
Source
364
59.2k
    {
365
59.2k
        Assume(count <= MAX_SIZE);
366
59.2k
        MultiIntBitSet ret;
367
59.2k
        if (count) {
368
58.8k
            unsigned i = 0;
369
230k
            while (count > LIMB_BITS) {
370
171k
                ret.m_val[i++] = I(~I{0});
371
171k
                count -= LIMB_BITS;
372
171k
            }
373
58.8k
            ret.m_val[i] = I(~I{0}) >> (LIMB_BITS - count);
374
58.8k
        }
375
59.2k
        return ret;
376
59.2k
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Fill(unsigned int)
Line
Count
Source
364
29.2k
    {
365
29.2k
        Assume(count <= MAX_SIZE);
366
29.2k
        MultiIntBitSet ret;
367
29.2k
        if (count) {
368
28.9k
            unsigned i = 0;
369
67.2k
            while (count > LIMB_BITS) {
370
38.2k
                ret.m_val[i++] = I(~I{0});
371
38.2k
                count -= LIMB_BITS;
372
38.2k
            }
373
28.9k
            ret.m_val[i] = I(~I{0}) >> (LIMB_BITS - count);
374
28.9k
        }
375
29.2k
        return ret;
376
29.2k
    }
377
    /** Return the number of bits that this object holds. */
378
192k
    static constexpr unsigned Size() noexcept { return MAX_SIZE; }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::Size()
Line
Count
Source
378
83.4k
    static constexpr unsigned Size() noexcept { return MAX_SIZE; }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Size()
Line
Count
Source
378
83.4k
    static constexpr unsigned Size() noexcept { return MAX_SIZE; }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Size()
Line
Count
Source
378
25.3k
    static constexpr unsigned Size() noexcept { return MAX_SIZE; }
379
    /** Compute the number of 1 bits in the bitset. */
380
    unsigned constexpr Count() const noexcept
381
62.8M
    {
382
62.8M
        unsigned ret{0};
383
307M
        for (I v : m_val) ret += PopCount(v);
384
62.8M
        return ret;
385
62.8M
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::Count() const
Line
Count
Source
381
28.0M
    {
382
28.0M
        unsigned ret{0};
383
56.0M
        for (I v : m_val) ret += PopCount(v);
384
28.0M
        return ret;
385
28.0M
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Count() const
Line
Count
Source
381
28.0M
    {
382
28.0M
        unsigned ret{0};
383
224M
        for (I v : m_val) ret += PopCount(v);
384
28.0M
        return ret;
385
28.0M
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Count() const
Line
Count
Source
381
6.82M
    {
382
6.82M
        unsigned ret{0};
383
27.3M
        for (I v : m_val) ret += PopCount(v);
384
6.82M
        return ret;
385
6.82M
    }
386
    /** Check if all bits are 0. */
387
    bool constexpr None() const noexcept
388
23.9M
    {
389
67.5M
        for (auto v : m_val) {
390
67.5M
            if (v != 0) return false;
391
67.5M
        }
392
5.83M
        return true;
393
23.9M
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::None() const
Line
Count
Source
388
10.8M
    {
389
15.5M
        for (auto v : m_val) {
390
15.5M
            if (v != 0) return false;
391
15.5M
        }
392
2.54M
        return true;
393
10.8M
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::None() const
Line
Count
Source
388
10.8M
    {
389
46.4M
        for (auto v : m_val) {
390
46.4M
            if (v != 0) return false;
391
46.4M
        }
392
2.54M
        return true;
393
10.8M
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::None() const
Line
Count
Source
388
2.21M
    {
389
5.54M
        for (auto v : m_val) {
390
5.54M
            if (v != 0) return false;
391
5.54M
        }
392
753k
        return true;
393
2.21M
    }
394
    /** Check if any bits are 1. */
395
23.8M
    bool constexpr Any() const noexcept { return !None(); }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::Any() const
Line
Count
Source
395
10.8M
    bool constexpr Any() const noexcept { return !None(); }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Any() const
Line
Count
Source
395
10.8M
    bool constexpr Any() const noexcept { return !None(); }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Any() const
Line
Count
Source
395
2.20M
    bool constexpr Any() const noexcept { return !None(); }
396
    /** Return an object that iterates over all 1 bits (++ and * only allowed when != end()). */
397
113M
    Iterator constexpr begin() const noexcept { return Iterator(m_val); }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::begin() const
Line
Count
Source
397
51.2M
    Iterator constexpr begin() const noexcept { return Iterator(m_val); }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::begin() const
Line
Count
Source
397
51.2M
    Iterator constexpr begin() const noexcept { return Iterator(m_val); }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::begin() const
Line
Count
Source
397
10.9M
    Iterator constexpr begin() const noexcept { return Iterator(m_val); }
398
    /** Return a dummy object to compare Iterators with. */
399
115M
    IteratorEnd constexpr end() const noexcept { return IteratorEnd(); }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::end() const
Line
Count
Source
399
52.1M
    IteratorEnd constexpr end() const noexcept { return IteratorEnd(); }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::end() const
Line
Count
Source
399
52.1M
    IteratorEnd constexpr end() const noexcept { return IteratorEnd(); }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::end() const
Line
Count
Source
399
11.2M
    IteratorEnd constexpr end() const noexcept { return IteratorEnd(); }
400
    /** Find the first element (requires Any()). */
401
    unsigned constexpr First() const noexcept
402
20.1M
    {
403
20.1M
        unsigned p = 0;
404
43.4M
        while (m_val[p] == 0) {
405
23.3M
            ++p;
406
23.3M
            Assume(p < N);
407
23.3M
        }
408
20.1M
        return std::countr_zero(m_val[p]) + p * LIMB_BITS;
409
20.1M
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::First() const
Line
Count
Source
402
9.20M
    {
403
9.20M
        unsigned p = 0;
404
11.5M
        while (m_val[p] == 0) {
405
2.32M
            ++p;
406
2.32M
            Assume(p < N);
407
2.32M
        }
408
9.20M
        return std::countr_zero(m_val[p]) + p * LIMB_BITS;
409
9.20M
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::First() const
Line
Count
Source
402
9.19M
    {
403
9.19M
        unsigned p = 0;
404
28.9M
        while (m_val[p] == 0) {
405
19.7M
            ++p;
406
19.7M
            Assume(p < N);
407
19.7M
        }
408
9.19M
        return std::countr_zero(m_val[p]) + p * LIMB_BITS;
409
9.19M
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::First() const
Line
Count
Source
402
1.73M
    {
403
1.73M
        unsigned p = 0;
404
3.03M
        while (m_val[p] == 0) {
405
1.29M
            ++p;
406
1.29M
            Assume(p < N);
407
1.29M
        }
408
1.73M
        return std::countr_zero(m_val[p]) + p * LIMB_BITS;
409
1.73M
    }
410
    /** Find the last element (requires Any()). */
411
    unsigned constexpr Last() const noexcept
412
1.73k
    {
413
1.73k
        unsigned p = N - 1;
414
5.28k
        while (m_val[p] == 0) {
415
3.54k
            Assume(p > 0);
416
3.54k
            --p;
417
3.54k
        }
418
1.73k
        return std::bit_width(m_val[p]) - 1 + p * LIMB_BITS;
419
1.73k
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::Last() const
Line
Count
Source
412
681
    {
413
681
        unsigned p = N - 1;
414
1.05k
        while (m_val[p] == 0) {
415
375
            Assume(p > 0);
416
375
            --p;
417
375
        }
418
681
        return std::bit_width(m_val[p]) - 1 + p * LIMB_BITS;
419
681
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Last() const
Line
Count
Source
412
681
    {
413
681
        unsigned p = N - 1;
414
3.26k
        while (m_val[p] == 0) {
415
2.58k
            Assume(p > 0);
416
2.58k
            --p;
417
2.58k
        }
418
681
        return std::bit_width(m_val[p]) - 1 + p * LIMB_BITS;
419
681
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Last() const
Line
Count
Source
412
375
    {
413
375
        unsigned p = N - 1;
414
960
        while (m_val[p] == 0) {
415
585
            Assume(p > 0);
416
585
            --p;
417
585
        }
418
375
        return std::bit_width(m_val[p]) - 1 + p * LIMB_BITS;
419
375
    }
420
    /** Set this object's bits to be the binary OR between respective bits from this and a. */
421
    constexpr MultiIntBitSet& operator|=(const MultiIntBitSet& a) noexcept
422
66.4M
    {
423
393M
        for (unsigned i = 0; i < N; ++i) {
424
326M
            m_val[i] |= a.m_val[i];
425
326M
        }
426
66.4M
        return *this;
427
66.4M
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::operator|=(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&)
Line
Count
Source
422
30.5M
    {
423
91.6M
        for (unsigned i = 0; i < N; ++i) {
424
61.1M
            m_val[i] |= a.m_val[i];
425
61.1M
        }
426
30.5M
        return *this;
427
30.5M
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::operator|=(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&)
Line
Count
Source
422
30.5M
    {
423
275M
        for (unsigned i = 0; i < N; ++i) {
424
244M
            m_val[i] |= a.m_val[i];
425
244M
        }
426
30.5M
        return *this;
427
30.5M
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::operator|=(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&)
Line
Count
Source
422
5.33M
    {
423
26.6M
        for (unsigned i = 0; i < N; ++i) {
424
21.3M
            m_val[i] |= a.m_val[i];
425
21.3M
        }
426
5.33M
        return *this;
427
5.33M
    }
428
    /** Set this object's bits to be the binary AND between respective bits from this and a. */
429
    constexpr MultiIntBitSet& operator&=(const MultiIntBitSet& a) noexcept
430
    {
431
        for (unsigned i = 0; i < N; ++i) {
432
            m_val[i] &= a.m_val[i];
433
        }
434
        return *this;
435
    }
436
    /** Set this object's bits to be the binary AND NOT between respective bits from this and a. */
437
    constexpr MultiIntBitSet& operator-=(const MultiIntBitSet& a) noexcept
438
46.8M
    {
439
276M
        for (unsigned i = 0; i < N; ++i) {
440
230M
            m_val[i] &= ~a.m_val[i];
441
230M
        }
442
46.8M
        return *this;
443
46.8M
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::operator-=(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&)
Line
Count
Source
438
21.3M
    {
439
64.0M
        for (unsigned i = 0; i < N; ++i) {
440
42.7M
            m_val[i] &= ~a.m_val[i];
441
42.7M
        }
442
21.3M
        return *this;
443
21.3M
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::operator-=(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&)
Line
Count
Source
438
21.3M
    {
439
192M
        for (unsigned i = 0; i < N; ++i) {
440
170M
            m_val[i] &= ~a.m_val[i];
441
170M
        }
442
21.3M
        return *this;
443
21.3M
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::operator-=(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&)
Line
Count
Source
438
4.14M
    {
439
20.7M
        for (unsigned i = 0; i < N; ++i) {
440
16.5M
            m_val[i] &= ~a.m_val[i];
441
16.5M
        }
442
4.14M
        return *this;
443
4.14M
    }
444
    /** Set this object's bits to be the binary XOR between respective bits from this and a. */
445
    constexpr MultiIntBitSet& operator^=(const MultiIntBitSet& a) noexcept
446
    {
447
        for (unsigned i = 0; i < N; ++i) {
448
            m_val[i] ^= a.m_val[i];
449
        }
450
        return *this;
451
    }
452
    /** Check whether the intersection between two sets is non-empty. */
453
    constexpr bool Overlaps(const MultiIntBitSet& a) const noexcept
454
23.8M
    {
455
138M
        for (unsigned i = 0; i < N; ++i) {
456
115M
            if (m_val[i] & a.m_val[i]) return true;
457
115M
        }
458
23.2M
        return false;
459
23.8M
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::Overlaps(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&) const
Line
Count
Source
454
10.8M
    {
455
32.0M
        for (unsigned i = 0; i < N; ++i) {
456
21.4M
            if (m_val[i] & a.m_val[i]) return true;
457
21.4M
        }
458
10.6M
        return false;
459
10.8M
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::Overlaps(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&) const
Line
Count
Source
454
10.8M
    {
455
95.8M
        for (unsigned i = 0; i < N; ++i) {
456
85.2M
            if (m_val[i] & a.m_val[i]) return true;
457
85.2M
        }
458
10.6M
        return false;
459
10.8M
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::Overlaps(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&) const
Line
Count
Source
454
2.13M
    {
455
10.4M
        for (unsigned i = 0; i < N; ++i) {
456
8.37M
            if (m_val[i] & a.m_val[i]) return true;
457
8.37M
        }
458
2.07M
        return false;
459
2.13M
    }
460
    /** Return an object with the binary AND between respective bits from a and b. */
461
    friend constexpr MultiIntBitSet operator&(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept
462
34.8M
    {
463
34.8M
        MultiIntBitSet r;
464
205M
        for (unsigned i = 0; i < N; ++i) {
465
171M
            r.m_val[i] = a.m_val[i] & b.m_val[i];
466
171M
        }
467
34.8M
        return r;
468
34.8M
    }
bitset_detail::operator&(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&, bitset_detail::MultiIntBitSet<unsigned int, 2u> const&)
Line
Count
Source
462
15.8M
    {
463
15.8M
        MultiIntBitSet r;
464
47.4M
        for (unsigned i = 0; i < N; ++i) {
465
31.6M
            r.m_val[i] = a.m_val[i] & b.m_val[i];
466
31.6M
        }
467
15.8M
        return r;
468
15.8M
    }
bitset_detail::operator&(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&, bitset_detail::MultiIntBitSet<unsigned char, 8u> const&)
Line
Count
Source
462
15.7M
    {
463
15.7M
        MultiIntBitSet r;
464
142M
        for (unsigned i = 0; i < N; ++i) {
465
126M
            r.m_val[i] = a.m_val[i] & b.m_val[i];
466
126M
        }
467
15.7M
        return r;
468
15.7M
    }
bitset_detail::operator&(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&, bitset_detail::MultiIntBitSet<unsigned char, 4u> const&)
Line
Count
Source
462
3.28M
    {
463
3.28M
        MultiIntBitSet r;
464
16.4M
        for (unsigned i = 0; i < N; ++i) {
465
13.1M
            r.m_val[i] = a.m_val[i] & b.m_val[i];
466
13.1M
        }
467
3.28M
        return r;
468
3.28M
    }
469
    /** Return an object with the binary OR between respective bits from a and b. */
470
    friend constexpr MultiIntBitSet operator|(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept
471
    {
472
        MultiIntBitSet r;
473
        for (unsigned i = 0; i < N; ++i) {
474
            r.m_val[i] = a.m_val[i] | b.m_val[i];
475
        }
476
        return r;
477
    }
478
    /** Return an object with the binary AND NOT between respective bits from a and b. */
479
    friend constexpr MultiIntBitSet operator-(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept
480
9.81M
    {
481
9.81M
        MultiIntBitSet r;
482
57.6M
        for (unsigned i = 0; i < N; ++i) {
483
47.8M
            r.m_val[i] = a.m_val[i] & ~b.m_val[i];
484
47.8M
        }
485
9.81M
        return r;
486
9.81M
    }
bitset_detail::operator-(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&, bitset_detail::MultiIntBitSet<unsigned int, 2u> const&)
Line
Count
Source
480
4.27M
    {
481
4.27M
        MultiIntBitSet r;
482
12.8M
        for (unsigned i = 0; i < N; ++i) {
483
8.55M
            r.m_val[i] = a.m_val[i] & ~b.m_val[i];
484
8.55M
        }
485
4.27M
        return r;
486
4.27M
    }
bitset_detail::operator-(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&, bitset_detail::MultiIntBitSet<unsigned char, 8u> const&)
Line
Count
Source
480
4.28M
    {
481
4.28M
        MultiIntBitSet r;
482
38.5M
        for (unsigned i = 0; i < N; ++i) {
483
34.2M
            r.m_val[i] = a.m_val[i] & ~b.m_val[i];
484
34.2M
        }
485
4.28M
        return r;
486
4.28M
    }
bitset_detail::operator-(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&, bitset_detail::MultiIntBitSet<unsigned char, 4u> const&)
Line
Count
Source
480
1.25M
    {
481
1.25M
        MultiIntBitSet r;
482
6.27M
        for (unsigned i = 0; i < N; ++i) {
483
5.01M
            r.m_val[i] = a.m_val[i] & ~b.m_val[i];
484
5.01M
        }
485
1.25M
        return r;
486
1.25M
    }
487
    /** Return an object with the binary XOR between respective bits from a and b. */
488
    friend constexpr MultiIntBitSet operator^(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept
489
    {
490
        MultiIntBitSet r;
491
        for (unsigned i = 0; i < N; ++i) {
492
            r.m_val[i] = a.m_val[i] ^ b.m_val[i];
493
        }
494
        return r;
495
    }
496
    /** Check if bitset a is a superset of bitset b (= every 1 bit in b is also in a). */
497
    constexpr bool IsSupersetOf(const MultiIntBitSet& a) const noexcept
498
104k
    {
499
614k
        for (unsigned i = 0; i < N; ++i) {
500
510k
            if (a.m_val[i] & ~m_val[i]) return false;
501
510k
        }
502
104k
        return true;
503
104k
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::IsSupersetOf(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&) const
Line
Count
Source
498
47.0k
    {
499
141k
        for (unsigned i = 0; i < N; ++i) {
500
94.0k
            if (a.m_val[i] & ~m_val[i]) return false;
501
94.0k
        }
502
47.0k
        return true;
503
47.0k
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::IsSupersetOf(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&) const
Line
Count
Source
498
47.0k
    {
499
423k
        for (unsigned i = 0; i < N; ++i) {
500
376k
            if (a.m_val[i] & ~m_val[i]) return false;
501
376k
        }
502
47.0k
        return true;
503
47.0k
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::IsSupersetOf(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&) const
Line
Count
Source
498
10.1k
    {
499
50.8k
        for (unsigned i = 0; i < N; ++i) {
500
40.6k
            if (a.m_val[i] & ~m_val[i]) return false;
501
40.6k
        }
502
10.1k
        return true;
503
10.1k
    }
504
    /** Check if bitset a is a subset of bitset b (= every 1 bit in a is also in b). */
505
    constexpr bool IsSubsetOf(const MultiIntBitSet& a) const noexcept
506
10.3M
    {
507
61.4M
        for (unsigned i = 0; i < N; ++i) {
508
51.1M
            if (m_val[i] & ~a.m_val[i]) return false;
509
51.1M
        }
510
10.3M
        return true;
511
10.3M
    }
bitset_detail::MultiIntBitSet<unsigned int, 2u>::IsSubsetOf(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&) const
Line
Count
Source
506
4.82M
    {
507
14.4M
        for (unsigned i = 0; i < N; ++i) {
508
9.64M
            if (m_val[i] & ~a.m_val[i]) return false;
509
9.64M
        }
510
4.82M
        return true;
511
4.82M
    }
bitset_detail::MultiIntBitSet<unsigned char, 8u>::IsSubsetOf(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&) const
Line
Count
Source
506
4.81M
    {
507
43.3M
        for (unsigned i = 0; i < N; ++i) {
508
38.5M
            if (m_val[i] & ~a.m_val[i]) return false;
509
38.5M
        }
510
4.81M
        return true;
511
4.81M
    }
bitset_detail::MultiIntBitSet<unsigned char, 4u>::IsSubsetOf(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&) const
Line
Count
Source
506
732k
    {
507
3.66M
        for (unsigned i = 0; i < N; ++i) {
508
2.92M
            if (m_val[i] & ~a.m_val[i]) return false;
509
2.92M
        }
510
732k
        return true;
511
732k
    }
512
    /** Check if bitset a and bitset b are identical. */
513
3.38M
    friend constexpr bool operator==(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept = default;
bitset_detail::operator==(bitset_detail::MultiIntBitSet<unsigned int, 2u> const&, bitset_detail::MultiIntBitSet<unsigned int, 2u> const&)
Line
Count
Source
513
1.47M
    friend constexpr bool operator==(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept = default;
bitset_detail::operator==(bitset_detail::MultiIntBitSet<unsigned char, 8u> const&, bitset_detail::MultiIntBitSet<unsigned char, 8u> const&)
Line
Count
Source
513
1.46M
    friend constexpr bool operator==(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept = default;
bitset_detail::operator==(bitset_detail::MultiIntBitSet<unsigned char, 4u> const&, bitset_detail::MultiIntBitSet<unsigned char, 4u> const&)
Line
Count
Source
513
446k
    friend constexpr bool operator==(const MultiIntBitSet& a, const MultiIntBitSet& b) noexcept = default;
514
    /** Swap two bitsets. */
515
    friend constexpr void swap(MultiIntBitSet& a, MultiIntBitSet& b) noexcept { std::swap(a.m_val, b.m_val); }
516
};
517
518
} // namespace bitset_detail
519
520
// BitSet dispatches to IntBitSet or MultiIntBitSet as appropriate for the requested minimum number
521
// of bits. Use IntBitSet up to 32-bit, or up to 64-bit on 64-bit platforms; above that, use a
522
// MultiIntBitSet of size_t.
523
template<unsigned BITS>
524
using BitSet = std::conditional_t<(BITS <= 32), bitset_detail::IntBitSet<uint32_t>,
525
               std::conditional_t<(BITS <= std::numeric_limits<size_t>::digits), bitset_detail::IntBitSet<size_t>,
526
               bitset_detail::MultiIntBitSet<size_t, CeilDiv(BITS, size_t{std::numeric_limits<size_t>::digits})>>>;
527
528
#endif // BITCOIN_UTIL_BITSET_H