New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
symmetric.hpp in vendors/XIOS/current/extern/boost/include/boost/numeric/ublas – NEMO

source: vendors/XIOS/current/extern/boost/include/boost/numeric/ublas/symmetric.hpp @ 3428

Last change on this file since 3428 was 3428, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

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