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