1#ifndef INTARNA_MATRIX_H_
2#define INTARNA_MATRIX_H_
13#include "IntaRNA/intarna_config.h"
14#if INTARNA_USE_STD_MDSPAN
17#include "mdspan/mdspan.hpp"
22namespace matrix_detail {
23#if INTARNA_USE_STD_MDSPAN
26namespace md = MDSPAN_IMPL_STANDARD_NAMESPACE;
29inline std::size_t
product(std::size_t rows, std::size_t columns) {
30 if (columns != 0 && rows > std::numeric_limits<std::size_t>::max() / columns)
31 throw std::length_error(
"matrix dimensions overflow");
32 return rows * columns;
35 if (n == std::numeric_limits<std::size_t>::max())
36 throw std::length_error(
"matrix dimensions overflow");
37 return n % 2 == 0 ?
product(n / 2, n + 1) :
product(n, (n + 1) / 2);
51 std::vector<T> values;
53 std::size_t rows = 0, columns = 0;
54 using Extents = matrix_detail::md::dextents<std::size_t, 2>;
67 Matrix(std::size_t rows, std::size_t columns,
const T &value = T{});
89 std::size_t
size1() const noexcept;
94 std::
size_t size2() const noexcept;
106 T &operator()(std::
size_t i, std::
size_t j);
113 const T &operator()(std::
size_t i, std::
size_t j) const;
131 void resize(std::
size_t newRows, std::
size_t newColumns,
bool preserve = true);
136Matrix<T>::
Matrix(std::
size_t rows, std::
size_t columns, const T &value)
137 : values(matrix_detail::product(rows, columns), value), rows(rows), columns(columns)
143 rows(std::exchange(other.rows, 0)), columns(std::exchange(other.columns, 0))
150 if (
this != &other) {
151 Matrix moved(std::move(other));
170{
return values.size(); }
176 assert(i < rows && j < columns);
177 return matrix_detail::md::mdspan<T, Extents>(values.data(), rows, columns)[i, j];
184 assert(i < rows && j < columns);
185 return matrix_detail::md::mdspan<const T, Extents>(values.data(), rows, columns)[i, j];
191{ std::fill(values.begin(), values.end(), T{}); }
197 values.swap(other.values);
198 std::swap(rows, other.rows);
199 std::swap(columns, other.columns);
206 if (rows == newRows && columns == newColumns)
return;
210 columns = newColumns;
213 Matrix next(newRows, newColumns);
214 for (std::size_t i = 0; i < std::min(rows, newRows); ++i)
215 for (std::size_t j = 0; j < std::min(columns, newColumns); ++j)
216 next(i, j) = (*this)(i, j);
229 std::vector<T> values;
232 using Extents = matrix_detail::md::dextents<std::size_t, 1>;
236 std::size_t offset(std::size_t i, std::size_t j)
const noexcept;
240 static std::size_t count(std::size_t rows, std::size_t columns);
280 std::
size_t size2() const noexcept;
285 std::
size_t storageSize() const noexcept;
292 T &operator()(std::
size_t i, std::
size_t j);
299 const T &operator()(std::
size_t i, std::
size_t j) const;
318 void resize(std::
size_t rows, std::
size_t columns,
bool preserve = true);
325 const auto remaining = n - i;
327 const auto tail = remaining % 2 == 0
328 ? (remaining / 2) * (remaining + 1) : remaining * ((remaining + 1) / 2);
329 return values.size() - tail + j - i;
336 if (rows != columns)
throw std::invalid_argument(
"upper-triangular matrix must be square");
337 return matrix_detail::triangle(rows);
343 : values(count(rows, columns)), n(rows)
349 : values(std::move(other.values)), n(std::exchange(other.n, 0))
356 if (
this != &other) {
376{
return values.size(); }
382 assert(i <= j && j < n);
383 return matrix_detail::md::mdspan<T, Extents>(values.data(), values.size())[offset(i, j)];
390 assert(i < n && j < n);
391 static const T zero{};
392 return i > j ? zero : matrix_detail::md::mdspan<const T, Extents>(values.data(), values.size())[offset(i, j)];
398{ std::fill(values.begin(), values.end(), T{}); }
404 values.swap(other.values);
405 std::swap(n, other.n);
412 const auto cells = count(rows, columns);
413 if (rows == n)
return;
415 values.resize(cells);
420 for (std::size_t i = 0; i < std::min(n, rows); ++i)
421 for (std::size_t j = i; j < std::min(n, rows); ++j)
422 next(i, j) = (*this)(i, j);
437 std::size_t columns = 0;
441 static std::size_t width(std::size_t columns, std::size_t lower, std::size_t upper);
495 T &operator()(std::
size_t i, std::
size_t j);
502 const T &operator()(std::
size_t i, std::
size_t j) const;
511 std::span<T>
row(std::
size_t i);
517 std::span<const T>
row(std::
size_t i) const;
538 void resize(std::
size_t rows, std::
size_t newColumns, std::
size_t lower,
539 std::
size_t upper,
bool preserve = true);
544std::
size_t UpperBandedMatrix<T>::width(std::
size_t columns, std::
size_t lower, std::
size_t upper)
546 if (lower != 0)
throw std::invalid_argument(
"upper-banded matrix requires lower=0");
547 return upper >= columns ? columns : upper + 1;
553 : band(rows, width(columns, lower, upper)), columns(columns)
559 : band(std::move(other.band)), columns(std::exchange(other.columns, 0))
566 if (
this != &other) {
576{
return band.
size1(); }
592 assert(i < size1() && j < columns && i <= j && j - i < band.
size2());
593 return band(i, j - i);
600 assert(i < size1() && j < columns);
601 static const T zero{};
602 return i > j || j - i >= band.
size2() ? zero : band(i, j - i);
610 const auto count = i < columns ? std::min(band.
size2(), columns-i) : 0;
611 return count == 0 ? std::span<T>{} : std::span<T>{&band(i, 0), count};
619 const auto count = i < columns ? std::min(band.
size2(), columns-i) : 0;
620 return count == 0 ? std::span<const T>{} : std::span<const T>{&band(i, 0), count};
632 band.
swap(other.band);
633 std::swap(columns, other.columns);
639 std::size_t upper,
bool preserve)
643 for (std::size_t i = 0; i < std::min(size1(), rows); ++i)
644 for (std::size_t d = 0; d < std::min(band.
size2(), next.band.size2())
645 && i < std::min(columns, newColumns)
646 && d < std::min(columns, newColumns) - i; ++d)
647 next.band(i, d) = band(i, d);
void swap(Matrix &other) noexcept
Definition Matrix.h:195
std::size_t size2() const noexcept
Definition Matrix.h:164
T & operator()(std::size_t i, std::size_t j)
Definition Matrix.h:174
std::size_t size1() const noexcept
Definition Matrix.h:159
Matrix & operator=(const Matrix &)=default
void resize(std::size_t newRows, std::size_t newColumns, bool preserve=true)
Definition Matrix.h:204
Matrix(Matrix &&other) noexcept
Definition Matrix.h:142
std::size_t storageSize() const noexcept
Definition Matrix.h:169
T value_type
Type of one stored cell.
Definition Matrix.h:57
void clear()
Definition Matrix.h:190
Matrix & operator=(Matrix &&other) noexcept
Definition Matrix.h:148
Matrix(const Matrix &)=default
Matrix(std::size_t rows, std::size_t columns, const T &value=T{})
Definition Matrix.h:136
UpperBandedMatrix(const UpperBandedMatrix &)=default
UpperBandedMatrix & operator=(UpperBandedMatrix &&other) noexcept
Definition Matrix.h:564
UpperBandedMatrix(std::size_t rows, std::size_t columns, std::size_t lower, std::size_t upper)
Definition Matrix.h:552
UpperBandedMatrix(UpperBandedMatrix &&other) noexcept
Definition Matrix.h:558
std::span< T > row(std::size_t i)
Definition Matrix.h:607
UpperBandedMatrix()=default
T & operator()(std::size_t i, std::size_t j)
Definition Matrix.h:590
std::size_t size1() const noexcept
Definition Matrix.h:575
std::size_t size2() const noexcept
Definition Matrix.h:580
std::size_t storageSize() const noexcept
Definition Matrix.h:585
void swap(UpperBandedMatrix &other) noexcept
Definition Matrix.h:630
UpperBandedMatrix & operator=(const UpperBandedMatrix &)=default
T value_type
Type of one stored cell.
Definition Matrix.h:444
void clear()
Definition Matrix.h:625
void resize(std::size_t rows, std::size_t newColumns, std::size_t lower, std::size_t upper, bool preserve=true)
Definition Matrix.h:638
T value_type
Type of one stored cell.
Definition Matrix.h:243
std::size_t storageSize() const noexcept
Definition Matrix.h:375
void clear()
Definition Matrix.h:397
T & operator()(std::size_t i, std::size_t j)
Definition Matrix.h:380
void swap(UpperTriangularMatrix &other) noexcept
Definition Matrix.h:402
void resize(std::size_t rows, std::size_t columns, bool preserve=true)
Definition Matrix.h:410
UpperTriangularMatrix(UpperTriangularMatrix &&other) noexcept
Definition Matrix.h:348
UpperTriangularMatrix(std::size_t rows, std::size_t columns)
Definition Matrix.h:342
UpperTriangularMatrix()=default
std::size_t size1() const noexcept
Definition Matrix.h:365
UpperTriangularMatrix & operator=(UpperTriangularMatrix &&other) noexcept
Definition Matrix.h:354
UpperTriangularMatrix & operator=(const UpperTriangularMatrix &)=default
std::size_t size2() const noexcept
Definition Matrix.h:370
UpperTriangularMatrix(const UpperTriangularMatrix &)=default
std::size_t product(std::size_t rows, std::size_t columns)
Definition Matrix.h:29
std::size_t triangle(std::size_t n)
Definition Matrix.h:34
Definition Accessibility.h:13