SeqAn3 3.1.0
The Modern C++ library for sequence analysis.
trace_iterator_base.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
18#include <seqan3/std/concepts>
19#include <seqan3/std/ranges>
20
21namespace seqan3::detail
22{
23
61template <typename derived_t, two_dimensional_matrix_iterator matrix_iter_t>
62class trace_iterator_base
63{
64private:
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
116public:
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;
126
131 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
153 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
196 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
232private:
238 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
The <concepts> header from C++20's standard library.
@ none
No flag is set.
Definition: debug_stream_type.hpp:32
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.