NDEVR
API Documentation
sparse_block_matrix_ccs.h
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 "Base/Headers/Buffer.hpp"
31#include "Base/Headers/Dictionary.h"
32#include <Eigen/Core>
33
34#include "matrix_operations.h"
35
36namespace NDEVR
37{
38
46 template <class MatrixType>
47 class SparseBlockMatrixCCS
48 {
49 public:
51 typedef MatrixType SparseMatrixBlock;
52
54 int cols() const {return _colBlockIndices->size() ? _colBlockIndices->last() : 0;}
56 int rows() const {return _rowBlockIndices->size() ? _rowBlockIndices->last() : 0;}
57
61 struct RowBlock
62 {
63 int row;
64 MatrixType block;
65 RowBlock()
66 : row(-1)
67 {}
68 RowBlock(int r)
69 : row(r)
70 {
71 //if (r < 0 || r > Constant<sint02>::Max)
72 // throw "Bad Call";
73 }
74 RowBlock(int r, MatrixType b)
75 : row(r)
76 , block(b)
77 {
78 //if (r < 0 || r > Constant<sint02>::Max)
79 // throw "Bad Call";
80 }
81 bool operator<(const RowBlock& other) const { return row < other.row;}
82 };
83 typedef Buffer<RowBlock> SparseColumn;
84
85 SparseBlockMatrixCCS()
86 : _rowBlockIndices(nullptr), _colBlockIndices(nullptr)
87 {}
88 SparseBlockMatrixCCS(const Buffer<int>& rowIndices, const Buffer<int>& colIndices) :
89 _rowBlockIndices(&rowIndices), _colBlockIndices(&colIndices)
90 {}
91
93 int rowsOfBlock(int r) const { return r ? (*_rowBlockIndices)[r] - (*_rowBlockIndices)[r-1] : (*_rowBlockIndices)[0] ; }
94
96 int colsOfBlock(int c) const { return c ? (*_colBlockIndices)[c] - (*_colBlockIndices)[c-1] : (*_colBlockIndices)[0]; }
97
99 int rowBaseOfBlock(int r) const { return r ? (*_rowBlockIndices)[r-1] : 0 ; }
100
102 int colBaseOfBlock(int c) const { return c ? (*_colBlockIndices)[c-1] : 0 ; }
103
105 const Buffer<SparseColumn>& columns() const { return m_block_cols;}
107
109 const Buffer<int>& rowBlockIndices() const { return (*_rowBlockIndices);}
110
112 const Buffer<int>& colBlockIndices() const { return (*_colBlockIndices);}
113
114 void rightMultiply(g_type*& dest, const g_type* src) const
115 {
116 int destSize=cols();
117
118 if (! dest){
119 dest=new g_type [ destSize ];
120 memset(dest,0, destSize*sizeof(g_type));
121 }
122
123 // map the memory by Eigen
124 Eigen::Map<Eigen::VectorX<g_type>> destVec(dest, destSize);
125 Eigen::Map<const Eigen::VectorX<g_type>> srcVec(src, rows());
126
127 for (uint04 i=0; i < m_block_cols.size(); ++i)
128 {
129 int destOffset = colBaseOfBlock(i);
130 for (auto it = m_block_cols[i].begin(); it != m_block_cols[i].end(); ++it)
131 {
132 const SparseMatrixBlock& a = it->block;
133 int srcOffset = rowBaseOfBlock(it->row);
134 // destVec += *a.transpose() * srcVec (according to the sub-vector parts)
135 internal::atxpy(a, srcVec, srcOffset, destVec, destOffset);
136 }
137 }
138 }
139
144 {
145 for (uint04 i=0; i < m_block_cols.size(); ++i)
146 {
147 std::sort(m_block_cols[i].begin(), m_block_cols[i].end());
148 }
149 }
150
154 int fillCCS(int* Cp, int* Ci, g_type* Cx, bool upperTriangle = false) const
155 {
156 assert(Cp && Ci && Cx && "Target destination is NULL");
157 int nz=0;
158 for (uint04 i=0; i < m_block_cols.size(); ++i)
159 {
160 int cstart=i ? (*_colBlockIndices)[i-1] : 0;
161 int csize=colsOfBlock(i);
162 for (int c=0; c<csize; ++c) {
163 *Cp=nz;
164 for (auto it = m_block_cols[i].begin(); it != m_block_cols[i].end(); ++it)
165 {
166 const SparseMatrixBlock* b = it->block;
167 int rstart=it->row ? (*_rowBlockIndices)[it->row-1] : 0;
168
169 int elemsToCopy = b->rows();
170 if (upperTriangle && rstart == cstart)
171 elemsToCopy = c + 1;
172 for (int r=0; r<elemsToCopy; ++r){
173 *Cx++ = (*b)(r,c);
174 *Ci++ = rstart++;
175 ++nz;
176 }
177 }
178 ++Cp;
179 }
180 }
181 *Cp=nz;
182 return nz;
183 }
184
189 int fillCCS(g_type* Cx, bool upperTriangle = false) const
190 {
191 assert(Cx && "Target destination is NULL");
192 g_type* CxStart = Cx;
193 int cstart = 0;
194 for (uint04 i=0; i < m_block_cols.size(); ++i)
195 {
196 int csize = (*_colBlockIndices)[i] - cstart;
197 for (int c = 0; c < csize; ++c)
198 {
199 for (auto it = m_block_cols[i].begin(); it != m_block_cols[i].end(); ++it)
200 {
201 const SparseMatrixBlock* b = it->block;
202 int rstart = it->row ? (*_rowBlockIndices)[it->row-1] : 0;
203
204 int elemsToCopy = b->rows();
205 if (upperTriangle && rstart == cstart)
206 elemsToCopy = c + 1;
207 memcpy(Cx, b->data() + c*b->rows(), elemsToCopy * sizeof(g_type));
208 Cx += elemsToCopy;
209
210 }
211 }
212 cstart = (*_colBlockIndices)[i];
213 }
214 return Cx - CxStart;
215 }
216
217 protected:
221 };
222
223
224
230 template <class MatrixType>
231 class SparseBlockMatrixHashMap
232 {
233 public:
235 typedef MatrixType SparseMatrixBlock;
236
238 int cols() const {return _colBlockIndices->size() ? _colBlockIndices->last() : 0;}
240 int rows() const {return _rowBlockIndices->size() ? _rowBlockIndices->last() : 0;}
241
242 typedef Dictionary<int, MatrixType> SparseColumn;
243
244 SparseBlockMatrixHashMap(const Buffer<int>& rowIndices, const Buffer<int>& colIndices) :
245 _rowBlockIndices(&rowIndices), _colBlockIndices(&colIndices)
246 {}
247
249 int rowsOfBlock(int r) const { return r ? (*_rowBlockIndices)[r] - (*_rowBlockIndices)[r-1] : (*_rowBlockIndices)[0] ; }
250
252 int colsOfBlock(int c) const { return c ? (*_colBlockIndices)[c] - (*_colBlockIndices)[c-1] : (*_colBlockIndices)[0]; }
253
255 int rowBaseOfBlock(int r) const { return r ? (*_rowBlockIndices)[r-1] : 0 ; }
256
258 int colBaseOfBlock(int c) const { return c ? (*_colBlockIndices)[c-1] : 0 ; }
259
261 const Buffer<SparseColumn>& columns() const { return m_block_cols;}
263
265 const Buffer<int>& rowBlockIndices() const { return (*_rowBlockIndices);}
266
268 const Buffer<int>& colBlockIndices() const { return (*_colBlockIndices);}
269
273 MatrixType* addBlock(int r, uint04 c, bool zeroBlock = false)
274 {
275 SparseColumn& sparseColumn = m_block_cols[c];
276 auto iter = sparseColumn.find(r);
277 if (iter == sparseColumn.end())
278 {
279 int rb = rowsOfBlock(r);
280 int cb = colsOfBlock(c);
281 MatrixType m(rb, cb);
282 if (zeroBlock)
283 m.setZero();
284 sparseColumn[r] = m;
285 return &sparseColumn[r];
286 }
287 return &iter.value();
288 }
289
290 protected:
294 };
295
296} //end namespace
297
298#endif
The equivelent of std::vector but with a bit more control.
Definition Buffer.hpp:58
A hash-based key-value store, useful for quick associative lookups.
Definition Dictionary.h:64
const Buffer< int > * _rowBlockIndices
vector of the indices of the blocks along the rows.
Buffer< SparseColumn > m_block_cols
the matrices stored in CCS order
const Buffer< int > * _colBlockIndices
vector of the indices of the blocks along the cols
MatrixType SparseMatrixBlock
this is the type of the elementary block, it is an Eigen::Matrix.
int colBaseOfBlock(int c) const
where does the col at block-col r start?
const Buffer< int > & colBlockIndices() const
indices of the column blocks
int cols() const
columns of the matrix
void sortColumns()
sort the blocks in each column
const Buffer< SparseColumn > & columns() const
the block matrices per block-column
int rows() const
rows of the matrix
int colsOfBlock(int c) const
how many cols does the block at block-col c has?
int rowsOfBlock(int r) const
how many rows does the block at block-row r has?
int rowBaseOfBlock(int r) const
where does the row at block-row r start?
int fillCCS(int *Cp, int *Ci, g_type *Cx, bool upperTriangle=false) const
fill the CCS arrays of a matrix, arrays have to be allocated beforehand
const Buffer< int > & rowBlockIndices() const
indices of the row blocks
int fillCCS(g_type *Cx, bool upperTriangle=false) const
fill the CCS arrays of a matrix, arrays have to be allocated beforehand.
Sparse matrix which uses blocks based on hash structures.
const Buffer< int > & colBlockIndices() const
indices of the column blocks
const Buffer< int > * _colBlockIndices
vector of the indices of the blocks along the cols
MatrixType * addBlock(int r, uint04 c, bool zeroBlock=false)
add a block to the pattern, return a pointer to the added block
int rows() const
rows of the matrix
int rowsOfBlock(int r) const
how many rows does the block at block-row r has?
const Buffer< int > * _rowBlockIndices
vector of the indices of the blocks along the rows.
int rowBaseOfBlock(int r) const
where does the row at block-row r start?
int colBaseOfBlock(int c) const
where does the col at block-col r start?
int cols() const
columns of the matrix
const Buffer< SparseColumn > & columns() const
the block matrices per block-column
MatrixType SparseMatrixBlock
this is the type of the elementary block, it is an Eigen::Matrix.
int colsOfBlock(int c) const
how many cols does the block at block-col c has?
const Buffer< int > & rowBlockIndices() const
indices of the row blocks
Buffer< SparseColumn > m_block_cols
the matrices stored in CCS order
Internal helper functions for block-wise matrix-vector products (axpy and atxpy).
The primary namespace for the NDEVR SDK.
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
MatrixType block
matrix pointer for the block