42#include <cereal/cereal.hpp>
43#include <cereal/macros.hpp>
44#include <cereal/specialize.hpp>
46#include <hibf/cereal/concepts.hpp>
47#include <hibf/contrib/aligned_allocator.hpp>
66 typename std::allocator_traits<
67 seqan::hibf::contrib::aligned_allocator<bool, 64u>>::template rebind_alloc<uint64_t>>
71 using allocator_t = seqan::hibf::contrib::aligned_allocator<bool, 64u>;
77 using chunk_type = uint64_t;
90 template <
bool is_const>
100 maybe_const_chunk_type * _chunk{};
101 chunk_type _chunk_mask{};
108 constexpr bit_reference(maybe_const_chunk_type * chunk,
size_type const local_chunk_position) noexcept :
110 _chunk_mask{
static_cast<chunk_type
>(1) << to_local_chunk_position(local_chunk_position)}
117 bit_reference() =
delete;
118 bit_reference(bit_reference
const & other) =
default;
119 bit_reference(bit_reference && other) =
default;
120 bit_reference & operator=(bit_reference
const & other)
125 bit_reference & operator=(bit_reference && other)
noexcept
135 constexpr bit_reference & operator=(
bool const bit)
noexcept
137 bit ? set() : clear();
145 constexpr bit_reference
const & operator=(
bool const bit)
const noexcept
148 bit ? set() : clear();
154 constexpr operator bool()
const noexcept
156 return *_chunk & _chunk_mask;
160 constexpr bit_reference & flip()
noexcept
162 (*this) ? clear() : set();
168 constexpr void set()
noexcept
170 *_chunk |= _chunk_mask;
174 constexpr void clear()
noexcept
176 *_chunk &= ~_chunk_mask;
183 template <
bool is_const>
189 friend class bit_iterator;
194 maybe_const_chunk_type * _chunk{};
202 using reference = bit_reference<is_const>;
203 using pointer = void;
212 bit_iterator() =
default;
218 explicit constexpr bit_iterator(maybe_const_chunk_type * chunk) noexcept : _chunk{chunk}, _chunk_position{0}
225 constexpr bit_iterator(bit_iterator<!is_const>
const & other)
noexcept
227 : _chunk{other._chunk}, _chunk_position{other._chunk_position}
235 constexpr reference operator*()
const noexcept
237 return reference{_chunk, _chunk_position};
243 return *((*this) +
count);
251 constexpr bit_iterator & operator++()
noexcept
253 _chunk += !
static_cast<bool>(to_local_chunk_position(++_chunk_position));
258 constexpr bit_iterator operator++(
int)
noexcept
260 bit_iterator tmp{*
this};
275 size_type updated_count = modulo_mask - to_local_chunk_position(_chunk_position) -
count;
276 _chunk_position = modulo_mask - to_local_chunk_position(updated_count);
277 _chunk -= to_chunk_position(updated_count);
282 _chunk += to_chunk_position(to_local_chunk_position(_chunk_position) +
count);
283 _chunk_position = to_local_chunk_position(_chunk_position +
count);
292 bit_iterator tmp{*
this};
303 constexpr bit_iterator & operator--()
noexcept
305 _chunk -= !
static_cast<bool>(to_local_chunk_position(--_chunk_position));
310 constexpr bit_iterator operator--(
int)
noexcept
312 bit_iterator tmp{*
this};
320 return *
this += -
count;
326 bit_iterator tmp{*
this};
331 template <
bool is_const_other>
332 constexpr difference_type operator-(bit_iterator<is_const_other> rhs)
const noexcept
334 return ((_chunk - rhs._chunk) << division_mask) -
335 to_local_chunk_position(rhs._chunk_position) +
336 to_local_chunk_position(_chunk_position);
344 template <
bool is_const_other>
345 bool operator==(bit_iterator<is_const_other>
const & rhs)
const
347 return _chunk == rhs._chunk
348 && (to_local_chunk_position(_chunk_position) == to_local_chunk_position(rhs._chunk_position));
352 template <
bool is_const_other>
355 if (
std::strong_ordering order = _chunk <=> rhs._chunk; order == std::strong_ordering::equivalent)
356 return to_local_chunk_position(_chunk_position) <=> to_local_chunk_position(rhs._chunk_position);
387 static constexpr size_type chunk_size =
sizeof(chunk_type) * CHAR_BIT;
389 static constexpr size_type modulo_mask = chunk_size - 1u;
470 template <std::input_iterator iterator_t, std::sentinel_for<iterator_t> sentinel_t>
472 constexpr void assign(iterator_t first, sentinel_t last)
476 tmp.
reserve(std::ranges::distance(first, last));
482 set_new_size(std::ranges::distance(
begin(),
end()));
533 [value = fill_chunk(bit)](chunk_type & chunk)
546 assert(position <
size());
548 return *std::ranges::next(
begin(), position);
554 assert(position <
size());
556 return *std::ranges::next(
begin(), position);
579 return (*
this)[
size() - 1u];
587 return (*
this)[
size() - 1u];
591 constexpr bool all() const noexcept
596 constexpr chunk_type mask = ~chunk_type{};
597 chunk_type
const *
const ptr = data();
600 for (
size_t i = 0; i < last_chunk; ++i)
605 return (ptr[last_chunk] | ~last_chunk_mask()) == mask;
609 constexpr bool any() const noexcept
614 chunk_type
const *
const ptr = data();
617 for (
size_t i = 0; i < last_chunk; ++i)
622 return (ptr[last_chunk] & last_chunk_mask()) != chunk_type{};
626 constexpr bool none() const noexcept
632 constexpr size_t count() const noexcept
637 chunk_type
const *
const ptr = data();
641 for (
size_t i = 0; i <
size; ++i)
659 constexpr bool empty() const noexcept
719 size_t const new_size =
size() + 1u;
722 set_new_size(new_size);
731 size_t const old_size =
size();
735 if (bit &&
size() > old_size)
749 assert(rhs.size() ==
size());
751 return binary_transform_impl(rhs,
752 [](
auto const & left_chunk,
auto const & right_chunk)
754 return left_chunk & right_chunk;
761 assert(rhs.size() ==
size());
763 return binary_transform_impl(rhs,
764 [](
auto const & left_chunk,
auto const & right_chunk)
766 return left_chunk | right_chunk;
773 assert(rhs.size() ==
size());
775 return binary_transform_impl(rhs,
776 [](
auto const & left_chunk,
auto const & right_chunk)
778 return left_chunk ^ right_chunk;
787 tmp.binary_transform_impl(*
this,
788 [](
auto const &,
auto const & right_chunk)
817 assert(rhs.size() ==
size());
819 return binary_transform_impl(rhs,
820 [](
auto const & left_chunk,
auto const & right_chunk)
822 return left_chunk & ~right_chunk;
830 [](chunk_type & chunk)
842 if (position >=
size())
846 (*this)[position].flip();
898 [[gnu::always_inline]]
inline constexpr chunk_type * data() noexcept
903 [[gnu::always_inline]]
inline constexpr chunk_type
const * data() const noexcept
915 template <cereal_archive archive_t>
916 void CEREAL_LOAD_FUNCTION_NAME(archive_t & archive)
922 size_t const vector_size = host_size_impl(_size);
924 resize_for_overwrite(vector_size);
928 for (
auto && v : *as_base())
933 archive(cereal::binary_data(data(), vector_size *
sizeof(chunk_type)));
938 template <cereal_archive archive_t>
939 void CEREAL_SAVE_FUNCTION_NAME(archive_t & archive)
const
948 for (
auto && v : *as_base())
953 archive(cereal::binary_data(data(),
base_t::size() *
sizeof(chunk_type)));
960#ifndef HIBF_UNINITIALISED_RESIZE
961 inline constexpr void resize_for_overwrite(
size_t const size)
968# if defined(_LIBCPP_VERSION)
969 inline void resize_for_overwrite(
size_t const size)
973 using allocator_t =
typename base_t::allocator_type;
978# pragma GCC diagnostic push
979# pragma GCC diagnostic ignored "-Wgnu-anonymous-struct"
980 _LIBCPP_COMPRESSED_PAIR(pointer, end_cap =
nullptr, allocator_type,
allocator);
981# pragma GCC diagnostic pop
984 static_assert(
sizeof(fake_vector) ==
sizeof(base_t));
985 static_assert(
alignof(fake_vector) ==
alignof(base_t));
990# if __has_feature(address_sanitizer)
996 fake_vector & vec =
reinterpret_cast<fake_vector &
>(*this);
997 vec.end = vec.begin +
size;
1001 inline constexpr void resize_for_overwrite(
size_t const size)
1006 this->_M_impl._M_finish = this->_M_impl._M_start +
size;
1012 template <
typename binary_operator_t>
1013 constexpr bit_vector & binary_transform_impl(
bit_vector const & rhs, binary_operator_t && op)
noexcept
1015 chunk_type *
const lhs_data = data();
1016 chunk_type
const *
const rhs_data = rhs.data();
1019 for (
size_t i = 0; i <
size; ++i)
1020 lhs_data[i] = op(lhs_data[i], rhs_data[i]);
1029 return chunks_needed(
count);
1033 constexpr void set_new_size(
size_type const new_size)
noexcept
1039 constexpr base_t
const * as_base() const noexcept
1041 return static_cast<base_t
const *
>(
this);
1045 constexpr base_t * as_base() noexcept
1047 return static_cast<base_t *
>(
this);
1053 return (
count + 63u) >> 6;
1063 constexpr chunk_type last_chunk_mask() const noexcept
1067 size_type const bits_in_last_chunk = to_local_chunk_position(
size());
1068 return bits_in_last_chunk ? (chunk_type{1u} << bits_in_last_chunk) - 1u : ~chunk_type{};
1072 constexpr chunk_type fill_chunk(
bool const bit)
const noexcept
1074 return (bit) ? ~chunk_type{} : chunk_type{};
1078 static constexpr size_type to_local_chunk_position(
size_type const position)
noexcept
1080 return position & modulo_mask;
1086 return position >> division_mask;
1102template <
typename archive_t>
1103struct specialize<archive_t, seqan::hibf::bit_vector, cereal::specialization::member_load_save>
T back_inserter(T... args)
An bit vector.
Definition bit_vector.hpp:68
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:727
constexpr reference back() noexcept
Access the last element.
Definition bit_vector.hpp:575
constexpr void swap(bit_vector &other) noexcept
Exchanges the contents of the container with those of others.
Definition bit_vector.hpp:851
allocator_t allocator_type
The allocator type to use.
Definition bit_vector.hpp:382
constexpr bit_vector operator~() const noexcept
Performs binary NOT.
Definition bit_vector.hpp:783
constexpr bit_vector & flip(size_type position)
Flips the bit at the given position.
Definition bit_vector.hpp:838
constexpr reference operator[](size_type const position) noexcept
Access specified element.
Definition bit_vector.hpp:544
constexpr bit_vector(allocator_type const &alloc=allocator_type{})
The default constructor which optionally sets the allocator.
Definition bit_vector.hpp:401
constexpr friend bit_vector operator|(bit_vector lhs, bit_vector const &rhs) noexcept
Performs binary OR.
Definition bit_vector.hpp:803
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:415
constexpr bit_vector & and_not(bit_vector const &rhs) noexcept
Computes the bitwise a &= ~b operator without an additional copy.
Definition bit_vector.hpp:815
constexpr size_type size() const noexcept
Returns the number of elements.
Definition bit_vector.hpp:653
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:426
constexpr size_t count() const noexcept
Returns the number of bits that are set to true.
Definition bit_vector.hpp:632
bit_iterator< false > iterator
The iterator over the bits.
Definition bit_vector.hpp:368
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:583
constexpr iterator end() noexcept
Returns an iterator to the end.
Definition bit_vector.hpp:880
constexpr friend bit_vector operator^(bit_vector lhs, bit_vector const &rhs) noexcept
Performs binary XOR.
Definition bit_vector.hpp:809
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:892
constexpr iterator begin() noexcept
Returns an iterator to the beginning.
Definition bit_vector.hpp:862
constexpr bit_vector & flip() noexcept
Flips all bits in-place.
Definition bit_vector.hpp:827
constexpr bool any() const noexcept
Checks if any bit is set to true.
Definition bit_vector.hpp:609
constexpr bool none() const noexcept
Checks if none of the bits is set to true.
Definition bit_vector.hpp:626
constexpr friend bit_vector operator&(bit_vector lhs, bit_vector const &rhs) noexcept
Performs binary AND.
Definition bit_vector.hpp:797
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:437
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:886
constexpr bit_vector & operator=(bit_vector &&)=default
Default.
bit_iterator< true > const_iterator
The const iterator over the bits.
Definition bit_vector.hpp:370
constexpr void assign(size_type const count, bool const bit)
Assigns values to the container.
Definition bit_vector.hpp:529
constexpr void assign(std::initializer_list< bool > const &ilist)
Assigns values to the container.
Definition bit_vector.hpp:504
constexpr bool all() const noexcept
Checks if all bits are set to true.
Definition bit_vector.hpp:591
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:868
constexpr void push_back(bool bit)
Adds an element to the end.
Definition bit_vector.hpp:717
size_t size_type
The size_type.
Definition bit_vector.hpp:378
constexpr bit_vector & operator|=(bit_vector const &rhs) noexcept
Performs binary OR between this and rhs.
Definition bit_vector.hpp:759
constexpr bool empty() const noexcept
Checks wether the container is empty.
Definition bit_vector.hpp:659
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:472
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:874
constexpr bit_vector & operator^=(bit_vector const &rhs) noexcept
Performs binary XOR between this and rhs.
Definition bit_vector.hpp:771
constexpr void reserve(size_type const new_capacity)
Reserves storage.
Definition bit_vector.hpp:687
constexpr bit_vector & operator&=(bit_vector const &rhs) noexcept
Performs binary AND between this and rhs.
Definition bit_vector.hpp:747
constexpr void clear() noexcept
Erases all elements. After this call, size() returns zero. capacity() remains unchanged.
Definition bit_vector.hpp:740
constexpr size_type capacity() const noexcept
Returns the capacity.
Definition bit_vector.hpp:665
constexpr const_reference operator[](size_type const position) const noexcept
Access specified element.
Definition bit_vector.hpp:552
Definition concepts.hpp:27