SeqAn3  3.2.0
The Modern C++ library for sequence analysis.
trace_matrix_full.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 <ranges>
16 #include <span>
17 #include <vector>
18 
28 
29 namespace seqan3::detail
30 {
31 
50 template <typename trace_t>
51  requires std::same_as<trace_t, trace_directions>
52 class trace_matrix_full
53 {
54 private:
56  using matrix_t =
57  two_dimensional_matrix<trace_t, aligned_allocator<trace_t, sizeof(trace_t)>, matrix_major_order::column>;
59  using physical_column_t = std::vector<trace_t>;
61  using virtual_column_t = decltype(views::repeat_n(trace_t{}, 1));
62 
63  class iterator;
64 
66  matrix_t complete_matrix{};
68  physical_column_t horizontal_column{};
70  virtual_column_t vertical_column{};
72  size_t column_count{};
74  size_t row_count{};
75 
76 public:
80  trace_matrix_full() = default;
81  trace_matrix_full(trace_matrix_full const &) = default;
82  trace_matrix_full(trace_matrix_full &&) = default;
83  trace_matrix_full & operator=(trace_matrix_full const &) = default;
84  trace_matrix_full & operator=(trace_matrix_full &&) = default;
85  ~trace_matrix_full() = default;
86 
88 
111  template <std::integral column_index_t, std::integral row_index_t>
112  void resize(column_index_type<column_index_t> const column_count, row_index_type<row_index_t> const row_count)
113  {
114  this->column_count = column_count.get();
115  this->row_count = row_count.get();
116  complete_matrix.resize(number_rows{this->row_count}, number_cols{this->column_count});
117  horizontal_column.resize(this->row_count);
118  vertical_column = views::repeat_n(trace_t{}, this->row_count);
119  }
120 
127  auto trace_path(matrix_coordinate const & trace_begin) const
128  {
129  using matrix_iter_t = std::ranges::iterator_t<matrix_t const>;
130  using trace_iterator_t = trace_iterator<matrix_iter_t>;
131  using path_t = std::ranges::subrange<trace_iterator_t, std::default_sentinel_t>;
132 
133  if (trace_begin.row >= row_count || trace_begin.col >= column_count)
134  throw std::invalid_argument{"The given coordinate exceeds the matrix in vertical or horizontal direction."};
135 
136  return path_t{trace_iterator_t{complete_matrix.begin() + matrix_offset{trace_begin}}, std::default_sentinel};
137  }
138 
143  iterator begin()
144  {
145  return iterator{*this, 0u};
146  }
147 
149  iterator begin() const = delete;
150 
152  iterator end()
153  {
154  return iterator{*this, column_count};
155  }
156 
158  iterator end() const = delete;
160 };
161 
171 template <typename trace_t>
172  requires std::same_as<trace_t, trace_directions>
173 class trace_matrix_full<trace_t>::iterator
174 {
175 private:
177  using single_trace_column_type = std::span<trace_t>;
179  using matrix_column_type = decltype(views::zip(std::declval<single_trace_column_type>(),
180  std::declval<physical_column_t &>(),
181  std::declval<virtual_column_t &>()));
183  using matrix_column_value_t = std::vector<std::ranges::range_value_t<matrix_column_type>>;
184 
185  // Defines a proxy that can be converted to the value type.
186  class column_proxy;
187 
189  trace_matrix_full * host_ptr{nullptr};
191  size_t current_column_id{};
192 
193 public:
198  using value_type = matrix_column_value_t;
200  using reference = column_proxy;
202  using pointer = void;
204  using difference_type = std::ptrdiff_t;
206  using iterator_category = std::input_iterator_tag;
208 
212  iterator() noexcept = default;
213  iterator(iterator const &) noexcept = default;
214  iterator(iterator &&) noexcept = default;
215  iterator & operator=(iterator const &) noexcept = default;
216  iterator & operator=(iterator &&) noexcept = default;
217  ~iterator() = default;
218 
224  explicit iterator(trace_matrix_full & host_matrix, size_t const initial_column_id) noexcept :
225  host_ptr{std::addressof(host_matrix)},
226  current_column_id{initial_column_id}
227  {}
229 
234  reference operator*() const
235  {
236  auto column_begin = host_ptr->complete_matrix.data() + current_column_id * host_ptr->row_count;
237  single_trace_column_type single_trace_column{column_begin, column_begin + host_ptr->row_count};
238 
239  return column_proxy{
240  views::zip(std::move(single_trace_column), host_ptr->horizontal_column, host_ptr->vertical_column)};
241  }
243 
248  iterator & operator++()
249  {
250  ++current_column_id;
251  return *this;
252  }
253 
255  void operator++(int)
256  {
257  ++(*this);
258  }
260 
265  friend bool operator==(iterator const & lhs, iterator const & rhs) noexcept
266  {
267  return lhs.current_column_id == rhs.current_column_id;
268  }
269 
271  friend bool operator!=(iterator const & lhs, iterator const & rhs) noexcept
272  {
273  return !(lhs == rhs);
274  }
276 };
277 
286 template <typename trace_t>
287  requires std::same_as<trace_t, trace_directions>
288 class trace_matrix_full<trace_t>::iterator::column_proxy : public std::ranges::view_interface<column_proxy>
289 {
290 private:
292  matrix_column_type column{};
293 
294 public:
298  column_proxy() = default;
299  column_proxy(column_proxy const &) = default;
300  column_proxy(column_proxy &&) = default;
301  column_proxy & operator=(column_proxy const &) = default;
302  column_proxy & operator=(column_proxy &&) = default;
303  ~column_proxy() = default;
304 
309  explicit column_proxy(matrix_column_type && column) noexcept : column{std::move(column)}
310  {}
312 
317  std::ranges::iterator_t<matrix_column_type> begin()
318  {
319  return column.begin();
320  }
322  std::ranges::iterator_t<matrix_column_type> begin() const = delete;
323 
325  std::ranges::sentinel_t<matrix_column_type> end()
326  {
327  return column.end();
328  }
329 
331  std::ranges::sentinel_t<matrix_column_type> end() const = delete;
333 
335  constexpr operator matrix_column_value_t() const
336  {
337  matrix_column_value_t target{};
338  std::ranges::copy(column, std::back_inserter(target));
339  return target;
340  }
341 };
342 
343 } // namespace seqan3::detail
T addressof(T... args)
Provides seqan3::aligned_allocator.
T back_inserter(T... args)
T begin(T... args)
T end(T... args)
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
constexpr auto zip
A view adaptor that takes several views and returns tuple-like values from every i-th element of each...
Definition: zip.hpp:573
constexpr auto repeat_n
A view factory that repeats a given value n times.
Definition: repeat_n.hpp:91
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 operator!=(T... args)
The <ranges> header from C++20's standard library.
Provides seqan3::views::repeat_n.
Provides std::span from the C++20 standard library.
Provides type traits for working with templates.
Provides the declaration of seqan3::detail::trace_directions.
Provides seqan3::detail::trace_iterator.
Provides seqan3::detail::two_dimensional_matrix.
Provides concepts that do not have equivalents in C++20.
Provides seqan3::views::zip.