SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
edit_distance_trace_matrix_full.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2021, 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 <bitset>
16 
20 
21 namespace seqan3::detail
22 {
23 
31 template <typename word_t, bool is_semi_global, bool use_max_errors>
32 class edit_distance_trace_matrix_full
33 {
34 public:
36  template <std::ranges::viewable_range database_t,
37  std::ranges::viewable_range query_t,
38  typename align_config_t,
39  typename edit_traits>
40  friend class edit_distance_unbanded;
41 
45  edit_distance_trace_matrix_full() = default;
46  edit_distance_trace_matrix_full(edit_distance_trace_matrix_full const &) = default;
47  edit_distance_trace_matrix_full(edit_distance_trace_matrix_full &&) = default;
48  edit_distance_trace_matrix_full & operator=(edit_distance_trace_matrix_full const &) = default;
49  edit_distance_trace_matrix_full & operator=(edit_distance_trace_matrix_full &&) = default;
50  ~edit_distance_trace_matrix_full() = default;
51 
52  protected:
54  template <typename derived_t, typename edit_traits>
55  friend class edit_distance_unbanded_trace_matrix_policy;
56 
60  edit_distance_trace_matrix_full(size_t const rows_size)
61  : rows_size{rows_size}, columns{}
62  {}
64 
65 private:
66  struct trace_path_iterator;
67 
68 public:
70  using word_type = word_t;
71 
73  static constexpr auto word_size = bits_of<word_type>;
74 
76  using value_type = detail::trace_directions;
77 
79  using reference = value_type;
80 
82  using size_type = size_t;
83 
92  void reserve(size_t const new_capacity)
93  {
94  columns.reserve(new_capacity);
95  }
96 
97 public:
99  reference at(matrix_coordinate const & coordinate) const noexcept
100  {
101  size_t row = coordinate.row;
102  size_t col = coordinate.col;
103 
104  assert(row < rows());
105  assert(col < cols());
106 
107  column_type const & column = columns[col];
108 
109  if constexpr(use_max_errors)
110  if (!(row < column.max_rows))
112 
113  if (row == 0u)
114  {
115  if constexpr(is_semi_global)
117 
118  if (col == 0u)
120 
121  return detail::trace_directions::left;
122  }
123 
124  size_t const idx = (row - 1u) / word_size;
125  size_t const offset = (row - 1u) % word_size;
126 
127  bool const left = std::bitset<word_size>(column.left[idx])[offset];
128  bool const diagonal = std::bitset<word_size>(column.diagonal[idx])[offset];
129  bool const up = std::bitset<word_size>(column.up[idx])[offset];
130 
131  auto const dir = (left ? detail::trace_directions::left : detail::trace_directions::none) |
132  (diagonal ? detail::trace_directions::diagonal : detail::trace_directions::none) |
133  (up ? detail::trace_directions::up : detail::trace_directions::none);
134 
135  return dir;
136  }
137 
139  size_t rows() const noexcept
140  {
141  return rows_size;
142  }
143 
145  size_t cols() const noexcept
146  {
147  return columns.size();
148  }
149 
156  auto trace_path(matrix_coordinate const & trace_begin) const
157  {
158  if (trace_begin.row >= rows() || trace_begin.col >= cols())
159  throw std::invalid_argument{"The given coordinate exceeds the matrix in vertical or horizontal direction."};
160 
161  using path_t = std::ranges::subrange<trace_path_iterator, std::default_sentinel_t>;
162  return path_t{trace_path_iterator{this, trace_begin}, std::default_sentinel};
163  }
164 
165 protected:
167  struct max_errors_state
168  {
171  size_t max_rows{};
172  };
173 
175  struct trace_matrix_state
176  {
180  std::vector<word_type> diagonal{};
183  };
184 
186  struct column_type :
187  enable_state_t<true, trace_matrix_state>,
188  enable_state_t<use_max_errors, max_errors_state>
189  {};
190 
196  void add_column(std::vector<word_type> left, std::vector<word_type> diagonal, std::vector<word_type> up)
198  requires (!use_max_errors)
200  {
201  column_type column{};
202  column.left = std::move(left);
203  column.diagonal = std::move(diagonal);
204  column.up = std::move(up);
205 
206  columns.push_back(std::move(column));
207  }
208 
215  void add_column(std::vector<word_type> left, std::vector<word_type> diagonal, std::vector<word_type> up,
216  size_t const max_rows)
218  requires use_max_errors
220  {
221  column_type column{};
222  column.left = std::move(left);
223  column.diagonal = std::move(diagonal);
224  column.up = std::move(up);
225  column.max_rows = max_rows;
226 
227  columns.push_back(std::move(column));
228  }
229 
230 private:
232  size_t rows_size{};
234  std::vector<column_type> columns{};
235 };
236 
251 template <typename word_t, bool is_semi_global, bool use_max_errors>
252 struct edit_distance_trace_matrix_full<word_t, is_semi_global, use_max_errors>::trace_path_iterator
253 {
258  using iterator_category = std::input_iterator_tag;
260  using value_type = detail::trace_directions;
262  using difference_type = std::ptrdiff_t;
264 
266  constexpr static value_type D = value_type::diagonal;
268  constexpr static value_type L = value_type::left;
270  constexpr static value_type U = value_type::up;
272  constexpr static value_type N = value_type::none;
273 
278  constexpr value_type operator*() const
279  {
280  value_type dir = parent->at(coordinate());
281 
282  if (dir == N)
283  return N;
284 
285  if ((dir & L) == L)
286  return L;
287  else if ((dir & U) == U)
288  return U;
289  else
290  return D;
291  }
292 
294  [[nodiscard]] constexpr matrix_coordinate const & coordinate() const
295  {
296  return coordinate_;
297  }
299 
304  constexpr trace_path_iterator & operator++()
305  {
306  value_type dir = *(*this);
307 
308  if ((dir & L) == L)
309  {
310  coordinate_.col = std::max<size_t>(coordinate_.col, 1) - 1;
311  }
312  else if ((dir & U) == U)
313  {
314  coordinate_.row = std::max<size_t>(coordinate_.row, 1) - 1;
315  }
316  else if ((dir & D) == D)
317  {
318  coordinate_.row = std::max<size_t>(coordinate_.row, 1) - 1;
319  coordinate_.col = std::max<size_t>(coordinate_.col, 1) - 1;
320  }
321 
322  // seqan3::trace_direction::none in an inner cell of the trace matrix is not possible in
323  // non-local alignments, e.g. global, semi-global, max-error, banded. On the other hand,
324  // this can happen in a cell of the first row or first colomn.
325  assert(dir != N || coordinate_.row == 0 || coordinate_.col == 0);
326 
327  return *this;
328  }
329 
331  constexpr void operator++(int)
332  {
333  ++(*this);
334  }
336 
341  friend bool operator==(trace_path_iterator const & it, std::default_sentinel_t)
342  {
343  return *it == value_type::none;
344  }
345 
347  friend bool operator==(std::default_sentinel_t, trace_path_iterator const & it)
348  {
349  return it == std::default_sentinel;
350  }
351 
353  friend bool operator!=(trace_path_iterator const & it, std::default_sentinel_t)
354  {
355  return !(it == std::default_sentinel);
356  }
357 
359  friend bool operator!=(std::default_sentinel_t, trace_path_iterator const & it)
360  {
361  return it != std::default_sentinel;
362  }
364 
366  edit_distance_trace_matrix_full const * parent{nullptr};
368  matrix_coordinate coordinate_{};
369 };
370 
371 } // namespace seqan3::detail
Provides utility functions for bit twiddling.
Forwards for seqan3::edit_distance_unbanded related types.
@ offset
Sequence (seqan3::field::seq) relative start position (0-based), unsigned value.
@ none
No flag is set.
Definition: debug_stream_type.hpp:32
typename decltype(detail::at< idx >(list_t{}))::type at
Return the type at given index from the type list.
Definition: traits.hpp:260
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:74
T left(T... args)
T operator!=(T... args)
T size(T... args)
Provides the declaration of seqan3::detail::trace_directions.