Scythe-1.0.3
|
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 */