IntaRNA 3.4.1
RNA-RNA interaction prediction | C++ API
Loading...
Searching...
No Matches
Matrix.h
Go to the documentation of this file.
1#ifndef INTARNA_MATRIX_H_
2#define INTARNA_MATRIX_H_
3
4#include <algorithm>
5#include <cassert>
6#include <cstddef>
7#include <limits>
8#include <span>
9#include <stdexcept>
10#include <utility>
11#include <vector>
12
13#include "IntaRNA/intarna_config.h"
14#if INTARNA_USE_STD_MDSPAN
15#include <mdspan>
16#else
17#include "mdspan/mdspan.hpp"
18#endif
19
20namespace IntaRNA {
21
22namespace matrix_detail {
23#if INTARNA_USE_STD_MDSPAN
24namespace md = std;
25#else
26namespace md = MDSPAN_IMPL_STANDARD_NAMESPACE;
27#endif
28
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;
33}
34inline std::size_t triangle(std::size_t n) {
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);
38}
39}
40
48template<class T>
49class Matrix {
51 std::vector<T> values;
53 std::size_t rows = 0, columns = 0;
54 using Extents = matrix_detail::md::dextents<std::size_t, 2>;
55public:
57 using value_type = T;
59 Matrix() = default;
67 Matrix(std::size_t rows, std::size_t columns, const T &value = T{});
69 Matrix(const Matrix &) = default;
73 Matrix &operator=(const Matrix &) = default;
78 Matrix(Matrix &&other) noexcept;
84 Matrix &operator=(Matrix &&other) noexcept;
89 std::size_t size1() const noexcept;
94 std::size_t size2() const noexcept;
99 std::size_t storageSize() 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;
117 void clear();
122 void swap(Matrix &other) noexcept;
131 void resize(std::size_t newRows, std::size_t newColumns, bool preserve = true);
132};
133
134template<class T>
135inline
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)
138{}
139
140template<class T>
141inline
142Matrix<T>::Matrix(Matrix &&other) noexcept : values(std::move(other.values)),
143 rows(std::exchange(other.rows, 0)), columns(std::exchange(other.columns, 0))
144{}
145
146template<class T>
147inline
149{
150 if (this != &other) {
151 Matrix moved(std::move(other));
152 swap(moved);
153 }
154 return *this;
155}
156
157template<class T>
158inline
159std::size_t Matrix<T>::size1() const noexcept
160{ return rows; }
161
162template<class T>
163inline
164std::size_t Matrix<T>::size2() const noexcept
165{ return columns; }
166
167template<class T>
168inline
169std::size_t Matrix<T>::storageSize() const noexcept
170{ return values.size(); }
171
172template<class T>
173inline
174T &Matrix<T>::operator()(std::size_t i, std::size_t j)
175{
176 assert(i < rows && j < columns);
177 return matrix_detail::md::mdspan<T, Extents>(values.data(), rows, columns)[i, j];
178}
179
180template<class T>
181inline
182const T &Matrix<T>::operator()(std::size_t i, std::size_t j) const
183{
184 assert(i < rows && j < columns);
185 return matrix_detail::md::mdspan<const T, Extents>(values.data(), rows, columns)[i, j];
186}
187
188template<class T>
189inline
191{ std::fill(values.begin(), values.end(), T{}); }
192
193template<class T>
194inline
195void Matrix<T>::swap(Matrix &other) noexcept
196{
197 values.swap(other.values);
198 std::swap(rows, other.rows);
199 std::swap(columns, other.columns);
200}
201
202template<class T>
203inline
204void Matrix<T>::resize(std::size_t newRows, std::size_t newColumns, bool preserve)
205{
206 if (rows == newRows && columns == newColumns) return;
207 if (!preserve) {
208 values.resize(matrix_detail::product(newRows, newColumns));
209 rows = newRows;
210 columns = newColumns;
211 return;
212 }
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);
217 swap(next);
218}
219
220
226template<class T>
229 std::vector<T> values;
231 std::size_t n = 0;
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);
241public:
243 using value_type = T;
253 UpperTriangularMatrix(std::size_t rows, std::size_t columns);
275 std::size_t size1() const noexcept;
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;
303 void clear();
308 void swap(UpperTriangularMatrix &other) noexcept;
318 void resize(std::size_t rows, std::size_t columns, bool preserve = true);
319};
320
321template<class T>
322inline
323std::size_t UpperTriangularMatrix<T>::offset(std::size_t i, std::size_t j) const noexcept
324{
325 const auto remaining = n - i;
326 // Constructor has already checked that every triangular size fits.
327 const auto tail = remaining % 2 == 0
328 ? (remaining / 2) * (remaining + 1) : remaining * ((remaining + 1) / 2);
329 return values.size() - tail + j - i;
330}
331
332template<class T>
333inline
334std::size_t UpperTriangularMatrix<T>::count(std::size_t rows, std::size_t columns)
335{
336 if (rows != columns) throw std::invalid_argument("upper-triangular matrix must be square");
337 return matrix_detail::triangle(rows);
338}
339
340template<class T>
341inline
342UpperTriangularMatrix<T>::UpperTriangularMatrix(std::size_t rows, std::size_t columns)
343 : values(count(rows, columns)), n(rows)
344{}
345
346template<class T>
347inline
349 : values(std::move(other.values)), n(std::exchange(other.n, 0))
350{}
351
352template<class T>
353inline
355{
356 if (this != &other) {
357 UpperTriangularMatrix moved(std::move(other));
358 swap(moved);
359 }
360 return *this;
361}
362
363template<class T>
364inline
365std::size_t UpperTriangularMatrix<T>::size1() const noexcept
366{ return n; }
367
368template<class T>
369inline
370std::size_t UpperTriangularMatrix<T>::size2() const noexcept
371{ return n; }
372
373template<class T>
374inline
375std::size_t UpperTriangularMatrix<T>::storageSize() const noexcept
376{ return values.size(); }
377
378template<class T>
379inline
380T &UpperTriangularMatrix<T>::operator()(std::size_t i, std::size_t j)
381{
382 assert(i <= j && j < n);
383 return matrix_detail::md::mdspan<T, Extents>(values.data(), values.size())[offset(i, j)];
384}
385
386template<class T>
387inline
388const T &UpperTriangularMatrix<T>::operator()(std::size_t i, std::size_t j) const
389{
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)];
393}
394
395template<class T>
396inline
398{ std::fill(values.begin(), values.end(), T{}); }
399
400template<class T>
401inline
403{
404 values.swap(other.values);
405 std::swap(n, other.n);
406}
407
408template<class T>
409inline
410void UpperTriangularMatrix<T>::resize(std::size_t rows, std::size_t columns, bool preserve)
411{
412 const auto cells = count(rows, columns);
413 if (rows == n) return;
414 if (!preserve) {
415 values.resize(cells);
416 n = rows;
417 return;
418 }
419 UpperTriangularMatrix next(rows, columns);
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);
423 swap(next);
424}
425
426
432template<class T>
435 Matrix<T> band;
437 std::size_t columns = 0;
441 static std::size_t width(std::size_t columns, std::size_t lower, std::size_t upper);
442public:
444 using value_type = T;
446 UpperBandedMatrix() = default;
456 UpperBandedMatrix(std::size_t rows, std::size_t columns, std::size_t lower, std::size_t upper);
478 std::size_t size1() const noexcept;
483 std::size_t size2() const noexcept;
488 std::size_t storageSize() const noexcept;
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;
521 void clear();
526 void swap(UpperBandedMatrix &other) noexcept;
538 void resize(std::size_t rows, std::size_t newColumns, std::size_t lower,
539 std::size_t upper, bool preserve = true);
540};
541
542template<class T>
543inline
544std::size_t UpperBandedMatrix<T>::width(std::size_t columns, std::size_t lower, std::size_t upper)
545{
546 if (lower != 0) throw std::invalid_argument("upper-banded matrix requires lower=0");
547 return upper >= columns ? columns : upper + 1;
548}
549
550template<class T>
551inline
552UpperBandedMatrix<T>::UpperBandedMatrix(std::size_t rows, std::size_t columns, std::size_t lower, std::size_t upper)
553 : band(rows, width(columns, lower, upper)), columns(columns)
554{}
555
556template<class T>
557inline
559 : band(std::move(other.band)), columns(std::exchange(other.columns, 0))
560{}
561
562template<class T>
563inline
565{
566 if (this != &other) {
567 UpperBandedMatrix moved(std::move(other));
568 swap(moved);
569 }
570 return *this;
571}
572
573template<class T>
574inline
575std::size_t UpperBandedMatrix<T>::size1() const noexcept
576{ return band.size1(); }
577
578template<class T>
579inline
580std::size_t UpperBandedMatrix<T>::size2() const noexcept
581{ return columns; }
582
583template<class T>
584inline
585std::size_t UpperBandedMatrix<T>::storageSize() const noexcept
586{ return band.storageSize(); }
587
588template<class T>
589inline
590T &UpperBandedMatrix<T>::operator()(std::size_t i, std::size_t j)
591{
592 assert(i < size1() && j < columns && i <= j && j - i < band.size2());
593 return band(i, j - i);
594}
595
596template<class T>
597inline
598const T &UpperBandedMatrix<T>::operator()(std::size_t i, std::size_t j) const
599{
600 assert(i < size1() && j < columns);
601 static const T zero{};
602 return i > j || j - i >= band.size2() ? zero : band(i, j - i);
603}
604
605template<class T>
606inline
607std::span<T> UpperBandedMatrix<T>::row(std::size_t i)
608{
609 assert(i < size1());
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};
612}
613
614template<class T>
615inline
616std::span<const T> UpperBandedMatrix<T>::row(std::size_t i) const
617{
618 assert(i < size1());
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};
621}
622
623template<class T>
624inline
626{ band.clear(); }
627
628template<class T>
629inline
631{
632 band.swap(other.band);
633 std::swap(columns, other.columns);
634}
635
636template<class T>
637inline
638void UpperBandedMatrix<T>::resize(std::size_t rows, std::size_t newColumns, std::size_t lower,
639 std::size_t upper, bool preserve)
640{
641 UpperBandedMatrix next(rows, newColumns, lower, upper);
642 if (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);
648 }
649 swap(next);
650}
651
652
653} // namespace IntaRNA
654#endif
Definition Matrix.h:49
void swap(Matrix &other) noexcept
Definition Matrix.h:195
std::size_t size2() const noexcept
Definition Matrix.h:164
Matrix()=default
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
Definition Matrix.h:433
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
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
Definition Matrix.h:227
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
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