2 #include "SparseMatrix.h"
4 namespace LODGenerator
{
7 void CSparseLine::add(int index
, double val
) {
10 for(int ii
=0; ii
< nb_coeffs_
; ii
++) {
11 if(coeff_
[ii
].index
== index
) {
12 coeff
= &(coeff_
[ii
]);
20 if(nb_coeffs_
> capacity_
) {
23 coeff
= &(coeff_
[nb_coeffs_
- 1]);
29 void CSparseLine::set(int index
, double val
) {
32 for(int ii
=0; ii
< nb_coeffs_
; ii
++) {
33 if(coeff_
[ii
].index
== index
) {
34 coeff
= &(coeff_
[ii
]);
42 if(nb_coeffs_
> capacity_
) {
45 coeff
= &(coeff_
[nb_coeffs_
- 1]);
51 int CSparseLine::find(int i
)
54 for(int ii
=0; ii
< nb_coeffs_
; ii
++) {
55 if(coeff_
[ii
].index
== i
) {
62 int CSparseLine::findSorted(int i
)
66 if(i
>coeff_
[nb_coeffs_
-1].index
)
69 int left
=0, right
=nb_coeffs_
-1;
70 if(coeff_
[left
].index
== i
)
72 if(coeff_
[right
].index
== i
)
74 int middle
= (left
+right
)/2;
78 if(coeff_
[middle
].index
== i
)
80 if(coeff_
[middle
].index
< i
)
84 middle
= (left
+right
)/2;
89 void CSparseLine::push_element(int index
, double val
)
92 if(nb_coeffs_
> capacity_
) {
95 CCoeff
* coeff
= &(coeff_
[nb_coeffs_
- 1]);
100 void CSparseLine::reserve(int nb_elements
)
102 if (nb_elements
<capacity_
) return;
104 int old_capacity
= capacity_
;
105 capacity_
= nb_elements
;
106 CAllocator
<CCoeff
>::reallocate(
107 coeff_
, old_capacity
, capacity_
111 void CSparseLine::erase_element(int index
)
113 if (index
!=nb_coeffs_
-1)
114 memmove(&coeff_
[index
], &coeff_
[index
+1], (nb_coeffs_
-index
-1)*sizeof(coeff_
[0]));
118 double CSparseLine::get(int index
) const {
119 CCoeff
* coeff
= NULL
;
120 // Search for a_{index}
121 for(int ii
=0; ii
< nb_coeffs_
; ii
++) {
122 if(coeff_
[ii
].index
== index
) {
123 coeff
= &(coeff_
[ii
]);
134 void CSparseLine::grow() {
135 int old_capacity
= capacity_
;
136 if (capacity_
>1000) {
137 capacity_
= (int)(capacity_
* 1.2);
139 capacity_
= capacity_
* 2;
141 CAllocator
<CCoeff
>::reallocate(
142 coeff_
, old_capacity
, capacity_
146 class CCoeffIndexCompare
{
148 bool operator()(const CCoeff
& c1
, const CCoeff
& c2
) {
149 return c1
.index
< c2
.index
;
153 void CSparseLine::sort() {
154 CCoeff
* begin
= coeff_
;
155 CCoeff
* end
= coeff_
+ nb_coeffs_
;
156 std::sort(begin
, end
, CCoeffIndexCompare());
159 void CSparseLine::removeDuplicates() {
161 if (nb_coeffs_
==0) return;
163 int nbDifferentCCoeffs
= 1;
164 for (int i
=1; i
<nb_coeffs_
; i
++)
165 if (coeff_
[i
-1].index
!=coeff_
[i
].index
)
166 nbDifferentCCoeffs
++;
168 CCoeff
* newCCoeffs
= CAllocator
<CCoeff
>::allocate(nbDifferentCCoeffs
);
169 newCCoeffs
[0] = coeff_
[0];
171 for (int i
=1; i
<nb_coeffs_
; i
++)
173 if (coeff_
[i
-1].index
!=coeff_
[i
].index
)
175 newCCoeffs
[k
] = coeff_
[i
];
179 newCCoeffs
[k
-1].a
= min(coeff_
[i
].a
, newCCoeffs
[k
-1].a
);
181 CAllocator
<CCoeff
>::deallocate(coeff_
);
183 nb_coeffs_
= nbDifferentCCoeffs
;
184 capacity_
= nbDifferentCCoeffs
;
187 CSparseMatrix::CSparseMatrix(int m
, int n
, EStorage storage
) {
189 allocate(m
,n
,storage
,false);
192 CSparseMatrix::CSparseMatrix(
193 int n
, EStorage storage
, bool symmetric_storage
196 allocate(n
,n
,storage
,symmetric_storage
);
199 CSparseMatrix::CSparseMatrix(const CSparseMatrix
& rhs
)
202 allocate(rhs
.m(), rhs
.n(), rhs
.storage(), rhs
.is_symmetric());
203 memcpy(diag_
, rhs
.diag_
, diag_size_
*sizeof(diag_
[0]));
205 if (rows_are_stored_
)
207 for (int i
=0; i
<m_
; i
++)
209 row_
[i
].coeff_
= new CCoeff
[std::max(2,rhs
.row_
[i
].nb_coeffs())];
210 memcpy(row_
[i
].coeff_
, rhs
.row_
[i
].coeff_
, rhs
.row_
[i
].nb_coeffs()*sizeof(row_
[i
].coeff_
[0]));
211 row_
[i
].nb_coeffs_
= rhs
.row_
[i
].nb_coeffs();
212 row_
[i
].capacity_
= std::max(2, rhs
.row_
[i
].nb_coeffs());
215 if (columns_are_stored_
)
217 for (int i
=0; i
<n_
; i
++)
219 column_
[i
].coeff_
= new CCoeff
[std::max(2,rhs
.column_
[i
].nb_coeffs())];
220 memcpy(column_
[i
].coeff_
, rhs
.column_
[i
].coeff_
, rhs
.column_
[i
].nb_coeffs()*sizeof(column_
[i
].coeff_
[0]));
221 column_
[i
].nb_coeffs_
= rhs
.column_
[i
].nb_coeffs();
222 column_
[i
].capacity_
= std::max(2, rhs
.column_
[i
].nb_coeffs());
227 CSparseMatrix
& CSparseMatrix::operator=(const CSparseMatrix
& rhs
)
230 allocate(rhs
.m(), rhs
.n(), rhs
.storage(), rhs
.is_symmetric());
231 memcpy(diag_
, rhs
.diag_
, diag_size_
*sizeof(diag_
[0]));
233 if (rows_are_stored_
)
235 for (int i
=0; i
<m_
; i
++)
237 row_
[i
].coeff_
= new CCoeff
[std::max(2,rhs
.row_
[i
].nb_coeffs())];
238 memcpy(row_
[i
].coeff_
, rhs
.row_
[i
].coeff_
, rhs
.row_
[i
].nb_coeffs()*sizeof(row_
[i
].coeff_
[0]));
239 row_
[i
].nb_coeffs_
= rhs
.row_
[i
].nb_coeffs();
240 row_
[i
].capacity_
= std::max(2, rhs
.row_
[i
].nb_coeffs());
243 if (columns_are_stored_
)
245 for (int i
=0; i
<n_
; i
++)
247 column_
[i
].coeff_
= new CCoeff
[std::max(2,rhs
.column_
[i
].nb_coeffs())];
248 memcpy(column_
[i
].coeff_
, rhs
.column_
[i
].coeff_
, rhs
.column_
[i
].nb_coeffs()*sizeof(column_
[i
].coeff_
[0]));
249 column_
[i
].nb_coeffs_
= rhs
.column_
[i
].nb_coeffs();
250 column_
[i
].capacity_
= std::max(2, rhs
.column_
[i
].nb_coeffs());
256 CSparseMatrix::~CSparseMatrix() {
260 CSparseMatrix::CSparseMatrix() {
270 rows_are_stored_
= false;
271 columns_are_stored_
= false;
272 symmetric_storage_
= false;
273 symmetric_tag_
= false;
276 int CSparseMatrix::nnz() const {
278 if(rows_are_stored()) {
279 for(int i
=0; i
<m(); i
++) {
280 result
+= row(i
).nb_coeffs();
282 } else if(columns_are_stored()) {
283 for(int j
=0; j
<n(); j
++) {
284 result
+= column(j
).nb_coeffs();
292 void CSparseMatrix::deallocate() {
305 rows_are_stored_
= false;
306 columns_are_stored_
= false;
307 symmetric_storage_
= false;
310 void CSparseMatrix::allocate(
311 int m
, int n
, EStorage storage
, bool symmetric_storage
313 if(storage_
!= eS_NONE
) {
319 diag_size_
= min(m
,n
);
320 symmetric_storage_
= symmetric_storage
;
321 symmetric_tag_
= false;
328 rows_are_stored_
= true;
329 columns_are_stored_
= false;
332 rows_are_stored_
= false;
333 columns_are_stored_
= true;
335 case eS_ROWS_AND_COLUMNS
:
336 rows_are_stored_
= true;
337 columns_are_stored_
= true;
340 diag_
= new double[diag_size_
];
341 for(int i
=0; i
<diag_size_
; i
++) {
345 if(rows_are_stored_
) {
351 if(columns_are_stored_
) {
352 column_
= new Column
[n
];
358 void CSparseMatrix::sort() {
359 if(rows_are_stored_
) {
360 for(int i
=0; i
<m_
; i
++) {
364 if(columns_are_stored_
) {
365 for(int j
=0; j
<n_
; j
++) {
371 void CSparseMatrix::zero() {
372 if(rows_are_stored_
) {
373 for(int i
=0; i
<m_
; i
++) {
377 if(columns_are_stored_
) {
378 for(int j
=0; j
<n_
; j
++) {
382 for(int i
=0; i
<diag_size_
; i
++) {
387 void CSparseMatrix::clear() {
388 if(rows_are_stored_
) {
389 for(int i
=0; i
<m_
; i
++) {
393 if(columns_are_stored_
) {
394 for(int j
=0; j
<n_
; j
++) {
398 for(int i
=0; i
<diag_size_
; i
++) {
403 static void mult_rows_symmetric(
404 const CSparseMatrix
& A
, const double* x
, double* y
407 for(int i
=0; i
<m
; i
++) {
409 const CSparseMatrix::Row
& Ri
= A
.row(i
);
410 for(int ij
=0; ij
<Ri
.nb_coeffs(); ij
++) {
411 const CCoeff
& c
= Ri
.coeff(ij
);
412 y
[i
] += c
.a
* x
[c
.index
];
414 y
[c
.index
] += c
.a
* x
[i
];
420 static void mult_rows(
421 const CSparseMatrix
& A
, const double* x
, double* y
424 for(int i
=0; i
<m
; i
++) {
426 const CSparseMatrix::Row
& Ri
= A
.row(i
);
427 for(int ij
=0; ij
<Ri
.nb_coeffs(); ij
++) {
428 const CCoeff
& c
= Ri
.coeff(ij
);
429 y
[i
] += c
.a
* x
[c
.index
];
435 static void mult_cols_symmetric(
436 const CSparseMatrix
& A
, const double* x
, double* y
438 ::memset(y
, 0, A
.m() * sizeof(double));
440 for(int j
=0; j
<n
; j
++) {
441 const CSparseMatrix::Column
& Cj
= A
.column(j
);
442 for(int ii
=0; ii
<Cj
.nb_coeffs(); ii
++) {
443 const CCoeff
& c
= Cj
.coeff(ii
);
444 y
[c
.index
] += c
.a
* x
[j
] ;
446 y
[j
] += c
.a
* x
[c
.index
];
452 static void mult_cols(
453 const CSparseMatrix
& A
, const double* x
, double* y
455 ::memset(y
, 0, A
.m() * sizeof(double));
457 for(int j
=0; j
<n
; j
++) {
458 const CSparseMatrix::Column
& Cj
= A
.column(j
);
459 for(int ii
=0; ii
<Cj
.nb_coeffs(); ii
++) {
460 const CCoeff
& c
= Cj
.coeff(ii
);
461 y
[c
.index
] += c
.a
* x
[j
];
466 void mult(const CSparseMatrix
& A
, const double* x
, double* y
) {
467 if(A
.rows_are_stored()) {
468 if(A
.has_symmetric_storage()) {
469 mult_rows_symmetric(A
, x
, y
);
474 if(A
.has_symmetric_storage()) {
475 mult_cols_symmetric(A
, x
, y
);
482 static void mult_xpose_rows(
483 const CSparseMatrix
& A
, const double* x
, double* y
485 ::memset(y
, 0, A
.n() * sizeof(double));
487 for(int i
=0; i
<m
; i
++) {
488 const CSparseMatrix::Row
& Ri
= A
.row(i
);
489 for(int ij
=0; ij
<Ri
.nb_coeffs(); ij
++) {
490 const CCoeff
& c
= Ri
.coeff(ij
);
491 y
[c
.index
] += c
.a
* x
[i
];
496 static void mult_xpose_cols(
497 const CSparseMatrix
& A
, const double* x
, double* y
500 for(int j
=0; j
<n
; j
++) {
502 const CSparseMatrix::Column
& Cj
= A
.column(j
);
503 for(int ii
=0; ii
<Cj
.nb_coeffs(); ii
++) {
504 const CCoeff
& c
= Cj
.coeff(ii
);
505 y
[j
] += c
.a
* x
[c
.index
];
511 const CSparseMatrix
& A
, const double* x
, double* y
513 if(A
.rows_are_stored()) {
514 if(A
.has_symmetric_storage()) {
515 mult_rows_symmetric(A
, x
, y
);
517 mult_xpose_rows(A
, x
, y
);
520 if(A
.has_symmetric_storage()) {
521 mult_cols_symmetric(A
, x
, y
);
523 mult_xpose_cols(A
, x
, y
);