SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
alignment_trace_matrix_full_banded.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, 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 
21 #include <seqan3/std/iterator>
22 #include <seqan3/std/ranges>
23 
24 namespace seqan3::detail
25 {
26 
50 template <typename trace_t, bool coordinate_only = false>
51 class alignment_trace_matrix_full_banded :
52  protected alignment_trace_matrix_base<trace_t>,
53  public alignment_matrix_column_major_range_base<alignment_trace_matrix_full_banded<trace_t, coordinate_only>>
54 {
55 private:
56  static_assert(std::same_as<trace_t, trace_directions> || simd_concept<trace_t>,
57  "Value type must either be a trace_directions object or a simd vector.");
58 
60  using matrix_base_t = alignment_trace_matrix_base<trace_t>;
62  using range_base_t = alignment_matrix_column_major_range_base<alignment_trace_matrix_full_banded<trace_t,
63  coordinate_only>>;
65  friend range_base_t;
66 
67 protected:
68  using typename matrix_base_t::element_type;
69  using typename matrix_base_t::coordinate_type;
70  using typename range_base_t::alignment_column_type;
72  using column_data_view_type = std::conditional_t<coordinate_only,
73  decltype(std::views::iota(coordinate_type{}, coordinate_type{})),
74  decltype(views::zip(std::declval<std::span<element_type>>(),
76  std::views::iota(coordinate_type{}, coordinate_type{})))>;
77 
78 public:
82  using value_type = alignment_trace_matrix_proxy<coordinate_type,
84  std::conditional_t<coordinate_only,
85  detail::ignore_t const,
86  trace_t>>;
88  using reference = value_type;
90  using iterator = typename range_base_t::iterator;
92  using sentinel = typename range_base_t::sentinel;
93  using typename matrix_base_t::size_type;
95 
99  constexpr alignment_trace_matrix_full_banded() = default;
102  constexpr alignment_trace_matrix_full_banded(alignment_trace_matrix_full_banded const &) = default;
104  constexpr alignment_trace_matrix_full_banded(alignment_trace_matrix_full_banded &&) = default;
106  constexpr alignment_trace_matrix_full_banded & operator=(alignment_trace_matrix_full_banded const &) = default;
108  constexpr alignment_trace_matrix_full_banded & operator=(alignment_trace_matrix_full_banded &&) = default;
110  ~alignment_trace_matrix_full_banded() = default;
111 
127  template <std::ranges::forward_range first_sequence_t, std::ranges::forward_range second_sequence_t>
128  constexpr alignment_trace_matrix_full_banded(first_sequence_t && first,
129  second_sequence_t && second,
130  align_cfg::band_fixed_size const & band,
131  [[maybe_unused]] trace_t const initial_value = trace_t{})
132  {
133  matrix_base_t::num_cols = static_cast<size_type>(std::ranges::distance(first) + 1);
134  matrix_base_t::num_rows = static_cast<size_type>(std::ranges::distance(second) + 1);
135 
136  band_col_index = std::min<int32_t>(std::max<int32_t>(band.upper_diagonal, 0),
137  matrix_base_t::num_cols - 1);
138  band_row_index = std::min<int32_t>(std::abs(std::min<int32_t>(band.lower_diagonal, 0)),
139  matrix_base_t::num_rows - 1);
140  band_size = band_col_index + band_row_index + 1;
141 
142  // Reserve one more cell to deal with last cell in the banded column which needs only the diagonal and up cell.
143  if constexpr (!coordinate_only)
144  {
145  matrix_base_t::data = typename matrix_base_t::pool_type{number_rows{static_cast<size_type>(band_size)},
146  number_cols{matrix_base_t::num_cols}};
147  matrix_base_t::cache_left.resize(band_size + 1, initial_value);
148  }
149  }
151 
153  auto trace_path(matrix_coordinate const & trace_begin)
154  {
155  static_assert(!coordinate_only, "Requested trace but storing the trace was disabled!");
156 
157  using matrix_iter_t = std::ranges::iterator_t<typename matrix_base_t::pool_type>;
158  using trace_iterator_t = trace_iterator_banded<matrix_iter_t>;
159  using path_t = std::ranges::subrange<trace_iterator_t, std::default_sentinel_t>;
160 
161  if (trace_begin.row >= static_cast<size_t>(band_size) || trace_begin.col >= matrix_base_t::num_cols)
162  throw std::invalid_argument{"The given coordinate exceeds the trace matrix size."};
163 
164  return path_t{trace_iterator_t{matrix_base_t::data.begin() + matrix_offset{trace_begin},
165  column_index_type{band_col_index}},
166  std::default_sentinel};
167  }
168 
170  int32_t band_col_index{};
172  int32_t band_row_index{};
174  int32_t band_size{};
175 
176 private:
178  constexpr alignment_column_type initialise_column(size_type const column_index) noexcept
179  {
180  int32_t slice_begin = std::max<int32_t>(0, band_col_index - column_index);
181  int32_t row_end_index = column_index - band_col_index + band_size;
182  int32_t slice_end = band_size - std::max<int32_t>(row_end_index - matrix_base_t::num_rows, 0);
183 
184  assert(row_end_index >= 0);
185  assert(slice_begin >= 0);
186  assert(slice_end > 0);
187  assert(slice_begin < slice_end);
188 
189  coordinate_type row_begin{column_index_type{column_index}, row_index_type{static_cast<size_type>(slice_begin)}};
190  coordinate_type row_end{column_index_type{column_index}, row_index_type{static_cast<size_type>(slice_end)}};
191  if constexpr (coordinate_only)
192  {
193  return alignment_column_type{*this,
194  column_data_view_type{std::views::iota(std::move(row_begin),
195  std::move(row_end))}};
196  }
197  else
198  {
199  matrix_coordinate band_begin{row_index_type{static_cast<size_type>(slice_begin)},
200  column_index_type{column_index}};
201  size_type slice_size = slice_end - slice_begin;
202  // We need to jump to the offset.
203  auto col = views::zip(
204  std::span<element_type>{std::addressof(matrix_base_t::data[band_begin]), slice_size},
205  std::span<element_type>{std::addressof(matrix_base_t::cache_left[slice_begin]), slice_size},
206  std::views::iota(std::move(row_begin), std::move(row_end)));
207  return alignment_column_type{*this, column_data_view_type{std::move(col)}};
208  }
209  }
210 
212  template <std::random_access_iterator iter_t>
213  constexpr value_type make_proxy(iter_t host_iter) noexcept
214  {
215  if constexpr (coordinate_only)
216  {
217  return {*host_iter, std::ignore, std::ignore, std::ignore, std::ignore};
218  }
219  else
220  {
221  return {std::get<2>(*host_iter), // the current coordinate.
222  std::get<0>(*host_iter), // the current cell.
223  std::get<1>(*(host_iter + 1)), // the last left cell to read from.
224  std::get<1>(*host_iter), // the next left cell to write to.
225  matrix_base_t::cache_up // the last up cell to read/write from/to.
226  };
227  }
228  }
229 };
230 
231 } // namespace seqan3::detail
zip.hpp
Provides seqan3::views::zip.
std::span
iterator
Provides C++20 additions to the <iterator> header.
alignment_trace_matrix_proxy.hpp
Provides seqan3::detail::alignment_trace_matrix_proxy.
std::addressof
T addressof(T... args)
align_config_band.hpp
Provides seqan3::detail::align_config_band.
seqan3::views::move
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:68
std::invalid_argument
alignment_trace_matrix_base.hpp
Provides seqan3::detail::alignment_trace_matrix_base.
ranges
Adaptations of concepts from the Ranges TS.
std::conditional_t
trace_iterator_banded.hpp
Provides seqan3::detail::trace_iterator_banded.
alignment_matrix_column_major_range_base.hpp
Provides seqan3::detail::alignment_matrix_column_major_range_base.
std::declval
T declval(T... args)