SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
trace_matrix_full.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 
15 #include <seqan3/std/ranges>
16 #include <seqan3/std/span>
17 #include <vector>
18 
28 
29 namespace seqan3::detail
30 {
31 
50 template <typename trace_t>
52  requires std::same_as<trace_t, trace_directions>
54 class trace_matrix_full
55 {
56 private:
58  using matrix_t = two_dimensional_matrix<trace_t,
59  aligned_allocator<trace_t, sizeof(trace_t)>,
60  matrix_major_order::column>;
62  using physical_column_t = std::vector<trace_t>;
64  using virtual_column_t = decltype(views::repeat_n(trace_t{}, 1));
65 
66  class iterator;
67 
69  matrix_t complete_matrix{};
71  physical_column_t horizontal_column{};
73  virtual_column_t vertical_column{};
75  size_t column_count{};
77  size_t row_count{};
78 
79 public:
83  trace_matrix_full() = default;
84  trace_matrix_full(trace_matrix_full const &) = default;
85  trace_matrix_full(trace_matrix_full &&) = default;
86  trace_matrix_full & operator=(trace_matrix_full const &) = default;
87  trace_matrix_full & operator=(trace_matrix_full &&) = default;
88  ~trace_matrix_full() = default;
89 
91 
114  template <std::integral column_index_t, std::integral row_index_t>
115  void resize(column_index_type<column_index_t> const column_count,
116  row_index_type<row_index_t> const row_count)
117  {
118  this->column_count = column_count.get();
119  this->row_count = row_count.get();
120  complete_matrix.resize(number_rows{this->row_count}, number_cols{this->column_count});
121  horizontal_column.resize(this->row_count);
122  vertical_column = views::repeat_n(trace_t{}, this->row_count);
123  }
124 
131  auto trace_path(matrix_coordinate const & trace_begin) const
132  {
133  using matrix_iter_t = std::ranges::iterator_t<matrix_t const>;
134  using trace_iterator_t = trace_iterator<matrix_iter_t>;
135  using path_t = std::ranges::subrange<trace_iterator_t, std::default_sentinel_t>;
136 
137  if (trace_begin.row >= row_count || trace_begin.col >= column_count)
138  throw std::invalid_argument{"The given coordinate exceeds the matrix in vertical or horizontal direction."};
139 
140  return path_t{trace_iterator_t{complete_matrix.begin() + matrix_offset{trace_begin}}, std::default_sentinel};
141  }
142 
147  iterator begin()
148  {
149  return iterator{*this, 0u};
150  }
151 
153  iterator begin() const = delete;
154 
156  iterator end()
157  {
158  return iterator{*this, column_count};
159  }
160 
162  iterator end() const = delete;
164 };
165 
175 template <typename trace_t>
177  requires std::same_as<trace_t, trace_directions>
179 class trace_matrix_full<trace_t>::iterator
180 {
181 private:
183  using single_trace_column_type = std::span<trace_t>;
185  using matrix_column_type = decltype(views::zip(std::declval<single_trace_column_type>(),
186  std::declval<physical_column_t &>(),
187  std::declval<virtual_column_t &>()));
189  using matrix_column_value_t = std::vector<std::ranges::range_value_t<matrix_column_type>>;
190 
191  // Defines a proxy that can be converted to the value type.
192  class column_proxy;
193 
195  trace_matrix_full * host_ptr{nullptr};
197  size_t current_column_id{};
198 
199 public:
204  using value_type = matrix_column_value_t;
206  using reference = column_proxy;
208  using pointer = void;
210  using difference_type = std::ptrdiff_t;
212  using iterator_category = std::input_iterator_tag;
214 
218  iterator() noexcept = default;
219  iterator(iterator const &) noexcept = default;
220  iterator(iterator &&) noexcept = default;
221  iterator & operator=(iterator const &) noexcept = default;
222  iterator & operator=(iterator &&) noexcept = default;
223  ~iterator() = default;
224 
230  explicit iterator(trace_matrix_full & host_matrix, size_t const initial_column_id) noexcept :
231  host_ptr{std::addressof(host_matrix)},
232  current_column_id{initial_column_id}
233  {}
235 
240  reference operator*() const
241  {
242  auto column_begin = host_ptr->complete_matrix.data() + current_column_id * host_ptr->row_count;
243  single_trace_column_type single_trace_column{column_begin, column_begin + host_ptr->row_count};
244 
245  return column_proxy{views::zip(std::move(single_trace_column),
246  host_ptr->horizontal_column,
247  host_ptr->vertical_column)};
248  }
250 
255  iterator & operator++()
256  {
257  ++current_column_id;
258  return *this;
259  }
260 
262  void operator++(int)
263  {
264  ++(*this);
265  }
267 
272  friend bool operator==(iterator const & lhs, iterator const & rhs) noexcept
273  {
274  return lhs.current_column_id == rhs.current_column_id;
275  }
276 
278  friend bool operator!=(iterator const & lhs, iterator const & rhs) noexcept
279  {
280  return !(lhs == rhs);
281  }
283 };
284 
293 template <typename trace_t>
295  requires std::same_as<trace_t, trace_directions>
297 class trace_matrix_full<trace_t>::iterator::column_proxy : public std::ranges::view_interface<column_proxy>
298 {
299 private:
301  matrix_column_type column{};
302 
303 public:
307  column_proxy() = default;
308  column_proxy(column_proxy const &) = default;
309  column_proxy(column_proxy &&) = default;
310  column_proxy & operator=(column_proxy const &) = default;
311  column_proxy & operator=(column_proxy &&) = default;
312  ~column_proxy() = default;
313 
318  explicit column_proxy(matrix_column_type && column) noexcept : column{std::move(column)}
319  {}
321 
326  std::ranges::iterator_t<matrix_column_type> begin()
327  {
328  return column.begin();
329  }
331  std::ranges::iterator_t<matrix_column_type> begin() const = delete;
332 
334  std::ranges::sentinel_t<matrix_column_type> end()
335  {
336  return column.end();
337  }
338 
340  std::ranges::sentinel_t<matrix_column_type> end() const = delete;
342 
344  constexpr operator matrix_column_value_t() const
345  {
346  matrix_column_value_t target{};
347  std::ranges::copy(column, std::cpp20::back_inserter(target));
348  return target;
349  }
350 };
351 
352 } // namespace seqan3::detail
T addressof(T... args)
T begin(T... args)
Provides type traits for working with templates.
T end(T... args)
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
constexpr auto zip
A zip view.
Definition: zip.hpp:29
constexpr auto repeat_n
A view factory that repeats a given value n times.
Definition: repeat_n.hpp:95
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:74
Provides seqan3::detail::matrix_index, seqan3::detail::matrix_coordinate and associated strong types.
T operator!=(T... args)
Adaptations of concepts from the Ranges TS.
Provides std::span from the C++20 standard library.
Provides the declaration of seqan3::detail::trace_directions.
Provides seqan3::detail::trace_iterator.
Provides seqan3::detail::two_dimensional_matrix.
Provides seqan3::aligned_allocator.
Provides seqan3::views::repeat_n.
Provides seqan3::views::zip.