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;
147 last.reset(BITS_PER_WORD - 1 -
m_pad_end);
201 if (before < after) {
206 std::move_backward(
begin() + before,
begin() + before + after,
end());
218 m_deque.resize((
count + BITS_PER_WORD - 1) / BITS_PER_WORD);
222 for (
auto& elem :
m_deque) elem.flip();
224 if (
count % BITS_PER_WORD) {
273 if (
m_deque.max_size() < std::numeric_limits<difference_type>::max() / BITS_PER_WORD) {
274 return m_deque.max_size() * BITS_PER_WORD;
276 return std::numeric_limits<difference_type>::max();
281 template<
typename It>
287 while (first != last) {
288 *(it++) = *(first++);
293 void assign(std::initializer_list<bool> ilist)
295 assign(ilist.size(),
false);
297 auto init = ilist.begin();
298 while (
init != ilist.end()) {
311 template<
typename It>
320 if (position >=
size())
throw std::out_of_range(
"bitdeque::at() out of range");
321 return begin()[position];
325 if (position >=
size())
throw std::out_of_range(
"bitdeque::at() out of range");
326 return cbegin()[position];
403 std::swap(
m_deque, other.m_deque);
413 size_type dist = std::distance(first, last);
415 if (before < after) {
416 std::move_backward(
begin(),
begin() + before,
end() - after);
418 return begin() + before;
422 return end() - after;
435 auto it =
begin() + before;
446 auto it_begin =
begin() + before;
448 auto it_end = it +
count;
449 while (it != it_end) *(it++) = val;
453 template<
typename It>
459 auto it_begin =
begin() + before;
461 while (first != last) {
462 *(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
friend bool operator!=(const Iterator &x, const Iterator &y)
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 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 bool operator>=(const Iterator &x, const Iterator &y)
friend difference_type operator-(const Iterator &x, const Iterator &y)
friend bool operator>(const Iterator &x, const Iterator &y)
friend bool operator<=(const Iterator &x, const Iterator &y)
friend Iterator operator+(difference_type dist, Iterator x)
friend bool operator<(const Iterator &x, const Iterator &y)
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