Scythe-1.0.3
matrix_forward_iterator.h
Go to the documentation of this file.
00001 /* 
00002  * Scythe Statistical Library Copyright (C) 2000-2002 Andrew D. Martin
00003  * and Kevin M. Quinn; 2002-present Andrew D. Martin, Kevin M. Quinn,
00004  * and Daniel Pemstein.  All Rights Reserved.
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify under the terms of the GNU General Public License as
00008  * published by Free Software Foundation; either version 2 of the
00009  * License, or (at your option) any later version.  See the text files
00010  * COPYING and LICENSE, distributed with this source code, for further
00011  * information.
00012  * --------------------------------------------------------------------
00013  *  scythestat/matrix_forward_iterator.h
00014  *
00015  * Forward iterators for the matrix class.
00016  *
00017  */
00018 
00035 #ifndef SCYTHE_MATRIX_FORWARD_ITERATOR_H
00036 #define SCYTHE_MATRIX_FORWARD_ITERATOR_H
00037 
00038 #include <iterator>
00039 
00040 #ifdef SCYTHE_COMPILE_DIRECT
00041 #include "defs.h"
00042 #include "error.h"
00043 #include "matrix.h"
00044 #else
00045 #include "scythestat/defs.h"
00046 #include "scythestat/error.h"
00047 #include "scythestat/matrix.h"
00048 #endif
00049 
00050 namespace scythe {
00051   /* convenience typedefs */
00052   namespace { // local to this file
00053     typedef unsigned int uint;
00054   }
00055   
00056   /* forward declaration of the matrix class */
00057   template <typename T_type, matrix_order ORDER, matrix_style STYLE>
00058   class Matrix;
00059 
00074   template <typename T_type, matrix_order ORDER, matrix_order M_ORDER,
00075             matrix_style M_STYLE>
00076   class const_matrix_forward_iterator
00077     : public std::iterator<std::forward_iterator_tag, T_type>
00078   {
00079     public:
00080       /**** TYPEDEFS ***/
00081       typedef const_matrix_forward_iterator<T_type, ORDER, 
00082               M_ORDER, M_STYLE> self;
00083 
00084       /* These are a little formal, but useful */
00085       typedef typename std::iterator_traits<self>::value_type
00086         value_type;
00087       typedef typename std::iterator_traits<self>::iterator_category
00088         iterator_category;
00089       typedef typename std::iterator_traits<self>::difference_type
00090         difference_type;
00091       typedef typename std::iterator_traits<self>::pointer pointer;
00092       typedef typename std::iterator_traits<self>::reference reference;
00093 
00094     
00095       /**** CONSTRUCTORS ****/
00096       
00097       /* Default constructor */
00098       const_matrix_forward_iterator ()
00099       {}
00100 
00101       /* Standard constructor */
00102       const_matrix_forward_iterator
00103         (const Matrix<value_type, M_ORDER, M_STYLE> &M)
00104         : pos_ (M.getArray()),
00105           matrix_ (&M)
00106       {
00107         SCYTHE_CHECK_30 (pos_ == 0, scythe_null_error,
00108             "Requesting iterator to NULL matrix");
00109 
00110         /* The basic story is: when M_STYLE == Concrete and ORDER ==
00111          * M_ORDER, we only need pos_ and iteration will be as fast as
00112          * possible.  All other types of iteration need more variables
00113          * to keep track of things and are slower.
00114          */
00115 
00116 
00117         if (M_STYLE != Concrete || M_ORDER != ORDER) {
00118           offset_ = 0;
00119 
00120           if (ORDER == Col) {
00121             lead_length_ = M.rows();
00122             lead_inc_ = M.rowstride();
00123             trail_inc_ = M.colstride();
00124           } else {
00125             lead_length_ = M.cols();
00126             lead_inc_ = M.colstride();
00127             trail_inc_ = M.rowstride();
00128           }
00129           jump_ = trail_inc_ + (1 - lead_length_) * lead_inc_;
00130           vend_ = pos_ + (lead_length_ - 1) * lead_inc_;
00131         }
00132 #if SCYTHE_DEBUG > 2
00133         size_ = M.size();
00134         start_ = pos_;
00135 #endif
00136       }
00137 
00138       /* Copy constructor */
00139       const_matrix_forward_iterator (const self &mi)
00140         : pos_ (mi.pos_),
00141           matrix_ (mi.matrix_)
00142       {
00143         if (M_STYLE != Concrete || M_ORDER != ORDER) {
00144           offset_ = mi.offset_;
00145           lead_length_ = mi.lead_length_;
00146           lead_inc_ = mi.lead_inc_;
00147           trail_inc_ = mi.trail_inc_;
00148           vend_ = mi.vend_;
00149           jump_ = mi.jump_;
00150         }
00151 #if SCYTHE_DEBUG > 2
00152         size_ = mi.size_;
00153         start_ = mi.start_;
00154 #endif
00155       }
00156 
00157       /**** EXTRA MODIFIER ****/
00158 
00159       /* This function lets us grab an end iterator quickly, for both
00160        * concrete and view matrices.  The view code is a bit of a
00161        * kludge, but it works.
00162        */
00163       inline self& set_end ()
00164       {
00165         if (M_STYLE == Concrete && ORDER == M_ORDER) {
00166           pos_ = matrix_->getArray() + matrix_->size();
00167         } else { 
00168           offset_ = matrix_->size();
00169         }
00170 
00171         return *this;
00172       }
00173 
00174       /* Returns the current index (in logical matrix terms) of the
00175        * iterator.
00176        */
00177       unsigned int get_index () const
00178       {
00179         return offset_;
00180       }
00181 
00182       /**** FORWARD ITERATOR FACILITIES ****/
00183 
00184       inline self& operator= (const self& mi)
00185       {
00186         pos_ = mi.pos_;
00187         matrix_ = mi.matrix_;
00188 
00189         if (M_STYLE != Concrete || M_ORDER != ORDER) {
00190           offset_ = mi.offset_;
00191           lead_length_ = mi.lead_length_;
00192           lead_inc_ = mi.lead_inc_;
00193           trail_inc_ = mi.trail_inc_;
00194           vend_ = mi.vend_;
00195           jump_ = mi.jump_;
00196         }
00197 #if SCYTHE_DEBUG > 2
00198         size_ = mi.size_;
00199         start_ = mi.start_;
00200 #endif
00201 
00202         return *this;
00203       }
00204 
00205       inline const reference operator* () const
00206       {
00207         SCYTHE_ITER_CHECK_BOUNDS();
00208         return *pos_;
00209       }
00210 
00211       inline const pointer operator-> () const
00212       {
00213         SCYTHE_ITER_CHECK_BOUNDS();
00214         return pos_;
00215       }
00216 
00217       inline self& operator++ ()
00218       {
00219         if (M_STYLE == Concrete && ORDER == M_ORDER)
00220           ++pos_;
00221         else {
00222           if (pos_ == vend_) {
00223             vend_ += trail_inc_;
00224             pos_ += jump_;
00225           } else {
00226             pos_ += lead_inc_;
00227           }
00228           ++offset_;
00229         }
00230 
00231         return *this;
00232       }
00233 
00234       inline self operator++ (int)
00235       {
00236         self tmp = *this;
00237         ++(*this);
00238         return tmp;
00239       }
00240 
00241       /* == is only defined for iterators of the same template type
00242        * that point to the same matrix.  Behavior for any other
00243        * comparison is undefined.
00244        *
00245        * Note that we have to be careful about iterator comparisons
00246        * when working with views and cross-grain iterators.
00247        * Specifically, we always have to rely on the offset value.
00248        * Obviously, with <> checks pos_ can jump all over the place in
00249        * cross-grain iterators, but also end iterators point to the
00250        * value after the last in the matrix.  In some cases, the
00251        * equation in += and -= will actually put pos_ inside the
00252        * matrix (often in an early position) in this case.
00253        */
00254       inline bool operator== (const self& x) const
00255       {
00256         if (M_STYLE == Concrete && ORDER == M_ORDER) {
00257           return pos_ == x.pos_;
00258         } else {
00259           return offset_ == x.offset_;
00260         }
00261       }
00262 
00263       /* Again, != is only officially defined for iterators over the
00264        * same matrix although the test will be trivially true for
00265        * matrices that don't view the same data, by implementation.
00266        */
00267       inline bool operator!= (const self &x) const
00268       {
00269         return !(*this == x);
00270       }
00271 
00272     protected:
00273 
00274       /**** INSTANCE VARIABLES ****/
00275       T_type* pos_;         // pointer to current position in array
00276       T_type *vend_;        // pointer to end of current vector
00277 
00278       uint offset_;         // logical offset into matrix
00279 
00280       // TODO Some of these can probably be uints
00281       int lead_length_;  // Logical length of leading dimension
00282       int lead_inc_;  // Memory distance between vectors in ldim
00283       int trail_inc_; // Memory distance between vectors in tdim
00284       int jump_; // Memory distance between end of one ldim vector and
00285                  // begin of next
00286       // Pointer to the matrix we're iterating over.  This is really
00287       // only needed to get variables necessary to set the end.
00288       // TODO Handle this more cleanly.
00289       const Matrix<T_type, M_ORDER, M_STYLE>* matrix_;
00290       // Size variable for range checking
00291 #if SCYTHE_DEBUG > 2
00292       uint size_;  // Logical matrix size
00293       T_type* start_; // Not normally needed, but used for bound check
00294 #endif
00295  };
00296 
00310   template <typename T_type, matrix_order ORDER, matrix_order M_ORDER,
00311             matrix_style M_STYLE>
00312   class matrix_forward_iterator
00313     : public const_matrix_forward_iterator<T_type, ORDER, 
00314                                            M_ORDER, M_STYLE>
00315   {
00316       /**** TYPEDEFS ***/
00317       typedef matrix_forward_iterator<T_type, ORDER, M_ORDER, 
00318                                       M_STYLE> self;
00319       typedef const_matrix_forward_iterator<T_type, ORDER, 
00320                                             M_ORDER, M_STYLE> Base;
00321     
00322     public:
00323       /* These are a little formal, but useful */
00324       typedef typename std::iterator_traits<Base>::value_type
00325         value_type;
00326       typedef typename std::iterator_traits<Base>::iterator_category
00327         iterator_category;
00328       typedef typename std::iterator_traits<Base>::difference_type
00329         difference_type;
00330       typedef typename std::iterator_traits<Base>::pointer pointer;
00331       typedef typename std::iterator_traits<Base>::reference reference;
00332 
00333     
00334       /**** CONSTRUCTORS ****/
00335       
00336       /* Default constructor */
00337       matrix_forward_iterator ()
00338         : Base () 
00339       {}
00340 
00341       /* Standard constructor */
00342       matrix_forward_iterator (const Matrix<value_type, M_ORDER, 
00343                                                   M_STYLE> &M)
00344         : Base(M)
00345       {}
00346 
00347       /* Copy constructor */
00348       matrix_forward_iterator (const self &mi)
00349         : Base (mi)
00350       {}
00351 
00352       /**** EXTRA MODIFIER ****/
00353       inline self& set_end ()
00354       {
00355         Base::set_end();
00356         return *this;
00357       }
00358 
00359       /**** FORWARD ITERATOR FACILITIES ****/
00360 
00361       /* We have to override a lot of these to get return values
00362        * right.*/
00363       inline self& operator= (const self& mi)
00364       {
00365         pos_ = mi.pos_;
00366         matrix_ = mi.matrix_;
00367 
00368         if (M_STYLE != Concrete || M_ORDER != ORDER) {
00369           offset_ = mi.offset_;
00370           lead_length_ = mi.lead_length_;
00371           lead_inc_ = mi.lead_inc_;
00372           trail_inc_ = mi.trail_inc_;
00373           vend_ = mi.vend_;
00374           jump_ = mi.jump_;
00375         }
00376 #if SCYTHE_DEBUG > 2
00377         size_ = mi.size_;
00378         start_ = mi.start_;
00379 #endif
00380 
00381         return *this;
00382       }
00383 
00384       inline reference operator* () const
00385       {
00386         SCYTHE_ITER_CHECK_BOUNDS();
00387         return *pos_;
00388       }
00389 
00390       inline pointer operator-> () const
00391       {
00392         SCYTHE_ITER_CHECK_BOUNDS();
00393         return pos_;
00394       }
00395 
00396       inline self& operator++ ()
00397       {
00398         Base::operator++();
00399         return *this;
00400       }
00401 
00402       inline self operator++ (int)
00403       {
00404         self tmp = *this;
00405         ++(*this);
00406         return tmp;
00407       }
00408 
00409     private:
00410       /* Get handles to base members.  It boggles the mind */
00411       using Base::pos_;
00412       using Base::vend_;
00413       using Base::offset_;
00414       using Base::lead_length_;
00415       using Base::lead_inc_;
00416       using Base::trail_inc_;
00417       using Base::jump_;
00418       using Base::matrix_;
00419 #if SCYTHE_DEBUG > 2
00420       using Base::size_;
00421       using Base::start_;
00422 #endif
00423   };
00424 
00425 } // namespace scythe
00426 
00427 #endif /* SCYTHE_MATRIX_ITERATOR_H */