Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/numeric/ublas/symmetric.hpp @ 30

Last change on this file since 30 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 81.0 KB
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            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            BOOST_UBLAS_INLINE
362            const_reference operator [] (difference_type n) const {
363                return *(*this + n);
364            }
365
366#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
367            BOOST_UBLAS_INLINE
368#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
369            typename self_type::
370#endif
371            const_iterator2 begin () const {
372                return (*this) ().find2 (1, it1_, 0);
373            }
374            BOOST_UBLAS_INLINE
375#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
376            typename self_type::
377#endif
378            const_iterator2 end () const {
379                return (*this) ().find2 (1, it1_, (*this) ().size2 ());
380            }
381            BOOST_UBLAS_INLINE
382#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
383            typename self_type::
384#endif
385            const_reverse_iterator2 rbegin () const {
386                return const_reverse_iterator2 (end ());
387            }
388            BOOST_UBLAS_INLINE
389#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
390            typename self_type::
391#endif
392            const_reverse_iterator2 rend () const {
393                return const_reverse_iterator2 (begin ());
394            }
395#endif
396
397            // Indices
398            BOOST_UBLAS_INLINE
399            size_type index1 () const {
400                return it1_;
401            }
402            BOOST_UBLAS_INLINE
403            size_type index2 () const {
404                return it2_;
405            }
406
407            // Assignment
408            BOOST_UBLAS_INLINE
409            const_iterator1 &operator = (const const_iterator1 &it) {
410                container_const_reference<self_type>::assign (&it ());
411                it1_ = it.it1_;
412                it2_ = it.it2_;
413                return *this;
414            }
415
416            // Comparison
417            BOOST_UBLAS_INLINE
418            bool operator == (const const_iterator1 &it) const {
419                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
420                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
421                return it1_ == it.it1_;
422            }
423            BOOST_UBLAS_INLINE
424            bool operator < (const const_iterator1 &it) const {
425                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
426                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
427                return it1_ < it.it1_;
428            }
429
430        private:
431            size_type it1_;
432            size_type it2_;
433        };
434#endif
435
436        BOOST_UBLAS_INLINE
437        const_iterator1 begin1 () const {
438            return find1 (0, 0, 0);
439        }
440        BOOST_UBLAS_INLINE
441        const_iterator1 end1 () const {
442            return find1 (0, size_, 0);
443        }
444
445#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
446        class iterator1:
447            public container_reference<symmetric_matrix>,
448            public random_access_iterator_base<packed_random_access_iterator_tag,
449                                               iterator1, value_type> {
450        public:
451            typedef typename symmetric_matrix::value_type value_type;
452            typedef typename symmetric_matrix::difference_type difference_type;
453            typedef typename symmetric_matrix::reference reference;
454            typedef typename symmetric_matrix::pointer pointer;
455            typedef iterator2 dual_iterator_type;
456            typedef reverse_iterator2 dual_reverse_iterator_type;
457
458            // Construction and destruction
459            BOOST_UBLAS_INLINE
460            iterator1 ():
461                container_reference<self_type> (), it1_ (), it2_ () {}
462            BOOST_UBLAS_INLINE
463            iterator1 (self_type &m, size_type it1, size_type it2):
464                container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
465
466            // Arithmetic
467            BOOST_UBLAS_INLINE
468            iterator1 &operator ++ () {
469                ++ it1_;
470                return *this;
471            }
472            BOOST_UBLAS_INLINE
473            iterator1 &operator -- () {
474                -- it1_;
475                return *this;
476            }
477            BOOST_UBLAS_INLINE
478            iterator1 &operator += (difference_type n) {
479                it1_ += n;
480                return *this;
481            }
482            BOOST_UBLAS_INLINE
483            iterator1 &operator -= (difference_type n) {
484                it1_ -= n;
485                return *this;
486            }
487            BOOST_UBLAS_INLINE
488            difference_type operator - (const iterator1 &it) const {
489                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
490                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
491                return it1_ - it.it1_;
492            }
493
494            // Dereference
495            BOOST_UBLAS_INLINE
496            reference operator * () const {
497                return (*this) () (it1_, it2_);
498            }
499            BOOST_UBLAS_INLINE
500            reference operator [] (difference_type n) const {
501                return *(*this + n);
502            }
503
504#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
505            BOOST_UBLAS_INLINE
506#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
507            typename self_type::
508#endif
509            iterator2 begin () const {
510                return (*this) ().find2 (1, it1_, 0);
511            }
512            BOOST_UBLAS_INLINE
513#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
514            typename self_type::
515#endif
516            iterator2 end () const {
517                return (*this) ().find2 (1, it1_, (*this) ().size2 ());
518            }
519            BOOST_UBLAS_INLINE
520#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
521            typename self_type::
522#endif
523            reverse_iterator2 rbegin () const {
524                return reverse_iterator2 (end ());
525            }
526            BOOST_UBLAS_INLINE
527#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
528            typename self_type::
529#endif
530            reverse_iterator2 rend () const {
531                return reverse_iterator2 (begin ());
532            }
533#endif
534
535            // Indices
536            BOOST_UBLAS_INLINE
537            size_type index1 () const {
538                return it1_;
539            }
540            BOOST_UBLAS_INLINE
541            size_type index2 () const {
542                return it2_;
543            }
544
545            // Assignment
546            BOOST_UBLAS_INLINE
547            iterator1 &operator = (const iterator1 &it) {
548                container_reference<self_type>::assign (&it ());
549                it1_ = it.it1_;
550                it2_ = it.it2_;
551                return *this;
552            }
553
554            // Comparison
555            BOOST_UBLAS_INLINE
556            bool operator == (const iterator1 &it) const {
557                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
558                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
559                return it1_ == it.it1_;
560            }
561            BOOST_UBLAS_INLINE
562            bool operator < (const iterator1 &it) const {
563                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
564                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
565                return it1_ < it.it1_;
566            }
567
568        private:
569            size_type it1_;
570            size_type it2_;
571
572            friend class const_iterator1;
573        };
574#endif
575
576        BOOST_UBLAS_INLINE
577        iterator1 begin1 () {
578            return find1 (0, 0, 0);
579        }
580        BOOST_UBLAS_INLINE
581        iterator1 end1 () {
582            return find1 (0, size_, 0);
583        }
584
585#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
586        class const_iterator2:
587            public container_const_reference<symmetric_matrix>,
588            public random_access_iterator_base<dense_random_access_iterator_tag,
589                                               const_iterator2, value_type> {
590        public:
591            typedef typename symmetric_matrix::value_type value_type;
592            typedef typename symmetric_matrix::difference_type difference_type;
593            typedef typename symmetric_matrix::const_reference reference;
594            typedef const typename symmetric_matrix::pointer pointer;
595
596            typedef const_iterator1 dual_iterator_type;
597            typedef const_reverse_iterator1 dual_reverse_iterator_type;
598
599            // Construction and destruction
600            BOOST_UBLAS_INLINE
601            const_iterator2 ():
602                container_const_reference<self_type> (), it1_ (), it2_ () {}
603            BOOST_UBLAS_INLINE
604            const_iterator2 (const self_type &m, size_type it1, size_type it2):
605                container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
606            BOOST_UBLAS_INLINE
607            const_iterator2 (const iterator2 &it):
608                container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
609
610            // Arithmetic
611            BOOST_UBLAS_INLINE
612            const_iterator2 &operator ++ () {
613                ++ it2_;
614                return *this;
615            }
616            BOOST_UBLAS_INLINE
617            const_iterator2 &operator -- () {
618                -- it2_;
619                return *this;
620            }
621            BOOST_UBLAS_INLINE
622            const_iterator2 &operator += (difference_type n) {
623                it2_ += n;
624                return *this;
625            }
626            BOOST_UBLAS_INLINE
627            const_iterator2 &operator -= (difference_type n) {
628                it2_ -= n;
629                return *this;
630            }
631            BOOST_UBLAS_INLINE
632            difference_type operator - (const const_iterator2 &it) const {
633                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
634                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
635                return it2_ - it.it2_;
636            }
637
638            // Dereference
639            BOOST_UBLAS_INLINE
640            const_reference operator * () const {
641                return (*this) () (it1_, it2_);
642            }
643            BOOST_UBLAS_INLINE
644            const_reference operator [] (difference_type n) const {
645                return *(*this + n);
646            }
647
648#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
649            BOOST_UBLAS_INLINE
650#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
651            typename self_type::
652#endif
653            const_iterator1 begin () const {
654                return (*this) ().find1 (1, 0, it2_);
655            }
656            BOOST_UBLAS_INLINE
657#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
658            typename self_type::
659#endif
660            const_iterator1 end () const {
661                return (*this) ().find1 (1, (*this) ().size1 (), it2_);
662            }
663            BOOST_UBLAS_INLINE
664#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
665            typename self_type::
666#endif
667            const_reverse_iterator1 rbegin () const {
668                return const_reverse_iterator1 (end ());
669            }
670            BOOST_UBLAS_INLINE
671#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
672            typename self_type::
673#endif
674            const_reverse_iterator1 rend () const {
675                return const_reverse_iterator1 (begin ());
676            }
677#endif
678
679            // Indices
680            BOOST_UBLAS_INLINE
681            size_type index1 () const {
682                return it1_;
683            }
684            BOOST_UBLAS_INLINE
685            size_type index2 () const {
686                return it2_;
687            }
688
689            // Assignment
690            BOOST_UBLAS_INLINE
691            const_iterator2 &operator = (const const_iterator2 &it) {
692                container_const_reference<self_type>::assign (&it ());
693                it1_ = it.it1_;
694                it2_ = it.it2_;
695                return *this;
696            }
697
698            // Comparison
699            BOOST_UBLAS_INLINE
700            bool operator == (const const_iterator2 &it) const {
701                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
702                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
703                return it2_ == it.it2_;
704            }
705            BOOST_UBLAS_INLINE
706            bool operator < (const const_iterator2 &it) const {
707                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
708                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
709                return it2_ < it.it2_;
710            }
711
712        private:
713            size_type it1_;
714            size_type it2_;
715        };
716#endif
717
718        BOOST_UBLAS_INLINE
719        const_iterator2 begin2 () const {
720            return find2 (0, 0, 0);
721        }
722        BOOST_UBLAS_INLINE
723        const_iterator2 end2 () const {
724            return find2 (0, 0, size_);
725        }
726
727#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
728        class iterator2:
729            public container_reference<symmetric_matrix>,
730            public random_access_iterator_base<packed_random_access_iterator_tag,
731                                               iterator2, value_type> {
732        public:
733            typedef typename symmetric_matrix::value_type value_type;
734            typedef typename symmetric_matrix::difference_type difference_type;
735            typedef typename symmetric_matrix::reference reference;
736            typedef typename symmetric_matrix::pointer pointer;
737
738            typedef iterator1 dual_iterator_type;
739            typedef reverse_iterator1 dual_reverse_iterator_type;
740
741            // Construction and destruction
742            BOOST_UBLAS_INLINE
743            iterator2 ():
744                container_reference<self_type> (), it1_ (), it2_ () {}
745            BOOST_UBLAS_INLINE
746            iterator2 (self_type &m, size_type it1, size_type it2):
747                container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
748
749            // Arithmetic
750            BOOST_UBLAS_INLINE
751            iterator2 &operator ++ () {
752                ++ it2_;
753                return *this;
754            }
755            BOOST_UBLAS_INLINE
756            iterator2 &operator -- () {
757                -- it2_;
758                return *this;
759            }
760            BOOST_UBLAS_INLINE
761            iterator2 &operator += (difference_type n) {
762                it2_ += n;
763                return *this;
764            }
765            BOOST_UBLAS_INLINE
766            iterator2 &operator -= (difference_type n) {
767                it2_ -= n;
768                return *this;
769            }
770            BOOST_UBLAS_INLINE
771            difference_type operator - (const iterator2 &it) const {
772                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
773                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
774                return it2_ - it.it2_;
775            }
776
777            // Dereference
778            BOOST_UBLAS_INLINE
779            reference operator * () const {
780                return (*this) () (it1_, it2_);
781            }
782            BOOST_UBLAS_INLINE
783            reference operator [] (difference_type n) const {
784                return *(*this + n);
785            }
786
787#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
788            BOOST_UBLAS_INLINE
789#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
790            typename self_type::
791#endif
792            iterator1 begin () const {
793                return (*this) ().find1 (1, 0, it2_);
794            }
795            BOOST_UBLAS_INLINE
796#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
797            typename self_type::
798#endif
799            iterator1 end () const {
800                return (*this) ().find1 (1, (*this) ().size1 (), it2_);
801            }
802            BOOST_UBLAS_INLINE
803#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
804            typename self_type::
805#endif
806            reverse_iterator1 rbegin () const {
807                return reverse_iterator1 (end ());
808            }
809            BOOST_UBLAS_INLINE
810#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
811            typename self_type::
812#endif
813            reverse_iterator1 rend () const {
814                return reverse_iterator1 (begin ());
815            }
816#endif
817
818            // Indices
819            BOOST_UBLAS_INLINE
820            size_type index1 () const {
821                return it1_;
822            }
823            BOOST_UBLAS_INLINE
824            size_type index2 () const {
825                return it2_;
826            }
827
828            // Assignment
829            BOOST_UBLAS_INLINE
830            iterator2 &operator = (const iterator2 &it) {
831                container_reference<self_type>::assign (&it ());
832                it1_ = it.it1_;
833                it2_ = it.it2_;
834                return *this;
835            }
836
837            // Comparison
838            BOOST_UBLAS_INLINE
839            bool operator == (const iterator2 &it) const {
840                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
841                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
842                return it2_ == it.it2_;
843            }
844            BOOST_UBLAS_INLINE
845            bool operator < (const iterator2 &it) const {
846                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
847                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
848                return it2_ < it.it2_;
849            }
850
851        private:
852            size_type it1_;
853            size_type it2_;
854
855            friend class const_iterator2;
856        };
857#endif
858
859        BOOST_UBLAS_INLINE
860        iterator2 begin2 () {
861            return find2 (0, 0, 0);
862        }
863        BOOST_UBLAS_INLINE
864        iterator2 end2 () {
865            return find2 (0, 0, size_);
866        }
867
868        // Reverse iterators
869
870        BOOST_UBLAS_INLINE
871        const_reverse_iterator1 rbegin1 () const {
872            return const_reverse_iterator1 (end1 ());
873        }
874        BOOST_UBLAS_INLINE
875        const_reverse_iterator1 rend1 () const {
876            return const_reverse_iterator1 (begin1 ());
877        }
878
879        BOOST_UBLAS_INLINE
880        reverse_iterator1 rbegin1 () {
881            return reverse_iterator1 (end1 ());
882        }
883        BOOST_UBLAS_INLINE
884        reverse_iterator1 rend1 () {
885            return reverse_iterator1 (begin1 ());
886        }
887
888        BOOST_UBLAS_INLINE
889        const_reverse_iterator2 rbegin2 () const {
890            return const_reverse_iterator2 (end2 ());
891        }
892        BOOST_UBLAS_INLINE
893        const_reverse_iterator2 rend2 () const {
894            return const_reverse_iterator2 (begin2 ());
895        }
896
897        BOOST_UBLAS_INLINE
898        reverse_iterator2 rbegin2 () {
899            return reverse_iterator2 (end2 ());
900        }
901        BOOST_UBLAS_INLINE
902        reverse_iterator2 rend2 () {
903            return reverse_iterator2 (begin2 ());
904        }
905
906    private:
907        size_type size_;
908        array_type data_;
909    };
910
911
912    // Symmetric matrix adaptor class
913    template<class M, class TRI>
914    class symmetric_adaptor:
915        public matrix_expression<symmetric_adaptor<M, TRI> > {
916
917        typedef symmetric_adaptor<M, TRI> self_type;
918    public:
919#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
920        using matrix_expression<self_type>::operator ();
921#endif
922        typedef const M const_matrix_type;
923        typedef M matrix_type;
924        typedef TRI triangular_type;
925        typedef typename M::size_type size_type;
926        typedef typename M::difference_type difference_type;
927        typedef typename M::value_type value_type;
928        typedef typename M::const_reference const_reference;
929        typedef typename boost::mpl::if_<boost::is_const<M>,
930                                          typename M::const_reference,
931                                          typename M::reference>::type reference;
932        typedef typename boost::mpl::if_<boost::is_const<M>,
933                                          typename M::const_closure_type,
934                                          typename M::closure_type>::type matrix_closure_type;
935        typedef const self_type const_closure_type;
936        typedef self_type closure_type;
937        // Replaced by _temporary_traits to avoid type requirements on M
938        //typedef typename M::vector_temporary_type vector_temporary_type;
939        //typedef typename M::matrix_temporary_type matrix_temporary_type;
940        typedef typename storage_restrict_traits<typename M::storage_category,
941                                                 packed_proxy_tag>::storage_category storage_category;
942        typedef typename M::orientation_category orientation_category;
943
944        // Construction and destruction
945        BOOST_UBLAS_INLINE
946        symmetric_adaptor (matrix_type &data):
947            matrix_expression<self_type> (),
948            data_ (data) {
949            BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
950        }
951        BOOST_UBLAS_INLINE
952        symmetric_adaptor (const symmetric_adaptor &m):
953            matrix_expression<self_type> (),
954            data_ (m.data_) {
955            BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
956        }
957
958        // Accessors
959        BOOST_UBLAS_INLINE
960        size_type size1 () const {
961            return data_.size1 ();
962        }
963        BOOST_UBLAS_INLINE
964        size_type size2 () const {
965            return data_.size2 ();
966        }
967
968        // Storage accessors
969        BOOST_UBLAS_INLINE
970        const matrix_closure_type &data () const {
971            return data_;
972        }
973        BOOST_UBLAS_INLINE
974        matrix_closure_type &data () {
975            return data_;
976        }
977
978        // Element access
979#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
980        BOOST_UBLAS_INLINE
981        const_reference operator () (size_type i, size_type j) const {
982            BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
983            BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
984            if (triangular_type::other (i, j))
985                return data () (i, j);
986            else
987                return data () (j, i);
988        }
989        BOOST_UBLAS_INLINE
990        reference operator () (size_type i, size_type j) {
991            BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
992            BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
993            if (triangular_type::other (i, j))
994                return data () (i, j);
995            else
996                return data () (j, i);
997        }
998#else
999        BOOST_UBLAS_INLINE
1000        reference operator () (size_type i, size_type j) const {
1001            BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1002            BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1003            if (triangular_type::other (i, j))
1004                return data () (i, j);
1005            else
1006                return data () (j, i);
1007        }
1008#endif
1009
1010        // Assignment
1011        BOOST_UBLAS_INLINE
1012        symmetric_adaptor &operator = (const symmetric_adaptor &m) {
1013            matrix_assign<scalar_assign, triangular_type> (*this, m);
1014            return *this;
1015        }
1016        BOOST_UBLAS_INLINE
1017        symmetric_adaptor &assign_temporary (symmetric_adaptor &m) {
1018            *this = m;
1019            return *this;
1020        }
1021        template<class AE>
1022        BOOST_UBLAS_INLINE
1023        symmetric_adaptor &operator = (const matrix_expression<AE> &ae) {
1024            matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae));
1025            return *this;
1026        }
1027        template<class AE>
1028        BOOST_UBLAS_INLINE
1029        symmetric_adaptor &assign (const matrix_expression<AE> &ae) {
1030            matrix_assign<scalar_assign, triangular_type> (*this, ae);
1031            return *this;
1032        }
1033        template<class AE>
1034        BOOST_UBLAS_INLINE
1035        symmetric_adaptor& operator += (const matrix_expression<AE> &ae) {
1036            matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae));
1037            return *this;
1038        }
1039        template<class AE>
1040        BOOST_UBLAS_INLINE
1041        symmetric_adaptor &plus_assign (const matrix_expression<AE> &ae) {
1042            matrix_assign<scalar_plus_assign, triangular_type> (*this, ae);
1043            return *this;
1044        }
1045        template<class AE>
1046        BOOST_UBLAS_INLINE
1047        symmetric_adaptor& operator -= (const matrix_expression<AE> &ae) {
1048            matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae));
1049            return *this;
1050        }
1051        template<class AE>
1052        BOOST_UBLAS_INLINE
1053        symmetric_adaptor &minus_assign (const matrix_expression<AE> &ae) {
1054            matrix_assign<scalar_minus_assign, triangular_type> (*this, ae);
1055            return *this;
1056        }
1057        template<class AT>
1058        BOOST_UBLAS_INLINE
1059        symmetric_adaptor& operator *= (const AT &at) {
1060            matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
1061            return *this;
1062        }
1063        template<class AT>
1064        BOOST_UBLAS_INLINE
1065        symmetric_adaptor& operator /= (const AT &at) {
1066            matrix_assign_scalar<scalar_divides_assign> (*this, at);
1067            return *this;
1068        }
1069
1070        // Closure comparison
1071        BOOST_UBLAS_INLINE
1072        bool same_closure (const symmetric_adaptor &sa) const {
1073            return (*this).data ().same_closure (sa.data ());
1074       }
1075
1076        // Swapping
1077        BOOST_UBLAS_INLINE
1078        void swap (symmetric_adaptor &m) {
1079            if (this != &m)
1080                matrix_swap<scalar_swap, triangular_type> (*this, m);
1081        }
1082        BOOST_UBLAS_INLINE
1083        friend void swap (symmetric_adaptor &m1, symmetric_adaptor &m2) {
1084            m1.swap (m2);
1085        }
1086
1087        // Iterator types
1088    private:
1089        // Use matrix iterator
1090        typedef typename M::const_iterator1 const_subiterator1_type;
1091        typedef typename boost::mpl::if_<boost::is_const<M>,
1092                                          typename M::const_iterator1,
1093                                          typename M::iterator1>::type subiterator1_type;
1094        typedef typename M::const_iterator2 const_subiterator2_type;
1095        typedef typename boost::mpl::if_<boost::is_const<M>,
1096                                          typename M::const_iterator2,
1097                                          typename M::iterator2>::type subiterator2_type;
1098
1099    public:
1100#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1101        typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
1102        typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
1103        typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
1104        typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
1105#else
1106        class const_iterator1;
1107        class iterator1;
1108        class const_iterator2;
1109        class iterator2;
1110#endif
1111        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1112        typedef reverse_iterator_base1<iterator1> reverse_iterator1;
1113        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1114        typedef reverse_iterator_base2<iterator2> reverse_iterator2;
1115
1116        // Element lookup
1117        BOOST_UBLAS_INLINE
1118        const_iterator1 find1 (int rank, size_type i, size_type j) const {
1119            if (triangular_type::other (i, j)) {
1120                if (triangular_type::other (size1 (), j)) {
1121                    return const_iterator1 (*this, 0, 0,
1122                                            data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j),
1123                                            data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ()));
1124                } else {
1125                    return const_iterator1 (*this, 0, 1,
1126                                            data ().find1 (rank, i, j), data ().find1 (rank, j, j),
1127                                            data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ()));
1128                }
1129            } else {
1130                if (triangular_type::other (size1 (), j)) {
1131                    return const_iterator1 (*this, 1, 0,
1132                                            data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j),
1133                                            data ().find2 (rank, j, i), data ().find2 (rank, j, j));
1134                } else {
1135                    return const_iterator1 (*this, 1, 1,
1136                                            data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()),
1137                                            data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ()));
1138                }
1139            }
1140        }
1141        BOOST_UBLAS_INLINE
1142        iterator1 find1 (int rank, size_type i, size_type j) {
1143            if (rank == 1)
1144                i = triangular_type::mutable_restrict1 (i, j);
1145            return iterator1 (*this, data ().find1 (rank, i, j));
1146        }
1147        BOOST_UBLAS_INLINE
1148        const_iterator2 find2 (int rank, size_type i, size_type j) const {
1149            if (triangular_type::other (i, j)) {
1150                if (triangular_type::other (i, size2 ())) {
1151                    return const_iterator2 (*this, 1, 1,
1152                                            data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()),
1153                                            data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ()));
1154                } else {
1155                    return const_iterator2 (*this, 1, 0,
1156                                            data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i),
1157                                            data ().find2 (rank, i, j), data ().find2 (rank, i, i));
1158                }
1159            } else {
1160                if (triangular_type::other (i, size2 ())) {
1161                    return const_iterator2 (*this, 0, 1,
1162                                            data ().find1 (rank, j, i), data ().find1 (rank, i, i),
1163                                            data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ()));
1164                } else {
1165                    return const_iterator2 (*this, 0, 0,
1166                                            data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i),
1167                                            data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ()));
1168                }
1169            }
1170        }
1171        BOOST_UBLAS_INLINE
1172        iterator2 find2 (int rank, size_type i, size_type j) {
1173            if (rank == 1)
1174                j = triangular_type::mutable_restrict2 (i, j);
1175            return iterator2 (*this, data ().find2 (rank, i, j));
1176        }
1177
1178        // Iterators simply are indices.
1179
1180#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1181        class const_iterator1:
1182            public container_const_reference<symmetric_adaptor>,
1183            public random_access_iterator_base<typename iterator_restrict_traits<
1184                                                   typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
1185                                               const_iterator1, value_type> {
1186        public:
1187            typedef typename const_subiterator1_type::value_type value_type;
1188            typedef typename const_subiterator1_type::difference_type difference_type;
1189            typedef typename const_subiterator1_type::reference reference;
1190            typedef typename const_subiterator1_type::pointer pointer;
1191
1192            typedef const_iterator2 dual_iterator_type;
1193            typedef const_reverse_iterator2 dual_reverse_iterator_type;
1194
1195            // Construction and destruction
1196            BOOST_UBLAS_INLINE
1197            const_iterator1 ():
1198                container_const_reference<self_type> (),
1199                begin_ (-1), end_ (-1), current_ (-1),
1200                it1_begin_ (), it1_end_ (), it1_ (),
1201                it2_begin_ (), it2_end_ (), it2_ () {}
1202            BOOST_UBLAS_INLINE
1203            const_iterator1 (const self_type &m, int begin, int end,
1204                             const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
1205                             const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
1206                container_const_reference<self_type> (m),
1207                begin_ (begin), end_ (end), current_ (begin),
1208                it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
1209                it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
1210                if (current_ == 0 && it1_ == it1_end_)
1211                    current_ = 1;
1212                if (current_ == 1 && it2_ == it2_end_)
1213                    current_ = 0;
1214                if ((current_ == 0 && it1_ == it1_end_) ||
1215                    (current_ == 1 && it2_ == it2_end_))
1216                    current_ = end_;
1217                BOOST_UBLAS_CHECK (current_ == end_ ||
1218                                   (current_ == 0 && it1_ != it1_end_) ||
1219                                   (current_ == 1 && it2_ != it2_end_), internal_logic ());
1220            }
1221            // FIXME cannot compile
1222            //  iterator1 does not have these members!
1223            BOOST_UBLAS_INLINE
1224            const_iterator1 (const iterator1 &it):
1225                container_const_reference<self_type> (it ()),
1226                begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
1227                it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
1228                it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
1229                BOOST_UBLAS_CHECK (current_ == end_ ||
1230                                   (current_ == 0 && it1_ != it1_end_) ||
1231                                   (current_ == 1 && it2_ != it2_end_), internal_logic ());
1232            }
1233
1234            // Arithmetic
1235            BOOST_UBLAS_INLINE
1236            const_iterator1 &operator ++ () {
1237                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1238                if (current_ == 0) {
1239                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1240                    ++ it1_;
1241                    if (it1_ == it1_end_ && end_ == 1) {
1242                        it2_ = it2_begin_;
1243                        current_ = 1;
1244                    }
1245                } else /* if (current_ == 1) */ {
1246                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1247                    ++ it2_;
1248                    if (it2_ == it2_end_ && end_ == 0) {
1249                        it1_ = it1_begin_;
1250                        current_ = 0;
1251                    }
1252                }
1253                return *this;
1254            }
1255            BOOST_UBLAS_INLINE
1256            const_iterator1 &operator -- () {
1257                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1258                if (current_ == 0) {
1259                    if (it1_ == it1_begin_ && begin_ == 1) {
1260                        it2_ = it2_end_;
1261                        BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
1262                        -- it2_;
1263                        current_ = 1;
1264                    } else {
1265                        -- it1_;
1266                    }
1267                } else /* if (current_ == 1) */ {
1268                    if (it2_ == it2_begin_ && begin_ == 0) {
1269                        it1_ = it1_end_;
1270                        BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
1271                        -- it1_;
1272                        current_ = 0;
1273                    } else {
1274                        -- it2_;
1275                    }
1276                }
1277                return *this;
1278            }
1279            BOOST_UBLAS_INLINE
1280            const_iterator1 &operator += (difference_type n) {
1281                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1282                if (current_ == 0) {
1283                    size_type d = (std::min) (n, it1_end_ - it1_);
1284                    it1_ += d;
1285                    n -= d;
1286                    if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
1287                        BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1288                        d = (std::min) (n, it2_end_ - it2_begin_);
1289                        it2_ = it2_begin_ + d;
1290                        n -= d;
1291                        current_ = 1;
1292                    }
1293                } else /* if (current_ == 1) */ {
1294                    size_type d = (std::min) (n, it2_end_ - it2_);
1295                    it2_ += d;
1296                    n -= d;
1297                    if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
1298                        BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1299                        d = (std::min) (n, it1_end_ - it1_begin_);
1300                        it1_ = it1_begin_ + d;
1301                        n -= d;
1302                        current_ = 0;
1303                    }
1304                }
1305                BOOST_UBLAS_CHECK (n == 0, external_logic ());
1306                return *this;
1307            }
1308            BOOST_UBLAS_INLINE
1309            const_iterator1 &operator -= (difference_type n) {
1310                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1311                if (current_ == 0) {
1312                    size_type d = (std::min) (n, it1_ - it1_begin_);
1313                    it1_ -= d;
1314                    n -= d;
1315                    if (n > 0) {
1316                        BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1317                        d = (std::min) (n, it2_end_ - it2_begin_);
1318                        it2_ = it2_end_ - d;
1319                        n -= d;
1320                        current_ = 1;
1321                    }
1322                } else /* if (current_ == 1) */ {
1323                    size_type d = (std::min) (n, it2_ - it2_begin_);
1324                    it2_ -= d;
1325                    n -= d;
1326                    if (n > 0) {
1327                        BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1328                        d = (std::min) (n, it1_end_ - it1_begin_);
1329                        it1_ = it1_end_ - d;
1330                        n -= d;
1331                        current_ = 0;
1332                    }
1333                }
1334                BOOST_UBLAS_CHECK (n == 0, external_logic ());
1335                return *this;
1336            }
1337            BOOST_UBLAS_INLINE
1338            difference_type operator - (const const_iterator1 &it) const {
1339                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1340                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1341                BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1342                BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1343                if (current_ == 0 && it.current_ == 0) {
1344                    return it1_ - it.it1_;
1345                } else if (current_ == 0 && it.current_ == 1) {
1346                    if (end_ == 1 && it.end_ == 1) {
1347                        return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
1348                    } else /* if (end_ == 0 && it.end_ == 0) */ {
1349                        return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
1350                    }
1351
1352                } else if (current_ == 1 && it.current_ == 0) {
1353                    if (end_ == 1 && it.end_ == 1) {
1354                        return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
1355                    } else /* if (end_ == 0 && it.end_ == 0) */ {
1356                        return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
1357                    }
1358                }
1359                /* current_ == 1 && it.current_ == 1 */ {
1360                    return it2_ - it.it2_;
1361                }
1362            }
1363
1364            // Dereference
1365            BOOST_UBLAS_INLINE
1366            const_reference operator * () const {
1367                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1368                if (current_ == 0) {
1369                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1370                    return *it1_;
1371                } else /* if (current_ == 1) */ {
1372                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1373                    return *it2_;
1374                }
1375            }
1376            BOOST_UBLAS_INLINE
1377            const_reference operator [] (difference_type n) const {
1378                return *(*this + n);
1379            }
1380
1381#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1382            BOOST_UBLAS_INLINE
1383#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1384            typename self_type::
1385#endif
1386            const_iterator2 begin () const {
1387                return (*this) ().find2 (1, index1 (), 0);
1388            }
1389            BOOST_UBLAS_INLINE
1390#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1391            typename self_type::
1392#endif
1393            const_iterator2 end () const {
1394                return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1395            }
1396            BOOST_UBLAS_INLINE
1397#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1398            typename self_type::
1399#endif
1400            const_reverse_iterator2 rbegin () const {
1401                return const_reverse_iterator2 (end ());
1402            }
1403            BOOST_UBLAS_INLINE
1404#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1405            typename self_type::
1406#endif
1407            const_reverse_iterator2 rend () const {
1408                return const_reverse_iterator2 (begin ());
1409            }
1410#endif
1411
1412            // Indices
1413            BOOST_UBLAS_INLINE
1414            size_type index1 () const {
1415                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1416                if (current_ == 0) {
1417                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1418                    return it1_.index1 ();
1419                } else /* if (current_ == 1) */ {
1420                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1421                    return it2_.index2 ();
1422                }
1423            }
1424            BOOST_UBLAS_INLINE
1425            size_type index2 () const {
1426                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1427                if (current_ == 0) {
1428                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1429                    return it1_.index2 ();
1430                } else /* if (current_ == 1) */ {
1431                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1432                    return it2_.index1 ();
1433                }
1434            }
1435
1436            // Assignment
1437            BOOST_UBLAS_INLINE
1438            const_iterator1 &operator = (const const_iterator1 &it) {
1439                container_const_reference<self_type>::assign (&it ());
1440                begin_ = it.begin_;
1441                end_ = it.end_;
1442                current_ = it.current_;
1443                it1_begin_ = it.it1_begin_;
1444                it1_end_ = it.it1_end_;
1445                it1_ = it.it1_;
1446                it2_begin_ = it.it2_begin_;
1447                it2_end_ = it.it2_end_;
1448                it2_ = it.it2_;
1449                return *this;
1450            }
1451
1452            // Comparison
1453            BOOST_UBLAS_INLINE
1454            bool operator == (const const_iterator1 &it) const {
1455                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1456                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1457                BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1458                BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1459                return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
1460                       (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
1461            }
1462            BOOST_UBLAS_INLINE
1463            bool operator < (const const_iterator1 &it) const {
1464                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1465                return it - *this > 0;
1466            }
1467
1468        private:
1469            int begin_;
1470            int end_;
1471            int current_;
1472            const_subiterator1_type it1_begin_;
1473            const_subiterator1_type it1_end_;
1474            const_subiterator1_type it1_;
1475            const_subiterator2_type it2_begin_;
1476            const_subiterator2_type it2_end_;
1477            const_subiterator2_type it2_;
1478        };
1479#endif
1480
1481        BOOST_UBLAS_INLINE
1482        const_iterator1 begin1 () const {
1483            return find1 (0, 0, 0);
1484        }
1485        BOOST_UBLAS_INLINE
1486        const_iterator1 end1 () const {
1487            return find1 (0, size1 (), 0);
1488        }
1489
1490#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1491        class iterator1:
1492            public container_reference<symmetric_adaptor>,
1493            public random_access_iterator_base<typename iterator_restrict_traits<
1494                                                   typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1495                                               iterator1, value_type> {
1496        public:
1497            typedef typename subiterator1_type::value_type value_type;
1498            typedef typename subiterator1_type::difference_type difference_type;
1499            typedef typename subiterator1_type::reference reference;
1500            typedef typename subiterator1_type::pointer pointer;
1501
1502            typedef iterator2 dual_iterator_type;
1503            typedef reverse_iterator2 dual_reverse_iterator_type;
1504
1505            // Construction and destruction
1506            BOOST_UBLAS_INLINE
1507            iterator1 ():
1508                container_reference<self_type> (), it1_ () {}
1509            BOOST_UBLAS_INLINE
1510            iterator1 (self_type &m, const subiterator1_type &it1):
1511                container_reference<self_type> (m), it1_ (it1) {}
1512
1513            // Arithmetic
1514            BOOST_UBLAS_INLINE
1515            iterator1 &operator ++ () {
1516                ++ it1_;
1517                return *this;
1518            }
1519            BOOST_UBLAS_INLINE
1520            iterator1 &operator -- () {
1521                -- it1_;
1522                return *this;
1523            }
1524            BOOST_UBLAS_INLINE
1525            iterator1 &operator += (difference_type n) {
1526                it1_ += n;
1527                return *this;
1528            }
1529            BOOST_UBLAS_INLINE
1530            iterator1 &operator -= (difference_type n) {
1531                it1_ -= n;
1532                return *this;
1533            }
1534            BOOST_UBLAS_INLINE
1535            difference_type operator - (const iterator1 &it) const {
1536                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1537                return it1_ - it.it1_;
1538            }
1539
1540            // Dereference
1541            BOOST_UBLAS_INLINE
1542            reference operator * () const {
1543                return *it1_;
1544            }
1545            BOOST_UBLAS_INLINE
1546            reference operator [] (difference_type n) const {
1547                return *(*this + n);
1548            }
1549
1550#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1551            BOOST_UBLAS_INLINE
1552#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1553            typename self_type::
1554#endif
1555            iterator2 begin () const {
1556                return (*this) ().find2 (1, index1 (), 0);
1557            }
1558            BOOST_UBLAS_INLINE
1559#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1560            typename self_type::
1561#endif
1562            iterator2 end () const {
1563                return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1564            }
1565            BOOST_UBLAS_INLINE
1566#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1567            typename self_type::
1568#endif
1569            reverse_iterator2 rbegin () const {
1570                return reverse_iterator2 (end ());
1571            }
1572            BOOST_UBLAS_INLINE
1573#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1574            typename self_type::
1575#endif
1576            reverse_iterator2 rend () const {
1577                return reverse_iterator2 (begin ());
1578            }
1579#endif
1580
1581            // Indices
1582            BOOST_UBLAS_INLINE
1583            size_type index1 () const {
1584                return it1_.index1 ();
1585            }
1586            BOOST_UBLAS_INLINE
1587            size_type index2 () const {
1588                return it1_.index2 ();
1589            }
1590
1591            // Assignment
1592            BOOST_UBLAS_INLINE
1593            iterator1 &operator = (const iterator1 &it) {
1594                container_reference<self_type>::assign (&it ());
1595                it1_ = it.it1_;
1596                return *this;
1597            }
1598
1599            // Comparison
1600            BOOST_UBLAS_INLINE
1601            bool operator == (const iterator1 &it) const {
1602                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1603                return it1_ == it.it1_;
1604            }
1605            BOOST_UBLAS_INLINE
1606            bool operator < (const iterator1 &it) const {
1607                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1608                return it1_ < it.it1_;
1609            }
1610
1611        private:
1612            subiterator1_type it1_;
1613
1614            friend class const_iterator1;
1615        };
1616#endif
1617
1618        BOOST_UBLAS_INLINE
1619        iterator1 begin1 () {
1620            return find1 (0, 0, 0);
1621        }
1622        BOOST_UBLAS_INLINE
1623        iterator1 end1 () {
1624            return find1 (0, size1 (), 0);
1625        }
1626
1627#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1628        class const_iterator2:
1629            public container_const_reference<symmetric_adaptor>,
1630            public random_access_iterator_base<typename iterator_restrict_traits<
1631                                                   typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
1632                                               const_iterator2, value_type> {
1633        public:
1634            typedef typename const_subiterator2_type::value_type value_type;
1635            typedef typename const_subiterator2_type::difference_type difference_type;
1636            typedef typename const_subiterator2_type::reference reference;
1637            typedef typename const_subiterator2_type::pointer pointer;
1638
1639            typedef const_iterator1 dual_iterator_type;
1640            typedef const_reverse_iterator1 dual_reverse_iterator_type;
1641
1642            // Construction and destruction
1643            BOOST_UBLAS_INLINE
1644            const_iterator2 ():
1645                container_const_reference<self_type> (),
1646                begin_ (-1), end_ (-1), current_ (-1),
1647                it1_begin_ (), it1_end_ (), it1_ (),
1648                it2_begin_ (), it2_end_ (), it2_ () {}
1649            BOOST_UBLAS_INLINE
1650            const_iterator2 (const self_type &m, int begin, int end,
1651                             const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
1652                             const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
1653                container_const_reference<self_type> (m),
1654                begin_ (begin), end_ (end), current_ (begin),
1655                it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
1656                it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
1657                if (current_ == 0 && it1_ == it1_end_)
1658                    current_ = 1;
1659                if (current_ == 1 && it2_ == it2_end_)
1660                    current_ = 0;
1661                if ((current_ == 0 && it1_ == it1_end_) ||
1662                    (current_ == 1 && it2_ == it2_end_))
1663                    current_ = end_;
1664                BOOST_UBLAS_CHECK (current_ == end_ ||
1665                                   (current_ == 0 && it1_ != it1_end_) ||
1666                                   (current_ == 1 && it2_ != it2_end_), internal_logic ());
1667            }
1668            // FIXME cannot compiler
1669            //  iterator2 does not have these members!
1670            BOOST_UBLAS_INLINE
1671            const_iterator2 (const iterator2 &it):
1672                container_const_reference<self_type> (it ()),
1673                begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
1674                it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
1675                it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
1676                BOOST_UBLAS_CHECK (current_ == end_ ||
1677                                   (current_ == 0 && it1_ != it1_end_) ||
1678                                   (current_ == 1 && it2_ != it2_end_), internal_logic ());
1679            }
1680
1681            // Arithmetic
1682            BOOST_UBLAS_INLINE
1683            const_iterator2 &operator ++ () {
1684                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1685                if (current_ == 0) {
1686                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1687                    ++ it1_;
1688                    if (it1_ == it1_end_ && end_ == 1) {
1689                        it2_ = it2_begin_;
1690                        current_ = 1;
1691                    }
1692                } else /* if (current_ == 1) */ {
1693                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1694                    ++ it2_;
1695                    if (it2_ == it2_end_ && end_ == 0) {
1696                        it1_ = it1_begin_;
1697                        current_ = 0;
1698                    }
1699                }
1700                return *this;
1701            }
1702            BOOST_UBLAS_INLINE
1703            const_iterator2 &operator -- () {
1704                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1705                if (current_ == 0) {
1706                    if (it1_ == it1_begin_ && begin_ == 1) {
1707                        it2_ = it2_end_;
1708                        BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
1709                        -- it2_;
1710                        current_ = 1;
1711                    } else {
1712                        -- it1_;
1713                    }
1714                } else /* if (current_ == 1) */ {
1715                    if (it2_ == it2_begin_ && begin_ == 0) {
1716                        it1_ = it1_end_;
1717                        BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
1718                        -- it1_;
1719                        current_ = 0;
1720                    } else {
1721                        -- it2_;
1722                    }
1723                }
1724                return *this;
1725            }
1726            BOOST_UBLAS_INLINE
1727            const_iterator2 &operator += (difference_type n) {
1728                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1729                if (current_ == 0) {
1730                    size_type d = (std::min) (n, it1_end_ - it1_);
1731                    it1_ += d;
1732                    n -= d;
1733                    if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
1734                        BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1735                        d = (std::min) (n, it2_end_ - it2_begin_);
1736                        it2_ = it2_begin_ + d;
1737                        n -= d;
1738                        current_ = 1;
1739                    }
1740                } else /* if (current_ == 1) */ {
1741                    size_type d = (std::min) (n, it2_end_ - it2_);
1742                    it2_ += d;
1743                    n -= d;
1744                    if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
1745                        BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1746                        d = (std::min) (n, it1_end_ - it1_begin_);
1747                        it1_ = it1_begin_ + d;
1748                        n -= d;
1749                        current_ = 0;
1750                    }
1751                }
1752                BOOST_UBLAS_CHECK (n == 0, external_logic ());
1753                return *this;
1754            }
1755            BOOST_UBLAS_INLINE
1756            const_iterator2 &operator -= (difference_type n) {
1757                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1758                if (current_ == 0) {
1759                    size_type d = (std::min) (n, it1_ - it1_begin_);
1760                    it1_ -= d;
1761                    n -= d;
1762                    if (n > 0) {
1763                        BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1764                        d = (std::min) (n, it2_end_ - it2_begin_);
1765                        it2_ = it2_end_ - d;
1766                        n -= d;
1767                        current_ = 1;
1768                    }
1769                } else /* if (current_ == 1) */ {
1770                    size_type d = (std::min) (n, it2_ - it2_begin_);
1771                    it2_ -= d;
1772                    n -= d;
1773                    if (n > 0) {
1774                        BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1775                        d = (std::min) (n, it1_end_ - it1_begin_);
1776                        it1_ = it1_end_ - d;
1777                        n -= d;
1778                        current_ = 0;
1779                    }
1780                }
1781                BOOST_UBLAS_CHECK (n == 0, external_logic ());
1782                return *this;
1783            }
1784            BOOST_UBLAS_INLINE
1785            difference_type operator - (const const_iterator2 &it) const {
1786                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1787                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1788                BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1789                BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1790                if (current_ == 0 && it.current_ == 0) {
1791                    return it1_ - it.it1_;
1792                } else if (current_ == 0 && it.current_ == 1) {
1793                    if (end_ == 1 && it.end_ == 1) {
1794                        return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
1795                    } else /* if (end_ == 0 && it.end_ == 0) */ {
1796                        return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
1797                    }
1798
1799                } else if (current_ == 1 && it.current_ == 0) {
1800                    if (end_ == 1 && it.end_ == 1) {
1801                        return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
1802                    } else /* if (end_ == 0 && it.end_ == 0) */ {
1803                        return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
1804                    }
1805                }
1806                /* current_ == 1 && it.current_ == 1 */ {
1807                    return it2_ - it.it2_;
1808                }
1809            }
1810
1811            // Dereference
1812            BOOST_UBLAS_INLINE
1813            const_reference operator * () const {
1814                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1815                if (current_ == 0) {
1816                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1817                    return *it1_;
1818                } else /* if (current_ == 1) */ {
1819                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1820                    return *it2_;
1821                }
1822            }
1823            BOOST_UBLAS_INLINE
1824            const_reference operator [] (difference_type n) const {
1825                return *(*this + n);
1826            }
1827
1828#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1829            BOOST_UBLAS_INLINE
1830#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1831            typename self_type::
1832#endif
1833            const_iterator1 begin () const {
1834                return (*this) ().find1 (1, 0, index2 ());
1835            }
1836            BOOST_UBLAS_INLINE
1837#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1838            typename self_type::
1839#endif
1840            const_iterator1 end () const {
1841                return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1842            }
1843            BOOST_UBLAS_INLINE
1844#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1845            typename self_type::
1846#endif
1847            const_reverse_iterator1 rbegin () const {
1848                return const_reverse_iterator1 (end ());
1849            }
1850            BOOST_UBLAS_INLINE
1851#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1852            typename self_type::
1853#endif
1854            const_reverse_iterator1 rend () const {
1855                return const_reverse_iterator1 (begin ());
1856            }
1857#endif
1858
1859            // Indices
1860            BOOST_UBLAS_INLINE
1861            size_type index1 () const {
1862                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1863                if (current_ == 0) {
1864                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1865                    return it1_.index2 ();
1866                } else /* if (current_ == 1) */ {
1867                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1868                    return it2_.index1 ();
1869                }
1870            }
1871            BOOST_UBLAS_INLINE
1872            size_type index2 () const {
1873                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1874                if (current_ == 0) {
1875                    BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1876                    return it1_.index1 ();
1877                } else /* if (current_ == 1) */ {
1878                    BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1879                    return it2_.index2 ();
1880                }
1881            }
1882
1883            // Assignment
1884            BOOST_UBLAS_INLINE
1885            const_iterator2 &operator = (const const_iterator2 &it) {
1886                container_const_reference<self_type>::assign (&it ());
1887                begin_ = it.begin_;
1888                end_ = it.end_;
1889                current_ = it.current_;
1890                it1_begin_ = it.it1_begin_;
1891                it1_end_ = it.it1_end_;
1892                it1_ = it.it1_;
1893                it2_begin_ = it.it2_begin_;
1894                it2_end_ = it.it2_end_;
1895                it2_ = it.it2_;
1896                return *this;
1897            }
1898
1899            // Comparison
1900            BOOST_UBLAS_INLINE
1901            bool operator == (const const_iterator2 &it) const {
1902                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1903                BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1904                BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1905                BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1906                return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
1907                       (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
1908            }
1909            BOOST_UBLAS_INLINE
1910            bool operator < (const const_iterator2 &it) const {
1911                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1912                return it - *this > 0;
1913            }
1914
1915        private:
1916            int begin_;
1917            int end_;
1918            int current_;
1919            const_subiterator1_type it1_begin_;
1920            const_subiterator1_type it1_end_;
1921            const_subiterator1_type it1_;
1922            const_subiterator2_type it2_begin_;
1923            const_subiterator2_type it2_end_;
1924            const_subiterator2_type it2_;
1925        };
1926#endif
1927
1928        BOOST_UBLAS_INLINE
1929        const_iterator2 begin2 () const {
1930            return find2 (0, 0, 0);
1931        }
1932        BOOST_UBLAS_INLINE
1933        const_iterator2 end2 () const {
1934            return find2 (0, 0, size2 ());
1935        }
1936
1937#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1938        class iterator2:
1939            public container_reference<symmetric_adaptor>,
1940            public random_access_iterator_base<typename iterator_restrict_traits<
1941                                                   typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1942                                               iterator2, value_type> {
1943        public:
1944            typedef typename subiterator2_type::value_type value_type;
1945            typedef typename subiterator2_type::difference_type difference_type;
1946            typedef typename subiterator2_type::reference reference;
1947            typedef typename subiterator2_type::pointer pointer;
1948
1949            typedef iterator1 dual_iterator_type;
1950            typedef reverse_iterator1 dual_reverse_iterator_type;
1951
1952            // Construction and destruction
1953            BOOST_UBLAS_INLINE
1954            iterator2 ():
1955                container_reference<self_type> (), it2_ () {}
1956            BOOST_UBLAS_INLINE
1957            iterator2 (self_type &m, const subiterator2_type &it2):
1958                container_reference<self_type> (m), it2_ (it2) {}
1959
1960            // Arithmetic
1961            BOOST_UBLAS_INLINE
1962            iterator2 &operator ++ () {
1963                ++ it2_;
1964                return *this;
1965            }
1966            BOOST_UBLAS_INLINE
1967            iterator2 &operator -- () {
1968                -- it2_;
1969                return *this;
1970            }
1971            BOOST_UBLAS_INLINE
1972            iterator2 &operator += (difference_type n) {
1973                it2_ += n;
1974                return *this;
1975            }
1976            BOOST_UBLAS_INLINE
1977            iterator2 &operator -= (difference_type n) {
1978                it2_ -= n;
1979                return *this;
1980            }
1981            BOOST_UBLAS_INLINE
1982            difference_type operator - (const iterator2 &it) const {
1983                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1984                return it2_ - it.it2_;
1985            }
1986
1987            // Dereference
1988            BOOST_UBLAS_INLINE
1989            reference operator * () const {
1990                return *it2_;
1991            }
1992            BOOST_UBLAS_INLINE
1993            reference operator [] (difference_type n) const {
1994                return *(*this + n);
1995            }
1996
1997#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1998            BOOST_UBLAS_INLINE
1999#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2000            typename self_type::
2001#endif
2002            iterator1 begin () const {
2003                return (*this) ().find1 (1, 0, index2 ());
2004            }
2005            BOOST_UBLAS_INLINE
2006#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2007            typename self_type::
2008#endif
2009            iterator1 end () const {
2010                return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
2011            }
2012            BOOST_UBLAS_INLINE
2013#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2014            typename self_type::
2015#endif
2016            reverse_iterator1 rbegin () const {
2017                return reverse_iterator1 (end ());
2018            }
2019            BOOST_UBLAS_INLINE
2020#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2021            typename self_type::
2022#endif
2023            reverse_iterator1 rend () const {
2024                return reverse_iterator1 (begin ());
2025            }
2026#endif
2027
2028            // Indices
2029            BOOST_UBLAS_INLINE
2030            size_type index1 () const {
2031                return it2_.index1 ();
2032            }
2033            BOOST_UBLAS_INLINE
2034            size_type index2 () const {
2035                return it2_.index2 ();
2036            }
2037
2038            // Assignment
2039            BOOST_UBLAS_INLINE
2040            iterator2 &operator = (const iterator2 &it) {
2041                container_reference<self_type>::assign (&it ());
2042                it2_ = it.it2_;
2043                return *this;
2044            }
2045
2046            // Comparison
2047            BOOST_UBLAS_INLINE
2048            bool operator == (const iterator2 &it) const {
2049                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2050                return it2_ == it.it2_;
2051            }
2052            BOOST_UBLAS_INLINE
2053            bool operator < (const iterator2 &it) const {
2054                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2055                return it2_ < it.it2_;
2056            }
2057
2058        private:
2059            subiterator2_type it2_;
2060
2061            friend class const_iterator2;
2062        };
2063#endif
2064
2065        BOOST_UBLAS_INLINE
2066        iterator2 begin2 () {
2067            return find2 (0, 0, 0);
2068        }
2069        BOOST_UBLAS_INLINE
2070        iterator2 end2 () {
2071            return find2 (0, 0, size2 ());
2072        }
2073
2074        // Reverse iterators
2075
2076        BOOST_UBLAS_INLINE
2077        const_reverse_iterator1 rbegin1 () const {
2078            return const_reverse_iterator1 (end1 ());
2079        }
2080        BOOST_UBLAS_INLINE
2081        const_reverse_iterator1 rend1 () const {
2082            return const_reverse_iterator1 (begin1 ());
2083        }
2084
2085        BOOST_UBLAS_INLINE
2086        reverse_iterator1 rbegin1 () {
2087            return reverse_iterator1 (end1 ());
2088        }
2089        BOOST_UBLAS_INLINE
2090        reverse_iterator1 rend1 () {
2091            return reverse_iterator1 (begin1 ());
2092        }
2093
2094        BOOST_UBLAS_INLINE
2095        const_reverse_iterator2 rbegin2 () const {
2096            return const_reverse_iterator2 (end2 ());
2097        }
2098        BOOST_UBLAS_INLINE
2099        const_reverse_iterator2 rend2 () const {
2100            return const_reverse_iterator2 (begin2 ());
2101        }
2102
2103        BOOST_UBLAS_INLINE
2104        reverse_iterator2 rbegin2 () {
2105            return reverse_iterator2 (end2 ());
2106        }
2107        BOOST_UBLAS_INLINE
2108        reverse_iterator2 rend2 () {
2109            return reverse_iterator2 (begin2 ());
2110        }
2111
2112    private:
2113        matrix_closure_type data_;
2114    };
2115
2116    // Specialization for temporary_traits
2117    template <class M, class TRI>
2118    struct vector_temporary_traits< symmetric_adaptor<M, TRI> >
2119    : vector_temporary_traits< M > {} ;
2120    template <class M, class TRI>
2121    struct vector_temporary_traits< const symmetric_adaptor<M, TRI> >
2122    : vector_temporary_traits< M > {} ;
2123
2124    template <class M, class TRI>
2125    struct matrix_temporary_traits< symmetric_adaptor<M, TRI> >
2126    : matrix_temporary_traits< M > {} ;
2127    template <class M, class TRI>
2128    struct matrix_temporary_traits< const symmetric_adaptor<M, TRI> >
2129    : matrix_temporary_traits< M > {} ;
2130
2131}}}
2132
2133#endif
Note: See TracBrowser for help on using the repository browser.