1 // 2 // Copyright (c) 2000-2002 3 // Joerg Walter, Mathias Koch 4 // 5 // Distributed under the Boost Software License, Version 1.0. (See 6 // accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 // 9 // The authors gratefully acknowledge the support of 10 // GeNeSys mbH & Co. KG in producing this work. 11 // 12 13 #ifndef _BOOST_UBLAS_ITERATOR_ 14 #define _BOOST_UBLAS_ITERATOR_ 15 16 #include <boost/numeric/ublas/exception.hpp> 17 #include <iterator> 18 19 20 namespace boost { namespace numeric { namespace ublas { 21 22 /** \brief Base class of all proxy classes that contain 23 * a (redirectable) reference to an immutable object. 24 * 25 * \param C the type of the container referred to 26 */ 27 template<class C> 28 class container_const_reference: 29 private nonassignable { 30 public: 31 typedef C container_type; 32 33 BOOST_UBLAS_INLINE container_const_reference()34 container_const_reference (): 35 c_ (0) {} 36 BOOST_UBLAS_INLINE container_const_reference(const container_type & c)37 container_const_reference (const container_type &c): 38 c_ (&c) {} 39 40 BOOST_UBLAS_INLINE operator ()() const41 const container_type &operator () () const { 42 return *c_; 43 } 44 45 BOOST_UBLAS_INLINE assign(const container_type * c)46 container_const_reference &assign (const container_type *c) { 47 c_ = c; 48 return *this; 49 } 50 51 // Closure comparison 52 BOOST_UBLAS_INLINE same_closure(const container_const_reference & cr) const53 bool same_closure (const container_const_reference &cr) const { 54 return c_ == cr.c_; 55 } 56 57 private: 58 const container_type *c_; 59 }; 60 61 /** \brief Base class of all proxy classes that contain 62 * a (redirectable) reference to a mutable object. 63 * 64 * \param C the type of the container referred to 65 */ 66 template<class C> 67 class container_reference: 68 private nonassignable { 69 public: 70 typedef C container_type; 71 72 BOOST_UBLAS_INLINE container_reference()73 container_reference (): 74 c_ (0) {} 75 BOOST_UBLAS_INLINE container_reference(container_type & c)76 container_reference (container_type &c): 77 c_ (&c) {} 78 79 BOOST_UBLAS_INLINE operator ()() const80 container_type &operator () () const { 81 return *c_; 82 } 83 84 BOOST_UBLAS_INLINE assign(container_type * c)85 container_reference &assign (container_type *c) { 86 c_ = c; 87 return *this; 88 } 89 90 // Closure comparison 91 BOOST_UBLAS_INLINE same_closure(const container_reference & cr) const92 bool same_closure (const container_reference &cr) const { 93 return c_ == cr.c_; 94 } 95 96 private: 97 container_type *c_; 98 }; 99 100 /** \brief Base class of all forward iterators. 101 * 102 * \param IC the iterator category 103 * \param I the derived iterator type 104 * \param T the value type 105 * 106 * The forward iterator can only proceed in one direction 107 * via the post increment operator. 108 */ 109 template<class IC, class I, class T> 110 struct forward_iterator_base: 111 public std::iterator<IC, T> { 112 typedef I derived_iterator_type; 113 typedef T derived_value_type; 114 115 // Arithmetic 116 BOOST_UBLAS_INLINE operator ++boost::numeric::ublas::forward_iterator_base117 derived_iterator_type operator ++ (int) { 118 derived_iterator_type &d (*static_cast<const derived_iterator_type *> (this)); 119 derived_iterator_type tmp (d); 120 ++ d; 121 return tmp; 122 } 123 BOOST_UBLAS_INLINE operator ++(derived_iterator_type & d,int)124 friend derived_iterator_type operator ++ (derived_iterator_type &d, int) { 125 derived_iterator_type tmp (d); 126 ++ d; 127 return tmp; 128 } 129 130 // Comparison 131 BOOST_UBLAS_INLINE operator !=boost::numeric::ublas::forward_iterator_base132 bool operator != (const derived_iterator_type &it) const { 133 const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this); 134 return ! (*d == it); 135 } 136 }; 137 138 /** \brief Base class of all bidirectional iterators. 139 * 140 * \param IC the iterator category 141 * \param I the derived iterator type 142 * \param T the value type 143 * 144 * The bidirectional iterator can proceed in both directions 145 * via the post increment and post decrement operator. 146 */ 147 template<class IC, class I, class T> 148 struct bidirectional_iterator_base: 149 public std::iterator<IC, T> { 150 typedef I derived_iterator_type; 151 typedef T derived_value_type; 152 153 // Arithmetic 154 BOOST_UBLAS_INLINE operator ++boost::numeric::ublas::bidirectional_iterator_base155 derived_iterator_type operator ++ (int) { 156 derived_iterator_type &d (*static_cast<const derived_iterator_type *> (this)); 157 derived_iterator_type tmp (d); 158 ++ d; 159 return tmp; 160 } 161 BOOST_UBLAS_INLINE operator ++(derived_iterator_type & d,int)162 friend derived_iterator_type operator ++ (derived_iterator_type &d, int) { 163 derived_iterator_type tmp (d); 164 ++ d; 165 return tmp; 166 } 167 BOOST_UBLAS_INLINE operator --boost::numeric::ublas::bidirectional_iterator_base168 derived_iterator_type operator -- (int) { 169 derived_iterator_type &d (*static_cast<const derived_iterator_type *> (this)); 170 derived_iterator_type tmp (d); 171 -- d; 172 return tmp; 173 } 174 BOOST_UBLAS_INLINE operator --(derived_iterator_type & d,int)175 friend derived_iterator_type operator -- (derived_iterator_type &d, int) { 176 derived_iterator_type tmp (d); 177 -- d; 178 return tmp; 179 } 180 181 // Comparison 182 BOOST_UBLAS_INLINE operator !=boost::numeric::ublas::bidirectional_iterator_base183 bool operator != (const derived_iterator_type &it) const { 184 const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this); 185 return ! (*d == it); 186 } 187 }; 188 189 /** \brief Base class of all random access iterators. 190 * 191 * \param IC the iterator category 192 * \param I the derived iterator type 193 * \param T the value type 194 * \param D the difference type, default: std::ptrdiff_t 195 * 196 * The random access iterator can proceed in both directions 197 * via the post increment/decrement operator or in larger steps 198 * via the +, - and +=, -= operators. The random access iterator 199 * is LessThan Comparable. 200 */ 201 template<class IC, class I, class T, class D = std::ptrdiff_t> 202 // ISSUE the default for D seems rather dangerous as it can easily be (silently) incorrect 203 struct random_access_iterator_base: 204 public std::iterator<IC, T> { 205 typedef I derived_iterator_type; 206 typedef T derived_value_type; 207 typedef D derived_difference_type; 208 209 /* FIXME Need to explicitly pass derived_reference_type as otherwise I undefined type or forward declared 210 typedef typename derived_iterator_type::reference derived_reference_type; 211 // Indexed element 212 BOOST_UBLAS_INLINE 213 derived_reference_type operator [] (derived_difference_type n) { 214 return *(*this + n); 215 } 216 */ 217 218 // Arithmetic 219 BOOST_UBLAS_INLINE operator ++boost::numeric::ublas::random_access_iterator_base220 derived_iterator_type operator ++ (int) { 221 derived_iterator_type &d (*static_cast<derived_iterator_type *> (this)); 222 derived_iterator_type tmp (d); 223 ++ d; 224 return tmp; 225 } 226 BOOST_UBLAS_INLINE operator ++(derived_iterator_type & d,int)227 friend derived_iterator_type operator ++ (derived_iterator_type &d, int) { 228 derived_iterator_type tmp (d); 229 ++ d; 230 return tmp; 231 } 232 BOOST_UBLAS_INLINE operator --boost::numeric::ublas::random_access_iterator_base233 derived_iterator_type operator -- (int) { 234 derived_iterator_type &d (*static_cast<derived_iterator_type *> (this)); 235 derived_iterator_type tmp (d); 236 -- d; 237 return tmp; 238 } 239 BOOST_UBLAS_INLINE operator --(derived_iterator_type & d,int)240 friend derived_iterator_type operator -- (derived_iterator_type &d, int) { 241 derived_iterator_type tmp (d); 242 -- d; 243 return tmp; 244 } 245 BOOST_UBLAS_INLINE operator +boost::numeric::ublas::random_access_iterator_base246 derived_iterator_type operator + (derived_difference_type n) const { 247 derived_iterator_type tmp (*static_cast<const derived_iterator_type *> (this)); 248 return tmp += n; 249 } 250 BOOST_UBLAS_INLINE operator +(const derived_iterator_type & d,derived_difference_type n)251 friend derived_iterator_type operator + (const derived_iterator_type &d, derived_difference_type n) { 252 derived_iterator_type tmp (d); 253 return tmp += n; 254 } 255 BOOST_UBLAS_INLINE operator +(derived_difference_type n,const derived_iterator_type & d)256 friend derived_iterator_type operator + (derived_difference_type n, const derived_iterator_type &d) { 257 derived_iterator_type tmp (d); 258 return tmp += n; 259 } 260 BOOST_UBLAS_INLINE operator -boost::numeric::ublas::random_access_iterator_base261 derived_iterator_type operator - (derived_difference_type n) const { 262 derived_iterator_type tmp (*static_cast<const derived_iterator_type *> (this)); 263 return tmp -= n; 264 } 265 BOOST_UBLAS_INLINE operator -(const derived_iterator_type & d,derived_difference_type n)266 friend derived_iterator_type operator - (const derived_iterator_type &d, derived_difference_type n) { 267 derived_iterator_type tmp (d); 268 return tmp -= n; 269 } 270 271 // Comparison 272 BOOST_UBLAS_INLINE operator !=boost::numeric::ublas::random_access_iterator_base273 bool operator != (const derived_iterator_type &it) const { 274 const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this); 275 return ! (*d == it); 276 } 277 BOOST_UBLAS_INLINE operator <=boost::numeric::ublas::random_access_iterator_base278 bool operator <= (const derived_iterator_type &it) const { 279 const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this); 280 return ! (it < *d); 281 } 282 BOOST_UBLAS_INLINE operator >=boost::numeric::ublas::random_access_iterator_base283 bool operator >= (const derived_iterator_type &it) const { 284 const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this); 285 return ! (*d < it); 286 } 287 BOOST_UBLAS_INLINE operator >boost::numeric::ublas::random_access_iterator_base288 bool operator > (const derived_iterator_type &it) const { 289 const derived_iterator_type *d = static_cast<const derived_iterator_type *> (this); 290 return it < *d; 291 } 292 }; 293 294 /** \brief Base class of all reverse iterators. (non-MSVC version) 295 * 296 * \param I the derived iterator type 297 * \param T the value type 298 * \param R the reference type 299 * 300 * The reverse iterator implements a bidirectional iterator 301 * reversing the elements of the underlying iterator. It 302 * implements most operators of a random access iterator. 303 * 304 * uBLAS extension: it.index() 305 */ 306 307 // Renamed this class from reverse_iterator to get 308 // typedef reverse_iterator<...> reverse_iterator 309 // working. Thanks to Gabriel Dos Reis for explaining this. 310 template <class I> 311 class reverse_iterator_base: 312 public std::reverse_iterator<I> { 313 public: 314 typedef typename I::container_type container_type; 315 typedef typename container_type::size_type size_type; 316 typedef typename I::difference_type difference_type; 317 typedef I iterator_type; 318 319 // Construction and destruction 320 BOOST_UBLAS_INLINE reverse_iterator_base()321 reverse_iterator_base (): 322 std::reverse_iterator<iterator_type> () {} 323 BOOST_UBLAS_INLINE reverse_iterator_base(const iterator_type & it)324 reverse_iterator_base (const iterator_type &it): 325 std::reverse_iterator<iterator_type> (it) {} 326 327 // Arithmetic 328 BOOST_UBLAS_INLINE operator ++()329 reverse_iterator_base &operator ++ () { 330 return *this = -- this->base (); 331 } 332 BOOST_UBLAS_INLINE operator ++(int)333 reverse_iterator_base operator ++ (int) { 334 reverse_iterator_base tmp (*this); 335 *this = -- this->base (); 336 return tmp; 337 } 338 BOOST_UBLAS_INLINE operator --()339 reverse_iterator_base &operator -- () { 340 return *this = ++ this->base (); 341 } 342 BOOST_UBLAS_INLINE operator --(int)343 reverse_iterator_base operator -- (int) { 344 reverse_iterator_base tmp (*this); 345 *this = ++ this->base (); 346 return tmp; 347 } 348 BOOST_UBLAS_INLINE operator +=(difference_type n)349 reverse_iterator_base &operator += (difference_type n) { 350 return *this = this->base () - n; 351 } 352 BOOST_UBLAS_INLINE operator -=(difference_type n)353 reverse_iterator_base &operator -= (difference_type n) { 354 return *this = this->base () + n; 355 } 356 357 BOOST_UBLAS_INLINE operator +(const reverse_iterator_base & it,difference_type n)358 friend reverse_iterator_base operator + (const reverse_iterator_base &it, difference_type n) { 359 reverse_iterator_base tmp (it); 360 return tmp += n; 361 } 362 BOOST_UBLAS_INLINE operator +(difference_type n,const reverse_iterator_base & it)363 friend reverse_iterator_base operator + (difference_type n, const reverse_iterator_base &it) { 364 reverse_iterator_base tmp (it); 365 return tmp += n; 366 } 367 BOOST_UBLAS_INLINE operator -(const reverse_iterator_base & it,difference_type n)368 friend reverse_iterator_base operator - (const reverse_iterator_base &it, difference_type n) { 369 reverse_iterator_base tmp (it); 370 return tmp -= n; 371 } 372 BOOST_UBLAS_INLINE operator -(const reverse_iterator_base & it1,const reverse_iterator_base & it2)373 friend difference_type operator - (const reverse_iterator_base &it1, const reverse_iterator_base &it2) { 374 return it2.base () - it1.base (); 375 } 376 377 BOOST_UBLAS_INLINE operator ()() const378 const container_type &operator () () const { 379 return this->base () (); 380 } 381 382 BOOST_UBLAS_INLINE index() const383 size_type index () const { 384 iterator_type tmp (this->base ()); 385 return (-- tmp).index (); 386 } 387 }; 388 389 /** \brief 1st base class of all matrix reverse iterators. (non-MSVC version) 390 * 391 * \param I the derived iterator type 392 * 393 * The reverse iterator implements a bidirectional iterator 394 * reversing the elements of the underlying iterator. It 395 * implements most operators of a random access iterator. 396 * 397 * uBLAS extension: it.index1(), it.index2() and access to 398 * the dual iterator via begin(), end(), rbegin(), rend() 399 */ 400 401 // Renamed this class from reverse_iterator1 to get 402 // typedef reverse_iterator1<...> reverse_iterator1 403 // working. Thanks to Gabriel Dos Reis for explaining this. 404 template <class I> 405 class reverse_iterator_base1: 406 public std::reverse_iterator<I> { 407 public: 408 typedef typename I::container_type container_type; 409 typedef typename container_type::size_type size_type; 410 typedef typename I::difference_type difference_type; 411 typedef I iterator_type; 412 typedef typename I::dual_iterator_type dual_iterator_type; 413 typedef typename I::dual_reverse_iterator_type dual_reverse_iterator_type; 414 415 // Construction and destruction 416 BOOST_UBLAS_INLINE reverse_iterator_base1()417 reverse_iterator_base1 (): 418 std::reverse_iterator<iterator_type> () {} 419 BOOST_UBLAS_INLINE reverse_iterator_base1(const iterator_type & it)420 reverse_iterator_base1 (const iterator_type &it): 421 std::reverse_iterator<iterator_type> (it) {} 422 423 // Arithmetic 424 BOOST_UBLAS_INLINE operator ++()425 reverse_iterator_base1 &operator ++ () { 426 return *this = -- this->base (); 427 } 428 BOOST_UBLAS_INLINE operator ++(int)429 reverse_iterator_base1 operator ++ (int) { 430 reverse_iterator_base1 tmp (*this); 431 *this = -- this->base (); 432 return tmp; 433 } 434 BOOST_UBLAS_INLINE operator --()435 reverse_iterator_base1 &operator -- () { 436 return *this = ++ this->base (); 437 } 438 BOOST_UBLAS_INLINE operator --(int)439 reverse_iterator_base1 operator -- (int) { 440 reverse_iterator_base1 tmp (*this); 441 *this = ++ this->base (); 442 return tmp; 443 } 444 BOOST_UBLAS_INLINE operator +=(difference_type n)445 reverse_iterator_base1 &operator += (difference_type n) { 446 return *this = this->base () - n; 447 } 448 BOOST_UBLAS_INLINE operator -=(difference_type n)449 reverse_iterator_base1 &operator -= (difference_type n) { 450 return *this = this->base () + n; 451 } 452 453 BOOST_UBLAS_INLINE operator +(const reverse_iterator_base1 & it,difference_type n)454 friend reverse_iterator_base1 operator + (const reverse_iterator_base1 &it, difference_type n) { 455 reverse_iterator_base1 tmp (it); 456 return tmp += n; 457 } 458 BOOST_UBLAS_INLINE operator +(difference_type n,const reverse_iterator_base1 & it)459 friend reverse_iterator_base1 operator + (difference_type n, const reverse_iterator_base1 &it) { 460 reverse_iterator_base1 tmp (it); 461 return tmp += n; 462 } 463 BOOST_UBLAS_INLINE operator -(const reverse_iterator_base1 & it,difference_type n)464 friend reverse_iterator_base1 operator - (const reverse_iterator_base1 &it, difference_type n) { 465 reverse_iterator_base1 tmp (it); 466 return tmp -= n; 467 } 468 BOOST_UBLAS_INLINE operator -(const reverse_iterator_base1 & it1,const reverse_iterator_base1 & it2)469 friend difference_type operator - (const reverse_iterator_base1 &it1, const reverse_iterator_base1 &it2) { 470 return it2.base () - it1.base (); 471 } 472 473 BOOST_UBLAS_INLINE operator ()() const474 const container_type &operator () () const { 475 return this->base () (); 476 } 477 478 BOOST_UBLAS_INLINE index1() const479 size_type index1 () const { 480 iterator_type tmp (this->base ()); 481 return (-- tmp).index1 (); 482 } 483 BOOST_UBLAS_INLINE index2() const484 size_type index2 () const { 485 iterator_type tmp (this->base ()); 486 return (-- tmp).index2 (); 487 } 488 489 BOOST_UBLAS_INLINE begin() const490 dual_iterator_type begin () const { 491 iterator_type tmp (this->base ()); 492 return (-- tmp).begin (); 493 } 494 BOOST_UBLAS_INLINE end() const495 dual_iterator_type end () const { 496 iterator_type tmp (this->base ()); 497 return (-- tmp).end (); 498 } 499 BOOST_UBLAS_INLINE rbegin() const500 dual_reverse_iterator_type rbegin () const { 501 return dual_reverse_iterator_type (end ()); 502 } 503 BOOST_UBLAS_INLINE rend() const504 dual_reverse_iterator_type rend () const { 505 return dual_reverse_iterator_type (begin ()); 506 } 507 }; 508 509 /** \brief 2nd base class of all matrix reverse iterators. (non-MSVC version) 510 * 511 * \param I the derived iterator type 512 * 513 * The reverse iterator implements a bidirectional iterator 514 * reversing the elements of the underlying iterator. It 515 * implements most operators of a random access iterator. 516 * 517 * uBLAS extension: it.index1(), it.index2() and access to 518 * the dual iterator via begin(), end(), rbegin(), rend() 519 * 520 * Note: this type is _identical_ to reverse_iterator_base1 521 */ 522 523 // Renamed this class from reverse_iterator2 to get 524 // typedef reverse_iterator2<...> reverse_iterator2 525 // working. Thanks to Gabriel Dos Reis for explaining this. 526 template <class I> 527 class reverse_iterator_base2: 528 public std::reverse_iterator<I> { 529 public: 530 typedef typename I::container_type container_type; 531 typedef typename container_type::size_type size_type; 532 typedef typename I::difference_type difference_type; 533 typedef I iterator_type; 534 typedef typename I::dual_iterator_type dual_iterator_type; 535 typedef typename I::dual_reverse_iterator_type dual_reverse_iterator_type; 536 537 // Construction and destruction 538 BOOST_UBLAS_INLINE reverse_iterator_base2()539 reverse_iterator_base2 (): 540 std::reverse_iterator<iterator_type> () {} 541 BOOST_UBLAS_INLINE reverse_iterator_base2(const iterator_type & it)542 reverse_iterator_base2 (const iterator_type &it): 543 std::reverse_iterator<iterator_type> (it) {} 544 545 // Arithmetic 546 BOOST_UBLAS_INLINE operator ++()547 reverse_iterator_base2 &operator ++ () { 548 return *this = -- this->base (); 549 } 550 BOOST_UBLAS_INLINE operator ++(int)551 reverse_iterator_base2 operator ++ (int) { 552 reverse_iterator_base2 tmp (*this); 553 *this = -- this->base (); 554 return tmp; 555 } 556 BOOST_UBLAS_INLINE operator --()557 reverse_iterator_base2 &operator -- () { 558 return *this = ++ this->base (); 559 } 560 BOOST_UBLAS_INLINE operator --(int)561 reverse_iterator_base2 operator -- (int) { 562 reverse_iterator_base2 tmp (*this); 563 *this = ++ this->base (); 564 return tmp; 565 } 566 BOOST_UBLAS_INLINE operator +=(difference_type n)567 reverse_iterator_base2 &operator += (difference_type n) { 568 return *this = this->base () - n; 569 } 570 BOOST_UBLAS_INLINE operator -=(difference_type n)571 reverse_iterator_base2 &operator -= (difference_type n) { 572 return *this = this->base () + n; 573 } 574 575 BOOST_UBLAS_INLINE operator +(const reverse_iterator_base2 & it,difference_type n)576 friend reverse_iterator_base2 operator + (const reverse_iterator_base2 &it, difference_type n) { 577 reverse_iterator_base2 tmp (it); 578 return tmp += n; 579 } 580 BOOST_UBLAS_INLINE operator +(difference_type n,const reverse_iterator_base2 & it)581 friend reverse_iterator_base2 operator + (difference_type n, const reverse_iterator_base2 &it) { 582 reverse_iterator_base2 tmp (it); 583 return tmp += n; 584 } 585 BOOST_UBLAS_INLINE operator -(const reverse_iterator_base2 & it,difference_type n)586 friend reverse_iterator_base2 operator - (const reverse_iterator_base2 &it, difference_type n) { 587 reverse_iterator_base2 tmp (it); 588 return tmp -= n; 589 } 590 BOOST_UBLAS_INLINE operator -(const reverse_iterator_base2 & it1,const reverse_iterator_base2 & it2)591 friend difference_type operator - (const reverse_iterator_base2 &it1, const reverse_iterator_base2 &it2) { 592 return it2.base () - it1.base (); 593 } 594 595 BOOST_UBLAS_INLINE operator ()() const596 const container_type &operator () () const { 597 return this->base () (); 598 } 599 600 BOOST_UBLAS_INLINE index1() const601 size_type index1 () const { 602 iterator_type tmp (this->base ()); 603 return (-- tmp).index1 (); 604 } 605 BOOST_UBLAS_INLINE index2() const606 size_type index2 () const { 607 iterator_type tmp (this->base ()); 608 return (-- tmp).index2 (); 609 } 610 611 BOOST_UBLAS_INLINE begin() const612 dual_iterator_type begin () const { 613 iterator_type tmp (this->base ()); 614 return (-- tmp).begin (); 615 } 616 BOOST_UBLAS_INLINE end() const617 dual_iterator_type end () const { 618 iterator_type tmp (this->base ()); 619 return (-- tmp).end (); 620 } 621 BOOST_UBLAS_INLINE rbegin() const622 dual_reverse_iterator_type rbegin () const { 623 return dual_reverse_iterator_type (end ()); 624 } 625 BOOST_UBLAS_INLINE rend() const626 dual_reverse_iterator_type rend () const { 627 return dual_reverse_iterator_type (begin ()); 628 } 629 }; 630 631 /** \brief A class implementing an indexed random access iterator. 632 * 633 * \param C the (mutable) container type 634 * \param IC the iterator category 635 * 636 * This class implements a random access iterator. The current 637 * position is stored as the unsigned integer it_ and the 638 * values are accessed via operator()(it_) of the container. 639 * 640 * uBLAS extension: index() 641 */ 642 643 template<class C, class IC> 644 class indexed_iterator: 645 public container_reference<C>, 646 public random_access_iterator_base<IC, 647 indexed_iterator<C, IC>, 648 typename C::value_type, 649 typename C::difference_type> { 650 public: 651 typedef C container_type; 652 typedef IC iterator_category; 653 typedef typename container_type::size_type size_type; 654 typedef typename container_type::difference_type difference_type; 655 typedef typename container_type::value_type value_type; 656 typedef typename container_type::reference reference; 657 658 // Construction and destruction 659 BOOST_UBLAS_INLINE indexed_iterator()660 indexed_iterator (): 661 container_reference<container_type> (), it_ () {} 662 BOOST_UBLAS_INLINE indexed_iterator(container_type & c,size_type it)663 indexed_iterator (container_type &c, size_type it): 664 container_reference<container_type> (c), it_ (it) {} 665 666 // Arithmetic 667 BOOST_UBLAS_INLINE operator ++()668 indexed_iterator &operator ++ () { 669 ++ it_; 670 return *this; 671 } 672 BOOST_UBLAS_INLINE operator --()673 indexed_iterator &operator -- () { 674 -- it_; 675 return *this; 676 } 677 BOOST_UBLAS_INLINE operator +=(difference_type n)678 indexed_iterator &operator += (difference_type n) { 679 it_ += n; 680 return *this; 681 } 682 BOOST_UBLAS_INLINE operator -=(difference_type n)683 indexed_iterator &operator -= (difference_type n) { 684 it_ -= n; 685 return *this; 686 } 687 BOOST_UBLAS_INLINE operator -(const indexed_iterator & it) const688 difference_type operator - (const indexed_iterator &it) const { 689 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 690 return it_ - it.it_; 691 } 692 693 // Dereference 694 BOOST_UBLAS_INLINE operator *() const695 reference operator * () const { 696 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); 697 return (*this) () (it_); 698 } 699 BOOST_UBLAS_INLINE operator [](difference_type n) const700 reference operator [] (difference_type n) const { 701 return *((*this) + n); 702 } 703 704 // Index 705 BOOST_UBLAS_INLINE index() const706 size_type index () const { 707 return it_; 708 } 709 710 // Assignment 711 BOOST_UBLAS_INLINE operator =(const indexed_iterator & it)712 indexed_iterator &operator = (const indexed_iterator &it) { 713 // FIX: ICC needs full qualification?! 714 // assign (&it ()); 715 container_reference<C>::assign (&it ()); 716 it_ = it.it_; 717 return *this; 718 } 719 720 // Comparison 721 BOOST_UBLAS_INLINE operator ==(const indexed_iterator & it) const722 bool operator == (const indexed_iterator &it) const { 723 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 724 return it_ == it.it_; 725 } 726 BOOST_UBLAS_INLINE operator <(const indexed_iterator & it) const727 bool operator < (const indexed_iterator &it) const { 728 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 729 return it_ < it.it_; 730 } 731 732 private: 733 size_type it_; 734 }; 735 736 /** \brief A class implementing an indexed random access iterator. 737 * 738 * \param C the (immutable) container type 739 * \param IC the iterator category 740 * 741 * This class implements a random access iterator. The current 742 * position is stored as the unsigned integer \c it_ and the 743 * values are accessed via \c operator()(it_) of the container. 744 * 745 * uBLAS extension: \c index() 746 * 747 * Note: there is an automatic conversion from 748 * \c indexed_iterator to \c indexed_const_iterator 749 */ 750 751 template<class C, class IC> 752 class indexed_const_iterator: 753 public container_const_reference<C>, 754 public random_access_iterator_base<IC, 755 indexed_const_iterator<C, IC>, 756 typename C::value_type, 757 typename C::difference_type> { 758 public: 759 typedef C container_type; 760 typedef IC iterator_category; 761 typedef typename container_type::size_type size_type; 762 typedef typename container_type::difference_type difference_type; 763 typedef typename container_type::value_type value_type; 764 typedef typename container_type::const_reference reference; 765 typedef indexed_iterator<container_type, iterator_category> iterator_type; 766 767 // Construction and destruction 768 BOOST_UBLAS_INLINE indexed_const_iterator()769 indexed_const_iterator (): 770 container_const_reference<container_type> (), it_ () {} 771 BOOST_UBLAS_INLINE indexed_const_iterator(const container_type & c,size_type it)772 indexed_const_iterator (const container_type &c, size_type it): 773 container_const_reference<container_type> (c), it_ (it) {} 774 BOOST_UBLAS_INLINE indexed_const_iterator(const iterator_type & it)775 indexed_const_iterator (const iterator_type &it): 776 container_const_reference<container_type> (it ()), it_ (it.index ()) {} 777 778 // Arithmetic 779 BOOST_UBLAS_INLINE operator ++()780 indexed_const_iterator &operator ++ () { 781 ++ it_; 782 return *this; 783 } 784 BOOST_UBLAS_INLINE operator --()785 indexed_const_iterator &operator -- () { 786 -- it_; 787 return *this; 788 } 789 BOOST_UBLAS_INLINE operator +=(difference_type n)790 indexed_const_iterator &operator += (difference_type n) { 791 it_ += n; 792 return *this; 793 } 794 BOOST_UBLAS_INLINE operator -=(difference_type n)795 indexed_const_iterator &operator -= (difference_type n) { 796 it_ -= n; 797 return *this; 798 } 799 BOOST_UBLAS_INLINE operator -(const indexed_const_iterator & it) const800 difference_type operator - (const indexed_const_iterator &it) const { 801 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 802 return it_ - it.it_; 803 } 804 805 // Dereference 806 BOOST_UBLAS_INLINE operator *() const807 reference operator * () const { 808 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); 809 return (*this) () (it_); 810 } 811 BOOST_UBLAS_INLINE operator [](difference_type n) const812 reference operator [] (difference_type n) const { 813 return *((*this) + n); 814 } 815 816 // Index 817 BOOST_UBLAS_INLINE index() const818 size_type index () const { 819 return it_; 820 } 821 822 // Assignment 823 BOOST_UBLAS_INLINE operator =(const indexed_const_iterator & it)824 indexed_const_iterator &operator = (const indexed_const_iterator &it) { 825 // FIX: ICC needs full qualification?! 826 // assign (&it ()); 827 container_const_reference<C>::assign (&it ()); 828 it_ = it.it_; 829 return *this; 830 } 831 832 // Comparison 833 BOOST_UBLAS_INLINE operator ==(const indexed_const_iterator & it) const834 bool operator == (const indexed_const_iterator &it) const { 835 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 836 return it_ == it.it_; 837 } 838 BOOST_UBLAS_INLINE operator <(const indexed_const_iterator & it) const839 bool operator < (const indexed_const_iterator &it) const { 840 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 841 return it_ < it.it_; 842 } 843 844 private: 845 size_type it_; 846 847 friend class indexed_iterator<container_type, iterator_category>; 848 }; 849 850 template<class C, class IC> 851 class indexed_iterator2; 852 853 /** \brief A class implementing an indexed random access iterator 854 * of a matrix. 855 * 856 * \param C the (mutable) container type 857 * \param IC the iterator category 858 * 859 * This class implements a random access iterator. The current 860 * position is stored as two unsigned integers \c it1_ and \c it2_ 861 * and the values are accessed via \c operator()(it1_, it2_) of the 862 * container. The iterator changes the first index. 863 * 864 * uBLAS extension: \c index1(), \c index2() and access to the 865 * dual iterator via \c begin(), \c end(), \c rbegin() and \c rend() 866 * 867 * Note: The container has to support the \code find2(rank, i, j) \endcode 868 * method 869 */ 870 871 template<class C, class IC> 872 class indexed_iterator1: 873 public container_reference<C>, 874 public random_access_iterator_base<IC, 875 indexed_iterator1<C, IC>, 876 typename C::value_type, 877 typename C::difference_type> { 878 public: 879 typedef C container_type; 880 typedef IC iterator_category; 881 typedef typename container_type::size_type size_type; 882 typedef typename container_type::difference_type difference_type; 883 typedef typename container_type::value_type value_type; 884 typedef typename container_type::reference reference; 885 886 typedef indexed_iterator2<container_type, iterator_category> dual_iterator_type; 887 typedef reverse_iterator_base2<dual_iterator_type> dual_reverse_iterator_type; 888 889 // Construction and destruction 890 BOOST_UBLAS_INLINE indexed_iterator1()891 indexed_iterator1 (): 892 container_reference<container_type> (), it1_ (), it2_ () {} 893 BOOST_UBLAS_INLINE indexed_iterator1(container_type & c,size_type it1,size_type it2)894 indexed_iterator1 (container_type &c, size_type it1, size_type it2): 895 container_reference<container_type> (c), it1_ (it1), it2_ (it2) {} 896 897 // Arithmetic 898 BOOST_UBLAS_INLINE operator ++()899 indexed_iterator1 &operator ++ () { 900 ++ it1_; 901 return *this; 902 } 903 BOOST_UBLAS_INLINE operator --()904 indexed_iterator1 &operator -- () { 905 -- it1_; 906 return *this; 907 } 908 BOOST_UBLAS_INLINE operator +=(difference_type n)909 indexed_iterator1 &operator += (difference_type n) { 910 it1_ += n; 911 return *this; 912 } 913 BOOST_UBLAS_INLINE operator -=(difference_type n)914 indexed_iterator1 &operator -= (difference_type n) { 915 it1_ -= n; 916 return *this; 917 } 918 BOOST_UBLAS_INLINE operator -(const indexed_iterator1 & it) const919 difference_type operator - (const indexed_iterator1 &it) const { 920 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 921 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 922 return it1_ - it.it1_; 923 } 924 925 // Dereference 926 BOOST_UBLAS_INLINE operator *() const927 reference operator * () const { 928 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 929 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 930 return (*this) () (it1_, it2_); 931 } 932 BOOST_UBLAS_INLINE operator [](difference_type n) const933 reference operator [] (difference_type n) const { 934 return *((*this) + n); 935 } 936 937 // Index 938 BOOST_UBLAS_INLINE index1() const939 size_type index1 () const { 940 return it1_; 941 } 942 BOOST_UBLAS_INLINE index2() const943 size_type index2 () const { 944 return it2_; 945 } 946 947 BOOST_UBLAS_INLINE begin() const948 dual_iterator_type begin () const { 949 return (*this) ().find2 (1, index1 (), 0); 950 } 951 BOOST_UBLAS_INLINE end() const952 dual_iterator_type end () const { 953 return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); 954 } 955 BOOST_UBLAS_INLINE rbegin() const956 dual_reverse_iterator_type rbegin () const { 957 return dual_reverse_iterator_type (end ()); 958 } 959 BOOST_UBLAS_INLINE rend() const960 dual_reverse_iterator_type rend () const { 961 return dual_reverse_iterator_type (begin ()); 962 } 963 964 // Assignment 965 BOOST_UBLAS_INLINE operator =(const indexed_iterator1 & it)966 indexed_iterator1 &operator = (const indexed_iterator1 &it) { 967 // FIX: ICC needs full qualification?! 968 // assign (&it ()); 969 container_reference<C>::assign (&it ()); 970 it1_ = it.it1_; 971 it2_ = it.it2_; 972 return *this; 973 } 974 975 // Comparison 976 BOOST_UBLAS_INLINE operator ==(const indexed_iterator1 & it) const977 bool operator == (const indexed_iterator1 &it) const { 978 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 979 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 980 return it1_ == it.it1_; 981 } 982 BOOST_UBLAS_INLINE operator <(const indexed_iterator1 & it) const983 bool operator < (const indexed_iterator1 &it) const { 984 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 985 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 986 return it1_ < it.it1_; 987 } 988 989 private: 990 size_type it1_; 991 size_type it2_; 992 }; 993 994 template<class C, class IC> 995 class indexed_const_iterator2; 996 997 /** \brief A class implementing an indexed random access iterator 998 * of a matrix. 999 * 1000 * \param C the (immutable) container type 1001 * \param IC the iterator category 1002 * 1003 * This class implements a random access iterator. The current 1004 * position is stored as two unsigned integers \c it1_ and \c it2_ 1005 * and the values are accessed via \c operator()(it1_, it2_) of the 1006 * container. The iterator changes the first index. 1007 * 1008 * uBLAS extension: \c index1(), \c index2() and access to the 1009 * dual iterator via \c begin(), \c end(), \c rbegin() and \c rend() 1010 * 1011 * Note 1: The container has to support the find2(rank, i, j) method 1012 * 1013 * Note 2: there is an automatic conversion from 1014 * \c indexed_iterator1 to \c indexed_const_iterator1 1015 */ 1016 1017 template<class C, class IC> 1018 class indexed_const_iterator1: 1019 public container_const_reference<C>, 1020 public random_access_iterator_base<IC, 1021 indexed_const_iterator1<C, IC>, 1022 typename C::value_type, 1023 typename C::difference_type> { 1024 public: 1025 typedef C container_type; 1026 typedef IC iterator_category; 1027 typedef typename container_type::size_type size_type; 1028 typedef typename container_type::difference_type difference_type; 1029 typedef typename container_type::value_type value_type; 1030 typedef typename container_type::const_reference reference; 1031 1032 typedef indexed_iterator1<container_type, iterator_category> iterator_type; 1033 typedef indexed_const_iterator2<container_type, iterator_category> dual_iterator_type; 1034 typedef reverse_iterator_base2<dual_iterator_type> dual_reverse_iterator_type; 1035 1036 // Construction and destruction 1037 BOOST_UBLAS_INLINE indexed_const_iterator1()1038 indexed_const_iterator1 (): 1039 container_const_reference<container_type> (), it1_ (), it2_ () {} 1040 BOOST_UBLAS_INLINE indexed_const_iterator1(const container_type & c,size_type it1,size_type it2)1041 indexed_const_iterator1 (const container_type &c, size_type it1, size_type it2): 1042 container_const_reference<container_type> (c), it1_ (it1), it2_ (it2) {} 1043 BOOST_UBLAS_INLINE indexed_const_iterator1(const iterator_type & it)1044 indexed_const_iterator1 (const iterator_type &it): 1045 container_const_reference<container_type> (it ()), it1_ (it.index1 ()), it2_ (it.index2 ()) {} 1046 1047 // Arithmetic 1048 BOOST_UBLAS_INLINE operator ++()1049 indexed_const_iterator1 &operator ++ () { 1050 ++ it1_; 1051 return *this; 1052 } 1053 BOOST_UBLAS_INLINE operator --()1054 indexed_const_iterator1 &operator -- () { 1055 -- it1_; 1056 return *this; 1057 } 1058 BOOST_UBLAS_INLINE operator +=(difference_type n)1059 indexed_const_iterator1 &operator += (difference_type n) { 1060 it1_ += n; 1061 return *this; 1062 } 1063 BOOST_UBLAS_INLINE operator -=(difference_type n)1064 indexed_const_iterator1 &operator -= (difference_type n) { 1065 it1_ -= n; 1066 return *this; 1067 } 1068 BOOST_UBLAS_INLINE operator -(const indexed_const_iterator1 & it) const1069 difference_type operator - (const indexed_const_iterator1 &it) const { 1070 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1071 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 1072 return it1_ - it.it1_; 1073 } 1074 1075 // Dereference 1076 BOOST_UBLAS_INLINE operator *() const1077 reference operator * () const { 1078 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 1079 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 1080 return (*this) () (it1_, it2_); 1081 } 1082 BOOST_UBLAS_INLINE operator [](difference_type n) const1083 reference operator [] (difference_type n) const { 1084 return *((*this) + n); 1085 } 1086 1087 // Index 1088 BOOST_UBLAS_INLINE index1() const1089 size_type index1 () const { 1090 return it1_; 1091 } 1092 BOOST_UBLAS_INLINE index2() const1093 size_type index2 () const { 1094 return it2_; 1095 } 1096 1097 BOOST_UBLAS_INLINE begin() const1098 dual_iterator_type begin () const { 1099 return (*this) ().find2 (1, index1 (), 0); 1100 } 1101 BOOST_UBLAS_INLINE end() const1102 dual_iterator_type end () const { 1103 return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); 1104 } 1105 BOOST_UBLAS_INLINE rbegin() const1106 dual_reverse_iterator_type rbegin () const { 1107 return dual_reverse_iterator_type (end ()); 1108 } 1109 BOOST_UBLAS_INLINE rend() const1110 dual_reverse_iterator_type rend () const { 1111 return dual_reverse_iterator_type (begin ()); 1112 } 1113 1114 // Assignment 1115 BOOST_UBLAS_INLINE operator =(const indexed_const_iterator1 & it)1116 indexed_const_iterator1 &operator = (const indexed_const_iterator1 &it) { 1117 // FIX: ICC needs full qualification?! 1118 // assign (&it ()); 1119 container_const_reference<C>::assign (&it ()); 1120 it1_ = it.it1_; 1121 it2_ = it.it2_; 1122 return *this; 1123 } 1124 1125 // Comparison 1126 BOOST_UBLAS_INLINE operator ==(const indexed_const_iterator1 & it) const1127 bool operator == (const indexed_const_iterator1 &it) const { 1128 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1129 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 1130 return it1_ == it.it1_; 1131 } 1132 BOOST_UBLAS_INLINE operator <(const indexed_const_iterator1 & it) const1133 bool operator < (const indexed_const_iterator1 &it) const { 1134 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1135 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 1136 return it1_ < it.it1_; 1137 } 1138 1139 private: 1140 size_type it1_; 1141 size_type it2_; 1142 1143 friend class indexed_iterator1<container_type, iterator_category>; 1144 }; 1145 1146 /** \brief A class implementing an indexed random access iterator 1147 * of a matrix. 1148 * 1149 * \param C the (mutable) container type 1150 * \param IC the iterator category 1151 * 1152 * This class implements a random access iterator. The current 1153 * position is stored as two unsigned integers \c it1_ and \c it2_ 1154 * and the values are accessed via \c operator()(it1_, it2_) of the 1155 * container. The iterator changes the second index. 1156 * 1157 * uBLAS extension: \c index1(), \c index2() and access to the 1158 * dual iterator via \c begin(), \c end(), \c rbegin() and \c rend() 1159 * 1160 * Note: The container has to support the find1(rank, i, j) method 1161 */ 1162 template<class C, class IC> 1163 class indexed_iterator2: 1164 public container_reference<C>, 1165 public random_access_iterator_base<IC, 1166 indexed_iterator2<C, IC>, 1167 typename C::value_type, 1168 typename C::difference_type> { 1169 public: 1170 typedef C container_type; 1171 typedef IC iterator_category; 1172 typedef typename container_type::size_type size_type; 1173 typedef typename container_type::difference_type difference_type; 1174 typedef typename container_type::value_type value_type; 1175 typedef typename container_type::reference reference; 1176 1177 typedef indexed_iterator1<container_type, iterator_category> dual_iterator_type; 1178 typedef reverse_iterator_base1<dual_iterator_type> dual_reverse_iterator_type; 1179 1180 // Construction and destruction 1181 BOOST_UBLAS_INLINE indexed_iterator2()1182 indexed_iterator2 (): 1183 container_reference<container_type> (), it1_ (), it2_ () {} 1184 BOOST_UBLAS_INLINE indexed_iterator2(container_type & c,size_type it1,size_type it2)1185 indexed_iterator2 (container_type &c, size_type it1, size_type it2): 1186 container_reference<container_type> (c), it1_ (it1), it2_ (it2) {} 1187 1188 // Arithmetic 1189 BOOST_UBLAS_INLINE operator ++()1190 indexed_iterator2 &operator ++ () { 1191 ++ it2_; 1192 return *this; 1193 } 1194 BOOST_UBLAS_INLINE operator --()1195 indexed_iterator2 &operator -- () { 1196 -- it2_; 1197 return *this; 1198 } 1199 BOOST_UBLAS_INLINE operator +=(difference_type n)1200 indexed_iterator2 &operator += (difference_type n) { 1201 it2_ += n; 1202 return *this; 1203 } 1204 BOOST_UBLAS_INLINE operator -=(difference_type n)1205 indexed_iterator2 &operator -= (difference_type n) { 1206 it2_ -= n; 1207 return *this; 1208 } 1209 BOOST_UBLAS_INLINE operator -(const indexed_iterator2 & it) const1210 difference_type operator - (const indexed_iterator2 &it) const { 1211 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1212 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 1213 return it2_ - it.it2_; 1214 } 1215 1216 // Dereference 1217 BOOST_UBLAS_INLINE operator *() const1218 reference operator * () const { 1219 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 1220 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 1221 return (*this) () (it1_, it2_); 1222 } 1223 BOOST_UBLAS_INLINE operator [](difference_type n) const1224 reference operator [] (difference_type n) const { 1225 return *((*this) + n); 1226 } 1227 1228 // Index 1229 BOOST_UBLAS_INLINE index1() const1230 size_type index1 () const { 1231 return it1_; 1232 } 1233 BOOST_UBLAS_INLINE index2() const1234 size_type index2 () const { 1235 return it2_; 1236 } 1237 1238 BOOST_UBLAS_INLINE begin() const1239 dual_iterator_type begin () const { 1240 return (*this) ().find1 (1, 0, index2 ()); 1241 } 1242 BOOST_UBLAS_INLINE end() const1243 dual_iterator_type end () const { 1244 return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); 1245 } 1246 BOOST_UBLAS_INLINE rbegin() const1247 dual_reverse_iterator_type rbegin () const { 1248 return dual_reverse_iterator_type (end ()); 1249 } 1250 BOOST_UBLAS_INLINE rend() const1251 dual_reverse_iterator_type rend () const { 1252 return dual_reverse_iterator_type (begin ()); 1253 } 1254 1255 // Assignment 1256 BOOST_UBLAS_INLINE operator =(const indexed_iterator2 & it)1257 indexed_iterator2 &operator = (const indexed_iterator2 &it) { 1258 // FIX: ICC needs full qualification?! 1259 // assign (&it ()); 1260 container_reference<C>::assign (&it ()); 1261 it1_ = it.it1_; 1262 it2_ = it.it2_; 1263 return *this; 1264 } 1265 1266 // Comparison 1267 BOOST_UBLAS_INLINE operator ==(const indexed_iterator2 & it) const1268 bool operator == (const indexed_iterator2 &it) const { 1269 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1270 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 1271 return it2_ == it.it2_; 1272 } 1273 BOOST_UBLAS_INLINE operator <(const indexed_iterator2 & it) const1274 bool operator < (const indexed_iterator2 &it) const { 1275 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1276 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 1277 return it2_ < it.it2_; 1278 } 1279 1280 private: 1281 size_type it1_; 1282 size_type it2_; 1283 }; 1284 1285 /** \brief A class implementing an indexed random access iterator 1286 * of a matrix. 1287 * 1288 * \param C the (immutable) container type 1289 * \param IC the iterator category 1290 * 1291 * This class implements a random access iterator. The current 1292 * position is stored as two unsigned integers \c it1_ and \c it2_ 1293 * and the values are accessed via \c operator()(it1_, it2_) of the 1294 * container. The iterator changes the second index. 1295 * 1296 * uBLAS extension: \c index1(), \c index2() and access to the 1297 * dual iterator via \c begin(), \c end(), \c rbegin() and \c rend() 1298 * 1299 * Note 1: The container has to support the \c find2(rank, i, j) method 1300 * 1301 * Note 2: there is an automatic conversion from 1302 * \c indexed_iterator2 to \c indexed_const_iterator2 1303 */ 1304 1305 template<class C, class IC> 1306 class indexed_const_iterator2: 1307 public container_const_reference<C>, 1308 public random_access_iterator_base<IC, 1309 indexed_const_iterator2<C, IC>, 1310 typename C::value_type, 1311 typename C::difference_type> { 1312 public: 1313 typedef C container_type; 1314 typedef IC iterator_category; 1315 typedef typename container_type::size_type size_type; 1316 typedef typename container_type::difference_type difference_type; 1317 typedef typename container_type::value_type value_type; 1318 typedef typename container_type::const_reference reference; 1319 1320 typedef indexed_iterator2<container_type, iterator_category> iterator_type; 1321 typedef indexed_const_iterator1<container_type, iterator_category> dual_iterator_type; 1322 typedef reverse_iterator_base1<dual_iterator_type> dual_reverse_iterator_type; 1323 1324 // Construction and destruction 1325 BOOST_UBLAS_INLINE indexed_const_iterator2()1326 indexed_const_iterator2 (): 1327 container_const_reference<container_type> (), it1_ (), it2_ () {} 1328 BOOST_UBLAS_INLINE indexed_const_iterator2(const container_type & c,size_type it1,size_type it2)1329 indexed_const_iterator2 (const container_type &c, size_type it1, size_type it2): 1330 container_const_reference<container_type> (c), it1_ (it1), it2_ (it2) {} 1331 BOOST_UBLAS_INLINE indexed_const_iterator2(const iterator_type & it)1332 indexed_const_iterator2 (const iterator_type &it): 1333 container_const_reference<container_type> (it ()), it1_ (it.index1 ()), it2_ (it.index2 ()) {} 1334 1335 // Arithmetic 1336 BOOST_UBLAS_INLINE operator ++()1337 indexed_const_iterator2 &operator ++ () { 1338 ++ it2_; 1339 return *this; 1340 } 1341 BOOST_UBLAS_INLINE operator --()1342 indexed_const_iterator2 &operator -- () { 1343 -- it2_; 1344 return *this; 1345 } 1346 BOOST_UBLAS_INLINE operator +=(difference_type n)1347 indexed_const_iterator2 &operator += (difference_type n) { 1348 it2_ += n; 1349 return *this; 1350 } 1351 BOOST_UBLAS_INLINE operator -=(difference_type n)1352 indexed_const_iterator2 &operator -= (difference_type n) { 1353 it2_ -= n; 1354 return *this; 1355 } 1356 BOOST_UBLAS_INLINE operator -(const indexed_const_iterator2 & it) const1357 difference_type operator - (const indexed_const_iterator2 &it) const { 1358 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1359 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 1360 return it2_ - it.it2_; 1361 } 1362 1363 // Dereference 1364 BOOST_UBLAS_INLINE operator *() const1365 reference operator * () const { 1366 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ()); 1367 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ()); 1368 return (*this) () (it1_, it2_); 1369 } 1370 BOOST_UBLAS_INLINE operator [](difference_type n) const1371 reference operator [] (difference_type n) const { 1372 return *((*this) + n); 1373 } 1374 1375 // Index 1376 BOOST_UBLAS_INLINE index1() const1377 size_type index1 () const { 1378 return it1_; 1379 } 1380 BOOST_UBLAS_INLINE index2() const1381 size_type index2 () const { 1382 return it2_; 1383 } 1384 1385 BOOST_UBLAS_INLINE begin() const1386 dual_iterator_type begin () const { 1387 return (*this) ().find1 (1, 0, index2 ()); 1388 } 1389 BOOST_UBLAS_INLINE end() const1390 dual_iterator_type end () const { 1391 return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); 1392 } 1393 BOOST_UBLAS_INLINE rbegin() const1394 dual_reverse_iterator_type rbegin () const { 1395 return dual_reverse_iterator_type (end ()); 1396 } 1397 BOOST_UBLAS_INLINE rend() const1398 dual_reverse_iterator_type rend () const { 1399 return dual_reverse_iterator_type (begin ()); 1400 } 1401 1402 // Assignment 1403 BOOST_UBLAS_INLINE operator =(const indexed_const_iterator2 & it)1404 indexed_const_iterator2 &operator = (const indexed_const_iterator2 &it) { 1405 // FIX: ICC needs full qualification?! 1406 // assign (&it ()); 1407 container_const_reference<C>::assign (&it ()); 1408 it1_ = it.it1_; 1409 it2_ = it.it2_; 1410 return *this; 1411 } 1412 1413 // Comparison 1414 BOOST_UBLAS_INLINE operator ==(const indexed_const_iterator2 & it) const1415 bool operator == (const indexed_const_iterator2 &it) const { 1416 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1417 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 1418 return it2_ == it.it2_; 1419 } 1420 BOOST_UBLAS_INLINE operator <(const indexed_const_iterator2 & it) const1421 bool operator < (const indexed_const_iterator2 &it) const { 1422 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1423 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 1424 return it2_ < it.it2_; 1425 } 1426 1427 private: 1428 size_type it1_; 1429 size_type it2_; 1430 1431 friend class indexed_iterator2<container_type, iterator_category>; 1432 }; 1433 1434 }}} 1435 1436 #endif 1437