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

Generated on Wed Oct 15 2014 00:37:23 for Jafar by doxygen 1.7.6.1
LAAS-CNRS