Boost.uBlas 1.49
Linear Algebra in C++: matrices, vectors and numeric algorithms

symmetric.hpp

Go to the documentation of this file.
00001 //
00002 //  Copyright (c) 2000-2002
00003 //  Joerg Walter, Mathias Koch
00004 //
00005 //  Distributed under the Boost Software License, Version 1.0. (See
00006 //  accompanying file LICENSE_1_0.txt or copy at
00007 //  http://www.boost.org/LICENSE_1_0.txt)
00008 //
00009 //  The authors gratefully acknowledge the support of
00010 //  GeNeSys mbH & Co. KG in producing this work.
00011 //
00012 
00013 #ifndef _BOOST_UBLAS_SYMMETRIC_
00014 #define _BOOST_UBLAS_SYMMETRIC_
00015 
00016 #include <boost/numeric/ublas/matrix.hpp>
00017 #include <boost/numeric/ublas/triangular.hpp>
00018 #include <boost/numeric/ublas/detail/temporary.hpp>
00019 
00020 // Iterators based on ideas of Jeremy Siek
00021 // Symmetric matrices are square. Thanks to Peter Schmitteckert for spotting this.
00022 
00023 namespace boost { namespace numeric { namespace ublas {
00024 
00025     template<class M>
00026     bool is_symmetric (const M &m) {
00027         typedef typename M::size_type size_type;
00028 
00029         if (m.size1 () != m.size2 ())
00030             return false;
00031         size_type size = BOOST_UBLAS_SAME (m.size1 (), m.size2 ());
00032         for (size_type i = 0; i < size; ++ i) {
00033             for (size_type j = i; j < size; ++ j) {
00034                 if (m (i, j) != m (j, i))
00035                     return false;
00036             }
00037         }
00038         return true;
00039     }
00040 
00041     // Array based symmetric matrix class
00042     template<class T, class TRI, class L, class A>
00043     class symmetric_matrix:
00044         public matrix_container<symmetric_matrix<T, TRI, L, A> > {
00045 
00046         typedef T *pointer;
00047         typedef TRI triangular_type;
00048         typedef L layout_type;
00049         typedef symmetric_matrix<T, TRI, L, A> self_type;
00050     public:
00051 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
00052         using matrix_container<self_type>::operator ();
00053 #endif
00054         typedef typename A::size_type size_type;
00055         typedef typename A::difference_type difference_type;
00056         typedef T value_type;
00057         typedef const T &const_reference;
00058         typedef T &reference;
00059         typedef A array_type;
00060 
00061         typedef const matrix_reference<const self_type> const_closure_type;
00062         typedef matrix_reference<self_type> closure_type;
00063         typedef vector<T, A> vector_temporary_type;
00064         typedef matrix<T, L, A> matrix_temporary_type;  // general sub-matrix
00065         typedef packed_tag storage_category;
00066         typedef typename L::orientation_category orientation_category;
00067 
00068         // Construction and destruction
00069         BOOST_UBLAS_INLINE
00070         symmetric_matrix ():
00071             matrix_container<self_type> (),
00072             size_ (0), data_ (0) {}
00073         BOOST_UBLAS_INLINE
00074         symmetric_matrix (size_type size):
00075             matrix_container<self_type> (),
00076             size_ (BOOST_UBLAS_SAME (size, size)), data_ (triangular_type::packed_size (layout_type (), size, size)) {
00077         }
00078         BOOST_UBLAS_INLINE
00079         symmetric_matrix (size_type size1, size_type size2):
00080             matrix_container<self_type> (),
00081             size_ (BOOST_UBLAS_SAME (size1, size2)), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
00082         }
00083         BOOST_UBLAS_INLINE
00084         symmetric_matrix (size_type size, const array_type &data):
00085             matrix_container<self_type> (),
00086             size_ (size), data_ (data) {}
00087         BOOST_UBLAS_INLINE
00088         symmetric_matrix (const symmetric_matrix &m):
00089             matrix_container<self_type> (),
00090             size_ (m.size_), data_ (m.data_) {}
00091         template<class AE>
00092         BOOST_UBLAS_INLINE
00093         symmetric_matrix (const matrix_expression<AE> &ae):
00094             matrix_container<self_type> (),
00095             size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())),
00096             data_ (triangular_type::packed_size (layout_type (), size_, size_)) {
00097             matrix_assign<scalar_assign> (*this, ae);
00098         }
00099 
00100         // Accessors
00101         BOOST_UBLAS_INLINE
00102         size_type size1 () const {
00103             return size_;
00104         }
00105         BOOST_UBLAS_INLINE
00106         size_type size2 () const {
00107             return size_;
00108         }
00109 
00110         // Storage accessors
00111         BOOST_UBLAS_INLINE
00112         const array_type &data () const {
00113             return data_;
00114         }
00115         BOOST_UBLAS_INLINE
00116         array_type &data () {
00117             return data_;
00118         }
00119 
00120         // Resizing
00121         BOOST_UBLAS_INLINE
00122         void resize (size_type size, bool preserve = true) {
00123             if (preserve) {
00124                 self_type temporary (size, size);
00125                 detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary);
00126             }
00127             else {
00128                 data ().resize (triangular_type::packed_size (layout_type (), size, size));
00129                 size_ = size;
00130             }
00131         }
00132         BOOST_UBLAS_INLINE
00133         void resize (size_type size1, size_type size2, bool preserve = true) {
00134             resize (BOOST_UBLAS_SAME (size1, size2), preserve);
00135         }
00136         BOOST_UBLAS_INLINE
00137         void resize_packed_preserve (size_type size) {
00138             size_ = BOOST_UBLAS_SAME (size, size);
00139             data ().resize (triangular_type::packed_size (layout_type (), size_, size_), value_type ());
00140         }
00141 
00142         // Element access
00143         BOOST_UBLAS_INLINE
00144         const_reference operator () (size_type i, size_type j) const {
00145             BOOST_UBLAS_CHECK (i < size_, bad_index ());
00146             BOOST_UBLAS_CHECK (j < size_, bad_index ());
00147             if (triangular_type::other (i, j))
00148                 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
00149             else
00150                 return data () [triangular_type::element (layout_type (), j, size_, i, size_)];
00151         }
00152         BOOST_UBLAS_INLINE
00153         reference at_element (size_type i, size_type j) {
00154             BOOST_UBLAS_CHECK (i < size_, bad_index ());
00155             BOOST_UBLAS_CHECK (j < size_, bad_index ());
00156             return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
00157         }
00158         BOOST_UBLAS_INLINE
00159         reference operator () (size_type i, size_type j) {
00160             BOOST_UBLAS_CHECK (i < size_, bad_index ());
00161             BOOST_UBLAS_CHECK (j < size_, bad_index ());
00162             if (triangular_type::other (i, j))
00163                 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
00164             else
00165                 return data () [triangular_type::element (layout_type (), j, size_, i, size_)];
00166         }
00167 
00168         // Element assignment
00169         BOOST_UBLAS_INLINE
00170         reference insert_element (size_type i, size_type j, const_reference t) {
00171             return (operator () (i, j) = t);
00172         }
00173         BOOST_UBLAS_INLINE
00174         void erase_element (size_type i, size_type j) {
00175             operator () (i, j) = value_type/*zero*/();
00176         }
00177         
00178         // Zeroing
00179         BOOST_UBLAS_INLINE
00180         void clear () {
00181             // data ().clear ();
00182             std::fill (data ().begin (), data ().end (), value_type/*zero*/());
00183         }
00184 
00185         // Assignment
00186         BOOST_UBLAS_INLINE
00187         symmetric_matrix &operator = (const symmetric_matrix &m) {
00188             size_ = m.size_;
00189             data () = m.data ();
00190             return *this;
00191         }
00192         BOOST_UBLAS_INLINE
00193         symmetric_matrix &assign_temporary (symmetric_matrix &m) {
00194             swap (m);
00195             return *this;
00196         }
00197         template<class AE>
00198         BOOST_UBLAS_INLINE
00199         symmetric_matrix &operator = (const matrix_expression<AE> &ae) {
00200             self_type temporary (ae);
00201             return assign_temporary (temporary);
00202         }
00203         template<class AE>
00204         BOOST_UBLAS_INLINE
00205         symmetric_matrix &assign (const matrix_expression<AE> &ae) {
00206             matrix_assign<scalar_assign> (*this, ae);
00207             return *this;
00208         }
00209         template<class AE>
00210         BOOST_UBLAS_INLINE
00211         symmetric_matrix& operator += (const matrix_expression<AE> &ae) {
00212             self_type temporary (*this + ae);
00213             return assign_temporary (temporary);
00214         }
00215         template<class AE>
00216         BOOST_UBLAS_INLINE
00217         symmetric_matrix &plus_assign (const matrix_expression<AE> &ae) {
00218             matrix_assign<scalar_plus_assign> (*this, ae);
00219             return *this;
00220         }
00221         template<class AE>
00222         BOOST_UBLAS_INLINE
00223         symmetric_matrix& operator -= (const matrix_expression<AE> &ae) {
00224             self_type temporary (*this - ae);
00225             return assign_temporary (temporary);
00226         }
00227         template<class AE>
00228         BOOST_UBLAS_INLINE
00229         symmetric_matrix &minus_assign (const matrix_expression<AE> &ae) {
00230             matrix_assign<scalar_minus_assign> (*this, ae);
00231             return *this;
00232         }
00233         template<class AT>
00234         BOOST_UBLAS_INLINE
00235         symmetric_matrix& operator *= (const AT &at) {
00236             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
00237             return *this;
00238         }
00239         template<class AT>
00240         BOOST_UBLAS_INLINE
00241         symmetric_matrix& operator /= (const AT &at) {
00242             matrix_assign_scalar<scalar_divides_assign> (*this, at);
00243             return *this;
00244         }
00245 
00246         // Swapping
00247         BOOST_UBLAS_INLINE
00248         void swap (symmetric_matrix &m) {
00249             if (this != &m) {
00250                 std::swap (size_, m.size_);
00251                 data ().swap (m.data ());
00252             }
00253         }
00254         BOOST_UBLAS_INLINE
00255         friend void swap (symmetric_matrix &m1, symmetric_matrix &m2) {
00256             m1.swap (m2);
00257         }
00258 
00259         // Iterator types
00260 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00261         typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
00262         typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
00263         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
00264         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
00265 #else
00266         class const_iterator1;
00267         class iterator1;
00268         class const_iterator2;
00269         class iterator2;
00270 #endif
00271         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
00272         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
00273         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
00274         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
00275 
00276         // Element lookup
00277         BOOST_UBLAS_INLINE
00278         const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
00279             return const_iterator1 (*this, i, j);
00280         }
00281         BOOST_UBLAS_INLINE
00282         iterator1 find1 (int rank, size_type i, size_type j) {
00283             if (rank == 1)
00284                 i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
00285             if (rank == 0)
00286                 i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2());
00287             return iterator1 (*this, i, j);
00288         }
00289         BOOST_UBLAS_INLINE
00290         const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
00291             return const_iterator2 (*this, i, j);
00292         }
00293         BOOST_UBLAS_INLINE
00294         iterator2 find2 (int rank, size_type i, size_type j) {
00295             if (rank == 1)
00296                 j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
00297             if (rank == 0)
00298                 j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2());
00299             return iterator2 (*this, i, j);
00300         }
00301 
00302         // Iterators simply are indices.
00303 
00304 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
00305         class const_iterator1:
00306             public container_const_reference<symmetric_matrix>,
00307             public random_access_iterator_base<dense_random_access_iterator_tag,
00308                                                const_iterator1, value_type> {
00309         public:
00310             typedef typename symmetric_matrix::value_type value_type;
00311             typedef typename symmetric_matrix::difference_type difference_type;
00312             typedef typename symmetric_matrix::const_reference reference;
00313             typedef const typename symmetric_matrix::pointer pointer;
00314 
00315             typedef const_iterator2 dual_iterator_type;
00316             typedef const_reverse_iterator2 dual_reverse_iterator_type;
00317 
00318             // Construction and destruction
00319             BOOST_UBLAS_INLINE
00320             const_iterator1 ():
00321                 container_const_reference<self_type> (), it1_ (), it2_ () {}
00322             BOOST_UBLAS_INLINE
00323             const_iterator1 (const self_type &m, size_type it1, size_type it2):
00324                 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
00325             BOOST_UBLAS_INLINE
00326             const_iterator1 (const iterator1 &it):
00327                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
00328 
00329             // Arithmetic
00330             BOOST_UBLAS_INLINE
00331             const_iterator1 &operator ++ () {
00332                 ++ it1_;
00333                 return *this;
00334             }
00335             BOOST_UBLAS_INLINE
00336             const_iterator1 &operator -- () {
00337                 -- it1_;
00338                 return *this;
00339             }
00340             BOOST_UBLAS_INLINE
00341             const_iterator1 &operator += (difference_type n) {
00342                 it1_ += n;
00343                 return *this;
00344             }
00345             BOOST_UBLAS_INLINE
00346             const_iterator1 &operator -= (difference_type n) {
00347                 it1_ -= n;
00348                 return *this;
00349             }
00350             BOOST_UBLAS_INLINE
00351             difference_type operator - (const const_iterator1 &it) const {
00352                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00353                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
00354                 return it1_ - it.it1_;
00355             }
00356 
00357             // Dereference
00358             BOOST_UBLAS_INLINE
00359             const_reference operator * () const {
00360                 return (*this) () (it1_, it2_);
00361             }
00362             BOOST_UBLAS_INLINE
00363             const_reference operator [] (difference_type n) const {
00364                 return *(*this + n);
00365             }
00366 
00367 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
00368             BOOST_UBLAS_INLINE
00369 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00370             typename self_type::
00371 #endif
00372             const_iterator2 begin () const {
00373                 return (*this) ().find2 (1, it1_, 0);
00374             }
00375             BOOST_UBLAS_INLINE
00376 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00377             typename self_type::
00378 #endif
00379             const_iterator2 end () const {
00380                 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
00381             }
00382             BOOST_UBLAS_INLINE
00383 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00384             typename self_type::
00385 #endif
00386             const_reverse_iterator2 rbegin () const {
00387                 return const_reverse_iterator2 (end ());
00388             }
00389             BOOST_UBLAS_INLINE
00390 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00391             typename self_type::
00392 #endif
00393             const_reverse_iterator2 rend () const {
00394                 return const_reverse_iterator2 (begin ());
00395             }
00396 #endif
00397 
00398             // Indices
00399             BOOST_UBLAS_INLINE
00400             size_type index1 () const {
00401                 return it1_;
00402             }
00403             BOOST_UBLAS_INLINE
00404             size_type index2 () const {
00405                 return it2_;
00406             }
00407 
00408             // Assignment
00409             BOOST_UBLAS_INLINE
00410             const_iterator1 &operator = (const const_iterator1 &it) {
00411                 container_const_reference<self_type>::assign (&it ());
00412                 it1_ = it.it1_;
00413                 it2_ = it.it2_;
00414                 return *this;
00415             }
00416 
00417             // Comparison
00418             BOOST_UBLAS_INLINE
00419             bool operator == (const const_iterator1 &it) const {
00420                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00421                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
00422                 return it1_ == it.it1_;
00423             }
00424             BOOST_UBLAS_INLINE
00425             bool operator < (const const_iterator1 &it) const {
00426                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00427                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
00428                 return it1_ < it.it1_;
00429             }
00430 
00431         private:
00432             size_type it1_;
00433             size_type it2_;
00434         };
00435 #endif
00436 
00437         BOOST_UBLAS_INLINE
00438         const_iterator1 begin1 () const {
00439             return find1 (0, 0, 0);
00440         }
00441         BOOST_UBLAS_INLINE
00442         const_iterator1 end1 () const {
00443             return find1 (0, size_, 0);
00444         }
00445 
00446 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
00447         class iterator1:
00448             public container_reference<symmetric_matrix>,
00449             public random_access_iterator_base<packed_random_access_iterator_tag,
00450                                                iterator1, value_type> {
00451         public:
00452             typedef typename symmetric_matrix::value_type value_type;
00453             typedef typename symmetric_matrix::difference_type difference_type;
00454             typedef typename symmetric_matrix::reference reference;
00455             typedef typename symmetric_matrix::pointer pointer;
00456             typedef iterator2 dual_iterator_type;
00457             typedef reverse_iterator2 dual_reverse_iterator_type;
00458 
00459             // Construction and destruction
00460             BOOST_UBLAS_INLINE
00461             iterator1 ():
00462                 container_reference<self_type> (), it1_ (), it2_ () {}
00463             BOOST_UBLAS_INLINE
00464             iterator1 (self_type &m, size_type it1, size_type it2):
00465                 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
00466 
00467             // Arithmetic
00468             BOOST_UBLAS_INLINE
00469             iterator1 &operator ++ () {
00470                 ++ it1_;
00471                 return *this;
00472             }
00473             BOOST_UBLAS_INLINE
00474             iterator1 &operator -- () {
00475                 -- it1_;
00476                 return *this;
00477             }
00478             BOOST_UBLAS_INLINE
00479             iterator1 &operator += (difference_type n) {
00480                 it1_ += n;
00481                 return *this;
00482             }
00483             BOOST_UBLAS_INLINE
00484             iterator1 &operator -= (difference_type n) {
00485                 it1_ -= n;
00486                 return *this;
00487             }
00488             BOOST_UBLAS_INLINE
00489             difference_type operator - (const iterator1 &it) const {
00490                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00491                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
00492                 return it1_ - it.it1_;
00493             }
00494 
00495             // Dereference
00496             BOOST_UBLAS_INLINE
00497             reference operator * () const {
00498                 return (*this) () (it1_, it2_);
00499             }
00500             BOOST_UBLAS_INLINE
00501             reference operator [] (difference_type n) const {
00502                 return *(*this + n);
00503             }
00504 
00505 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
00506             BOOST_UBLAS_INLINE
00507 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00508             typename self_type::
00509 #endif
00510             iterator2 begin () const {
00511                 return (*this) ().find2 (1, it1_, 0);
00512             }
00513             BOOST_UBLAS_INLINE
00514 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00515             typename self_type::
00516 #endif
00517             iterator2 end () const {
00518                 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
00519             }
00520             BOOST_UBLAS_INLINE
00521 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00522             typename self_type::
00523 #endif
00524             reverse_iterator2 rbegin () const {
00525                 return reverse_iterator2 (end ());
00526             }
00527             BOOST_UBLAS_INLINE
00528 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00529             typename self_type::
00530 #endif
00531             reverse_iterator2 rend () const {
00532                 return reverse_iterator2 (begin ());
00533             }
00534 #endif
00535 
00536             // Indices
00537             BOOST_UBLAS_INLINE
00538             size_type index1 () const {
00539                 return it1_;
00540             }
00541             BOOST_UBLAS_INLINE
00542             size_type index2 () const {
00543                 return it2_;
00544             }
00545 
00546             // Assignment
00547             BOOST_UBLAS_INLINE
00548             iterator1 &operator = (const iterator1 &it) {
00549                 container_reference<self_type>::assign (&it ());
00550                 it1_ = it.it1_;
00551                 it2_ = it.it2_;
00552                 return *this;
00553             }
00554 
00555             // Comparison
00556             BOOST_UBLAS_INLINE
00557             bool operator == (const iterator1 &it) const {
00558                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00559                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
00560                 return it1_ == it.it1_;
00561             }
00562             BOOST_UBLAS_INLINE
00563             bool operator < (const iterator1 &it) const {
00564                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00565                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
00566                 return it1_ < it.it1_;
00567             }
00568 
00569         private:
00570             size_type it1_;
00571             size_type it2_;
00572 
00573             friend class const_iterator1;
00574         };
00575 #endif
00576 
00577         BOOST_UBLAS_INLINE
00578         iterator1 begin1 () {
00579             return find1 (0, 0, 0);
00580         }
00581         BOOST_UBLAS_INLINE
00582         iterator1 end1 () {
00583             return find1 (0, size_, 0);
00584         }
00585 
00586 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
00587         class const_iterator2:
00588             public container_const_reference<symmetric_matrix>,
00589             public random_access_iterator_base<dense_random_access_iterator_tag,
00590                                                const_iterator2, value_type> {
00591         public:
00592             typedef typename symmetric_matrix::value_type value_type;
00593             typedef typename symmetric_matrix::difference_type difference_type;
00594             typedef typename symmetric_matrix::const_reference reference;
00595             typedef const typename symmetric_matrix::pointer pointer;
00596 
00597             typedef const_iterator1 dual_iterator_type;
00598             typedef const_reverse_iterator1 dual_reverse_iterator_type;
00599 
00600             // Construction and destruction
00601             BOOST_UBLAS_INLINE
00602             const_iterator2 ():
00603                 container_const_reference<self_type> (), it1_ (), it2_ () {}
00604             BOOST_UBLAS_INLINE
00605             const_iterator2 (const self_type &m, size_type it1, size_type it2):
00606                 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
00607             BOOST_UBLAS_INLINE
00608             const_iterator2 (const iterator2 &it):
00609                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
00610 
00611             // Arithmetic
00612             BOOST_UBLAS_INLINE
00613             const_iterator2 &operator ++ () {
00614                 ++ it2_;
00615                 return *this;
00616             }
00617             BOOST_UBLAS_INLINE
00618             const_iterator2 &operator -- () {
00619                 -- it2_;
00620                 return *this;
00621             }
00622             BOOST_UBLAS_INLINE
00623             const_iterator2 &operator += (difference_type n) {
00624                 it2_ += n;
00625                 return *this;
00626             }
00627             BOOST_UBLAS_INLINE
00628             const_iterator2 &operator -= (difference_type n) {
00629                 it2_ -= n;
00630                 return *this;
00631             }
00632             BOOST_UBLAS_INLINE
00633             difference_type operator - (const const_iterator2 &it) const {
00634                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00635                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
00636                 return it2_ - it.it2_;
00637             }
00638 
00639             // Dereference
00640             BOOST_UBLAS_INLINE
00641             const_reference operator * () const {
00642                 return (*this) () (it1_, it2_);
00643             }
00644             BOOST_UBLAS_INLINE
00645             const_reference operator [] (difference_type n) const {
00646                 return *(*this + n);
00647             }
00648 
00649 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
00650             BOOST_UBLAS_INLINE
00651 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00652             typename self_type::
00653 #endif
00654             const_iterator1 begin () const {
00655                 return (*this) ().find1 (1, 0, it2_);
00656             }
00657             BOOST_UBLAS_INLINE
00658 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00659             typename self_type::
00660 #endif
00661             const_iterator1 end () const {
00662                 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
00663             }
00664             BOOST_UBLAS_INLINE
00665 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00666             typename self_type::
00667 #endif
00668             const_reverse_iterator1 rbegin () const {
00669                 return const_reverse_iterator1 (end ());
00670             }
00671             BOOST_UBLAS_INLINE
00672 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00673             typename self_type::
00674 #endif
00675             const_reverse_iterator1 rend () const {
00676                 return const_reverse_iterator1 (begin ());
00677             }
00678 #endif
00679 
00680             // Indices
00681             BOOST_UBLAS_INLINE
00682             size_type index1 () const {
00683                 return it1_;
00684             }
00685             BOOST_UBLAS_INLINE
00686             size_type index2 () const {
00687                 return it2_;
00688             }
00689 
00690             // Assignment
00691             BOOST_UBLAS_INLINE
00692             const_iterator2 &operator = (const const_iterator2 &it) {
00693                 container_const_reference<self_type>::assign (&it ());
00694                 it1_ = it.it1_;
00695                 it2_ = it.it2_;
00696                 return *this;
00697             }
00698 
00699             // Comparison
00700             BOOST_UBLAS_INLINE
00701             bool operator == (const const_iterator2 &it) const {
00702                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00703                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
00704                 return it2_ == it.it2_;
00705             }
00706             BOOST_UBLAS_INLINE
00707             bool operator < (const const_iterator2 &it) const {
00708                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00709                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
00710                 return it2_ < it.it2_;
00711             }
00712 
00713         private:
00714             size_type it1_;
00715             size_type it2_;
00716         };
00717 #endif
00718 
00719         BOOST_UBLAS_INLINE
00720         const_iterator2 begin2 () const {
00721             return find2 (0, 0, 0);
00722         }
00723         BOOST_UBLAS_INLINE
00724         const_iterator2 end2 () const {
00725             return find2 (0, 0, size_);
00726         }
00727 
00728 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
00729         class iterator2:
00730             public container_reference<symmetric_matrix>,
00731             public random_access_iterator_base<packed_random_access_iterator_tag,
00732                                                iterator2, value_type> {
00733         public:
00734             typedef typename symmetric_matrix::value_type value_type;
00735             typedef typename symmetric_matrix::difference_type difference_type;
00736             typedef typename symmetric_matrix::reference reference;
00737             typedef typename symmetric_matrix::pointer pointer;
00738 
00739             typedef iterator1 dual_iterator_type;
00740             typedef reverse_iterator1 dual_reverse_iterator_type;
00741 
00742             // Construction and destruction
00743             BOOST_UBLAS_INLINE
00744             iterator2 ():
00745                 container_reference<self_type> (), it1_ (), it2_ () {}
00746             BOOST_UBLAS_INLINE
00747             iterator2 (self_type &m, size_type it1, size_type it2):
00748                 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
00749 
00750             // Arithmetic
00751             BOOST_UBLAS_INLINE
00752             iterator2 &operator ++ () {
00753                 ++ it2_;
00754                 return *this;
00755             }
00756             BOOST_UBLAS_INLINE
00757             iterator2 &operator -- () {
00758                 -- it2_;
00759                 return *this;
00760             }
00761             BOOST_UBLAS_INLINE
00762             iterator2 &operator += (difference_type n) {
00763                 it2_ += n;
00764                 return *this;
00765             }
00766             BOOST_UBLAS_INLINE
00767             iterator2 &operator -= (difference_type n) {
00768                 it2_ -= n;
00769                 return *this;
00770             }
00771             BOOST_UBLAS_INLINE
00772             difference_type operator - (const iterator2 &it) const {
00773                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00774                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
00775                 return it2_ - it.it2_;
00776             }
00777 
00778             // Dereference
00779             BOOST_UBLAS_INLINE
00780             reference operator * () const {
00781                 return (*this) () (it1_, it2_);
00782             }
00783             BOOST_UBLAS_INLINE
00784             reference operator [] (difference_type n) const {
00785                 return *(*this + n);
00786             }
00787 
00788 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
00789             BOOST_UBLAS_INLINE
00790 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00791             typename self_type::
00792 #endif
00793             iterator1 begin () const {
00794                 return (*this) ().find1 (1, 0, it2_);
00795             }
00796             BOOST_UBLAS_INLINE
00797 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00798             typename self_type::
00799 #endif
00800             iterator1 end () const {
00801                 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
00802             }
00803             BOOST_UBLAS_INLINE
00804 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00805             typename self_type::
00806 #endif
00807             reverse_iterator1 rbegin () const {
00808                 return reverse_iterator1 (end ());
00809             }
00810             BOOST_UBLAS_INLINE
00811 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
00812             typename self_type::
00813 #endif
00814             reverse_iterator1 rend () const {
00815                 return reverse_iterator1 (begin ());
00816             }
00817 #endif
00818 
00819             // Indices
00820             BOOST_UBLAS_INLINE
00821             size_type index1 () const {
00822                 return it1_;
00823             }
00824             BOOST_UBLAS_INLINE
00825             size_type index2 () const {
00826                 return it2_;
00827             }
00828 
00829             // Assignment
00830             BOOST_UBLAS_INLINE
00831             iterator2 &operator = (const iterator2 &it) {
00832                 container_reference<self_type>::assign (&it ());
00833                 it1_ = it.it1_;
00834                 it2_ = it.it2_;
00835                 return *this;
00836             }
00837 
00838             // Comparison
00839             BOOST_UBLAS_INLINE
00840             bool operator == (const iterator2 &it) const {
00841                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00842                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
00843                 return it2_ == it.it2_;
00844             }
00845             BOOST_UBLAS_INLINE
00846             bool operator < (const iterator2 &it) const {
00847                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
00848                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
00849                 return it2_ < it.it2_;
00850             }
00851 
00852         private:
00853             size_type it1_;
00854             size_type it2_;
00855 
00856             friend class const_iterator2;
00857         };
00858 #endif
00859 
00860         BOOST_UBLAS_INLINE
00861         iterator2 begin2 () {
00862             return find2 (0, 0, 0);
00863         }
00864         BOOST_UBLAS_INLINE
00865         iterator2 end2 () {
00866             return find2 (0, 0, size_);
00867         }
00868 
00869         // Reverse iterators
00870 
00871         BOOST_UBLAS_INLINE
00872         const_reverse_iterator1 rbegin1 () const {
00873             return const_reverse_iterator1 (end1 ());
00874         }
00875         BOOST_UBLAS_INLINE
00876         const_reverse_iterator1 rend1 () const {
00877             return const_reverse_iterator1 (begin1 ());
00878         }
00879 
00880         BOOST_UBLAS_INLINE
00881         reverse_iterator1 rbegin1 () {
00882             return reverse_iterator1 (end1 ());
00883         }
00884         BOOST_UBLAS_INLINE
00885         reverse_iterator1 rend1 () {
00886             return reverse_iterator1 (begin1 ());
00887         }
00888 
00889         BOOST_UBLAS_INLINE
00890         const_reverse_iterator2 rbegin2 () const {
00891             return const_reverse_iterator2 (end2 ());
00892         }
00893         BOOST_UBLAS_INLINE
00894         const_reverse_iterator2 rend2 () const {
00895             return const_reverse_iterator2 (begin2 ());
00896         }
00897 
00898         BOOST_UBLAS_INLINE
00899         reverse_iterator2 rbegin2 () {
00900             return reverse_iterator2 (end2 ());
00901         }
00902         BOOST_UBLAS_INLINE
00903         reverse_iterator2 rend2 () {
00904             return reverse_iterator2 (begin2 ());
00905         }
00906 
00907     private:
00908         size_type size_;
00909         array_type data_;
00910     };
00911 
00912 
00913     // Symmetric matrix adaptor class
00914     template<class M, class TRI>
00915     class symmetric_adaptor:
00916         public matrix_expression<symmetric_adaptor<M, TRI> > {
00917 
00918         typedef symmetric_adaptor<M, TRI> self_type;
00919     public:
00920 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
00921         using matrix_expression<self_type>::operator ();
00922 #endif
00923         typedef const M const_matrix_type;
00924         typedef M matrix_type;
00925         typedef TRI triangular_type;
00926         typedef typename M::size_type size_type;
00927         typedef typename M::difference_type difference_type;
00928         typedef typename M::value_type value_type;
00929         typedef typename M::const_reference const_reference;
00930         typedef typename boost::mpl::if_<boost::is_const<M>,
00931                                           typename M::const_reference,
00932                                           typename M::reference>::type reference;
00933         typedef typename boost::mpl::if_<boost::is_const<M>,
00934                                           typename M::const_closure_type,
00935                                           typename M::closure_type>::type matrix_closure_type;
00936         typedef const self_type const_closure_type;
00937         typedef self_type closure_type;
00938         // Replaced by _temporary_traits to avoid type requirements on M
00939         //typedef typename M::vector_temporary_type vector_temporary_type;
00940         //typedef typename M::matrix_temporary_type matrix_temporary_type;
00941         typedef typename storage_restrict_traits<typename M::storage_category,
00942                                                  packed_proxy_tag>::storage_category storage_category;
00943         typedef typename M::orientation_category orientation_category;
00944 
00945         // Construction and destruction
00946         BOOST_UBLAS_INLINE
00947         symmetric_adaptor (matrix_type &data):
00948             matrix_expression<self_type> (),
00949             data_ (data) {
00950             BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
00951         }
00952         BOOST_UBLAS_INLINE
00953         symmetric_adaptor (const symmetric_adaptor &m):
00954             matrix_expression<self_type> (),
00955             data_ (m.data_) {
00956             BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
00957         }
00958 
00959         // Accessors
00960         BOOST_UBLAS_INLINE
00961         size_type size1 () const {
00962             return data_.size1 ();
00963         }
00964         BOOST_UBLAS_INLINE
00965         size_type size2 () const {
00966             return data_.size2 ();
00967         }
00968 
00969         // Storage accessors
00970         BOOST_UBLAS_INLINE
00971         const matrix_closure_type &data () const {
00972             return data_;
00973         }
00974         BOOST_UBLAS_INLINE
00975         matrix_closure_type &data () {
00976             return data_;
00977         }
00978 
00979         // Element access
00980 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
00981         BOOST_UBLAS_INLINE
00982         const_reference operator () (size_type i, size_type j) const {
00983             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
00984             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
00985             if (triangular_type::other (i, j))
00986                 return data () (i, j);
00987             else
00988                 return data () (j, i);
00989         }
00990         BOOST_UBLAS_INLINE
00991         reference operator () (size_type i, size_type j) {
00992             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
00993             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
00994             if (triangular_type::other (i, j))
00995                 return data () (i, j);
00996             else
00997                 return data () (j, i);
00998         }
00999 #else
01000         BOOST_UBLAS_INLINE
01001         reference operator () (size_type i, size_type j) const {
01002             BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
01003             BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
01004             if (triangular_type::other (i, j))
01005                 return data () (i, j);
01006             else
01007                 return data () (j, i);
01008         }
01009 #endif
01010 
01011         // Assignment
01012         BOOST_UBLAS_INLINE
01013         symmetric_adaptor &operator = (const symmetric_adaptor &m) {
01014             matrix_assign<scalar_assign, triangular_type> (*this, m);
01015             return *this;
01016         }
01017         BOOST_UBLAS_INLINE
01018         symmetric_adaptor &assign_temporary (symmetric_adaptor &m) {
01019             *this = m;
01020             return *this;
01021         }
01022         template<class AE>
01023         BOOST_UBLAS_INLINE
01024         symmetric_adaptor &operator = (const matrix_expression<AE> &ae) {
01025             matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae));
01026             return *this;
01027         }
01028         template<class AE>
01029         BOOST_UBLAS_INLINE
01030         symmetric_adaptor &assign (const matrix_expression<AE> &ae) {
01031             matrix_assign<scalar_assign, triangular_type> (*this, ae);
01032             return *this;
01033         }
01034         template<class AE>
01035         BOOST_UBLAS_INLINE
01036         symmetric_adaptor& operator += (const matrix_expression<AE> &ae) {
01037             matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae));
01038             return *this;
01039         }
01040         template<class AE>
01041         BOOST_UBLAS_INLINE
01042         symmetric_adaptor &plus_assign (const matrix_expression<AE> &ae) {
01043             matrix_assign<scalar_plus_assign, triangular_type> (*this, ae);
01044             return *this;
01045         }
01046         template<class AE>
01047         BOOST_UBLAS_INLINE
01048         symmetric_adaptor& operator -= (const matrix_expression<AE> &ae) {
01049             matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae));
01050             return *this;
01051         }
01052         template<class AE>
01053         BOOST_UBLAS_INLINE
01054         symmetric_adaptor &minus_assign (const matrix_expression<AE> &ae) {
01055             matrix_assign<scalar_minus_assign, triangular_type> (*this, ae);
01056             return *this;
01057         }
01058         template<class AT>
01059         BOOST_UBLAS_INLINE
01060         symmetric_adaptor& operator *= (const AT &at) {
01061             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
01062             return *this;
01063         }
01064         template<class AT>
01065         BOOST_UBLAS_INLINE
01066         symmetric_adaptor& operator /= (const AT &at) {
01067             matrix_assign_scalar<scalar_divides_assign> (*this, at);
01068             return *this;
01069         }
01070 
01071         // Closure comparison
01072         BOOST_UBLAS_INLINE
01073         bool same_closure (const symmetric_adaptor &sa) const {
01074             return (*this).data ().same_closure (sa.data ());
01075        }
01076 
01077         // Swapping
01078         BOOST_UBLAS_INLINE
01079         void swap (symmetric_adaptor &m) {
01080             if (this != &m)
01081                 matrix_swap<scalar_swap, triangular_type> (*this, m);
01082         }
01083         BOOST_UBLAS_INLINE
01084         friend void swap (symmetric_adaptor &m1, symmetric_adaptor &m2) {
01085             m1.swap (m2);
01086         }
01087 
01088         // Iterator types
01089     private:
01090         // Use matrix iterator
01091         typedef typename M::const_iterator1 const_subiterator1_type;
01092         typedef typename boost::mpl::if_<boost::is_const<M>,
01093                                           typename M::const_iterator1,
01094                                           typename M::iterator1>::type subiterator1_type;
01095         typedef typename M::const_iterator2 const_subiterator2_type;
01096         typedef typename boost::mpl::if_<boost::is_const<M>,
01097                                           typename M::const_iterator2,
01098                                           typename M::iterator2>::type subiterator2_type;
01099 
01100     public:
01101 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
01102         typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
01103         typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
01104         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
01105         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
01106 #else
01107         class const_iterator1;
01108         class iterator1;
01109         class const_iterator2;
01110         class iterator2;
01111 #endif
01112         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
01113         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
01114         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
01115         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
01116 
01117         // Element lookup
01118         BOOST_UBLAS_INLINE
01119         const_iterator1 find1 (int rank, size_type i, size_type j) const {
01120             if (triangular_type::other (i, j)) {
01121                 if (triangular_type::other (size1 (), j)) {
01122                     return const_iterator1 (*this, 0, 0,
01123                                             data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j),
01124                                             data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ()));
01125                 } else {
01126                     return const_iterator1 (*this, 0, 1,
01127                                             data ().find1 (rank, i, j), data ().find1 (rank, j, j),
01128                                             data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ()));
01129                 }
01130             } else {
01131                 if (triangular_type::other (size1 (), j)) {
01132                     return const_iterator1 (*this, 1, 0,
01133                                             data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j),
01134                                             data ().find2 (rank, j, i), data ().find2 (rank, j, j));
01135                 } else {
01136                     return const_iterator1 (*this, 1, 1,
01137                                             data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()),
01138                                             data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ()));
01139                 }
01140             }
01141         }
01142         BOOST_UBLAS_INLINE
01143         iterator1 find1 (int rank, size_type i, size_type j) {
01144             if (rank == 1)
01145                 i = triangular_type::mutable_restrict1 (i, j, size1(), size2());
01146             return iterator1 (*this, data ().find1 (rank, i, j));
01147         }
01148         BOOST_UBLAS_INLINE
01149         const_iterator2 find2 (int rank, size_type i, size_type j) const {
01150             if (triangular_type::other (i, j)) {
01151                 if (triangular_type::other (i, size2 ())) {
01152                     return const_iterator2 (*this, 1, 1,
01153                                             data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()),
01154                                             data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ()));
01155                 } else {
01156                     return const_iterator2 (*this, 1, 0,
01157                                             data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i),
01158                                             data ().find2 (rank, i, j), data ().find2 (rank, i, i));
01159                 }
01160             } else {
01161                 if (triangular_type::other (i, size2 ())) {
01162                     return const_iterator2 (*this, 0, 1,
01163                                             data ().find1 (rank, j, i), data ().find1 (rank, i, i),
01164                                             data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ()));
01165                 } else {
01166                     return const_iterator2 (*this, 0, 0,
01167                                             data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i),
01168                                             data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ()));
01169                 }
01170             }
01171         }
01172         BOOST_UBLAS_INLINE
01173         iterator2 find2 (int rank, size_type i, size_type j) {
01174             if (rank == 1)
01175                 j = triangular_type::mutable_restrict2 (i, j, size1(), size2());
01176             return iterator2 (*this, data ().find2 (rank, i, j));
01177         }
01178 
01179         // Iterators simply are indices.
01180 
01181 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
01182         class const_iterator1:
01183             public container_const_reference<symmetric_adaptor>,
01184             public random_access_iterator_base<typename iterator_restrict_traits<
01185                                                    typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
01186                                                const_iterator1, value_type> {
01187         public:
01188             typedef typename const_subiterator1_type::value_type value_type;
01189             typedef typename const_subiterator1_type::difference_type difference_type;
01190             typedef typename const_subiterator1_type::reference reference;
01191             typedef typename const_subiterator1_type::pointer pointer;
01192 
01193             typedef const_iterator2 dual_iterator_type;
01194             typedef const_reverse_iterator2 dual_reverse_iterator_type;
01195 
01196             // Construction and destruction
01197             BOOST_UBLAS_INLINE
01198             const_iterator1 ():
01199                 container_const_reference<self_type> (),
01200                 begin_ (-1), end_ (-1), current_ (-1),
01201                 it1_begin_ (), it1_end_ (), it1_ (),
01202                 it2_begin_ (), it2_end_ (), it2_ () {}
01203             BOOST_UBLAS_INLINE
01204             const_iterator1 (const self_type &m, int begin, int end,
01205                              const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
01206                              const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
01207                 container_const_reference<self_type> (m),
01208                 begin_ (begin), end_ (end), current_ (begin),
01209                 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
01210                 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
01211                 if (current_ == 0 && it1_ == it1_end_)
01212                     current_ = 1;
01213                 if (current_ == 1 && it2_ == it2_end_)
01214                     current_ = 0;
01215                 if ((current_ == 0 && it1_ == it1_end_) ||
01216                     (current_ == 1 && it2_ == it2_end_))
01217                     current_ = end_;
01218                 BOOST_UBLAS_CHECK (current_ == end_ ||
01219                                    (current_ == 0 && it1_ != it1_end_) ||
01220                                    (current_ == 1 && it2_ != it2_end_), internal_logic ());
01221             }
01222             // FIXME cannot compile
01223             //  iterator1 does not have these members!
01224             BOOST_UBLAS_INLINE
01225             const_iterator1 (const iterator1 &it):
01226                 container_const_reference<self_type> (it ()),
01227                 begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
01228                 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
01229                 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
01230                 BOOST_UBLAS_CHECK (current_ == end_ ||
01231                                    (current_ == 0 && it1_ != it1_end_) ||
01232                                    (current_ == 1 && it2_ != it2_end_), internal_logic ());
01233             }
01234 
01235             // Arithmetic
01236             BOOST_UBLAS_INLINE
01237             const_iterator1 &operator ++ () {
01238                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01239                 if (current_ == 0) {
01240                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
01241                     ++ it1_;
01242                     if (it1_ == it1_end_ && end_ == 1) {
01243                         it2_ = it2_begin_;
01244                         current_ = 1;
01245                     }
01246                 } else /* if (current_ == 1) */ {
01247                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
01248                     ++ it2_;
01249                     if (it2_ == it2_end_ && end_ == 0) {
01250                         it1_ = it1_begin_;
01251                         current_ = 0;
01252                     }
01253                 }
01254                 return *this;
01255             }
01256             BOOST_UBLAS_INLINE
01257             const_iterator1 &operator -- () {
01258                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01259                 if (current_ == 0) {
01260                     if (it1_ == it1_begin_ && begin_ == 1) {
01261                         it2_ = it2_end_;
01262                         BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
01263                         -- it2_;
01264                         current_ = 1;
01265                     } else {
01266                         -- it1_;
01267                     }
01268                 } else /* if (current_ == 1) */ {
01269                     if (it2_ == it2_begin_ && begin_ == 0) {
01270                         it1_ = it1_end_;
01271                         BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
01272                         -- it1_;
01273                         current_ = 0;
01274                     } else {
01275                         -- it2_;
01276                     }
01277                 }
01278                 return *this;
01279             }
01280             BOOST_UBLAS_INLINE
01281             const_iterator1 &operator += (difference_type n) {
01282                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01283                 if (current_ == 0) {
01284                     size_type d = (std::min) (n, it1_end_ - it1_);
01285                     it1_ += d;
01286                     n -= d;
01287                     if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
01288                         BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
01289                         d = (std::min) (n, it2_end_ - it2_begin_);
01290                         it2_ = it2_begin_ + d;
01291                         n -= d;
01292                         current_ = 1;
01293                     }
01294                 } else /* if (current_ == 1) */ {
01295                     size_type d = (std::min) (n, it2_end_ - it2_);
01296                     it2_ += d;
01297                     n -= d;
01298                     if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
01299                         BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
01300                         d = (std::min) (n, it1_end_ - it1_begin_);
01301                         it1_ = it1_begin_ + d;
01302                         n -= d;
01303                         current_ = 0;
01304                     }
01305                 }
01306                 BOOST_UBLAS_CHECK (n == 0, external_logic ());
01307                 return *this;
01308             }
01309             BOOST_UBLAS_INLINE
01310             const_iterator1 &operator -= (difference_type n) {
01311                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01312                 if (current_ == 0) {
01313                     size_type d = (std::min) (n, it1_ - it1_begin_);
01314                     it1_ -= d;
01315                     n -= d;
01316                     if (n > 0) {
01317                         BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
01318                         d = (std::min) (n, it2_end_ - it2_begin_);
01319                         it2_ = it2_end_ - d;
01320                         n -= d;
01321                         current_ = 1;
01322                     }
01323                 } else /* if (current_ == 1) */ {
01324                     size_type d = (std::min) (n, it2_ - it2_begin_);
01325                     it2_ -= d;
01326                     n -= d;
01327                     if (n > 0) {
01328                         BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
01329                         d = (std::min) (n, it1_end_ - it1_begin_);
01330                         it1_ = it1_end_ - d;
01331                         n -= d;
01332                         current_ = 0;
01333                     }
01334                 }
01335                 BOOST_UBLAS_CHECK (n == 0, external_logic ());
01336                 return *this;
01337             }
01338             BOOST_UBLAS_INLINE
01339             difference_type operator - (const const_iterator1 &it) const {
01340                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01341                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01342                 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
01343                 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
01344                 if (current_ == 0 && it.current_ == 0) {
01345                     return it1_ - it.it1_;
01346                 } else if (current_ == 0 && it.current_ == 1) {
01347                     if (end_ == 1 && it.end_ == 1) {
01348                         return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
01349                     } else /* if (end_ == 0 && it.end_ == 0) */ {
01350                         return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
01351                     }
01352 
01353                 } else if (current_ == 1 && it.current_ == 0) {
01354                     if (end_ == 1 && it.end_ == 1) {
01355                         return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
01356                     } else /* if (end_ == 0 && it.end_ == 0) */ {
01357                         return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
01358                     }
01359                 }
01360                 /* current_ == 1 && it.current_ == 1 */ {
01361                     return it2_ - it.it2_;
01362                 }
01363             }
01364 
01365             // Dereference
01366             BOOST_UBLAS_INLINE
01367             const_reference operator * () const {
01368                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01369                 if (current_ == 0) {
01370                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
01371                     return *it1_;
01372                 } else /* if (current_ == 1) */ {
01373                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
01374                     return *it2_;
01375                 }
01376             }
01377             BOOST_UBLAS_INLINE
01378             const_reference operator [] (difference_type n) const {
01379                 return *(*this + n);
01380             }
01381 
01382 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
01383             BOOST_UBLAS_INLINE
01384 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01385             typename self_type::
01386 #endif
01387             const_iterator2 begin () const {
01388                 return (*this) ().find2 (1, index1 (), 0);
01389             }
01390             BOOST_UBLAS_INLINE
01391 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01392             typename self_type::
01393 #endif
01394             const_iterator2 end () const {
01395                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
01396             }
01397             BOOST_UBLAS_INLINE
01398 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01399             typename self_type::
01400 #endif
01401             const_reverse_iterator2 rbegin () const {
01402                 return const_reverse_iterator2 (end ());
01403             }
01404             BOOST_UBLAS_INLINE
01405 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01406             typename self_type::
01407 #endif
01408             const_reverse_iterator2 rend () const {
01409                 return const_reverse_iterator2 (begin ());
01410             }
01411 #endif
01412 
01413             // Indices
01414             BOOST_UBLAS_INLINE
01415             size_type index1 () const {
01416                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01417                 if (current_ == 0) {
01418                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
01419                     return it1_.index1 ();
01420                 } else /* if (current_ == 1) */ {
01421                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
01422                     return it2_.index2 ();
01423                 }
01424             }
01425             BOOST_UBLAS_INLINE
01426             size_type index2 () const {
01427                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01428                 if (current_ == 0) {
01429                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
01430                     return it1_.index2 ();
01431                 } else /* if (current_ == 1) */ {
01432                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
01433                     return it2_.index1 ();
01434                 }
01435             }
01436 
01437             // Assignment
01438             BOOST_UBLAS_INLINE
01439             const_iterator1 &operator = (const const_iterator1 &it) {
01440                 container_const_reference<self_type>::assign (&it ());
01441                 begin_ = it.begin_;
01442                 end_ = it.end_;
01443                 current_ = it.current_;
01444                 it1_begin_ = it.it1_begin_;
01445                 it1_end_ = it.it1_end_;
01446                 it1_ = it.it1_;
01447                 it2_begin_ = it.it2_begin_;
01448                 it2_end_ = it.it2_end_;
01449                 it2_ = it.it2_;
01450                 return *this;
01451             }
01452 
01453             // Comparison
01454             BOOST_UBLAS_INLINE
01455             bool operator == (const const_iterator1 &it) const {
01456                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01457                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01458                 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
01459                 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
01460                 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
01461                        (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
01462             }
01463             BOOST_UBLAS_INLINE
01464             bool operator < (const const_iterator1 &it) const {
01465                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01466                 return it - *this > 0;
01467             }
01468 
01469         private:
01470             int begin_;
01471             int end_;
01472             int current_;
01473             const_subiterator1_type it1_begin_;
01474             const_subiterator1_type it1_end_;
01475             const_subiterator1_type it1_;
01476             const_subiterator2_type it2_begin_;
01477             const_subiterator2_type it2_end_;
01478             const_subiterator2_type it2_;
01479         };
01480 #endif
01481 
01482         BOOST_UBLAS_INLINE
01483         const_iterator1 begin1 () const {
01484             return find1 (0, 0, 0);
01485         }
01486         BOOST_UBLAS_INLINE
01487         const_iterator1 end1 () const {
01488             return find1 (0, size1 (), 0);
01489         }
01490 
01491 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
01492         class iterator1:
01493             public container_reference<symmetric_adaptor>,
01494             public random_access_iterator_base<typename iterator_restrict_traits<
01495                                                    typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
01496                                                iterator1, value_type> {
01497         public:
01498             typedef typename subiterator1_type::value_type value_type;
01499             typedef typename subiterator1_type::difference_type difference_type;
01500             typedef typename subiterator1_type::reference reference;
01501             typedef typename subiterator1_type::pointer pointer;
01502 
01503             typedef iterator2 dual_iterator_type;
01504             typedef reverse_iterator2 dual_reverse_iterator_type;
01505 
01506             // Construction and destruction
01507             BOOST_UBLAS_INLINE
01508             iterator1 ():
01509                 container_reference<self_type> (), it1_ () {}
01510             BOOST_UBLAS_INLINE
01511             iterator1 (self_type &m, const subiterator1_type &it1):
01512                 container_reference<self_type> (m), it1_ (it1) {}
01513 
01514             // Arithmetic
01515             BOOST_UBLAS_INLINE
01516             iterator1 &operator ++ () {
01517                 ++ it1_;
01518                 return *this;
01519             }
01520             BOOST_UBLAS_INLINE
01521             iterator1 &operator -- () {
01522                 -- it1_;
01523                 return *this;
01524             }
01525             BOOST_UBLAS_INLINE
01526             iterator1 &operator += (difference_type n) {
01527                 it1_ += n;
01528                 return *this;
01529             }
01530             BOOST_UBLAS_INLINE
01531             iterator1 &operator -= (difference_type n) {
01532                 it1_ -= n;
01533                 return *this;
01534             }
01535             BOOST_UBLAS_INLINE
01536             difference_type operator - (const iterator1 &it) const {
01537                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01538                 return it1_ - it.it1_;
01539             }
01540 
01541             // Dereference
01542             BOOST_UBLAS_INLINE
01543             reference operator * () const {
01544                 return *it1_;
01545             }
01546             BOOST_UBLAS_INLINE
01547             reference operator [] (difference_type n) const {
01548                 return *(*this + n);
01549             }
01550 
01551 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
01552             BOOST_UBLAS_INLINE
01553 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01554             typename self_type::
01555 #endif
01556             iterator2 begin () const {
01557                 return (*this) ().find2 (1, index1 (), 0);
01558             }
01559             BOOST_UBLAS_INLINE
01560 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01561             typename self_type::
01562 #endif
01563             iterator2 end () const {
01564                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
01565             }
01566             BOOST_UBLAS_INLINE
01567 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01568             typename self_type::
01569 #endif
01570             reverse_iterator2 rbegin () const {
01571                 return reverse_iterator2 (end ());
01572             }
01573             BOOST_UBLAS_INLINE
01574 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01575             typename self_type::
01576 #endif
01577             reverse_iterator2 rend () const {
01578                 return reverse_iterator2 (begin ());
01579             }
01580 #endif
01581 
01582             // Indices
01583             BOOST_UBLAS_INLINE
01584             size_type index1 () const {
01585                 return it1_.index1 ();
01586             }
01587             BOOST_UBLAS_INLINE
01588             size_type index2 () const {
01589                 return it1_.index2 ();
01590             }
01591 
01592             // Assignment
01593             BOOST_UBLAS_INLINE
01594             iterator1 &operator = (const iterator1 &it) {
01595                 container_reference<self_type>::assign (&it ());
01596                 it1_ = it.it1_;
01597                 return *this;
01598             }
01599 
01600             // Comparison
01601             BOOST_UBLAS_INLINE
01602             bool operator == (const iterator1 &it) const {
01603                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01604                 return it1_ == it.it1_;
01605             }
01606             BOOST_UBLAS_INLINE
01607             bool operator < (const iterator1 &it) const {
01608                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01609                 return it1_ < it.it1_;
01610             }
01611 
01612         private:
01613             subiterator1_type it1_;
01614 
01615             friend class const_iterator1;
01616         };
01617 #endif
01618 
01619         BOOST_UBLAS_INLINE
01620         iterator1 begin1 () {
01621             return find1 (0, 0, 0);
01622         }
01623         BOOST_UBLAS_INLINE
01624         iterator1 end1 () {
01625             return find1 (0, size1 (), 0);
01626         }
01627 
01628 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
01629         class const_iterator2:
01630             public container_const_reference<symmetric_adaptor>,
01631             public random_access_iterator_base<typename iterator_restrict_traits<
01632                                                    typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
01633                                                const_iterator2, value_type> {
01634         public:
01635             typedef typename const_subiterator2_type::value_type value_type;
01636             typedef typename const_subiterator2_type::difference_type difference_type;
01637             typedef typename const_subiterator2_type::reference reference;
01638             typedef typename const_subiterator2_type::pointer pointer;
01639 
01640             typedef const_iterator1 dual_iterator_type;
01641             typedef const_reverse_iterator1 dual_reverse_iterator_type;
01642 
01643             // Construction and destruction
01644             BOOST_UBLAS_INLINE
01645             const_iterator2 ():
01646                 container_const_reference<self_type> (),
01647                 begin_ (-1), end_ (-1), current_ (-1),
01648                 it1_begin_ (), it1_end_ (), it1_ (),
01649                 it2_begin_ (), it2_end_ (), it2_ () {}
01650             BOOST_UBLAS_INLINE
01651             const_iterator2 (const self_type &m, int begin, int end,
01652                              const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
01653                              const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
01654                 container_const_reference<self_type> (m),
01655                 begin_ (begin), end_ (end), current_ (begin),
01656                 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
01657                 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
01658                 if (current_ == 0 && it1_ == it1_end_)
01659                     current_ = 1;
01660                 if (current_ == 1 && it2_ == it2_end_)
01661                     current_ = 0;
01662                 if ((current_ == 0 && it1_ == it1_end_) ||
01663                     (current_ == 1 && it2_ == it2_end_))
01664                     current_ = end_;
01665                 BOOST_UBLAS_CHECK (current_ == end_ ||
01666                                    (current_ == 0 && it1_ != it1_end_) ||
01667                                    (current_ == 1 && it2_ != it2_end_), internal_logic ());
01668             }
01669             // FIXME cannot compiler
01670             //  iterator2 does not have these members!
01671             BOOST_UBLAS_INLINE
01672             const_iterator2 (const iterator2 &it):
01673                 container_const_reference<self_type> (it ()),
01674                 begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
01675                 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
01676                 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
01677                 BOOST_UBLAS_CHECK (current_ == end_ ||
01678                                    (current_ == 0 && it1_ != it1_end_) ||
01679                                    (current_ == 1 && it2_ != it2_end_), internal_logic ());
01680             }
01681 
01682             // Arithmetic
01683             BOOST_UBLAS_INLINE
01684             const_iterator2 &operator ++ () {
01685                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01686                 if (current_ == 0) {
01687                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
01688                     ++ it1_;
01689                     if (it1_ == it1_end_ && end_ == 1) {
01690                         it2_ = it2_begin_;
01691                         current_ = 1;
01692                     }
01693                 } else /* if (current_ == 1) */ {
01694                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
01695                     ++ it2_;
01696                     if (it2_ == it2_end_ && end_ == 0) {
01697                         it1_ = it1_begin_;
01698                         current_ = 0;
01699                     }
01700                 }
01701                 return *this;
01702             }
01703             BOOST_UBLAS_INLINE
01704             const_iterator2 &operator -- () {
01705                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01706                 if (current_ == 0) {
01707                     if (it1_ == it1_begin_ && begin_ == 1) {
01708                         it2_ = it2_end_;
01709                         BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
01710                         -- it2_;
01711                         current_ = 1;
01712                     } else {
01713                         -- it1_;
01714                     }
01715                 } else /* if (current_ == 1) */ {
01716                     if (it2_ == it2_begin_ && begin_ == 0) {
01717                         it1_ = it1_end_;
01718                         BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
01719                         -- it1_;
01720                         current_ = 0;
01721                     } else {
01722                         -- it2_;
01723                     }
01724                 }
01725                 return *this;
01726             }
01727             BOOST_UBLAS_INLINE
01728             const_iterator2 &operator += (difference_type n) {
01729                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01730                 if (current_ == 0) {
01731                     size_type d = (std::min) (n, it1_end_ - it1_);
01732                     it1_ += d;
01733                     n -= d;
01734                     if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
01735                         BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
01736                         d = (std::min) (n, it2_end_ - it2_begin_);
01737                         it2_ = it2_begin_ + d;
01738                         n -= d;
01739                         current_ = 1;
01740                     }
01741                 } else /* if (current_ == 1) */ {
01742                     size_type d = (std::min) (n, it2_end_ - it2_);
01743                     it2_ += d;
01744                     n -= d;
01745                     if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
01746                         BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
01747                         d = (std::min) (n, it1_end_ - it1_begin_);
01748                         it1_ = it1_begin_ + d;
01749                         n -= d;
01750                         current_ = 0;
01751                     }
01752                 }
01753                 BOOST_UBLAS_CHECK (n == 0, external_logic ());
01754                 return *this;
01755             }
01756             BOOST_UBLAS_INLINE
01757             const_iterator2 &operator -= (difference_type n) {
01758                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01759                 if (current_ == 0) {
01760                     size_type d = (std::min) (n, it1_ - it1_begin_);
01761                     it1_ -= d;
01762                     n -= d;
01763                     if (n > 0) {
01764                         BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
01765                         d = (std::min) (n, it2_end_ - it2_begin_);
01766                         it2_ = it2_end_ - d;
01767                         n -= d;
01768                         current_ = 1;
01769                     }
01770                 } else /* if (current_ == 1) */ {
01771                     size_type d = (std::min) (n, it2_ - it2_begin_);
01772                     it2_ -= d;
01773                     n -= d;
01774                     if (n > 0) {
01775                         BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
01776                         d = (std::min) (n, it1_end_ - it1_begin_);
01777                         it1_ = it1_end_ - d;
01778                         n -= d;
01779                         current_ = 0;
01780                     }
01781                 }
01782                 BOOST_UBLAS_CHECK (n == 0, external_logic ());
01783                 return *this;
01784             }
01785             BOOST_UBLAS_INLINE
01786             difference_type operator - (const const_iterator2 &it) const {
01787                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01788                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01789                 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
01790                 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
01791                 if (current_ == 0 && it.current_ == 0) {
01792                     return it1_ - it.it1_;
01793                 } else if (current_ == 0 && it.current_ == 1) {
01794                     if (end_ == 1 && it.end_ == 1) {
01795                         return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
01796                     } else /* if (end_ == 0 && it.end_ == 0) */ {
01797                         return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
01798                     }
01799 
01800                 } else if (current_ == 1 && it.current_ == 0) {
01801                     if (end_ == 1 && it.end_ == 1) {
01802                         return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
01803                     } else /* if (end_ == 0 && it.end_ == 0) */ {
01804                         return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
01805                     }
01806                 }
01807                 /* current_ == 1 && it.current_ == 1 */ {
01808                     return it2_ - it.it2_;
01809                 }
01810             }
01811 
01812             // Dereference
01813             BOOST_UBLAS_INLINE
01814             const_reference operator * () const {
01815                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01816                 if (current_ == 0) {
01817                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
01818                     return *it1_;
01819                 } else /* if (current_ == 1) */ {
01820                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
01821                     return *it2_;
01822                 }
01823             }
01824             BOOST_UBLAS_INLINE
01825             const_reference operator [] (difference_type n) const {
01826                 return *(*this + n);
01827             }
01828 
01829 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
01830             BOOST_UBLAS_INLINE
01831 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01832             typename self_type::
01833 #endif
01834             const_iterator1 begin () const {
01835                 return (*this) ().find1 (1, 0, index2 ());
01836             }
01837             BOOST_UBLAS_INLINE
01838 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01839             typename self_type::
01840 #endif
01841             const_iterator1 end () const {
01842                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
01843             }
01844             BOOST_UBLAS_INLINE
01845 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01846             typename self_type::
01847 #endif
01848             const_reverse_iterator1 rbegin () const {
01849                 return const_reverse_iterator1 (end ());
01850             }
01851             BOOST_UBLAS_INLINE
01852 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
01853             typename self_type::
01854 #endif
01855             const_reverse_iterator1 rend () const {
01856                 return const_reverse_iterator1 (begin ());
01857             }
01858 #endif
01859 
01860             // Indices
01861             BOOST_UBLAS_INLINE
01862             size_type index1 () const {
01863                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01864                 if (current_ == 0) {
01865                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
01866                     return it1_.index2 ();
01867                 } else /* if (current_ == 1) */ {
01868                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
01869                     return it2_.index1 ();
01870                 }
01871             }
01872             BOOST_UBLAS_INLINE
01873             size_type index2 () const {
01874                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01875                 if (current_ == 0) {
01876                     BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
01877                     return it1_.index1 ();
01878                 } else /* if (current_ == 1) */ {
01879                     BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
01880                     return it2_.index2 ();
01881                 }
01882             }
01883 
01884             // Assignment
01885             BOOST_UBLAS_INLINE
01886             const_iterator2 &operator = (const const_iterator2 &it) {
01887                 container_const_reference<self_type>::assign (&it ());
01888                 begin_ = it.begin_;
01889                 end_ = it.end_;
01890                 current_ = it.current_;
01891                 it1_begin_ = it.it1_begin_;
01892                 it1_end_ = it.it1_end_;
01893                 it1_ = it.it1_;
01894                 it2_begin_ = it.it2_begin_;
01895                 it2_end_ = it.it2_end_;
01896                 it2_ = it.it2_;
01897                 return *this;
01898             }
01899 
01900             // Comparison
01901             BOOST_UBLAS_INLINE
01902             bool operator == (const const_iterator2 &it) const {
01903                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01904                 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
01905                 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
01906                 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
01907                 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
01908                        (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
01909             }
01910             BOOST_UBLAS_INLINE
01911             bool operator < (const const_iterator2 &it) const {
01912                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01913                 return it - *this > 0;
01914             }
01915 
01916         private:
01917             int begin_;
01918             int end_;
01919             int current_;
01920             const_subiterator1_type it1_begin_;
01921             const_subiterator1_type it1_end_;
01922             const_subiterator1_type it1_;
01923             const_subiterator2_type it2_begin_;
01924             const_subiterator2_type it2_end_;
01925             const_subiterator2_type it2_;
01926         };
01927 #endif
01928 
01929         BOOST_UBLAS_INLINE
01930         const_iterator2 begin2 () const {
01931             return find2 (0, 0, 0);
01932         }
01933         BOOST_UBLAS_INLINE
01934         const_iterator2 end2 () const {
01935             return find2 (0, 0, size2 ());
01936         }
01937 
01938 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
01939         class iterator2:
01940             public container_reference<symmetric_adaptor>,
01941             public random_access_iterator_base<typename iterator_restrict_traits<
01942                                                    typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
01943                                                iterator2, value_type> {
01944         public:
01945             typedef typename subiterator2_type::value_type value_type;
01946             typedef typename subiterator2_type::difference_type difference_type;
01947             typedef typename subiterator2_type::reference reference;
01948             typedef typename subiterator2_type::pointer pointer;
01949 
01950             typedef iterator1 dual_iterator_type;
01951             typedef reverse_iterator1 dual_reverse_iterator_type;
01952 
01953             // Construction and destruction
01954             BOOST_UBLAS_INLINE
01955             iterator2 ():
01956                 container_reference<self_type> (), it2_ () {}
01957             BOOST_UBLAS_INLINE
01958             iterator2 (self_type &m, const subiterator2_type &it2):
01959                 container_reference<self_type> (m), it2_ (it2) {}
01960 
01961             // Arithmetic
01962             BOOST_UBLAS_INLINE
01963             iterator2 &operator ++ () {
01964                 ++ it2_;
01965                 return *this;
01966             }
01967             BOOST_UBLAS_INLINE
01968             iterator2 &operator -- () {
01969                 -- it2_;
01970                 return *this;
01971             }
01972             BOOST_UBLAS_INLINE
01973             iterator2 &operator += (difference_type n) {
01974                 it2_ += n;
01975                 return *this;
01976             }
01977             BOOST_UBLAS_INLINE
01978             iterator2 &operator -= (difference_type n) {
01979                 it2_ -= n;
01980                 return *this;
01981             }
01982             BOOST_UBLAS_INLINE
01983             difference_type operator - (const iterator2 &it) const {
01984                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
01985                 return it2_ - it.it2_;
01986             }
01987 
01988             // Dereference
01989             BOOST_UBLAS_INLINE
01990             reference operator * () const {
01991                 return *it2_;
01992             }
01993             BOOST_UBLAS_INLINE
01994             reference operator [] (difference_type n) const {
01995                 return *(*this + n);
01996             }
01997 
01998 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
01999             BOOST_UBLAS_INLINE
02000 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02001             typename self_type::
02002 #endif
02003             iterator1 begin () const {
02004                 return (*this) ().find1 (1, 0, index2 ());
02005             }
02006             BOOST_UBLAS_INLINE
02007 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02008             typename self_type::
02009 #endif
02010             iterator1 end () const {
02011                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
02012             }
02013             BOOST_UBLAS_INLINE
02014 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02015             typename self_type::
02016 #endif
02017             reverse_iterator1 rbegin () const {
02018                 return reverse_iterator1 (end ());
02019             }
02020             BOOST_UBLAS_INLINE
02021 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
02022             typename self_type::
02023 #endif
02024             reverse_iterator1 rend () const {
02025                 return reverse_iterator1 (begin ());
02026             }
02027 #endif
02028 
02029             // Indices
02030             BOOST_UBLAS_INLINE
02031             size_type index1 () const {
02032                 return it2_.index1 ();
02033             }
02034             BOOST_UBLAS_INLINE
02035             size_type index2 () const {
02036                 return it2_.index2 ();
02037             }
02038 
02039             // Assignment
02040             BOOST_UBLAS_INLINE
02041             iterator2 &operator = (const iterator2 &it) {
02042                 container_reference<self_type>::assign (&it ());
02043                 it2_ = it.it2_;
02044                 return *this;
02045             }
02046 
02047             // Comparison
02048             BOOST_UBLAS_INLINE
02049             bool operator == (const iterator2 &it) const {
02050                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
02051                 return it2_ == it.it2_;
02052             }
02053             BOOST_UBLAS_INLINE
02054             bool operator < (const iterator2 &it) const {
02055                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
02056                 return it2_ < it.it2_;
02057             }
02058 
02059         private:
02060             subiterator2_type it2_;
02061 
02062             friend class const_iterator2;
02063         };
02064 #endif
02065 
02066         BOOST_UBLAS_INLINE
02067         iterator2 begin2 () {
02068             return find2 (0, 0, 0);
02069         }
02070         BOOST_UBLAS_INLINE
02071         iterator2 end2 () {
02072             return find2 (0, 0, size2 ());
02073         }
02074 
02075         // Reverse iterators
02076 
02077         BOOST_UBLAS_INLINE
02078         const_reverse_iterator1 rbegin1 () const {
02079             return const_reverse_iterator1 (end1 ());
02080         }
02081         BOOST_UBLAS_INLINE
02082         const_reverse_iterator1 rend1 () const {
02083             return const_reverse_iterator1 (begin1 ());
02084         }
02085 
02086         BOOST_UBLAS_INLINE
02087         reverse_iterator1 rbegin1 () {
02088             return reverse_iterator1 (end1 ());
02089         }
02090         BOOST_UBLAS_INLINE
02091         reverse_iterator1 rend1 () {
02092             return reverse_iterator1 (begin1 ());
02093         }
02094 
02095         BOOST_UBLAS_INLINE
02096         const_reverse_iterator2 rbegin2 () const {
02097             return const_reverse_iterator2 (end2 ());
02098         }
02099         BOOST_UBLAS_INLINE
02100         const_reverse_iterator2 rend2 () const {
02101             return const_reverse_iterator2 (begin2 ());
02102         }
02103 
02104         BOOST_UBLAS_INLINE
02105         reverse_iterator2 rbegin2 () {
02106             return reverse_iterator2 (end2 ());
02107         }
02108         BOOST_UBLAS_INLINE
02109         reverse_iterator2 rend2 () {
02110             return reverse_iterator2 (begin2 ());
02111         }
02112 
02113     private:
02114         matrix_closure_type data_;
02115     };
02116 
02117     // Specialization for temporary_traits
02118     template <class M, class TRI>
02119     struct vector_temporary_traits< symmetric_adaptor<M, TRI> >
02120     : vector_temporary_traits< M > {} ;
02121     template <class M, class TRI>
02122     struct vector_temporary_traits< const symmetric_adaptor<M, TRI> >
02123     : vector_temporary_traits< M > {} ;
02124 
02125     template <class M, class TRI>
02126     struct matrix_temporary_traits< symmetric_adaptor<M, TRI> >
02127     : matrix_temporary_traits< M > {} ;
02128     template <class M, class TRI>
02129     struct matrix_temporary_traits< const symmetric_adaptor<M, TRI> >
02130     : matrix_temporary_traits< M > {} ;
02131 
02132 }}}
02133 
02134 #endif