latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 2002, 2003, 2004, 2005, 2006 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * This file is part of the LTI-Computer Vision Library (LTI-Lib) 00006 * 00007 * The LTI-Lib is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public License (LGPL) 00009 * as published by the Free Software Foundation; either version 2.1 of 00010 * the License, or (at your option) any later version. 00011 * 00012 * The LTI-Lib is distributed in the hope that it will be 00013 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00014 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with the LTI-Lib; see the file LICENSE. If 00019 * not, write to the Free Software Foundation, Inc., 59 Temple Place - 00020 * Suite 330, Boston, MA 02111-1307, USA. 00021 */ 00022 00023 00024 /*---------------------------------------------------------------- 00025 * project ....: LTI Digital Image/Signal Processing Library 00026 * file .......: ltiSparseMatrix.h 00027 * authors ....: Bastian Ibach 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 26.04.02 00030 * revisions ..: $Id: ltiSparseMatrix.h,v 1.5 2006/02/08 12:45:53 ltilib Exp $ 00031 */ 00032 00033 00034 #ifndef _LTI_SPARSEMATRIX_H_ 00035 #define _LTI_SPARSEMATRIX_H_ 00036 00037 #include "ltiMathObject.h" 00038 #include "ltiVector.h" 00039 #include "ltiMatrix.h" 00040 #include <vector> 00041 #include <map> 00042 #include <iostream> 00043 00044 namespace lti { 00045 /** 00046 * SparseMatrix container class. 00047 * 00048 * The lti::sparseMatrix class allows the representation 00049 * of \e n x \e m matrices as sparse matrices (SM). 00050 * 00051 * The SM class is a container class implemented as template. 00052 * 00053 * All types defined in ltiTypes.h except \c bool can be contained. 00054 * 00055 * A matrix is normaly defined as sparse if it contains a lot of zeros, in 00056 * this class you can use an arbitrary value denoted with \e sparseValue. 00057 * 00058 * Only the non-sparse values of the matrix are saved in the container 00059 * using the Compressed Row Storage format. 00060 * 00061 * Due to the characteristics of the storage, the method at() is here 00062 * a read-only one. To write values into the matrix use the setAt() or 00063 * forceAt() methods. 00064 * 00065 * The Compressed Row Storage (CRS) format puts the subsequent nonsparse 00066 * values of the matrix rows in contiguous memory locations. 00067 * 00068 * The CRS format uses three vectors to store the non sparse values: 00069 * - values, type of T 00070 * - colIndex, type of int 00071 * - rowPtr, type of int 00072 * 00073 * In the \b values vector are saved the values of the non sparse elements 00074 * of the matrix, as they are traversed in a row-wise fashion. 00075 * 00076 * The \b colIndex vector stores the column indices of the elements 00077 * in the values vector. 00078 * 00079 * The \b rowPtr vector stores the position in the values vector that start a 00080 * new row. The vector size is equal number of rows plus one. The last value 00081 * in the rowPtr vector is needed to calculate the number of elements in the 00082 * last row of the matrix. 00083 * 00084 * Example: 00085 * 00086 * \code 00087 * matrix A = ( 0 2 5 0 00088 * 1 0 0 0 00089 * 0 4 0 6 ) 00090 * \endcode 00091 * 00092 * 00093 * The CRS format for the matrix A is specified by the vectors given below: 00094 * 00095 * \code 00096 * values = ( 2 5 1 4 6 ) 00097 * colIndex = ( 1 2 0 1 3 ) 00098 * 00099 * rowPtr = ( 0 2 3 5 ) 00100 * \endcode 00101 * 00102 * The \b iterators of the sparse matrices visit only the non sparse values, 00103 * as this is usually the required task. 00104 * 00105 * You can use the getPosition() methods to gain the index of the element 00106 * pointed by an iterator. If for each non-sparse element you need to 00107 * compute its index, it is more efficient to avoid iterators and using the 00108 * data structures of the CRS directly: 00109 * 00110 * \code 00111 * 00112 * // assume you are in a template class/method of type T, or that type 00113 * // T is somehow defined (for example typedef float T) 00114 * 00115 * lti::point p; // the coordinates 00116 * lti::sparseMatrix<T> smat; 00117 * 00118 * // ... fill the sparse matrix with data here 00119 * 00120 * const lti::ivector& rows = smat.getRowPtr(); 00121 * const std::vector<int>& cols = smat.getColIndex(); 00122 * const std::vector<T>& vals = smat.getValues(); 00123 * 00124 * int i,f,l; 00125 * T val; 00126 * 00127 * // for each row 00128 * for (p.y=0;p.y<rows.lastIdx();++p.y) { 00129 * f=rows.at(p.y); // first row element 00130 * l=rows.at(p.y+1); // last row element 00131 * for (i=f;i<l;++i) { // for each element in row 00132 * p.x=cols[i]; 00133 * val=vals[i]; 00134 * // the matrix element at \c p contains value \c val 00135 * // here you can do whatever you need to... 00136 * } 00137 * } 00138 * 00139 * \endcode 00140 * 00141 * @ingroup gAggregate 00142 * @ingroup gLinearAlgebra 00143 */ 00144 template<class T> 00145 class sparseMatrix : public mathObject { 00146 public: 00147 00148 /** 00149 * type of the contained data 00150 */ 00151 typedef T value_type; 00152 00153 /** 00154 * iterator 00155 * the iterator points to one element of the values vector 00156 * you only have access to these values, not to the sparseValues 00157 */ 00158 typedef typename std::vector<T>::iterator iterator; 00159 00160 00161 /** 00162 * const_iterator 00163 * the const_iterator points to one element of the values vector 00164 * you only have access to these values, not to the sparseValues 00165 */ 00166 typedef typename std::vector<T>::const_iterator const_iterator; 00167 00168 00169 /** 00170 * default constructor creates an empty sparseMatrix 00171 */ 00172 sparseMatrix(); 00173 00174 /** 00175 * construct a sparse matrix of the given size and fill it 00176 * with the given value (i.e. use the given value as sparse value). 00177 */ 00178 sparseMatrix(const int theRows,const int theCols,const T& sparseVal=T()); 00179 00180 /** 00181 * construct a sparse matrix of the given size and fill it 00182 * with the given value (i.e. use the given value as sparse value). 00183 */ 00184 sparseMatrix(const point& size,const T& sparseVal=T()); 00185 00186 /** 00187 * copy constructor. 00188 * 00189 * create this sparseMatrix as a connected copy of another sparseMatrix 00190 * for this const version, the data will be always copied! 00191 * 00192 * @param other the sparseMatrix to be copied. 00193 */ 00194 sparseMatrix(const sparseMatrix<T>& other); 00195 00196 /** 00197 * destructor 00198 */ 00199 virtual ~sparseMatrix(); 00200 00201 /** 00202 * resize the given sparse matrix and fill it with the given 00203 * value. 00204 * It is not possible to keep the old data when resizing 00205 * the matrix. 00206 */ 00207 bool resize(const int rows,const int cols,const T& sparseVal); 00208 00209 /** 00210 * resize the given sparse matrix and fill it with the given 00211 * value. 00212 * It is not possible to keep the old data when resizing 00213 * the matrix. 00214 */ 00215 bool resize(const point& size,const T& sparseVal); 00216 00217 /** 00218 * convert matrix to SparseMatrix 00219 * 00220 * @param srcMatrix the matrix converted to sparseMatrix 00221 * @param sValue the value of srcMatrix used as sparseValue 00222 * in the sparseMatrix 00223 * @return a reference to this object. 00224 */ 00225 sparseMatrix<T>& castFrom(const matrix<T>& srcMatrix, const T& sValue); 00226 00227 /** 00228 * convert matrix to SparseMatrix 00229 * 00230 * The value of the srcMatrix used as sparseValue is chosen by 00231 * statistical evaluation (the most used one), which of course 00232 * cost some time. 00233 * 00234 * @param srcMatrix the matrix to be converted into a sparseMatrix 00235 * @return a reference to this object. 00236 */ 00237 sparseMatrix<T>& castFrom(const matrix<T>& srcMatrix); 00238 00239 /** 00240 * convert the other sparse matrix of type U to this sparse matrix 00241 * of type T 00242 */ 00243 template<class U> 00244 sparseMatrix<T>& castFrom(const sparseMatrix<U>& other) { 00245 if(&other == this) { // Caution could be the same Matrix 00246 return(*this); 00247 } 00248 00249 theSize = other.size(); 00250 typename std::vector<U>::const_iterator oit; 00251 typename std::vector<T>::iterator it; 00252 values.resize(other.getValues().size()); 00253 for (oit=other.values.begin(),it=values.begin(); 00254 it!=values.end(); 00255 ++it,++oit) { 00256 *it = static_cast<T>(*oit); 00257 } 00258 00259 colIndex = other.getColIndex(); 00260 rowPtr = other.getRowPtr(); 00261 numNonSparseValues = other.getNumNonSparseValues(); 00262 sparseValue = static_cast<T>(other.sparseValue); 00263 return (*this); 00264 } 00265 00266 /** 00267 * convert SparseMatrix to matrix 00268 * @param destMatrix the lti::matrix where this sparseMatrix will be 00269 * copied into. 00270 */ 00271 bool castTo(matrix<T>& destMatrix); 00272 00273 /** 00274 * copy the contents of other to this object 00275 * @param other the matrix to be copied 00276 */ 00277 sparseMatrix<T>& copy(const sparseMatrix<T>& other); 00278 00279 /** 00280 * iterator begin 00281 */ 00282 iterator begin(); 00283 00284 /** 00285 * iterator end 00286 */ 00287 iterator end(); 00288 00289 /** 00290 * const_iterator begin 00291 */ 00292 const_iterator begin() const; 00293 00294 /** 00295 * const_iterator end 00296 */ 00297 const_iterator end() const; 00298 00299 /** 00300 * access element at the given row and column 00301 * @param row the row of the element 00302 * @param col the column of the element 00303 * @return a reference to the matrix element 00304 */ 00305 inline const T& at(const int row, const int col) const { 00306 return getAt(row,col); 00307 } 00308 00309 /** 00310 * access element at the given row and column 00311 * @param row the row of the element 00312 * @param col the column of the element 00313 * @return the value of the matrix element 00314 */ 00315 const T& getAt(const int row, const int col) const; 00316 00317 /** 00318 * get a read-write reference to the given element, and in case 00319 * the element was a "sparse" one, insert it first (with the sparse 00320 * value. 00321 * 00322 * You can for example use this method, when you want to increment the 00323 * elements in a sparse matrix: 00324 * \code 00325 * sparseMatrix<int> sparseMat(1000,1000,0); 00326 * sparseMat.setAt(row,col,getAt(row,col)+1); 00327 * \endcode 00328 * is very inefficient, because the element at (row,col) must be 00329 * search twice. 00330 * On the other hand 00331 * \code 00332 * sparseMat.forceAt(row,col)++; 00333 * \endcode 00334 * makes just one access to the point and returns a reference. 00335 * 00336 * Note that if you just call forceAt without explicitelly changing 00337 * the value thereafter, you will have sparseElement as normal elements 00338 * in your matrix. So, please use with care. The normal way to 00339 * reset a value with the sparseValue is using setAt(row,col,sparseValue). 00340 */ 00341 T& forceAt(const int row, const int col); 00342 00343 /** 00344 * get a read-write reference to the given element, and in case 00345 * the element was a "sparse" one, insert it first. 00346 */ 00347 inline T& forceAt(const point& p) { 00348 return forceAt(p.y,p.x); 00349 } 00350 00351 /** 00352 * modify element at the given row and column 00353 * @param row the row of the element 00354 * @param col the column of the element 00355 * @param newValue new value for a matrix element 00356 * @return true if existing value is changed or 00357 * false if sparseValue is replaced by element 00358 */ 00359 bool setAt(const int row, const int col, const T newValue); 00360 00361 /** 00362 * modify element at point 00363 * @param position index of the element in sparseMatrix to be set 00364 * @param newValue new value for a matrix element 00365 * @return true if existing value is changed or false if 00366 * sparseValue is replaced by element 00367 */ 00368 inline bool setAt(const point& position, const T newValue) { 00369 return setAt(position.y,position.x,newValue); 00370 } 00371 00372 /** 00373 * insert element at the given row and column 00374 * @param iniValue the value to fill the (sub-)matrix with 00375 * @param fromRow the row to begin fill 00376 * @param fromCol the column to begin fill 00377 * @param toRow the last row to fill 00378 * @param toCol the last col to fill 00379 */ 00380 void fill(const T& iniValue, 00381 const int& fromRow=0, 00382 const int& fromCol=0, 00383 const int& toRow=MaxInt32, 00384 const int& toCol=MaxInt32); 00385 00386 /** 00387 * clear sparseMatrix to get a empty sparseMatrix 00388 * sparseValue is set to zero 00389 */ 00390 void clear(); 00391 00392 /** 00393 * returns true if there are only "sparse values" on 00394 * the matrix. 00395 */ 00396 bool empty() const; 00397 00398 /** 00399 * get the position in the matrix of the iterator 00400 * @param iter iterator that points to a non-sparse element 00401 * @return point with index of the pointed element 00402 */ 00403 point getPosition(const iterator& iter); 00404 00405 /** 00406 * get the position in the matrix of the const_iterator 00407 * @param iter const_iterator that points to a non-sparse element 00408 * @return point with index of the pointed element 00409 */ 00410 point getPosition(const const_iterator& iter); 00411 00412 /** 00413 * get a copy of the row of the matrix 00414 * @param row the row to be accessed 00415 * @return a vector with the contents of the row of the matrix 00416 */ 00417 lti::vector<T> getRowCopy(const int& row) const; 00418 00419 /** 00420 * get a copy of the column of the matrix 00421 * @param col the column to be accessed 00422 * @return a vector with the contents of the column of the matrix 00423 */ 00424 lti::vector<T> getColumnCopy(const int& col) const; 00425 00426 /** 00427 * @return the name of this class: "sparseMatrix" 00428 */ 00429 virtual const char* getTypeName() const; 00430 00431 /** 00432 * create a clone of this matrix 00433 * @return a pointer to a copy of this matrix 00434 */ 00435 virtual mathObject* clone() const; 00436 00437 /** 00438 * assignment operator (alias for copy(other)) 00439 * 00440 * @param other the matrix to be copied 00441 * @returns a reference to the actual matrix 00442 */ 00443 sparseMatrix<T>& operator=(const sparseMatrix<T>& other); 00444 00445 /** 00446 * compare this sparseMatrix with other 00447 * 00448 * @param other the sparseMatrix to be compared with 00449 * @return true if both sparseMatrices have the same SparseValue 00450 * the same values-, colIndex- and rowPtr-vector 00451 */ 00452 bool operator==(const sparseMatrix<T> other) const; 00453 00454 /** 00455 * returns size of the sparseMatrix 00456 */ 00457 const point& size() const; 00458 00459 /** 00460 * returns the number of non-sparse valued elements in the sparseMatrix 00461 */ 00462 int getNumNonSparseValues() const; 00463 00464 /** 00465 * return the used sparse value 00466 */ 00467 T getSparseValue() const; 00468 00469 /** 00470 * return the number of columns of the matrix 00471 */ 00472 inline const int& columns() const { 00473 return numCols; 00474 } 00475 00476 /** 00477 * return the number of columns of the matrix 00478 */ 00479 inline const int& rows() const { 00480 return numRows; 00481 } 00482 00483 /** 00484 * @name Arithmetical Operations 00485 */ 00486 //@{ 00487 00488 /** 00489 * alias for add(const T value) 00490 * 00491 * @param value the value added to each element of the matrix 00492 * @returns a reference to the actual matrix 00493 */ 00494 sparseMatrix<T>& operator+=(const T value); 00495 00496 /** 00497 * add a constant value to this matrix and leave result in new matrix 00498 * 00499 * @param value the value added to each element of the matrix 00500 * @returns a new matrix with the result 00501 */ 00502 sparseMatrix<T> operator+(const T value) const; 00503 00504 /** 00505 * alias for multiply(const T value) 00506 * 00507 * @param value the constant value 00508 * @return a reference to the actual matrix 00509 */ 00510 sparseMatrix<T>& operator*=(const T value); 00511 00512 /** 00513 * add a constant value to all elements of the matrix 00514 * and leave the result here 00515 * @param value the constant value 00516 * @return return a reference to the actual matrix 00517 */ 00518 sparseMatrix<T>& add(const T value); 00519 00520 /** 00521 * devide the elements of the matrix by a constant value 00522 * and leave the result here 00523 * @param value the constant value (divisor) 00524 * @return return a reference to the actual matrix 00525 */ 00526 sparseMatrix<T>& divide(const T value); 00527 00528 /** 00529 * multiply the elements of the matrix by a constant value 00530 * and leave the result there 00531 * @param value the constant value 00532 * @return a reference to the actual matrix 00533 */ 00534 sparseMatrix<T>& multiply(const T value); 00535 00536 /** 00537 * multiply sparseMatrix with vector, write result 00538 * to a new vector 00539 * 00540 * @param srcVec vector to be multiplied with, 00541 * Its dimension must be equal to the number of columns of the matrix. 00542 * @param destVec vector to write result to 00543 * Its dimension will be equal to the number of rows of the matrix. 00544 */ 00545 void multiply(const vector<T>& srcVec, vector<T>& destVec) const; 00546 00547 /** 00548 * transpose sparseMatrix 00549 * 00550 * @return return a reference to the sparseMatrix 00551 */ 00552 sparseMatrix<T> transpose(); 00553 00554 /** 00555 * get maximum value of the matrix 00556 * @return return a copy of this value 00557 */ 00558 T maximum() const; 00559 00560 /** 00561 * get index of maximum value of the matrix 00562 * @return return a copy of the index as a point 00563 */ 00564 point getIndexOfMaximum() const; 00565 00566 /** 00567 * get minimum value of the matrix 00568 * @return return a copy of this value 00569 */ 00570 T minimum() const; 00571 00572 /** 00573 * get index of minimum value of the matrix 00574 * @return return a copy of the index as a point 00575 */ 00576 point getIndexOfMinimum() const; 00577 //@} 00578 00579 /** 00580 * @name Input and Output 00581 */ 00582 //@{ 00583 00584 /** 00585 * write the object in the given ioHandler 00586 */ 00587 virtual bool write(ioHandler& handler,const bool complete = true) const; 00588 00589 /** 00590 * read the object from the given ioHandler 00591 */ 00592 virtual bool read(ioHandler& handler,const bool complete = true); 00593 00594 //@} 00595 00596 /** 00597 * Following methods allow the access to the internal data structures, 00598 * which can be used to access very efficiently the non-sparse elements 00599 * in the rows of the matrix. 00600 */ 00601 //@{ 00602 /** 00603 * returns values vector 00604 */ 00605 const std::vector<T>& getValues() const; 00606 00607 /** 00608 * returns colIndex vector 00609 * vector of int 00610 */ 00611 const std::vector<int>& getColIndex() const; 00612 00613 /** 00614 * returns rowPtr vector 00615 * vector of int 00616 */ 00617 const lti::vector<int>& getRowPtr() const; 00618 //@} 00619 00620 private: 00621 00622 /** 00623 * theSize.x is equal numColumns and theSize.y is equal numRows 00624 */ 00625 point theSize; 00626 00627 /** 00628 * number of rows of the sparseMatrix 00629 */ 00630 int& numRows; 00631 00632 /** 00633 * number of columns of the sparseMatrix 00634 */ 00635 int& numCols; 00636 00637 /** 00638 * number of non zero values 00639 */ 00640 int numNonSparseValues; 00641 00642 /** 00643 * value which is sparse, normaly this is zero 00644 */ 00645 T sparseValue; 00646 00647 /** 00648 * vector of type T, containing the non-sparse values of the sparseMatrix 00649 * Format: Compressed Row Storage 00650 */ 00651 std::vector<T> values; 00652 00653 /** 00654 * vector of int, containing the column indices of the non Zero values 00655 * must have the same size as the vector with the values 00656 */ 00657 std::vector<int> colIndex; 00658 00659 /** 00660 * vector of int, containing the position in the values vector, where 00661 * a new row begins 00662 */ 00663 lti::vector<int> rowPtr; 00664 00665 /* 00666 * !!! for internal use only !! 00667 * 00668 * setSparseValue, insert sparseValue at given row and column 00669 * 00670 * 00671 bool setSparseValue(const int& row, const int&col, 00672 const T& value); 00673 */ 00674 00675 /** 00676 * !!! for internal use only !! 00677 * 00678 * setSparseValue, insert sparseValue at given row and column 00679 * 00680 */ 00681 bool setSparseValue(const int& row, const int& col); 00682 00683 /** 00684 * !!! for internal use only !! 00685 * 00686 * fillSparseValue, fill region of sparseMatrix with sparseValue 00687 * 00688 */ 00689 bool fillSparseValue(const int& fromRow, const int& fromCol, 00690 const int& toRow, const int& toCol); 00691 00692 }; 00693 00694 } 00695 00696 namespace std { 00697 00698 /** 00699 * outputs the elements of the vector on a stream 00700 */ 00701 template <class T> 00702 ostream& operator<<(ostream& outStr, const lti::sparseMatrix<T>& sMatrix); 00703 } 00704 00705 00706 #endif