00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00035 #ifndef SCYTHE_MATRIX_RANDOM_ACCESS_ITERATOR_H
00036 #define SCYTHE_MATRIX_RANDOM_ACCESS_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
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 namespace scythe {
00071
00072 namespace {
00073 typedef unsigned int uint;
00074 }
00075
00076
00077 template <typename T_type, matrix_order ORDER, matrix_style STYLE>
00078 class Matrix;
00079
00094 template <typename T_type, matrix_order ORDER, matrix_order M_ORDER,
00095 matrix_style M_STYLE>
00096 class const_matrix_random_access_iterator
00097 : public std::iterator<std::random_access_iterator_tag, T_type>
00098 {
00099 public:
00100
00101 typedef const_matrix_random_access_iterator<T_type, ORDER,
00102 M_ORDER, M_STYLE> self;
00103
00104
00105 typedef typename std::iterator_traits<self>::value_type
00106 value_type;
00107 typedef typename std::iterator_traits<self>::iterator_category
00108 iterator_category;
00109 typedef typename std::iterator_traits<self>::difference_type
00110 difference_type;
00111 typedef typename std::iterator_traits<self>::pointer pointer;
00112 typedef typename std::iterator_traits<self>::reference reference;
00113
00114
00115
00116
00117
00118 const_matrix_random_access_iterator ()
00119 {}
00120
00121
00122 const_matrix_random_access_iterator
00123 ( const Matrix<value_type, M_ORDER, M_STYLE> &M)
00124 : start_ (M.getArray())
00125 {
00126 SCYTHE_CHECK_30 (start_ == 0, scythe_null_error,
00127 "Requesting iterator to NULL matrix");
00128 pos_ = start_;
00129
00130
00131
00132
00133
00134
00135
00136 if (M_STYLE != Concrete || M_ORDER != ORDER) {
00137 offset_ = 0;
00138
00139 if (ORDER == Col) {
00140 lead_length_ = M.rows();
00141 lead_inc_ = M.rowstride();
00142 trail_inc_ = M.colstride();
00143 } else {
00144 lead_length_ = M.cols();
00145 lead_inc_ = M.colstride();
00146 trail_inc_ = M.rowstride();
00147 }
00148 jump_ = trail_inc_ + (1 - lead_length_) * lead_inc_;
00149 }
00150
00151 #if SCYTHE_DEBUG > 2
00152 size_ = M.size();
00153 #endif
00154 }
00155
00156
00157 const_matrix_random_access_iterator (const self &mi)
00158 : start_ (mi.start_),
00159 pos_ (mi.pos_)
00160 {
00161 if (M_STYLE != Concrete || M_ORDER != ORDER) {
00162 offset_ = mi.offset_;
00163 lead_length_ = mi.lead_length_;
00164 lead_inc_ = mi.lead_inc_;
00165 trail_inc_ = mi.trail_inc_;
00166 jump_ = mi.jump_;
00167 }
00168 #if SCYTHE_DEBUG > 2
00169 size_ = mi.size_;
00170 #endif
00171 }
00172
00173
00174
00175 inline self& operator= (const self& mi)
00176 {
00177 start_ = mi.start_;
00178 pos_ = mi.pos_;
00179
00180 if (M_STYLE != Concrete || M_ORDER != ORDER) {
00181 offset_ = mi.offset_;
00182 lead_length_ = mi.lead_length_;
00183 lead_inc_ = mi.lead_inc_;
00184 trail_inc_ = mi.trail_inc_;
00185 jump_ = mi.jump_;
00186 }
00187 #if SCYTHE_DEBUG > 2
00188 size_ = mi.size_;
00189 #endif
00190
00191 return *this;
00192 }
00193
00194 inline const reference operator* () const
00195 {
00196 SCYTHE_ITER_CHECK_BOUNDS();
00197 return *pos_;
00198 }
00199
00200 inline const pointer operator-> () const
00201 {
00202 SCYTHE_ITER_CHECK_BOUNDS();
00203 return pos_;
00204 }
00205
00206 inline self& operator++ ()
00207 {
00208 if (M_STYLE == Concrete && ORDER == M_ORDER)
00209 ++pos_;
00210 else if (++offset_ % lead_length_ == 0)
00211 pos_ += jump_;
00212 else
00213 pos_ += lead_inc_;
00214
00215 return *this;
00216 }
00217
00218 inline self operator++ (int)
00219 {
00220 self tmp = *this;
00221 ++(*this);
00222 return tmp;
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 inline bool operator== (const self& x) const
00239 {
00240 if (M_STYLE == Concrete && ORDER == M_ORDER) {
00241 return pos_ == x.pos_;
00242 } else {
00243 return offset_ == x.offset_;
00244 }
00245 }
00246
00247
00248
00249
00250
00251 inline bool operator!= (const self &x) const
00252 {
00253 return !(*this == x);
00254 }
00255
00256
00257
00258 inline self& operator-- ()
00259 {
00260 if (M_STYLE == Concrete && ORDER == M_ORDER)
00261 --pos_;
00262 else if (offset_-- % lead_length_ == 0)
00263 pos_ -= jump_;
00264 else
00265 pos_ -= lead_inc_;
00266
00267 return *this;
00268 }
00269
00270 inline self operator-- (int)
00271 {
00272 self tmp = *this;
00273 --(*this);
00274 return tmp;
00275 }
00276
00277
00278
00279 inline const reference operator[] (difference_type n) const
00280 {
00281 if (M_STYLE == Concrete && ORDER == M_ORDER) {
00282 SCYTHE_ITER_CHECK_OFFSET_BOUNDS(start_ + n);
00283 return *(start_ + n);
00284 } else {
00285 uint trailing = n / lead_length_;
00286 uint leading = n % lead_length_;
00287
00288 T_type* place = start_ + leading * lead_inc_
00289 + trailing * trail_inc_;
00290
00291 SCYTHE_ITER_CHECK_POINTER_BOUNDS(place);
00292 return *place;
00293 }
00294 }
00295
00296 inline self& operator+= (difference_type n)
00297 {
00298 if (M_STYLE == Concrete && ORDER == M_ORDER) {
00299 pos_ += n;
00300 } else {
00301 offset_ += n;
00302 uint trailing = offset_ / lead_length_;
00303 uint leading = offset_ % lead_length_;
00304
00305 pos_ = start_ + leading * lead_inc_
00306 + trailing * trail_inc_;
00307 }
00308
00309 return *this;
00310 }
00311
00312 inline self& operator-= (difference_type n)
00313 {
00314 if (M_STYLE == Concrete && ORDER == M_ORDER) {
00315 pos_ -= n;
00316 } else {
00317 offset_ -= n;
00318 uint trailing = offset_ / lead_length_;
00319 uint leading = offset_ % lead_length_;
00320
00321 pos_ = start_ + leading * lead_inc_
00322 + trailing * trail_inc_;
00323 }
00324
00325 return *this;
00326 }
00327
00328
00329
00330 inline difference_type operator- (const self& x) const
00331 {
00332 if (M_STYLE == Concrete && ORDER == M_ORDER) {
00333 return pos_ - x.pos_;
00334 } else {
00335 return offset_ - x.offset_;
00336 }
00337 }
00338
00339 inline difference_type operator< (const self& x) const
00340 {
00341 if (M_STYLE == Concrete && ORDER == M_ORDER) {
00342 return pos_ < x.pos_;
00343 } else {
00344 return offset_ < x.offset_;
00345 }
00346 }
00347
00348 inline difference_type operator> (const self& x) const
00349 {
00350 if (M_STYLE == Concrete && ORDER == M_ORDER) {
00351 return pos_ > x.pos_;
00352 } else {
00353 return offset_ > x.offset_;
00354 }
00355 }
00356
00357 inline difference_type operator<= (const self& x) const
00358 {
00359 if (M_STYLE == Concrete && ORDER == M_ORDER) {
00360 return pos_ <= x.pos_;
00361 } else {
00362 return offset_ <= x.offset_;
00363 }
00364 }
00365
00366 inline difference_type operator>= (const self& x) const
00367 {
00368 if (M_STYLE == Concrete && ORDER == M_ORDER) {
00369 return pos_ >= x.pos_;
00370 } else {
00371 return offset_ >= x.offset_;
00372 }
00373 }
00374
00375 protected:
00376
00377
00378 T_type* start_;
00379 T_type* pos_;
00380
00381 uint offset_;
00382
00383
00384 int lead_length_;
00385 int lead_inc_;
00386 int trail_inc_;
00387 int jump_;
00388
00389
00390
00391 #if SCYTHE_DEBUG > 2
00392 uint size_;
00393 #endif
00394
00395 };
00396
00410 template <typename T_type, matrix_order ORDER, matrix_order M_ORDER,
00411 matrix_style M_STYLE>
00412 class matrix_random_access_iterator
00413 : public const_matrix_random_access_iterator<T_type, ORDER,
00414 M_ORDER, M_STYLE>
00415 {
00416
00417 typedef matrix_random_access_iterator<T_type, ORDER, M_ORDER,
00418 M_STYLE> self;
00419 typedef const_matrix_random_access_iterator<T_type, ORDER,
00420 M_ORDER, M_STYLE> Base;
00421
00422 public:
00423
00424 typedef typename std::iterator_traits<Base>::value_type
00425 value_type;
00426 typedef typename std::iterator_traits<Base>::iterator_category
00427 iterator_category;
00428 typedef typename std::iterator_traits<Base>::difference_type
00429 difference_type;
00430 typedef typename std::iterator_traits<Base>::pointer pointer;
00431 typedef typename std::iterator_traits<Base>::reference reference;
00432
00433
00434
00435
00436
00437 matrix_random_access_iterator ()
00438 : Base ()
00439 {}
00440
00441
00442 matrix_random_access_iterator (const Matrix<value_type, M_ORDER,
00443 M_STYLE> &M)
00444 : Base(M)
00445 {}
00446
00447
00448 matrix_random_access_iterator (const self &mi)
00449 : Base (mi)
00450 {}
00451
00452
00453
00454
00455
00456 inline self& operator= (const self& mi)
00457 {
00458 start_ = mi.start_;
00459 pos_ = mi.pos_;
00460
00461 if (M_STYLE != Concrete || M_ORDER != ORDER) {
00462 offset_ = mi.offset_;
00463 lead_length_ = mi.lead_length_;
00464 lead_inc_ = mi.lead_inc_;
00465 trail_inc_ = mi.trail_inc_;
00466 jump_ = mi.jump_;
00467 }
00468 #if SCYTHE_DEBUG > 2
00469 size_ = mi.size_;
00470 #endif
00471
00472 return *this;
00473 }
00474
00475 inline reference operator* () const
00476 {
00477 SCYTHE_ITER_CHECK_BOUNDS();
00478 return *pos_;
00479 }
00480
00481 inline pointer operator-> () const
00482 {
00483 SCYTHE_ITER_CHECK_BOUNDS();
00484 return pos_;
00485 }
00486
00487 inline self& operator++ ()
00488 {
00489 Base::operator++();
00490 return *this;
00491 }
00492
00493 inline self operator++ (int)
00494 {
00495 self tmp = *this;
00496 ++(*this);
00497 return tmp;
00498 }
00499
00500
00501
00502 inline self& operator-- ()
00503 {
00504 Base::operator--();
00505 return *this;
00506 }
00507
00508 inline self operator-- (int)
00509 {
00510 self tmp = *this;
00511 --(*this);
00512 return tmp;
00513 }
00514
00515
00516
00517 inline reference operator[] (difference_type n) const
00518 {
00519 if (M_STYLE == Concrete && ORDER == M_ORDER) {
00520 SCYTHE_ITER_CHECK_POINTER_BOUNDS(start_ + n);
00521 return *(start_ + n);
00522 } else {
00523 uint trailing = n / lead_length_;
00524 uint leading = n % lead_length_;
00525
00526 T_type* place = start_ + leading * lead_inc_
00527 + trailing * trail_inc_;
00528
00529 SCYTHE_ITER_CHECK_POINTER_BOUNDS(place);
00530 return *place;
00531 }
00532 }
00533
00534 inline self& operator+= (difference_type n)
00535 {
00536 Base::operator+=(n);
00537 return *this;
00538 }
00539
00540 inline self& operator-= (difference_type n)
00541 {
00542 Base::operator-= (n);
00543 return *this;
00544 }
00545
00546
00547
00548 private:
00549
00550 using Base::start_;
00551 using Base::pos_;
00552 using Base::offset_;
00553 using Base::lead_length_;
00554 using Base::lead_inc_;
00555 using Base::trail_inc_;
00556 using Base::jump_;
00557 #if SCYTHE_DEBUG > 2
00558 using Base::size_;
00559 #endif
00560 };
00561
00562 template <class T_type, matrix_order ORDER, matrix_order M_ORDER,
00563 matrix_style STYLE>
00564 inline
00565 const_matrix_random_access_iterator<T_type, ORDER, M_ORDER, STYLE>
00566 operator+ (const_matrix_random_access_iterator<T_type, ORDER, M_ORDER, STYLE> x, int n)
00567 {
00568 x += n;
00569 return x;
00570 }
00571
00572 template <class T_type, matrix_order ORDER, matrix_order M_ORDER,
00573 matrix_style STYLE>
00574 inline
00575 const_matrix_random_access_iterator<T_type, ORDER, M_ORDER, STYLE>
00576 operator+ (int n, const_matrix_random_access_iterator<T_type, ORDER,
00577 M_ORDER,
00578 STYLE> x)
00579 {
00580 x += n;
00581 return x;
00582 }
00583
00584 template <class T_type, matrix_order ORDER, matrix_order M_ORDER,
00585 matrix_style STYLE>
00586 inline
00587 const_matrix_random_access_iterator<T_type, ORDER, M_ORDER, STYLE>
00588 operator- (const_matrix_random_access_iterator<T_type, ORDER, M_ORDER, STYLE> x, int n)
00589 {
00590 x -= n;
00591 return x;
00592 }
00593
00594 template <class T_type, matrix_order ORDER, matrix_order M_ORDER,
00595 matrix_style STYLE>
00596 inline matrix_random_access_iterator<T_type, ORDER, M_ORDER, STYLE>
00597 operator+ (matrix_random_access_iterator<T_type, ORDER, M_ORDER,
00598 STYLE> x, int n)
00599 {
00600 x += n;
00601 return x;
00602 }
00603
00604 template <class T_type, matrix_order ORDER, matrix_order M_ORDER,
00605 matrix_style STYLE>
00606 inline matrix_random_access_iterator<T_type, ORDER, M_ORDER, STYLE>
00607 operator+ (int n, matrix_random_access_iterator<T_type, ORDER,
00608 M_ORDER, STYLE> x)
00609 {
00610 x += n;
00611 return x;
00612 }
00613
00614 template <class T_type, matrix_order ORDER, matrix_order M_ORDER,
00615 matrix_style STYLE>
00616 inline matrix_random_access_iterator<T_type, ORDER, M_ORDER, STYLE>
00617 operator- (matrix_random_access_iterator<T_type, ORDER, M_ORDER,
00618 STYLE> x, int n)
00619 {
00620 x -= n;
00621 return x;
00622 }
00623
00624 }
00625
00626 #endif