SeqAn3  3.2.0
The Modern C++ library for sequence analysis.
two_dimensional_matrix_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 #include <type_traits>
18 
22 
23 namespace seqan3::detail
24 {
25 
38 enum struct matrix_major_order : uint8_t
39 {
40  column,
41  row
42 };
43 
75 template <typename derived_t, matrix_major_order order>
76 class two_dimensional_matrix_iterator_base
77 {
78 private:
80  friend derived_t;
81 
83  template <typename other_derived_t, matrix_major_order other_order>
84  requires (order == other_order)
85  friend class two_dimensional_matrix_iterator_base;
86 
91  constexpr two_dimensional_matrix_iterator_base() = default;
93  constexpr two_dimensional_matrix_iterator_base(two_dimensional_matrix_iterator_base const &) = default;
95  constexpr two_dimensional_matrix_iterator_base(two_dimensional_matrix_iterator_base &&) = default;
97  constexpr two_dimensional_matrix_iterator_base & operator=(two_dimensional_matrix_iterator_base const &) = default;
99  constexpr two_dimensional_matrix_iterator_base & operator=(two_dimensional_matrix_iterator_base &&) = default;
101  ~two_dimensional_matrix_iterator_base() = default;
103 
105  template <typename _derived_t>
106  using difference_type = typename _derived_t::difference_type;
107 
109  template <typename _derived_t>
110  using reference = typename _derived_t::reference;
111 
113  template <typename _derived_t>
114  using pointer = typename _derived_t::pointer;
115 
116 public:
121  template <typename dummy_t = derived_t>
122  constexpr reference<dummy_t> operator*() const noexcept
123  {
124  return *as_derived().host_iter;
125  }
126 
128  template <typename dummy_t = derived_t>
129  constexpr reference<dummy_t> operator[](std::iter_difference_t<dummy_t> const offset) const noexcept
130  {
131  return *(as_derived() + offset);
132  }
133 
135  template <typename dummy_t = derived_t>
136  constexpr reference<dummy_t> operator[](matrix_offset const & offset) const noexcept
137  {
138  return *(as_derived() + offset);
139  }
140 
142  template <typename dummy_t = derived_t>
143  constexpr pointer<dummy_t> operator->() const noexcept
144  {
145  return std::addressof(*as_derived().host_iter);
146  }
147 
158  SEQAN3_DOXYGEN_ONLY(constexpr seqan3::detail::matrix_coordinate coordinate() const noexcept {})
160 
179  SEQAN3_DOXYGEN_ONLY(constexpr derived_t & operator+=(matrix_offset const & offset) noexcept {})
180 
182  constexpr derived_t & operator++() noexcept
183  {
184  if constexpr (order == matrix_major_order::column)
185  return as_derived() += matrix_offset{row_index_type{1}, column_index_type{0}};
186  else
187  return as_derived() += matrix_offset{row_index_type{0}, column_index_type{1}};
188  }
189 
191  constexpr derived_t operator++(int) noexcept
192  {
193  derived_t previous{as_derived()};
194  ++(*this);
195  return previous;
196  }
197 
199  template <typename dummy_t = derived_t>
200  constexpr derived_t & operator+=(std::iter_difference_t<dummy_t> const offset) noexcept
201  {
202  if constexpr (order == matrix_major_order::column)
203  return as_derived() += matrix_offset{row_index_type{offset}, column_index_type{0}};
204  else
205  return as_derived() += matrix_offset{row_index_type{0}, column_index_type{offset}};
206  }
207 
209  template <typename dummy_t = derived_t>
210  constexpr derived_t operator+(std::iter_difference_t<dummy_t> const offset) const noexcept
211  {
212  derived_t next{as_derived()};
213  next += offset;
214  return next;
215  }
216 
218  template <typename dummy_t = derived_t>
219  constexpr friend derived_t operator+(std::iter_difference_t<dummy_t> const offset, derived_t const iter)
220  {
221  return iter + offset;
222  }
223 
225  constexpr derived_t operator+(matrix_offset const & offset) const noexcept
226  {
227  derived_t next{as_derived()};
228  next += offset;
229  return next;
230  }
231 
233  constexpr friend derived_t operator+(matrix_offset const & offset, derived_t const iter)
234  {
235  return iter + offset;
236  }
237 
239  constexpr derived_t & operator--() noexcept
240  {
241  if constexpr (order == matrix_major_order::column)
242  return as_derived() += matrix_offset{row_index_type{-1}, column_index_type{0}};
243  else
244  return as_derived() += matrix_offset{row_index_type{0}, column_index_type{-1}};
245  }
246 
248  constexpr derived_t operator--(int) noexcept
249  {
250  derived_t previous{as_derived()};
251  --(*this);
252  return previous;
253  }
254 
256  template <typename dummy_t = derived_t>
257  constexpr derived_t & operator-=(std::iter_difference_t<dummy_t> const offset) noexcept
258  {
259  return *this += -offset;
260  }
261 
263  template <typename dummy_t = derived_t>
264  constexpr derived_t operator-(std::iter_difference_t<dummy_t> const offset) const noexcept
265  {
266  derived_t next{as_derived()};
267  next -= offset;
268  return next;
269  }
270 
272  constexpr derived_t & operator-=(matrix_offset const & offset) noexcept
273  {
274  return as_derived() += matrix_offset{row_index_type{-offset.row}, column_index_type{-offset.col}};
275  }
276 
278  constexpr derived_t operator-(matrix_offset const & offset) const noexcept
279  {
280  derived_t next{as_derived()};
281  next -= offset;
282  return next;
283  }
284 
286  template <typename dummy_t = derived_t>
287  friend constexpr std::iter_difference_t<dummy_t> operator-(derived_t const lhs, derived_t const rhs) noexcept
288  {
289  return lhs.as_host_iter() - rhs.as_host_iter();
290  }
292 
297  // What if the derived type is different?
298  // How can make sure this is the same type?
299  template <typename other_derived_t>
300  requires std::constructible_from<derived_t, other_derived_t>
301  || std::constructible_from<other_derived_t, derived_t>
302  constexpr bool operator==(two_dimensional_matrix_iterator_base<other_derived_t, order> const & rhs) const noexcept
303  {
304  return as_derived().host_iter == rhs.as_derived().host_iter;
305  }
306 
308  template <typename other_derived_t>
309  requires std::constructible_from<derived_t, other_derived_t>
310  || std::constructible_from<other_derived_t, derived_t>
311  constexpr bool operator!=(two_dimensional_matrix_iterator_base<other_derived_t, order> const & rhs) const noexcept
312  {
313  return !(*this == rhs);
314  }
315 
317  template <typename other_derived_t>
318  requires std::constructible_from<derived_t, other_derived_t>
319  || std::constructible_from<other_derived_t, derived_t>
320  constexpr bool operator<(two_dimensional_matrix_iterator_base<other_derived_t, order> const & rhs) const noexcept
321  {
322  return as_derived().host_iter < rhs.as_derived().host_iter;
323  }
324 
326  template <typename other_derived_t>
327  requires std::constructible_from<derived_t, other_derived_t>
328  || std::constructible_from<other_derived_t, derived_t>
329  constexpr bool operator<=(two_dimensional_matrix_iterator_base<other_derived_t, order> const & rhs) const noexcept
330  {
331  return as_derived().host_iter <= rhs.as_derived().host_iter;
332  }
333 
335  template <typename other_derived_t>
336  requires std::constructible_from<derived_t, other_derived_t>
337  || std::constructible_from<other_derived_t, derived_t>
338  constexpr bool operator>(two_dimensional_matrix_iterator_base<other_derived_t, order> const & rhs) const noexcept
339  {
340  return as_derived().host_iter > rhs.as_derived().host_iter;
341  }
342 
344  template <typename other_derived_t>
345  requires std::constructible_from<derived_t, other_derived_t>
346  || std::constructible_from<other_derived_t, derived_t>
347  constexpr bool operator>=(two_dimensional_matrix_iterator_base<other_derived_t, order> const & rhs) const noexcept
348  {
349  return as_derived().host_iter >= rhs.as_derived().host_iter;
350  }
352 
353 private:
355  constexpr auto const & as_host_iter() const
356  {
357  return as_derived().host_iter;
358  }
359 
361  constexpr derived_t & as_derived()
362  {
363  return static_cast<derived_t &>(*this);
364  }
365 
367  constexpr derived_t const & as_derived() const
368  {
369  return static_cast<derived_t const &>(*this);
370  }
371 
372  // matrix_iterator_t host_iter{}; //!< The wrapped matrix iterator.
373 };
374 } // namespace seqan3::detail
T addressof(T... args)
Provides various type traits on generic types.
The <concepts> header from C++20's standard library.
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
@ offset
Sequence (seqan3::field::seq) relative start position (0-based), unsigned value.
Provides various transformation traits for use on iterators.
Provides seqan3::detail::matrix_index, seqan3::detail::matrix_coordinate and associated strong types.
matrix_index< size_t > matrix_coordinate
A coordinate type to access an element inside of a two-dimensional matrix.
Definition: matrix_coordinate.hpp:178
T next(T... args)
T operator!=(T... args)
The <ranges> header from C++20's standard library.