SeqAn3 3.2.0
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-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
22namespace seqan3::detail
23{
24
62template <typename derived_t, two_dimensional_matrix_iterator matrix_iter_t>
63class trace_iterator_base
64{
65private:
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
113public:
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
229private:
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
@ none
No flag is set.
Definition: debug_stream_type.hpp:32
T operator!=(T... args)
Provides the declaration of seqan3::detail::trace_directions.
Provides seqan3::detail::two_dimensional_matrix_iterator_base.
Provides seqan3::detail::two_dimensional_matrix_iterator.