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)
122 return *
this = bool(other);
124 bit_reference & operator=(bit_reference && other)
noexcept
126 return *
this = bool(other);
133 constexpr bit_reference & operator=(
bool const bit)
noexcept
135 bit ? set() : clear();
142 constexpr bit_reference
const & operator=(
bool const bit)
const noexcept
145 bit ? set() : clear();
151 constexpr operator bool()
const noexcept
153 return *_chunk & _chunk_mask;
157 constexpr bit_reference & flip()
noexcept
159 (*this) ? clear() : set();
165 constexpr void set()
noexcept
167 *_chunk |= _chunk_mask;
171 constexpr void clear()
noexcept
173 *_chunk &= ~_chunk_mask;
180 template <
bool is_const>
186 friend class bit_iterator;
191 maybe_const_chunk_type * _chunk{};
199 using reference = bit_reference<is_const>;
200 using pointer = void;
209 bit_iterator() =
default;
215 explicit constexpr bit_iterator(maybe_const_chunk_type * chunk) noexcept : _chunk{chunk}, _chunk_position{0}
222 constexpr bit_iterator(bit_iterator<!is_const>
const & other)
noexcept
224 : _chunk{other._chunk}, _chunk_position{other._chunk_position}
232 constexpr reference operator*()
const noexcept
234 return reference{_chunk, _chunk_position};
240 return *((*this) + count);
248 constexpr bit_iterator & operator++()
noexcept
250 _chunk += !
static_cast<bool>(to_local_chunk_position(++_chunk_position));
255 constexpr bit_iterator operator++(
int)
noexcept
257 bit_iterator tmp{*
this};
263 constexpr bit_iterator & operator+=(
difference_type const count)
noexcept
272 size_type updated_count = modulo_mask - to_local_chunk_position(_chunk_position) - count;
273 _chunk_position = modulo_mask - to_local_chunk_position(updated_count);
274 _chunk -= to_chunk_position(updated_count);
279 _chunk += to_chunk_position(to_local_chunk_position(_chunk_position) + count);
280 _chunk_position = to_local_chunk_position(_chunk_position + count);
287 constexpr bit_iterator operator+(
difference_type const count)
const noexcept
289 bit_iterator tmp{*
this};
294 friend constexpr bit_iterator operator+(
difference_type const count, bit_iterator rhs)
noexcept
300 constexpr bit_iterator & operator--()
noexcept
302 _chunk -= !
static_cast<bool>(to_local_chunk_position(--_chunk_position));
307 constexpr bit_iterator operator--(
int)
noexcept
309 bit_iterator tmp{*
this};
315 constexpr bit_iterator & operator-=(
difference_type const count)
noexcept
317 return *
this += -count;
321 constexpr bit_iterator operator-(
difference_type const count)
const noexcept
323 bit_iterator tmp{*
this};
328 template <
bool is_const_other>
329 constexpr difference_type operator-(bit_iterator<is_const_other> rhs)
const noexcept
331 return ((_chunk - rhs._chunk) << division_mask) -
332 to_local_chunk_position(rhs._chunk_position) +
333 to_local_chunk_position(_chunk_position);
341 template <
bool is_const_other>
342 bool operator==(bit_iterator<is_const_other>
const & rhs)
const
344 return _chunk == rhs._chunk
345 && (to_local_chunk_position(_chunk_position) == to_local_chunk_position(rhs._chunk_position));
349 template <
bool is_const_other>
352 if (
std::strong_ordering order = _chunk <=> rhs._chunk; order == std::strong_ordering::equivalent)
353 return to_local_chunk_position(_chunk_position) <=> to_local_chunk_position(rhs._chunk_position);
384 static constexpr size_type chunk_size =
sizeof(chunk_type) * CHAR_BIT;
386 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
591 constexpr chunk_type mask = ~static_cast<chunk_type>(0);
593 [](chunk_type
const & chunk)
595 return chunk == mask;
600 constexpr bool any() const noexcept
602 constexpr chunk_type mask =
static_cast<chunk_type
>(0);
604 [](chunk_type
const & chunk)
611 constexpr bool none() const noexcept
627 constexpr bool empty() const noexcept
687 size_t const new_size =
size() + 1u;
690 set_new_size(new_size);
699 size_t const old_size =
size();
703 if (bit &&
size() > old_size)
717 assert(rhs.size() ==
size());
719 return binary_transform_impl(rhs,
720 [](
auto const & left_chunk,
auto const & right_chunk)
722 return left_chunk & right_chunk;
729 assert(rhs.size() ==
size());
731 return binary_transform_impl(rhs,
732 [](
auto const & left_chunk,
auto const & right_chunk)
734 return left_chunk | right_chunk;
741 assert(rhs.size() ==
size());
743 return binary_transform_impl(rhs,
744 [](
auto const & left_chunk,
auto const & right_chunk)
746 return left_chunk ^ right_chunk;
755 tmp.binary_transform_impl(*
this,
756 [](
auto const &,
auto const & right_chunk)
785 assert(rhs.size() ==
size());
787 return binary_transform_impl(rhs,
788 [](
auto const & left_chunk,
auto const & right_chunk)
790 return left_chunk & ~right_chunk;
798 [](chunk_type & chunk)
810 if (position >=
size())
814 (*this)[position].flip();
883 template <cereal_archive archive_t>
884 void CEREAL_LOAD_FUNCTION_NAME(archive_t & archive)
890 size_t const vector_size = host_size_impl(_size);
892 resize_for_overwrite(vector_size);
896 for (
auto && v : *as_base())
901 archive(cereal::binary_data(data(), vector_size *
sizeof(chunk_type)));
906 template <cereal_archive archive_t>
907 void CEREAL_SAVE_FUNCTION_NAME(archive_t & archive)
const
916 for (
auto && v : *as_base())
921 archive(cereal::binary_data(data(),
base_t::size() *
sizeof(chunk_type)));
928#ifndef HIBF_UNINITIALISED_RESIZE
936# if defined(_LIBCPP_VERSION)
937 inline void resize_for_overwrite(
size_t const size)
941 using allocator_t =
typename base_t::allocator_type;
949 static_assert(
sizeof(fake_vector) ==
sizeof(base_t));
950 static_assert(
alignof(fake_vector) ==
alignof(base_t));
956# ifndef _LIBCPP_HAS_NO_ASAN
957 __sanitizer_annotate_contiguous_container(
base_t::data(),
963 fake_vector & vec =
reinterpret_cast<fake_vector &
>(*this);
964 vec.end = vec.begin +
size;
973 this->_M_impl._M_finish = this->_M_impl._M_start +
size;
979 template <
typename binary_operator_t>
980 constexpr bit_vector & binary_transform_impl(
bit_vector const & rhs, binary_operator_t && op)
noexcept
982 chunk_type *
const lhs_data = data();
983 chunk_type
const *
const rhs_data = rhs.data();
986 for (
size_t i = 0; i <
size; ++i)
987 lhs_data[i] = op(lhs_data[i], rhs_data[i]);
996 return chunks_needed(count);
1000 constexpr void set_new_size(
size_type const new_size)
noexcept
1006 constexpr base_t
const * as_base() const noexcept
1008 return static_cast<base_t
const *
>(
this);
1012 constexpr base_t * as_base() noexcept
1014 return static_cast<base_t *
>(
this);
1020 return (count + 63u) >> 6;
1024 constexpr chunk_type fill_chunk(
bool const bit)
const noexcept
1026 return (bit) ? ~chunk_type{} : chunk_type{};
1030 static constexpr size_type to_local_chunk_position(
size_type const position)
noexcept
1032 return position & modulo_mask;
1038 return position >> division_mask;
1054template <
typename archive_t>
1055struct 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:695
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:819
allocator_t allocator_type
The allocator type to use.
Definition bit_vector.hpp:379
constexpr bit_vector operator~() const noexcept
Performs binary NOT.
Definition bit_vector.hpp:751
constexpr bit_vector & flip(size_type position)
Flips the bit at the given position.
Definition bit_vector.hpp:806
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:398
constexpr friend bit_vector operator|(bit_vector lhs, bit_vector const &rhs) noexcept
Performs binary OR.
Definition bit_vector.hpp:771
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:783
constexpr size_type size() const noexcept
Returns the number of elements.
Definition bit_vector.hpp:621
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:423
bit_iterator< false > iterator
The iterator over the bits.
Definition bit_vector.hpp:365
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:848
constexpr friend bit_vector operator^(bit_vector lhs, bit_vector const &rhs) noexcept
Performs binary XOR.
Definition bit_vector.hpp:777
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:860
constexpr iterator begin() noexcept
Returns an iterator to the beginning.
Definition bit_vector.hpp:830
constexpr bit_vector & flip() noexcept
Flips all bits in-place.
Definition bit_vector.hpp:795
constexpr bool any() const noexcept
Checks if any bit is set to true.
Definition bit_vector.hpp:600
constexpr bool none() const noexcept
Checks if none of the bits is set to true.
Definition bit_vector.hpp:611
constexpr friend bit_vector operator&(bit_vector lhs, bit_vector const &rhs) noexcept
Performs binary AND.
Definition bit_vector.hpp:765
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:854
constexpr bit_vector & operator=(bit_vector &&)=default
Default.
bit_iterator< true > const_iterator
The const iterator over the bits.
Definition bit_vector.hpp:367
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:836
constexpr void push_back(bool bit)
Adds an element to the end.
Definition bit_vector.hpp:685
size_t size_type
The size_type.
Definition bit_vector.hpp:375
constexpr bit_vector & operator|=(bit_vector const &rhs) noexcept
Performs binary OR between this and rhs.
Definition bit_vector.hpp:727
constexpr bool empty() const noexcept
Checks wether the container is empty.
Definition bit_vector.hpp:627
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:842
constexpr bit_vector & operator^=(bit_vector const &rhs) noexcept
Performs binary XOR between this and rhs.
Definition bit_vector.hpp:739
constexpr void reserve(size_type const new_capacity)
Reserves storage.
Definition bit_vector.hpp:655
constexpr bit_vector & operator&=(bit_vector const &rhs) noexcept
Performs binary AND between this and rhs.
Definition bit_vector.hpp:715
constexpr void clear() noexcept
Erases all elements. After this call, size() returns zero. capacity() remains unchanged.
Definition bit_vector.hpp:708
constexpr size_type capacity() const noexcept
Returns the capacity.
Definition bit_vector.hpp:633
constexpr const_reference operator[](size_type const position) const noexcept
Access specified element.
Definition bit_vector.hpp:550
Definition concepts.hpp:25