26 namespace seqan3::detail
31 struct number_cols : strong_type<size_t, number_cols>
34 using strong_type<size_t, number_cols>::strong_type;
39 struct number_rows : strong_type<size_t, number_rows>
42 using strong_type<size_t, number_rows>::strong_type;
61 template <
typename value_t,
63 matrix_major_order order = matrix_major_order::row>
64 class two_dimensional_matrix
75 template <
bool const_range>
83 using value_type =
typename storage_type::value_type;
84 using reference =
typename storage_type::reference;
85 using const_reference =
typename storage_type::const_reference;
86 using pointer =
typename storage_type::pointer;
87 using const_pointer =
typename storage_type::const_pointer;
88 using difference_type =
typename storage_type::difference_type;
89 using size_type =
typename storage_type::size_type;
90 using iterator = basic_iterator<false>;
91 using const_iterator = basic_iterator<true>;
97 two_dimensional_matrix() =
default;
98 two_dimensional_matrix(two_dimensional_matrix
const &) =
default;
99 two_dimensional_matrix(two_dimensional_matrix &&) =
default;
100 two_dimensional_matrix & operator=(two_dimensional_matrix
const &) =
default;
101 two_dimensional_matrix & operator=(two_dimensional_matrix &&) =
default;
102 ~two_dimensional_matrix() =
default;
108 two_dimensional_matrix(number_rows
const row_dim, number_cols
const col_dim) :
109 row_dim{row_dim.
get()}, col_dim{col_dim.
get()}
111 storage.resize(row_dim.get() * col_dim.get());
120 template <std::ranges::forward_range entries_t>
122 requires (std::convertible_to<std::ranges::range_value_t<entries_t>, value_type>)
124 two_dimensional_matrix(number_rows const row_dim, number_cols const col_dim, entries_t entries) :
125 row_dim{row_dim.get()},
126 col_dim{col_dim.get()}
128 static_assert(std::move_constructible<std::ranges::range_value_t<entries_t>>,
"The value type must be moveable.");
130 assert(
static_cast<size_t>(std::ranges::distance(entries)) == (row_dim.get() * col_dim.get()));
131 storage.resize(row_dim.get() * col_dim.get());
136 two_dimensional_matrix(number_rows
const row_dim, number_cols
const col_dim, storage_type entries) :
137 row_dim{row_dim.
get()},
138 col_dim{col_dim.
get()}
140 assert(
static_cast<size_t>(std::ranges::distance(entries)) == (row_dim.get() * col_dim.get()));
169 template <
typename other_value_t,
typename other_allocator_t, matrix_major_order other_order>
171 requires std::assignable_from<other_value_t &, value_t &>
173 explicit constexpr two_dimensional_matrix(two_dimensional_matrix<other_value_t,
175 other_order>
const & matrix) :
176 two_dimensional_matrix{number_rows{matrix.rows()}, number_cols{matrix.cols()}}
178 for (
size_t i = 0; i < cols(); ++i)
180 for (
size_t j = 0; j < rows(); ++j)
182 matrix_coordinate coord{row_index_type{j}, column_index_type{i}};
183 (*this)[coord] = matrix[coord];
192 constexpr reference operator[](matrix_coordinate
const & coordinate) noexcept
194 assert(coordinate.col < cols());
195 assert(coordinate.row < rows());
197 return *(
begin() + matrix_offset{row_index_type{
static_cast<std::ptrdiff_t>(coordinate.row)},
202 constexpr const_reference operator[](matrix_coordinate
const & coordinate)
const noexcept
204 assert(coordinate.col < cols());
205 assert(coordinate.row < rows());
207 return *(
begin() + matrix_offset{row_index_type{
static_cast<std::ptrdiff_t>(coordinate.row)},
212 constexpr reference
at(matrix_coordinate
const & coordinate)
214 if (coordinate.col >= cols())
215 throw std::invalid_argument{
"Column index is out of range. Please check the dimensions of the matrix."};
216 if (coordinate.row >= rows())
217 throw std::invalid_argument{
"Row index is out of range. Please check the dimensions of the matrix."};
219 return (*
this)[coordinate];
223 constexpr const_reference
at(matrix_coordinate
const & coordinate)
const
225 if (coordinate.col >= cols())
226 throw std::invalid_argument{
"Column index is out of range. Please check the dimensions of the matrix."};
227 if (coordinate.row >= rows())
228 throw std::invalid_argument{
"Row index is out of range. Please check the dimensions of the matrix."};
230 return (*
this)[coordinate];
238 void resize(number_rows
const row_dim, number_cols
const col_dim)
240 this->row_dim = row_dim.get();
241 this->col_dim = col_dim.get();
242 storage.resize(this->row_dim * this->col_dim);
246 size_t rows() const noexcept
252 size_t cols() const noexcept
258 constexpr pointer
data() noexcept
260 return storage.data();
264 constexpr const_pointer
data() const noexcept
266 return storage.data();
274 constexpr iterator
begin() noexcept
276 return {*
this, storage.begin()};
279 constexpr const_iterator
begin() const noexcept
281 return {*
this, storage.begin()};
285 constexpr const_iterator
cbegin() const noexcept
291 constexpr iterator
end() noexcept
293 return {*
this, storage.end()};
297 constexpr const_iterator
end() const noexcept
299 return {*
this, storage.end()};
303 constexpr const_iterator
cend() const noexcept
311 storage_type storage;
324 template <
typename value_t,
typename allocator_t, matrix_major_order order>
325 template <
bool const_range>
326 class two_dimensional_matrix<value_t, allocator_t, order>::basic_iterator :
327 public two_dimensional_matrix_iterator_base<basic_iterator<const_range>, order>
331 using parent_t = detail::maybe_const_range_t<const_range, two_dimensional_matrix>;
334 using base_t = two_dimensional_matrix_iterator_base<basic_iterator, order>;
337 template <
typename derived_t, matrix_major_order other_order>
339 requires is_type_specialisation_of_v<derived_t, basic_iterator> && (other_order == order)
341 friend class two_dimensional_matrix_iterator_base;
344 template <
bool other_const_range>
345 friend class basic_iterator;
348 using storage_iterator = detail::maybe_const_iterator_t<const_range, storage_type>;
360 using pointer =
typename storage_iterator::pointer;
370 constexpr basic_iterator() =
default;
371 constexpr basic_iterator(basic_iterator
const &) =
default;
372 constexpr basic_iterator(basic_iterator &&) =
default;
373 constexpr basic_iterator & operator=(basic_iterator
const &) =
default;
374 constexpr basic_iterator & operator=(basic_iterator &&) =
default;
375 ~basic_iterator() =
default;
381 constexpr basic_iterator(parent_t & matrix, storage_iterator iter) :
387 constexpr basic_iterator(basic_iterator<!const_range>
const & other) noexcept
391 : matrix_ptr{other.matrix_ptr},
392 host_iter{other.host_iter}
397 using base_t::operator+=;
400 constexpr basic_iterator & operator+=(matrix_offset
const & offset) noexcept
402 assert(matrix_ptr !=
nullptr);
404 if constexpr (order == matrix_major_order::column)
406 host_iter += (
offset.col * matrix_ptr->rows());
412 host_iter += (
offset.row * matrix_ptr->cols());
418 matrix_coordinate coordinate() const noexcept
420 assert(matrix_ptr !=
nullptr);
422 auto diff = *
this - matrix_ptr->begin();
423 if constexpr (order == matrix_major_order::column)
424 return {row_index_type{diff % matrix_ptr->rows()}, column_index_type{diff / matrix_ptr->rows()}};
426 return {row_index_type{diff / matrix_ptr->cols()}, column_index_type{diff % matrix_ptr->cols()}};
431 parent_t * matrix_ptr{
nullptr};
432 storage_iterator host_iter{};
Adaptations of algorithms from the Ranges TS.
Provides various transformation traits used by the range module.
Provides seqan3::detail::deferred_crtp_base.
Provides type traits for working with templates.
@ offset
Sequence (seqan3::field::seq) relative start position (0-based), unsigned value.
typename decltype(detail::at< idx >(list_t{}))::type at
Return the type at given index from the type list.
Definition: traits.hpp:260
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.
constexpr auto const & get(configuration< configs_t... > const &config) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:429
Adaptations of concepts from the Ranges TS.
Provides seqan3::detail::two_dimensional_matrix_iterator_base.