g2o
Loading...
Searching...
No Matches
sparse_block_matrix.hpp
Go to the documentation of this file.
1// g2o - General Graph Optimization
2// Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright notice,
10// this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27#include <cassert>
28
29namespace g2o {
30
31template <class MatrixType>
33 int rb, int cb,
34 bool hasStorage)
35 : _rowBlockIndices(rbi, rbi + rb),
36 _colBlockIndices(cbi, cbi + cb),
37 _blockCols(cb),
38 _hasStorage(hasStorage) {}
39
40template <class MatrixType>
42 : _blockCols(0), _hasStorage(true) {}
43
44template <class MatrixType>
46#ifdef G2O_OPENMP
47#pragma omp parallel for default(shared) if (_blockCols.size() > 100)
48#endif
49 for (int i = 0; i < static_cast<int>(_blockCols.size()); ++i) {
51 it = _blockCols[i].begin();
52 it != _blockCols[i].end(); ++it) {
54 if (_hasStorage && dealloc)
55 delete b;
56 else
57 b->setZero();
58 }
59 if (_hasStorage && dealloc) _blockCols[i].clear();
60 }
61}
62
63template <class MatrixType>
65 if (_hasStorage) clear(true);
66}
67
68template <class MatrixType>
70SparseBlockMatrix<MatrixType>::block(int r, int c, bool alloc) {
72 _blockCols[c].find(r);
74 if (it == _blockCols[c].end()) {
75 if (!_hasStorage && !alloc)
76 return nullptr;
77 else {
78 int rb = rowsOfBlock(r);
79 int cb = colsOfBlock(c);
80 _block =
82 _block->setZero();
83 std::pair<typename SparseBlockMatrix<MatrixType>::IntBlockMap::iterator,
84 bool>
85 result = _blockCols[c].insert(std::make_pair(r, _block));
86 (void)result;
87 assert(result.second);
88 }
89 } else {
90 _block = it->second;
91 }
92 return _block;
93}
95template <class MatrixType>
99 _blockCols[c].find(r);
100 if (it == _blockCols[c].end()) return nullptr;
101 return it->second;
102}
104template <class MatrixType>
106 SparseBlockMatrix* ret =
107 new SparseBlockMatrix(&_rowBlockIndices[0], &_colBlockIndices[0],
108 _rowBlockIndices.size(), _colBlockIndices.size());
109 for (size_t i = 0; i < _blockCols.size(); ++i) {
111 it = _blockCols[i].begin();
112 it != _blockCols[i].end(); ++it) {
115 *it->second);
116 ret->_blockCols[i].insert(std::make_pair(it->first, b));
117 }
118 }
119 ret->_hasStorage = true;
120 return ret;
121}
122
123template <class MatrixType>
124template <class MatrixTransposedType>
127 for (size_t i = 0; i < _blockCols.size(); ++i) {
129 it = _blockCols[i].begin();
130 it != _blockCols[i].end(); ++it) {
133 dest.block(i, it->first, true);
134 *d = s->transpose();
135 }
137}
138
139template <class MatrixType>
140template <class MatrixTransposedType>
143 if (!dest._hasStorage) return false;
144 if (_rowBlockIndices.size() != dest._colBlockIndices.size()) return false;
145 if (_colBlockIndices.size() != dest._rowBlockIndices.size()) return false;
146 for (size_t i = 0; i < _rowBlockIndices.size(); ++i) {
147 if (_rowBlockIndices[i] != dest._colBlockIndices[i]) return false;
148 }
149 for (size_t i = 0; i < _colBlockIndices.size(); ++i) {
150 if (_colBlockIndices[i] != dest._rowBlockIndices[i]) return false;
151 }
152
153 transpose_internal(dest);
154 return true;
156
157template <class MatrixType>
158template <class MatrixTransposedType>
159std::unique_ptr<SparseBlockMatrix<MatrixTransposedType>>
161 auto dest = std::make_unique<SparseBlockMatrix<MatrixTransposedType>>(
162 &_colBlockIndices[0], &_rowBlockIndices[0], _colBlockIndices.size(),
163 _rowBlockIndices.size());
164 transpose_internal(*dest);
165 return dest;
167
168template <class MatrixType>
171 for (size_t i = 0; i < _blockCols.size(); ++i) {
173 it = _blockCols[i].begin();
174 it != _blockCols[i].end(); ++it) {
177 dest.block(it->first, i, true);
178 (*d) += *s;
179 }
181}
182
183template <class MatrixType>
185 SparseBlockMatrix<MatrixType>& dest) const {
186 if (!dest._hasStorage) return false;
187 if (_rowBlockIndices.size() != dest._rowBlockIndices.size()) return false;
188 if (_colBlockIndices.size() != dest._colBlockIndices.size()) return false;
189 for (size_t i = 0; i < _rowBlockIndices.size(); ++i) {
190 if (_rowBlockIndices[i] != dest._rowBlockIndices[i]) return false;
191 }
192 for (size_t i = 0; i < _colBlockIndices.size(); ++i) {
193 if (_colBlockIndices[i] != dest._colBlockIndices[i]) return false;
194 }
196 add_internal(dest);
197 return true;
198}
199
200template <class MatrixType>
201std::unique_ptr<SparseBlockMatrix<MatrixType>>
203 auto a = std::make_unique<SparseBlockMatrix>(
204 &_rowBlockIndices[0], &_colBlockIndices[0], _rowBlockIndices.size(),
205 _colBlockIndices.size());
206 add_internal(*a);
207 return a;
209
210template <class MatrixType>
211template <class MatrixResultType, class MatrixFactorType>
215 // sanity check
216 if (_colBlockIndices.size() != M->_rowBlockIndices.size()) return false;
217 for (size_t i = 0; i < _colBlockIndices.size(); ++i) {
218 if (_colBlockIndices[i] != M->_rowBlockIndices[i]) return false;
219 }
220 if (!dest) {
222 &_rowBlockIndices[0], &(M->_colBlockIndices[0]),
223 _rowBlockIndices.size(), M->_colBlockIndices.size());
224 }
225 if (!dest->_hasStorage) return false;
226 for (size_t i = 0; i < M->_blockCols.size(); ++i) {
227 for (typename SparseBlockMatrix<
228 MatrixFactorType>::IntBlockMap::const_iterator it =
229 M->_blockCols[i].begin();
230 it != M->_blockCols[i].end(); ++it) {
231 // look for a non-zero block in a row of column it
232 int colM = i;
234 it->second;
236 _blockCols[it->first].begin();
237 while (rbt != _blockCols[it->first].end()) {
238 // int colA=it->first;
239 int rowA = rbt->first;
241 rbt->second;
243 dest->block(rowA, colM, true);
244 assert(c->rows() == a->rows());
245 assert(c->cols() == b->cols());
246 ++rbt;
247 (*c) += (*a) * (*b);
248 }
249 }
250 }
251 return true;
252}
253
254template <class MatrixType>
256 const double* src) const {
257 if (!dest) {
258 dest = new double[_rowBlockIndices[_rowBlockIndices.size() - 1]];
259 memset(dest, 0,
260 _rowBlockIndices[_rowBlockIndices.size() - 1] * sizeof(double));
261 }
263 // map the memory by Eigen
264 Eigen::Map<VectorX> destVec(dest, rows());
265 const Eigen::Map<const VectorX> srcVec(src, cols());
266
267 for (size_t i = 0; i < _blockCols.size(); ++i) {
268 int srcOffset = i ? _colBlockIndices[i - 1] : 0;
269
271 it = _blockCols[i].begin();
272 it != _blockCols[i].end(); ++it) {
274 it->second;
275 int destOffset = it->first ? _rowBlockIndices[it->first - 1] : 0;
276 // destVec += *a * srcVec (according to the sub-vector parts)
277 internal::template axpy<
279 *a, srcVec, srcOffset, destVec, destOffset);
280 }
281 }
282}
283
284template <class MatrixType>
286 double*& dest, const double* src) const {
287 if (!dest) {
288 dest = new double[_rowBlockIndices[_rowBlockIndices.size() - 1]];
289 memset(dest, 0,
290 _rowBlockIndices[_rowBlockIndices.size() - 1] * sizeof(double));
291 }
292
293 // map the memory by Eigen
294 Eigen::Map<VectorX> destVec(dest, rows());
295 const Eigen::Map<const VectorX> srcVec(src, cols());
296
297 for (size_t i = 0; i < _blockCols.size(); ++i) {
298 int srcOffset = colBaseOfBlock(i);
300 it = _blockCols[i].begin();
301 it != _blockCols[i].end(); ++it) {
303 it->second;
304 int destOffset = rowBaseOfBlock(it->first);
305 if (destOffset > srcOffset) // only upper triangle
306 break;
307 // destVec += *a * srcVec (according to the sub-vector parts)
308 internal::template axpy<
310 *a, srcVec, srcOffset, destVec, destOffset);
311 if (destOffset < srcOffset)
312 internal::template atxpy<
314 *a, srcVec, destOffset, destVec, srcOffset);
315 }
316 }
317}
318
319template <class MatrixType>
321 const double* src) const {
322 int destSize = cols();
323
324 if (!dest) {
325 dest = new double[destSize];
326 memset(dest, 0, destSize * sizeof(double));
327 }
328
329 // map the memory by Eigen
330 Eigen::Map<VectorX> destVec(dest, destSize);
331 Eigen::Map<const VectorX> srcVec(src, rows());
332
333#ifdef G2O_OPENMP
334#pragma omp parallel for default(shared) schedule(dynamic, 10)
335#endif
336 for (int i = 0; i < static_cast<int>(_blockCols.size()); ++i) {
337 int destOffset = colBaseOfBlock(i);
339 it = _blockCols[i].begin();
340 it != _blockCols[i].end(); ++it) {
342 it->second;
343 int srcOffset = rowBaseOfBlock(it->first);
344 // destVec += *a.transpose() * srcVec (according to the sub-vector parts)
345 internal::template atxpy<
347 *a, srcVec, srcOffset, destVec, destOffset);
348 }
349 }
350}
351
352template <class MatrixType>
354 for (size_t i = 0; i < _blockCols.size(); ++i) {
356 it = _blockCols[i].begin();
357 it != _blockCols[i].end(); ++it) {
359 *a *= a_;
360 }
361 }
362}
363
364template <class MatrixType>
366 int rmin, int rmax, int cmin, int cmax, bool alloc) const {
367 int m = rmax - rmin;
368 int n = cmax - cmin;
369 int rowIdx[m];
370 rowIdx[0] = rowsOfBlock(rmin);
371 for (int i = 1; i < m; ++i) {
372 rowIdx[i] = rowIdx[i - 1] + rowsOfBlock(rmin + i);
373 }
374
375 int colIdx[n];
376 colIdx[0] = colsOfBlock(cmin);
377 for (int i = 1; i < n; ++i) {
378 colIdx[i] = colIdx[i - 1] + colsOfBlock(cmin + i);
379 }
380 SparseBlockMatrix* s = new SparseBlockMatrix(rowIdx, colIdx, m, n, true);
381 for (int i = 0; i < n; ++i) {
382 int mc = cmin + i;
384 it = _blockCols[mc].begin();
385 it != _blockCols[mc].end(); ++it) {
386 if (it->first >= rmin && it->first < rmax) {
388 alloc ? new
390 *(it->second))
391 : it->second;
392 s->_blockCols[i].insert(std::make_pair(it->first - rmin, b));
393 }
394 }
395 }
396 s->_hasStorage = alloc;
397 return s;
398}
399
400template <class MatrixType>
402 size_t count = 0;
403 for (size_t i = 0; i < _blockCols.size(); ++i) count += _blockCols[i].size();
404 return count;
405}
406
407template <class MatrixType>
409 if (MatrixType::SizeAtCompileTime != Eigen::Dynamic) {
410 size_t nnz = nonZeroBlocks() * MatrixType::SizeAtCompileTime;
411 return nnz;
412 } else {
413 size_t count = 0;
414 for (size_t i = 0; i < _blockCols.size(); ++i) {
416 it = _blockCols[i].begin();
417 it != _blockCols[i].end(); ++it) {
419 it->second;
420 count += a->cols() * a->rows();
421 }
422 }
423 return count;
424 }
425}
426
427template <class MatrixType>
428std::ostream& operator<<(std::ostream& os,
430 os << "RBI: " << m.rowBlockIndices().size();
431 for (size_t i = 0; i < m.rowBlockIndices().size(); ++i)
432 os << " " << m.rowBlockIndices()[i];
433 os << std::endl;
434 os << "CBI: " << m.colBlockIndices().size();
435 for (size_t i = 0; i < m.colBlockIndices().size(); ++i)
436 os << " " << m.colBlockIndices()[i];
437 os << std::endl;
438
439 for (size_t i = 0; i < m.blockCols().size(); ++i) {
441 it = m.blockCols()[i].begin();
442 it != m.blockCols()[i].end(); ++it) {
444 it->second;
445 os << "BLOCK: " << it->first << " " << i << std::endl;
446 os << *b << std::endl;
447 }
448 }
449 return os;
450}
451
452template <class MatrixType>
454 SparseBlockMatrix<MatrixType>*& dest, const int* pinv,
455 bool upperTriangle) const {
456 // compute the permuted version of the new row/column layout
457 size_t n = _rowBlockIndices.size();
458 // computed the block sizes
459 std::vector<int> blockSizes(_rowBlockIndices.size());
460 blockSizes[0] = _rowBlockIndices[0];
461 for (size_t i = 1; i < n; ++i) {
462 blockSizes[i] = _rowBlockIndices[i] - _rowBlockIndices[i - 1];
463 }
464 // permute them
465 std::vector<int> pBlockIndices(_rowBlockIndices.size());
466 for (size_t i = 0; i < n; ++i) {
467 pBlockIndices[pinv[i]] = blockSizes[i];
468 }
469 for (size_t i = 1; i < n; ++i) {
470 pBlockIndices[i] += pBlockIndices[i - 1];
471 }
472 // allocate C, or check the structure;
473 if (!dest) {
474 dest =
475 new SparseBlockMatrix(pBlockIndices.data(), pBlockIndices.data(), n, n);
476 } else {
477 if (dest->_rowBlockIndices.size() != n) return false;
478 if (dest->_colBlockIndices.size() != n) return false;
479 for (size_t i = 0; i < n; ++i) {
480 if (dest->_rowBlockIndices[i] != pBlockIndices[i]) return false;
481 if (dest->_colBlockIndices[i] != pBlockIndices[i]) return false;
482 }
483 dest->clear();
484 }
485 // now ready to permute the columns
486 for (size_t i = 0; i < n; ++i) {
487 int pi = pinv[i];
489 it = _blockCols[i].begin();
490 it != _blockCols[i].end(); ++it) {
491 int pj = pinv[it->first];
492
494 it->second;
495
497 if (!upperTriangle || pj <= pi) {
498 b = dest->block(pj, pi, true);
499 assert(b->cols() == s->cols());
500 assert(b->rows() == s->rows());
501 *b = *s;
502 } else {
503 b = dest->block(pi, pj, true);
504 assert(b);
505 assert(b->rows() == s->cols());
506 assert(b->cols() == s->rows());
507 *b = s->transpose();
508 }
509 }
510 // within each row,
511 }
512 return true;
513}
514
515template <class MatrixType>
517 bool upperTriangle) const {
518 assert(Cx && "Target destination is NULL");
519 double* CxStart = Cx;
520 for (size_t i = 0; i < _blockCols.size(); ++i) {
521 int cstart = i ? _colBlockIndices[i - 1] : 0;
522 int csize = colsOfBlock(i);
523 for (int c = 0; c < csize; ++c) {
525 it = _blockCols[i].begin();
526 it != _blockCols[i].end(); ++it) {
528 it->second;
529 int rstart = it->first ? _rowBlockIndices[it->first - 1] : 0;
530
531 int elemsToCopy = b->rows();
532 if (upperTriangle && rstart == cstart) elemsToCopy = c + 1;
533 memcpy(Cx, b->data() + c * b->rows(), elemsToCopy * sizeof(double));
534 Cx += elemsToCopy;
535 }
536 }
537 }
538 return Cx - CxStart;
539}
540
541template <class MatrixType>
542int SparseBlockMatrix<MatrixType>::fillCCS(int* Cp, int* Ci, double* Cx,
543 bool upperTriangle) const {
544 assert(Cp && Ci && Cx && "Target destination is NULL");
545 int nz = 0;
546 for (size_t i = 0; i < _blockCols.size(); ++i) {
547 int cstart = i ? _colBlockIndices[i - 1] : 0;
548 int csize = colsOfBlock(i);
549 for (int c = 0; c < csize; ++c) {
550 *Cp = nz;
552 it = _blockCols[i].begin();
553 it != _blockCols[i].end(); ++it) {
555 it->second;
556 int rstart = it->first ? _rowBlockIndices[it->first - 1] : 0;
557
558 int elemsToCopy = b->rows();
559 if (upperTriangle && rstart == cstart) elemsToCopy = c + 1;
560 for (int r = 0; r < elemsToCopy; ++r) {
561 *Cx++ = (*b)(r, c);
562 *Ci++ = rstart++;
563 ++nz;
564 }
565 }
566 ++Cp;
567 }
568 }
569 *Cp = nz;
570 return nz;
571}
572
573template <class MatrixType>
575 MatrixStructure& ms) const {
576 ms.alloc(_colBlockIndices.size(), nonZeroBlocks());
577 ms.m = _rowBlockIndices.size();
578 fillBlockStructure(ms.Ap, ms.Aii);
579}
580
581template <class MatrixType>
583 int nz = 0;
584 for (int c = 0; c < static_cast<int>(_blockCols.size()); ++c) {
585 *Cp = nz;
586 for (auto it = _blockCols[c].begin(); it != _blockCols[c].end(); ++it) {
587 const int& r = it->first;
588 if (r <= c) {
589 *Ci++ = r;
590 ++nz;
591 }
592 }
593 Cp++;
594 }
595 *Cp = nz;
596 assert(nz <= static_cast<int>(nonZeroBlocks()));
597}
598
599template <class MatrixType>
601 bool upperTriangle) const {
602 std::string name = filename;
603 std::string::size_type lastDot = name.find_last_of('.');
604 if (lastDot != std::string::npos) name.resize(lastDot);
605
606 std::vector<TripletEntry> entries;
607 for (size_t i = 0; i < _blockCols.size(); ++i) {
608 const int& c = i;
610 it = _blockCols[i].begin();
611 it != _blockCols[i].end(); ++it) {
612 const int& r = it->first;
613 const MatrixType& m = *(it->second);
614 for (int cc = 0; cc < m.cols(); ++cc)
615 for (int rr = 0; rr < m.rows(); ++rr) {
616 int aux_r = rowBaseOfBlock(r) + rr;
617 int aux_c = colBaseOfBlock(c) + cc;
618 entries.push_back(TripletEntry(aux_r, aux_c, m(rr, cc)));
619 if (upperTriangle && r != c) {
620 entries.push_back(TripletEntry(aux_c, aux_r, m(rr, cc)));
621 }
622 }
623 }
624 }
625
626 int nz = entries.size();
627 std::sort(entries.begin(), entries.end(), TripletColSort());
628
629 std::ofstream fout(filename);
630 fout << "# name: " << name << std::endl;
631 fout << "# type: sparse matrix" << std::endl;
632 fout << "# nnz: " << nz << std::endl;
633 fout << "# rows: " << rows() << std::endl;
634 fout << "# columns: " << cols() << std::endl;
635 fout << std::setprecision(9) << std::fixed << std::endl;
636
637 for (std::vector<TripletEntry>::const_iterator it = entries.begin();
638 it != entries.end(); ++it) {
639 const TripletEntry& entry = *it;
640 fout << entry.r + 1 << " " << entry.c + 1 << " " << entry.x << std::endl;
641 }
642 return fout.good();
643}
644
645template <class MatrixType>
647 SparseBlockMatrixCCS<MatrixType>& blockCCS) const {
648 blockCCS.blockCols().resize(blockCols().size());
649 int numblocks = 0;
650 for (size_t i = 0; i < blockCols().size(); ++i) {
651 const IntBlockMap& row = blockCols()[i];
653 blockCCS.blockCols()[i];
654 dest.clear();
655 dest.reserve(row.size());
656 for (typename IntBlockMap::const_iterator it = row.begin(); it != row.end();
657 ++it) {
658 dest.push_back(typename SparseBlockMatrixCCS<MatrixType>::RowBlock(
659 it->first, it->second));
660 ++numblocks;
661 }
662 }
663 return numblocks;
664}
665
666template <class MatrixType>
668 SparseBlockMatrixCCS<MatrixType>& blockCCS) const {
669 blockCCS.blockCols().clear();
670 blockCCS.blockCols().resize(_rowBlockIndices.size());
671 int numblocks = 0;
672 for (size_t i = 0; i < blockCols().size(); ++i) {
673 const IntBlockMap& row = blockCols()[i];
674 for (typename IntBlockMap::const_iterator it = row.begin(); it != row.end();
675 ++it) {
677 blockCCS.blockCols()[it->first];
678 dest.push_back(
679 typename SparseBlockMatrixCCS<MatrixType>::RowBlock(i, it->second));
680 ++numblocks;
681 }
682 }
683 return numblocks;
684}
685
686template <class MatrixType>
689 // sort the sparse columns and add them to the map structures by
690 // exploiting that we are inserting a sorted structure
691 typedef std::pair<int, MatrixType*> SparseColumnPair;
693 HashSparseColumn;
694 for (size_t i = 0; i < hashMatrix.blockCols().size(); ++i) {
695 // prepare a temporary vector for sorting
696 HashSparseColumn& column = hashMatrix.blockCols()[i];
697 if (column.size() == 0) continue;
698 std::vector<SparseColumnPair> sparseRowSorted; // temporary structure
699 sparseRowSorted.reserve(column.size());
700 for (typename HashSparseColumn::const_iterator it = column.begin();
701 it != column.end(); ++it)
702 sparseRowSorted.push_back(*it);
703 std::sort(sparseRowSorted.begin(), sparseRowSorted.end(),
705 // try to free some memory early
706 HashSparseColumn aux;
707 std::swap(aux, column);
708 // now insert sorted vector to the std::map structure
709 IntBlockMap& destColumnMap = blockCols()[i];
710 destColumnMap.insert(sparseRowSorted[0]);
711 for (size_t j = 1; j < sparseRowSorted.size(); ++j) {
713 destColumnMap.end();
714 --hint; // cppreference says the element goes after the hint (until
715 // C++11)
716 destColumnMap.insert(hint, sparseRowSorted[j]);
717 }
718 }
719}
720
721} // namespace g2o
representing the structure of a matrix in column compressed structure (only the upper triangular part...
int * Aii
row indices of A, of size nz = Ap [n]
int m
A is m-by-n. m must be >= 0.
void alloc(int n_, int nz)
int * Ap
column pointers for A, of size n+1
Sparse matrix which uses blocks.
std::vector< RowBlock > SparseColumn
const std::vector< SparseColumn > & blockCols() const
the block matrices per block-column
Sparse matrix which uses blocks based on hash structures.
std::unordered_map< int, MatrixType * > SparseColumn
const std::vector< SparseColumn > & blockCols() const
the block matrices per block-column
Sparse matrix which uses blocks.
size_t nonZeros() const
number of non-zero elements
void takePatternFromHash(SparseBlockMatrixHashMap< MatrixType > &hashMatrix)
bool symmPermutation(SparseBlockMatrix< MatrixType > *&dest, const int *pinv, bool onlyUpper=false) const
bool add(SparseBlockMatrix< MatrixType > &dest) const
adds the current matrix to the destination
bool transpose(SparseBlockMatrix< MatrixTransposedType > &dest) const
bool writeOctave(const char *filename, bool upperTriangle=true) const
int fillSparseBlockMatrixCCSTransposed(SparseBlockMatrixCCS< MatrixType > &blockCCS) const
size_t nonZeroBlocks() const
number of allocated blocks
int fillCCS(int *Cp, int *Ci, double *Cx, bool upperTriangle=false) const
const std::vector< IntBlockMap > & blockCols() const
the block matrices per block-column
int fillSparseBlockMatrixCCS(SparseBlockMatrixCCS< MatrixType > &blockCCS) const
std::unique_ptr< SparseBlockMatrix< MatrixType > > added() const
SparseBlockMatrix * slice(int rmin, int rmax, int cmin, int cmax, bool alloc=true) const
void rightMultiply(double *&dest, const double *src) const
dest = M * (*this)
void multiplySymmetricUpperTriangle(double *&dest, const double *src) const
const std::vector< int > & colBlockIndices() const
indices of the column blocks
std::unique_ptr< SparseBlockMatrix< MatrixTransposedType > > transposed() const
std::map< int, SparseMatrixBlock * > IntBlockMap
int rows() const
rows of the matrix
SparseMatrixBlock * block(int r, int c, bool alloc=false)
SparseBlockMatrix * clone() const
deep copy of a sparse-block-matrix;
std::vector< int > _rowBlockIndices
MatrixType SparseMatrixBlock
this is the type of the elementary block, it is an Eigen::Matrix.
bool multiply(SparseBlockMatrix< MatrixResultType > *&dest, const SparseBlockMatrix< MatrixFactorType > *M) const
dest = (*this) * M
int cols() const
columns of the matrix
std::vector< int > _colBlockIndices
void add_internal(SparseBlockMatrix< MatrixType > &dest) const
void fillBlockStructure(MatrixStructure &ms) const
exports the non zero blocks in the structure matrix ms
std::vector< IntBlockMap > _blockCols
const std::vector< int > & rowBlockIndices() const
indices of the row blocks
void clear(bool dealloc=false)
void transpose_internal(SparseBlockMatrix< MatrixTransposedType > &dest) const
void scale(double a)
*this *= a
std::ostream & operator<<(std::ostream &os, const G2OBatchStatistics &st)