source: NonGTP/Boost/boost/numeric/ublas/symmetric.hpp @ 857

Revision 857, 81.7 KB checked in by igarcia, 19 years ago (diff)
Line 
1//
2//  Copyright (c) 2000-2002
3//  Joerg Walter, Mathias Koch
4//
5//  Permission to use, copy, modify, distribute and sell this software
6//  and its documentation for any purpose is hereby granted without fee,
7//  provided that the above copyright notice appear in all copies and
8//  that both that copyright notice and this permission notice appear
9//  in supporting documentation.  The authors make no representations
10//  about the suitability of this software for any purpose.
11//  It is provided "as is" without express or implied warranty.
12//
13//  The authors gratefully acknowledge the support of
14//  GeNeSys mbH & Co. KG in producing this work.
15//
16
17#ifndef _BOOST_UBLAS_SYMMETRIC_
18#define _BOOST_UBLAS_SYMMETRIC_
19
20#include <boost/numeric/ublas/matrix.hpp>
21#include <boost/numeric/ublas/detail/temporary.hpp>
22
23// Iterators based on ideas of Jeremy Siek
24// Symmetric matrices are square. Thanks to Peter Schmitteckert for spotting this.
25
26namespace boost { namespace numeric { namespace ublas {
27
28    template<class M>
29    bool is_symmetric (const M &m) {
30        typedef typename M::size_type size_type;
31
32        if (m.size1 () != m.size2 ())
33            return false;
34        size_type size = BOOST_UBLAS_SAME (m.size1 (), m.size2 ());
35        for (size_type i = 0; i < size; ++ i) {
36            for (size_type j = i; j < size; ++ j) {
37                if (m (i, j) != m (j, i))
38                    return false;
39            }
40        }
41        return true;
42    }
43
44    // Array based symmetric matrix class
45    template<class T, class TRI, class L, class A>
46    class symmetric_matrix:
47        public matrix_container<symmetric_matrix<T, TRI, L, A> > {
48
49        typedef T *pointer;
50        typedef TRI triangular_type;
51        typedef L layout_type;
52        typedef symmetric_matrix<T, TRI, L, A> self_type;
53    public:
54#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
55        using matrix_container<self_type>::operator ();
56#endif
57        typedef typename A::size_type size_type;
58        typedef typename A::difference_type difference_type;
59        typedef T value_type;
60        typedef const T &const_reference;
61        typedef T &reference;
62        typedef A array_type;
63
64        typedef const matrix_reference<const self_type> const_closure_type;
65        typedef matrix_reference<self_type> closure_type;
66        typedef vector<T, A> vector_temporary_type;
67        typedef matrix<T, L, A> matrix_temporary_type;  // general sub-matrix
68        typedef packed_tag storage_category;
69        typedef typename L::orientation_category orientation_category;
70
71        // Construction and destruction
72        BOOST_UBLAS_INLINE
73        symmetric_matrix ():
74            matrix_container<self_type> (),
75            size_ (0), data_ (0) {}
76        BOOST_UBLAS_INLINE
77        symmetric_matrix (size_type size):
78            matrix_container<self_type> (),
79            size_ (BOOST_UBLAS_SAME (size, size)), data_ (triangular_type::packed_size (layout_type (), size, size)) {
80        }
81        BOOST_UBLAS_INLINE
82        symmetric_matrix (size_type size1, size_type size2):
83            matrix_container<self_type> (),
84            size_ (BOOST_UBLAS_SAME (size1, size2)), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
85        }
86        BOOST_UBLAS_INLINE
87        symmetric_matrix (size_type size, const array_type &data):
88            matrix_container<self_type> (),
89            size_ (size), data_ (data) {}
90        BOOST_UBLAS_INLINE
91        symmetric_matrix (const symmetric_matrix &m):
92            matrix_container<self_type> (),
93            size_ (m.size_), data_ (m.data_) {}
94        template<class AE>
95        BOOST_UBLAS_INLINE
96        symmetric_matrix (const matrix_expression<AE> &ae):
97            matrix_container<self_type> (),
98            size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())),
99            data_ (triangular_type::packed_size (layout_type (), size_, size_)) {
100            matrix_assign<scalar_assign> (*this, ae);
101        }
102
103        // Accessors
104        BOOST_UBLAS_INLINE
105        size_type size1 () const {
106            return size_;
107        }
108        BOOST_UBLAS_INLINE
109        size_type size2 () const {
110            return size_;
111        }
112
113        // Storage accessors
114        BOOST_UBLAS_INLINE
115        const array_type &data () const {
116            return data_;
117        }
118        BOOST_UBLAS_INLINE
119        array_type &data () {
120            return data_;
121        }
122
123        // Resizing
124        BOOST_UBLAS_INLINE
125        void resize (size_type size, bool preserve = true) {
126            if (preserve) {
127                self_type temporary (size, size);
128                detail::matrix_resize_preserve<layout_type> (*this, temporary);
129            }
130            else {
131                data ().resize (triangular_type::packed_size (layout_type (), size, size));
132                size_ = size;
133            }
134        }
135        BOOST_UBLAS_INLINE
136        void resize (size_type size1, size_type size2, bool preserve = true) {
137            resize (BOOST_UBLAS_SAME (size1, size2), preserve);
138        }
139        BOOST_UBLAS_INLINE
140        void resize_packed_preserve (size_type size) {
141            size_ = BOOST_UBLAS_SAME (size, size);
142            data ().resize (triangular_type::packed_size (layout_type (), size_, size_), value_type ());
143        }
144
145        // Element access
146        BOOST_UBLAS_INLINE
147        const_reference operator () (size_type i, size_type j) const {
148            BOOST_UBLAS_CHECK (i < size_, bad_index ());
149            BOOST_UBLAS_CHECK (j < size_, bad_index ());
150            if (triangular_type::other (i, j))
151                return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
152            else
153                return data () [triangular_type::element (layout_type (), j, size_, i, size_)];
154        }
155        BOOST_UBLAS_INLINE
156        reference at_element (size_type i, size_type j) {
157            BOOST_UBLAS_CHECK (i < size_, bad_index ());
158            BOOST_UBLAS_CHECK (j < size_, bad_index ());
159            return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
160        }
161        BOOST_UBLAS_INLINE
162        reference operator () (size_type i, size_type j) {
163            BOOST_UBLAS_CHECK (i < size_, bad_index ());
164            BOOST_UBLAS_CHECK (j < size_, bad_index ());
165            if (triangular_type::other (i, j))
166                return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
167            else
168                return data () [triangular_type::element (layout_type (), j, size_, i, size_)];
169        }
170
171        // Element assignment
172        BOOST_UBLAS_INLINE
173        reference insert_element (size_type i, size_type j, const_reference t) {
174            return (operator () (i, j) = t);
175        }
176        BOOST_UBLAS_INLINE
177        void erase_element (size_type i, size_type j) {
178            return (operator () (i, j) = value_type/*zero*/());
179        }
180       
181        // Zeroing
182        BOOST_UBLAS_INLINE
183        void clear () {
184            // data ().clear ();
185            std::fill (data ().begin (), data ().end (), value_type/*zero*/());
186        }
187
188        // Assignment
189        BOOST_UBLAS_INLINE
190        symmetric_matrix &operator = (const symmetric_matrix &m) {
191            size_ = m.size_;
192            data () = m.data ();
193            return *this;
194        }
195        BOOST_UBLAS_INLINE
196        symmetric_matrix &assign_temporary (symmetric_matrix &m) {
197            swap (m);
198            return *this;
199        }
200        template<class AE>
201        BOOST_UBLAS_INLINE
202        symmetric_matrix &operator = (const matrix_expression<AE> &ae) {
203            self_type temporary (ae);
204            return assign_temporary (temporary);
205        }
206        template<class AE>
207        BOOST_UBLAS_INLINE
208        symmetric_matrix &assign (const matrix_expression<AE> &ae) {
209            matrix_assign<scalar_assign> (*this, ae);
210            return *this;
211        }
212        template<class AE>
213        BOOST_UBLAS_INLINE
214        symmetric_matrix& operator += (const matrix_expression<AE> &ae) {
215            self_type temporary (*this + ae);
216            return assign_temporary (temporary);
217        }
218        template<class AE>
219        BOOST_UBLAS_INLINE
220        symmetric_matrix &plus_assign (const matrix_expression<AE> &ae) {
221            matrix_assign<scalar_plus_assign> (*this, ae);
222            return *this;
223        }
224        template<class AE>
225        BOOST_UBLAS_INLINE
226        symmetric_matrix& operator -= (const matrix_expression<AE> &ae) {
227            self_type temporary (*this - ae);
228            return assign_temporary (temporary);
229        }
230        template<class AE>
231        BOOST_UBLAS_INLINE
232        symmetric_matrix &minus_assign (const matrix_expression<AE> &ae) {
233            matrix_assign<scalar_minus_assign> (*this, ae);
234            return *this;
235        }
236        template<class AT>
237        BOOST_UBLAS_INLINE
238        symmetric_matrix& operator *= (const AT &at) {
239            matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
240            return *this;
241        }
242        template<class AT>
243        BOOST_UBLAS_INLINE
244        symmetric_matrix& operator /= (const AT &at) {
245            matrix_assign_scalar<scalar_divides_assign> (*this, at);
246            return *this;
247        }
248
249        // Swapping
250        BOOST_UBLAS_INLINE
251        void swap (symmetric_matrix &m) {
252            if (this != &m) {
253                std::swap (size_, m.size_);
254                data ().swap (m.data ());
255            }
256        }
257        BOOST_UBLAS_INLINE
258        friend void swap (symmetric_matrix &m1, symmetric_matrix &m2) {
259            m1.swap (m2);
260        }
261
262        // Iterator types
263#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
264        typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
265        typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
266        typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
267        typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
268#else
269        class const_iterator1;
270        class iterator1;
271        class const_iterator2;
272        class iterator2;
273#endif
274        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
275        typedef reverse_iterator_base1<iterator1> reverse_iterator1;
276        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
277        typedef reverse_iterator_base2<iterator2> reverse_iterator2;
278
279        // Element lookup
280        BOOST_UBLAS_INLINE
281        const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
282            return const_iterator1 (*this, i, j);
283        }
284        BOOST_UBLAS_INLINE
285        iterator1 find1 (int rank, size_type i, size_type j) {
286            if (rank == 1)
287                i = triangular_type::mutable_restrict1 (i, j);
288            return iterator1 (*this, i, j);
289        }
290        BOOST_UBLAS_INLINE
291        const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
292            return const_iterator2 (*this, i, j);
293        }
294        BOOST_UBLAS_INLINE
295        iterator2 find2 (int rank, size_type i, size_type j) {
296            if (rank == 1)
297                j = triangular_type::mutable_restrict2 (i, j);
298            return iterator2 (*this, i, j);
299        }
300
301        // Iterators simply are indices.
302
303#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
304        class const_iterator1:
305            public container_const_reference<symmetric_matrix>,
306            public random_access_iterator_base<dense_random_access_iterator_tag,
307                                               const_iterator1, value_type> {
308        public:
309            typedef typename symmetric_matrix::value_type value_type;
310            typedef typename symmetric_matrix::difference_type difference_type;
311            typedef typename symmetric_matrix::const_reference reference;
312            typedef const typename symmetric_matrix::pointer pointer;
313
314            typedef const_iterator2 dual_iterator_type;
315            typedef const_reverse_iterator2 dual_reverse_iterator_type;
316
317            // Construction and destruction
318            BOOST_UBLAS_INLINE
319            const_iterator1 ():
320                container_const_reference<self_type> (), it1_ (), it2_ () {}
321            BOOST_UBLAS_INLINE
322            const_iterator1 (const self_type &m, size_type it1, size_type it2):
323                container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
324            BOOST_UBLAS_INLINE
325            const_iterator1 (const iterator1 &it):
326                container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
327
328            // Arithmetic
329            BOOST_UBLAS_INLINE
330            const_iterator1 &operator ++ () {
331                ++ it1_;
332                return *this;
333            }
334            BOOST_UBLAS_INLINE
335            const_iterator1 &operator -- () {
336                -- it1_;
337                return *this;
338            }
339            BOOST_UBLAS_INLINE
340            const_iterator1 &operator += (difference_type n) {
341                it1_ += n;
342                return *this;
343            }
344            BOOST_UBLAS_INLINE
345            const_iterator1 &operator -= (difference_type n) {
346                it1_ -= n;
347                return *this;
348            }
349            BOOST_UBLAS_INLINE
350            difference_type operator - (const const_iterator1 &it) const {
351                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
352                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
353                return it1_ - it.it1_;
354            }
355
356            // Dereference
357            BOOST_UBLAS_INLINE
358            const_reference operator * () const {
359                return (*this) () (it1_, it2_);
360            }
361
362#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
363            BOOST_UBLAS_INLINE
364#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
365            typename self_type::
366#endif
367            const_iterator2 begin () const {
368                return (*this) ().find2 (1, it1_, 0);
369            }
370            BOOST_UBLAS_INLINE
371#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
372            typename self_type::
373#endif
374            const_iterator2 end () const {
375                return (*this) ().find2 (1, it1_, (*this) ().size2 ());
376            }
377            BOOST_UBLAS_INLINE
378#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
379            typename self_type::
380#endif
381            const_reverse_iterator2 rbegin () const {
382                return const_reverse_iterator2 (end ());
383            }
384            BOOST_UBLAS_INLINE
385#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
386            typename self_type::
387#endif
388            const_reverse_iterator2 rend () const {
389                return const_reverse_iterator2 (begin ());
390            }
391#endif
392
393            // Indices
394            BOOST_UBLAS_INLINE
395            size_type index1 () const {
396                return it1_;
397            }
398            BOOST_UBLAS_INLINE
399            size_type index2 () const {
400                return it2_;
401            }
402
403            // Assignment
404            BOOST_UBLAS_INLINE
405            const_iterator1 &operator = (const const_iterator1 &it) {
406                container_const_reference<self_type>::assign (&it ());
407                it1_ = it.it1_;
408                it2_ = it.it2_;
409                return *this;
410            }
411
412            // Comparison
413            BOOST_UBLAS_INLINE
414            bool operator == (const const_iterator1 &it) const {
415                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
416                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
417                return it1_ == it.it1_;
418            }
419            BOOST_UBLAS_INLINE
420            bool operator < (const const_iterator1 &it) const {
421                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
422                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
423                return it1_ < it.it1_;
424            }
425
426        private:
427            size_type it1_;
428            size_type it2_;
429        };
430#endif
431
432        BOOST_UBLAS_INLINE
433        const_iterator1 begin1 () const {
434            return find1 (0, 0, 0);
435        }
436        BOOST_UBLAS_INLINE
437        const_iterator1 end1 () const {
438            return find1 (0, size_, 0);
439        }
440
441#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
442        class iterator1:
443            public container_reference<symmetric_matrix>,
444            public random_access_iterator_base<packed_random_access_iterator_tag,
445                                               iterator1, value_type> {
446        public:
447            typedef typename symmetric_matrix::value_type value_type;
448            typedef typename symmetric_matrix::difference_type difference_type;
449            typedef typename symmetric_matrix::reference reference;
450            typedef typename symmetric_matrix::pointer pointer;
451            typedef iterator2 dual_iterator_type;
452            typedef reverse_iterator2 dual_reverse_iterator_type;
453
454            // Construction and destruction
455            BOOST_UBLAS_INLINE
456            iterator1 ():
457                container_reference<self_type> (), it1_ (), it2_ () {}
458            BOOST_UBLAS_INLINE
459            iterator1 (self_type &m, size_type it1, size_type it2):
460                container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
461
462            // Arithmetic
463            BOOST_UBLAS_INLINE
464            iterator1 &operator ++ () {
465                ++ it1_;
466                return *this;
467            }
468            BOOST_UBLAS_INLINE
469            iterator1 &operator -- () {
470                -- it1_;
471                return *this;
472            }
473            BOOST_UBLAS_INLINE
474            iterator1 &operator += (difference_type n) {
475                it1_ += n;
476                return *this;
477            }
478            BOOST_UBLAS_INLINE
479            iterator1 &operator -= (difference_type n) {
480                it1_ -= n;
481                return *this;
482            }
483            BOOST_UBLAS_INLINE
484            difference_type operator - (const iterator1 &it) const {
485                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
486                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
487                return it1_ - it.it1_;
488            }
489
490            // Dereference
491            BOOST_UBLAS_INLINE
492            reference operator * () const {
493                return (*this) () (it1_, it2_);
494            }
495
496#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
497            BOOST_UBLAS_INLINE
498#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
499            typename self_type::
500#endif
501            iterator2 begin () const {
502                return (*this) ().find2 (1, it1_, 0);
503            }
504            BOOST_UBLAS_INLINE
505#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
506            typename self_type::
507#endif
508            iterator2 end () const {
509                return (*this) ().find2 (1, it1_, (*this) ().size2 ());
510            }
511            BOOST_UBLAS_INLINE
512#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
513            typename self_type::
514#endif
515            reverse_iterator2 rbegin () const {
516                return reverse_iterator2 (end ());
517            }
518            BOOST_UBLAS_INLINE
519#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
520            typename self_type::
521#endif
522            reverse_iterator2 rend () const {
523                return reverse_iterator2 (begin ());
524            }
525#endif
526
527            // Indices
528            BOOST_UBLAS_INLINE
529            size_type index1 () const {
530                return it1_;
531            }
532            BOOST_UBLAS_INLINE
533            size_type index2 () const {
534                return it2_;
535            }
536
537            // Assignment
538            BOOST_UBLAS_INLINE
539            iterator1 &operator = (const iterator1 &it) {
540                container_reference<self_type>::assign (&it ());
541                it1_ = it.it1_;
542                it2_ = it.it2_;
543                return *this;
544            }
545
546            // Comparison
547            BOOST_UBLAS_INLINE
548            bool operator == (const iterator1 &it) const {
549                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
550                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
551                return it1_ == it.it1_;
552            }
553            BOOST_UBLAS_INLINE
554            bool operator < (const iterator1 &it) const {
555                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
556                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
557                return it1_ < it.it1_;
558            }
559
560        private:
561            size_type it1_;
562            size_type it2_;
563
564            friend class const_iterator1;
565        };
566#endif
567
568        BOOST_UBLAS_INLINE
569        iterator1 begin1 () {
570            return find1 (0, 0, 0);
571        }
572        BOOST_UBLAS_INLINE
573        iterator1 end1 () {
574            return find1 (0, size_, 0);
575        }
576
577#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
578        class const_iterator2:
579            public container_const_reference<symmetric_matrix>,
580            public random_access_iterator_base<dense_random_access_iterator_tag,
581                                               const_iterator2, value_type> {
582        public:
583            typedef typename symmetric_matrix::value_type value_type;
584            typedef typename symmetric_matrix::difference_type difference_type;
585            typedef typename symmetric_matrix::const_reference reference;
586            typedef const typename symmetric_matrix::pointer pointer;
587
588            typedef const_iterator1 dual_iterator_type;
589            typedef const_reverse_iterator1 dual_reverse_iterator_type;
590
591            // Construction and destruction
592            BOOST_UBLAS_INLINE
593            const_iterator2 ():
594                container_const_reference<self_type> (), it1_ (), it2_ () {}
595            BOOST_UBLAS_INLINE
596            const_iterator2 (const self_type &m, size_type it1, size_type it2):
597                container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
598            BOOST_UBLAS_INLINE
599            const_iterator2 (const iterator2 &it):
600                container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
601
602            // Arithmetic
603            BOOST_UBLAS_INLINE
604            const_iterator2 &operator ++ () {
605                ++ it2_;
606                return *this;
607            }
608            BOOST_UBLAS_INLINE
609            const_iterator2 &operator -- () {
610                -- it2_;
611                return *this;
612            }
613            BOOST_UBLAS_INLINE
614            const_iterator2 &operator += (difference_type n) {
615                it2_ += n;
616                return *this;
617            }
618            BOOST_UBLAS_INLINE
619            const_iterator2 &operator -= (difference_type n) {
620                it2_ -= n;
621                return *this;
622            }
623            BOOST_UBLAS_INLINE
624            difference_type operator - (const const_iterator2 &it) const {
625                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
626                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
627                return it2_ - it.it2_;
628            }
629
630            // Dereference
631            BOOST_UBLAS_INLINE
632            const_reference operator * () const {
633                return (*this) () (it1_, it2_);
634            }
635
636#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
637            BOOST_UBLAS_INLINE
638#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
639            typename self_type::
640#endif
641            const_iterator1 begin () const {
642                return (*this) ().find1 (1, 0, it2_);
643            }
644            BOOST_UBLAS_INLINE
645#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
646            typename self_type::
647#endif
648            const_iterator1 end () const {
649                return (*this) ().find1 (1, (*this) ().size1 (), it2_);
650            }
651            BOOST_UBLAS_INLINE
652#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
653            typename self_type::
654#endif
655            const_reverse_iterator1 rbegin () const {
656                return const_reverse_iterator1 (end ());
657            }
658            BOOST_UBLAS_INLINE
659#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
660            typename self_type::
661#endif
662            const_reverse_iterator1 rend () const {
663                return const_reverse_iterator1 (begin ());
664            }
665#endif
666
667            // Indices
668            BOOST_UBLAS_INLINE
669            size_type index1 () const {
670                return it1_;
671            }
672            BOOST_UBLAS_INLINE
673            size_type index2 () const {
674                return it2_;
675            }
676
677            // Assignment
678            BOOST_UBLAS_INLINE
679            const_iterator2 &operator = (const const_iterator2 &it) {
680                container_const_reference<self_type>::assign (&it ());
681                it1_ = it.it1_;
682                it2_ = it.it2_;
683                return *this;
684            }
685
686            // Comparison
687            BOOST_UBLAS_INLINE
688            bool operator == (const const_iterator2 &it) const {
689                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
690                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
691                return it2_ == it.it2_;
692            }
693            BOOST_UBLAS_INLINE
694            bool operator < (const const_iterator2 &it) const {
695                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
696                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
697                return it2_ < it.it2_;
698            }
699
700        private:
701            size_type it1_;
702            size_type it2_;
703        };
704#endif
705
706        BOOST_UBLAS_INLINE
707        const_iterator2 begin2 () const {
708            return find2 (0, 0, 0);
709        }
710        BOOST_UBLAS_INLINE
711        const_iterator2 end2 () const {
712            return find2 (0, 0, size_);
713        }
714
715#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
716        class iterator2:
717            public container_reference<symmetric_matrix>,
718            public random_access_iterator_base<packed_random_access_iterator_tag,
719                                               iterator2, value_type> {
720        public:
721            typedef typename symmetric_matrix::value_type value_type;
722            typedef typename symmetric_matrix::difference_type difference_type;
723            typedef typename symmetric_matrix::reference reference;
724            typedef typename symmetric_matrix::pointer pointer;
725
726            typedef iterator1 dual_iterator_type;
727            typedef reverse_iterator1 dual_reverse_iterator_type;
728
729            // Construction and destruction
730            BOOST_UBLAS_INLINE
731            iterator2 ():
732                container_reference<self_type> (), it1_ (), it2_ () {}
733            BOOST_UBLAS_INLINE
734            iterator2 (self_type &m, size_type it1, size_type it2):
735                container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
736
737            // Arithmetic
738            BOOST_UBLAS_INLINE
739            iterator2 &operator ++ () {
740                ++ it2_;
741                return *this;
742            }
743            BOOST_UBLAS_INLINE
744            iterator2 &operator -- () {
745                -- it2_;
746                return *this;
747            }
748            BOOST_UBLAS_INLINE
749            iterator2 &operator += (difference_type n) {
750                it2_ += n;
751                return *this;
752            }
753            BOOST_UBLAS_INLINE
754            iterator2 &operator -= (difference_type n) {
755                it2_ -= n;
756                return *this;
757            }
758            BOOST_UBLAS_INLINE
759            difference_type operator - (const iterator2 &it) const {
760                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
761                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
762                return it2_ - it.it2_;
763            }
764
765            // Dereference
766            BOOST_UBLAS_INLINE
767            reference operator * () const {
768                return (*this) () (it1_, it2_);
769            }
770
771#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
772            BOOST_UBLAS_INLINE
773#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
774            typename self_type::
775#endif
776            iterator1 begin () const {
777                return (*this) ().find1 (1, 0, it2_);
778            }
779            BOOST_UBLAS_INLINE
780#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
781            typename self_type::
782#endif
783            iterator1 end () const {
784                return (*this) ().find1 (1, (*this) ().size1 (), it2_);
785            }
786            BOOST_UBLAS_INLINE
787#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
788            typename self_type::
789#endif
790            reverse_iterator1 rbegin () const {
791                return reverse_iterator1 (end ());
792            }
793            BOOST_UBLAS_INLINE
794#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
795            typename self_type::
796#endif
797            reverse_iterator1 rend () const {
798                return reverse_iterator1 (begin ());
799            }
800#endif
801
802            // Indices
803            BOOST_UBLAS_INLINE
804            size_type index1 () const {
805                return it1_;
806            }
807            BOOST_UBLAS_INLINE
808            size_type index2 () const {
809                return it2_;
810            }
811
812            // Assignment
813            BOOST_UBLAS_INLINE
814            iterator2 &operator = (const iterator2 &it) {
815                container_reference<self_type>::assign (&it ());
816                it1_ = it.it1_;
817                it2_ = it.it2_;
818                return *this;
819            }
820
821            // Comparison
822            BOOST_UBLAS_INLINE
823            bool operator == (const iterator2 &it) const {
824                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
825                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
826                return it2_ == it.it2_;
827            }
828            BOOST_UBLAS_INLINE
829            bool operator < (const iterator2 &it) const {
830                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
831                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
832                return it2_ < it.it2_;
833            }
834
835        private:
836            size_type it1_;
837            size_type it2_;
838
839            friend class const_iterator2;
840        };
841#endif
842
843        BOOST_UBLAS_INLINE
844        iterator2 begin2 () {
845            return find2 (0, 0, 0);
846        }
847        BOOST_UBLAS_INLINE
848        iterator2 end2 () {
849            return find2 (0, 0, size_);
850        }
851
852        // Reverse iterators
853
854        BOOST_UBLAS_INLINE
855        const_reverse_iterator1 rbegin1 () const {
856            return const_reverse_iterator1 (end1 ());
857        }
858        BOOST_UBLAS_INLINE
859        const_reverse_iterator1 rend1 () const {
860            return const_reverse_iterator1 (begin1 ());
861        }
862
863        BOOST_UBLAS_INLINE
864        reverse_iterator1 rbegin1 () {
865            return reverse_iterator1 (end1 ());
866        }
867        BOOST_UBLAS_INLINE
868        reverse_iterator1 rend1 () {
869            return reverse_iterator1 (begin1 ());
870        }
871
872        BOOST_UBLAS_INLINE
873        const_reverse_iterator2 rbegin2 () const {
874            return const_reverse_iterator2 (end2 ());
875        }
876        BOOST_UBLAS_INLINE
877        const_reverse_iterator2 rend2 () const {
878            return const_reverse_iterator2 (begin2 ());
879        }
880
881        BOOST_UBLAS_INLINE
882        reverse_iterator2 rbegin2 () {
883            return reverse_iterator2 (end2 ());
884        }
885        BOOST_UBLAS_INLINE
886        reverse_iterator2 rend2 () {
887            return reverse_iterator2 (begin2 ());
888        }
889
890    private:
891        size_type size_;
892        array_type data_;
893    };
894
895
896    // Symmetric matrix adaptor class
897    template<class M, class TRI>
898    class symmetric_adaptor:
899        public matrix_expression<symmetric_adaptor<M, TRI> > {
900
901        typedef symmetric_adaptor<M, TRI> self_type;
902    public:
903#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
904        using matrix_expression<self_type>::operator ();
905#endif
906        typedef const M const_matrix_type;
907        typedef M matrix_type;
908        typedef TRI triangular_type;
909        typedef typename M::size_type size_type;
910        typedef typename M::difference_type difference_type;
911        typedef typename M::value_type value_type;
912        typedef typename M::const_reference const_reference;
913        typedef typename boost::mpl::if_<boost::is_const<M>,
914                                          typename M::const_reference,
915                                          typename M::reference>::type reference;
916        typedef typename boost::mpl::if_<boost::is_const<M>,
917                                          typename M::const_closure_type,
918                                          typename M::closure_type>::type matrix_closure_type;
919        typedef const self_type const_closure_type;
920        typedef self_type closure_type;
921        // Replaced by _temporary_traits to avoid type requirements on M
922        //typedef typename M::vector_temporary_type vector_temporary_type;
923        //typedef typename M::matrix_temporary_type matrix_temporary_type;
924        typedef typename storage_restrict_traits<typename M::storage_category,
925                                                 packed_proxy_tag>::storage_category storage_category;
926        typedef typename M::orientation_category orientation_category;
927
928        // Construction and destruction
929        BOOST_UBLAS_INLINE
930        symmetric_adaptor (matrix_type &data):
931            matrix_expression<self_type> (),
932            data_ (data) {
933            BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
934        }
935        BOOST_UBLAS_INLINE
936        symmetric_adaptor (const symmetric_adaptor &m):
937            matrix_expression<self_type> (),
938            data_ (m.data_) {
939            BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
940        }
941
942        // Accessors
943        BOOST_UBLAS_INLINE
944        size_type size1 () const {
945            return data_.size1 ();
946        }
947        BOOST_UBLAS_INLINE
948        size_type size2 () const {
949            return data_.size2 ();
950        }
951
952        // Storage accessors
953        BOOST_UBLAS_INLINE
954        const matrix_closure_type &data () const {
955            return data_;
956        }
957        BOOST_UBLAS_INLINE
958        matrix_closure_type &data () {
959            return data_;
960        }
961
962        // Element access
963#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
964        BOOST_UBLAS_INLINE
965        const_reference operator () (size_type i, size_type j) const {
966            BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
967            BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
968            if (triangular_type::other (i, j))
969                return data () (i, j);
970            else
971                return data () (j, i);
972        }
973        BOOST_UBLAS_INLINE
974        reference operator () (size_type i, size_type j) {
975            BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
976            BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
977            if (triangular_type::other (i, j))
978                return data () (i, j);
979            else
980                return data () (j, i);
981        }
982#else
983        BOOST_UBLAS_INLINE
984        reference operator () (size_type i, size_type j) const {
985            BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
986            BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
987            if (triangular_type::other (i, j))
988                return data () (i, j);
989            else
990                return data () (j, i);
991        }
992#endif
993
994        // Assignment
995        BOOST_UBLAS_INLINE
996        symmetric_adaptor &operator = (const symmetric_adaptor &m) {
997            matrix_assign<scalar_assign, triangular_type> (*this, m);
998            return *this;
999        }
1000        BOOST_UBLAS_INLINE
1001        symmetric_adaptor &assign_temporary (symmetric_adaptor &m) {
1002            *this = m;
1003            return *this;
1004        }
1005        template<class AE>
1006        BOOST_UBLAS_INLINE
1007        symmetric_adaptor &operator = (const matrix_expression<AE> &ae) {
1008            matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae));
1009            return *this;
1010        }
1011        template<class AE>
1012        BOOST_UBLAS_INLINE
1013        symmetric_adaptor &assign (const matrix_expression<AE> &ae) {
1014            matrix_assign<scalar_assign, triangular_type> (*this, ae);
1015            return *this;
1016        }
1017        template<class AE>
1018        BOOST_UBLAS_INLINE
1019        symmetric_adaptor& operator += (const matrix_expression<AE> &ae) {
1020            matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae));
1021            return *this;
1022        }
1023        template<class AE>
1024        BOOST_UBLAS_INLINE
1025        symmetric_adaptor &plus_assign (const matrix_expression<AE> &ae) {
1026            matrix_assign<scalar_plus_assign, triangular_type> (*this, ae);
1027            return *this;
1028        }
1029        template<class AE>
1030        BOOST_UBLAS_INLINE
1031        symmetric_adaptor& operator -= (const matrix_expression<AE> &ae) {
1032            matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae));
1033            return *this;
1034        }
1035        template<class AE>
1036        BOOST_UBLAS_INLINE
1037        symmetric_adaptor &minus_assign (const matrix_expression<AE> &ae) {
1038            matrix_assign<scalar_minus_assign, triangular_type> (*this, ae);
1039            return *this;
1040        }
1041        template<class AT>
1042        BOOST_UBLAS_INLINE
1043        symmetric_adaptor& operator *= (const AT &at) {
1044            matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
1045            return *this;
1046        }
1047        template<class AT>
1048        BOOST_UBLAS_INLINE
1049        symmetric_adaptor& operator /= (const AT &at) {
1050            matrix_assign_scalar<scalar_divides_assign> (*this, at);
1051            return *this;
1052        }
1053
1054        // Closure comparison
1055        BOOST_UBLAS_INLINE
1056        bool same_closure (const symmetric_adaptor &sa) const {
1057            return (*this).data ().same_closure (sa.data ());
1058       }
1059
1060        // Swapping
1061        BOOST_UBLAS_INLINE
1062        void swap (symmetric_adaptor &m) {
1063            if (this != &m)
1064                matrix_swap<scalar_swap, triangular_type> (*this, m);
1065        }
1066        BOOST_UBLAS_INLINE
1067        friend void swap (symmetric_adaptor &m1, symmetric_adaptor &m2) {
1068            m1.swap (m2);
1069        }
1070
1071        // Iterator types
1072    private:
1073        // Use matrix iterator
1074        typedef typename M::const_iterator1 const_subiterator1_type;
1075        typedef typename boost::mpl::if_<boost::is_const<M>,
1076                                          typename M::const_iterator1,
1077                                          typename M::iterator1>::type subiterator1_type;
1078        typedef typename M::const_iterator2 const_subiterator2_type;
1079        typedef typename boost::mpl::if_<boost::is_const<M>,
1080                                          typename M::const_iterator2,
1081                                          typename M::iterator2>::type subiterator2_type;
1082
1083    public:
1084#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1085        typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
1086        typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
1087        typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
1088        typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
1089#else
1090        class const_iterator1;
1091        class iterator1;
1092        class const_iterator2;
1093        class iterator2;
1094#endif
1095        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1096        typedef reverse_iterator_base1<iterator1> reverse_iterator1;
1097        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1098        typedef reverse_iterator_base2<iterator2> reverse_iterator2;
1099
1100        // Element lookup
1101        BOOST_UBLAS_INLINE
1102        const_iterator1 find1 (int rank, size_type i, size_type j) const {
1103            if (triangular_type::other (i, j)) {
1104                if (triangular_type::other (size1 (), j)) {
1105                    return const_iterator1 (*this, 0, 0,
1106                                            data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j),
1107                                            data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ()));
1108                } else {
1109                    return const_iterator1 (*this, 0, 1,
1110                                            data ().find1 (rank, i, j), data ().find1 (rank, j, j),
1111                                            data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ()));
1112                }
1113            } else {
1114                if (triangular_type::other (size1 (), j)) {
1115                    return const_iterator1 (*this, 1, 0,
1116                                            data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j),
1117                                            data ().find2 (rank, j, i), data ().find2 (rank, j, j));
1118                } else {
1119                    return const_iterator1 (*this, 1, 1,
1120                                            data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()),
1121                                            data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ()));
1122                }
1123            }
1124        }
1125        BOOST_UBLAS_INLINE
1126        iterator1 find1 (int rank, size_type i, size_type j) {
1127            if (rank == 1)
1128                i = triangular_type::mutable_restrict1 (i, j);
1129            return iterator1 (*this, data ().find1 (rank, i, j));
1130        }
1131        BOOST_UBLAS_INLINE
1132        const_iterator2 find2 (int rank, size_type i, size_type j) const {
1133            if (triangular_type::other (i, j)) {
1134                if (triangular_type::other (i, size2 ())) {
1135                    return const_iterator2 (*this, 1, 1,
1136                                            data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()),
1137                                            data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ()));
1138                } else {
1139                    return const_iterator2 (*this, 1, 0,
1140                                            data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i),
1141                                            data ().find2 (rank, i, j), data ().find2 (rank, i, i));
1142                }
1143            } else {
1144                if (triangular_type::other (i, size2 ())) {
1145                    return const_iterator2 (*this, 0, 1,
1146                                            data ().find1 (rank, j, i), data ().find1 (rank, i, i),
1147                                            data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ()));
1148                } else {
1149                    return const_iterator2 (*this, 0, 0,
1150                                            data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i),
1151                                            data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ()));
1152                }
1153            }
1154        }
1155        BOOST_UBLAS_INLINE
1156        iterator2 find2 (int rank, size_type i, size_type j) {
1157            if (rank == 1)
1158                j = triangular_type::mutable_restrict2 (i, j);
1159            return iterator2 (*this, data ().find2 (rank, i, j));
1160        }
1161
1162        // Iterators simply are indices.
1163
1164#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1165        class const_iterator1:
1166            public container_const_reference<symmetric_adaptor>,
1167            public random_access_iterator_base<typename iterator_restrict_traits<
1168                                                   typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
1169                                               const_iterator1, value_type> {
1170        public:
1171            typedef typename const_subiterator1_type::value_type value_type;
1172            typedef typename const_subiterator1_type::difference_type difference_type;
1173            typedef typename const_subiterator1_type::reference reference;
1174            typedef typename const_subiterator1_type::pointer pointer;
1175
1176            typedef const_iterator2 dual_iterator_type;
1177            typedef const_reverse_iterator2 dual_reverse_iterator_type;
1178
1179            // Construction and destruction
1180            BOOST_UBLAS_INLINE
1181            const_iterator1 ():
1182                container_const_reference<self_type> (),
1183                begin_ (-1), end_ (-1), current_ (-1),
1184                it1_begin_ (), it1_end_ (), it1_ (),
1185                it2_begin_ (), it2_end_ (), it2_ () {}
1186            BOOST_UBLAS_INLINE
1187            const_iterator1 (const self_type &m, int begin, int end,
1188                             const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
1189                             const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
1190                container_const_reference<self_type> (m),
1191                begin_ (begin), end_ (end), current_ (begin),
1192                it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
1193                it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
1194                if (current_ == 0 && it1_ == it1_end_)
1195                    current_ = 1;
1196                if (current_ == 1 && it2_ == it2_end_)
1197                    current_ = 0;
1198                if ((current_ == 0 && it1_ == it1_end_) ||
1199                    (current_ == 1 && it2_ == it2_end_))
1200                    current_ = end_;
1201                BOOST_UBLAS_CHECK (current_ == end_ ||
1202                                   (current_ == 0 && it1_ != it1_end_) ||
1203                                   (current_ == 1 && it2_ != it2_end_), internal_logic ());
1204            }
1205            // FIXME cannot compile
1206            //  iterator1 does not have these members!
1207            BOOST_UBLAS_INLINE
1208            const_iterator1 (const iterator1 &it):
1209                container_const_reference<self_type> (it ()),
1210                begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
1211                it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
1212                it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
1213                BOOST_UBLAS_CHECK (current_ == end_ ||
1214                                   (current_ == 0 && it1_ != it1_end_) ||
1215                                   (current_ == 1 && it2_ != it2_end_), internal_logic ());
1216            }
1217
1218            // Arithmetic
1219            BOOST_UBLAS_INLINE
1220            const_iterator1 &operator ++ () {
1221                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1222                if (current_ == 0) {
1223                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1224                    ++ it1_;
1225                    if (it1_ == it1_end_ && end_ == 1) {
1226                        it2_ = it2_begin_;
1227                        current_ = 1;
1228                    }
1229                } else /* if (current_ == 1) */ {
1230                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1231                    ++ it2_;
1232                    if (it2_ == it2_end_ && end_ == 0) {
1233                        it1_ = it1_begin_;
1234                        current_ = 0;
1235                    }
1236                }
1237                return *this;
1238            }
1239            BOOST_UBLAS_INLINE
1240            const_iterator1 &operator -- () {
1241                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1242                if (current_ == 0) {
1243                    if (it1_ == it1_begin_ && begin_ == 1) {
1244                        it2_ = it2_end_;
1245                        BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
1246                        -- it2_;
1247                        current_ = 1;
1248                    } else {
1249                        -- it1_;
1250                    }
1251                } else /* if (current_ == 1) */ {
1252                    if (it2_ == it2_begin_ && begin_ == 0) {
1253                        it1_ = it1_end_;
1254                        BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
1255                        -- it1_;
1256                        current_ = 0;
1257                    } else {
1258                        -- it2_;
1259                    }
1260                }
1261                return *this;
1262            }
1263            BOOST_UBLAS_INLINE
1264            const_iterator1 &operator += (difference_type n) {
1265                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1266                if (current_ == 0) {
1267                    size_type d = (std::min) (n, it1_end_ - it1_);
1268                    it1_ += d;
1269                    n -= d;
1270                    if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
1271                        BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1272                        d = (std::min) (n, it2_end_ - it2_begin_);
1273                        it2_ = it2_begin_ + d;
1274                        n -= d;
1275                        current_ = 1;
1276                    }
1277                } else /* if (current_ == 1) */ {
1278                    size_type d = (std::min) (n, it2_end_ - it2_);
1279                    it2_ += d;
1280                    n -= d;
1281                    if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
1282                        BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1283                        d = (std::min) (n, it1_end_ - it1_begin_);
1284                        it1_ = it1_begin_ + d;
1285                        n -= d;
1286                        current_ = 0;
1287                    }
1288                }
1289                BOOST_UBLAS_CHECK (n == 0, external_logic ());
1290                return *this;
1291            }
1292            BOOST_UBLAS_INLINE
1293            const_iterator1 &operator -= (difference_type n) {
1294                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1295                if (current_ == 0) {
1296                    size_type d = (std::min) (n, it1_ - it1_begin_);
1297                    it1_ -= d;
1298                    n -= d;
1299                    if (n > 0) {
1300                        BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1301                        d = (std::min) (n, it2_end_ - it2_begin_);
1302                        it2_ = it2_end_ - d;
1303                        n -= d;
1304                        current_ = 1;
1305                    }
1306                } else /* if (current_ == 1) */ {
1307                    size_type d = (std::min) (n, it2_ - it2_begin_);
1308                    it2_ -= d;
1309                    n -= d;
1310                    if (n > 0) {
1311                        BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1312                        d = (std::min) (n, it1_end_ - it1_begin_);
1313                        it1_ = it1_end_ - d;
1314                        n -= d;
1315                        current_ = 0;
1316                    }
1317                }
1318                BOOST_UBLAS_CHECK (n == 0, external_logic ());
1319                return *this;
1320            }
1321            BOOST_UBLAS_INLINE
1322            difference_type operator - (const const_iterator1 &it) const {
1323                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1324                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1325                BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1326                BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1327                if (current_ == 0 && it.current_ == 0) {
1328                    return it1_ - it.it1_;
1329                } else if (current_ == 0 && it.current_ == 1) {
1330                    if (end_ == 1 && it.end_ == 1) {
1331                        return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
1332                    } else /* if (end_ == 0 && it.end_ == 0) */ {
1333                        return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
1334                    }
1335
1336                } else if (current_ == 1 && it.current_ == 0) {
1337                    if (end_ == 1 && it.end_ == 1) {
1338                        return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
1339                    } else /* if (end_ == 0 && it.end_ == 0) */ {
1340                        return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
1341                    }
1342                } else /* if (current_ == 1 && it.current_ == 1) */ {
1343                    return it2_ - it.it2_;
1344                }
1345                return 0; /* avoid compiler warnings */
1346            }
1347
1348            // Dereference
1349            BOOST_UBLAS_INLINE
1350            const_reference operator * () const {
1351                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1352                if (current_ == 0) {
1353                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1354                    return *it1_;
1355                } else /* if (current_ == 1) */ {
1356                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1357                    return *it2_;
1358                }
1359            }
1360
1361#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1362            BOOST_UBLAS_INLINE
1363#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1364            typename self_type::
1365#endif
1366            const_iterator2 begin () const {
1367                return (*this) ().find2 (1, index1 (), 0);
1368            }
1369            BOOST_UBLAS_INLINE
1370#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1371            typename self_type::
1372#endif
1373            const_iterator2 end () const {
1374                return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1375            }
1376            BOOST_UBLAS_INLINE
1377#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1378            typename self_type::
1379#endif
1380            const_reverse_iterator2 rbegin () const {
1381                return const_reverse_iterator2 (end ());
1382            }
1383            BOOST_UBLAS_INLINE
1384#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1385            typename self_type::
1386#endif
1387            const_reverse_iterator2 rend () const {
1388                return const_reverse_iterator2 (begin ());
1389            }
1390#endif
1391
1392            // Indices
1393            BOOST_UBLAS_INLINE
1394            size_type index1 () const {
1395                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1396                if (current_ == 0) {
1397                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1398                    return it1_.index1 ();
1399                } else /* if (current_ == 1) */ {
1400                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1401                    return it2_.index2 ();
1402                }
1403            }
1404            BOOST_UBLAS_INLINE
1405            size_type index2 () const {
1406                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1407                if (current_ == 0) {
1408                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1409                    return it1_.index2 ();
1410                } else /* if (current_ == 1) */ {
1411                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1412                    return it2_.index1 ();
1413                }
1414            }
1415
1416            // Assignment
1417            BOOST_UBLAS_INLINE
1418            const_iterator1 &operator = (const const_iterator1 &it) {
1419                container_const_reference<self_type>::assign (&it ());
1420                begin_ = it.begin_;
1421                end_ = it.end_;
1422                current_ = it.current_;
1423                it1_begin_ = it.it1_begin_;
1424                it1_end_ = it.it1_end_;
1425                it1_ = it.it1_;
1426                it2_begin_ = it.it2_begin_;
1427                it2_end_ = it.it2_end_;
1428                it2_ = it.it2_;
1429                return *this;
1430            }
1431
1432            // Comparison
1433            BOOST_UBLAS_INLINE
1434            bool operator == (const const_iterator1 &it) const {
1435                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1436                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1437                BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1438                BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1439                return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
1440                       (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
1441            }
1442            BOOST_UBLAS_INLINE
1443            bool operator < (const const_iterator1 &it) const {
1444                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1445                return it - *this > 0;
1446            }
1447
1448        private:
1449            int begin_;
1450            int end_;
1451            int current_;
1452            const_subiterator1_type it1_begin_;
1453            const_subiterator1_type it1_end_;
1454            const_subiterator1_type it1_;
1455            const_subiterator2_type it2_begin_;
1456            const_subiterator2_type it2_end_;
1457            const_subiterator2_type it2_;
1458        };
1459#endif
1460
1461        BOOST_UBLAS_INLINE
1462        const_iterator1 begin1 () const {
1463            return find1 (0, 0, 0);
1464        }
1465        BOOST_UBLAS_INLINE
1466        const_iterator1 end1 () const {
1467            return find1 (0, size1 (), 0);
1468        }
1469
1470#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1471        class iterator1:
1472            public container_reference<symmetric_adaptor>,
1473            public random_access_iterator_base<typename iterator_restrict_traits<
1474                                                   typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1475                                               iterator1, value_type> {
1476        public:
1477            typedef typename subiterator1_type::value_type value_type;
1478            typedef typename subiterator1_type::difference_type difference_type;
1479            typedef typename subiterator1_type::reference reference;
1480            typedef typename subiterator1_type::pointer pointer;
1481
1482            typedef iterator2 dual_iterator_type;
1483            typedef reverse_iterator2 dual_reverse_iterator_type;
1484
1485            // Construction and destruction
1486            BOOST_UBLAS_INLINE
1487            iterator1 ():
1488                container_reference<self_type> (), it1_ () {}
1489            BOOST_UBLAS_INLINE
1490            iterator1 (self_type &m, const subiterator1_type &it1):
1491                container_reference<self_type> (m), it1_ (it1) {}
1492
1493            // Arithmetic
1494            BOOST_UBLAS_INLINE
1495            iterator1 &operator ++ () {
1496                ++ it1_;
1497                return *this;
1498            }
1499            BOOST_UBLAS_INLINE
1500            iterator1 &operator -- () {
1501                -- it1_;
1502                return *this;
1503            }
1504            BOOST_UBLAS_INLINE
1505            iterator1 &operator += (difference_type n) {
1506                it1_ += n;
1507                return *this;
1508            }
1509            BOOST_UBLAS_INLINE
1510            iterator1 &operator -= (difference_type n) {
1511                it1_ -= n;
1512                return *this;
1513            }
1514            BOOST_UBLAS_INLINE
1515            difference_type operator - (const iterator1 &it) const {
1516                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1517                return it1_ - it.it1_;
1518            }
1519
1520            // Dereference
1521            BOOST_UBLAS_INLINE
1522            reference operator * () const {
1523                return *it1_;
1524            }
1525
1526#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1527            BOOST_UBLAS_INLINE
1528#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1529            typename self_type::
1530#endif
1531            iterator2 begin () const {
1532                return (*this) ().find2 (1, index1 (), 0);
1533            }
1534            BOOST_UBLAS_INLINE
1535#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1536            typename self_type::
1537#endif
1538            iterator2 end () const {
1539                return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1540            }
1541            BOOST_UBLAS_INLINE
1542#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1543            typename self_type::
1544#endif
1545            reverse_iterator2 rbegin () const {
1546                return reverse_iterator2 (end ());
1547            }
1548            BOOST_UBLAS_INLINE
1549#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1550            typename self_type::
1551#endif
1552            reverse_iterator2 rend () const {
1553                return reverse_iterator2 (begin ());
1554            }
1555#endif
1556
1557            // Indices
1558            BOOST_UBLAS_INLINE
1559            size_type index1 () const {
1560                return it1_.index1 ();
1561            }
1562            BOOST_UBLAS_INLINE
1563            size_type index2 () const {
1564                return it1_.index2 ();
1565            }
1566
1567            // Assignment
1568            BOOST_UBLAS_INLINE
1569            iterator1 &operator = (const iterator1 &it) {
1570                container_reference<self_type>::assign (&it ());
1571                it1_ = it.it1_;
1572                return *this;
1573            }
1574
1575            // Comparison
1576            BOOST_UBLAS_INLINE
1577            bool operator == (const iterator1 &it) const {
1578                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1579                return it1_ == it.it1_;
1580            }
1581            BOOST_UBLAS_INLINE
1582            bool operator < (const iterator1 &it) const {
1583                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1584                return it1_ < it.it1_;
1585            }
1586
1587        private:
1588            subiterator1_type it1_;
1589
1590            friend class const_iterator1;
1591        };
1592#endif
1593
1594        BOOST_UBLAS_INLINE
1595        iterator1 begin1 () {
1596            return find1 (0, 0, 0);
1597        }
1598        BOOST_UBLAS_INLINE
1599        iterator1 end1 () {
1600            return find1 (0, size1 (), 0);
1601        }
1602
1603#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1604        class const_iterator2:
1605            public container_const_reference<symmetric_adaptor>,
1606            public random_access_iterator_base<typename iterator_restrict_traits<
1607                                                   typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
1608                                               const_iterator2, value_type> {
1609        public:
1610            typedef typename const_subiterator2_type::value_type value_type;
1611            typedef typename const_subiterator2_type::difference_type difference_type;
1612            typedef typename const_subiterator2_type::reference reference;
1613            typedef typename const_subiterator2_type::pointer pointer;
1614
1615            typedef const_iterator1 dual_iterator_type;
1616            typedef const_reverse_iterator1 dual_reverse_iterator_type;
1617
1618            // Construction and destruction
1619            BOOST_UBLAS_INLINE
1620            const_iterator2 ():
1621                container_const_reference<self_type> (),
1622                begin_ (-1), end_ (-1), current_ (-1),
1623                it1_begin_ (), it1_end_ (), it1_ (),
1624                it2_begin_ (), it2_end_ (), it2_ () {}
1625            BOOST_UBLAS_INLINE
1626            const_iterator2 (const self_type &m, int begin, int end,
1627                             const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
1628                             const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
1629                container_const_reference<self_type> (m),
1630                begin_ (begin), end_ (end), current_ (begin),
1631                it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
1632                it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
1633                if (current_ == 0 && it1_ == it1_end_)
1634                    current_ = 1;
1635                if (current_ == 1 && it2_ == it2_end_)
1636                    current_ = 0;
1637                if ((current_ == 0 && it1_ == it1_end_) ||
1638                    (current_ == 1 && it2_ == it2_end_))
1639                    current_ = end_;
1640                BOOST_UBLAS_CHECK (current_ == end_ ||
1641                                   (current_ == 0 && it1_ != it1_end_) ||
1642                                   (current_ == 1 && it2_ != it2_end_), internal_logic ());
1643            }
1644            // FIXME cannot compiler
1645            //  iterator2 does not have these members!
1646            BOOST_UBLAS_INLINE
1647            const_iterator2 (const iterator2 &it):
1648                container_const_reference<self_type> (it ()),
1649                begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
1650                it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
1651                it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
1652                BOOST_UBLAS_CHECK (current_ == end_ ||
1653                                   (current_ == 0 && it1_ != it1_end_) ||
1654                                   (current_ == 1 && it2_ != it2_end_), internal_logic ());
1655            }
1656
1657            // Arithmetic
1658            BOOST_UBLAS_INLINE
1659            const_iterator2 &operator ++ () {
1660                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1661                if (current_ == 0) {
1662                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1663                    ++ it1_;
1664                    if (it1_ == it1_end_ && end_ == 1) {
1665                        it2_ = it2_begin_;
1666                        current_ = 1;
1667                    }
1668                } else /* if (current_ == 1) */ {
1669                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1670                    ++ it2_;
1671                    if (it2_ == it2_end_ && end_ == 0) {
1672                        it1_ = it1_begin_;
1673                        current_ = 0;
1674                    }
1675                }
1676                return *this;
1677            }
1678            BOOST_UBLAS_INLINE
1679            const_iterator2 &operator -- () {
1680                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1681                if (current_ == 0) {
1682                    if (it1_ == it1_begin_ && begin_ == 1) {
1683                        it2_ = it2_end_;
1684                        BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
1685                        -- it2_;
1686                        current_ = 1;
1687                    } else {
1688                        -- it1_;
1689                    }
1690                } else /* if (current_ == 1) */ {
1691                    if (it2_ == it2_begin_ && begin_ == 0) {
1692                        it1_ = it1_end_;
1693                        BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
1694                        -- it1_;
1695                        current_ = 0;
1696                    } else {
1697                        -- it2_;
1698                    }
1699                }
1700                return *this;
1701            }
1702            BOOST_UBLAS_INLINE
1703            const_iterator2 &operator += (difference_type n) {
1704                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1705                if (current_ == 0) {
1706                    size_type d = (std::min) (n, it1_end_ - it1_);
1707                    it1_ += d;
1708                    n -= d;
1709                    if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
1710                        BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1711                        d = (std::min) (n, it2_end_ - it2_begin_);
1712                        it2_ = it2_begin_ + d;
1713                        n -= d;
1714                        current_ = 1;
1715                    }
1716                } else /* if (current_ == 1) */ {
1717                    size_type d = (std::min) (n, it2_end_ - it2_);
1718                    it2_ += d;
1719                    n -= d;
1720                    if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
1721                        BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1722                        d = (std::min) (n, it1_end_ - it1_begin_);
1723                        it1_ = it1_begin_ + d;
1724                        n -= d;
1725                        current_ = 0;
1726                    }
1727                }
1728                BOOST_UBLAS_CHECK (n == 0, external_logic ());
1729                return *this;
1730            }
1731            BOOST_UBLAS_INLINE
1732            const_iterator2 &operator -= (difference_type n) {
1733                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1734                if (current_ == 0) {
1735                    size_type d = (std::min) (n, it1_ - it1_begin_);
1736                    it1_ -= d;
1737                    n -= d;
1738                    if (n > 0) {
1739                        BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1740                        d = (std::min) (n, it2_end_ - it2_begin_);
1741                        it2_ = it2_end_ - d;
1742                        n -= d;
1743                        current_ = 1;
1744                    }
1745                } else /* if (current_ == 1) */ {
1746                    size_type d = (std::min) (n, it2_ - it2_begin_);
1747                    it2_ -= d;
1748                    n -= d;
1749                    if (n > 0) {
1750                        BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1751                        d = (std::min) (n, it1_end_ - it1_begin_);
1752                        it1_ = it1_end_ - d;
1753                        n -= d;
1754                        current_ = 0;
1755                    }
1756                }
1757                BOOST_UBLAS_CHECK (n == 0, external_logic ());
1758                return *this;
1759            }
1760            BOOST_UBLAS_INLINE
1761            difference_type operator - (const const_iterator2 &it) const {
1762                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1763                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1764                BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1765                BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1766                if (current_ == 0 && it.current_ == 0) {
1767                    return it1_ - it.it1_;
1768                } else if (current_ == 0 && it.current_ == 1) {
1769                    if (end_ == 1 && it.end_ == 1) {
1770                        return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
1771                    } else /* if (end_ == 0 && it.end_ == 0) */ {
1772                        return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
1773                    }
1774
1775                } else if (current_ == 1 && it.current_ == 0) {
1776                    if (end_ == 1 && it.end_ == 1) {
1777                        return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
1778                    } else /* if (end_ == 0 && it.end_ == 0) */ {
1779                        return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
1780                    }
1781                } else /* if (current_ == 1 && it.current_ == 1) */ {
1782                    return it2_ - it.it2_;
1783                }
1784                return 0; /* avoid compiler warnings */
1785            }
1786
1787            // Dereference
1788            BOOST_UBLAS_INLINE
1789            const_reference operator * () const {
1790                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1791                if (current_ == 0) {
1792                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1793                    return *it1_;
1794                } else /* if (current_ == 1) */ {
1795                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1796                    return *it2_;
1797                }
1798            }
1799
1800#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1801            BOOST_UBLAS_INLINE
1802#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1803            typename self_type::
1804#endif
1805            const_iterator1 begin () const {
1806                return (*this) ().find1 (1, 0, index2 ());
1807            }
1808            BOOST_UBLAS_INLINE
1809#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1810            typename self_type::
1811#endif
1812            const_iterator1 end () const {
1813                return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1814            }
1815            BOOST_UBLAS_INLINE
1816#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1817            typename self_type::
1818#endif
1819            const_reverse_iterator1 rbegin () const {
1820                return const_reverse_iterator1 (end ());
1821            }
1822            BOOST_UBLAS_INLINE
1823#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1824            typename self_type::
1825#endif
1826            const_reverse_iterator1 rend () const {
1827                return const_reverse_iterator1 (begin ());
1828            }
1829#endif
1830
1831            // Indices
1832            BOOST_UBLAS_INLINE
1833            size_type index1 () const {
1834                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1835                if (current_ == 0) {
1836                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1837                    return it1_.index2 ();
1838                } else /* if (current_ == 1) */ {
1839                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1840                    return it2_.index1 ();
1841                }
1842            }
1843            BOOST_UBLAS_INLINE
1844            size_type index2 () const {
1845                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1846                if (current_ == 0) {
1847                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1848                    return it1_.index1 ();
1849                } else /* if (current_ == 1) */ {
1850                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1851                    return it2_.index2 ();
1852                }
1853            }
1854
1855            // Assignment
1856            BOOST_UBLAS_INLINE
1857            const_iterator2 &operator = (const const_iterator2 &it) {
1858                container_const_reference<self_type>::assign (&it ());
1859                begin_ = it.begin_;
1860                end_ = it.end_;
1861                current_ = it.current_;
1862                it1_begin_ = it.it1_begin_;
1863                it1_end_ = it.it1_end_;
1864                it1_ = it.it1_;
1865                it2_begin_ = it.it2_begin_;
1866                it2_end_ = it.it2_end_;
1867                it2_ = it.it2_;
1868                return *this;
1869            }
1870
1871            // Comparison
1872            BOOST_UBLAS_INLINE
1873            bool operator == (const const_iterator2 &it) const {
1874                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1875                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1876                BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1877                BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1878                return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
1879                       (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
1880            }
1881            BOOST_UBLAS_INLINE
1882            bool operator < (const const_iterator2 &it) const {
1883                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1884                return it - *this > 0;
1885            }
1886
1887        private:
1888            int begin_;
1889            int end_;
1890            int current_;
1891            const_subiterator1_type it1_begin_;
1892            const_subiterator1_type it1_end_;
1893            const_subiterator1_type it1_;
1894            const_subiterator2_type it2_begin_;
1895            const_subiterator2_type it2_end_;
1896            const_subiterator2_type it2_;
1897        };
1898#endif
1899
1900        BOOST_UBLAS_INLINE
1901        const_iterator2 begin2 () const {
1902            return find2 (0, 0, 0);
1903        }
1904        BOOST_UBLAS_INLINE
1905        const_iterator2 end2 () const {
1906            return find2 (0, 0, size2 ());
1907        }
1908
1909#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1910        class iterator2:
1911            public container_reference<symmetric_adaptor>,
1912            public random_access_iterator_base<typename iterator_restrict_traits<
1913                                                   typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1914                                               iterator2, value_type> {
1915        public:
1916            typedef typename subiterator2_type::value_type value_type;
1917            typedef typename subiterator2_type::difference_type difference_type;
1918            typedef typename subiterator2_type::reference reference;
1919            typedef typename subiterator2_type::pointer pointer;
1920
1921            typedef iterator1 dual_iterator_type;
1922            typedef reverse_iterator1 dual_reverse_iterator_type;
1923
1924            // Construction and destruction
1925            BOOST_UBLAS_INLINE
1926            iterator2 ():
1927                container_reference<self_type> (), it2_ () {}
1928            BOOST_UBLAS_INLINE
1929            iterator2 (self_type &m, const subiterator2_type &it2):
1930                container_reference<self_type> (m), it2_ (it2) {}
1931
1932            // Arithmetic
1933            BOOST_UBLAS_INLINE
1934            iterator2 &operator ++ () {
1935                ++ it2_;
1936                return *this;
1937            }
1938            BOOST_UBLAS_INLINE
1939            iterator2 &operator -- () {
1940                -- it2_;
1941                return *this;
1942            }
1943            BOOST_UBLAS_INLINE
1944            iterator2 &operator += (difference_type n) {
1945                it2_ += n;
1946                return *this;
1947            }
1948            BOOST_UBLAS_INLINE
1949            iterator2 &operator -= (difference_type n) {
1950                it2_ -= n;
1951                return *this;
1952            }
1953            BOOST_UBLAS_INLINE
1954            difference_type operator - (const iterator2 &it) const {
1955                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1956                return it2_ - it.it2_;
1957            }
1958
1959            // Dereference
1960            BOOST_UBLAS_INLINE
1961            reference operator * () const {
1962                return *it2_;
1963            }
1964
1965#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1966            BOOST_UBLAS_INLINE
1967#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1968            typename self_type::
1969#endif
1970            iterator1 begin () const {
1971                return (*this) ().find1 (1, 0, index2 ());
1972            }
1973            BOOST_UBLAS_INLINE
1974#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1975            typename self_type::
1976#endif
1977            iterator1 end () const {
1978                return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1979            }
1980            BOOST_UBLAS_INLINE
1981#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1982            typename self_type::
1983#endif
1984            reverse_iterator1 rbegin () const {
1985                return reverse_iterator1 (end ());
1986            }
1987            BOOST_UBLAS_INLINE
1988#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1989            typename self_type::
1990#endif
1991            reverse_iterator1 rend () const {
1992                return reverse_iterator1 (begin ());
1993            }
1994#endif
1995
1996            // Indices
1997            BOOST_UBLAS_INLINE
1998            size_type index1 () const {
1999                return it2_.index1 ();
2000            }
2001            BOOST_UBLAS_INLINE
2002            size_type index2 () const {
2003                return it2_.index2 ();
2004            }
2005
2006            // Assignment
2007            BOOST_UBLAS_INLINE
2008            iterator2 &operator = (const iterator2 &it) {
2009                container_reference<self_type>::assign (&it ());
2010                it2_ = it.it2_;
2011                return *this;
2012            }
2013
2014            // Comparison
2015            BOOST_UBLAS_INLINE
2016            bool operator == (const iterator2 &it) const {
2017                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2018                return it2_ == it.it2_;
2019            }
2020            BOOST_UBLAS_INLINE
2021            bool operator < (const iterator2 &it) const {
2022                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2023                return it2_ < it.it2_;
2024            }
2025
2026        private:
2027            subiterator2_type it2_;
2028
2029            friend class const_iterator2;
2030        };
2031#endif
2032
2033        BOOST_UBLAS_INLINE
2034        iterator2 begin2 () {
2035            return find2 (0, 0, 0);
2036        }
2037        BOOST_UBLAS_INLINE
2038        iterator2 end2 () {
2039            return find2 (0, 0, size2 ());
2040        }
2041
2042        // Reverse iterators
2043
2044        BOOST_UBLAS_INLINE
2045        const_reverse_iterator1 rbegin1 () const {
2046            return const_reverse_iterator1 (end1 ());
2047        }
2048        BOOST_UBLAS_INLINE
2049        const_reverse_iterator1 rend1 () const {
2050            return const_reverse_iterator1 (begin1 ());
2051        }
2052
2053        BOOST_UBLAS_INLINE
2054        reverse_iterator1 rbegin1 () {
2055            return reverse_iterator1 (end1 ());
2056        }
2057        BOOST_UBLAS_INLINE
2058        reverse_iterator1 rend1 () {
2059            return reverse_iterator1 (begin1 ());
2060        }
2061
2062        BOOST_UBLAS_INLINE
2063        const_reverse_iterator2 rbegin2 () const {
2064            return const_reverse_iterator2 (end2 ());
2065        }
2066        BOOST_UBLAS_INLINE
2067        const_reverse_iterator2 rend2 () const {
2068            return const_reverse_iterator2 (begin2 ());
2069        }
2070
2071        BOOST_UBLAS_INLINE
2072        reverse_iterator2 rbegin2 () {
2073            return reverse_iterator2 (end2 ());
2074        }
2075        BOOST_UBLAS_INLINE
2076        reverse_iterator2 rend2 () {
2077            return reverse_iterator2 (begin2 ());
2078        }
2079
2080    private:
2081        matrix_closure_type data_;
2082    };
2083
2084    // Specialization for temporary_traits
2085    template <class M, class TRI>
2086    struct vector_temporary_traits< symmetric_adaptor<M, TRI> >
2087    : vector_temporary_traits< M > {} ;
2088
2089    template <class M, class TRI>
2090    struct matrix_temporary_traits< symmetric_adaptor<M, TRI> >
2091    : matrix_temporary_traits< M > {} ;
2092
2093}}}
2094
2095#endif
Note: See TracBrowser for help on using the repository browser.