USGS

Isis 3.0 Object Programmers' Reference

Home

SparseBlockMatrix.cpp
1 #include "SparseBlockMatrix.h"
2 
3 #include <boost/numeric/ublas/matrix_sparse.hpp>
4 #include <boost/numeric/ublas/matrix_proxy.hpp>
5 #include <boost/numeric/ublas/io.hpp>
6 
7 #include <iostream>
8 #include <iomanip>
9 #include <QDebug>
10 #include <QMapIterator>
11 #include <QListIterator>
12 
13 #include "IString.h"
14 
15 using namespace boost::numeric::ublas;
16 
17 namespace Isis {
18 
22  SparseBlockColumnMatrix::~SparseBlockColumnMatrix() {
23  wipe();
24  }
25 
26 
32  void SparseBlockColumnMatrix::wipe() {
33  qDeleteAll(values());
34  clear();
35  }
36 
37 
41  SparseBlockColumnMatrix::SparseBlockColumnMatrix(const SparseBlockColumnMatrix& src) {
42  copy(src);
43  }
44 
45 
49  void SparseBlockColumnMatrix::copy(const SparseBlockColumnMatrix& src) {
50  // handi-wipe
51  wipe();
52 
53  // copy matrix blocks from src
54  QMapIterator<int, matrix<double>*> it(src);
55  while (it.hasNext()) {
56  it.next();
57 
58  // copy matrix block from src
59  matrix<double>* m = new matrix<double>(*(it.value()));
60 
61  // insert matrix into map
62  this->insert(it.key(),m);
63  }
64  }
65 
66 
71  SparseBlockColumnMatrix::operator=(const SparseBlockColumnMatrix& src) {
72  if ( this == &src )
73  return *this;
74 
75  copy(src);
76 
77  return *this;
78  }
79 
80 
91  bool SparseBlockColumnMatrix::InsertMatrixBlock(int nColumnBlock, int nRows,
92  int nCols) {
93 
94  // check if matrix already exists at the key "nColumnBlock"
95  if ( this->contains(nColumnBlock) )
96  return true;
97 
98  // allocate matrix block with nRows and nCols
99  matrix<double>* m = new matrix<double>(nRows,nCols);
100 
101  if ( !m )
102  return false;
103 
104  // zero matrix elements
105  m->clear();
106 
107  // insert matrix into map
108  this->insert(nColumnBlock,m);
109 
110  return true;
111  }
112 
113 
118  int SparseBlockColumnMatrix::numberOfElements() {
119  int nElements = 0;
120 
121  QMapIterator<int, matrix<double>*> it(*this);
122  while (it.hasNext()) {
123  it.next();
124 
125  if( !it.value() )
126  continue;
127 
128  nElements += it.value()->size1()*it.value()->size2();
129  }
130 
131  return nElements;
132  }
133 
134 
139  int SparseBlockColumnMatrix::numberOfColumns() {
140 
141  int nColumns = 0;
142 
143  QMapIterator<int, matrix<double>*> it(*this);
144  while (it.hasNext()) {
145  it.next();
146 
147  if( !it.value() )
148  continue;
149 
150  nColumns = it.value()->size2();
151  break;
152  }
153 
154  return nColumns;
155  }
156 
157 
162  int SparseBlockColumnMatrix::numberOfRows() {
163 
164  // iterate to last block (the diagonal one)
165  QMapIterator<int, matrix<double>*> it(*this);
166  while (it.hasNext()) {
167  it.next();
168 
169  if( !it.value() )
170  continue;
171  }
172 
173  int nRows = it.value()->size1();
174 
175  return nRows;
176  }
177 
178 
182  void SparseBlockColumnMatrix::print(std::ostream& outstream) {
183  if ( size() == 0 ) {
184  outstream << "Empty SparseBlockColumnMatrix..." << std::endl;
185  return;
186  }
187 
188  outstream << "Printing SparseBlockColumnMatrix..." << std::endl;
189  QMapIterator<int, matrix<double>*> it(*this);
190  while (it.hasNext()) {
191  it.next();
192 
193  if( it.value() )
194  outstream << it.key() << std::endl << *(it.value()) << std::endl
195  << std::endl;
196  else
197  outstream << "NULL block pointer at row[" << IString(it.key())
198  << "]!" << std::endl;
199  }
200  }
201 
202 
206  void SparseBlockColumnMatrix::zeroBlocks() {
207  QMapIterator<int, matrix<double>*> it(*this);
208  while ( it.hasNext() ) {
209  it.next();
210  it.value()->clear();
211  }
212  }
213 
214 
218  QDataStream &operator<<(QDataStream &stream, const SparseBlockColumnMatrix &sbcm) {
219  // write number of blocks in this column
220  int nBlocks = sbcm.size();
221  stream << nBlocks;
222 
223  QMapIterator<int, matrix<double>*> it(sbcm);
224  while ( it.hasNext() ) {
225  it.next();
226 
227  if( !it.value() )
228  continue;
229 
230  int nRows = it.value()->size1();
231  int nCols = it.value()->size2();
232 
233  // write block number (key); rows (size1); and columns (size2)
234  stream << it.key() << nRows << nCols;
235 
236  double* data = &it.value()->data()[0];
237 
238  // write raw matrix data
239  stream.writeRawData((const char*)data, nRows*nCols*sizeof(double));
240  }
241 
242  return stream;
243  }
244 
245 
249  QDataStream &operator>>(QDataStream &stream, SparseBlockColumnMatrix &sbcm) {
250  int nBlocks, nBlockNumber, nRows, nCols;
251  int i, r, c;
252 
253  stream >> nBlocks;
254 
255  for ( i = 0; i < nBlocks; i++) {
256  // read block number (key); rows (size1); and columns (size2)
257  stream >> nBlockNumber >> nRows >> nCols;
258 
259  double data[nRows*nCols];
260 
261  // read raw matrix data
262  stream.readRawData((char*)data, nRows*nCols*sizeof(double));
263 
264  // insert matrix at correct key
265  sbcm.InsertMatrixBlock(nBlockNumber, nRows, nCols);
266 
267  // get matrix
268  matrix<double>* matrix = sbcm[nBlockNumber];
269 
270  // fill with data
271  for (r = 0; r < nRows; r++ ) {
272  for (c = 0; c < nCols; c++ ) {
273  int nLocation = r*nRows + c;
274  (*matrix)(r,c) = data[nLocation];
275  }
276  }
277  }
278 
279  return stream;
280  }
281 
285  QDebug operator<<(QDebug dbg, const SparseBlockColumnMatrix &sbcm) {
286  dbg.space() << "New Block" << endl;
287 
288  QMapIterator<int, matrix<double>*> it(sbcm);
289  while ( it.hasNext() ) {
290  it.next();
291 
292  if( !it.value() )
293  continue;
294 
295  // get matrix
296  matrix<double>* matrix = it.value();
297 
298  // matrix rows, columns
299  int nRows = matrix->size1();
300  int nCols = matrix->size2();
301 
302  dbg.nospace() << qSetFieldWidth(4);
303  dbg.nospace() << qSetRealNumberPrecision(8);
304 
305  for (int r = 0; r < nRows; r++ ) {
306  for (int c = 0; c < nCols; c++ ) {
307  dbg.space() << (*matrix)(r,c);
308  }
309  dbg.space() << endl;
310  }
311  dbg.space() << endl;
312  }
313 
314  return dbg;
315  }
316 
317 
319  // SparseBlockRowMatrix methods
320 
324  SparseBlockRowMatrix::~SparseBlockRowMatrix() {
325  wipe();
326  }
327 
328 
334  void SparseBlockRowMatrix::wipe() {
335  qDeleteAll(values());
336  clear();
337  }
338 
339 
343  SparseBlockRowMatrix::SparseBlockRowMatrix(const SparseBlockRowMatrix& src) {
344  copy(src);
345  }
346 
347 
351  void SparseBlockRowMatrix::copy(const SparseBlockRowMatrix& src) {
352  // handi-wipe
353  wipe();
354 
355  // copy matrix blocks from src
356  QMapIterator<int, matrix<double>*> it(src);
357  while (it.hasNext()) {
358  it.next();
359 
360  // copy matrix block from src
361  matrix<double>* m = new matrix<double>(*(it.value()));
362 
363  // insert matrix into map
364  this->insert(it.key(),m);
365  }
366  }
367 
368 
373  SparseBlockRowMatrix::operator=(const SparseBlockRowMatrix& src) {
374  if ( this == &src )
375  return *this;
376 
377  copy(src);
378 
379  return *this;
380  }
381 
382 
393  bool SparseBlockRowMatrix::InsertMatrixBlock(int nRowBlock, int nRows,
394  int nCols) {
395  if ( this->contains(nRowBlock) )
396  return false;
397 
398  matrix<double>* m = new matrix<double>(nRows,nCols);
399 
400  if ( !m )
401  return false;
402 
403  m->clear();
404 
405  this->insert(nRowBlock,m);
406 
407  return true;
408  }
409 
410 
415  int SparseBlockRowMatrix::numberOfElements() {
416  int nElements = 0;
417 
418  QMapIterator<int, matrix<double>*> it(*this);
419  while ( it.hasNext() ) {
420  it.next();
421 
422  if( !it.value() )
423  continue;
424 
425  nElements += it.value()->size1()*it.value()->size2();
426  }
427 
428  return nElements;
429  }
430 
431 
435  void SparseBlockRowMatrix::print(std::ostream& outstream) {
436  if ( size() == 0 ) {
437  outstream << "Empty SparseBlockRowMatrix..." << std::endl;
438  return;
439  }
440 
441  outstream << "Printing SparseBlockRowMatrix..." << std::endl;
442  QMapIterator<int, matrix<double>*> it(*this);
443  while ( it.hasNext() ) {
444  it.next();
445 
446  if( it.value() )
447  outstream << it.key() << std::endl << *(it.value()) << std::endl
448  << std::endl;
449  else
450  outstream << "NULL block pointer at column[" << IString(it.key())
451  << "]!" << std::endl;
452  }
453  }
454 
455 
459  void SparseBlockRowMatrix::zeroBlocks() {
460  QMapIterator<int, matrix<double>*> it(*this);
461  while ( it.hasNext() ) {
462  it.next();
463  it.value()->clear();
464  }
465  }
466 
467 
472  void SparseBlockRowMatrix::copyToBoost(compressed_matrix<double>& B) {
473  B.clear();
474 
475  int ncols, nstart, nend, nrowBlock;
476  range rRow = range(0,3);
477  range rCol;
478 
479  QMapIterator<int, matrix<double>*> it(*this);
480  while ( it.hasNext() ) {
481  it.next();
482 
483  nrowBlock = it.key();
484  matrix<double>* m = it.value();
485 
486  ncols = m->size2();
487 
488  nstart = nrowBlock*ncols;
489  nend = nstart + ncols;
490 
491  rCol = range(nstart,nend);
492 
493  matrix_range<compressed_matrix<double> > m1 (B, rRow, rCol);
494 
495  m1 = *m;
496  }
497  }
498 
502  QDataStream &operator<<(QDataStream &stream, const SparseBlockRowMatrix &sbrm) {
503  // write number of blocks in this column
504  int nBlocks = sbrm.size();
505  stream << nBlocks;
506 
507  QMapIterator<int, matrix<double>*> it(sbrm);
508  while ( it.hasNext() ) {
509  it.next();
510 
511  if( !it.value() )
512  continue;
513 
514  int nRows = it.value()->size1();
515  int nCols = it.value()->size2();
516 
517  // write block number (key); rows (size1); and columns (size2)
518  stream << it.key() << nRows << nCols;
519 
520  double* data = &it.value()->data()[0];
521 
522  // write raw matrix data
523  stream.writeRawData((const char*)data, nRows*nCols*sizeof(double));
524  }
525 
526  return stream;
527  }
528 
529 
533  QDataStream &operator>>(QDataStream &stream, SparseBlockRowMatrix &sbrm) {
534  int nBlocks, nBlockNumber, nRows, nCols;
535  int i, r, c;
536 
537  stream >> nBlocks;
538 
539  for ( i = 0; i < nBlocks; i++) {
540  // read block number (key); rows (size1); and columns (size2)
541  stream >> nBlockNumber >> nRows >> nCols;
542 
543  double data[nRows*nCols];
544 
545  // read raw matrix data
546  stream.readRawData((char*)data, nRows*nCols*sizeof(double));
547 
548  // insert matrix at correct key
549  sbrm.InsertMatrixBlock(nBlockNumber, nRows, nCols);
550 
551  // get matrix
552  matrix<double>* matrix = sbrm[nBlockNumber];
553 
554  // fill with data
555  for (r = 0; r < nRows; r++ ) {
556  for (c = 0; c < nCols; c++ ) {
557  int nLocation = r*nRows + c;
558  (*matrix)(r,c) = data[nLocation];
559  }
560  }
561  }
562 
563  return stream;
564  }
565 
569  QDebug operator<<(QDebug dbg, const SparseBlockRowMatrix &sbrm) {
570  dbg.space() << "New Block" << endl;
571 
572  QMapIterator<int, matrix<double>*> it(sbrm);
573  while ( it.hasNext() ) {
574  it.next();
575 
576  if( !it.value() )
577  continue;
578 
579  // get matrix
580  matrix<double>* matrix = it.value();
581 
582  // matrix rows, columns
583  int nRows = matrix->size1();
584  int nCols = matrix->size2();
585 
586  dbg.nospace() << qSetFieldWidth(4);
587  dbg.nospace() << qSetRealNumberPrecision(8);
588 
589  for (int r = 0; r < nRows; r++ ) {
590  for (int c = 0; c < nCols; c++ ) {
591  dbg.space() << (*matrix)(r,c);
592  }
593  dbg.space() << endl;
594  }
595  dbg.space() << endl;
596  }
597 
598  return dbg;
599  }
600 
601 
603  // SparseBlockMatrix methods
604 
608  SparseBlockMatrix::~SparseBlockMatrix() {
609  wipe();
610  }
611 
612 
618  void SparseBlockMatrix::wipe() {
619  qDeleteAll(*this);
620  clear();
621  }
622 
623 
627  SparseBlockMatrix::SparseBlockMatrix(const SparseBlockMatrix& src) {
628  copy(src);
629  }
630 
634  void SparseBlockMatrix::copy(const SparseBlockMatrix& src) {
635  // handi-wipe
636  wipe();
637 
638  // copy all SparseBlockColumnMatrix objects from src
639  for( int i = 0; i < src.size(); i++ ) {
640  append( new SparseBlockColumnMatrix(*(src.at(i))));
641  }
642  }
643 
644 
648  SparseBlockMatrix& SparseBlockMatrix::operator=(const SparseBlockMatrix& src) {
649  if ( this == &src )
650  return *this;
651 
652  copy(src);
653 
654  return *this;
655  }
656 
657 
663  bool SparseBlockMatrix::setNumberOfColumns( int n ) {
664 
665  for( int i = 0; i < n; i++ )
666  append( new SparseBlockColumnMatrix() );
667 
668  return true;
669  }
670 
671 
683  bool SparseBlockMatrix::InsertMatrixBlock(int nColumnBlock, int nRowBlock,
684  int nRows, int nCols) {
685  return (*this)[nColumnBlock]->InsertMatrixBlock(nRowBlock, nRows, nCols);
686  }
687 
688 
692  int SparseBlockMatrix::numberOfBlocks() {
693  int nBlocks = 0;
694 
695  for( int i = 0; i < size(); i++ ) {
696  if ( !(*this)[i] )
697  continue;
698 
699  nBlocks += (*this)[i]->size();
700  }
701 
702  return nBlocks;
703  }
704 
705 
710  int SparseBlockMatrix::numberOfDiagonalBlocks() {
711  int ndiagBlocks = 0;
712 
713  for( int i = 0; i < size(); i++ ) {
714  SparseBlockColumnMatrix* column = at(i);
715 
716  if ( !column )
717  continue;
718 
719  QMapIterator<int, matrix<double>*> it(*column);
720  while (it.hasNext()) {
721  it.next();
722 
723  if( it.key() == i ) {
724  ndiagBlocks++;
725  break;
726  }
727  }
728  }
729 
730  return ndiagBlocks;
731  }
732 
733 
737  int SparseBlockMatrix::numberOfOffDiagonalBlocks() {
738  return (numberOfBlocks() - numberOfDiagonalBlocks());
739  }
740 
741 
745  int SparseBlockMatrix::numberOfElements() {
746  int nElements = 0;
747 
748  for( int i = 0; i < size(); i++ ) {
749  if ( !(*this)[i] )
750  continue;
751 
752  nElements += (*this)[i]->numberOfElements();
753  }
754 
755  return nElements;
756  }
757 
758 
765  matrix<double>* SparseBlockMatrix::getBlock(int column, int row) {
766  return (*(*this)[column])[row];
767  }
768 
769 
773  void SparseBlockMatrix::zeroBlocks() {
774  for ( int i = 0; i < size(); i++ )
775  (*this)[i]->zeroBlocks();
776  }
777 
778 
782  void SparseBlockMatrix::print(std::ostream& outstream) {
783  if ( size() == 0 ) {
784  outstream << "Empty SparseBlockMatrix..." << std::endl;
785  return;
786  }
787 
788  outstream << "Printing SparseBlockMatrix..." << std::endl;
789  for( int i = 0; i < size(); i++ ) {
790  SparseBlockColumnMatrix* column = at(i);
791 
792  if ( column )
793  column->print(outstream);
794  else
795  outstream << "NULL column pointer at column[" << IString(i)
796  << "]!" << std::endl;
797  }
798  }
799 
800 
804  QDataStream &operator<<(QDataStream &stream, const SparseBlockMatrix &sparseBlockMatrix) {
805  int nBlockColumns = sparseBlockMatrix.size();
806 
807  stream << nBlockColumns;
808 
809  for (int i =0; i < nBlockColumns; i++)
810  stream << *sparseBlockMatrix.at(i);
811 
812  return stream;
813  }
814 
815 
819  QDataStream &operator>>(QDataStream &stream, SparseBlockMatrix &sparseBlockMatrix) {
820  int nBlockColumns;
821 
822  // read and set number of block columns
823  stream >> nBlockColumns;
824  sparseBlockMatrix.setNumberOfColumns(nBlockColumns);
825 
826  for (int i =0; i < nBlockColumns; i++)
827  stream >> *sparseBlockMatrix.at(i);
828 
829  return stream;
830  }
831 
835  QDebug operator<<(QDebug dbg, const SparseBlockMatrix &m) {
836  int nBlockColumns = m.size();
837 
838  for (int i =0; i < nBlockColumns; i++)
839  dbg << *m.at(i);
840 
841  return dbg;
842  }
843 }