SeqAn3 3.3.0
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
trace_iterator_base.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2023, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2023, 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 friend class trace_iterator_base;
72
74 friend derived_t;
75
79 constexpr trace_iterator_base() = default;
80 constexpr trace_iterator_base(trace_iterator_base const &) = default;
81 constexpr trace_iterator_base(trace_iterator_base &&) = default;
82 constexpr trace_iterator_base & operator=(trace_iterator_base const &) = default;
83 constexpr trace_iterator_base & operator=(trace_iterator_base &&) = default;
84 ~trace_iterator_base() = default;
85
89 constexpr trace_iterator_base(matrix_iter_t const matrix_iter) noexcept : matrix_iter{matrix_iter}
90 {
91 set_trace_direction(*matrix_iter);
92 }
93
104 template <typename other_derived_t, two_dimensional_matrix_iterator other_matrix_iter_t>
105 requires std::constructible_from<matrix_iter_t, other_matrix_iter_t>
106 constexpr trace_iterator_base(trace_iterator_base<other_derived_t, other_matrix_iter_t> const & other) noexcept :
107 trace_iterator_base{other.matrix_iter}
108 {}
110
111public:
115 // Doxygen: https://github.com/seqan/product_backlog/issues/424
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::carry_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::carry_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))
261 {
262 current_direction = trace_directions::up;
263 }
264 else if (static_cast<bool>(dir & trace_directions::left))
265 {
266 current_direction = trace_directions::left;
267 }
268 else
269 {
270 current_direction = trace_directions::none;
271 }
272 }
273
275 constexpr derived_t & derived() noexcept
276 {
277 return static_cast<derived_t &>(*this);
278 }
279
281 constexpr derived_t const & derived() const noexcept
282 {
283 return static_cast<derived_t const &>(*this);
284 }
285
286 matrix_iter_t matrix_iter{};
287 trace_directions current_direction{};
288};
289
290} // namespace seqan3::detail
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.