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)