40#include <cereal/cereal.hpp>
41#include <cereal/macros.hpp>
42#include <cereal/specialize.hpp>
44#include <hibf/cereal/concepts.hpp>
45#include <hibf/contrib/aligned_allocator.hpp>
64 typename std::allocator_traits<
65 seqan::hibf::contrib::aligned_allocator<bool, 64u>>::template rebind_alloc<uint64_t>>
69 using allocator_t = seqan::hibf::contrib::aligned_allocator<bool, 64u>;
75 using chunk_type = uint64_t;
88 template <
bool is_const>
98 maybe_const_chunk_type * _chunk{};
99 chunk_type _chunk_mask{};
106 constexpr bit_reference(maybe_const_chunk_type * chunk,
size_type const local_chunk_position) noexcept :
108 _chunk_mask{
static_cast<chunk_type
>(1) << to_local_chunk_position(local_chunk_position)}
115 bit_reference() =
delete;
116 bit_reference(bit_reference
const & other) =
default;
117 bit_reference(bit_reference && other) =
default;
118 bit_reference & operator=(bit_reference
const & other)
123 bit_reference & operator=(bit_reference && other)
noexcept
133 constexpr bit_reference & operator=(
bool const bit)
noexcept
135 bit ? set() : clear();
143 constexpr bit_reference
const & operator=(
bool const bit)
const noexcept
146 bit ? set() : clear();
152 constexpr operator bool()
const noexcept
154 return *_chunk & _chunk_mask;
158 constexpr bit_reference & flip()
noexcept
160 (*this) ? clear() : set();
166 constexpr void set()
noexcept
168 *_chunk |= _chunk_mask;
172 constexpr void clear()
noexcept
174 *_chunk &= ~_chunk_mask;
181 template <
bool is_const>
187 friend class bit_iterator;
192 maybe_const_chunk_type * _chunk{};
200 using reference = bit_reference<is_const>;
201 using pointer = void;
210 bit_iterator() =
default;
216 explicit constexpr bit_iterator(maybe_const_chunk_type * chunk) noexcept : _chunk{chunk}, _chunk_position{0}
223 constexpr bit_iterator(bit_iterator<!is_const>
const & other)
noexcept
225 : _chunk{other._chunk}, _chunk_position{other._chunk_position}
233 constexpr reference operator*()
const noexcept
235 return reference{_chunk, _chunk_position};
241 return *((*this) +
count);
249 constexpr bit_iterator & operator++()
noexcept
251 _chunk += !
static_cast<bool>(to_local_chunk_position(++_chunk_position));
256 constexpr bit_iterator operator++(
int)
noexcept
258 bit_iterator tmp{*
this};
273 size_type updated_count = modulo_mask - to_local_chunk_position(_chunk_position) -
count;
274 _chunk_position = modulo_mask - to_local_chunk_position(updated_count);
275 _chunk -= to_chunk_position(updated_count);
280 _chunk += to_chunk_position(to_local_chunk_position(_chunk_position) +
count);
281 _chunk_position = to_local_chunk_position(_chunk_position +
count);
290 bit_iterator tmp{*
this};
301 constexpr bit_iterator & operator--()
noexcept
303 _chunk -= !
static_cast<bool>(to_local_chunk_position(--_chunk_position));
308 constexpr bit_iterator operator--(
int)
noexcept
310 bit_iterator tmp{*
this};
318 return *
this += -
count;
324 bit_iterator tmp{*
this};
329 template <
bool is_const_other>
330 constexpr difference_type operator-(bit_iterator<is_const_other> rhs)
const noexcept
332 return ((_chunk - rhs._chunk) << division_mask) -
333 to_local_chunk_position(rhs._chunk_position) +
334 to_local_chunk_position(_chunk_position);
342 template <
bool is_const_other>
343 bool operator==(bit_iterator<is_const_other>
const & rhs)
const
345 return _chunk == rhs._chunk
346 && (to_local_chunk_position(_chunk_position) == to_local_chunk_position(rhs._chunk_position));
350 template <
bool is_const_other>
353 if (
std::strong_ordering order = _chunk <=> rhs._chunk; order == std::strong_ordering::equivalent)
354 return to_local_chunk_position(_chunk_position) <=> to_local_chunk_position(rhs._chunk_position);
385 static constexpr size_type chunk_size =
sizeof(chunk_type) * CHAR_BIT;
387 static constexpr size_type modulo_mask = chunk_size - 1u;
468 template <std::input_iterator iterator_t, std::sentinel_for<iterator_t> sentinel_t>
470 constexpr void assign(iterator_t first, sentinel_t last)
474 tmp.
reserve(std::ranges::distance(first, last));
480 set_new_size(std::ranges::distance(
begin(),
end()));
531 [value = fill_chunk(bit)](chunk_type & chunk)
544 assert(position <
size());
546 return *std::ranges::next(
begin(), position);
552 assert(position <
size());
554 return *std::ranges::next(
begin(), position);
577 return (*
this)[
size() - 1u];
585 return (*
this)[
size() - 1u];
589 constexpr bool all() const noexcept
594 constexpr chunk_type mask = ~chunk_type{};
595 chunk_type
const *
const ptr = data();
598 for (
size_t i = 0; i < last_chunk; ++i)
603 return (ptr[last_chunk] | ~last_chunk_mask()) == mask;
607 constexpr bool any() const noexcept
612 chunk_type
const *
const ptr = data();
615 for (
size_t i = 0; i < last_chunk; ++i)
620 return (ptr[last_chunk] & last_chunk_mask()) != chunk_type{};
624 constexpr bool none() const noexcept
630 constexpr size_t count() const noexcept
635 chunk_type
const *
const ptr = data();
639 for (
size_t i = 0; i <
size; ++i)
657 constexpr bool empty() const noexcept
717 size_t const new_size =
size() + 1u;
720 set_new_size(new_size);
729 size_t const old_size =
size();
733 if (bit &&
size() > old_size)
747 assert(rhs.size() ==
size());
749 return binary_transform_impl(rhs,
750 [](
auto const & left_chunk,
auto const & right_chunk)
752 return left_chunk & right_chunk;
759 assert(rhs.size() ==
size());
761 return binary_transform_impl(rhs,
762 [](
auto const & left_chunk,
auto const & right_chunk)
764 return left_chunk | right_chunk;
771 assert(rhs.size() ==
size());
773 return binary_transform_impl(rhs,
774 [](
auto const & left_chunk,
auto const & right_chunk)
776 return left_chunk ^ right_chunk;
785 tmp.binary_transform_impl(*
this,
786 [](
auto const &,
auto const & right_chunk)
815 assert(rhs.size() ==
size());
817 return binary_transform_impl(rhs,
818 [](
auto const & left_chunk,
auto const & right_chunk)
820 return left_chunk & ~right_chunk;
828 [](chunk_type & chunk)
840 if (position >=
size())
844 (*this)[position].flip();
896 [[gnu::always_inline]]
inline constexpr chunk_type * data() noexcept
901 [[gnu::always_inline]]
inline constexpr chunk_type
const * data() const noexcept
913 template <cereal_archive archive_t>
914 void CEREAL_LOAD_FUNCTION_NAME(archive_t & archive)
920 size_t const vector_size = host_size_impl(_size);
922 resize_for_overwrite(vector_size);
926 for (
auto && v : *as_base())
931 archive(cereal::binary_data(data(), vector_size *
sizeof(chunk_type)));
936 template <cereal_archive archive_t>
937 void CEREAL_SAVE_FUNCTION_NAME(archive_t & archive)
const
946 for (
auto && v : *as_base())
951 archive(cereal::binary_data(data(),
base_t::size() *
sizeof(chunk_type)));
958#ifndef HIBF_UNINITIALISED_RESIZE
959 inline constexpr void resize_for_overwrite(
size_t const size)
966# if defined(_LIBCPP_VERSION)
967 inline void resize_for_overwrite(
size_t const size)
971 using allocator_t =
typename base_t::allocator_type;
976# pragma GCC diagnostic push
977# pragma GCC diagnostic ignored "-Wgnu-anonymous-struct"
978 _LIBCPP_COMPRESSED_PAIR(pointer, end_cap =
nullptr, allocator_type,
allocator);
979# pragma GCC diagnostic pop
982 static_assert(
sizeof(fake_vector) ==
sizeof(base_t));
983 static_assert(
alignof(fake_vector) ==
alignof(base_t));
988# if __has_feature(address_sanitizer)
994 fake_vector & vec =
reinterpret_cast<fake_vector &
>(*this);
995 vec.end = vec.begin +
size;
999 inline constexpr void resize_for_overwrite(
size_t const size)
1004 this->_M_impl._M_finish = this->_M_impl._M_start +
size;
1010 template <
typename binary_operator_t>
1011 constexpr bit_vector & binary_transform_impl(
bit_vector const & rhs, binary_operator_t && op)
noexcept
1013 chunk_type *
const lhs_data = data();
1014 chunk_type
const *
const rhs_data = rhs.data();
1017 for (
size_t i = 0; i <
size; ++i)
1018 lhs_data[i] = op(lhs_data[i], rhs_data[i]);
1027 return chunks_needed(
count);
1031 constexpr void set_new_size(
size_type const new_size)
noexcept
1037 constexpr base_t
const * as_base() const noexcept
1039 return static_cast<base_t
const *
>(
this);
1043 constexpr base_t * as_base() noexcept
1045 return static_cast<base_t *
>(
this);
1051 return (
count + 63u) >> 6;
1061 constexpr chunk_type last_chunk_mask() const noexcept
1065 size_type const bits_in_last_chunk = to_local_chunk_position(
size());
1066 return bits_in_last_chunk ? (chunk_type{1u} << bits_in_last_chunk) - 1u : ~chunk_type{};
1070 constexpr chunk_type fill_chunk(
bool const bit)
const noexcept
1072 return (bit) ? ~chunk_type{} : chunk_type{};
1076 static constexpr size_type to_local_chunk_position(
size_type const position)
noexcept
1078 return position & modulo_mask;
1084 return position >> division_mask;
1100template <
typename archive_t>
1101struct specialize<archive_t, seqan::hibf::bit_vector, cereal::specialization::member_load_save>
T back_inserter(T... args)
An bit vector.
Definition bit_vector.hpp:66
constexpr void resize(size_type const count, bool const bit={})
Changes the number of elements stored, where additional copies of bit are appended.
Definition bit_vector.hpp:725
constexpr reference back() noexcept
Access the last element.
Definition bit_vector.hpp:573
constexpr void swap(bit_vector &other) noexcept
Exchanges the contents of the container with those of others.
Definition bit_vector.hpp:849
allocator_t allocator_type
The allocator type to use.
Definition bit_vector.hpp:380
constexpr bit_vector operator~() const noexcept
Performs binary NOT.
Definition bit_vector.hpp:781
constexpr bit_vector & flip(size_type position)
Flips the bit at the given position.
Definition bit_vector.hpp:836
constexpr reference operator[](size_type const position) noexcept
Access specified element.
Definition bit_vector.hpp:542
constexpr bit_vector(allocator_type const &alloc=allocator_type{})
The default constructor which optionally sets the allocator.
Definition bit_vector.hpp:399
constexpr friend bit_vector operator|(bit_vector lhs, bit_vector const &rhs) noexcept
Performs binary OR.
Definition bit_vector.hpp:801
constexpr bit_vector(size_type const count, bool const bit, allocator_type const &alloc=allocator_type{})
Constructs the bit vector with count copies of elements with value bit.
Definition bit_vector.hpp:413
constexpr bit_vector & and_not(bit_vector const &rhs) noexcept
Computes the bitwise a &= ~b operator without an additional copy.
Definition bit_vector.hpp:813
constexpr size_type size() const noexcept
Returns the number of elements.
Definition bit_vector.hpp:651
constexpr bit_vector(std::initializer_list< bool > list, allocator_type const &alloc=allocator_type{})
Constructs the container initialised with the elements in list.
Definition bit_vector.hpp:424
constexpr size_t count() const noexcept
Returns the number of bits that are set to true.
Definition bit_vector.hpp:630
bit_iterator< false > iterator
The iterator over the bits.
Definition bit_vector.hpp:366
constexpr bit_vector(bit_vector &&)=default
Default.
constexpr const_reference back() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition bit_vector.hpp:581
constexpr iterator end() noexcept
Returns an iterator to the end.
Definition bit_vector.hpp:878
constexpr friend bit_vector operator^(bit_vector lhs, bit_vector const &rhs) noexcept
Performs binary XOR.
Definition bit_vector.hpp:807
constexpr bit_vector(bit_vector const &)=default
Default.
constexpr ~bit_vector()=default
Default.
constexpr const_iterator cend() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition bit_vector.hpp:890
constexpr iterator begin() noexcept
Returns an iterator to the beginning.
Definition bit_vector.hpp:860
constexpr bit_vector & flip() noexcept
Flips all bits in-place.
Definition bit_vector.hpp:825
constexpr bool any() const noexcept
Checks if any bit is set to true.
Definition bit_vector.hpp:607
constexpr bool none() const noexcept
Checks if none of the bits is set to true.
Definition bit_vector.hpp:624
constexpr friend bit_vector operator&(bit_vector lhs, bit_vector const &rhs) noexcept
Performs binary AND.
Definition bit_vector.hpp:795
constexpr bit_vector(size_type const count, allocator_type const &alloc=allocator_type{})
Constructs the container with count default-inserted instances of bool. No copies are made.
Definition bit_vector.hpp:435
constexpr const_iterator end() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition bit_vector.hpp:884
constexpr bit_vector & operator=(bit_vector &&)=default
Default.
bit_iterator< true > const_iterator
The const iterator over the bits.
Definition bit_vector.hpp:368
constexpr void assign(size_type const count, bool const bit)
Assigns values to the container.
Definition bit_vector.hpp:527
constexpr void assign(std::initializer_list< bool > const &ilist)
Assigns values to the container.
Definition bit_vector.hpp:502
constexpr bool all() const noexcept
Checks if all bits are set to true.
Definition bit_vector.hpp:589
constexpr const_iterator begin() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition bit_vector.hpp:866
constexpr void push_back(bool bit)
Adds an element to the end.
Definition bit_vector.hpp:715
size_t size_type
The size_type.
Definition bit_vector.hpp:376
constexpr bit_vector & operator|=(bit_vector const &rhs) noexcept
Performs binary OR between this and rhs.
Definition bit_vector.hpp:757
constexpr bool empty() const noexcept
Checks wether the container is empty.
Definition bit_vector.hpp:657
constexpr bit_vector & operator=(bit_vector const &)=default
Default.
constexpr void assign(iterator_t first, sentinel_t last)
Assigns values to the container.
Definition bit_vector.hpp:470
constexpr const_iterator cbegin() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition bit_vector.hpp:872
constexpr bit_vector & operator^=(bit_vector const &rhs) noexcept
Performs binary XOR between this and rhs.
Definition bit_vector.hpp:769
constexpr void reserve(size_type const new_capacity)
Reserves storage.
Definition bit_vector.hpp:685
constexpr bit_vector & operator&=(bit_vector const &rhs) noexcept
Performs binary AND between this and rhs.
Definition bit_vector.hpp:745
constexpr void clear() noexcept
Erases all elements. After this call, size() returns zero. capacity() remains unchanged.
Definition bit_vector.hpp:738
constexpr size_type capacity() const noexcept
Returns the capacity.
Definition bit_vector.hpp:663
constexpr const_reference operator[](size_type const position) const noexcept
Access specified element.
Definition bit_vector.hpp:550
Definition concepts.hpp:27