SeqAn3  3.0.0
The Modern C++ library for sequence analysis.
bitcompressed_vector.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2019, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <type_traits>
16 
17 #include <sdsl/int_vector.hpp>
18 
27 #include <seqan3/std/concepts>
28 #include <seqan3/std/iterator>
29 #include <seqan3/std/ranges>
30 
31 namespace seqan3
32 {
33 
34 // forward
35 class debug_stream_type;
36 
65 template <Alphabet alphabet_type>
67  requires std::is_same_v<alphabet_type, std::remove_reference_t<alphabet_type>>
70 {
71 private:
73  static constexpr size_t bits_per_letter = std::ceil(std::log2(alphabet_size<alphabet_type>));
74 
75  static_assert(bits_per_letter <= 64, "Alphabet must be representable in at most 64bit.");
76 
78  using data_type = sdsl::int_vector<bits_per_letter>;
79 
81  data_type data;
82 
85  class reference_proxy_type : public alphabet_proxy<reference_proxy_type, alphabet_type>
86  {
87  private:
91  friend base_t;
92 
95  static uint8_t constexpr safe_bits_per_letter = (bits_per_letter == 8 ||
96  bits_per_letter == 16 ||
97  bits_per_letter == 32) ? 64 : bits_per_letter;
98 
100  using internal_proxy_type = sdsl::int_vector_reference<sdsl::int_vector<safe_bits_per_letter>>;
102  ranges::semiregular_t<internal_proxy_type> internal_proxy;
103 
105  constexpr void on_update() noexcept
106  {
107  internal_proxy.get() = static_cast<base_t &>(*this).to_rank();
108  }
109 
110  public:
111  // Import from base:
112  using base_t::operator=;
113 
117  constexpr reference_proxy_type() noexcept = default;
118  constexpr reference_proxy_type(reference_proxy_type const &) noexcept = default;
119  constexpr reference_proxy_type(reference_proxy_type &&) noexcept = default;
120  constexpr reference_proxy_type & operator=(reference_proxy_type const &) noexcept = default;
121  constexpr reference_proxy_type & operator=(reference_proxy_type &&) noexcept = default;
122  ~reference_proxy_type() noexcept = default;
123 
125  reference_proxy_type(internal_proxy_type const & internal) noexcept :
126  internal_proxy{internal}
127  {
128  static_cast<base_t &>(*this).assign_rank(internal);
129  }
131  };
132 
135  //NOTE(h-2): it is entirely unclear to me why we need this
136  template <typename t>
137  requires std::is_same_v<value_type_t<remove_cvref_t<t>>, alphabet_type>
138  static constexpr bool has_same_value_type_v = true;
140 
141 public:
145  using value_type = alphabet_type;
150  reference_proxy_type>;
152  using const_reference = alphabet_type;
154  using iterator = detail::random_access_iterator<bitcompressed_vector>;
156  using const_iterator = detail::random_access_iterator<bitcompressed_vector const>;
162 
164  // this signals to range-v3 that something is a container :|
165  using allocator_type = void;
167 
171  bitcompressed_vector() = default;
172  constexpr bitcompressed_vector(bitcompressed_vector const &) = default;
173  constexpr bitcompressed_vector(bitcompressed_vector &&) = default;
174  constexpr bitcompressed_vector & operator=(bitcompressed_vector const &) = default;
175  constexpr bitcompressed_vector & operator=(bitcompressed_vector &&) = default;
176  ~bitcompressed_vector() = default;
177 
191  template <std::ranges::InputRange other_range_t>
193  requires has_same_value_type_v<other_range_t>
195  explicit bitcompressed_vector(other_range_t && range) :
197  {}
198 
211  bitcompressed_vector(size_type const count, value_type const value) :
212  data(count, to_rank(value))
213  {}
214 
230  template <std::ForwardIterator begin_iterator_type, std::Sentinel<begin_iterator_type> end_iterator_type>
231  bitcompressed_vector(begin_iterator_type begin_it, end_iterator_type end_it)
235  {
236  insert(cend(), begin_it, end_it);
237  }
238 
251  bitcompressed_vector(std::begin(ilist), std::end(ilist))
252  {}
253 
266  {
267  assign(std::begin(ilist), std::end(ilist));
268  return *this;
269  }
270 
284  template <std::ranges::InputRange other_range_t>
285  void assign(other_range_t && range)
289  {
290  bitcompressed_vector rhs{std::forward<other_range_t>(range)};
291  swap(rhs);
292  }
293 
306  void assign(size_type const count, value_type const value)
307  {
308  bitcompressed_vector rhs{count, value};
309  swap(rhs);
310  }
311 
327  template <std::ForwardIterator begin_iterator_type, std::Sentinel<begin_iterator_type> end_iterator_type>
328  void assign(begin_iterator_type begin_it, end_iterator_type end_it)
332  {
333  bitcompressed_vector rhs{begin_it, end_it};
334  swap(rhs);
335  }
336 
349  {
350  assign(std::begin(ilist), std::end(ilist));
351  }
352 
354 
371  iterator begin() noexcept
372  {
373  return iterator{*this};
374  }
375 
377  const_iterator begin() const noexcept
378  {
379  return const_iterator{*this};
380  }
381 
383  const_iterator cbegin() const noexcept
384  {
385  return const_iterator{*this};
386  }
387 
401  iterator end() noexcept
402  {
403  return iterator{*this, size()};
404  }
405 
407  const_iterator end() const noexcept
408  {
409  return const_iterator{*this, size()};
410  }
411 
413  const_iterator cend() const noexcept
414  {
415  return const_iterator{*this, size()};
416  }
418 
436  {
437  if (i >= size()) // [[unlikely]]
438  {
439  throw std::out_of_range{"Trying to access element behind the last in bitcompressed_vector."};
440  }
441  return (*this)[i];
442  }
443 
445  const_reference at(size_type const i) const
446  {
447  if (i >= size()) // [[unlikely]]
448  {
449  throw std::out_of_range{"Trying to access element behind the last in bitcompressed_vector."};
450  }
451  return (*this)[i];
452  }
453 
469  reference operator[](size_type const i) noexcept
470  {
471  assert(i < size());
472  return data[i];
473  }
474 
476  const_reference operator[](size_type const i) const noexcept
477  {
478  assert(i < size());
479  return assign_rank_to(data[i], const_reference{});
480  }
481 
495  reference front() noexcept
496  {
497  assert(size() > 0);
498  return (*this)[0];
499  }
500 
502  const_reference front() const noexcept
503  {
504  assert(size() > 0);
505  return (*this)[0];
506  }
507 
521  reference back() noexcept
522  {
523  assert(size() > 0);
524  return (*this)[size()-1];
525  }
526 
528  const_reference back() const noexcept
529  {
530  assert(size() > 0);
531  return (*this)[size()-1];
532  }
533 
548  bool empty() const noexcept
549  {
550  return size() == 0;
551  }
552 
564  size_type size() const noexcept
565  {
566  return data.size();
567  }
568 
583  size_type max_size() const noexcept
584  {
585  return data.max_size();
586  }
587 
603  size_type capacity() const noexcept
604  {
605  return data.capacity();
606  }
607 
626  void reserve(size_type const new_cap)
627  {
628  data.reserve(new_cap);
629  }
630 
647  {
648  data.shrink_to_fit();
649  }
651 
666  void clear() noexcept
667  {
668  data.clear();
669  }
670 
690  {
691  return insert(pos, 1, value);
692  }
693 
713  iterator insert(const_iterator pos, size_type const count, value_type const value)
714  {
715  auto const pos_as_num = std::distance(cbegin(), pos); // we want to insert BEFORE this position
716 
717  data.insert(data.begin() + pos_as_num, count, to_rank(value));
718 
719  return begin() + pos_as_num;
720  }
721 
746  template <std::ForwardIterator begin_iterator_type, std::Sentinel<begin_iterator_type> end_iterator_type>
747  iterator insert(const_iterator pos, begin_iterator_type begin_it, end_iterator_type end_it)
751  {
752  auto const pos_as_num = std::distance(cbegin(), pos);
753 
755  | view::convert<value_type>
756  | view::to_rank;
757  data.insert(data.begin() + pos_as_num, seqan3::begin(v), seqan3::end(v));
758 
759  return begin() + pos_as_num;
760  }
761 
781  {
782  return insert(pos, ilist.begin(), ilist.end());
783  }
784 
805  {
806  if (begin_it >= end_it) // [[unlikely]]
807  return begin() + std::distance(cbegin(), end_it);
808 
809  auto const begin_it_pos = std::distance(cbegin(), begin_it);
810  auto const end_it_pos = std::distance(cbegin(), end_it);
811 
812  data.erase(data.cbegin() + begin_it_pos,
813  data.cbegin() + end_it_pos);
814 
815  return begin() + begin_it_pos;
816  }
817 
838  {
839  return erase(pos, pos + 1);
840  }
841 
857  void push_back(value_type const value)
858  {
859  data.push_back(to_rank(value));
860  }
861 
878  void pop_back()
879  {
880  assert(size() > 0);
881  data.pop_back();
882  }
883 
910  void resize(size_type const count)
911  {
912  assert(count < max_size());
913  data.resize(count);
914  }
915 
920  void resize(size_type const count, value_type const value)
921  {
922  assert(count < max_size());
923  data.resize(count, to_rank(value));
924  }
925 
937  constexpr void swap(bitcompressed_vector & rhs) noexcept
938  {
939  std::swap(data, rhs.data);
940  }
941 
943  constexpr void swap(bitcompressed_vector && rhs) noexcept
944  {
945  std::swap(data, rhs.data);
946  }
948 
961  friend constexpr void swap(bitcompressed_vector & lhs, bitcompressed_vector & rhs) noexcept
962  {
963  std::swap(lhs, rhs);
964  }
965 
967  friend constexpr void swap(bitcompressed_vector && lhs, bitcompressed_vector && rhs) noexcept
968  {
969  std::swap(lhs, rhs);
970  }
972 
977  constexpr bool operator==(bitcompressed_vector const & rhs) const noexcept
979  {
980  return data == rhs.data;
981  }
982 
984  constexpr bool operator!=(bitcompressed_vector const & rhs) const noexcept
985  {
986  return data != rhs.data;
987  }
988 
990  constexpr bool operator<(bitcompressed_vector const & rhs) const noexcept
991  {
992  return data < rhs.data;
993  }
994 
996  constexpr bool operator>(bitcompressed_vector const & rhs) const noexcept
997  {
998  return data > rhs.data;
999  }
1000 
1002  constexpr bool operator<=(bitcompressed_vector const & rhs) const noexcept
1003  {
1004  return data <= rhs.data;
1005  }
1006 
1008  constexpr bool operator>=(bitcompressed_vector const & rhs) const noexcept
1009  {
1010  return data >= rhs.data;
1011  }
1013 
1021  template <CerealArchive archive_t>
1022  void CEREAL_SERIALIZE_FUNCTION_NAME(archive_t & archive)
1023  {
1024  archive(data); //TODO: data not yet serialisable
1025  }
1027 };
1028 
1029 } // namespace seqan3
void pop_back()
Removes the last element of the container.
Definition: bitcompressed_vector.hpp:878
reference front() noexcept
Return the first element. Calling front on an empty container is undefined.
Definition: bitcompressed_vector.hpp:495
iterator end() noexcept
Returns an iterator to the element following the last element of the container.
Definition: bitcompressed_vector.hpp:401
::ranges::subrange< it_t, sen_t, k > subrange
Create a view from a pair of iterator and sentinel.
Definition: ranges:339
void assign(other_range_t &&range)
Assign from a different range.
Definition: bitcompressed_vector.hpp:285
T distance(T... args)
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:207
void clear() noexcept
Removes all elements from the container.
Definition: bitcompressed_vector.hpp:666
T ceil(T... args)
A CRTP-base that eases the definition of proxy types returned in place of regular alphabets...
Definition: alphabet_proxy.hpp:131
T swap(T... args)
constexpr void swap(bitcompressed_vector &&rhs) noexcept
Swap contents with another instance.
Definition: bitcompressed_vector.hpp:943
void push_back(value_type const value)
Appends the given element value to the end of the container.
Definition: bitcompressed_vector.hpp:857
Provides C++20 additions to the <iterator> header.
Provides various shortcuts for common std::ranges functions.
constexpr bool operator>(bitcompressed_vector const &rhs) const noexcept
Checks whether *this is greater than rhs.
Definition: bitcompressed_vector.hpp:996
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:103
const_reference back() const noexcept
Return the last element.
Definition: bitcompressed_vector.hpp:528
const_iterator cend() const noexcept
Returns an iterator to the element following the last element of the container.
Definition: bitcompressed_vector.hpp:413
constexpr bool operator!=(bitcompressed_vector const &rhs) const noexcept
Checks whether *this is not equal to rhs.
Definition: bitcompressed_vector.hpp:984
~bitcompressed_vector()=default
Defaulted.
SeqAn specific customisations in the standard namespace.
constexpr bool operator<(bitcompressed_vector const &rhs) const noexcept
Checks whether *this is less than rhs.
Definition: bitcompressed_vector.hpp:990
iterator insert(const_iterator pos, begin_iterator_type begin_it, end_iterator_type end_it)
Inserts elements from range [begin_it, end_it) before position in the container.
Definition: bitcompressed_vector.hpp:747
T end(T... args)
Provides seqan3::view::convert.
size_type max_size() const noexcept
Returns the maximum number of elements the container is able to hold due to system or library impleme...
Definition: bitcompressed_vector.hpp:583
Provides the seqan3::detail::random_access_iterator class.
constexpr bool operator<=(bitcompressed_vector const &rhs) const noexcept
Checks whether *this is less than or equal to rhs.
Definition: bitcompressed_vector.hpp:1002
The main SeqAn3 namespace.
size_type_t< data_type > size_type
An unsigned integer type (usually std::size_t)
Definition: bitcompressed_vector.hpp:160
reference at(size_type const i)
Return the i-th element.
Definition: bitcompressed_vector.hpp:435
iterator insert(const_iterator pos, value_type const value)
Inserts value before position in the container.
Definition: bitcompressed_vector.hpp:689
typename difference_type< t >::type difference_type_t
Shortcut for seqan3::difference_type (TransformationTrait shortcut).
Definition: pre.hpp:166
reference back() noexcept
Return the last element.
Definition: bitcompressed_vector.hpp:521
detail::random_access_iterator< bitcompressed_vector > iterator
The iterator type of this container (a random access iterator).
Definition: bitcompressed_vector.hpp:154
friend constexpr void swap(bitcompressed_vector &&lhs, bitcompressed_vector &&rhs) noexcept
Definition: bitcompressed_vector.hpp:967
bitcompressed_vector(std::initializer_list< value_type > ilist)
Construct from std::initializer_list.
Definition: bitcompressed_vector.hpp:250
void assign(size_type const count, value_type const value)
Assign with count times value.
Definition: bitcompressed_vector.hpp:306
const_iterator end() const noexcept
Returns an iterator to the element following the last element of the container.
Definition: bitcompressed_vector.hpp:407
constexpr bool operator==(bitcompressed_vector const &rhs) const noexcept
Checks whether *this is equal to rhs.
Definition: bitcompressed_vector.hpp:978
iterator insert(const_iterator pos, std::initializer_list< value_type > const &ilist)
Inserts elements from initializer list before position in the container.
Definition: bitcompressed_vector.hpp:780
Provides seqan3::view::to_rank.
reference operator[](size_type const i) noexcept
Return the i-th element.
Definition: bitcompressed_vector.hpp:469
Provides various type traits.
constexpr bitcompressed_vector & operator=(bitcompressed_vector const &)=default
Defaulted.
The Concepts library.
const_reference at(size_type const i) const
Return the i-th element.
Definition: bitcompressed_vector.hpp:445
const_reference operator[](size_type const i) const noexcept
Return the i-th element.
Definition: bitcompressed_vector.hpp:476
Adaptations of concepts from the Ranges TS.
bitcompressed_vector(other_range_t &&range)
Construct from a different range.
Definition: bitcompressed_vector.hpp:195
Free function/type trait wrappers for alphabets with member functions/types.
Refines seqan3::Alphabet and adds assignability.
detail::random_access_iterator< bitcompressed_vector const > const_iterator
The const_iterator type of this container (a random access iterator).
Definition: bitcompressed_vector.hpp:156
::ranges::begin begin
Alias for ranges::begin. Returns an iterator to the beginning of a range.
Definition: ranges:174
void assign(begin_iterator_type begin_it, end_iterator_type end_it)
Assign from pair of iterators.
Definition: bitcompressed_vector.hpp:328
alphabet_type value_type
Equals the alphabet_type.
Definition: bitcompressed_vector.hpp:146
Adaptions of concepts from the Cereal library.
The concept std::CommonReference<T, U> specifies that two types T and U share a common reference type...
const_reference front() const noexcept
Return the first element. Calling front on an empty container is undefined.
Definition: bitcompressed_vector.hpp:502
friend constexpr void swap(bitcompressed_vector &lhs, bitcompressed_vector &rhs) noexcept
Swap contents with another instance.
Definition: bitcompressed_vector.hpp:961
iterator erase(const_iterator begin_it, const_iterator end_it)
Removes specified elements from the container.
Definition: bitcompressed_vector.hpp:804
bitcompressed_vector(begin_iterator_type begin_it, end_iterator_type end_it)
Construct from pair of iterators.
Definition: bitcompressed_vector.hpp:231
typename size_type< t >::type size_type_t
Shortcut for seqan3::size_type (TransformationTrait shortcut).
Definition: pre.hpp:195
bitcompressed_vector(size_type const count, value_type const value)
Construct with count times value.
Definition: bitcompressed_vector.hpp:211
void reserve(size_type const new_cap)
Increase the capacity to a value that&#39;s greater or equal to new_cap.
Definition: bitcompressed_vector.hpp:626
bitcompressed_vector & operator=(std::initializer_list< value_type > ilist)
Assign from std::initializer_list.
Definition: bitcompressed_vector.hpp:265
T begin(T... args)
iterator insert(const_iterator pos, size_type const count, value_type const value)
Inserts count copies of value before position in the container.
Definition: bitcompressed_vector.hpp:713
size_type capacity() const noexcept
Returns the number of elements that the container has currently allocated space for.
Definition: bitcompressed_vector.hpp:603
const_iterator cbegin() const noexcept
Returns an iterator to the first element of the container.
Definition: bitcompressed_vector.hpp:383
A space-optimised version of std::vector that compresses multiple letters into a single byte...
Definition: bitcompressed_vector.hpp:69
Provides seqan3::view::to_char.
void shrink_to_fit()
Requests the removal of unused capacity.
Definition: bitcompressed_vector.hpp:646
size_type size() const noexcept
Returns the number of elements in the container, i.e. std::distance(begin(), end()).
Definition: bitcompressed_vector.hpp:564
constexpr bool operator>=(bitcompressed_vector const &rhs) const noexcept
Checks whether *this is greater than or equal to rhs.
Definition: bitcompressed_vector.hpp:1008
typename reference< t >::type reference_t
Shortcut for seqan3::reference (TransformationTrait shortcut).
Definition: pre.hpp:77
void resize(size_type const count)
Resizes the container to contain count elements.
Definition: bitcompressed_vector.hpp:910
iterator begin() noexcept
Returns an iterator to the first element of the container.
Definition: bitcompressed_vector.hpp:371
bitcompressed_vector()=default
Defaulted.
difference_type_t< data_type > difference_type
A signed integer type (usually std::ptrdiff_t)
Definition: bitcompressed_vector.hpp:158
const_iterator begin() const noexcept
Returns an iterator to the first element of the container.
Definition: bitcompressed_vector.hpp:377
bool empty() const noexcept
Checks whether the container is empty.
Definition: bitcompressed_vector.hpp:548
alphabet_type const_reference
Equals the alphabet_type / value_type.
Definition: bitcompressed_vector.hpp:152
::ranges::end end
Alias for ranges::end. Returns an iterator to the end of a range.
Definition: ranges:179
void assign(std::initializer_list< value_type > ilist)
Assign from std::initializer_list.
Definition: bitcompressed_vector.hpp:348
void resize(size_type const count, value_type const value)
Resizes the container to contain count elements.
Definition: bitcompressed_vector.hpp:920
auto const to_rank
A view that calls seqan3::to_rank() on each element in the input range.
Definition: to_rank.hpp:68
iterator erase(const_iterator pos)
Removes specified elements from the container.
Definition: bitcompressed_vector.hpp:837
constexpr void swap(bitcompressed_vector &rhs) noexcept
Swap contents with another instance.
Definition: bitcompressed_vector.hpp:937