4
// using a variant on CSR format
14
unsigned int m, n; // dimensions
15
std::vector<std::vector<unsigned int> > index; // for each row, a list of all column indices (sorted)
16
std::vector<std::vector<T> > value; // values corresponding to index
18
explicit SparseMatrix(unsigned int m_=0)
19
: m(m_), n(m_), index(m_), value(m_)
21
const unsigned int expected_nonzeros_per_row=7;
22
for(unsigned int i=0; i<m; ++i){
23
index[i].reserve(expected_nonzeros_per_row);
24
value[i].reserve(expected_nonzeros_per_row);
28
explicit SparseMatrix(unsigned int m_, unsigned int n_, unsigned int expected_nonzeros_per_row)
29
: m(m_), n(n_), index(m_), value(m_)
31
for(unsigned int i=0; i<m; ++i){
32
index[i].reserve(expected_nonzeros_per_row);
33
value[i].reserve(expected_nonzeros_per_row);
46
for(unsigned int i=0; i<m; ++i){
52
void resize(unsigned int m_, unsigned int n_)
60
T operator()(unsigned int i, unsigned int j) const
63
for(unsigned int k=0; k<index[i].size(); ++k){
64
if(index[i][k]==j) return value[i][k];
65
else if(index[i][k]>j) return 0;
70
void set_element(unsigned int i, unsigned int j, T new_value)
74
for(; k<index[i].size(); ++k){
76
value[i][k]=new_value;
78
}else if(index[i][k]>j){
79
insert(index[i], k, j);
80
insert(value[i], k, new_value);
84
index[i].push_back(j);
85
value[i].push_back(new_value);
88
void add_to_element(unsigned int i, unsigned int j, T increment_value)
92
for(; k<index[i].size(); ++k){
94
value[i][k]+=increment_value;
96
}else if(index[i][k]>j){
97
insert(index[i], k, j);
98
insert(value[i], k, increment_value);
102
index[i].push_back(j);
103
value[i].push_back(increment_value);
106
// assumes indices is already sorted
107
void add_sparse_row(unsigned int i, const std::vector<unsigned int> &indices, const std::vector<T> &values)
110
unsigned int j=0, k=0;
111
while(j<indices.size() && k<index[i].size()){
112
if(index[i][k]<indices[j]){
114
}else if(index[i][k]>indices[j]){
115
insert(index[i], k, indices[j]);
116
insert(value[i], k, values[j]);
119
value[i][k]+=values[j];
124
for(; j<indices.size(); ++j){
125
index[i].push_back(indices[j]);
126
value[i].push_back(values[j]);
130
// assumes indices is already sorted
131
void add_sparse_row(unsigned int i, const std::vector<unsigned int> &indices, T multiplier, const std::vector<T> &values)
134
unsigned int j=0, k=0;
135
while(j<indices.size() && k<index[i].size()){
136
if(index[i][k]<indices[j]){
138
}else if(index[i][k]>indices[j]){
139
insert(index[i], k, indices[j]);
140
insert(value[i], k, multiplier*values[j]);
143
value[i][k]+=multiplier*values[j];
148
for(;j<indices.size(); ++j){
149
index[i].push_back(indices[j]);
150
value[i].push_back(multiplier*values[j]);
154
// assumes matrix has symmetric structure - so the indices in row i tell us which columns to delete i from
155
void symmetric_remove_row_and_column(unsigned int i)
158
for(unsigned int a=0; a<index[i].size(); ++a){
159
unsigned int j=index[i][a]; //
160
for(unsigned int b=0; b<index[j].size(); ++b){
172
void write_matlab(std::ostream &output, const char *variable_name)
174
output<<variable_name<<"=sparse([";
175
for(unsigned int i=0; i<m; ++i){
176
for(unsigned int j=0; j<index[i].size(); ++j){
181
for(unsigned int i=0; i<m; ++i){
182
for(unsigned int j=0; j<index[i].size(); ++j){
183
output<<index[i][j]+1<<" ";
187
for(unsigned int i=0; i<m; ++i){
188
for(unsigned int j=0; j<value[i].size(); ++j){
189
output<<value[i][j]<<" ";
192
output<<"], "<<m<<", "<<n<<");"<<std::endl;
196
typedef SparseMatrix<float> SparseMatrixf;
197
typedef SparseMatrix<double> SparseMatrixd;
199
// perform result=matrix*x
201
void multiply(const SparseMatrix<T> &matrix, const std::vector<T> &x, std::vector<T> &result)
203
assert(matrix.n==x.size());
204
result.resize(matrix.m);
205
for(unsigned int i=0; i<matrix.m; ++i){
207
for(unsigned int j=0; j<matrix.index[i].size(); ++j){
208
result[i]+=matrix.value[i][j]*x[matrix.index[i][j]];
213
// perform result=result-matrix*x
215
void multiply_and_subtract(const SparseMatrix<T> &matrix, const std::vector<T> &x, std::vector<T> &result)
217
assert(matrix.n==x.size());
218
result.resize(matrix.m);
219
for(unsigned int i=0; i<matrix.m; ++i){
220
for(unsigned int j=0; j<matrix.index[i].size(); ++j){
221
result[i]-=matrix.value[i][j]*x[matrix.index[i][j]];
226
// compute C=A*B (B might equal A)
228
void multiply_sparse_matrices(const SparseMatrix<T> &A, const SparseMatrix<T> &B, SparseMatrix<T> &C)
233
for(unsigned int i=0; i<A.m; ++i){
234
for(unsigned int p=0; p<A.index[i].size(); ++p){
235
unsigned int k=A.index[i][p];
236
C.add_sparse_row(i, B.index[k], A.value[i][p], B.value[k]);
241
// compute C=A^T*B (B might equal A)
243
void multiply_AtB(const SparseMatrix<T> &A, const SparseMatrix<T> &B, SparseMatrix<T> &C)
248
for(unsigned int k=0; k<A.m; ++k){
249
for(unsigned int p=0; p<A.index[k].size(); ++p){
250
unsigned int i=A.index[k][p];
251
C.add_sparse_row(i, B.index[k], A.value[k][p], B.value[k]);
256
// compute C=A*D*B (B might equal A)
258
void multiply_sparse_matrices_with_diagonal_weighting(const SparseMatrix<T> &A, const std::vector<T> &diagD,
259
const SparseMatrix<T> &B, SparseMatrix<T> &C)
262
assert(diagD.size()==A.n);
265
for(unsigned int i=0; i<A.m; ++i){
266
for(unsigned int p=0; p<A.index[i].size(); ++p){
267
unsigned int k=A.index[i][p];
268
C.add_sparse_row(i, B.index[k], A.value[i][p]*diagD[k], B.value[k]);
273
// compute C=A^T*D*B (B might equal A)
275
void multiply_AtDB(const SparseMatrix<T> &A, const std::vector<T>& diagD, const SparseMatrix<T> &B, SparseMatrix<T> &C)
280
for(unsigned int k=0; k<A.m; ++k){
281
for(unsigned int p=0; p<A.index[k].size(); ++p){
282
unsigned int i=A.index[k][p];
283
C.add_sparse_row(i, B.index[k], A.value[k][p]*diagD[k], B.value[k]);
288
// set T to the transpose of A
290
void compute_transpose(const SparseMatrix<T> &A, SparseMatrix<T> &C)
294
for(unsigned int i=0; i<A.m; ++i){
295
for(unsigned int p=0; p<A.index[i].size(); ++p){
296
unsigned int k=A.index[i][p];
297
C.index[k].push_back(i);
298
C.value[k].push_back(A.value[i][p]);
304
struct FixedSparseMatrix
306
unsigned int m, n; // dimension
307
std::vector<T> value; // nonzero values row by row
308
std::vector<unsigned int> colindex; // corresponding column indices
309
std::vector<unsigned int> rowstart; // where each row starts in value and colindex (and last entry is one past the end, the number of nonzeros)
311
explicit FixedSparseMatrix(unsigned int m_=0)
312
: m(m_), n(m_), value(0), colindex(0), rowstart(m_+1)
315
explicit FixedSparseMatrix(unsigned int m_, unsigned int n_)
316
: m(m_), n(n_), value(0), colindex(0), rowstart(m_+1)
327
void resize(unsigned int m_, unsigned int n_)
331
rowstart.resize(m+1);
334
void construct_from_matrix(const SparseMatrix<T> &matrix)
336
resize(matrix.m, matrix.n);
338
for(unsigned int i=0; i<m; ++i){
339
rowstart[i+1]=rowstart[i]+matrix.index[i].size();
341
value.resize(rowstart[m]);
342
colindex.resize(rowstart[m]);
344
for(unsigned int i=0; i<m; ++i){
345
for(unsigned int k=0; k<matrix.index[i].size(); ++k){
346
value[j]=matrix.value[i][k];
347
colindex[j]=matrix.index[i][k];
353
void write_matlab(std::ostream &output, const char *variable_name)
355
output<<variable_name<<"=sparse([";
356
for(unsigned int i=0; i<m; ++i){
357
for(unsigned int j=rowstart[i]; j<rowstart[i+1]; ++j){
362
for(unsigned int i=0; i<m; ++i){
363
for(unsigned int j=rowstart[i]; j<rowstart[i+1]; ++j){
364
output<<colindex[j]+1<<" ";
368
for(unsigned int i=0; i<m; ++i){
369
for(unsigned int j=rowstart[i]; j<rowstart[i+1]; ++j){
370
output<<value[j]<<" ";
373
output<<"], "<<m<<", "<<n<<");"<<std::endl;
377
typedef FixedSparseMatrix<float> FixedSparseMatrixf;
378
typedef FixedSparseMatrix<double> FixedSparseMatrixd;
380
// perform result=matrix*x
382
void multiply(const FixedSparseMatrix<T> &matrix, const std::vector<T> &x, std::vector<T> &result)
384
assert(matrix.n==x.size());
385
result.resize(matrix.m);
386
for(unsigned int i=0; i<matrix.m; ++i){
388
for(unsigned int j=matrix.rowstart[i]; j<matrix.rowstart[i+1]; ++j){
389
result[i]+=matrix.value[j]*x[matrix.colindex[j]];
394
// perform result=result-matrix*x
396
void multiply_and_subtract(const FixedSparseMatrix<T> &matrix, const std::vector<T> &x, std::vector<T> &result)
398
assert(matrix.n==x.size());
399
result.resize(matrix.m);
400
for(unsigned int i=0; i<matrix.m; ++i){
401
for(unsigned int j=matrix.rowstart[i]; j<matrix.rowstart[i+1]; ++j){
402
result[i]-=matrix.value[j]*x[matrix.colindex[j]];