Main MRPT website > C++ reference
MRPT logo
CSparseMatrixTemplate.h
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | The Mobile Robot Programming Toolkit (MRPT) C++ library |
3  | |
4  | http://www.mrpt.org/ |
5  | |
6  | Copyright (C) 2005-2012 University of Malaga |
7  | |
8  | This software was written by the Machine Perception and Intelligent |
9  | Robotics Lab, University of Malaga (Spain). |
10  | Contact: Jose-Luis Blanco <jlblanco@ctima.uma.es> |
11  | |
12  | This file is part of the MRPT project. |
13  | |
14  | MRPT is free software: you can redistribute it and/or modify |
15  | it under the terms of the GNU General Public License as published by |
16  | the Free Software Foundation, either version 3 of the License, or |
17  | (at your option) any later version. |
18  | |
19  | MRPT is distributed in the hope that it will be useful, |
20  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
21  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22  | GNU General Public License for more details. |
23  | |
24  | You should have received a copy of the GNU General Public License |
25  | along with MRPT. If not, see <http://www.gnu.org/licenses/>. |
26  | |
27  +---------------------------------------------------------------------------+ */
28 #ifndef CSparseMatrixTemplate_H
29 #define CSparseMatrixTemplate_H
30 
31 #include <mrpt/utils/utils_defs.h>
32 
33 namespace mrpt {
34 namespace math {
35  using namespace std;
36 
37  /** A sparse matrix container (with cells of any type), with iterators.
38  * This class stores only those elements created by assigning them a value, for example: "M(2,3)=8;".
39  *
40  * This class doesn't implement math operations since it's a generic sparse container, but it can be
41  * used to initialize the contents of a CSparse library-based matrix of type mrpt::math::CSparseMatrix.
42  *
43  * Note that reading non-existing cell elements will return the default value (0 for numbers)
44  * and that cell will remain non-created in the matrix.
45  *
46  * There is an additional method "exists(i,j)" to check whether a given element exists in the matrix.
47  *
48  * \sa mrpt::math::CSparseMatrix, CSparseSymmetricalMatrix
49  * \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.
50  * \ingroup mrpt_base_grp
51  */
52  template<class T>
54  //Public typedefs
55  public:
56  /**
57  * Internal map type, used to store the actual matrix.
58  */
59  typedef typename std::map<std::pair<size_t,size_t>,T> SparseMatrixMap;
60  /**
61  * Const iterator to move through the matrix.
62  * \sa CSparseMatrixTemplate::const_reverse_iterator
63  */
65  /**
66  * Const reverse iterator to move through the matrix.
67  * \sa CSparseMatrixTemplate::const_iterator
68  */
69  typedef typename SparseMatrixMap::const_reverse_iterator const_reverse_iterator;
70  protected:
71  /**
72  * Size of the matrix.
73  */
74  size_t mRows,mColumns;
75  /**
76  * Actual matrix.
77  */
79  public:
80  /**
81  * Basic constructor with no data. Size is set to (0,0).
82  */
83  CSparseMatrixTemplate():mRows(0),mColumns(0) {}
84  /**
85  * Constructor with default size.
86  */
87  CSparseMatrixTemplate(size_t nR,size_t nC):mRows(nR),mColumns(nC) {}
88  /**
89  * Element access operator. Doesn't check bounds.
90  */
91  inline T operator()(size_t r,size_t c) const {
92  const_iterator it=objectList.find(make_pair(r,c));
93  if (it==objectList.end()) return T();
94  else return it->second;
95  }
96 
97  /** Element access operator. Checks bounds.
98  */
99  inline bool exists(size_t r,size_t c) const {
100 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
101  if (r>=mRows||c>=mColumns) throw std::logic_error("Out of range");
102 #endif
103  return (objectList.find(make_pair(r,c)) != objectList.end());
104  }
105 
106  /**
107  * Reference access operator. Checks for bounds.
108  */
109  inline T& operator()(size_t r,size_t c) {
110 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
111  if (r>=mRows||c>=mColumns) throw std::logic_error("Out of range");
112 #endif
113  return objectList[make_pair(r,c)];
114  }
115  /**
116  * Returns the amount of rows in this matrix.
117  * \sa getColCount,getRow
118  */
119  inline size_t getRowCount() const {
120  return mRows;
121  }
122  /**
123  * Returns the amount of columns in this matrix.
124  * \sa getRowCount
125  */
126  inline size_t getColCount() const {
127  return mColumns;
128  }
129  /**
130  * Extracts a full row from the matrix.
131  * \sa getRowCount,getColumn,setRow
132  * \throw std::logic_error on out of range.
133  */
134  void getRow(size_t nRow,std::vector<T> &vec) const {
135 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
136  if (nRow>=mRows) throw std::logic_error("Out of range");
137 #endif
138  vec.resize(mColumns);
139  size_t nextIndex=0;
140  for (typename SparseMatrixMap::const_iterator it=objectList.begin();it!=objectList.end();++it) {
141  const pair<size_t,size_t> &index=it->first;
142  if (index.first<nRow) continue;
143  else if (index.first==nRow) {
144  for (size_t i=nextIndex;i<index.second;i++) vec[i]=T();
145  vec[index.second]=it->second;
146  nextIndex=index.second+1;
147  } else {
148  for (size_t i=nextIndex;i<mColumns;i++) vec[i]=T();
149  break;
150  }
151  }
152  }
153  /**
154  * Extracts a full column from the matrix.
155  * \sa getColCount,getRow,setColumn
156  * \throw std::logic_error on out of range.
157  */
158  void getColumn(size_t nCol,std::vector<T> &vec) const {
159 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
160  if (nCol>=mColumns) throw std::logic_error("Out of range");
161 #endif
162  vec.resize(mRows);
163  size_t nextIndex=0;
164  for (typename SparseMatrixMap::const_iterator it=objectList.begin();it!=objectList.end();++it) {
165  const pair<size_t,size_t> &index=it->first;
166  if (index.second==nCol) {
167  for (size_t i=nextIndex;i<index.first;i++) vec[i]=T();
168  vec[index.first]=it->second;
169  nextIndex=index.first+1;
170  }
171  }
172  for (size_t i=nextIndex;i<mRows;i++) vec[i]=T();
173  }
174  /**
175  * Inserts an element into the matrix.
176  * \sa operator()(size_t,size_t)
177  */
178  inline void insert(size_t row,size_t column,const T& obj) {
179  operator()(row,column)=obj;
180  }
181 
182  /** Inserts submatrix at a given location */
183  template <class MATRIX_LIKE>
184  inline void insertMatrix(size_t row,size_t column,const MATRIX_LIKE& mat)
185  {
186  for (size_t nr=0;nr<mat.getRowCount();nr++)
187  for (size_t nc=0;nc<mat.getColCount();nc++)
188  operator()(row+nr,column+nc)=mat(nr,nc);
189  }
190 
191  //Public interface only supports const iterators. This way, no user of this class will be able to freely modify it contents.
192  /**
193  * 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.
194  * \sa end,rbegin,rend
195  */
196  inline const_iterator begin() const {
197  return objectList.begin();
198  }
199  /**
200  * 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.
201  * \sa begin,rbegin,rend
202  */
203  inline const_iterator end() const {
204  return objectList.end();
205  }
206  /**
207  * 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.
208  * \sa begin,end,rend
209  */
211  return objectList.rbegin();
212  }
213  /**
214  * 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.
215  * \sa begin,end,rbegin
216  */
217  inline const_reverse_iterator rend() const {
218  return objectList.rend();
219  }
220  /**
221  * 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).
222  * \sa getRow
223  * \throw std::logic_error on out of range or wrong sized vector.
224  */
225  void setRow(size_t nRow,const std::vector<T> &vec,const T& nullObject=T()) {
226 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
227  if (nRow>=mRows) throw std::logic_error("Out of range");
228 #endif
229  size_t N=vec.size();
230  if (N!=mColumns) throw std::logic_error("Wrong-sized vector");
231  for (size_t i=0;i<N;i++) {
232  const T &obj=vec[i];
233  pair<size_t,size_t> index=make_pair(nRow,i);
234  if (obj==nullObject) objectList.erase(index);
235  else objectList[index]=obj;
236  }
237  }
238  /**
239  * 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).
240  * \sa getColumn
241  * \throw std::logic_error on out of range or wrong sized vector.
242  */
243  void setColumn(size_t nCol,const std::vector<T> &vec,const T& nullObject=T()) {
244 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
245  if (nCol>=mColumns) throw std::logic_error("Out of range");
246 #endif
247  size_t N=vec.size();
248  if (N!=mRows) throw std::logic_error("Wrong-sized vector");
249  for (size_t i=0;i<N;i++) {
250  const T &obj=vec[i];
251  pair<size_t,size_t> index=make_pair(i,nCol);
252  if (obj==nullObject) objectList.erase(index);
253  else objectList[index]=obj;
254  }
255  }
256  /**
257  * Changes the size of the matrix.
258  */
259  void resize(size_t nRows,size_t nCols) {
260  // if (mRows<0||mColumns<0) throw std::logic_error("Invalid range"); // This case never happens!
261  if (mRows==nRows && mColumns==nCols) return;
262  mRows=nRows;
263  mColumns=nCols;
264  std::vector<pair<size_t,size_t> > toErase;
265  for (const_iterator it=objectList.begin();it!=objectList.end();++it) {
266  const pair<size_t,size_t> &i=it->first;
267  if (i.first>=nRows||i.second>=nCols) toErase.push_back(it->first);
268  }
269  for (std::vector<pair<size_t,size_t> >::const_iterator it=toErase.begin();it!=toErase.end();++it) objectList.erase(*it);
270  }
271  /**
272  * Extracts a submatrix form the matrix.
273  * \sa operator()(size_t,size_t)
274  * \throw std::logic_error on invalid bounds.
275  */
276  CSparseMatrixTemplate<T> operator()(size_t firstRow,size_t lastRow,size_t firstColumn,size_t lastColumn) const {
277 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
278  if (lastRow>=mRows||lastColumn>=mColumns) throw std::logic_error("Out of range");
279  if (firstRow>lastRow||firstColumn>lastColumn) throw std::logic_error("Invalid size");
280 #endif
281  CSparseMatrixTemplate<T> res=CSparseMatrixTemplate<T>(lastRow+1-firstRow,lastColumn+1-firstColumn);
282  for (typename SparseMatrixMap::const_iterator it=begin();it!=end();++it) {
283  const pair<size_t,size_t> &i=it->first;
284  if (i.first>=firstRow&&i.first<=lastRow&&i.second>=firstColumn&&i.second<=lastColumn) res(i.first-firstRow,i.second-firstColumn)=it->second;
285  }
286  return res;
287  }
288  /**
289  * Gets a vector containing all the elements of the matrix, ignoring their position.
290  */
291  void getAsVector(std::vector<T> &vec) const {
292  size_t N=objectList.size();
293  vec.resize(0);
294  vec.reserve(N);
295  for (const_iterator it=objectList.begin();it!=objectList.end();++it) vec.push_back(it->second);
296  }
297  /**
298  * Gets the amount of non-null elements inside the matrix.
299  * \sa getNullElements,isNull,isNotNull
300  */
301  inline size_t getNonNullElements() const {
302  return objectList.size();
303  }
304  /** Are there no elements set to !=0 ?
305  * \sa getNullElements,isNull,isNotNull
306  */
307  inline bool empty() const { return objectList.empty(); }
308 
309  /**
310  * Gets the amount of null elements inside the matrix.
311  * \sa getNonNullElements,isNull,isNotNull
312  */
313  inline size_t getNullElements() const {
314  return mRows*mColumns-getNonNullElements();
315  }
316  /**
317  * Checks whether an element of the matrix is the default object.
318  * \sa getNonNullElements,getNullElements,isNotNull
319  * \throw std::logic_error on out of range
320  */
321  inline bool isNull(size_t nRow,size_t nCol) const {
322  if (nRow>=mRows||nCol>=mColumns) throw std::logic_error("Out of range");
323  return objectList.count(make_pair(nRow,nCol))==0;
324  }
325  /**
326  * Checks whether an element of the matrix is not the default object.
327  * \sa getNonNullElements,getNullElements,isNull
328  */
329  inline bool isNotNull(size_t nRow,size_t nCol) const {
330  if (nRow>=mRows||nCol>=mColumns) throw std::logic_error("Out of range");
331  return objectList.count(make_pair(nRow,nCol))>0;
332  }
333  /**
334  * Completely removes all elements, although maintaining the matrix's size.
335  */
336  inline void clear() {
337  objectList.clear();
338  }
339  /**
340  * Checks each non-null elements against the basic objects, erasing unnecesary references to it.
341  */
342  void purge(T nullObject=T()) {
343  std::vector<std::pair<size_t,size_t> > nulls;
344  for (const_iterator it=begin();it!=end();++it) if (it->second==nullObject) nulls.push_back(it->first);
345  for (std::vector<std::pair<size_t,size_t> >::const_iterator it=nulls.begin();it!=nulls.end();++it) objectList.erase(*it);
346  }
347  }; // end of sparse matrix
348 
349  /** A sparse matrix container for square symmetrical content around the main diagonal.
350  * This class saves half of the space with respect to CSparseMatrixTemplate since only those entries (c,r) such as c>=r are really stored,
351  * but both (c,r) and (r,c) can be retrieved or set and both redirect to the same internal cell container.
352  * \sa CSparseMatrixTemplate
353  */
354  template<class T>
356  public:
361 
362  void resize(size_t matrixSize) {
363  CSparseMatrixTemplate<T>::resize(matrixSize,matrixSize);
364  }
365 
366  inline T operator()(size_t r,size_t c) const {
367  if (c<r) std::swap(r,c); // Symmetrical matrix
369  if (it==CSparseMatrixTemplate<T>::objectList.end()) return T();
370  else return it->second;
371  }
372  inline T& operator()(size_t r,size_t c) {
373  if (c<r) std::swap(r,c); // Symmetrical matrix
374  if (r>=CSparseMatrixTemplate<T>::mRows||c>=CSparseMatrixTemplate<T>::mColumns) throw std::logic_error("Out of range");
375  return CSparseMatrixTemplate<T>::objectList[make_pair(r,c)];
376  }
377 
378  }; // end of CSparseSymmetricalMatrix
379 
380 }
381 }
382 #endif



Page generated by Doxygen 1.8.3 for MRPT 0.9.6 SVN: at Fri Feb 15 22:05:02 EST 2013