00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <assert.h>
00018 #include "sparse_block_matrix.h"
00019
00020 namespace g2o {
00021 using namespace Eigen;
00022
00023 namespace {
00024 struct TripletEntry
00025 {
00026 int r, c;
00027 double x;
00028 TripletEntry(int r_, int c_, double x_) : r(r_), c(c_), x(x_) {}
00029 };
00030
00031
00032
00033 struct TripletColSort
00034 {
00035 bool operator()(const TripletEntry& e1, const TripletEntry& e2) const
00036 {
00037 return e1.c < e2.c || (e1.c == e2.c && e1.r < e2.r);
00038 }
00039 };
00040 }
00041
00042
00043
00044
00045
00046 template <class MatrixType>
00047 SparseBlockMatrix<MatrixType>::SparseBlockMatrix
00048 (
00049 const int *rbi, const int *cbi,
00050 int rb, int cb, bool hasStorage
00051 ):
00052 _rowBlockIndices(rbi, rbi+rb),
00053 _colBlockIndices(cbi, cbi+cb),
00054 _blockCols(cb), _hasStorage(hasStorage)
00055 {}
00056
00057
00058
00059 template <class MatrixType>
00060 SparseBlockMatrix<MatrixType>::SparseBlockMatrix():
00061 _blockCols(0), _hasStorage(true)
00062 {}
00063
00064
00065
00066
00067 template <class MatrixType>
00068 void SparseBlockMatrix<MatrixType>::clear(bool dealloc)
00069 {
00070 # ifdef G2O_OPENMP
00071 # pragma omp parallel for default (shared) if (_blockCols.size() > 100)
00072 # endif
00073 for (int i=0; i < static_cast<int>(_blockCols.size()); ++i)
00074 {
00075 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00076 it = _blockCols[i].begin();
00077 it != _blockCols[i].end();
00078 it++)
00079 {
00080 typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* b=it->second;
00081 if (_hasStorage && dealloc) delete b;
00082 else b->setZero();
00083 }
00084 if (_hasStorage && dealloc) _blockCols[i].clear();
00085 }
00086 }
00087
00088
00089
00090 template <class MatrixType>
00091 SparseBlockMatrix<MatrixType>::~SparseBlockMatrix()
00092 {
00093 if (_hasStorage) clear(true);
00094 }
00095
00096
00097
00098
00099
00100
00101 template <class MatrixType>
00102 typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock*
00103 SparseBlockMatrix<MatrixType>::block(int r, int c, bool alloc)
00104 {
00105 typename SparseBlockMatrix<MatrixType>::IntBlockMap::iterator it =
00106 _blockCols[c].find(r);
00107
00108 typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* _block = 0;
00109
00110 if (it == _blockCols[c].end())
00111 {
00112 if (!_hasStorage && ! alloc ) return 0;
00113 else
00114 {
00115 int rb = rowsOfBlock(r);
00116 int cb = colsOfBlock(c);
00117 _block =
00118 new typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock(rb,cb);
00119 _block->setZero();
00120 std::pair
00121 <
00122 typename SparseBlockMatrix<MatrixType>::IntBlockMap::iterator,
00123 bool
00124 > result =_blockCols[c].insert(std::make_pair(r,_block));
00125 (void) result;
00126 assert (result.second);
00127 }
00128 }else _block = it->second;
00129
00130 return _block;
00131 }
00132
00133
00134
00135 template <class MatrixType>
00136 const typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock*
00137 SparseBlockMatrix<MatrixType>::block(int r, int c) const
00138 {
00139 typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator it =
00140 _blockCols[c].find(r);
00141 if (it==_blockCols[c].end()) return 0;
00142 return it->second;
00143 }
00144
00145
00146
00147 template <class MatrixType>
00148 SparseBlockMatrix<MatrixType>* SparseBlockMatrix<MatrixType>::clone() const
00149 {
00150 SparseBlockMatrix* ret =
00151 new SparseBlockMatrix
00152 (
00153 &_rowBlockIndices[0], &_colBlockIndices[0],
00154 _rowBlockIndices.size(), _colBlockIndices.size()
00155 );
00156 for (size_t i=0; i<_blockCols.size(); i++)
00157 {
00158 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00159 it = _blockCols[i].begin();
00160 it != _blockCols[i].end();
00161 it++)
00162 {
00163 typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* b =
00164 new typename
00165 SparseBlockMatrix<MatrixType>::SparseMatrixBlock(*it->second);
00166
00167 ret->_blockCols[i].insert(std::make_pair(it->first, b));
00168 }
00169 }
00170 ret->_hasStorage = true;
00171 return ret;
00172 }
00173
00174
00175
00176 template <class MatrixType>
00177 template <class MatrixTransposedType>
00178 bool SparseBlockMatrix<MatrixType>::transpose
00179 (SparseBlockMatrix<MatrixTransposedType>*& dest) const
00180 {
00181 if (! dest)
00182 {
00183 dest =
00184 new SparseBlockMatrix<MatrixTransposedType>
00185 (
00186 &_colBlockIndices[0], &_rowBlockIndices[0],
00187 _colBlockIndices.size(), _rowBlockIndices.size()
00188 );
00189 }else
00190 {
00191 if(! dest->_hasStorage) return false;
00192 if(_rowBlockIndices.size()!=dest->_colBlockIndices.size()) return false;
00193 if(_colBlockIndices.size()!=dest->_rowBlockIndices.size()) return false;
00194
00195 for (size_t i=0; i<_rowBlockIndices.size(); i++)
00196 {
00197 if(_rowBlockIndices[i]!=dest->_colBlockIndices[i]) return false;
00198 }
00199
00200 for (size_t i=0; i<_colBlockIndices.size(); i++)
00201 if(_colBlockIndices[i]!=dest->_rowBlockIndices[i]) return false;
00202 }
00203
00204 for (size_t i=0; i<_blockCols.size(); i++)
00205 {
00206 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00207 it = _blockCols[i].begin();
00208 it != _blockCols[i].end();
00209 it++)
00210 {
00211 typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* s =
00212 it->second;
00213 typename SparseBlockMatrix<MatrixTransposedType>::SparseMatrixBlock* d =
00214 dest->block(i,it->first,true);
00215 *d = s->transpose();
00216 }
00217 }
00218 return true;
00219 }
00220
00221
00222
00223 template <class MatrixType>
00224 bool SparseBlockMatrix<MatrixType>::add(SparseBlockMatrix*& dest) const
00225 {
00226 if (! dest)
00227 {
00228 dest =
00229 new SparseBlockMatrix
00230 (
00231 &_rowBlockIndices[0], &_colBlockIndices[0],
00232 _rowBlockIndices.size(), _colBlockIndices.size()
00233 );
00234 }else
00235 {
00236 if(! dest->_hasStorage) return false;
00237
00238 if(_rowBlockIndices.size()!=dest->_rowBlockIndices.size()) return false;
00239 if(_colBlockIndices.size()!=dest->_colBlockIndices.size()) return false;
00240 for (size_t i=0; i<_rowBlockIndices.size(); i++)
00241 {
00242 if(_rowBlockIndices[i]!=dest->_rowBlockIndices[i]) return false;
00243 }
00244 for (size_t i=0; i<_colBlockIndices.size(); i++)
00245 {
00246 if(_colBlockIndices[i]!=dest->_colBlockIndices[i]) return false;
00247 }
00248 }
00249
00250 for (size_t i=0; i<_blockCols.size(); i++)
00251 {
00252 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00253 it = _blockCols[i].begin();
00254 it != _blockCols[i].end();
00255 it++)
00256 {
00257 typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* s =
00258 it->second;
00259 typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* d =
00260 dest->block(it->first,i,true);
00261 (*d) += *s;
00262 }
00263 }
00264 return true;
00265 }
00266
00267
00268
00269 template <class MatrixType>
00270 template < class MatrixResultType, class MatrixFactorType >
00271 bool SparseBlockMatrix<MatrixType>::multiply
00272 (
00273 SparseBlockMatrix<MatrixResultType>*& dest,
00274 const SparseBlockMatrix<MatrixFactorType> * M
00275 ) const
00276 {
00277
00278 if(_colBlockIndices.size()!=M->_rowBlockIndices.size()) return false;
00279 for (size_t i=0; i<_colBlockIndices.size(); i++)
00280 if(_colBlockIndices[i]!=M->_rowBlockIndices[i]) return false;
00281
00282 if (! dest)
00283 {
00284 dest =
00285 new SparseBlockMatrix<MatrixResultType>
00286 (
00287 &_rowBlockIndices[0], &(M->_colBlockIndices[0]),
00288 _rowBlockIndices.size(), M->_colBlockIndices.size()
00289 );
00290 }
00291
00292 if (! dest->_hasStorage) return false;
00293
00294 for (size_t i=0; i<M->_blockCols.size(); i++)
00295 {
00296 for (typename SparseBlockMatrix<MatrixFactorType>::IntBlockMap::
00297 const_iterator it = M->_blockCols[i].begin();
00298 it != M->_blockCols[i].end();
00299 it++)
00300 {
00301
00302 int colM = i;
00303 const typename SparseBlockMatrix<MatrixFactorType>::
00304 SparseMatrixBlock *b = it->second;
00305
00306 typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00307 rbt = _blockCols[it->first].begin();
00308
00309 while(rbt!=_blockCols[it->first].end())
00310 {
00311
00312 int rowA = rbt->first;
00313 typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock *a =
00314 rbt->second;
00315 typename SparseBlockMatrix<MatrixResultType>::SparseMatrixBlock *c =
00316 dest->block(rowA,colM,true);
00317 assert (c->rows()==a->rows());
00318 assert (c->cols()==b->cols());
00319 rbt++;
00320 (*c) += (*a)*(*b);
00321 }
00322 }
00323 }
00324 return false;
00325 }
00326
00327
00328
00329 template<typename MatrixType>
00330 inline void axpy
00331 (
00332 const MatrixType& A, const Map<VectorXd>& x,
00333 int xoff, Map<VectorXd>& y, int yoff
00334 )
00335 {
00336 y.segment<MatrixType::RowsAtCompileTime>(yoff) +=
00337 A * x.segment<MatrixType::ColsAtCompileTime>(xoff);
00338 }
00339
00340
00341
00342 template<>
00343 inline void axpy
00344 (
00345 const MatrixXd& A, const Map<VectorXd>& x,
00346 int xoff, Map<VectorXd>& y, int yoff
00347 )
00348 {
00349 y.segment(yoff, A.rows()) += A * x.segment(xoff, A.cols());
00350 }
00351
00352
00353
00354 template<typename MatrixType>
00355 inline void atxpy
00356 (
00357 const MatrixType& A, Map<const VectorXd>& x,
00358 int xoff, Map<VectorXd>& y, int yoff
00359 )
00360 {
00361 y.segment<MatrixType::ColsAtCompileTime>(yoff) +=
00362 A.transpose() * x.segment<MatrixType::RowsAtCompileTime>(xoff);
00363 }
00364
00365
00366
00367 template<>
00368 inline void atxpy
00369 (
00370 const MatrixXd& A, Map<const VectorXd>& x,
00371 int xoff, Map<VectorXd>& y, int yoff
00372 )
00373 {
00374 y.segment(yoff, A.cols()) += A.transpose() * x.segment(xoff, A.rows());
00375 }
00376
00377
00378
00379 template <class MatrixType>
00380 void SparseBlockMatrix<MatrixType>::multiply(double*& dest, const double* src)
00381 const
00382 {
00383 if (! dest)
00384 {
00385 dest = new double [_rowBlockIndices[_rowBlockIndices.size()-1] ];
00386 memset
00387 (dest, 0, _rowBlockIndices[_rowBlockIndices.size()-1]*sizeof(double));
00388 }
00389
00390
00391 Map<VectorXd> destVec(dest, rows());
00392 const Map<VectorXd> srcVec(src, cols());
00393
00394 for (size_t i=0; i<_blockCols.size(); i++)
00395 {
00396 int srcOffset = i ? _colBlockIndices[i-1] : 0;
00397
00398 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00399 it = _blockCols[i].begin();
00400 it != _blockCols[i].end();
00401 ++it)
00402 {
00403 const typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* a =
00404 it->second;
00405 int destOffset = it->first ? _rowBlockIndices[it->first - 1] : 0;
00406
00407 axpy(*a, srcVec, srcOffset, destVec, destOffset);
00408 }
00409 }
00410 }
00411
00412
00413
00414 template <class MatrixType>
00415 void SparseBlockMatrix<MatrixType>::rightMultiply
00416 (double*& dest, const double* src) const
00417 {
00418 int destSize=cols();
00419
00420 if (! dest)
00421 {
00422 dest=new double [ destSize ];
00423 memset(dest,0, destSize*sizeof(double));
00424 }
00425
00426
00427 Map<VectorXd> destVec(dest, destSize);
00428 Map<const VectorXd> srcVec(src, rows());
00429
00430 # ifdef G2O_OPENMP
00431 # pragma omp parallel for default (shared)
00432 # endif
00433 for (int i=0; i < static_cast<int>(_blockCols.size()); i++)
00434 {
00435 int destOffset = colBaseOfBlock(i);
00436 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00437 it = _blockCols[i].begin();
00438 it != _blockCols[i].end();
00439 ++it)
00440 {
00441 const typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* a =
00442 it->second;
00443 int srcOffset = rowBaseOfBlock(it->first);
00444
00445 atxpy(*a, srcVec, srcOffset, destVec, destOffset);
00446 }
00447 }
00448
00449 }
00450
00451
00452
00453 template <class MatrixType>
00454 void SparseBlockMatrix<MatrixType>::scale(double a_)
00455 {
00456 for (size_t i=0; i<_blockCols.size(); i++)
00457 {
00458 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00459 it = _blockCols[i].begin();
00460 it != _blockCols[i].end();
00461 ++it)
00462 {
00463 typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* a=it->second;
00464 *a *= a_;
00465 }
00466 }
00467 }
00468
00469
00470
00471 template <class MatrixType>
00472 SparseBlockMatrix<MatrixType>* SparseBlockMatrix<MatrixType>::slice
00473 (int rmin, int rmax, int cmin, int cmax, bool alloc) const
00474 {
00475 int m = rmax-rmin;
00476 int n = cmax-cmin;
00477 int rowIdx [m];
00478 rowIdx[0] = rowsOfBlock(rmin);
00479 for (int i = 1; i<m; i++)
00480 rowIdx[i]=rowIdx[i-1]+rowsOfBlock(rmin+i);
00481
00482 int colIdx [n];
00483 colIdx[0] = colsOfBlock(cmin);
00484 for (int i=1; i<n; i++)
00485 colIdx[i]=colIdx[i-1]+colsOfBlock(cmin+i);
00486
00487 typename SparseBlockMatrix<MatrixType>::SparseBlockMatrix* s =
00488 new SparseBlockMatrix(rowIdx, colIdx, m, n, true);
00489
00490 for (int i=0; i<n; i++)
00491 {
00492 int mc=cmin+i;
00493 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00494 it = _blockCols[mc].begin();
00495 it != _blockCols[mc].end();
00496 it++)
00497 {
00498 if (it->first >= rmin && it->first < rmax)
00499 {
00500 typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* b =
00501 alloc
00502 ? new typename
00503 SparseBlockMatrix<MatrixType>::SparseMatrixBlock (*(it->second))
00504 : it->second;
00505
00506 s->_blockCols[i].insert(std::make_pair(it->first-rmin, b));
00507 }
00508 }
00509 }
00510 s->_hasStorage=alloc;
00511 return s;
00512 }
00513
00514
00515
00516 template <class MatrixType>
00517 size_t SparseBlockMatrix<MatrixType>::nonZeroBlocks() const
00518 {
00519 size_t count=0;
00520 for (size_t i=0; i<_blockCols.size(); i++)
00521 count+=_blockCols[i].size();
00522 return count;
00523 }
00524
00525
00526
00527 template <class MatrixType>
00528 size_t SparseBlockMatrix<MatrixType>::nonZeros() const
00529 {
00530 if (MatrixType::SizeAtCompileTime != Eigen::Dynamic)
00531 {
00532 size_t nnz = nonZeroBlocks() * MatrixType::SizeAtCompileTime;
00533 return nnz;
00534 }else
00535 {
00536 size_t count=0;
00537 for (size_t i=0; i<_blockCols.size(); i++)
00538 {
00539 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00540 it = _blockCols[i].begin();
00541 it != _blockCols[i].end();
00542 it++)
00543 {
00544 const typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* a =
00545 it->second;
00546 count += a->cols()*a->rows();
00547 }
00548 }
00549 return count;
00550 }
00551 }
00552
00553
00554
00555 template <class MatrixType>
00556 std::ostream& operator <<
00557 (std::ostream& os, const SparseBlockMatrix<MatrixType>& m)
00558 {
00559 os << "RBI: " << m.rowBlockIndices().size();
00560 for (size_t i=0; i<m.rowBlockIndices().size(); i++)
00561 os << " " << m.rowBlockIndices()[i];
00562 os << std::endl;
00563
00564 os << "CBI: " << m.colBlockIndices().size();
00565 for (size_t i=0; i<m.colBlockIndices().size(); i++)
00566 os << " " << m.colBlockIndices()[i];
00567 os << std::endl;
00568
00569 for (size_t i=0; i<m.blockCols().size(); i++)
00570 {
00571 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00572 it = m.blockCols()[i].begin();
00573 it != m.blockCols()[i].end();
00574 it++)
00575 {
00576 const typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* b =
00577 it->second;
00578 os << "BLOCK: " << it->first << " " << i << std::endl
00579 << *b << std::endl;
00580 }
00581 }
00582 return os;
00583 }
00584
00585
00586
00587 template <class MatrixType>
00588 bool SparseBlockMatrix<MatrixType>::symmPermutation
00589 (SparseBlockMatrix<MatrixType>*& dest, const int* pinv, bool upperTriangle)
00590 const
00591 {
00592
00593 size_t n=_rowBlockIndices.size();
00594
00595
00596 int blockSizes[_rowBlockIndices.size()];
00597 blockSizes[0]=_rowBlockIndices[0];
00598 for (size_t i=1; i<n; i++)
00599 blockSizes[i]=_rowBlockIndices[i]-_rowBlockIndices[i-1];
00600
00601
00602 int pBlockIndices[_rowBlockIndices.size()];
00603 for (size_t i=0; i<n; i++)
00604 pBlockIndices[pinv[i]]=blockSizes[i];
00605
00606 for (size_t i=1; i<n; i++)
00607 pBlockIndices[i] += pBlockIndices[i-1];
00608
00609
00610 if(! dest)
00611 {
00612 dest =
00613 new SparseBlockMatrix(pBlockIndices, pBlockIndices, n, n);
00614 }else
00615 {
00616 if(dest->_rowBlockIndices.size()!=n) return false;
00617 if(dest->_colBlockIndices.size()!=n) return false;
00618 for (size_t i=0; i<n; i++)
00619 {
00620 if(dest->_rowBlockIndices[i]!=pBlockIndices[i]) return false;
00621 if(dest->_colBlockIndices[i]!=pBlockIndices[i]) return false;
00622 }
00623 dest->clear();
00624 }
00625
00626
00627 for (size_t i=0; i<n; i++)
00628 {
00629
00630 int pi = pinv[i];
00631 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00632 it = _blockCols[i].begin();
00633 it!=_blockCols[i].end();
00634 it++)
00635 {
00636 int pj=pinv[it->first];
00637
00638 const typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* s =
00639 it->second;
00640
00641 typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* b = 0;
00642 if (! upperTriangle || pj<=pi)
00643 {
00644 b = dest->block(pj,pi,true);
00645 assert(b->cols() == s->cols());
00646 assert(b->rows() == s->rows());
00647 *b = *s;
00648 }else
00649 {
00650 b = dest->block(pi,pj,true);
00651 assert(b);
00652 assert(b->rows() == s->cols());
00653 assert(b->cols() == s->rows());
00654 *b = s->transpose();
00655 }
00656 }
00657
00658
00659 }
00660 return true;
00661 }
00662
00663
00664
00665 template <class MatrixType>
00666 int SparseBlockMatrix<MatrixType>::fillCCS(double* Cx, bool upperTriangle)
00667 const
00668 {
00669 double* CxStart = Cx;
00670 for (size_t i=0; i<_blockCols.size(); ++i)
00671 {
00672 int cstart=i ? _colBlockIndices[i-1] : 0;
00673 int csize=colsOfBlock(i);
00674 for (int c=0; c<csize; c++)
00675 {
00676 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00677 it = _blockCols[i].begin();
00678 it != _blockCols[i].end();
00679 ++it)
00680 {
00681 const typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* b =
00682 it->second;
00683 int rstart = it->first ? _rowBlockIndices[it->first-1] : 0;
00684
00685 int elemsToCopy = b->rows();
00686 if (upperTriangle && rstart == cstart) elemsToCopy = c + 1;
00687
00688 memcpy(Cx, b->data() + c*b->rows(), elemsToCopy * sizeof(double));
00689 Cx += elemsToCopy;
00690 }
00691 }
00692 }
00693 return Cx - CxStart;
00694 }
00695
00696
00697
00698 template <class MatrixType>
00699 int SparseBlockMatrix<MatrixType>::fillCCS
00700 (int* Cp, int* Ci, double* Cx, bool upperTriangle) const
00701 {
00702 int nz=0;
00703 for (size_t i=0; i<_blockCols.size(); ++i)
00704 {
00705 int cstart = i ? _colBlockIndices[i-1] : 0;
00706 int csize = colsOfBlock(i);
00707 for (int c = 0; c<csize; c++)
00708 {
00709 *Cp = nz;
00710 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00711 it = _blockCols[i].begin();
00712 it != _blockCols[i].end();
00713 ++it)
00714 {
00715 const typename SparseBlockMatrix<MatrixType>::SparseMatrixBlock* b =
00716 it->second;
00717 int rstart=it->first ? _rowBlockIndices[it->first-1] : 0;
00718
00719 int elemsToCopy = b->rows();
00720 if (upperTriangle && rstart == cstart) elemsToCopy = c + 1;
00721
00722 for (int r=0; r<elemsToCopy; ++r)
00723 {
00724 *Cx++ = (*b)(r,c);
00725 *Ci++ = rstart++;
00726 ++nz;
00727 }
00728 }
00729 ++Cp;
00730 }
00731 }
00732 *Cp = nz;
00733 return nz;
00734 }
00735
00736
00737
00738 template <class MatrixType>
00739 void SparseBlockMatrix<MatrixType>::fillBlockStructure(MatrixStructure& ms)
00740 const
00741 {
00742 int n = _colBlockIndices.size();
00743 int nzMax = (int)nonZeroBlocks();
00744
00745 ms.alloc(n, nzMax);
00746 ms.m = _rowBlockIndices.size();
00747
00748 int nz = 0;
00749 int* Cp = ms.Ap;
00750 int* Ci = ms.Aii;
00751 for (size_t i = 0; i<_blockCols.size(); ++i)
00752 {
00753 *Cp = nz;
00754 const int& c = i;
00755 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00756 it = _blockCols[i].begin();
00757 it != _blockCols[i].end();
00758 ++it)
00759 {
00760 const int& r = it->first;
00761 if (r <= c)
00762 {
00763 *Ci++ = r;
00764 ++nz;
00765 }
00766 }
00767 Cp++;
00768 }
00769 *Cp = nz;
00770 assert(nz <= nzMax);
00771 }
00772
00773
00774
00775 template <class MatrixType>
00776 bool SparseBlockMatrix<MatrixType>::writeOctave
00777 (const char* filename, bool upperTriangle) const
00778 {
00779 std::string name = filename;
00780 std::string::size_type lastDot = name.find_last_of('.');
00781 if(lastDot != std::string::npos) name = name.substr(0, lastDot);
00782
00783 std::vector<TripletEntry> entries;
00784 for (size_t i = 0; i<_blockCols.size(); ++i)
00785 {
00786 const int& c = i;
00787 for (typename SparseBlockMatrix<MatrixType>::IntBlockMap::const_iterator
00788 it = _blockCols[i].begin();
00789 it != _blockCols[i].end();
00790 ++it)
00791 {
00792 const int& r = it->first;
00793 const MatrixType& m = *(it->second);
00794 for (int cc = 0; cc < m.cols(); ++cc)
00795 for (int rr = 0; rr < m.rows(); ++rr)
00796 {
00797 int aux_r = rowBaseOfBlock(r) + rr;
00798 int aux_c = colBaseOfBlock(c) + cc;
00799 entries.push_back(TripletEntry(aux_r, aux_c, m(rr, cc)));
00800 if (upperTriangle && r != c)
00801 {
00802 entries.push_back(TripletEntry(aux_c, aux_r, m(rr, cc)));
00803 }
00804 }
00805 }
00806 }
00807
00808 int nz = entries.size();
00809 std::sort(entries.begin(), entries.end(), TripletColSort());
00810
00811 std::ofstream fout(filename);
00812 fout << "# name: " << name << std::endl;
00813 fout << "# type: sparse matrix" << std::endl;
00814 fout << "# nnz: " << nz << std::endl;
00815 fout << "# rows: " << rows() << std::endl;
00816 fout << "# columns: " << cols() << std::endl;
00817 fout << std::setprecision(9) << std::endl;
00818
00819 for (std::vector<TripletEntry>::const_iterator
00820 it = entries.begin();
00821 it != entries.end();
00822 ++it)
00823 {
00824 const TripletEntry& entry = *it;
00825 fout << entry.r+1 << " " << entry.c+1 << " " << entry.x << std::endl;
00826 }
00827 return fout.good();
00828 }
00829
00830 }