numerics
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 std::vector<real> vals,
10 std::vector<idx> col_idx,
11 std::vector<idx> row_ptr)
12 : n_rows_(n_rows), n_cols_(n_cols),
13 vals_(std::move(vals)),
14 col_idx_(std::move(col_idx)),
15 row_ptr_(std::move(row_ptr))
16{
17 if (row_ptr_.size() != n_rows_ + 1)
18 throw std::invalid_argument("SparseMatrix: row_ptr must have length n_rows+1");
19 if (col_idx_.size() != vals_.size())
20 throw std::invalid_argument("SparseMatrix: col_idx and vals must have equal length");
21}
22
24 const std::vector<idx>& rows,
25 const std::vector<idx>& cols,
26 const std::vector<real>& vals) {
27 if (rows.size() != cols.size() || rows.size() != vals.size())
28 throw std::invalid_argument("SparseMatrix::from_triplets: inconsistent input sizes");
29
30 // Count entries per row
31 std::vector<idx> row_count(n_rows, 0);
32 for (idx k = 0; k < rows.size(); ++k) {
33 if (rows[k] >= n_rows || cols[k] >= n_cols)
34 throw std::out_of_range("SparseMatrix::from_triplets: index out of range");
35 ++row_count[rows[k]];
36 }
37
38 // Build row_ptr
39 std::vector<idx> row_ptr(n_rows + 1, 0);
40 for (idx i = 0; i < n_rows; ++i) row_ptr[i + 1] = row_ptr[i] + row_count[i];
41
43 std::vector<real> out_vals(nnz, 0.0);
44 std::vector<idx> out_col(nnz);
45
46 // Fill entries (stable insertion within each row)
47 std::vector<idx> fill_pos = row_ptr;
48 for (idx k = 0; k < rows.size(); ++k) {
49 idx pos = fill_pos[rows[k]]++;
50 out_col[pos] = cols[k];
51 out_vals[pos] = vals[k];
52 }
53
54 // Sort each row by column and sum duplicates
55 for (idx i = 0; i < n_rows; ++i) {
56 idx start = row_ptr[i], end = row_ptr[i + 1];
57 // Sort by column index
58 std::vector<idx> order(end - start);
59 std::iota(order.begin(), order.end(), 0);
60 std::sort(order.begin(), order.end(),
61 [&](idx a, idx b){ return out_col[start + a] < out_col[start + b]; });
62
63 std::vector<real> sv(end - start);
64 std::vector<idx> sc(end - start);
65 for (idx k = 0; k < order.size(); ++k) {
66 sv[k] = out_vals[start + order[k]];
67 sc[k] = out_col [start + order[k]];
68 }
69 for (idx k = 0; k < order.size(); ++k) {
70 out_vals[start + k] = sv[k];
71 out_col [start + k] = sc[k];
72 }
73
74 // Sum duplicates in-place
75 idx write = start;
76 for (idx k = start; k < end; ) {
78 real sum = 0.0;
79 while (k < end && out_col[k] == cur_col) sum += out_vals[k++];
81 out_vals[write++] = sum;
82 }
83 // Compact row_ptr if duplicates were merged
84 row_ptr[i + 1] = write;
85 // Shift remaining rows' data (rare; only matters if duplicates exist)
86 if (write < end) {
87 for (idx k = end; k < nnz; ++k) {
88 out_vals[write + (k - end)] = out_vals[k];
89 out_col [write + (k - end)] = out_col [k];
90 }
91 nnz -= (end - write);
92 out_vals.resize(nnz);
93 out_col .resize(nnz);
94 // Fix subsequent row_ptr entries
95 idx delta = end - write;
96 for (idx r = i + 2; r <= n_rows; ++r) row_ptr[r] -= delta;
97 }
98 }
99
100 return SparseMatrix(n_rows, n_cols,
101 std::move(out_vals), std::move(out_col), std::move(row_ptr));
102}
103
105 for (idx k = row_ptr_[i]; k < row_ptr_[i + 1]; ++k)
106 if (col_idx_[k] == j) return vals_[k];
107 return 0.0;
108}
109
110void sparse_matvec(const SparseMatrix& A, const Vector& x, Vector& y) {
111 if (A.n_cols() != x.size() || A.n_rows() != y.size())
112 throw std::invalid_argument("Dimension mismatch in sparse_matvec");
113 for (idx i = 0; i < A.n_rows(); ++i) {
114 real sum = 0.0;
115 for (idx k = A.row_ptr()[i]; k < A.row_ptr()[i + 1]; ++k)
116 sum += A.values()[k] * x[A.col_idx()[k]];
117 y[i] = sum;
118 }
119}
120
121} // namespace num
constexpr idx size() const noexcept
Definition vector.hpp:77
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:104
idx nnz() const
Definition sparse.hpp:33
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:23
idx n_cols() const
Definition sparse.hpp:32
const idx * row_ptr() const
Definition sparse.hpp:40
idx n_rows() const
Definition sparse.hpp:31
double real
Definition types.hpp:10
constexpr T ipow(T x) noexcept
Compute x^N at compile time via repeated squaring.
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:110
Compressed Sparse Row (CSR) matrix and operations.