5#ifndef BITCOIN_UTIL_BITDEQUE_H
6#define BITCOIN_UTIL_BITDEQUE_H
21template<
int BITS_PER_WORD = 4096 * 8>
27 static_assert(BITS_PER_WORD > 0);
37 using deque_iterator = std::conditional_t<Const, typename deque_type::const_iterator, typename deque_type::iterator>;
49 using reference = std::conditional_t<Const, bool, typename word_type::reference>;
60 template<
bool ConstArg = Const,
typename = std::enable_if_t<Const && ConstArg>>
66 if (dist +
m_bitpos >= BITS_PER_WORD) {
71 auto jump = dist / BITS_PER_WORD;
73 m_bitpos += dist - jump * BITS_PER_WORD;
74 }
else if (dist < 0) {
81 auto jump = dist / BITS_PER_WORD;
83 m_bitpos -= dist - jump * BITS_PER_WORD;
143 last.reset(BITS_PER_WORD - 1 -
m_pad_end);
197 if (before < after) {
202 std::move_backward(
begin() + before,
begin() + before + after,
end());
214 m_deque.resize((
count + BITS_PER_WORD - 1) / BITS_PER_WORD);
218 for (
auto& elem :
m_deque) elem.flip();
220 if (
count % BITS_PER_WORD) {
269 if (
m_deque.max_size() < std::numeric_limits<difference_type>::max() / BITS_PER_WORD) {
270 return m_deque.max_size() * BITS_PER_WORD;
272 return std::numeric_limits<difference_type>::max();
277 template<
typename It>
283 while (first != last) {
284 *(it++) = *(first++);
289 void assign(std::initializer_list<bool> ilist)
291 assign(ilist.size(),
false);
293 auto init = ilist.begin();
294 while (
init != ilist.end()) {
307 template<
typename It>
316 if (position >=
size())
throw std::out_of_range(
"bitdeque::at() out of range");
317 return begin()[position];
321 if (position >=
size())
throw std::out_of_range(
"bitdeque::at() out of range");
322 return cbegin()[position];
399 std::swap(
m_deque, other.m_deque);
409 size_type dist = std::distance(first, last);
411 if (before < after) {
412 std::move_backward(
begin(),
begin() + before,
end() - after);
414 return begin() + before;
418 return end() - after;
431 auto it =
begin() + before;
442 auto it_begin =
begin() + before;
444 auto it_end = it +
count;
445 while (it != it_end) *(it++) = val;
449 template<
typename It>
455 auto it_begin =
begin() + before;
457 while (first != last) {
458 *(it++) = *(first++);
Iterator to a bitdeque element, const or not.
std::ptrdiff_t difference_type
std::conditional_t< Const, typename deque_type::const_iterator, typename deque_type::iterator > deque_iterator
Iterator()=default
Default constructor.
Iterator & operator=(const Iterator &)=default
std::conditional_t< Const, bool, typename word_type::reference > reference
Iterator(const Iterator &)=default
Default copy constructor.
Iterator & operator-=(difference_type dist)
std::random_access_iterator_tag iterator_category
reference operator*() const
Iterator(const deque_iterator &it, int bitpos)
Iterator(const Iterator< false > &x)
Conversion from non-const to const iterator.
friend bool operator==(const Iterator &x, const Iterator &y)
friend auto operator<=>(const Iterator &x, const Iterator &y)
friend Iterator operator-(Iterator x, difference_type dist)
Iterator & operator+=(difference_type dist)
reference operator[](difference_type pos) const
friend Iterator operator+(Iterator x, difference_type dist)
friend difference_type operator-(const Iterator &x, const Iterator &y)
friend Iterator operator+(difference_type dist, Iterator x)
Class that mimics std::deque<bool>, but with std::vector<bool>'s bit packing.
reference emplace_front(bool val)
void erase_front(size_type n)
Shrink the container by n bits, removing from the beginning.
void assign(std::initializer_list< bool > ilist)
Set the container equal to the bits in ilist.
int m_pad_begin
Number of unused bits at the front of m_deque.front().
std::deque< word_type > deque_type
const_iterator begin() const noexcept
bitdeque(bitdeque &&) noexcept=default
Move constructor.
bitdeque(const bitdeque &)=default
Copy constructor.
const_iterator end() const noexcept
size_type size() const noexcept
Count the number of bits in the container.
bool empty() const noexcept
Determine whether the container is empty.
typename deque_type::difference_type difference_type
void clear() noexcept
Empty the container.
reverse_iterator rend() noexcept
void assign(size_type count, bool val)
Set the container equal to count times the value of val.
typename word_type::reference reference
bitdeque & operator=(std::initializer_list< bool > ilist)
Set the container equal to the bits in ilist.
bitdeque()
Construct an empty container.
const_reference front() const
int m_pad_end
Number of unused bits at the back of m_deque.back().
const_reference at(size_type position) const
reverse_iterator rbegin() noexcept
std::reverse_iterator< iterator > reverse_iterator
iterator erase(iterator first, iterator last)
void extend_front(size_type n)
Extend the container by n bits, adding at the beginning.
friend void swap(bitdeque &b1, bitdeque &b2) noexcept
const_reverse_iterator crend() const noexcept
void shrink_to_fit()
Release unused memory.
bitdeque(It first, It last)
Construct a container containing the bits in [first,last).
bitdeque(size_type count, bool val)
Construct a container containing count times the value of val.
std::reverse_iterator< const_iterator > const_reverse_iterator
reference emplace_back(bool val)
void resize(size_type n)
Resize the container.
void assign(It first, It last)
Set the container equal to the bits in [first,last).
const_reverse_iterator rend() const noexcept
reference at(size_type position)
std::bitset< BITS_PER_WORD > word_type
const_reference operator[](size_type position) const
size_type max_size() const noexcept
Return the maximum size of the container.
const_reverse_iterator crbegin() const noexcept
bitdeque(std::initializer_list< bool > ilist)
Construct a container containing the bits in ilist.
iterator insert(const_iterator pos, size_type count, bool val)
iterator erase(iterator pos)
deque_type m_deque
Deque of bitsets storing the actual bit data.
iterator insert(const_iterator pos, bool val)
iterator erase(const_iterator first, const_iterator last)
bitdeque(size_t count)
Construct a container containing count false values.
void push_front(bool val)
void insert_zeroes(size_type before, size_type count)
Insert a sequence of falses anywhere in the container.
void swap(bitdeque &other) noexcept
iterator emplace(const_iterator pos, bool val)
iterator insert(const_iterator pos, It first, It last)
const_reference back() const
iterator begin() noexcept
const_reverse_iterator rbegin() const noexcept
iterator erase(const_iterator pos)
void erase_back(size_type n)
Shrink the container by n bits, removing from the end.
const_iterator cbegin() const noexcept
reference operator[](size_type position)
void extend_back(size_type n)
Extend the container by n bits, adding at the end.
const_iterator cend() const noexcept