SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
trace_iterator_base.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2024 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2024 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <concepts>
13#include <ranges>
14
18
19namespace seqan3::detail
20{
21
59template <typename derived_t, two_dimensional_matrix_iterator matrix_iter_t>
60class trace_iterator_base
61{
62private:
63 static_assert(std::same_as<std::iter_value_t<matrix_iter_t>, trace_directions>,
64 "Value type of the underlying iterator must be seqan3::detail::trace_directions.");
65
67 template <typename other_derived_t, two_dimensional_matrix_iterator other_matrix_iter_t>
68 friend class trace_iterator_base;
69
71 friend derived_t;
72
76 constexpr trace_iterator_base() = default;
77 constexpr trace_iterator_base(trace_iterator_base const &) = default;
78 constexpr trace_iterator_base(trace_iterator_base &&) = default;
79 constexpr trace_iterator_base & operator=(trace_iterator_base const &) = default;
80 constexpr trace_iterator_base & operator=(trace_iterator_base &&) = default;
81 ~trace_iterator_base() = default;
82
86 constexpr trace_iterator_base(matrix_iter_t const matrix_iter) noexcept : matrix_iter{matrix_iter}
87 {
88 set_trace_direction(*matrix_iter);
89 }
90
101 template <typename other_derived_t, two_dimensional_matrix_iterator other_matrix_iter_t>
102 requires std::constructible_from<matrix_iter_t, other_matrix_iter_t>
103 constexpr trace_iterator_base(trace_iterator_base<other_derived_t, other_matrix_iter_t> const & other) noexcept :
104 trace_iterator_base{other.matrix_iter}
105 {}
107
108public:
112 // Doxygen: https://github.com/seqan/product_backlog/issues/424
114 using value_type = trace_directions;
115 using reference = trace_directions const &;
116 using pointer = value_type const *;
117 using difference_type = std::ptrdiff_t;
118 using iterator_category = std::forward_iterator_tag;
120
125 reference operator*() const noexcept
126 {
127 return current_direction;
128 }
129
131 pointer operator->() const noexcept
132 {
133 return &current_direction;
134 }
135
137 [[nodiscard]] constexpr matrix_coordinate coordinate() const noexcept
138 {
139 return matrix_iter.coordinate();
140 }
142
147 constexpr derived_t & operator++() noexcept
148 {
149 trace_directions old_dir = *matrix_iter;
150
151 assert(old_dir != trace_directions::none);
152
153 if (current_direction == trace_directions::up)
154 {
155 derived().go_up(matrix_iter);
156 // Set new trace direction if last position was up_open.
157 if (static_cast<bool>(old_dir & trace_directions::carry_up_open))
158 set_trace_direction(*matrix_iter);
159 }
160 else if (current_direction == trace_directions::left)
161 {
162 derived().go_left(matrix_iter);
163 // Set new trace direction if last position was left_open.
164 if (static_cast<bool>(old_dir & trace_directions::carry_left_open))
165 set_trace_direction(*matrix_iter);
166 }
167 else
168 {
169 assert(current_direction == trace_directions::diagonal);
170
171 derived().go_diagonal(matrix_iter);
172 set_trace_direction(*matrix_iter);
173 }
174 return derived();
175 }
176
178 constexpr derived_t operator++(int) noexcept
179 {
180 derived_t tmp{derived()};
181 ++(*this);
182 return tmp;
183 }
185
190 constexpr friend bool operator==(derived_t const & lhs, derived_t const & rhs) noexcept
191 {
192 return lhs.matrix_iter == rhs.matrix_iter;
193 }
194
196 constexpr friend bool operator==(derived_t const & lhs, std::default_sentinel_t const &) noexcept
197 {
198 return *lhs.matrix_iter == trace_directions::none;
199 }
200
202 constexpr friend bool operator==(std::default_sentinel_t const &, derived_t const & rhs) noexcept
203 {
204 return rhs == std::default_sentinel;
205 }
206
208 constexpr friend bool operator!=(derived_t const & lhs, derived_t const & rhs) noexcept
209 {
210 return !(lhs == rhs);
211 }
212
214 constexpr friend bool operator!=(derived_t const & lhs, std::default_sentinel_t const &) noexcept
215 {
216 return !(lhs == std::default_sentinel);
217 }
218
220 constexpr friend bool operator!=(std::default_sentinel_t const &, derived_t const & rhs) noexcept
221 {
222 return !(rhs == std::default_sentinel);
223 }
225
226private:
232 constexpr void go_left(matrix_iter_t & iter) const noexcept
233 {
234 iter -= matrix_offset{row_index_type{0}, column_index_type{1}};
235 }
236
238 constexpr void go_up(matrix_iter_t & iter) const noexcept
239 {
240 iter -= matrix_offset{row_index_type{1}, column_index_type{0}};
241 }
242
244 constexpr void go_diagonal(matrix_iter_t & iter) const noexcept
245 {
246 iter -= matrix_offset{row_index_type{1}, column_index_type{1}};
247 }
249
251 void set_trace_direction(trace_directions const dir) noexcept
252 {
253 if (static_cast<bool>(dir & trace_directions::diagonal))
254 {
255 current_direction = trace_directions::diagonal;
256 }
257 else if (static_cast<bool>(dir & trace_directions::up))
258 {
259 current_direction = trace_directions::up;
260 }
261 else if (static_cast<bool>(dir & trace_directions::left))
262 {
263 current_direction = trace_directions::left;
264 }
265 else
266 {
267 current_direction = trace_directions::none;
268 }
269 }
270
272 constexpr derived_t & derived() noexcept
273 {
274 return static_cast<derived_t &>(*this);
275 }
276
278 constexpr derived_t const & derived() const noexcept
279 {
280 return static_cast<derived_t const &>(*this);
281 }
282
283 matrix_iter_t matrix_iter{};
284 trace_directions current_direction{};
285};
286
287} // 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.
Hide me