numerics 0.1.0
Loading...
Searching...
No Matches
sparse.cpp
Go to the documentation of this file.
2#include <algorithm>
3#include <numeric>
4#include <stdexcept>
5
6namespace num {
7
9 idx n_cols,
10 std::vector<real> vals,
11 std::vector<idx> col_idx,
12 std::vector<idx> row_ptr)
13 : n_rows_(n_rows),
14 n_cols_(n_cols),
15 vals_(std::move(vals)),
16 col_idx_(std::move(col_idx)),
17 row_ptr_(std::move(row_ptr)) {
18 if (row_ptr_.size() != n_rows_ + 1)
19 throw std::invalid_argument("SparseMatrix: row_ptr must have length n_rows+1");
20 if (col_idx_.size() != vals_.size())
21 throw std::invalid_argument(
22 "SparseMatrix: col_idx and vals must have equal length");
23}
24
26 idx n_cols,
27 const std::vector<idx>& rows,
28 const std::vector<idx>& cols,
29 const std::vector<real>& vals) {
30 if (rows.size() != cols.size() || rows.size() != vals.size())
31 throw std::invalid_argument(
32 "SparseMatrix::from_triplets: inconsistent input sizes");
33
34 // Count entries per row
35 std::vector<idx> row_count(n_rows, 0);
36 for (idx k = 0; k < rows.size(); ++k) {
37 if (rows[k] >= n_rows || cols[k] >= n_cols)
38 throw std::out_of_range("SparseMatrix::from_triplets: index out of range");
39 ++row_count[rows[k]];
40 }
41
42 // Build row_ptr
43 std::vector<idx> row_ptr(n_rows + 1, 0);
44 for (idx i = 0; i < n_rows; ++i)
45 row_ptr[i + 1] = row_ptr[i] + row_count[i];
46
48 std::vector<real> out_vals(nnz, 0.0);
49 std::vector<idx> out_col(nnz);
50
51 // Fill entries (stable insertion within each row)
52 std::vector<idx> fill_pos = row_ptr;
53 for (idx k = 0; k < rows.size(); ++k) {
54 idx pos = fill_pos[rows[k]]++;
55 out_col[pos] = cols[k];
56 out_vals[pos] = vals[k];
57 }
58
59 // Sort each row by column and sum duplicates
60 for (idx i = 0; i < n_rows; ++i) {
61 idx start = row_ptr[i], end = row_ptr[i + 1];
62 // Sort by column index
63 std::vector<idx> order(end - start);
64 std::iota(order.begin(), order.end(), 0);
65 std::sort(order.begin(), order.end(), [&](idx a, idx b) {
66 return out_col[start + a] < out_col[start + b];
67 });
68
69 std::vector<real> sv(end - start);
70 std::vector<idx> sc(end - start);
71 for (idx k = 0; k < order.size(); ++k) {
72 sv[k] = out_vals[start + order[k]];
73 sc[k] = out_col[start + order[k]];
74 }
75 for (idx k = 0; k < order.size(); ++k) {
76 out_vals[start + k] = sv[k];
77 out_col[start + k] = sc[k];
78 }
79
80 // Sum duplicates in-place
81 idx write = start;
82 for (idx k = start; k < end;) {
83 idx cur_col = out_col[k];
84 real sum = 0.0;
85 while (k < end && out_col[k] == cur_col)
86 sum += out_vals[k++];
87 out_col[write] = cur_col;
88 out_vals[write++] = sum;
89 }
90 // Compact row_ptr if duplicates were merged
91 row_ptr[i + 1] = write;
92 // Shift remaining rows' data (rare; only matters if duplicates exist)
93 if (write < end) {
94 for (idx k = end; k < nnz; ++k) {
95 out_vals[write + (k - end)] = out_vals[k];
96 out_col[write + (k - end)] = out_col[k];
97 }
98 nnz -= (end - write);
99 out_vals.resize(nnz);
100 out_col.resize(nnz);
101 // Fix subsequent row_ptr entries
102 idx delta = end - write;
103 for (idx r = i + 2; r <= n_rows; ++r)
104 row_ptr[r] -= delta;
105 }
106 }
107
108 return SparseMatrix(n_rows,
109 n_cols,
110 std::move(out_vals),
111 std::move(out_col),
112 std::move(row_ptr));
113}
114
116 for (idx k = row_ptr_[i]; k < row_ptr_[i + 1]; ++k)
117 if (col_idx_[k] == j)
118 return vals_[k];
119 return 0.0;
120}
121
122void sparse_matvec(const SparseMatrix& A, const Vector& x, Vector& y) {
123 if (A.n_cols() != x.size() || A.n_rows() != y.size())
124 throw std::invalid_argument("Dimension mismatch in sparse_matvec");
125 for (idx i = 0; i < A.n_rows(); ++i) {
126 real sum = 0.0;
127 for (idx k = A.row_ptr()[i]; k < A.row_ptr()[i + 1]; ++k)
128 sum += A.values()[k] * x[A.col_idx()[k]];
129 y[i] = sum;
130 }
131}
132
133} // namespace num
constexpr idx size() const noexcept
Definition vector.hpp:83
Sparse matrix in Compressed Sparse Row (CSR) format.
Definition sparse.hpp:15
real operator()(idx i, idx j) const
Element access A(i,j); returns 0 if outside stored pattern – O(nnz/n)
Definition sparse.cpp:115
idx nnz() const
Definition sparse.hpp:35
SparseMatrix(idx n_rows, idx n_cols, std::vector< real > vals, std::vector< idx > col_idx, std::vector< idx > row_ptr)
Construct from raw CSR arrays (takes ownership)
Definition sparse.cpp:8
static SparseMatrix from_triplets(idx n_rows, idx n_cols, const std::vector< idx > &rows, const std::vector< idx > &cols, const std::vector< real > &vals)
Build from coordinate (COO / triplet) lists.
Definition sparse.cpp:25
idx n_cols() const
Definition sparse.hpp:34
const idx * row_ptr() const
Definition sparse.hpp:43
idx n_rows() const
Definition sparse.hpp:33
const idx * col_idx() const
Definition sparse.hpp:42
const real * values() const
Definition sparse.hpp:41
Compressed Sparse Row (CSR) matrix and operations.
double real
Definition types.hpp:10
std::size_t idx
Definition types.hpp:11
void sparse_matvec(const SparseMatrix &A, const Vector &x, Vector &y)
y = A * x
Definition sparse.cpp:122