ublas: symmetric.hpp Source File

- Main Page
- Related Pages
- Classes
- Files

- File List

# symmetric.hpp

    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