00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00035 #ifndef SCYTHE_MATRIX_BIDIRECTIONAL_ITERATOR_H
00036 #define SCYTHE_MATRIX_BIDIRECTIONAL_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
00052 namespace {
00053 typedef unsigned int uint;
00054 }
00055
00056
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_bidirectional_iterator
00077 : public std::iterator<std::bidirectional_iterator_tag, T_type>
00078 {
00079 public:
00080
00081 typedef const_matrix_bidirectional_iterator<T_type, ORDER,
00082 M_ORDER, M_STYLE> self;
00083
00084
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
00096
00097
00098 const_matrix_bidirectional_iterator ()
00099 {}
00100
00101
00102 const_matrix_bidirectional_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
00111
00112
00113
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 vbegin_ = pos_;
00132 }
00133 #if SCYTHE_DEBUG > 2
00134 size_ = M.size();
00135 start_ = pos_;
00136 #endif
00137
00138 }
00139
00140
00141 const_matrix_bidirectional_iterator (const self &mi)
00142 : pos_ (mi.pos_),
00143 matrix_ (mi.matrix_)
00144 {
00145 if (M_STYLE != Concrete || M_ORDER != ORDER) {
00146 offset_ = mi.offset_;
00147 lead_length_ = mi.lead_length_;
00148 lead_inc_ = mi.lead_inc_;
00149 trail_inc_ = mi.trail_inc_;
00150 vend_ = mi.vend_;
00151 vbegin_ = mi.vbegin_;
00152 jump_ = mi.jump_;
00153 }
00154
00155 #if SCYTHE_DEBUG > 2
00156 size_ = mi.size_;
00157 start_ = mi.start_;
00158 #endif
00159 }
00160
00161
00162
00163
00164
00165
00166 inline self& set_end ()
00167 {
00168 if (M_STYLE == Concrete && ORDER == M_ORDER) {
00169 pos_ = matrix_->getArray() + matrix_->size();
00170 } else {
00171 if (ORDER == Col) {
00172 vbegin_ += trail_inc_ * matrix_->cols();
00173 vend_ += trail_inc_ * matrix_->cols();
00174 } else {
00175 vbegin_ += trail_inc_ * matrix_->rows();
00176 vend_ += trail_inc_ * matrix_->rows();
00177 }
00178
00179 pos_ = vbegin_;
00180 offset_ = matrix_->size();
00181 }
00182
00183 return *this;
00184 }
00185
00186
00187
00188 inline self& operator= (const self& mi)
00189 {
00190 pos_ = mi.pos_;
00191 matrix_ = mi.matrix_;
00192
00193 if (M_STYLE != Concrete || M_ORDER != ORDER) {
00194 offset_ = mi.offset_;
00195 lead_length_ = mi.lead_length_;
00196 lead_inc_ = mi.lead_inc_;
00197 trail_inc_ = mi.trail_inc_;
00198 vend_ = mi.vend_;
00199 vbegin_ = mi.vbegin_;
00200 jump_ = mi.jump_;
00201 }
00202 #if SCYTHE_DEBUG > 2
00203 size_ = mi.size_;
00204 start_ = mi.start_;
00205 #endif
00206
00207 return *this;
00208 }
00209
00210 inline const reference operator* () const
00211 {
00212 SCYTHE_ITER_CHECK_BOUNDS();
00213 return *pos_;
00214 }
00215
00216 inline const pointer operator-> () const
00217 {
00218 SCYTHE_ITER_CHECK_BOUNDS();
00219 return pos_;
00220 }
00221
00222 inline self& operator++ ()
00223 {
00224 if (M_STYLE == Concrete && ORDER == M_ORDER)
00225 ++pos_;
00226 else {
00227 if (pos_ == vend_) {
00228 vend_ += trail_inc_;
00229 vbegin_ += trail_inc_;
00230 pos_ += jump_;
00231 } else {
00232 pos_ += lead_inc_;
00233 }
00234 ++offset_;
00235 }
00236
00237 return *this;
00238 }
00239
00240 inline self operator++ (int)
00241 {
00242 self tmp = *this;
00243 ++(*this);
00244 return tmp;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 inline bool operator== (const self& x) const
00261 {
00262 if (M_STYLE == Concrete && ORDER == M_ORDER) {
00263 return pos_ == x.pos_;
00264 } else {
00265 return offset_ == x.offset_;
00266 }
00267 }
00268
00269
00270
00271
00272
00273 inline bool operator!= (const self &x) const
00274 {
00275 return !(*this == x);
00276 }
00277
00278
00279 inline self& operator-- ()
00280 {
00281 if (M_STYLE == Concrete && ORDER == M_ORDER)
00282 --pos_;
00283 else {
00284 if (pos_ == vbegin_) {
00285 vend_ -= trail_inc_;
00286 vbegin_ -= trail_inc_;
00287 pos_ -= jump_;
00288 } else {
00289 pos_ -= lead_inc_;
00290 }
00291 --offset_;
00292 }
00293
00294 return *this;
00295 }
00296
00297 inline self operator-- (int)
00298 {
00299 self tmp = *this;
00300 --(*this);
00301 return tmp;
00302 }
00303
00304 protected:
00305
00306
00307 T_type* pos_;
00308 T_type *vend_;
00309 T_type *vbegin_;
00310
00311 uint offset_;
00312
00313
00314 int lead_length_;
00315 int lead_inc_;
00316 int trail_inc_;
00317 int jump_;
00318
00319
00320 const Matrix<T_type, M_ORDER, M_STYLE>* matrix_;
00321
00322 #if SCYTHE_DEBUG > 2
00323 uint size_;
00324 T_type* start_;
00325 #endif
00326 };
00327
00342 template <typename T_type, matrix_order ORDER, matrix_order M_ORDER,
00343 matrix_style M_STYLE>
00344 class matrix_bidirectional_iterator
00345 : public const_matrix_bidirectional_iterator<T_type, ORDER,
00346 M_ORDER, M_STYLE>
00347 {
00348
00349 typedef matrix_bidirectional_iterator<T_type, ORDER, M_ORDER,
00350 M_STYLE> self;
00351 typedef const_matrix_bidirectional_iterator<T_type, ORDER,
00352 M_ORDER, M_STYLE> Base;
00353
00354 public:
00355
00356 typedef typename std::iterator_traits<Base>::value_type
00357 value_type;
00358 typedef typename std::iterator_traits<Base>::iterator_category
00359 iterator_category;
00360 typedef typename std::iterator_traits<Base>::difference_type
00361 difference_type;
00362 typedef typename std::iterator_traits<Base>::pointer pointer;
00363 typedef typename std::iterator_traits<Base>::reference reference;
00364
00365
00366
00367
00368
00369 matrix_bidirectional_iterator ()
00370 : Base ()
00371 {}
00372
00373
00374 matrix_bidirectional_iterator (const Matrix<value_type, M_ORDER,
00375 M_STYLE> &M)
00376 : Base(M)
00377 {}
00378
00379
00380 matrix_bidirectional_iterator (const self &mi)
00381 : Base (mi)
00382 {}
00383
00384
00385 inline self& set_end ()
00386 {
00387 Base::set_end();
00388 return *this;
00389 }
00390
00391
00392
00393
00394
00395 inline self& operator= (const self& mi)
00396 {
00397 pos_ = mi.pos_;
00398 matrix_ = mi.matrix_;
00399
00400 if (M_STYLE != Concrete || M_ORDER != ORDER) {
00401 offset_ = mi.offset_;
00402 lead_length_ = mi.lead_length_;
00403 lead_inc_ = mi.lead_inc_;
00404 trail_inc_ = mi.trail_inc_;
00405 vend_ = mi.vend_;
00406 vbegin_ = mi.vbegin_;
00407 jump_ = mi.jump_;
00408 }
00409 #if SCYTHE_DEBUG > 2
00410 size_ = mi.size_;
00411 start_ = mi.start_;
00412 #endif
00413
00414 return *this;
00415 }
00416
00417 inline reference operator* () const
00418 {
00419 SCYTHE_ITER_CHECK_BOUNDS();
00420 return *pos_;
00421 }
00422
00423 inline pointer operator-> () const
00424 {
00425 SCYTHE_ITER_CHECK_BOUNDS();
00426 return pos_;
00427 }
00428
00429 inline self& operator++ ()
00430 {
00431 Base::operator++();
00432 return *this;
00433 }
00434
00435 inline self operator++ (int)
00436 {
00437 self tmp = *this;
00438 ++(*this);
00439 return tmp;
00440 }
00441
00442 inline self& operator-- ()
00443 {
00444 Base::operator--();
00445 return *this;
00446 }
00447
00448 inline self operator-- (int)
00449 {
00450 self tmp = *this;
00451 --(*this);
00452 return tmp;
00453 }
00454
00455 private:
00456
00457 using Base::pos_;
00458 using Base::vend_;
00459 using Base::vbegin_;
00460 using Base::offset_;
00461 using Base::lead_length_;
00462 using Base::lead_inc_;
00463 using Base::trail_inc_;
00464 using Base::jump_;
00465 using Base::matrix_;
00466 #if SCYTHE_DEBUG > 2
00467 using Base::size_;
00468 using Base::start_;
00469 #endif
00470 };
00471
00472 }
00473
00474 #endif