Main MRPT website > C++ reference
MRPT logo
CSparseMatrixTemplate.h
Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                       http://www.mrpt.org/                                |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
00026    |                                                                           |
00027    +---------------------------------------------------------------------------+ */
00028 #ifndef CSparseMatrixTemplate_H
00029 #define CSparseMatrixTemplate_H
00030 
00031 #include <mrpt/utils/utils_defs.h>
00032 
00033 namespace mrpt  {
00034 namespace math  {
00035     using namespace std;
00036 
00037     /** A sparse matrix container (with cells of any type), with iterators.
00038       *  This class stores only those elements created by assigning them a value, for example: "M(2,3)=8;".
00039       *
00040       *  This class doesn't implement math operations since it's a generic sparse container, but it can be
00041       *   used to initialize the contents of a CSparse library-based matrix of type mrpt::math::CSparseMatrix.
00042       *
00043       *  Note that reading non-existing cell elements will return the default value (0 for numbers)
00044       *   and that cell will remain non-created in the matrix.
00045       *
00046       *  There is an additional method "exists(i,j)" to check whether a given element exists in the matrix.
00047       *
00048       *  \sa mrpt::math::CSparseMatrix, CSparseSymmetricalMatrix
00049       *  \note Methods marked as "Doesn't check bounds" mean that if an access to an element out of the matrix size is tried, an empty element will be assumed, but this will not raise any invalid memory access.
00050       * \ingroup mrpt_base_grp
00051       */
00052         template<class T>
00053         class CSparseMatrixTemplate     {
00054                 //Public typedefs
00055         public:
00056                 /**
00057                   * Internal map type, used to store the actual matrix.
00058                   */
00059                 typedef typename std::map<std::pair<size_t,size_t>,T> SparseMatrixMap;
00060                 /**
00061                   * Const iterator to move through the matrix.
00062                   * \sa CSparseMatrixTemplate::const_reverse_iterator
00063                   */
00064                 typedef typename SparseMatrixMap::const_iterator const_iterator;
00065                 /**
00066                   * Const reverse iterator to move through the matrix.
00067                   * \sa CSparseMatrixTemplate::const_iterator
00068                   */
00069                 typedef typename SparseMatrixMap::const_reverse_iterator const_reverse_iterator;
00070         protected:
00071                 /**
00072                   * Size of the matrix.
00073                   */
00074                 size_t mRows,mColumns;
00075                 /**
00076                   * Actual matrix.
00077                   */
00078                 SparseMatrixMap objectList;
00079         public:
00080                 /**
00081                   * Basic constructor with no data. Size is set to (0,0).
00082                   */
00083                 CSparseMatrixTemplate():mRows(0),mColumns(0)    {}
00084                 /**
00085                   * Constructor with default size.
00086                   */
00087                 CSparseMatrixTemplate(size_t nR,size_t nC):mRows(nR),mColumns(nC)       {}
00088                 /**
00089                   * Element access operator. Doesn't check bounds.
00090                   */
00091                 inline T operator()(size_t r,size_t c) const    {
00092                         const_iterator it=objectList.find(make_pair(r,c));
00093                         if (it==objectList.end()) return T();
00094                         else return it->second;
00095                 }
00096 
00097                 /** Element access operator. Checks bounds.
00098                   */
00099                 inline bool exists(size_t r,size_t c) const     {
00100 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
00101                         if (r>=mRows||c>=mColumns) throw std::logic_error("Out of range");
00102 #endif
00103                         return (objectList.find(make_pair(r,c)) != objectList.end());
00104                 }
00105 
00106                 /**
00107                   * Reference access operator. Checks for bounds.
00108                   */
00109                 inline T& operator()(size_t r,size_t c) {
00110 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
00111                         if (r>=mRows||c>=mColumns) throw std::logic_error("Out of range");
00112 #endif
00113                         return objectList[make_pair(r,c)];
00114                 }
00115                 /**
00116                   * Returns the amount of rows in this matrix.
00117                   * \sa getColCount,getRow
00118                   */
00119                 inline size_t getRowCount() const       {
00120                         return mRows;
00121                 }
00122                 /**
00123                   * Returns the amount of columns in this matrix.
00124                   * \sa getRowCount
00125                   */
00126                 inline size_t getColCount() const       {
00127                         return mColumns;
00128                 }
00129                 /**
00130                   * Extracts a full row from the matrix.
00131                   * \sa getRowCount,getColumn,setRow
00132                   * \throw std::logic_error on out of range.
00133                   */
00134                 void getRow(size_t nRow,std::vector<T> &vec) const      {
00135 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
00136                         if (nRow>=mRows) throw std::logic_error("Out of range");
00137 #endif
00138                         vec.resize(mColumns);
00139                         size_t nextIndex=0;
00140                         for (typename SparseMatrixMap::const_iterator it=objectList.begin();it!=objectList.end();++it)  {
00141                                 const pair<size_t,size_t> &index=it->first;
00142                                 if (index.first<nRow) continue;
00143                                 else if (index.first==nRow)     {
00144                                         for (size_t i=nextIndex;i<index.second;i++) vec[i]=T();
00145                                         vec[index.second]=it->second;
00146                                         nextIndex=index.second+1;
00147                                 }       else    {
00148                                         for (size_t i=nextIndex;i<mColumns;i++) vec[i]=T();
00149                                         break;
00150                                 }
00151                         }
00152                 }
00153                 /**
00154                   * Extracts a full column from the matrix.
00155                   * \sa getColCount,getRow,setColumn
00156                   * \throw std::logic_error on out of range.
00157                   */
00158                 void getColumn(size_t nCol,std::vector<T> &vec) const   {
00159 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
00160                         if (nCol>=mColumns) throw std::logic_error("Out of range");
00161 #endif
00162                         vec.resize(mRows);
00163                         size_t nextIndex=0;
00164                         for (typename SparseMatrixMap::const_iterator it=objectList.begin();it!=objectList.end();++it)  {
00165                                 const pair<size_t,size_t> &index=it->first;
00166                                 if (index.second==nCol) {
00167                                         for (size_t i=nextIndex;i<index.first;i++) vec[i]=T();
00168                                         vec[index.first]=it->second;
00169                                         nextIndex=index.first+1;
00170                                 }
00171                         }
00172                         for (size_t i=nextIndex;i<mRows;i++) vec[i]=T();
00173                 }
00174                 /**
00175                   * Inserts an element into the matrix.
00176                   * \sa operator()(size_t,size_t)
00177                   */
00178                 inline void insert(size_t row,size_t column,const T& obj)       {
00179                         operator()(row,column)=obj;
00180                 }
00181 
00182                 /** Inserts submatrix at a given location */
00183                 template <class MATRIX_LIKE>
00184                 inline void insertMatrix(size_t row,size_t column,const MATRIX_LIKE& mat)
00185                 {
00186                         for (size_t nr=0;nr<mat.getRowCount();nr++)
00187                                 for (size_t nc=0;nc<mat.getColCount();nc++)
00188                                         operator()(row+nr,column+nc)=mat(nr,nc);
00189                 }
00190 
00191                 //Public interface only supports const iterators. This way, no user of this class will be able to freely modify it contents.
00192                 /**
00193                   * Returns an iterator which points to the starting point of the matrix. It's a const_iterator, so that the usar isn't able to modify the matrix content into an invalid state.
00194                   * \sa end,rbegin,rend
00195                   */
00196                 inline const_iterator begin() const     {
00197                         return objectList.begin();
00198                 }
00199                 /**
00200                   * Returns an iterator which points to the end of the matrix. It's a const_iterator, so that the usar isn't able to modify the matrix content into an invalid state.
00201                   * \sa begin,rbegin,rend
00202                   */
00203                 inline const_iterator end() const       {
00204                         return objectList.end();
00205                 }
00206                 /**
00207                   * Returns an iterator which points to the end of the matrix, and can be used to move backwards. It's a const_reverse_iterator, so that the usar isn't able to modify the matrix content into an invalid state.
00208                   * \sa begin,end,rend
00209                   */
00210                 inline const_reverse_iterator rbegin() const    {
00211                         return objectList.rbegin();
00212                 }
00213                 /**
00214                   * Returns an iterator which points to the starting point of the matrix, although it's the upper limit of the matrix since it's a reverse iterator. Also, it's a const_reverse_iterator, so that the usar isn't able to modify the matrix content into an invalid state.
00215                   * \sa begin,end,rbegin
00216                   */
00217                 inline const_reverse_iterator rend() const      {
00218                         return objectList.rend();
00219                 }
00220                 /**
00221                   * Inserts a full row into the matrix. The third argument is used to specify a null object (which won't be inserted, since the matrix is sparse).
00222                   * \sa getRow
00223                   * \throw std::logic_error on out of range or wrong sized vector.
00224                   */
00225                 void setRow(size_t nRow,const std::vector<T> &vec,const T& nullObject=T())      {
00226 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
00227                         if (nRow>=mRows) throw std::logic_error("Out of range");
00228 #endif
00229                         size_t N=vec.size();
00230                         if (N!=mColumns) throw std::logic_error("Wrong-sized vector");
00231                         for (size_t i=0;i<N;i++)        {
00232                                 const T &obj=vec[i];
00233                                 pair<size_t,size_t> index=make_pair(nRow,i);
00234                                 if (obj==nullObject) objectList.erase(index);
00235                                 else objectList[index]=obj;
00236                         }
00237                 }
00238                 /**
00239                   * Inserts a full column into the matrix. The third argument is used to specify a null object (which won't be inserted, since the matrix is sparse).
00240                   * \sa getColumn
00241                   * \throw std::logic_error on out of range or wrong sized vector.
00242                   */
00243                 void setColumn(size_t nCol,const std::vector<T> &vec,const T& nullObject=T())   {
00244 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
00245                         if (nCol>=mColumns) throw std::logic_error("Out of range");
00246 #endif
00247                         size_t N=vec.size();
00248                         if (N!=mRows) throw std::logic_error("Wrong-sized vector");
00249                         for (size_t i=0;i<N;i++)        {
00250                                 const T &obj=vec[i];
00251                                 pair<size_t,size_t> index=make_pair(i,nCol);
00252                                 if (obj==nullObject) objectList.erase(index);
00253                                 else objectList[index]=obj;
00254                         }
00255                 }
00256                 /**
00257                   * Changes the size of the matrix.
00258                   */
00259                 void resize(size_t nRows,size_t nCols)  {
00260                         // if (mRows<0||mColumns<0) throw std::logic_error("Invalid range"); // This case never happens!
00261                         if (mRows==nRows && mColumns==nCols) return;
00262                         mRows=nRows;
00263                         mColumns=nCols;
00264                         std::vector<pair<size_t,size_t> > toErase;
00265                         for (const_iterator it=objectList.begin();it!=objectList.end();++it)    {
00266                                 const pair<size_t,size_t> &i=it->first;
00267                                 if (i.first>=nRows||i.second>=nCols) toErase.push_back(it->first);
00268                         }
00269                         for (std::vector<pair<size_t,size_t> >::const_iterator it=toErase.begin();it!=toErase.end();++it) objectList.erase(*it);
00270                 }
00271                 /**
00272                   * Extracts a submatrix form the matrix.
00273                   * \sa operator()(size_t,size_t)
00274                   * \throw std::logic_error on invalid bounds.
00275                   */
00276                 CSparseMatrixTemplate<T> operator()(size_t firstRow,size_t lastRow,size_t firstColumn,size_t lastColumn) const  {
00277 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
00278                         if (lastRow>=mRows||lastColumn>=mColumns) throw std::logic_error("Out of range");
00279                         if (firstRow>lastRow||firstColumn>lastColumn) throw std::logic_error("Invalid size");
00280 #endif
00281                         CSparseMatrixTemplate<T> res=CSparseMatrixTemplate<T>(lastRow+1-firstRow,lastColumn+1-firstColumn);
00282                         for (typename SparseMatrixMap::const_iterator it=begin();it!=end();++it)        {
00283                                 const pair<size_t,size_t> &i=it->first;
00284                                 if (i.first>=firstRow&&i.first<=lastRow&&i.second>=firstColumn&&i.second<=lastColumn) res(i.first-firstRow,i.second-firstColumn)=it->second;
00285                         }
00286                         return res;
00287                 }
00288                 /**
00289                   * Gets a vector containing all the elements of the matrix, ignoring their position.
00290                   */
00291                 void getAsVector(std::vector<T> &vec) const     {
00292                         size_t N=objectList.size();
00293                         vec.resize(0);
00294                         vec.reserve(N);
00295                         for (const_iterator it=objectList.begin();it!=objectList.end();++it) vec.push_back(it->second);
00296                 }
00297                 /**
00298                   * Gets the amount of non-null elements inside the matrix.
00299                   * \sa getNullElements,isNull,isNotNull
00300                   */
00301                 inline size_t getNonNullElements() const        {
00302                         return objectList.size();
00303                 }
00304                 /** Are there no elements set to !=0 ?
00305                   * \sa getNullElements,isNull,isNotNull
00306                   */
00307                 inline bool empty() const       { return objectList.empty(); }
00308 
00309                 /**
00310                   * Gets the amount of null elements inside the matrix.
00311                   * \sa getNonNullElements,isNull,isNotNull
00312                   */
00313                 inline size_t getNullElements() const   {
00314                         return mRows*mColumns-getNonNullElements();
00315                 }
00316                 /**
00317                   * Checks whether an element of the matrix is the default object.
00318                   * \sa getNonNullElements,getNullElements,isNotNull
00319                   * \throw std::logic_error on out of range
00320                   */
00321                 inline bool isNull(size_t nRow,size_t nCol) const       {
00322                         if (nRow>=mRows||nCol>=mColumns) throw std::logic_error("Out of range");
00323                         return objectList.count(make_pair(nRow,nCol))==0;
00324                 }
00325                 /**
00326                   * Checks whether an element of the matrix is not the default object.
00327                   * \sa getNonNullElements,getNullElements,isNull
00328                   */
00329                 inline bool isNotNull(size_t nRow,size_t nCol) const    {
00330                         if (nRow>=mRows||nCol>=mColumns) throw std::logic_error("Out of range");
00331                         return objectList.count(make_pair(nRow,nCol))>0;
00332                 }
00333                 /**
00334                   * Completely removes all elements, although maintaining the matrix's size.
00335                   */
00336                 inline void clear()     {
00337                         objectList.clear();
00338                 }
00339                 /**
00340                   * Checks each non-null elements against the basic objects, erasing unnecesary references to it.
00341                   */
00342                 void purge(T nullObject=T())    {
00343                         std::vector<std::pair<size_t,size_t> > nulls;
00344                         for (const_iterator it=begin();it!=end();++it) if (it->second==nullObject) nulls.push_back(it->first);
00345                         for (std::vector<std::pair<size_t,size_t> >::const_iterator it=nulls.begin();it!=nulls.end();++it) objectList.erase(*it);
00346                 }
00347         }; // end of sparse matrix
00348 
00349     /** A sparse matrix container for square symmetrical content around the main diagonal.
00350       *  This class saves half of the space with respect to CSparseMatrixTemplate since only those entries (c,r) such as c>=r are really stored,
00351       *   but both (c,r) and (r,c) can be retrieved or set and both redirect to the same internal cell container.
00352       *  \sa CSparseMatrixTemplate
00353       */
00354         template<class T>
00355         class CSparseSymmetricalMatrix : public CSparseMatrixTemplate<T> {
00356                 public:
00357                 CSparseSymmetricalMatrix() : CSparseMatrixTemplate<T>() { }
00358                 explicit CSparseSymmetricalMatrix(const CSparseSymmetricalMatrix &o) : CSparseMatrixTemplate<T>(o) { }
00359                 explicit CSparseSymmetricalMatrix(const CSparseMatrixTemplate<T> &o) : CSparseMatrixTemplate<T>(o) { }
00360                 virtual ~CSparseSymmetricalMatrix() { }
00361 
00362                 void resize(size_t matrixSize) {
00363                         CSparseMatrixTemplate<T>::resize(matrixSize,matrixSize);
00364                 }
00365 
00366                 inline T operator()(size_t r,size_t c) const    {
00367                         if (c<r) std::swap(r,c); // Symmetrical matrix
00368                         typename CSparseMatrixTemplate<T>::const_iterator it=CSparseMatrixTemplate<T>::objectList.find(make_pair(r,c));
00369                         if (it==CSparseMatrixTemplate<T>::objectList.end()) return T();
00370                         else return it->second;
00371                 }
00372                 inline T& operator()(size_t r,size_t c) {
00373                         if (c<r) std::swap(r,c); // Symmetrical matrix
00374                         if (r>=CSparseMatrixTemplate<T>::mRows||c>=CSparseMatrixTemplate<T>::mColumns) throw std::logic_error("Out of range");
00375                         return CSparseMatrixTemplate<T>::objectList[make_pair(r,c)];
00376                 }
00377 
00378         }; // end of CSparseSymmetricalMatrix
00379 
00380 }
00381 }
00382 #endif



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011