SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
trace_iterator_base.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 
18 #include <seqan3/std/concepts>
19 #include <seqan3/std/ranges>
20 
21 namespace seqan3::detail
22 {
23 
61 template <typename derived_t, two_dimensional_matrix_iterator matrix_iter_t>
62 class trace_iterator_base
63 {
64 private:
65  static_assert(std::same_as<std::iter_value_t<matrix_iter_t>, trace_directions>,
66  "Value type of the underlying iterator must be seqan3::detail::trace_directions.");
67 
69  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>
74  friend class trace_iterator_base;
75 
77  friend derived_t;
78 
82  constexpr trace_iterator_base() = default;
83  constexpr trace_iterator_base(trace_iterator_base const &) = default;
84  constexpr trace_iterator_base(trace_iterator_base &&) = default;
85  constexpr trace_iterator_base & operator=(trace_iterator_base const &) = default;
86  constexpr trace_iterator_base & operator=(trace_iterator_base &&) = default;
87  ~trace_iterator_base() = default;
88 
92  constexpr trace_iterator_base(matrix_iter_t const matrix_iter) noexcept : matrix_iter{matrix_iter}
93  {
94  set_trace_direction(*matrix_iter);
95  }
96 
107  template <typename other_derived_t, two_dimensional_matrix_iterator other_matrix_iter_t>
109  requires std::constructible_from<matrix_iter_t, other_matrix_iter_t>
111  constexpr trace_iterator_base(trace_iterator_base<other_derived_t, other_matrix_iter_t> const & other) noexcept :
112  trace_iterator_base{other.matrix_iter}
113  {}
115 
116 public:
120  using value_type = trace_directions;
121  using reference = trace_directions const &;
122  using pointer = value_type *;
123  using difference_type = std::ptrdiff_t;
124  using iterator_category = std::forward_iterator_tag;
125 
130  reference operator*() const noexcept
132  {
133  return current_direction;
134  }
135 
137  pointer operator->() const noexcept
138  {
139  return &current_direction;
140  }
141 
143  [[nodiscard]] constexpr matrix_coordinate coordinate() const noexcept
144  {
145  return matrix_iter.coordinate();
146  }
148 
152  constexpr derived_t & operator++() noexcept
154  {
155  trace_directions old_dir = *matrix_iter;
156 
157  assert(old_dir != trace_directions::none);
158 
159  if (current_direction == trace_directions::up)
160  {
161  derived().go_up(matrix_iter);
162  // Set new trace direction if last position was up_open.
163  if (static_cast<bool>(old_dir & trace_directions::up_open))
164  set_trace_direction(*matrix_iter);
165  }
166  else if (current_direction == trace_directions::left)
167  {
168  derived().go_left(matrix_iter);
169  // Set new trace direction if last position was left_open.
170  if (static_cast<bool>(old_dir & trace_directions::left_open))
171  set_trace_direction(*matrix_iter);
172  }
173  else
174  {
175  assert(current_direction == trace_directions::diagonal);
176 
177  derived().go_diagonal(matrix_iter);
178  set_trace_direction(*matrix_iter);
179  }
180  return derived();
181  }
182 
184  constexpr derived_t operator++(int) noexcept
185  {
186  derived_t tmp{derived()};
187  ++(*this);
188  return tmp;
189  }
191 
195  constexpr friend bool operator==(derived_t const & lhs, derived_t const & rhs) noexcept
197  {
198  return lhs.matrix_iter == rhs.matrix_iter;
199  }
200 
202  constexpr friend bool operator==(derived_t const & lhs, std::default_sentinel_t const &) noexcept
203  {
204  return *lhs.matrix_iter == trace_directions::none;
205  }
206 
208  constexpr friend bool operator==(std::default_sentinel_t const &, derived_t const & rhs) noexcept
209  {
210  return rhs == std::default_sentinel;
211  }
212 
214  constexpr friend bool operator!=(derived_t const & lhs, derived_t const & rhs) noexcept
215  {
216  return !(lhs == rhs);
217  }
218 
220  constexpr friend bool operator!=(derived_t const & lhs, std::default_sentinel_t const &) noexcept
221  {
222  return !(lhs == std::default_sentinel);
223  }
224 
226  constexpr friend bool operator!=(std::default_sentinel_t const &, derived_t const & rhs) noexcept
227  {
228  return !(rhs == std::default_sentinel);
229  }
231 
232 private:
237  constexpr void go_left(matrix_iter_t & iter) const noexcept
239  {
240  iter -= matrix_offset{row_index_type{0}, column_index_type{1}};
241  }
242 
244  constexpr void go_up(matrix_iter_t & iter) const noexcept
245  {
246  iter -= matrix_offset{row_index_type{1}, column_index_type{0}};
247  }
248 
250  constexpr void go_diagonal(matrix_iter_t & iter) const noexcept
251  {
252  iter -= matrix_offset{row_index_type{1}, column_index_type{1}};
253  }
255 
257  void set_trace_direction(trace_directions const dir) noexcept
258  {
259  if (static_cast<bool>(dir & trace_directions::diagonal))
260  {
261  current_direction = trace_directions::diagonal;
262  }
263  else if (static_cast<bool>(dir & trace_directions::up) ||
264  static_cast<bool>(dir & trace_directions::up_open))
265  {
266  current_direction = trace_directions::up;
267  }
268  else if (static_cast<bool>(dir & trace_directions::left) ||
269  static_cast<bool>(dir & trace_directions::left_open))
270  {
271  current_direction = trace_directions::left;
272  }
273  else
274  {
275  current_direction = trace_directions::none;
276  }
277  }
278 
280  constexpr derived_t & derived() noexcept
281  {
282  return static_cast<derived_t &>(*this);
283  }
284 
286  constexpr derived_t const & derived() const noexcept
287  {
288  return static_cast<derived_t const &>(*this);
289  }
290 
291  matrix_iter_t matrix_iter{};
292  trace_directions current_direction{};
293 };
294 
295 } // namespace seqan3::detail
two_dimensional_matrix_iterator_concept.hpp
Provides seqan3::detail::two_dimensional_matrix_iterator.
std::rel_ops::operator!=
T operator!=(T... args)
std::forward_iterator_tag
concepts
The Concepts library.
trace_directions.hpp
Provides the declaration of seqan3::detail::trace_directions.
std::iter_value_t
two_dimensional_matrix_iterator_base.hpp
Provides seqan3::detail::two_dimensional_matrix_iterator_base.
ranges
Adaptations of concepts from the Ranges TS.
std::ptrdiff_t
seqan3::none
@ none
No flag is set.
Definition: debug_stream_type.hpp:30