SeqAn3  3.0.2
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 
25 #include <seqan3/std/ranges>
26 
27 namespace seqan3
28 {
29 
55 template <typename index_t>
57 {
58 public:
60  using index_type = index_t;
61 
65  using size_type = typename index_type::size_type;
68 
72  using fwd_cursor = fm_index_cursor<fm_index<typename index_type::alphabet_type,
74  index_type::text_layout_mode,
75  typename index_type::sdsl_index_type>>;
77 
78 private:
80  using sdsl_char_type = typename index_type::sdsl_char_type;
82  using sdsl_index_type = typename index_t::sdsl_index_type;
84  using sdsl_sigma_type = typename index_type::sdsl_sigma_type;
86  using index_alphabet_type = typename index_t::alphabet_type;
91 
93  index_type const * index;
94 
98  size_type fwd_lb;
101  size_type fwd_rb;
103  size_type rev_lb;
105  size_type rev_rb;
106  //\}
107 
109  sdsl_sigma_type sigma;
110 
117  // parent_* and _last_char only have to be stored for the (unidirectional) cursor that has been used last for
118  // extend_right() or cycle_back() resp. extend_left() or cycle_front(), (i.e. either fwd or rev). Thus there is no
119  // need to store it twice. Once the cursor is switched, the information becomes invalid anyway.
120 
122  size_type parent_lb{};
124  size_type parent_rb{};
126  sdsl_char_type _last_char;
127  //\}
128 
130  size_type depth; // equal for both cursors. only stored once
131 
132  // supports assertions to check whether cycle_back() resp. cycle_front() is called on the same direction as the last
133  // extend_right([...]) resp. extend_left([...])
134 #ifndef NDEBUG
135  // cycle_back() and cycle_front()
137  bool fwd_cursor_last_used = false;
138 #endif
139 
141  size_type offset() const noexcept
142  {
143  assert(index->size() > query_length());
144  return index->size() - query_length() - 1; // since the string is reversed during construction
145  }
146 
148  template <typename csa_t>
150  requires (std::same_as<csa_t, typename index_type::sdsl_index_type> ||
151  std::same_as<csa_t, typename index_type::rev_sdsl_index_type>)
153  bool bidirectional_search(csa_t const & csa, sdsl_char_type const c,
154  size_type & l_fwd, size_type & r_fwd,
155  size_type & l_bwd, size_type & r_bwd) const noexcept
156  {
157  assert((l_fwd <= r_fwd) && (r_fwd < csa.size()));
158  assert(r_fwd + 1 >= l_fwd);
159  assert(r_bwd + 1 - l_bwd == r_fwd + 1 - l_fwd);
160 
161  size_type _l_fwd, _r_fwd, _l_bwd, _r_bwd;
162 
163  size_type cc = c;
164  if constexpr(!std::same_as<index_alphabet_type, sdsl::plain_byte_alphabet>)
165  {
166  cc = csa.char2comp[c];
167  if (cc == 0 && c > 0) // [[unlikely]]
168  return false;
169  }
170 
171  size_type const c_begin = csa.C[cc];
172  if (r_fwd + 1 - l_fwd == csa.size()) // [[unlikely]]
173  {
174  _l_fwd = c_begin;
175  _l_bwd = c_begin;
176  _r_fwd = csa.C[cc + 1] - 1;
177  _r_bwd = _r_fwd;
178  // if we use not the plain_byte_alphabet, we could return always return true here
179  }
180  else
181  {
182  auto const r_s_b = csa.wavelet_tree.lex_count(l_fwd, r_fwd + 1, c);
183  size_type const rank_l = std::get<0>(r_s_b);
184  size_type const s = std::get<1>(r_s_b), b = std::get<2>(r_s_b);
185  size_type const rank_r = r_fwd - l_fwd - s - b + rank_l;
186  _l_fwd = c_begin + rank_l;
187  _r_fwd = c_begin + rank_r;
188  _l_bwd = l_bwd + s;
189  _r_bwd = r_bwd - b;
190  }
191 
192  if (_r_fwd >= _l_fwd)
193  {
194  l_fwd = _l_fwd;
195  r_fwd = _r_fwd;
196  l_bwd = _l_bwd;
197  r_bwd = _r_bwd;
198  assert(r_fwd + 1 >= l_fwd);
199  assert(r_bwd + 1 - l_bwd == r_fwd + 1 - l_fwd);
200  return true;
201  }
202  return false;
203  }
204 
206  template <typename csa_t>
208  requires (std::same_as<csa_t, typename index_type::sdsl_index_type> ||
209  std::same_as<csa_t, typename index_type::rev_sdsl_index_type>)
211  bool bidirectional_search_cycle(csa_t const & csa, sdsl_char_type const c,
212  size_type const l_parent, size_type const r_parent,
213  size_type & l_fwd, size_type & r_fwd,
214  size_type & l_bwd, size_type & r_bwd) const noexcept
215  {
216  assert((l_parent <= r_parent) && (r_parent < csa.size()));
217 
218  size_type c_begin;
219  if constexpr(std::same_as<index_alphabet_type, sdsl::plain_byte_alphabet>)
220  c_begin = csa.C[c]; // TODO: check whether this can be removed
221  else
222  c_begin = csa.C[csa.char2comp[c]];
223 
224  auto const r_s_b = csa.wavelet_tree.lex_count(l_parent, r_parent + 1, c);
225  size_type const s = std::get<1>(r_s_b),
226  b = std::get<2>(r_s_b),
227  rank_l = std::get<0>(r_s_b),
228  rank_r = r_parent - l_parent - s - b + rank_l;
229 
230  size_type const _l_fwd = c_begin + rank_l;
231  size_type const _r_fwd = c_begin + rank_r;
232  size_type const _l_bwd = r_bwd + 1;
233  size_type const _r_bwd = r_bwd + 1 + rank_r - rank_l;
234 
235  if (_r_fwd >= _l_fwd)
236  {
237  l_fwd = _l_fwd;
238  r_fwd = _r_fwd;
239  l_bwd = _l_bwd;
240  r_bwd = _r_bwd;
241  assert(r_fwd + 1 >= l_fwd);
242  assert(r_bwd + 1 - l_bwd == r_fwd + 1 - l_fwd);
243  return true;
244  }
245  return false;
246  }
247 
248 public:
249 
253  // Default construction is necessary to make this class semi-regular and e.g., to allow construction of
255  // std::array of cursors.
256  bi_fm_index_cursor() noexcept = default;
257  bi_fm_index_cursor(bi_fm_index_cursor const &) noexcept = default;
258  bi_fm_index_cursor & operator=(bi_fm_index_cursor const &) noexcept = default;
259  bi_fm_index_cursor(bi_fm_index_cursor &&) noexcept = default;
260  bi_fm_index_cursor & operator=(bi_fm_index_cursor &&) noexcept = default;
261  ~bi_fm_index_cursor() = default;
262 
264  bi_fm_index_cursor(index_t const & _index) noexcept : index(&_index),
265  fwd_lb(0), fwd_rb(_index.size() - 1),
266  rev_lb(0), rev_rb(_index.size() - 1),
267  sigma(_index.fwd_fm.index.sigma - index_t::text_layout_mode),
268  depth(0)
269  {}
270  //\}
271 
284  bool operator==(bi_fm_index_cursor const & rhs) const noexcept
285  {
286  assert(index != nullptr);
287  // equal SA interval implies equal parent node information (or both are root nodes)
288  assert(!(fwd_lb == rhs.fwd_lb && fwd_rb == rhs.fwd_rb && depth == rhs.depth) ||
289  (depth == 0) ||
290  (parent_lb == rhs.parent_lb && parent_rb == rhs.parent_rb && _last_char == rhs._last_char));
291 
292  return std::tie(fwd_lb, fwd_rb, depth) == std::tie(rhs.fwd_lb, rhs.fwd_rb, rhs.depth);
293  }
294 
307  bool operator!=(bi_fm_index_cursor const & rhs) const noexcept
308  {
309  assert(index != nullptr);
310 
311  return !(*this == rhs);
312  }
313 
331  bool extend_right() noexcept
332  {
333  #ifndef NDEBUG
334  fwd_cursor_last_used = true;
335  #endif
336 
337  assert(index != nullptr);
338 
339  size_type new_parent_lb = fwd_lb, new_parent_rb = fwd_rb;
340 
341  sdsl_char_type c = 1; // NOTE: start with 0 or 1 depending on implicit_sentintel
342  while (c < sigma &&
343  !bidirectional_search(index->fwd_fm.index, index->fwd_fm.index.comp2char[c],
344  fwd_lb, fwd_rb, rev_lb, rev_rb))
345  {
346  ++c;
347  }
348 
349  if (c != sigma)
350  {
351  parent_lb = new_parent_lb;
352  parent_rb = new_parent_rb;
353 
354  _last_char = c;
355  ++depth;
356 
357  return true;
358  }
359  return false;
360  }
361 
379  bool extend_left() noexcept
380  {
381  #ifndef NDEBUG
382  fwd_cursor_last_used = false;
383  #endif
384 
385  assert(index != nullptr);
386 
387  size_type new_parent_lb = rev_lb, new_parent_rb = rev_rb;
388 
389  sdsl_char_type c = 1; // NOTE: start with 0 or 1 depending on implicit_sentintel
390  while (c < sigma &&
391  !bidirectional_search(index->rev_fm.index, index->rev_fm.index.comp2char[c],
392  rev_lb, rev_rb, fwd_lb, fwd_rb))
393  {
394  ++c;
395  }
396 
397  if (c != sigma)
398  {
399  parent_lb = new_parent_lb;
400  parent_rb = new_parent_rb;
401 
402  _last_char = c;
403  ++depth;
404 
405  return true;
406  }
407  return false;
408  }
409 
423  template <typename char_t>
425  requires std::convertible_to<char_t, index_alphabet_type>
427  bool extend_right(char_t const c) noexcept
428  {
429  #ifndef NDEBUG
430  fwd_cursor_last_used = true;
431  #endif
432 
433  assert(index != nullptr);
434  // The rank cannot exceed 255 for single text and 254 for text collections as they are reserved as sentinels
435  // for the indexed text.
436  assert(seqan3::to_rank(static_cast<index_alphabet_type>(c)) <
437  ((index_type::text_layout_mode == text_layout::single) ? 255 : 254));
438 
439  size_type new_parent_lb = fwd_lb, new_parent_rb = fwd_rb;
440 
441  auto c_char = seqan3::to_rank(static_cast<index_alphabet_type>(c)) + 1;
442  if (bidirectional_search(index->fwd_fm.index, c_char, fwd_lb, fwd_rb, rev_lb, rev_rb))
443  {
444  parent_lb = new_parent_lb;
445  parent_rb = new_parent_rb;
446 
447  _last_char = c_char;
448  ++depth;
449 
450  return true;
451  }
452  return false;
453  }
454 
456  template <typename char_type>
458  requires seqan3::detail::is_char_adaptation_v<char_type>
460  bool extend_right(char_type const * cstring) noexcept
461  {
463  }
464 
478  template <typename char_t>
480  requires std::convertible_to<char_t, index_alphabet_type>
482  bool extend_left(char_t const c) noexcept
483  {
484  #ifndef NDEBUG
485  fwd_cursor_last_used = false;
486  #endif
487 
488  assert(index != nullptr);
489  // The rank cannot exceed 255 for single text and 254 for text collections as they are reserved as sentinels
490  // for the indexed text.
491  assert(seqan3::to_rank(static_cast<index_alphabet_type>(c)) <
492  ((index_type::text_layout_mode == text_layout::single) ? 255 : 254));
493 
494  size_type new_parent_lb = rev_lb, new_parent_rb = rev_rb;
495 
496  auto c_char = seqan3::to_rank(static_cast<index_alphabet_type>(c)) + 1;
497  if (bidirectional_search(index->rev_fm.index, c_char, rev_lb, rev_rb, fwd_lb, fwd_rb))
498  {
499  parent_lb = new_parent_lb;
500  parent_rb = new_parent_rb;
501 
502  _last_char = c_char;
503  ++depth;
504 
505  return true;
506  }
507  return false;
508  }
509 
511  template <typename char_type>
513  requires seqan3::detail::is_char_adaptation_v<char_type>
515  bool extend_left(char_type const * cstring) noexcept
516  {
518  }
519 
536  template <std::ranges::range seq_t>
537  bool extend_right(seq_t && seq) noexcept
538  {
539  static_assert(std::ranges::forward_range<seq_t>, "The query must model forward_range.");
540  static_assert(std::convertible_to<range_innermost_value_t<seq_t>, index_alphabet_type>,
541  "The alphabet of the sequence must be convertible to the alphabet of the index.");
542 
543  assert(index != nullptr);
544 
545  auto first = std::ranges::begin(seq);
546  auto last = std::ranges::end(seq);
547 
548  #ifndef NDEBUG
549  fwd_cursor_last_used = (first != last); // only if seq was not empty
550  #endif
551 
552  size_type _fwd_lb = fwd_lb, _fwd_rb = fwd_rb, _rev_lb = rev_lb, _rev_rb = rev_rb;
553  size_type new_parent_lb = parent_lb, new_parent_rb = parent_rb;
554  sdsl_char_type c = _last_char;
555  size_t len{0};
556 
557  for (auto it = first; it != last; ++len, ++it)
558  {
559  // The rank cannot exceed 255 for single text and 254 for text collections as they are reserved as sentinels
560  // for the indexed text.
561  assert(seqan3::to_rank(static_cast<index_alphabet_type>(*it)) <
562  ((index_type::text_layout_mode == text_layout::single) ? 255 : 254));
563 
564  c = seqan3::to_rank(static_cast<index_alphabet_type>(*it)) + 1;
565 
566  new_parent_lb = _fwd_lb;
567  new_parent_rb = _fwd_rb;
568  if (!bidirectional_search(index->fwd_fm.index, c, _fwd_lb, _fwd_rb, _rev_lb, _rev_rb))
569  return false;
570  }
571 
572  fwd_lb = _fwd_lb;
573  fwd_rb = _fwd_rb;
574  rev_lb = _rev_lb;
575  rev_rb = _rev_rb;
576 
577  parent_lb = new_parent_lb;
578  parent_rb = new_parent_rb;
579 
580  _last_char = c;
581  depth += len;
582 
583  return true;
584  }
585 
606  template <std::ranges::range seq_t>
607  bool extend_left(seq_t && seq) noexcept
608  {
609  static_assert(std::ranges::bidirectional_range<seq_t>, "The query must model bidirectional_range.");
610  static_assert(std::convertible_to<range_innermost_value_t<seq_t>, index_alphabet_type>,
611  "The alphabet of the sequence must be convertible to the alphabet of the index.");
612  assert(index != nullptr);
613 
614  auto rev_seq = std::views::reverse(seq);
615  auto first = std::ranges::begin(rev_seq);
616  auto last = std::ranges::end(rev_seq);
617 
618  #ifndef NDEBUG
619  if (first != last) // only if seq was not empty
620  fwd_cursor_last_used = false;
621  #endif
622 
623  size_type _fwd_lb = fwd_lb, _fwd_rb = fwd_rb,
624  _rev_lb = rev_lb, _rev_rb = rev_rb;
625  size_type new_parent_lb = parent_lb, new_parent_rb = parent_rb;
626  sdsl_char_type c = _last_char;
627  size_t len{0};
628 
629  for (auto it = first; it != last; ++len, ++it)
630  {
631  // The rank cannot exceed 255 for single text and 254 for text collections as they are reserved as sentinels
632  // for the indexed text.
633  assert(seqan3::to_rank(static_cast<index_alphabet_type>(*it)) <
634  ((index_type::text_layout_mode == text_layout::single) ? 255 : 254));
635 
636  c = seqan3::to_rank(static_cast<index_alphabet_type>(*it)) + 1;
637 
638  new_parent_lb = _rev_lb;
639  new_parent_rb = _rev_rb;
640  if (!bidirectional_search(index->rev_fm.index, c, _rev_lb, _rev_rb, _fwd_lb, _fwd_rb))
641  return false;
642  }
643 
644  fwd_lb = _fwd_lb;
645  fwd_rb = _fwd_rb;
646  rev_lb = _rev_lb;
647  rev_rb = _rev_rb;
648 
649  parent_lb = new_parent_lb;
650  parent_rb = new_parent_rb;
651  _last_char = c;
652  depth += len;
653 
654  return true;
655  }
656 
683  bool cycle_back() noexcept
684  {
685  #ifndef NDEBUG
686  // cycle_back() can only be used if the last extension was to the right.
687  assert(fwd_cursor_last_used);
688  #endif
689 
690  assert(index != nullptr && query_length() > 0);
691 
692  sdsl_char_type c = _last_char + 1;
693 
694  while (c < sigma &&
695  !bidirectional_search_cycle(index->fwd_fm.index, index->fwd_fm.index.comp2char[c],
696  parent_lb, parent_rb, fwd_lb, fwd_rb, rev_lb, rev_rb))
697  {
698  ++c;
699  }
700 
701  if (c != sigma)
702  {
703  _last_char = c;
704 
705  return true;
706  }
707  return false;
708  }
709 
736  bool cycle_front() noexcept
737  {
738  #ifndef NDEBUG
739  // cycle_front() can only be used if the last extension was to the left.
740  assert(!fwd_cursor_last_used);
741  #endif
742 
743  assert(index != nullptr && query_length() > 0);
744 
745  sdsl_char_type c = _last_char + 1;
746  while (c < sigma &&
747  !bidirectional_search_cycle(index->rev_fm.index, index->rev_fm.index.comp2char[c],
748  parent_lb, parent_rb, rev_lb, rev_rb, fwd_lb, fwd_rb))
749  {
750  ++c;
751  }
752 
753  if (c != sigma)
754  {
755  _last_char = c;
756 
757  return true;
758  }
759  return false;
760  }
761 
762 
779  size_type last_rank() noexcept
780  {
781  assert(index != nullptr && query_length() > 0);
782 
783  return index->fwd_fm.index.comp2char[_last_char] - 1; // text is not allowed to contain ranks of 0
784  }
785 
798  size_type query_length() const noexcept
799  {
800  assert(index != nullptr);
801  // depth == 0 -> root node
802  assert(depth != 0 ||
803  (fwd_lb == rev_lb &&
804  fwd_rb == rev_rb &&
805  fwd_lb == 0 &&
806  fwd_rb == index->size() - 1));
807 
808  return depth;
809  }
810 
830  fwd_cursor to_fwd_cursor() const noexcept
831  {
832  assert(index != nullptr);
833 
834  fwd_cursor cur{index->fwd_fm};
835  cur.parent_lb = parent_lb;
836  cur.parent_rb = parent_rb;
837  cur.node = {fwd_lb, fwd_rb, depth, _last_char};
838 
839  #ifndef NDEBUG
840  if (!fwd_cursor_last_used)
841  {
842  // invalidate parent interval
843  cur.parent_lb = 1;
844  cur.parent_rb = 0;
845  }
846  #endif
847 
848  return cur;
849  }
850 
867  template <std::ranges::range text_t>
868  auto path_label(text_t && text) const noexcept
870  requires (index_t::text_layout_mode == text_layout::single)
872  {
873  static_assert(std::ranges::input_range<text_t>, "The text must model input_range.");
874  static_assert(range_dimension_v<text_t> == 1, "The input cannot be a text collection.");
875  static_assert(std::same_as<range_innermost_value_t<text_t>, index_alphabet_type>,
876  "The alphabet types of the given text and index differ.");
877  assert(index != nullptr);
878 
879  size_type const query_begin = offset() - index->fwd_fm.index[fwd_lb];
880  return text | views::slice(query_begin, query_begin + query_length());
881  }
882 
884  template <std::ranges::range text_t>
885  auto path_label(text_t && text) const noexcept
887  requires (index_t::text_layout_mode == text_layout::collection)
889  {
890  static_assert(std::ranges::input_range<text_t>, "The text collection must model input_range.");
891  static_assert(range_dimension_v<text_t> == 2, "The input must be a text collection.");
892  static_assert(std::same_as<range_innermost_value_t<text_t>, index_alphabet_type>,
893  "The alphabet types of the given text and index differ.");
894  assert(index != nullptr);
895 
896  // Position of query in concatenated text.
897  size_type const location = offset() - index->fwd_fm.index[fwd_lb];
898 
899  // The rank represents the number of start positions of the individual sequences/texts in the collection
900  // before position `location + 1` and thereby also the number of delimiters.
901  size_type const rank = index->fwd_fm.text_begin_rs.rank(location + 1);
902  assert(rank > 0);
903  size_type const text_id = rank - 1;
904 
905  // The start location of the `text_id`-th text in the sequence (position of the `rank`-th 1 in the bitvector).
906  size_type const start_location = index->fwd_fm.text_begin_ss.select(rank);
907  // Substract lengths of previous sequences.
908  size_type const query_begin = location - start_location;
909 
910  // Take subtext, slice query out of it
911  return text[text_id] | views::slice(query_begin, query_begin + query_length());
912  }
913 
925  size_type count() const noexcept
926  {
927  assert(index != nullptr && (1 + fwd_rb - fwd_lb == 1 + rev_rb - rev_lb));
928 
929  return 1 + fwd_rb - fwd_lb;
930  }
931 
945  requires (index_t::text_layout_mode == text_layout::single)
947  {
948  assert(index != nullptr);
949 
950  locate_result_type occ{};
951  occ.reserve(count());
952  for (size_type i = 0; i < count(); ++i)
953  {
954  occ.emplace_back(0, offset() - index->fwd_fm.index[fwd_lb + i]);
955  }
956  return occ;
957  }
958 
962  requires (index_t::text_layout_mode == text_layout::collection)
964  {
965  assert(index != nullptr);
966 
968  occ.reserve(count());
969  for (size_type i = 0; i < count(); ++i)
970  {
971  size_type loc = offset() - index->fwd_fm.index[fwd_lb + i];
972  size_type sequence_rank = index->fwd_fm.text_begin_rs.rank(loc + 1);
973  size_type sequence_position = loc - index->fwd_fm.text_begin_ss.select(sequence_rank);
974  occ.emplace_back(sequence_rank - 1, sequence_position);
975  }
976  return occ;
977  }
978 
991  auto lazy_locate() const
993  requires (index_t::text_layout_mode == text_layout::single)
995  {
996  assert(index != nullptr);
997 
998  return std::views::iota(fwd_lb, fwd_lb + count())
999  | std::views::transform([*this, _offset = offset()] (auto sa_pos)
1000  {
1001  return locate_result_value_type{0u, _offset - index->fwd_fm.index[sa_pos]};
1002  });
1003  }
1004 
1006  auto lazy_locate() const
1008  requires (index_t::text_layout_mode == text_layout::collection)
1010  {
1011  assert(index != nullptr);
1012 
1013  return std::views::iota(fwd_lb, fwd_lb + count())
1014  | std::views::transform([*this, _offset = offset()] (auto sa_pos)
1015  {
1016  return _offset - index->fwd_fm.index[sa_pos];
1017  })
1018  | std::views::transform([*this] (auto loc)
1019  {
1020  size_type sequence_rank = index->fwd_fm.text_begin_rs.rank(loc + 1);
1021  size_type sequence_position = loc - index->fwd_fm.text_begin_ss.select(sequence_rank);
1022  return locate_result_value_type{sequence_rank-1, sequence_position};
1023  });
1024  }
1025 };
1026 
1028 
1029 } // namespace seqan3
seqan3::bi_fm_index_cursor::extend_left
bool extend_left(char_type const *cstring) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: bi_fm_index_cursor.hpp:515
seqan3::single
@ 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:607
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:537
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:331
std::basic_string_view
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:830
std::pair
std::vector::reserve
T reserve(T... args)
seqan3::fm_index
The SeqAn FM Index.
Definition: fm_index.hpp:194
std::vector
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:960
seqan3::range_innermost_value_t
typename range_innermost_value< t >::type range_innermost_value_t
Shortcut for seqan3::range_innermost_value (transformation_trait shortcut).
Definition: range.hpp:226
seqan3::to_rank
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:143
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:427
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:284
seqan3::bi_fm_index_cursor::locate
locate_result_type locate() const
Locates the occurrences of the searched query in the text.
Definition: bi_fm_index_cursor.hpp:943
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:798
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:66
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:925
std::tie
T tie(T... args)
seqan3::seq
constexpr sequenced_policy seq
Global execution policy object for sequenced execution policy.
Definition: execution.hpp:54
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:82
seqan3::collection
@ 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:60
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:482
range.hpp
Provides various transformation traits used by the range module.
array
seqan3
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
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:736
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:683
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 std::ranges::view is retu...
Definition: bi_fm_index_cursor.hpp:991
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:379
seqan3::bi_fm_index_cursor::extend_right
bool extend_right(char_type const *cstring) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: bi_fm_index_cursor.hpp:460
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:306
char.hpp
Provides alphabet adaptations for standard char types.
ranges
Adaptations of concepts from the Ranges TS.
std::vector::emplace_back
T emplace_back(T... args)
uint.hpp
Provides alphabet adaptations for standard uint types.
seqan3::bi_fm_index_cursor
The SeqAn Bidirectional FM Index Cursor.
Definition: bi_fm_index_cursor.hpp:57
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:307
seqan3::fm_index_cursor
The SeqAn FM Index Cursor.
Definition: fm_index_cursor.hpp:57
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:868
concept.hpp
Core alphabet concept and free function/type trait wrappers.
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:779