SeqAn3  3.2.0-rc.1
The Modern C++ library for sequence analysis.
trace_iterator_base.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, 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 <concepts>
16 #include <ranges>
17 
21 
22 namespace seqan3::detail
23 {
24 
62 template <typename derived_t, two_dimensional_matrix_iterator matrix_iter_t>
63 class trace_iterator_base
64 {
65 private:
66  static_assert(std::same_as<std::iter_value_t<matrix_iter_t>, trace_directions>,
67  "Value type of the underlying iterator must be seqan3::detail::trace_directions.");
68 
70  template <typename other_derived_t, two_dimensional_matrix_iterator other_matrix_iter_t>
71  requires std::constructible_from<derived_t, other_derived_t>
72  && std::constructible_from<matrix_iter_t, other_matrix_iter_t>
73  friend class trace_iterator_base;
74 
76  friend derived_t;
77 
81  constexpr trace_iterator_base() = default;
82  constexpr trace_iterator_base(trace_iterator_base const &) = default;
83  constexpr trace_iterator_base(trace_iterator_base &&) = default;
84  constexpr trace_iterator_base & operator=(trace_iterator_base const &) = default;
85  constexpr trace_iterator_base & operator=(trace_iterator_base &&) = default;
86  ~trace_iterator_base() = default;
87 
91  constexpr trace_iterator_base(matrix_iter_t const matrix_iter) noexcept : matrix_iter{matrix_iter}
92  {
93  set_trace_direction(*matrix_iter);
94  }
95 
106  template <typename other_derived_t, two_dimensional_matrix_iterator other_matrix_iter_t>
107  requires std::constructible_from<matrix_iter_t, other_matrix_iter_t>
108  constexpr trace_iterator_base(trace_iterator_base<other_derived_t, other_matrix_iter_t> const & other) noexcept :
109  trace_iterator_base{other.matrix_iter}
110  {}
112 
113 public:
117  using value_type = trace_directions;
118  using reference = trace_directions const &;
119  using pointer = value_type const *;
120  using difference_type = std::ptrdiff_t;
121  using iterator_category = std::forward_iterator_tag;
123 
128  reference operator*() const noexcept
129  {
130  return current_direction;
131  }
132 
134  pointer operator->() const noexcept
135  {
136  return &current_direction;
137  }
138 
140  [[nodiscard]] constexpr matrix_coordinate coordinate() const noexcept
141  {
142  return matrix_iter.coordinate();
143  }
145 
150  constexpr derived_t & operator++() noexcept
151  {
152  trace_directions old_dir = *matrix_iter;
153 
154  assert(old_dir != trace_directions::none);
155 
156  if (current_direction == trace_directions::up)
157  {
158  derived().go_up(matrix_iter);
159  // Set new trace direction if last position was up_open.
160  if (static_cast<bool>(old_dir & trace_directions::up_open))
161  set_trace_direction(*matrix_iter);
162  }
163  else if (current_direction == trace_directions::left)
164  {
165  derived().go_left(matrix_iter);
166  // Set new trace direction if last position was left_open.
167  if (static_cast<bool>(old_dir & trace_directions::left_open))
168  set_trace_direction(*matrix_iter);
169  }
170  else
171  {
172  assert(current_direction == trace_directions::diagonal);
173 
174  derived().go_diagonal(matrix_iter);
175  set_trace_direction(*matrix_iter);
176  }
177  return derived();
178  }
179 
181  constexpr derived_t operator++(int) noexcept
182  {
183  derived_t tmp{derived()};
184  ++(*this);
185  return tmp;
186  }
188 
193  constexpr friend bool operator==(derived_t const & lhs, derived_t const & rhs) noexcept
194  {
195  return lhs.matrix_iter == rhs.matrix_iter;
196  }
197 
199  constexpr friend bool operator==(derived_t const & lhs, std::default_sentinel_t const &) noexcept
200  {
201  return *lhs.matrix_iter == trace_directions::none;
202  }
203 
205  constexpr friend bool operator==(std::default_sentinel_t const &, derived_t const & rhs) noexcept
206  {
207  return rhs == std::default_sentinel;
208  }
209 
211  constexpr friend bool operator!=(derived_t const & lhs, derived_t const & rhs) noexcept
212  {
213  return !(lhs == rhs);
214  }
215 
217  constexpr friend bool operator!=(derived_t const & lhs, std::default_sentinel_t const &) noexcept
218  {
219  return !(lhs == std::default_sentinel);
220  }
221 
223  constexpr friend bool operator!=(std::default_sentinel_t const &, derived_t const & rhs) noexcept
224  {
225  return !(rhs == std::default_sentinel);
226  }
228 
229 private:
235  constexpr void go_left(matrix_iter_t & iter) const noexcept
236  {
237  iter -= matrix_offset{row_index_type{0}, column_index_type{1}};
238  }
239 
241  constexpr void go_up(matrix_iter_t & iter) const noexcept
242  {
243  iter -= matrix_offset{row_index_type{1}, column_index_type{0}};
244  }
245 
247  constexpr void go_diagonal(matrix_iter_t & iter) const noexcept
248  {
249  iter -= matrix_offset{row_index_type{1}, column_index_type{1}};
250  }
252 
254  void set_trace_direction(trace_directions const dir) noexcept
255  {
256  if (static_cast<bool>(dir & trace_directions::diagonal))
257  {
258  current_direction = trace_directions::diagonal;
259  }
260  else if (static_cast<bool>(dir & trace_directions::up) || static_cast<bool>(dir & trace_directions::up_open))
261  {
262  current_direction = trace_directions::up;
263  }
264  else if (static_cast<bool>(dir & trace_directions::left)
265  || static_cast<bool>(dir & trace_directions::left_open))
266  {
267  current_direction = trace_directions::left;
268  }
269  else
270  {
271  current_direction = trace_directions::none;
272  }
273  }
274 
276  constexpr derived_t & derived() noexcept
277  {
278  return static_cast<derived_t &>(*this);
279  }
280 
282  constexpr derived_t const & derived() const noexcept
283  {
284  return static_cast<derived_t const &>(*this);
285  }
286 
287  matrix_iter_t matrix_iter{};
288  trace_directions current_direction{};
289 };
290 
291 } // namespace seqan3::detail
The <concepts> header from C++20's standard library.
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
@ none
No flag is set.
Definition: debug_stream_type.hpp:32
matrix_index< size_t > matrix_coordinate
A coordinate type to access an element inside of a two-dimensional matrix.
Definition: matrix_coordinate.hpp:178
T operator!=(T... args)
The <ranges> header from C++20's standard library.
Provides the declaration of seqan3::detail::trace_directions.
Provides seqan3::detail::two_dimensional_matrix_iterator_base.
Provides seqan3::detail::two_dimensional_matrix_iterator.