g2o
Loading...
Searching...
No Matches
sparse_block_matrix_ccs.h
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#ifndef G2O_SPARSE_BLOCK_MATRIX_CCS_H
28#define G2O_SPARSE_BLOCK_MATRIX_CCS_H
29
30#include <Eigen/Core>
31#include <cassert>
32#include <unordered_map>
33#include <vector>
34
35#include "g2o/config.h"
36#include "matrix_operations.h"
37
38namespace g2o {
39
47template <class MatrixType>
49 public:
51 typedef MatrixType SparseMatrixBlock;
52
54 int cols() const {
55 return _colBlockIndices.size() ? _colBlockIndices.back() : 0;
56 }
58 int rows() const {
59 return _rowBlockIndices.size() ? _rowBlockIndices.back() : 0;
60 }
61
65 struct RowBlock {
66 int row;
67 MatrixType* block;
68 RowBlock() : row(-1), block(0) {}
69 RowBlock(int r, MatrixType* b) : row(r), block(b) {}
70 bool operator<(const RowBlock& other) const { return row < other.row; }
71 };
72 typedef std::vector<RowBlock> SparseColumn;
73
74 SparseBlockMatrixCCS(const std::vector<int>& rowIndices,
75 const std::vector<int>& colIndices)
76 : _rowBlockIndices(rowIndices), _colBlockIndices(colIndices) {}
77
79 int rowsOfBlock(int r) const {
80 return r ? _rowBlockIndices[r] - _rowBlockIndices[r - 1]
82 }
83
85 int colsOfBlock(int c) const {
86 return c ? _colBlockIndices[c] - _colBlockIndices[c - 1]
88 }
89
91 int rowBaseOfBlock(int r) const { return r ? _rowBlockIndices[r - 1] : 0; }
92
94 int colBaseOfBlock(int c) const { return c ? _colBlockIndices[c - 1] : 0; }
95
97 const std::vector<SparseColumn>& blockCols() const { return _blockCols; }
98 std::vector<SparseColumn>& blockCols() { return _blockCols; }
99
101 const std::vector<int>& rowBlockIndices() const { return _rowBlockIndices; }
102
104 const std::vector<int>& colBlockIndices() const { return _colBlockIndices; }
105
106 void rightMultiply(double*& dest, const double* src) const {
107 int destSize = cols();
108
109 if (!dest) {
110 dest = new double[destSize];
111 memset(dest, 0, destSize * sizeof(double));
112 }
113
114 // map the memory by Eigen
115 Eigen::Map<VectorX> destVec(dest, destSize);
116 Eigen::Map<const VectorX> srcVec(src, rows());
117
118#ifdef G2O_OPENMP
119#pragma omp parallel for default(shared) schedule(dynamic, 10)
120#endif
121 for (int i = 0; i < static_cast<int>(_blockCols.size()); ++i) {
122 int destOffset = colBaseOfBlock(i);
123 for (typename SparseColumn::const_iterator it = _blockCols[i].begin();
124 it != _blockCols[i].end(); ++it) {
125 const SparseMatrixBlock* a = it->block;
126 int srcOffset = rowBaseOfBlock(it->row);
127 // destVec += *a.transpose() * srcVec (according to the sub-vector
128 // parts)
129 internal::template atxpy<SparseMatrixBlock>(*a, srcVec, srcOffset,
130 destVec, destOffset);
131 }
132 }
133 }
134
138 void sortColumns() {
139 for (int i = 0; i < static_cast<int>(_blockCols.size()); ++i) {
140 std::sort(_blockCols[i].begin(), _blockCols[i].end());
141 }
142 }
143
147 int fillCCS(int* Cp, int* Ci, double* Cx, bool upperTriangle = false) const {
148 assert(Cp && Ci && Cx && "Target destination is NULL");
149 int nz = 0;
150 for (size_t i = 0; i < _blockCols.size(); ++i) {
151 int cstart = i ? _colBlockIndices[i - 1] : 0;
152 int csize = colsOfBlock(i);
153 for (int c = 0; c < csize; ++c) {
154 *Cp = nz;
155 for (typename SparseColumn::const_iterator it = _blockCols[i].begin();
156 it != _blockCols[i].end(); ++it) {
157 const SparseMatrixBlock* b = it->block;
158 int rstart = it->row ? _rowBlockIndices[it->row - 1] : 0;
159
160 int elemsToCopy = b->rows();
161 if (upperTriangle && rstart == cstart) elemsToCopy = c + 1;
162 for (int r = 0; r < elemsToCopy; ++r) {
163 *Cx++ = (*b)(r, c);
164 *Ci++ = rstart++;
165 ++nz;
166 }
167 }
168 ++Cp;
169 }
170 }
171 *Cp = nz;
172 return nz;
173 }
174
180 int fillCCS(double* Cx, bool upperTriangle = false) const {
181 assert(Cx && "Target destination is NULL");
182 double* CxStart = Cx;
183 int cstart = 0;
184 for (size_t i = 0; i < _blockCols.size(); ++i) {
185 int csize = _colBlockIndices[i] - cstart;
186 for (int c = 0; c < csize; ++c) {
187 for (typename SparseColumn::const_iterator it = _blockCols[i].begin();
188 it != _blockCols[i].end(); ++it) {
189 const SparseMatrixBlock* b = it->block;
190 int rstart = it->row ? _rowBlockIndices[it->row - 1] : 0;
191
192 int elemsToCopy = b->rows();
193 if (upperTriangle && rstart == cstart) elemsToCopy = c + 1;
194 memcpy(Cx, b->data() + c * b->rows(), elemsToCopy * sizeof(double));
195 Cx += elemsToCopy;
196 }
197 }
198 cstart = _colBlockIndices[i];
199 }
200 return Cx - CxStart;
201 }
202
203 protected:
204 const std::vector<int>& _rowBlockIndices;
206 const std::vector<int>&
208 std::vector<SparseColumn> _blockCols;
209};
210
216template <class MatrixType>
218 public:
220 typedef MatrixType SparseMatrixBlock;
221
223 int cols() const {
224 return _colBlockIndices.size() ? _colBlockIndices.back() : 0;
225 }
227 int rows() const {
228 return _rowBlockIndices.size() ? _rowBlockIndices.back() : 0;
229 }
230
231 typedef std::unordered_map<int, MatrixType*> SparseColumn;
232
233 SparseBlockMatrixHashMap(const std::vector<int>& rowIndices,
234 const std::vector<int>& colIndices)
235 : _rowBlockIndices(rowIndices), _colBlockIndices(colIndices) {}
236
238 int rowsOfBlock(int r) const {
239 return r ? _rowBlockIndices[r] - _rowBlockIndices[r - 1]
240 : _rowBlockIndices[0];
241 }
242
244 int colsOfBlock(int c) const {
245 return c ? _colBlockIndices[c] - _colBlockIndices[c - 1]
246 : _colBlockIndices[0];
247 }
248
250 int rowBaseOfBlock(int r) const { return r ? _rowBlockIndices[r - 1] : 0; }
251
253 int colBaseOfBlock(int c) const { return c ? _colBlockIndices[c - 1] : 0; }
254
256 const std::vector<SparseColumn>& blockCols() const { return _blockCols; }
257 std::vector<SparseColumn>& blockCols() { return _blockCols; }
258
260 const std::vector<int>& rowBlockIndices() const { return _rowBlockIndices; }
261
263 const std::vector<int>& colBlockIndices() const { return _colBlockIndices; }
264
268 MatrixType* addBlock(int r, int c, bool zeroBlock = false) {
269 assert(c < (int)_blockCols.size() &&
270 "accessing column which is not available");
271 SparseColumn& sparseColumn = _blockCols[c];
272 typename SparseColumn::iterator foundIt = sparseColumn.find(r);
273 if (foundIt == sparseColumn.end()) {
274 int rb = rowsOfBlock(r);
275 int cb = colsOfBlock(c);
276 MatrixType* m = new MatrixType(rb, cb);
277 if (zeroBlock) m->setZero();
278 sparseColumn[r] = m;
279 return m;
280 }
281 return foundIt->second;
282 }
283
284 protected:
285 const std::vector<int>& _rowBlockIndices;
287 const std::vector<int>&
289 std::vector<SparseColumn> _blockCols;
290};
291
292} // namespace g2o
293
294#endif
Sparse matrix which uses blocks.
int rowsOfBlock(int r) const
how many rows does the block at block-row r has?
int fillCCS(int *Cp, int *Ci, double *Cx, bool upperTriangle=false) const
int colsOfBlock(int c) const
how many cols does the block at block-col c has?
MatrixType SparseMatrixBlock
this is the type of the elementary block, it is an Eigen::Matrix.
std::vector< RowBlock > SparseColumn
int cols() const
columns of the matrix
int colBaseOfBlock(int c) const
where does the col at block-col r start?
int fillCCS(double *Cx, bool upperTriangle=false) const
const std::vector< SparseColumn > & blockCols() const
the block matrices per block-column
const std::vector< int > & rowBlockIndices() const
indices of the row blocks
int rowBaseOfBlock(int r) const
where does the row at block-row r start?
std::vector< SparseColumn > _blockCols
the matrices stored in CCS order
SparseBlockMatrixCCS(const std::vector< int > &rowIndices, const std::vector< int > &colIndices)
std::vector< SparseColumn > & blockCols()
int rows() const
rows of the matrix
void rightMultiply(double *&dest, const double *src) const
const std::vector< int > & colBlockIndices() const
indices of the column blocks
const std::vector< int > & _colBlockIndices
vector of the indices of the blocks along the cols
const std::vector< int > & _rowBlockIndices
Sparse matrix which uses blocks based on hash structures.
MatrixType SparseMatrixBlock
this is the type of the elementary block, it is an Eigen::Matrix.
const std::vector< int > & _colBlockIndices
vector of the indices of the blocks along the cols
MatrixType * addBlock(int r, int c, bool zeroBlock=false)
std::unordered_map< int, MatrixType * > SparseColumn
int colsOfBlock(int c) const
how many cols does the block at block-col c has?
const std::vector< int > & rowBlockIndices() const
indices of the row blocks
int cols() const
columns of the matrix
std::vector< SparseColumn > & blockCols()
int rowBaseOfBlock(int r) const
where does the row at block-row r start?
const std::vector< int > & _rowBlockIndices
SparseBlockMatrixHashMap(const std::vector< int > &rowIndices, const std::vector< int > &colIndices)
const std::vector< SparseColumn > & blockCols() const
the block matrices per block-column
int colBaseOfBlock(int c) const
where does the col at block-col r start?
const std::vector< int > & colBlockIndices() const
indices of the column blocks
int rows() const
rows of the matrix
std::vector< SparseColumn > _blockCols
the matrices stored in CCS order
int rowsOfBlock(int r) const
how many rows does the block at block-row r has?
MatrixType * block
matrix pointer for the block
bool operator<(const RowBlock &other) const