Main MRPT website > C++ reference
MRPT logo

matrix_iterators.h

Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                   http://mrpt.sourceforge.net/                            |
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  mrpt_matrix_iterators_H
00029 #define  mrpt_matrix_iterators_H
00030 
00031 #include <mrpt/math/math_frwds.h>  // Fordward declarations
00032 
00033 #include <algorithm>
00034 #include <iterator>
00035 
00036 #if 0
00037 
00038 // Macro for defining iterator/const_iterator/.... in any dynamic-like matrix.
00039 #define DECLARE_MRPT_MATRIX_ITERATORS \
00040         /*! @name Iterator stuff @{ */ \
00041         typedef mrpt::math::detail::CGenericMatrixIterator<mrpt_autotype>  iterator; \
00042         typedef mrpt::math::detail::CGenericMatrixConstIterator<mrpt_autotype>  const_iterator; \
00043         typedef std::reverse_iterator<iterator>                 reverse_iterator;  \
00044         typedef std::reverse_iterator<const_iterator>   const_reverse_iterator; \
00045         inline iterator                 begin()   { return iterator(*this,0,0); } \
00046         inline iterator                 end()     { return iterator(*this,mrpt_autotype::getRowCount(),0); } \
00047         inline const_iterator   begin() const   { return const_iterator(*this,0,0); } \
00048         inline const_iterator   end() const             { return const_iterator(*this,mrpt_autotype::getRowCount(),0); } \
00049         inline reverse_iterator                 rbegin()                { return reverse_iterator(end()); } \
00050         inline const_reverse_iterator   rbegin() const  { return const_reverse_iterator(end()); } \
00051         inline reverse_iterator                 rend()                  { return reverse_iterator(begin()); } \
00052         inline const_reverse_iterator   rend() const    { return const_reverse_iterator(begin()); } \
00053         /*! @} */ \
00054 
00055 
00056 namespace mrpt {
00057 namespace math {
00058 namespace detail {
00059 
00060         /** @name Iterator-related stuff
00061                 @{ */
00062 
00063         /** A random-access iterator for trasversing all the elements of a matrix, left to right, top to bottom.
00064           * Only in DEBUG mode, the iterator checks for the limits of the matrix.
00065           * \note The size of a matrix being accessed through an iterator should NOT be modifed or the iterator will become invalid.
00066           * \note The end() iterator is represented by column=0, row=N_ROWS.
00067           * \note An excelent reference for iterators theory: http://www.cs.helsinki.fi/u/tpkarkka/alglib/k06/lectures/iterators.html
00068           */
00069         template <class MATRIXTYPE>
00070         struct CGenericMatrixIterator : public std::iterator<std::random_access_iterator_tag,typename MATRIXTYPE::value_type>
00071         {
00072         private:
00073                 typedef std::iterator<std::random_access_iterator_tag,typename MATRIXTYPE::value_type> iterator_base;
00074                 MATRIXTYPE      *m_matrix;                              //!< A reference to the source of this iterator
00075                 size_t          m_cur_row, m_cur_col;   //!< The iterator points to this element.
00076                 typedef typename MATRIXTYPE::value_type T; //!< The type of the matrix elements
00077 
00078                 inline void check_limits(bool allow_end = false) const
00079                 {
00080 #ifdef _DEBUG
00081                         ASSERTMSG_(m_matrix!=NULL,"non initialized iterator");
00082                         if (m_cur_col>=m_matrix->getColCount()) THROW_EXCEPTION("Column index out of range in iterator.")
00083                         if (!allow_end) {
00084                                 if (m_cur_row>=m_matrix->getRowCount()) { THROW_EXCEPTION("Row index out of range in iterator.") }
00085                         } else {
00086                                 if (m_cur_row>m_matrix->getRowCount())  THROW_EXCEPTION("Row index out of range in iterator.") }
00087 #endif
00088                 }
00089 
00090         public:
00091                 inline bool operator <(const CGenericMatrixIterator<MATRIXTYPE> &it2) const
00092                 {
00093                         if (m_cur_row<m_cur_col) return true;
00094                         else if (m_cur_row==it2.m_cur_row)
00095                                  return m_cur_col<it2.m_cur_col;
00096                         else return false;
00097                 }
00098                 inline bool operator >(const CGenericMatrixIterator<MATRIXTYPE> &it2) const
00099                 {
00100                         if (m_cur_row<m_cur_col) return false;
00101                         else if (m_cur_row==it2.m_cur_row)
00102                                  return m_cur_col>it2.m_cur_col;
00103                         else return true;
00104                 }
00105 
00106                 inline size_t getCol() const { return m_cur_col; }
00107                 inline size_t getRow() const { return m_cur_row; }
00108 
00109                 inline CGenericMatrixIterator() : m_matrix(NULL),m_cur_row(0),m_cur_col(0) { }
00110                 inline CGenericMatrixIterator(MATRIXTYPE &obj, size_t start_row, size_t start_col)
00111                         : m_matrix(&obj),m_cur_row(start_row),m_cur_col(start_col)
00112                 {
00113                         check_limits(true); // Dont report as error an iterator to end().
00114                 }
00115                 inline typename MATRIXTYPE::reference operator*() const {
00116                         check_limits();
00117                         return m_matrix->get_unsafe(m_cur_row,m_cur_col);
00118                 }
00119                 inline CGenericMatrixIterator<MATRIXTYPE> &operator++() {
00120                         check_limits();
00121                         if (++m_cur_col>=m_matrix->getColCount()) { m_cur_col=0; ++m_cur_row; }
00122                         return *this;
00123                 }
00124                 inline CGenericMatrixIterator<MATRIXTYPE> operator++(int)       {
00125                         CGenericMatrixIterator<MATRIXTYPE> it=*this;
00126                         ++*this;
00127                         return it;
00128                 }
00129                 inline CGenericMatrixIterator<MATRIXTYPE> &operator--() {
00130                         if (!m_cur_col) {
00131                                 m_cur_col = m_matrix->getColCount()-1;
00132                                 --m_cur_row;
00133                         }
00134                         else --m_cur_col;
00135                         check_limits();
00136                         return *this;
00137                 }
00138                 inline CGenericMatrixIterator<MATRIXTYPE> operator--(int)       {
00139                         CGenericMatrixIterator<MATRIXTYPE> it=*this;
00140                         --*this;
00141                         return it;
00142                 }
00143                 CGenericMatrixIterator<MATRIXTYPE> &operator+=(typename iterator_base::difference_type off)     {
00144                         const size_t N = m_matrix->getColCount();
00145                         if (off>=0)
00146                         {  // Advance all as columns, then count how many rows should that be in fact:
00147                                 m_cur_col+=off;
00148                                 m_cur_row+=m_cur_col/N;
00149                                 m_cur_col=m_cur_col%N;
00150                         }
00151                         else
00152                         {  // Going backwards is more complicated since m_cur_* are not signed:
00153                                 const size_t idx=(m_cur_col+(m_cur_row*N)) + off;
00154                                 m_cur_row = idx/N;
00155                                 m_cur_col = idx%N;
00156                         }
00157                         check_limits(true);
00158                         return *this;
00159                 }
00160                 inline CGenericMatrixIterator<MATRIXTYPE> operator+(typename iterator_base::difference_type off) const  {
00161                         CGenericMatrixIterator<MATRIXTYPE> it=*this;
00162                         it+=off;
00163                         return it;
00164                 }
00165                 inline CGenericMatrixIterator<MATRIXTYPE> &operator-=(typename iterator_base::difference_type off)      {
00166                         return (*this)+=(-off);
00167                 }
00168                 inline CGenericMatrixIterator<MATRIXTYPE> operator-(typename iterator_base::difference_type off) const  {
00169                         CGenericMatrixIterator<MATRIXTYPE> it=*this;
00170                         it-=off;
00171                         return it;
00172                 }
00173                 typename iterator_base::difference_type operator-(const CGenericMatrixIterator<MATRIXTYPE> &it) const   {
00174                         return m_matrix->getColCount()*( m_cur_row-it.m_cur_row ) + ( m_cur_col-it.m_cur_col);
00175                 }
00176                 inline typename MATRIXTYPE::reference operator[](typename iterator_base::difference_type off) const     {
00177                         const size_t incr_row = off / m_matrix->getColCount();
00178                         const size_t incr_col = off % m_matrix->getColCount();
00179                         return (*m_matrix)(m_cur_row+incr_row,m_cur_col+incr_col);
00180                 }
00181                 inline bool operator==(const CGenericMatrixIterator<MATRIXTYPE> &it) const {
00182                         return (m_cur_col==it.m_cur_col)&&(m_cur_row==it.m_cur_row)&&(m_matrix==it.m_matrix);
00183                 }
00184                 inline bool operator!=(const CGenericMatrixIterator<MATRIXTYPE> &it) const {
00185                         return !(operator==(it));
00186                 }
00187         }; // end CGenericMatrixIterator<MATRIXTYPE>
00188 
00189         /** A random-access const iterator for trasversing all the elements of a matrix, left to right, top to bottom.
00190           * Only in DEBUG mode, the iterator checks for the limits of the matrix.
00191           * \note The size of a matrix being accessed through an iterator should NOT be modifed or the iterator will become invalid.
00192           * \note The end() iterator is represented by column=0, row=N_ROWS.
00193           * \note An excelent reference for iterators theory: http://www.cs.helsinki.fi/u/tpkarkka/alglib/k06/lectures/iterators.html
00194           */
00195         template <class MATRIXTYPE>
00196         struct CGenericMatrixConstIterator : public std::iterator<std::random_access_iterator_tag,typename MATRIXTYPE::value_type>
00197         {
00198         private:
00199                 typedef std::iterator<std::random_access_iterator_tag,typename MATRIXTYPE::value_type> iterator_base;
00200                 const MATRIXTYPE *m_matrix;                             //!< A reference to the source of this iterator
00201                 size_t  m_cur_row, m_cur_col;   //!< The iterator points to this element.
00202                 typedef typename MATRIXTYPE::value_type T; //!< The type of the matrix elements
00203 
00204                 inline void check_limits(bool allow_end = false) const
00205                 {
00206 #ifdef _DEBUG
00207                         ASSERTMSG_(m_matrix!=NULL,"non initialized iterator");
00208                         if (m_cur_col>=m_matrix->getColCount()) THROW_EXCEPTION("Column index out of range in iterator.")
00209                         if (!allow_end)
00210                         {
00211                                 if (m_cur_row>=m_matrix->getRowCount()) { THROW_EXCEPTION("Row index out of range in iterator.") }
00212                                 else if (m_cur_row>m_matrix->getRowCount())  THROW_EXCEPTION("Row index out of range in iterator.")
00213                         }
00214 #endif
00215                 }
00216 
00217         public:
00218                 inline bool operator <(const CGenericMatrixConstIterator<MATRIXTYPE> &it2) const
00219                 {
00220                         if (m_cur_row<m_cur_col) return true;
00221                         else if (m_cur_row==it2.m_cur_row)
00222                                  return m_cur_col<it2.m_cur_col;
00223                         else return false;
00224                 }
00225                 inline bool operator >(const CGenericMatrixConstIterator<MATRIXTYPE> &it2) const
00226                 {
00227                         if (m_cur_row<m_cur_col) return false;
00228                         else if (m_cur_row==it2.m_cur_row)
00229                                  return m_cur_col>it2.m_cur_col;
00230                         else return true;
00231                 }
00232 
00233                 inline size_t getCol() const { return m_cur_col; }
00234                 inline size_t getRow() const { return m_cur_row; }
00235 
00236                 inline CGenericMatrixConstIterator() : m_matrix(NULL),m_cur_row(0),m_cur_col(0) { }
00237                 inline CGenericMatrixConstIterator(const MATRIXTYPE &obj,size_t start_row, size_t start_col)
00238                         : m_matrix(&obj),m_cur_row(start_row),m_cur_col(start_col)
00239                 {
00240                         check_limits(true); // Dont report as error an iterator to end().
00241                 }
00242                 inline typename MATRIXTYPE::const_reference operator*() const   {
00243                         check_limits();
00244                         return m_matrix->get_unsafe(m_cur_row,m_cur_col);
00245                 }
00246                 inline CGenericMatrixConstIterator<MATRIXTYPE> &operator++() {
00247                         check_limits();
00248                         if (++m_cur_col>=m_matrix->getColCount()) { m_cur_col=0; ++m_cur_row; }
00249                         return *this;
00250                 }
00251                 inline CGenericMatrixConstIterator<MATRIXTYPE> operator++(int)  {
00252                         CGenericMatrixConstIterator<MATRIXTYPE> it=*this;
00253                         ++*this;
00254                         return it;
00255                 }
00256                 inline CGenericMatrixConstIterator<MATRIXTYPE> &operator--()    {
00257                         if (!m_cur_col) {
00258                                 m_cur_col = m_matrix->getColCount()-1;
00259                                 --m_cur_row;
00260                         }
00261                         else --m_cur_col;
00262                         check_limits();
00263                         return *this;
00264                 }
00265                 inline CGenericMatrixConstIterator<MATRIXTYPE> operator--(int)  {
00266                         CGenericMatrixConstIterator<MATRIXTYPE> it=*this;
00267                         --*this;
00268                         return it;
00269                 }
00270                 CGenericMatrixConstIterator<MATRIXTYPE> &operator+=(typename iterator_base::difference_type off)        {
00271                         const size_t N = m_matrix->getColCount();
00272                         if (off>=0)
00273                         {  // Advance all as columns, then count how many rows should that be in fact:
00274                                 m_cur_col+=off;
00275                                 m_cur_row+=m_cur_col/N;
00276                                 m_cur_col=m_cur_col%N;
00277                         }
00278                         else
00279                         {  // Going backwards is more complicated since m_cur_* are not signed:
00280                                 const size_t idx=(m_cur_col+m_cur_row*N) + off;
00281                                 m_cur_row = idx/N;
00282                                 m_cur_col = idx%N;
00283                         }
00284                         check_limits(true);
00285                         return *this;
00286                 }
00287                 inline CGenericMatrixConstIterator<MATRIXTYPE> operator+(typename iterator_base::difference_type off) const     {
00288                         CGenericMatrixConstIterator<MATRIXTYPE> it=*this;
00289                         it+=off;
00290                         return it;
00291                 }
00292                 CGenericMatrixConstIterator<MATRIXTYPE> &operator-=(typename iterator_base::difference_type off)        {
00293                         return (*this)+=(-off);
00294                 }
00295                 inline CGenericMatrixConstIterator<MATRIXTYPE> operator-(typename iterator_base::difference_type off) const     {
00296                         CGenericMatrixConstIterator<MATRIXTYPE> it=*this;
00297                         it-=off;
00298                         return it;
00299                 }
00300                 typename iterator_base::difference_type operator-(const CGenericMatrixConstIterator<MATRIXTYPE> &it) const      {
00301                         return m_matrix->getColCount()*( m_cur_row-it.m_cur_row ) + ( m_cur_col-it.m_cur_col);
00302                 }
00303                 inline typename MATRIXTYPE::const_reference operator[](typename iterator_base::difference_type off) const       {
00304                         const size_t incr_row = off / m_matrix->getColCount();
00305                         const size_t incr_col = off % m_matrix->getColCount();
00306                         return (*m_matrix)(m_cur_row+incr_row,m_cur_col+incr_col);
00307                 }
00308                 inline bool operator==(const CGenericMatrixConstIterator<MATRIXTYPE> &it) const {
00309                         return (m_cur_col==it.m_cur_col)&&(m_cur_row==it.m_cur_row)&&(m_matrix==it.m_matrix);
00310                 }
00311                 inline bool operator!=(const CGenericMatrixConstIterator<MATRIXTYPE> &it) const {
00312                         return !(operator==(it));
00313                 }
00314         }; // end CGenericMatrixConstIterator<MATRIXTYPE>
00315 
00316         /** @} */
00317 
00318 } // end namespace
00319 } // end namespace
00320 } // end namespace
00321 
00322 #endif
00323 
00324 #endif



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN:exported at Tue Jan 25 21:56:31 UTC 2011