10#define SPARSEMATRIX_HH
23#include "densematrix.hh"
30template <
typename REAL>
43 std::vector<REAL> _data;
48 std::vector<size_type> _colIndices;
49 std::vector<size_type> _rowPtr;
54 static bool bScientific;
58 static const REAL _zero;
68 [](
const std::string &a,
REAL b) {
69 return a +
", " + std::to_string(b);
77 template <
class T,
template <
class...>
class Template>
78 struct is_specialization : std::false_type {};
80 template <
template <
class...>
class Template,
class... Args>
81 struct is_specialization<Template<Args...>, Template> : std::true_type {};
83 bool checkIfAccessIsInBounds(
const size_type row_index,
85 if (not (row_index < m_rows)) {
86 HDNUM_ERROR(
"Out of bounds access: row too big! -> " +
87 std::to_string(row_index) +
" is not < " +
88 std::to_string(m_rows));
91 if (not (col_index < m_cols)) {
92 HDNUM_ERROR(
"Out of bounds access: column too big! -> " +
93 std::to_string(col_index) +
" is not < " +
94 std::to_string(m_cols));
120 : _rowPtr(_rows + 1), m_rows(_rows), m_cols(
_cols) {}
166 using difference_type = std::ptrdiff_t;
167 using value_type = std::pair<REAL &, size_type const &>;
168 using pointer = value_type *;
169 using reference = value_type &;
170 using iterator_category = std::bidirectional_iterator_tag;
192 return std::make_pair(std::ref(*_valIter),
193 std::cref(*_colIndicesIter));
200 [[
nodiscard]]
typename value_type::first_type value() {
201 return std::ref(*_valIter);
204 [[
nodiscard]]
typename value_type::second_type index() {
205 return std::cref(*_colIndicesIter);
209 return (_valIter ==
other._valIter)
and
210 (_colIndicesIter ==
other._colIndicesIter);
217 typename std::vector<REAL>::iterator _valIter;
218 std::vector<size_type>::iterator _colIndicesIter;
227 using difference_type = std::ptrdiff_t;
228 using value_type = std::pair<REAL const &, size_type const &>;
229 using pointer = value_type *;
230 using reference = value_type &;
231 using iterator_category = std::bidirectional_iterator_tag;
234 typename std::vector<REAL>::const_iterator
valIter,
254 return std::make_pair(std::ref(*_valIter),
255 std::cref(*_colIndicesIter));
262 [[
nodiscard]]
typename value_type::first_type value() {
263 return std::ref(*_valIter);
266 [[
nodiscard]]
typename value_type::second_type index() {
267 return std::cref(*_colIndicesIter);
271 return (_valIter ==
other._valIter)
and
272 (_colIndicesIter ==
other._colIndicesIter);
279 typename std::vector<REAL>::const_iterator _valIter;
280 std::vector<size_type>::const_iterator _colIndicesIter;
289 using difference_type = std::ptrdiff_t;
293 using iterator_category = std::random_access_iterator_tag;
297 typename std::vector<REAL>::iterator
valIter)
310 (_colIndicesIter + *_rowPtrIter));
314 (_valIter + *(_rowPtrIter + 1)),
315 (_colIndicesIter + *(_rowPtrIter + 1)));
367 return other - (*this) > 0;
371 return other < (*this);
378 return _rowPtrIter ==
rhs._rowPtrIter;
381 return _rowPtrIter !=
rhs._rowPtrIter;
385 std::vector<size_type>::iterator _rowPtrIter;
386 std::vector<size_type>::iterator _colIndicesIter;
387 typename std::vector<REAL>::iterator _valIter;
396 using difference_type = std::ptrdiff_t;
400 using iterator_category = std::bidirectional_iterator_tag;
403 std::vector<size_type>::const_iterator
rowPtrIter,
405 typename std::vector<REAL>::const_iterator
valIter)
418 (_valIter + *_rowPtrIter), (_colIndicesIter + *_rowPtrIter));
422 (_valIter + *(_rowPtrIter + 1)),
423 (_colIndicesIter + *(_rowPtrIter + 1)));
427 return this->begin();
482 return other - (*this) > 0;
486 return other < (*this);
493 return _rowPtrIter ==
rhs._rowPtrIter;
496 return _rowPtrIter !=
rhs._rowPtrIter;
500 std::vector<size_type>::const_iterator _rowPtrIter;
501 std::vector<size_type>::const_iterator _colIndicesIter;
502 typename std::vector<REAL>::const_iterator _valIter;
524 return row_iterator(_rowPtr.begin(), _colIndices.begin(),
547 return row_iterator(_rowPtr.end() - 1, _colIndices.begin(),
624 using value_pair =
typename const_column_index_iterator::value_type;
625 auto row = const_row_iterator(_rowPtr.begin() +
row_index,
626 _colIndices.begin(), _data.begin());
627 return std::find_if(
row.ibegin(),
row.iend(),
631 return el.second == col_index;
636 auto row = const_row_iterator(_rowPtr.begin() + row_index,
637 _colIndices.begin(), _data.begin());
638 return find(row_index, col_index) != row.iend();
645 using value_pair =
typename const_column_index_iterator::value_type;
647 _colIndices.begin(), _data.begin());
653 return el.second == col_index;
659 throw std::out_of_range(
660 "There is no non-zero element for these given indicies!");
668 using value_pair =
typename const_column_index_iterator::value_type;
670 _colIndices.begin(), _data.begin());
674 return el.second == col_index;
687 (_colIndices ==
other._colIndices)
and
689 (m_rows ==
other.m_rows);
714 return builder.build();
721 std::transform(_data.cbegin(), _data.cend(), _data.begin(),
722 [&](
REAL value) { return value * scalar; });
729 std::transform(_data.cbegin(), _data.cend(), _data.begin(),
730 [&](
REAL value) { return value / scalar; });
743 static_assert(std::is_convertible<V, REAL>::value,
744 "The types in the Matrix vector multiplication cant be "
745 "converted properly!");
749 (std::string(
"The result vector has the wrong dimension! ") +
750 "Vector dimension " + std::to_string(
result.size()) +
751 " != " + std::to_string(
this->
colsize()) +
" colsize"));
756 (std::string(
"The input vector has the wrong dimension! ") +
757 "Vector dimension " + std::to_string(x.size()) +
758 " != " + std::to_string(
this->
colsize()) +
" colsize"));
762 for (
auto row : (*this)) {
765 return result + (x[el.second] * el.first);
794 static_assert(std::is_convertible<V, REAL>::value,
795 "The types in the Matrix vector multiplication cant be "
796 "converted properly!");
800 (std::string(
"The result vector has the wrong dimension! ") +
801 "Vector dimension " + std::to_string(
result.size()) +
802 " != " + std::to_string(
this->
colsize()) +
" colsize"));
807 (std::string(
"The input vector has the wrong dimension! ") +
808 "Vector dimension " + std::to_string(
result.size()) +
809 " != " + std::to_string(
this->
colsize()) +
" colsize"));
813 for (
auto row : (*this)) {
816 return result + (x[el.second] * el.first);
823 template <
typename norm_type>
826 for (
auto row : *this) {
828 std::accumulate(row.begin(), row.end(), norm_type {},
829 [](norm_type res, REAL value) -> norm_type {
830 return res + std::abs(value);
856 return "values=" + comma_fold(_data) +
"\n" +
857 "colInd=" + comma_fold(_colIndices) +
"\n" +
858 "rowPtr=" + comma_fold(_rowPtr) +
"\n";
861 void print() const noexcept { std::cout << *
this; }
923 std::vector<std::map<size_type, REAL>> _rows;
929 builder(
const std::initializer_list<std::initializer_list<REAL>> &
v)
930 : m_rows {
v.size()}, m_cols {
v.begin()->size()}, _rows(m_rows) {
932 for (
auto &
row :
v) {
944 std::pair<typename std::map<size_type, REAL>::iterator,
bool> addEntry(
946 return _rows.at(
i).emplace(
j, value);
949 std::pair<typename std::map<size_type, REAL>::iterator,
bool> addEntry(
951 return addEntry(
i,
j,
REAL {});
958 (_rows ==
other._rows);
975 _rows.resize(m_cols);
979 void clear()
noexcept {
980 for (
auto &
row : _rows) {
985 [[
nodiscard]] std::string to_string()
const {
987 for (std::size_t
i = 0;
i < _rows.size();
i++) {
989 output += std::to_string(
i) +
", " +
990 std::to_string(
indexpair.first) +
" => " +
1000 for (std::size_t
i = 0;
i < _rows.size();
i++) {
1013template <
typename REAL>
1015template <
typename REAL>
1017template <
typename REAL>
1019template <
typename REAL>
1021template <
typename REAL>
1024template <
typename REAL>
1025std::ostream &operator<<(std::ostream &s,
const SparseMatrix<REAL> &A) {
1029 s <<
" " << std::setw(A.iwidth()) <<
" "
1031 for (size_type j = 0; j < A.colsize(); ++j) {
1032 s << std::setw(A.width()) << j <<
" ";
1036 for (size_type i = 0; i < A.rowsize(); ++i) {
1037 s <<
" " << std::setw(A.iwidth()) << i <<
" ";
1038 for (size_type j = 0; j < A.colsize(); ++j) {
1039 if (A.scientific()) {
1040 s << std::setw(A.width()) << std::scientific << std::showpoint
1041 << std::setprecision(A.precision()) << A(i, j) <<
" ";
1043 s << std::setw(A.width()) << std::fixed << std::showpoint
1044 << std::setprecision(A.precision()) << A(i, j) <<
" ";
1053template <
typename REAL>
1054inline void zero(SparseMatrix<REAL> &A) {
1055 A = SparseMatrix<REAL>(A.rowsize(), A.colsize());
1091template <
class REAL>
1094 HDNUM_ERROR(
"Will not overwrite A since Dimensions are not equal!");
1099template <
typename REAL>
1100inline void readMatrixFromFile(
const std::string &
filename,
1112 if (
fin.is_open()) {
1114 while (
fin.peek() ==
'%')
fin.ignore(2048,
'\n');
1126 iss >> i >> j >> value;
1128 builder.addEntry(i - 1, j - 1, value);
1130 A = builder.build();
1133 HDNUM_ERROR((
"Could not osspen file! \"" + filename +
"\""));
Class with mathematical matrix operations.
Definition densematrix.hh:33
size_t rowsize() const
get number of rows of the matrix
Definition densematrix.hh:136
size_t colsize() const
get number of columns of the matrix
Definition densematrix.hh:153
Definition sparsematrix.hh:920
Definition sparsematrix.hh:160
Definition sparsematrix.hh:221
Definition sparsematrix.hh:390
Definition sparsematrix.hh:283
Sparse matrix Class with mathematical matrix operations.
Definition sparsematrix.hh:31
void mv(Vector< V > &result, const Vector< V > &x) const
matrix vector product y = A*x
Definition sparsematrix.hh:742
std::size_t size_type
Types used for array indices.
Definition sparsematrix.hh:34
size_type rowsize() const
get number of rows of the matrix
Definition sparsematrix.hh:138
void precision(size_type i) const
set data precision for pretty-printing
Definition sparsematrix.hh:618
Vector< REAL > operator*(const Vector< REAL > &x) const
matrix vector product A*x
Definition sparsematrix.hh:778
const_row_iterator end() const
Definition sparsematrix.hh:574
static SparseMatrix identity(const size_type dimN)
identity for the matrix
Definition sparsematrix.hh:886
typename std::vector< REAL >::const_iterator const_column_iterator
type of a const regular column iterator (no access to indices)
Definition sparsematrix.hh:39
row_iterator begin()
get a (possibly modifying) row iterator for the sparse matrix
Definition sparsematrix.hh:523
bool operator!=(const SparseMatrix &other) const
checks whether two matricies are unequal based on values and dimension
Definition sparsematrix.hh:693
void umv(Vector< V > &result, const Vector< V > &x) const
update matrix vector product y += A*x
Definition sparsematrix.hh:793
size_type colsize() const
get number of columns of the matrix
Definition sparsematrix.hh:155
SparseMatrix< REAL > matchingIdentity() const
creates a matching identity
Definition sparsematrix.hh:918
SparseMatrix(const size_type _rows, const size_type _cols)
constructor with added dimensions and columns
Definition sparsematrix.hh:119
REAL & get(const size_type row_index, const size_type col_index)
write access on matrix element A_ij using A.get(i,j)
Definition sparsematrix.hh:642
SparseMatrix operator*=(const REAL scalar)
Definition sparsematrix.hh:719
size_type precision() const
get data precision for pretty-printing
Definition sparsematrix.hh:609
const_row_iterator cbegin() const
get a (non modifying) row iterator for the sparse matrix
Definition sparsematrix.hh:556
typename std::vector< REAL >::iterator column_iterator
type of a regular column iterator (no access to indices)
Definition sparsematrix.hh:37
void width(size_type i) const
set data field width for pretty-printing
Definition sparsematrix.hh:615
void identity(SparseMatrix< REAL > &A)
Definition sparsematrix.hh:1092
size_type width() const
get data field width for pretty-printing
Definition sparsematrix.hh:606
SparseMatrix operator/=(const REAL scalar)
Definition sparsematrix.hh:727
const_row_iterator cend() const
get a (non modifying) row iterator for the sparse matrix
Definition sparsematrix.hh:566
auto norm_infty() const
calculate row sum norm
Definition sparsematrix.hh:847
void scientific(bool b) const
Switch between floating point (default=true) and fixed point (false) display.
Definition sparsematrix.hh:600
const REAL & operator()(const size_type row_index, const size_type col_index) const
read-access on matrix element A_ij using A(i,j)
Definition sparsematrix.hh:664
void iwidth(size_type i) const
set index field width for pretty-printing
Definition sparsematrix.hh:612
size_type iwidth() const
get index field width for pretty-printing
Definition sparsematrix.hh:603
bool scientific() const
pretty-print output properties
Definition sparsematrix.hh:158
row_iterator end()
get a (possibly modifying) row iterator for the sparse matrix
Definition sparsematrix.hh:546
const_row_iterator begin() const
Definition sparsematrix.hh:572
bool operator==(const SparseMatrix &other) const
checks whether two matricies are equal based on values and dimension
Definition sparsematrix.hh:684
SparseMatrix()=default
default constructor (empty SparseMatrix)