SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
alignment_trace_matrix_full_banded.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 <iterator>
13#include <ranges>
14
21
22namespace seqan3::detail
23{
24
49template <typename trace_t, bool coordinate_only = false>
50class alignment_trace_matrix_full_banded :
51 protected alignment_trace_matrix_base<trace_t>,
52 public alignment_matrix_column_major_range_base<alignment_trace_matrix_full_banded<trace_t, coordinate_only>>
53{
54private:
55 static_assert(std::same_as<trace_t, trace_directions> || simd_concept<trace_t>,
56 "Value type must either be a trace_directions object or a simd vector.");
57
59 using matrix_base_t = alignment_trace_matrix_base<trace_t>;
61 using range_base_t =
62 alignment_matrix_column_major_range_base<alignment_trace_matrix_full_banded<trace_t, coordinate_only>>;
64 friend range_base_t;
65
66protected:
67 using typename matrix_base_t::coordinate_type;
68 using typename matrix_base_t::element_type;
69 using typename range_base_t::alignment_column_type;
71 using column_data_view_type =
72 std::conditional_t<coordinate_only,
73 decltype(std::views::iota(coordinate_type{}, coordinate_type{})),
76 std::views::iota(coordinate_type{}, coordinate_type{})))>;
77
78public:
83 using value_type =
84 alignment_trace_matrix_proxy<coordinate_type,
87 using reference = value_type;
89 using iterator = typename range_base_t::iterator;
91 using sentinel = typename range_base_t::sentinel;
92 using typename matrix_base_t::size_type;
94
99 constexpr alignment_trace_matrix_full_banded() = default;
101 constexpr alignment_trace_matrix_full_banded(alignment_trace_matrix_full_banded const &) = default;
103 constexpr alignment_trace_matrix_full_banded(alignment_trace_matrix_full_banded &&) = default;
105 constexpr alignment_trace_matrix_full_banded & operator=(alignment_trace_matrix_full_banded const &) = default;
107 constexpr alignment_trace_matrix_full_banded & operator=(alignment_trace_matrix_full_banded &&) = default;
109 ~alignment_trace_matrix_full_banded() = default;
110
126 template <std::ranges::forward_range first_sequence_t, std::ranges::forward_range second_sequence_t>
127 constexpr alignment_trace_matrix_full_banded(first_sequence_t && first,
128 second_sequence_t && second,
129 align_cfg::band_fixed_size const & band,
130 [[maybe_unused]] trace_t const initial_value = trace_t{})
131 {
132 matrix_base_t::num_cols = static_cast<size_type>(std::ranges::distance(first) + 1);
133 matrix_base_t::num_rows = static_cast<size_type>(std::ranges::distance(second) + 1);
134
135 band_col_index = std::min<int32_t>(std::max<int32_t>(band.upper_diagonal, 0), matrix_base_t::num_cols - 1);
136 band_row_index =
137 std::min<int32_t>(std::abs(std::min<int32_t>(band.lower_diagonal, 0)), matrix_base_t::num_rows - 1);
138 band_size = band_col_index + band_row_index + 1;
139
140 // Reserve one more cell to deal with last cell in the banded column which needs only the diagonal and up cell.
141 if constexpr (!coordinate_only)
142 {
143 matrix_base_t::data = typename matrix_base_t::pool_type{number_rows{static_cast<size_type>(band_size)},
144 number_cols{matrix_base_t::num_cols}};
145 matrix_base_t::cache_left.resize(band_size + 1, initial_value);
146 }
147 }
149
151 auto trace_path(matrix_coordinate const & trace_begin)
152 {
153 static_assert(!coordinate_only, "Requested trace but storing the trace was disabled!");
154
155 using matrix_iter_t = std::ranges::iterator_t<typename matrix_base_t::pool_type>;
156 using trace_iterator_t = trace_iterator_banded<matrix_iter_t>;
157 using path_t = std::ranges::subrange<trace_iterator_t, std::default_sentinel_t>;
158
159 if (trace_begin.row >= static_cast<size_t>(band_size) || trace_begin.col >= matrix_base_t::num_cols)
160 throw std::invalid_argument{"The given coordinate exceeds the trace matrix size."};
161
162 return path_t{trace_iterator_t{matrix_base_t::data.begin() + matrix_offset{trace_begin},
163 column_index_type{band_col_index}},
164 std::default_sentinel};
165 }
166
168 int32_t band_col_index{};
170 int32_t band_row_index{};
172 int32_t band_size{};
173
174private:
176 constexpr alignment_column_type initialise_column(size_type const column_index) noexcept
177 {
178 int32_t slice_begin = std::max<int32_t>(0, band_col_index - column_index);
179 int32_t row_end_index = column_index - band_col_index + band_size;
180 int32_t slice_end = band_size - std::max<int32_t>(row_end_index - matrix_base_t::num_rows, 0);
181
182 assert(row_end_index >= 0);
183 assert(slice_begin >= 0);
184 assert(slice_end > 0);
185 assert(slice_begin < slice_end);
186
187 coordinate_type row_begin{column_index_type{column_index}, row_index_type{static_cast<size_type>(slice_begin)}};
188 coordinate_type row_end{column_index_type{column_index}, row_index_type{static_cast<size_type>(slice_end)}};
189 if constexpr (coordinate_only)
190 {
191 return alignment_column_type{
192 *this,
193 column_data_view_type{std::views::iota(std::move(row_begin), std::move(row_end))}};
194 }
195 else
196 {
197 matrix_coordinate band_begin{row_index_type{static_cast<size_type>(slice_begin)},
198 column_index_type{column_index}};
199 size_type slice_size = slice_end - slice_begin;
200 // We need to jump to the offset.
201 auto col =
202 views::zip(std::span<element_type>{std::addressof(matrix_base_t::data[band_begin]), slice_size},
203 std::span<element_type>{std::addressof(matrix_base_t::cache_left[slice_begin]), slice_size},
204 std::views::iota(std::move(row_begin), std::move(row_end)));
205 return alignment_column_type{*this, column_data_view_type{std::move(col)}};
206 }
207 }
208
210 template <std::random_access_iterator iter_t>
211 constexpr value_type make_proxy(iter_t host_iter) noexcept
212 {
213 if constexpr (coordinate_only)
214 {
215 return {*host_iter, std::ignore, std::ignore, std::ignore, std::ignore};
216 }
217 else
218 {
219 return {
220 std::get<2>(*host_iter), // the current coordinate.
221 std::get<0>(*host_iter), // the current cell.
222 std::get<1>(*(host_iter + 1)), // the last left cell to read from.
223 std::get<1>(*host_iter), // the next left cell to write to.
224 matrix_base_t::cache_up // the last up cell to read/write from/to.
225 };
226 }
227 }
228};
229
230} // namespace seqan3::detail
T addressof(T... args)
Provides seqan3::detail::align_config_band.
Provides seqan3::detail::alignment_matrix_column_major_range_base.
Provides seqan3::detail::alignment_trace_matrix_base.
Provides seqan3::detail::alignment_trace_matrix_proxy.
T declval(T... args)
seqan::stl::views::zip zip
A view adaptor that takes several views and returns tuple-like values from every i-th element of each...
Definition zip.hpp:24
Provides seqan3::detail::trace_iterator_banded.
Provides seqan3::views::zip.
Hide me