SeqAn3  3.0.1
The Modern C++ library for sequence analysis.
bi_fm_index_cursor.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, 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 <array>
16 
17 #include <sdsl/suffix_trees.hpp>
18 
19 #include <seqan3/alphabet/all.hpp>
24 #include <seqan3/std/ranges>
25 
26 namespace seqan3
27 {
28 
54 template <typename index_t>
56 {
57 public:
59  using index_type = index_t;
60 
64  using size_type = typename index_type::size_type;
67 
71  using fwd_cursor = fm_index_cursor<fm_index<typename index_type::alphabet_type,
73  index_type::text_layout_mode,
74  typename index_type::sdsl_index_type>>;
76  using rev_cursor = fm_index_cursor<fm_index<typename index_type::alphabet_type,
77  index_type::text_layout_mode,
78  typename index_type::sdsl_index_type>>;
80 
81 private:
83  using sdsl_char_type = typename index_type::sdsl_char_type;
85  using sdsl_sigma_type = typename index_type::sdsl_sigma_type;
87  using index_alphabet_type = typename index_t::alphabet_type;
88 
90  index_type const * index;
91 
95  size_type fwd_lb;
98  size_type fwd_rb;
100  size_type rev_lb;
102  size_type rev_rb;
103  //\}
104 
106  sdsl_sigma_type sigma;
107 
114  // parent_* and _last_char only have to be stored for the (unidirectional) cursor that has been used last for
115  // extend_right() or cycle_back() resp. extend_left() or cycle_front(), (i.e. either fwd or rev). Thus there is no
116  // need to store it twice. Once the cursor is switched, the information becomes invalid anyway.
117 
119  size_type parent_lb;
121  size_type parent_rb;
123  sdsl_char_type _last_char;
124  //\}
125 
127  size_type depth; // equal for both cursors. only stored once
128 
129  // supports assertions to check whether cycle_back() resp. cycle_front() is called on the same direction as the last
130  // extend_right([...]) resp. extend_left([...])
131 #ifndef NDEBUG
132  // cycle_back() and cycle_front()
134  bool fwd_cursor_last_used = false;
135 #endif
136 
138  size_type offset() const noexcept
139  {
140  assert(index->size() > query_length());
141  return index->size() - query_length() - 1; // since the string is reversed during construction
142  }
143 
145  template <detail::sdsl_index csa_t>
146  bool bidirectional_search(csa_t const & csa, sdsl_char_type const c,
147  size_type & l_fwd, size_type & r_fwd,
148  size_type & l_bwd, size_type & r_bwd) const noexcept
149  {
150  assert((l_fwd <= r_fwd) && (r_fwd < csa.size()));
151  assert(r_fwd + 1 >= l_fwd);
152  assert(r_bwd + 1 - l_bwd == r_fwd + 1 - l_fwd);
153 
154  size_type _l_fwd, _r_fwd, _l_bwd, _r_bwd;
155 
156  size_type cc = c;
158  {
159  cc = csa.char2comp[c];
160  if (cc == 0 && c > 0) // [[unlikely]]
161  return false;
162  }
163 
164  size_type const c_begin = csa.C[cc];
165  if (r_fwd + 1 - l_fwd == csa.size()) // [[unlikely]]
166  {
167  _l_fwd = c_begin;
168  _l_bwd = c_begin;
169  _r_fwd = csa.C[cc + 1] - 1;
170  _r_bwd = _r_fwd;
171  // if we use not the plain_byte_alphabet, we could return always return true here
172  }
173  else
174  {
175  auto const r_s_b = csa.wavelet_tree.lex_count(l_fwd, r_fwd + 1, c);
176  size_type const rank_l = std::get<0>(r_s_b);
177  size_type const s = std::get<1>(r_s_b), b = std::get<2>(r_s_b);
178  size_type const rank_r = r_fwd - l_fwd - s - b + rank_l;
179  _l_fwd = c_begin + rank_l;
180  _r_fwd = c_begin + rank_r;
181  _l_bwd = l_bwd + s;
182  _r_bwd = r_bwd - b;
183  }
184 
185  if (_r_fwd >= _l_fwd)
186  {
187  l_fwd = _l_fwd;
188  r_fwd = _r_fwd;
189  l_bwd = _l_bwd;
190  r_bwd = _r_bwd;
191  assert(r_fwd + 1 >= l_fwd);
192  assert(r_bwd + 1 - l_bwd == r_fwd + 1 - l_fwd);
193  return true;
194  }
195  return false;
196  }
197 
199  template <detail::sdsl_index csa_t>
200  bool bidirectional_search_cycle(csa_t const & csa, sdsl_char_type const c,
201  size_type const l_parent, size_type const r_parent,
202  size_type & l_fwd, size_type & r_fwd,
203  size_type & l_bwd, size_type & r_bwd) const noexcept
204  {
205  assert((l_parent <= r_parent) && (r_parent < csa.size()));
206 
207  size_type c_begin;
209  c_begin = csa.C[c]; // TODO: check whether this can be removed
210  else
211  c_begin = csa.C[csa.char2comp[c]];
212 
213  auto const r_s_b = csa.wavelet_tree.lex_count(l_parent, r_parent + 1, c);
214  size_type const s = std::get<1>(r_s_b),
215  b = std::get<2>(r_s_b),
216  rank_l = std::get<0>(r_s_b),
217  rank_r = r_parent - l_parent - s - b + rank_l;
218 
219  size_type const _l_fwd = c_begin + rank_l;
220  size_type const _r_fwd = c_begin + rank_r;
221  size_type const _l_bwd = r_bwd + 1;
222  size_type const _r_bwd = r_bwd + 1 + rank_r - rank_l;
223 
224  if (_r_fwd >= _l_fwd)
225  {
226  l_fwd = _l_fwd;
227  r_fwd = _r_fwd;
228  l_bwd = _l_bwd;
229  r_bwd = _r_bwd;
230  assert(r_fwd + 1 >= l_fwd);
231  assert(r_bwd + 1 - l_bwd == r_fwd + 1 - l_fwd);
232  return true;
233  }
234  return false;
235  }
236 
237 public:
238 
242  // Default construction is necessary to make this class semi-regular and e.g., to allow construction of
244  // std::array of cursors.
245  bi_fm_index_cursor() noexcept = default;
246  bi_fm_index_cursor(bi_fm_index_cursor const &) noexcept = default;
247  bi_fm_index_cursor & operator=(bi_fm_index_cursor const &) noexcept = default;
248  bi_fm_index_cursor(bi_fm_index_cursor &&) noexcept = default;
249  bi_fm_index_cursor & operator=(bi_fm_index_cursor &&) noexcept = default;
250  ~bi_fm_index_cursor() = default;
251 
253  bi_fm_index_cursor(index_t const & _index) noexcept : index(&_index),
254  fwd_lb(0), fwd_rb(_index.size() - 1),
255  rev_lb(0), rev_rb(_index.size() - 1),
256  sigma(_index.fwd_fm.index.sigma - index_t::text_layout_mode),
257  depth(0)
258  {}
259  //\}
260 
273  bool operator==(bi_fm_index_cursor const & rhs) const noexcept
274  {
275  assert(index != nullptr);
276  // equal SA interval implies equal parent node information (or both are root nodes)
277  assert(!(fwd_lb == rhs.fwd_lb && fwd_rb == rhs.fwd_rb && depth == rhs.depth) ||
278  (depth == 0) ||
279  (parent_lb == rhs.parent_lb && parent_rb == rhs.parent_rb && _last_char == rhs._last_char));
280 
281  return std::tie(fwd_lb, fwd_rb, depth) == std::tie(rhs.fwd_lb, rhs.fwd_rb, rhs.depth);
282  }
283 
296  bool operator!=(bi_fm_index_cursor const & rhs) const noexcept
297  {
298  assert(index != nullptr);
299 
300  return !(*this == rhs);
301  }
302 
320  bool extend_right() noexcept
321  {
322  #ifndef NDEBUG
323  fwd_cursor_last_used = true;
324  #endif
325 
326  assert(index != nullptr);
327 
328  size_type new_parent_lb = fwd_lb, new_parent_rb = fwd_rb;
329 
330  sdsl_char_type c = 1; // NOTE: start with 0 or 1 depending on implicit_sentintel
331  while (c < sigma &&
332  !bidirectional_search(index->fwd_fm.index, index->fwd_fm.index.comp2char[c],
333  fwd_lb, fwd_rb, rev_lb, rev_rb))
334  {
335  ++c;
336  }
337 
338  if (c != sigma)
339  {
340  parent_lb = new_parent_lb;
341  parent_rb = new_parent_rb;
342 
343  _last_char = c;
344  ++depth;
345 
346  return true;
347  }
348  return false;
349  }
350 
368  bool extend_left() noexcept
369  {
370  #ifndef NDEBUG
371  fwd_cursor_last_used = false;
372  #endif
373 
374  assert(index != nullptr);
375 
376  size_type new_parent_lb = rev_lb, new_parent_rb = rev_rb;
377 
378  sdsl_char_type c = 1; // NOTE: start with 0 or 1 depending on implicit_sentintel
379  while (c < sigma &&
380  !bidirectional_search(index->rev_fm.index, index->rev_fm.index.comp2char[c],
381  rev_lb, rev_rb, fwd_lb, fwd_rb))
382  {
383  ++c;
384  }
385 
386  if (c != sigma)
387  {
388  parent_lb = new_parent_lb;
389  parent_rb = new_parent_rb;
390 
391  _last_char = c;
392  ++depth;
393 
394  return true;
395  }
396  return false;
397  }
398 
412  template <typename char_t>
413  bool extend_right(char_t const c) noexcept
414  {
415  #ifndef NDEBUG
416  fwd_cursor_last_used = true;
417  #endif
418 
420  "The character must be convertible to the alphabet of the index.");
421 
422  assert(index != nullptr);
423 
424  size_type new_parent_lb = fwd_lb, new_parent_rb = fwd_rb;
425 
426  auto c_char = to_rank(static_cast<index_alphabet_type>(c)) + 1;
427  if (bidirectional_search(index->fwd_fm.index, c_char, fwd_lb, fwd_rb, rev_lb, rev_rb))
428  {
429  parent_lb = new_parent_lb;
430  parent_rb = new_parent_rb;
431 
432  _last_char = c_char;
433  ++depth;
434 
435  return true;
436  }
437  return false;
438  }
439 
453  template <typename char_t>
454  bool extend_left(char_t const c) noexcept
455  {
456  #ifndef NDEBUG
457  fwd_cursor_last_used = false;
458  #endif
459 
461  "The character must be convertible to the alphabet of the index.");
462 
463  assert(index != nullptr);
464 
465  size_type new_parent_lb = rev_lb, new_parent_rb = rev_rb;
466 
467  auto c_char = to_rank(static_cast<index_alphabet_type>(c)) + 1;
468  if (bidirectional_search(index->rev_fm.index, c_char, rev_lb, rev_rb, fwd_lb, fwd_rb))
469  {
470  parent_lb = new_parent_lb;
471  parent_rb = new_parent_rb;
472 
473  _last_char = c_char;
474  ++depth;
475 
476  return true;
477  }
478  return false;
479  }
480 
497  template <std::ranges::range seq_t>
498  bool extend_right(seq_t && seq) noexcept
499  {
500  static_assert(std::ranges::forward_range<seq_t>, "The query must model forward_range.");
501  static_assert(std::convertible_to<innermost_value_type_t<seq_t>, index_alphabet_type>,
502  "The alphabet of the sequence must be convertible to the alphabet of the index.");
503 
504  assert(index != nullptr);
505 
506  auto first = std::ranges::begin(seq);
507  auto last = std::ranges::end(seq);
508 
509  #ifndef NDEBUG
510  fwd_cursor_last_used = (first != last); // only if seq was not empty
511  #endif
512 
513  size_type _fwd_lb = fwd_lb, _fwd_rb = fwd_rb, _rev_lb = rev_lb, _rev_rb = rev_rb;
514  size_type new_parent_lb = parent_lb, new_parent_rb = parent_rb;
515  sdsl_char_type c = _last_char;
516  size_t len{0};
517 
518  for (auto it = first; it != last; ++len, ++it)
519  {
520  c = to_rank(static_cast<index_alphabet_type>(*it)) + 1;
521 
522  new_parent_lb = _fwd_lb;
523  new_parent_rb = _fwd_rb;
524  if (!bidirectional_search(index->fwd_fm.index, c, _fwd_lb, _fwd_rb, _rev_lb, _rev_rb))
525  return false;
526  }
527 
528  fwd_lb = _fwd_lb;
529  fwd_rb = _fwd_rb;
530  rev_lb = _rev_lb;
531  rev_rb = _rev_rb;
532 
533  parent_lb = new_parent_lb;
534  parent_rb = new_parent_rb;
535 
536  _last_char = c;
537  depth += len;
538 
539  return true;
540  }
541 
562  template <std::ranges::range seq_t>
563  bool extend_left(seq_t && seq) noexcept
564  {
565  static_assert(std::ranges::bidirectional_range<seq_t>, "The query must model bidirectional_range.");
566  static_assert(std::convertible_to<innermost_value_type_t<seq_t>, index_alphabet_type>,
567  "The alphabet of the sequence must be convertible to the alphabet of the index.");
568  assert(index != nullptr);
569 
570  auto rev_seq = std::views::reverse(seq);
571  auto first = std::ranges::begin(rev_seq);
572  auto last = std::ranges::end(rev_seq);
573 
574  #ifndef NDEBUG
575  if (first != last) // only if seq was not empty
576  fwd_cursor_last_used = false;
577  #endif
578 
579  size_type _fwd_lb = fwd_lb, _fwd_rb = fwd_rb,
580  _rev_lb = rev_lb, _rev_rb = rev_rb;
581  size_type new_parent_lb = parent_lb, new_parent_rb = parent_rb;
582  sdsl_char_type c = _last_char;
583  size_t len{0};
584 
585  for (auto it = first; it != last; ++len, ++it)
586  {
587  c = to_rank(static_cast<index_alphabet_type>(*it)) + 1;
588 
589  new_parent_lb = _rev_lb;
590  new_parent_rb = _rev_rb;
591  if (!bidirectional_search(index->rev_fm.index, c, _rev_lb, _rev_rb, _fwd_lb, _fwd_rb))
592  return false;
593  }
594 
595  fwd_lb = _fwd_lb;
596  fwd_rb = _fwd_rb;
597  rev_lb = _rev_lb;
598  rev_rb = _rev_rb;
599 
600  parent_lb = new_parent_lb;
601  parent_rb = new_parent_rb;
602  _last_char = c;
603  depth += len;
604 
605  return true;
606  }
607 
634  bool cycle_back() noexcept
635  {
636  #ifndef NDEBUG
637  // cycle_back() can only be used if the last extension was to the right.
638  assert(fwd_cursor_last_used);
639  #endif
640 
641  assert(index != nullptr && query_length() > 0);
642 
643  sdsl_char_type c = _last_char + 1;
644 
645  while (c < sigma &&
646  !bidirectional_search_cycle(index->fwd_fm.index, index->fwd_fm.index.comp2char[c],
647  parent_lb, parent_rb, fwd_lb, fwd_rb, rev_lb, rev_rb))
648  {
649  ++c;
650  }
651 
652  if (c != sigma)
653  {
654  _last_char = c;
655 
656  return true;
657  }
658  return false;
659  }
660 
687  bool cycle_front() noexcept
688  {
689  #ifndef NDEBUG
690  // cycle_front() can only be used if the last extension was to the left.
691  assert(!fwd_cursor_last_used);
692  #endif
693 
694  assert(index != nullptr && query_length() > 0);
695 
696  sdsl_char_type c = _last_char + 1;
697  while (c < sigma &&
698  !bidirectional_search_cycle(index->rev_fm.index, index->rev_fm.index.comp2char[c],
699  parent_lb, parent_rb, rev_lb, rev_rb, fwd_lb, fwd_rb))
700  {
701  ++c;
702  }
703 
704  if (c != sigma)
705  {
706  _last_char = c;
707 
708  return true;
709  }
710  return false;
711  }
712 
713 
730  size_type last_rank() noexcept
731  {
732  assert(index != nullptr && query_length() > 0);
733 
734  return index->fwd_fm.index.comp2char[_last_char] - 1; // text is not allowed to contain ranks of 0
735  }
736 
749  size_type query_length() const noexcept
750  {
751  assert(index != nullptr);
752  // depth == 0 -> root node
753  assert(depth != 0 ||
754  (fwd_lb == rev_lb &&
755  fwd_rb == rev_rb &&
756  fwd_lb == 0 &&
757  fwd_rb == index->size() - 1));
758 
759  return depth;
760  }
761 
781  fwd_cursor to_fwd_cursor() const noexcept
782  {
783  assert(index != nullptr);
784 
785  fwd_cursor cur{index->fwd_fm};
786  cur.parent_lb = parent_lb;
787  cur.parent_rb = parent_rb;
788  cur.node = {fwd_lb, fwd_rb, depth, _last_char};
789 
790  #ifndef NDEBUG
791  if (!fwd_cursor_last_used)
792  {
793  // invalidate parent interval
794  cur.parent_lb = 1;
795  cur.parent_rb = 0;
796  }
797  #endif
798 
799  return cur;
800  }
801 
826  rev_cursor to_rev_cursor() const noexcept
827  {
828  assert(index != nullptr);
829 
830  rev_cursor cur{index->rev_fm};
831  cur.parent_lb = parent_lb;
832  cur.parent_rb = parent_rb;
833  cur.node = {rev_lb, rev_rb, depth, _last_char};
834 
835  #ifndef NDEBUG
836  if (fwd_cursor_last_used)
837  {
838  // invalidate parent interval
839  cur.parent_lb = 1;
840  cur.parent_rb = 0;
841  }
842  #endif
843 
844  return cur;
845  }
846 
863  template <std::ranges::range text_t>
864  auto path_label(text_t && text) const noexcept
866  requires index_t::text_layout_mode == text_layout::single
868  {
869  static_assert(std::ranges::input_range<text_t>, "The text must model input_range.");
870  static_assert(dimension_v<text_t> == 1, "The input cannot be a text collection.");
871  static_assert(std::same_as<innermost_value_type_t<text_t>, index_alphabet_type>,
872  "The alphabet types of the given text and index differ.");
873  assert(index != nullptr);
874 
875  size_type const query_begin = offset() - index->fwd_fm.index[fwd_lb];
876  return text | views::slice(query_begin, query_begin + query_length());
877  }
878 
880  template <std::ranges::range text_t>
881  auto path_label(text_t && text) const noexcept
883  requires index_t::text_layout_mode == text_layout::collection
885  {
886  static_assert(std::ranges::input_range<text_t>, "The text collection must model input_range.");
887  static_assert(dimension_v<text_t> == 2, "The input must be a text collection.");
888  static_assert(std::same_as<innermost_value_type_t<text_t>, index_alphabet_type>,
889  "The alphabet types of the given text and index differ.");
890  assert(index != nullptr);
891 
892  size_type const loc = offset() - index->fwd_fm.index[fwd_lb];
893  size_type const query_begin = loc - index->fwd_fm.text_begin_rs.rank(loc + 1) + 1; // Substract delimiters
894  return text | views::join | views::slice(query_begin, query_begin + query_length());
895  }
896 
908  size_type count() const noexcept
909  {
910  assert(index != nullptr && (1 + fwd_rb - fwd_lb == 1 + rev_rb - rev_lb));
911 
912  return 1 + fwd_rb - fwd_lb;
913  }
914 
928  requires index_t::text_layout_mode == text_layout::single
930  {
931  assert(index != nullptr);
932 
934  for (size_type i = 0; i < occ.size(); ++i)
935  {
936  occ[i] = offset() - index->fwd_fm.index[fwd_lb + i];
937  }
938  return occ;
939  }
940 
944  requires index_t::text_layout_mode == text_layout::collection
946  {
947  assert(index != nullptr);
948 
950  occ.reserve(count());
951  for (size_type i = 0; i < count(); ++i)
952  {
953  size_type loc = offset() - index->fwd_fm.index[fwd_lb + i];
954  size_type sequence_rank = index->fwd_fm.text_begin_rs.rank(loc + 1);
955  size_type sequence_position = loc - index->fwd_fm.text_begin_ss.select(sequence_rank);
956  occ.emplace_back(sequence_rank - 1, sequence_position);
957  }
958  return occ;
959  }
960 
973  auto lazy_locate() const
975  requires index_t::text_layout_mode == text_layout::single
977  {
978  assert(index != nullptr);
979 
980  return std::views::iota(fwd_lb, fwd_lb + count())
981  | std::views::transform([*this, _offset = offset()] (auto sa_pos)
982  {
983  return _offset - index->fwd_fm.index[sa_pos];
984  });
985  }
986 
988  auto lazy_locate() const
990  requires index_t::text_layout_mode == text_layout::collection
992  {
993  assert(index != nullptr);
994 
995  return std::views::iota(fwd_lb, fwd_lb + count())
996  | std::views::transform([*this, _offset = offset()] (auto sa_pos)
997  {
998  return _offset - index->fwd_fm.index[sa_pos];
999  })
1000  | std::views::transform([*this] (auto loc)
1001  {
1002  size_type sequence_rank = index->fwd_fm.text_begin_rs.rank(loc + 1);
1003  size_type sequence_position = loc - index->fwd_fm.text_begin_ss.select(sequence_rank);
1004  return std::make_pair(sequence_rank-1, sequence_position);
1005  });
1006  }
1007 
1008 };
1009 
1011 
1012 } // namespace seqan3
seqan3::single
The text is a single range.
Definition: concept.hpp:84
seqan3::bi_fm_index_cursor::extend_left
bool extend_left(seq_t &&seq) noexcept
Tries to extend the query by seq to the left.
Definition: bi_fm_index_cursor.hpp:563
seqan3::field::seq
The "sequence", usually a range of nucleotides or amino acids.
seqan3::bi_fm_index_cursor::extend_right
bool extend_right(seq_t &&seq) noexcept
Tries to extend the query by seq to the right.
Definition: bi_fm_index_cursor.hpp:498
seqan3::bi_fm_index_cursor::extend_right
bool extend_right() noexcept
Tries to extend the query by the smallest possible character to the right such that the query is foun...
Definition: bi_fm_index_cursor.hpp:320
seqan3::bi_fm_index_cursor::to_fwd_cursor
fwd_cursor to_fwd_cursor() const noexcept
Returns a unidirectional seqan3::fm_index_cursor on the original text. path_label() on the returned u...
Definition: bi_fm_index_cursor.hpp:781
std::vector::reserve
T reserve(T... args)
seqan3::fm_index
The SeqAn FM Index.
Definition: fm_index.hpp:134
std::vector
std::vector::size
T size(T... args)
seqan3::bi_fm_index_cursor::locate
std::vector< std::pair< size_type, size_type > > locate() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: bi_fm_index_cursor.hpp:942
seqan3::to_rank
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:142
seqan3::bi_fm_index_cursor::extend_right
bool extend_right(char_t const c) noexcept
Tries to extend the query by the character c to the right.
Definition: bi_fm_index_cursor.hpp:413
seqan3::bi_fm_index_cursor::operator==
bool operator==(bi_fm_index_cursor const &rhs) const noexcept
Compares two cursors.
Definition: bi_fm_index_cursor.hpp:273
seqan3::bi_fm_index_cursor::query_length
size_type query_length() const noexcept
Returns the depth of the cursor node in the implicit suffix tree, i.e. the length of the sequence sea...
Definition: bi_fm_index_cursor.hpp:749
bi_fm_index.hpp
Provides the bidirectional seqan3::bi_fm_index.
seqan3::bi_fm_index_cursor::size_type
typename index_type::size_type size_type
Type for representing positions in the indexed text.
Definition: bi_fm_index_cursor.hpp:65
seqan3::bi_fm_index_cursor::count
size_type count() const noexcept
Counts the number of occurrences of the searched query in the text.
Definition: bi_fm_index_cursor.hpp:908
std::tie
T tie(T... args)
seqan3::text_layout
text_layout
The possible text layouts (single, collection) the seqan3::fm_index and seqan3::bi_fm_index can suppo...
Definition: concept.hpp:81
same_as
The concept std::same_as<T, U> is satisfied if and only if T and U denote the same type.
seqan3::collection
The text is a range of ranges.
Definition: concept.hpp:86
seqan3::bi_fm_index_cursor::index_type
index_t index_type
Type of the index.
Definition: bi_fm_index_cursor.hpp:59
slice.hpp
Provides seqan3::views::slice.
seqan3::bi_fm_index_cursor::extend_left
bool extend_left(char_t const c) noexcept
Tries to extend the query by the character c to the left.
Definition: bi_fm_index_cursor.hpp:454
range.hpp
Provides various transformation traits used by the range module.
array
seqan3
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:36
all.hpp
Meta-header for the alphabet module.
seqan3::bi_fm_index_cursor::cycle_front
bool cycle_front() noexcept
Tries to replace the leftmost character of the query by the next lexicographically larger character s...
Definition: bi_fm_index_cursor.hpp:687
seqan3::bi_fm_index_cursor::cycle_back
bool cycle_back() noexcept
Tries to replace the rightmost character of the query by the next lexicographically larger character ...
Definition: bi_fm_index_cursor.hpp:634
convertible_to
The concept std::convertible_to<From, To> specifies that an expression of the type and value category...
seqan3::bi_fm_index_cursor::lazy_locate
auto lazy_locate() const
Locates the occurrences of the searched query in the text on demand, i.e. a ranges::view is returned ...
Definition: bi_fm_index_cursor.hpp:973
seqan3::bi_fm_index_cursor::extend_left
bool extend_left() noexcept
Tries to extend the query by the smallest possible character to the left such that the query is found...
Definition: bi_fm_index_cursor.hpp:368
seqan3::fm_index::size
size_type size() const noexcept
Returns the length of the indexed text including sentinel characters.
Definition: fm_index.hpp:406
seqan3::pack_traits::size
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:116
seqan3::size_type
Exposes the size_type of another type.
Definition: pre.hpp:188
join.hpp
Provides seqan3::views::join.
ranges
Adaptations of concepts from the Ranges TS.
std::vector::emplace_back
T emplace_back(T... args)
seqan3::bi_fm_index_cursor
The SeqAn Bidirectional FM Index Cursor.
Definition: bi_fm_index_cursor.hpp:55
seqan3::bi_fm_index_cursor::locate
std::vector< size_type > locate() const
Locates the occurrences of the searched query in the text.
Definition: bi_fm_index_cursor.hpp:926
seqan3::views::slice
constexpr auto slice
A view adaptor that returns a half-open interval on the underlying range.
Definition: slice.hpp:141
seqan3::bi_fm_index_cursor::operator!=
bool operator!=(bi_fm_index_cursor const &rhs) const noexcept
Compares two cursors.
Definition: bi_fm_index_cursor.hpp:296
seqan3::innermost_value_type_t
typename innermost_value_type< t >::type innermost_value_type_t
Shortcut for seqan3::innermost_value_type (transformation_trait shortcut).
Definition: range.hpp:191
seqan3::fm_index_cursor
The SeqAn FM Index Cursor.
Definition: fm_index_cursor.hpp:59
std::make_pair
T make_pair(T... args)
seqan3::bi_fm_index_cursor::to_rev_cursor
rev_cursor to_rev_cursor() const noexcept
Returns a unidirectional seqan3::fm_index_cursor on the reversed text. path_label() on the returned u...
Definition: bi_fm_index_cursor.hpp:826
seqan3::pack_traits::transform
seqan3::type_list< trait_t< pack_t >... > transform
Apply a transformation trait to every type in the pack and return a seqan3::type_list of the results.
Definition: traits.hpp:307
seqan3::bi_fm_index_cursor::bi_fm_index_cursor
bi_fm_index_cursor() noexcept=default
Default constructor. Accessing member functions on a default constructed object is undefined behavior...
seqan3::bi_fm_index_cursor::path_label
auto path_label(text_t &&text) const noexcept
Returns the searched query.
Definition: bi_fm_index_cursor.hpp:864
seqan3::bi_fm_index_cursor::last_rank
size_type last_rank() noexcept
Outputs the rightmost respectively leftmost rank depending on whether extend_right() or extend_left()...
Definition: bi_fm_index_cursor.hpp:730