Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:18

0001 //
0002 //  Copyright (c) 2003
0003 //  Gunter Winkler, Joerg Walter
0004 //
0005 //  Distributed under the Boost Software License, Version 1.0. (See
0006 //  accompanying file LICENSE_1_0.txt or copy at
0007 //  http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 //  The authors gratefully acknowledge the support of
0010 //  GeNeSys mbH & Co. KG in producing this work.
0011 //
0012 
0013 #ifndef _BOOST_UBLAS_VECTOR_OF_VECTOR_
0014 #define _BOOST_UBLAS_VECTOR_OF_VECTOR_
0015 
0016 #include <boost/type_traits.hpp>
0017 
0018 #include <boost/numeric/ublas/storage_sparse.hpp>
0019 #include <boost/numeric/ublas/matrix_sparse.hpp>
0020 
0021 // Iterators based on ideas of Jeremy Siek
0022 
0023 namespace boost { namespace numeric { namespace ublas {
0024 
0025     // uBLAS sparse vector based sparse matrix class
0026     // FIXME outer vector can be sparse type but it is completely filled
0027     template<class T, class L, class A>
0028     class generalized_vector_of_vector:
0029         public matrix_container<generalized_vector_of_vector<T, L, A> > {
0030 
0031         typedef T &true_reference;
0032         typedef T *pointer;
0033         typedef const T *const_pointer;
0034         typedef L layout_type;
0035         typedef generalized_vector_of_vector<T, L, A> self_type;
0036     public:
0037 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
0038         using matrix_container<self_type>::operator ();
0039 #endif
0040         typedef typename A::size_type size_type;
0041         typedef typename A::difference_type difference_type;
0042         typedef T value_type;
0043         typedef const T &const_reference;
0044 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
0045         typedef T &reference;
0046 #else
0047         typedef sparse_matrix_element<self_type> reference;
0048 #endif
0049         typedef A array_type;
0050         typedef const matrix_reference<const self_type> const_closure_type;
0051         typedef matrix_reference<self_type> closure_type;
0052         typedef typename A::value_type vector_data_value_type;
0053         typedef vector_data_value_type vector_temporary_type;
0054         typedef self_type matrix_temporary_type;
0055         typedef sparse_tag storage_category;
0056         typedef typename L::orientation_category orientation_category;
0057 
0058         // Construction and destruction
0059         BOOST_UBLAS_INLINE
0060         generalized_vector_of_vector ():
0061             matrix_container<self_type> (),
0062             size1_ (0), size2_ (0), data_ (1) {
0063             const size_type sizeM = layout_type::size_M (size1_, size2_);
0064              // create size1+1 empty vector elements
0065             data_.insert_element (sizeM, vector_data_value_type ());
0066             storage_invariants ();
0067         }
0068         BOOST_UBLAS_INLINE
0069                 generalized_vector_of_vector (size_type size1, size_type size2, size_type /*non_zeros = 0*/):
0070             matrix_container<self_type> (),
0071             size1_ (size1), size2_ (size2), data_ (layout_type::size_M (size1_, size2_) + 1) {
0072             const size_type sizeM = layout_type::size_M (size1_, size2_);
0073             const size_type sizem = layout_type::size_m (size1_, size2_);
0074             for (size_type i = 0; i < sizeM; ++ i) // create size1 vector elements
0075                 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
0076             data_.insert_element (sizeM, vector_data_value_type ());
0077             storage_invariants ();
0078         }
0079         BOOST_UBLAS_INLINE
0080         generalized_vector_of_vector (const generalized_vector_of_vector &m):
0081             matrix_container<self_type> (),
0082             size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {
0083             storage_invariants ();
0084         }
0085         template<class AE>
0086         BOOST_UBLAS_INLINE
0087                 generalized_vector_of_vector (const matrix_expression<AE> &ae, size_type /*non_zeros = 0*/):
0088             matrix_container<self_type> (),
0089             size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size_M (size1_, size2_) + 1) {
0090             const size_type sizeM = layout_type::size_M (size1_, size2_);
0091             const size_type sizem = layout_type::size_m (size1_, size2_);
0092             for (size_type i = 0; i < sizeM; ++ i) // create size1 vector elements
0093                 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
0094             data_.insert_element (sizeM, vector_data_value_type ());
0095             storage_invariants ();
0096             matrix_assign<scalar_assign> (*this, ae);
0097         }
0098 
0099         // Accessors
0100         BOOST_UBLAS_INLINE
0101         size_type size1 () const {
0102             return size1_;
0103         }
0104         BOOST_UBLAS_INLINE
0105         size_type size2 () const {
0106             return size2_;
0107         }
0108         BOOST_UBLAS_INLINE
0109         size_type nnz_capacity () const {
0110             size_type non_zeros = 0;
0111             for (const_vectoriterator_type itv = data_.begin (); itv != data_.end (); ++ itv)
0112                 non_zeros += (*itv).nnz_capacity ();
0113             return non_zeros;
0114         }
0115         BOOST_UBLAS_INLINE
0116         size_type nnz () const {
0117             size_type non_zeros = 0;
0118             for (const_vectoriterator_type itv = data_.begin (); itv != data_.end (); ++ itv)
0119                 non_zeros += (*itv).nnz ();
0120             return non_zeros;
0121         }
0122 
0123         // Storage accessors
0124         BOOST_UBLAS_INLINE
0125         const array_type &data () const {
0126             return data_;
0127         }
0128         BOOST_UBLAS_INLINE
0129         array_type &data () {
0130             return data_;
0131         }
0132 
0133         // Resizing
0134         BOOST_UBLAS_INLINE
0135         void resize (size_type size1, size_type size2, bool preserve = true) {
0136             const size_type oldM = layout_type::size_M (size1_, size2_);
0137             size1_ = size1;
0138             size2_ = size2;
0139             const size_type sizeM = layout_type::size_M (size1_, size2_);
0140             const size_type sizem = layout_type::size_m (size1_, size2_);
0141             data ().resize (sizeM + 1, preserve);
0142             if (preserve) {
0143                 for (size_type i = 0; (i <= oldM) && (i < sizeM); ++ i)
0144                     ref (data () [i]).resize (sizem, preserve);
0145                 for (size_type i = oldM+1; i < sizeM; ++ i) // create new vector elements
0146                     data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
0147                 if (sizeM > oldM) {
0148                     data_.insert_element (sizeM, vector_data_value_type ());
0149                 } else {
0150                     ref (data () [sizeM]).resize (0, false);
0151                 }
0152             } else {
0153                 for (size_type i = 0; i < sizeM; ++ i) 
0154                     data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
0155                 data_.insert_element (sizeM, vector_data_value_type ());
0156             }
0157             storage_invariants ();
0158         }
0159 
0160         // Element support
0161         BOOST_UBLAS_INLINE
0162         pointer find_element (size_type i, size_type j) {
0163             return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
0164         }
0165         BOOST_UBLAS_INLINE
0166         const_pointer find_element (size_type i, size_type j) const {
0167             const size_type elementM = layout_type::index_M (i, j);
0168             const size_type elementm = layout_type::index_m (i, j);
0169             // optimise: check the storage_type and index directly if element always exists
0170             if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) {
0171                 return & (data () [elementM] [elementm]);
0172             }
0173             else {
0174                 const typename array_type::value_type *pv = data ().find_element (elementM);
0175                 if (!pv)
0176                     return 0;
0177                 return pv->find_element (elementm);
0178             }
0179         }
0180 
0181         // Element access
0182         BOOST_UBLAS_INLINE
0183         const_reference operator () (size_type i, size_type j) const {
0184             const_pointer p = find_element (i, j);
0185             // optimise: check the storage_type and index directly if element always exists
0186             if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) {
0187                 BOOST_UBLAS_CHECK (p, internal_logic () );
0188                 return *p;
0189             }
0190             else {
0191                 if (p)
0192                     return *p;
0193                 else
0194                     return zero_;
0195             }
0196         }
0197         BOOST_UBLAS_INLINE
0198         reference operator () (size_type i, size_type j) {
0199 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
0200             return at_element (i, j);
0201 #else
0202             return reference (*this, i, j);
0203 #endif
0204         }
0205 
0206         // Assignment
0207         BOOST_UBLAS_INLINE
0208         generalized_vector_of_vector &operator = (const generalized_vector_of_vector &m) {
0209             if (this != &m) {
0210                 size1_ = m.size1_;
0211                 size2_ = m.size2_;
0212                 data () = m.data ();
0213             }
0214             storage_invariants ();
0215             return *this;
0216         }
0217         BOOST_UBLAS_INLINE
0218         generalized_vector_of_vector &assign_temporary (generalized_vector_of_vector &m) {
0219             swap (m);
0220             return *this;
0221         }
0222         template<class AE>
0223         BOOST_UBLAS_INLINE
0224         generalized_vector_of_vector &operator = (const matrix_expression<AE> &ae) {
0225             self_type temporary (ae);
0226             return assign_temporary (temporary);
0227         }
0228         template<class AE>
0229         BOOST_UBLAS_INLINE
0230         generalized_vector_of_vector &assign (const matrix_expression<AE> &ae) {
0231             matrix_assign<scalar_assign> (*this, ae);
0232             return *this;
0233         }
0234         template<class AE>
0235         BOOST_UBLAS_INLINE
0236         generalized_vector_of_vector& operator += (const matrix_expression<AE> &ae) {
0237             self_type temporary (*this + ae);
0238             return assign_temporary (temporary);
0239         }
0240         template<class AE>
0241         BOOST_UBLAS_INLINE
0242         generalized_vector_of_vector &plus_assign (const matrix_expression<AE> &ae) { 
0243             matrix_assign<scalar_plus_assign> (*this, ae);
0244             return *this;
0245         }
0246         template<class AE>
0247         BOOST_UBLAS_INLINE
0248         generalized_vector_of_vector& operator -= (const matrix_expression<AE> &ae) {
0249             self_type temporary (*this - ae);
0250             return assign_temporary (temporary);
0251         }
0252         template<class AE>
0253         BOOST_UBLAS_INLINE
0254         generalized_vector_of_vector &minus_assign (const matrix_expression<AE> &ae) {
0255             matrix_assign<scalar_minus_assign> (*this, ae);
0256             return *this;
0257         }
0258         template<class AT>
0259         BOOST_UBLAS_INLINE
0260         generalized_vector_of_vector& operator *= (const AT &at) {
0261             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
0262             return *this;
0263         }
0264         template<class AT>
0265         BOOST_UBLAS_INLINE
0266         generalized_vector_of_vector& operator /= (const AT &at) {
0267             matrix_assign_scalar<scalar_divides_assign> (*this, at);
0268             return *this;
0269         }
0270 
0271         // Swapping
0272         BOOST_UBLAS_INLINE
0273         void swap (generalized_vector_of_vector &m) {
0274             if (this != &m) {
0275                 std::swap (size1_, m.size1_);
0276                 std::swap (size2_, m.size2_);
0277                 data ().swap (m.data ());
0278             }
0279             storage_invariants ();
0280         }
0281         BOOST_UBLAS_INLINE
0282         friend void swap (generalized_vector_of_vector &m1, generalized_vector_of_vector &m2) {
0283             m1.swap (m2);
0284         }
0285 
0286         // Sorting
0287         void sort () {
0288             vectoriterator_type itv (data ().begin ());
0289             vectoriterator_type itv_end (data ().end ());
0290             while (itv != itv_end) {
0291                 (*itv).sort ();
0292                 ++ itv;
0293             }
0294         }
0295 
0296         // Element insertion and erasure
0297         BOOST_UBLAS_INLINE
0298         true_reference insert_element (size_type i, size_type j, const_reference t) {
0299             const size_type elementM = layout_type::index_M (i, j);
0300             const size_type elementm = layout_type::index_m (i, j);
0301             vector_data_value_type& vd (ref (data () [elementM]));
0302             storage_invariants ();
0303             return vd.insert_element (elementm, t);
0304         }
0305         BOOST_UBLAS_INLINE
0306         void append_element (size_type i, size_type j, const_reference t) {
0307             const size_type elementM = layout_type::index_M (i, j);
0308             const size_type elementm = layout_type::index_m (i, j);
0309             vector_data_value_type& vd (ref (data () [elementM]));
0310             storage_invariants ();
0311             return vd.append_element (elementm, t);
0312         }
0313         BOOST_UBLAS_INLINE
0314         void erase_element (size_type i, size_type j) {
0315             vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
0316             if (itv == data ().end ())
0317                 return;
0318             (*itv).erase_element (layout_type::index_m (i, j));
0319             storage_invariants ();
0320         }
0321         BOOST_UBLAS_INLINE
0322         void clear () {
0323             const size_type sizeM = layout_type::size_M (size1_, size2_);
0324             // FIXME should clear data () if this is done via value_type/*zero*/() then it is not size preserving
0325             for (size_type i = 0; i < sizeM; ++ i)
0326                 ref (data () [i]).clear ();
0327             storage_invariants ();
0328         }
0329 
0330         // Iterator types
0331     private:
0332         // Use vector iterator
0333         typedef typename A::const_iterator const_vectoriterator_type;
0334         typedef typename A::iterator vectoriterator_type;
0335         typedef typename A::value_type::const_iterator const_subiterator_type;
0336         typedef typename A::value_type::iterator subiterator_type;
0337 
0338         BOOST_UBLAS_INLINE
0339         true_reference at_element (size_type i, size_type j) {
0340             return ref (ref (data () [layout_type::index_M (i, j)]) [layout_type::index_m (i, j)]);
0341         }
0342 
0343     public:
0344         class const_iterator1;
0345         class iterator1;
0346         class const_iterator2;
0347         class iterator2;
0348         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
0349         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
0350         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
0351         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
0352 
0353         // Element lookup
0354         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
0355         const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
0356             for (;;) {
0357                 const_vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
0358                 const_vectoriterator_type itv_end (data ().end ());
0359                 if (itv == itv_end)
0360                     return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
0361 
0362                 const_subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
0363                 const_subiterator_type it_end ((*itv).end ());
0364                 if (rank == 0)
0365                     return const_iterator1 (*this, rank, i, j, itv, it);
0366                 if (it != it_end && it.index () == layout_type::index_m (i, j))
0367                     return const_iterator1 (*this, rank, i, j, itv, it);
0368                 if (direction > 0) {
0369                     if (layout_type::fast_i ()) {
0370                         if (it == it_end)
0371                             return const_iterator1 (*this, rank, i, j, itv, it);
0372                         i = it.index ();
0373                     } else {
0374                         if (i >= size1_)
0375                             return const_iterator1 (*this, rank, i, j, itv, it);
0376                         ++ i;
0377                     }
0378                 } else /* if (direction < 0)  */ {
0379                     if (layout_type::fast_i ()) {
0380                         if (it == (*itv).begin ())
0381                             return const_iterator1 (*this, rank, i, j, itv, it);
0382                         --it;
0383                         i = it.index ();
0384                     } else {
0385                         if (i == 0)
0386                             return const_iterator1 (*this, rank, i, j, itv, it);
0387                         -- i;
0388                     }
0389                 }
0390             }
0391         }
0392         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
0393         iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
0394             for (;;) {
0395                 vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
0396                 vectoriterator_type itv_end (data ().end ());
0397                 if (itv == itv_end)
0398                     return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
0399 
0400                 subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
0401                 subiterator_type it_end ((*itv).end ());
0402                 if (rank == 0)
0403                     return iterator1 (*this, rank, i, j, itv, it);
0404                 if (it != it_end && it.index () == layout_type::index_m (i, j))
0405                     return iterator1 (*this, rank, i, j, itv, it);
0406                 if (direction > 0) {
0407                     if (layout_type::fast_i ()) {
0408                         if (it == it_end)
0409                             return iterator1 (*this, rank, i, j, itv, it);
0410                         i = it.index ();
0411                     } else {
0412                         if (i >= size1_)
0413                             return iterator1 (*this, rank, i, j, itv, it);
0414                         ++ i;
0415                     }
0416                 } else /* if (direction < 0)  */ {
0417                     if (layout_type::fast_i ()) {
0418                         if (it == (*itv).begin ())
0419                             return iterator1 (*this, rank, i, j, itv, it);
0420                         --it;
0421                         i = it.index ();
0422                     } else {
0423                         if (i == 0)
0424                             return iterator1 (*this, rank, i, j, itv, it);
0425                         -- i;
0426                     }
0427                 }
0428             }
0429         }
0430         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
0431         const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
0432             for (;;) {
0433                 const_vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
0434                 const_vectoriterator_type itv_end (data ().end ());
0435                 if (itv == itv_end)
0436                     return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
0437 
0438                 const_subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
0439                 const_subiterator_type it_end ((*itv).end ());
0440                 if (rank == 0)
0441                     return const_iterator2 (*this, rank, i, j, itv, it);
0442                 if (it != it_end && it.index () == layout_type::index_m (i, j))
0443                     return const_iterator2 (*this, rank, i, j, itv, it);
0444                 if (direction > 0) {
0445                     if (layout_type::fast_j ()) {
0446                         if (it == it_end)
0447                             return const_iterator2 (*this, rank, i, j, itv, it);
0448                         j = it.index ();
0449                     } else {
0450                         if (j >= size2_)
0451                             return const_iterator2 (*this, rank, i, j, itv, it);
0452                         ++ j;
0453                     }
0454                 } else /* if (direction < 0)  */ {
0455                     if (layout_type::fast_j ()) {
0456                         if (it == (*itv).begin ())
0457                             return const_iterator2 (*this, rank, i, j, itv, it);
0458                         --it;
0459                         j = it.index ();
0460                     } else {
0461                         if (j == 0)
0462                             return const_iterator2 (*this, rank, i, j, itv, it);
0463                         -- j;
0464                     }
0465                 }
0466             }
0467         }
0468         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.    
0469         iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
0470             for (;;) {
0471                 vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
0472                 vectoriterator_type itv_end (data ().end ());
0473                 if (itv == itv_end)
0474                     return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
0475 
0476                 subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
0477                 subiterator_type it_end ((*itv).end ());
0478                 if (rank == 0)
0479                     return iterator2 (*this, rank, i, j, itv, it);
0480                 if (it != it_end && it.index () == layout_type::index_m (i, j))
0481                     return iterator2 (*this, rank, i, j, itv, it);
0482                 if (direction > 0) {
0483                     if (layout_type::fast_j ()) {
0484                         if (it == it_end)
0485                             return iterator2 (*this, rank, i, j, itv, it);
0486                         j = it.index ();
0487                     } else {
0488                         if (j >= size2_)
0489                             return iterator2 (*this, rank, i, j, itv, it);
0490                         ++ j;
0491                     }
0492                 } else /* if (direction < 0)  */ {
0493                     if (layout_type::fast_j ()) {
0494                         if (it == (*itv).begin ())
0495                             return iterator2 (*this, rank, i, j, itv, it);
0496                         --it;
0497                         j = it.index ();
0498                     } else {
0499                         if (j == 0)
0500                             return iterator2 (*this, rank, i, j, itv, it);
0501                         -- j;
0502                     }
0503                 }
0504             }
0505         }
0506 
0507 
0508         class const_iterator1:
0509             public container_const_reference<generalized_vector_of_vector>,
0510             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
0511                                                const_iterator1, value_type> {
0512         public:
0513             typedef typename generalized_vector_of_vector::difference_type difference_type;
0514             typedef typename generalized_vector_of_vector::value_type value_type;
0515             typedef typename generalized_vector_of_vector::const_reference reference;
0516             typedef const typename generalized_vector_of_vector::pointer pointer;
0517 
0518             typedef const_iterator2 dual_iterator_type;
0519             typedef const_reverse_iterator2 dual_reverse_iterator_type;
0520 
0521             // Construction and destruction
0522             BOOST_UBLAS_INLINE
0523             const_iterator1 ():
0524                 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
0525             BOOST_UBLAS_INLINE
0526             const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it):
0527                 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
0528             BOOST_UBLAS_INLINE
0529             const_iterator1 (const iterator1 &it):
0530                 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
0531 
0532             // Arithmetic
0533             BOOST_UBLAS_INLINE
0534             const_iterator1 &operator ++ () {
0535                 if (rank_ == 1 && layout_type::fast_i ())
0536                     ++ it_;
0537                 else {
0538                     const self_type &m = (*this) ();
0539                     i_ = index1 () + 1;
0540                     if (rank_ == 1 && ++ itv_ == m.end1 ().itv_) 
0541                         *this = m.find1 (rank_, i_, j_, 1);
0542                     else if (rank_ == 1) {
0543                         it_ = (*itv_).begin ();
0544                         if (it_ == (*itv_).end () || index2 () != j_)
0545                             *this = m.find1 (rank_, i_, j_, 1);
0546                     }
0547                 }
0548                 return *this;
0549             }
0550             BOOST_UBLAS_INLINE
0551             const_iterator1 &operator -- () {
0552                 if (rank_ == 1 && layout_type::fast_i ())
0553                     -- it_;
0554                 else {
0555                     const self_type &m = (*this) ();
0556                     i_ = index1 () - 1;
0557                     if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
0558                         *this = m.find1 (rank_, i_, j_, -1);
0559                     else if (rank_ == 1) {
0560                         it_ = (*itv_).begin ();
0561                         if (it_ == (*itv_).end () || index2 () != j_)
0562                             *this = m.find1 (rank_, i_, j_, -1);
0563                     } 
0564                 }
0565                 return *this;
0566             }
0567 
0568             // Dereference
0569             BOOST_UBLAS_INLINE
0570             const_reference operator * () const {
0571                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
0572                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
0573                 if (rank_ == 1) {
0574                     return *it_;
0575                 } else {
0576                     return (*this) () (i_, j_);
0577                 }
0578             }
0579 
0580 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0581             BOOST_UBLAS_INLINE
0582 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0583             typename self_type::
0584 #endif
0585             const_iterator2 begin () const {
0586                 const self_type &m = (*this) ();
0587                 return m.find2 (1, index1 (), 0);
0588             }
0589             BOOST_UBLAS_INLINE
0590 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0591             typename self_type::
0592 #endif
0593             const_iterator2 cbegin () const {
0594                 return begin ();
0595             }
0596             BOOST_UBLAS_INLINE
0597 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0598             typename self_type::
0599 #endif
0600             const_iterator2 end () const {
0601                 const self_type &m = (*this) ();
0602                 return m.find2 (1, index1 (), m.size2 ());
0603             }
0604             BOOST_UBLAS_INLINE
0605 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0606             typename self_type::
0607 #endif
0608             const_iterator2 cend () const {
0609                 return end ();
0610             }
0611 
0612             BOOST_UBLAS_INLINE
0613 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0614             typename self_type::
0615 #endif
0616             const_reverse_iterator2 rbegin () const {
0617                 return const_reverse_iterator2 (end ());
0618             }
0619             BOOST_UBLAS_INLINE
0620 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0621             typename self_type::
0622 #endif
0623             const_reverse_iterator2 crbegin () const {
0624                 return rbegin ();
0625             }
0626             BOOST_UBLAS_INLINE
0627 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0628             typename self_type::
0629 #endif
0630             const_reverse_iterator2 rend () const {
0631                 return const_reverse_iterator2 (begin ());
0632             }
0633             BOOST_UBLAS_INLINE
0634 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0635             typename self_type::
0636 #endif
0637             const_reverse_iterator2 crend () const {
0638                 return rend ();
0639             }
0640 #endif
0641 
0642             // Indices
0643             BOOST_UBLAS_INLINE
0644             size_type index1 () const {
0645                 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
0646                 if (rank_ == 1) {
0647                     BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
0648                     return layout_type::index_M (itv_.index (), it_.index ());
0649                 } else {
0650                     return i_;
0651                 }
0652             }
0653             BOOST_UBLAS_INLINE
0654             size_type index2 () const {
0655                 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
0656                 if (rank_ == 1) {
0657                     BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
0658                     return layout_type::index_m (itv_.index (), it_.index ());
0659                 } else {
0660                     return j_;
0661                 }
0662             }
0663 
0664             // Assignment
0665             BOOST_UBLAS_INLINE
0666             const_iterator1 &operator = (const const_iterator1 &it) {
0667                 container_const_reference<self_type>::assign (&it ());
0668                 rank_ = it.rank_;
0669                 i_ = it.i_;
0670                 j_ = it.j_;
0671                 itv_ = it.itv_;
0672                 it_ = it.it_;
0673                 return *this;
0674             }
0675 
0676             // Comparison
0677             BOOST_UBLAS_INLINE
0678             bool operator == (const const_iterator1 &it) const {
0679                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0680                 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
0681                 if (rank_ == 1 || it.rank_ == 1) {
0682                     return it_ == it.it_;
0683                 } else {
0684                     return i_ == it.i_ && j_ == it.j_;
0685                 }
0686             }
0687 
0688         private:
0689             int rank_;
0690             size_type i_;
0691             size_type j_;
0692             const_vectoriterator_type itv_;
0693             const_subiterator_type it_;
0694         };
0695 
0696         BOOST_UBLAS_INLINE
0697         const_iterator1 begin1 () const {
0698             return find1 (0, 0, 0);
0699         }
0700         BOOST_UBLAS_INLINE
0701         const_iterator1 cbegin1 () const {
0702             return begin1 ();
0703         }
0704         BOOST_UBLAS_INLINE
0705         const_iterator1 end1 () const {
0706             return find1 (0, size1_, 0);
0707         }
0708         BOOST_UBLAS_INLINE
0709         const_iterator1 cend1 () const {
0710             return end1 ();
0711         }
0712 
0713         class iterator1:
0714             public container_reference<generalized_vector_of_vector>,
0715             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
0716                                                iterator1, value_type> {
0717         public:
0718             typedef typename generalized_vector_of_vector::difference_type difference_type;
0719             typedef typename generalized_vector_of_vector::value_type value_type;
0720             typedef typename generalized_vector_of_vector::true_reference reference;
0721             typedef typename generalized_vector_of_vector::pointer pointer;
0722 
0723             typedef iterator2 dual_iterator_type;
0724             typedef reverse_iterator2 dual_reverse_iterator_type;
0725 
0726             // Construction and destruction
0727             BOOST_UBLAS_INLINE
0728             iterator1 ():
0729                 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
0730             BOOST_UBLAS_INLINE
0731             iterator1 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it):
0732                 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
0733 
0734             // Arithmetic
0735             BOOST_UBLAS_INLINE
0736             iterator1 &operator ++ () {
0737                 if (rank_ == 1 && layout_type::fast_i ())
0738                     ++ it_;
0739                 else {
0740                     self_type &m = (*this) ();
0741                     i_ = index1 () + 1;
0742                     if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
0743                         *this = m.find1 (rank_, i_, j_, 1);
0744                     else if (rank_ == 1) {
0745                         it_ = (*itv_).begin ();
0746                         if (it_ == (*itv_).end () || index2 () != j_)
0747                             *this = m.find1 (rank_, i_, j_, 1);
0748                     }
0749                 }
0750                 return *this;
0751             }
0752             BOOST_UBLAS_INLINE
0753             iterator1 &operator -- () {
0754                 if (rank_ == 1 && layout_type::fast_i ())
0755                     -- it_;
0756                 else {
0757                     self_type &m = (*this) ();
0758                     i_ = index1 () - 1;
0759                     if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
0760                         *this = m.find1 (rank_, i_, j_, -1);
0761                     else if (rank_ == 1) {
0762                         it_ = (*itv_).begin ();
0763                         if (it_ == (*itv_).end () || index2 () != j_)
0764                             *this = m.find1 (rank_, i_, j_, -1);
0765                     }
0766                 }
0767                 return *this;
0768             }
0769 
0770             // Dereference
0771             BOOST_UBLAS_INLINE
0772             true_reference operator * () const {
0773                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
0774                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
0775                 if (rank_ == 1) {
0776                     return *it_;
0777                 } else {
0778                     return (*this) ().at_element (i_, j_);
0779                 }
0780             }
0781 
0782 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0783             BOOST_UBLAS_INLINE
0784 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0785             typename self_type::
0786 #endif
0787             iterator2 begin () const {
0788                 self_type &m = (*this) ();
0789                 return m.find2 (1, index1 (), 0);
0790             }
0791             BOOST_UBLAS_INLINE
0792 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0793             typename self_type::
0794 #endif
0795             iterator2 end () const {
0796                 self_type &m = (*this) ();
0797                 return m.find2 (1, index1 (), m.size2 ());
0798             }
0799             BOOST_UBLAS_INLINE
0800 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0801             typename self_type::
0802 #endif
0803             reverse_iterator2 rbegin () const {
0804                 return reverse_iterator2 (end ());
0805             }
0806             BOOST_UBLAS_INLINE
0807 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0808             typename self_type::
0809 #endif
0810             reverse_iterator2 rend () const {
0811                 return reverse_iterator2 (begin ());
0812             }
0813 #endif
0814 
0815             // Indices
0816             BOOST_UBLAS_INLINE
0817             size_type index1 () const {
0818                 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
0819                 if (rank_ == 1) {
0820                     BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
0821                     return layout_type::index_M (itv_.index (), it_.index ());
0822                 } else {
0823                     return i_;
0824                 }
0825             }
0826             BOOST_UBLAS_INLINE
0827             size_type index2 () const {
0828                 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
0829                 if (rank_ == 1) {
0830                     BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
0831                     return layout_type::index_m (itv_.index (), it_.index ());
0832                 } else {
0833                     return j_;
0834                 }
0835             }
0836 
0837             // Assignment 
0838             BOOST_UBLAS_INLINE
0839             iterator1 &operator = (const iterator1 &it) {
0840                 container_reference<self_type>::assign (&it ());
0841                 rank_ = it.rank_;
0842                 i_ = it.i_;
0843                 j_ = it.j_;
0844                 itv_ = it.itv_;
0845                 it_ = it.it_;
0846                 return *this;
0847             }
0848 
0849             // Comparison
0850             BOOST_UBLAS_INLINE
0851             bool operator == (const iterator1 &it) const {
0852                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
0853                 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
0854                 if (rank_ == 1 || it.rank_ == 1) {
0855                     return it_ == it.it_;
0856                 } else {
0857                     return i_ == it.i_ && j_ == it.j_;
0858                 }
0859             }
0860 
0861         private:
0862             int rank_;
0863             size_type i_;
0864             size_type j_;
0865             vectoriterator_type itv_;
0866             subiterator_type it_;
0867             
0868             friend class const_iterator1;
0869         };
0870 
0871         BOOST_UBLAS_INLINE
0872         iterator1 begin1 () {
0873             return find1 (0, 0, 0);
0874         }
0875         BOOST_UBLAS_INLINE
0876         iterator1 end1 () {
0877             return find1 (0, size1_, 0);
0878         }
0879 
0880         class const_iterator2:
0881             public container_const_reference<generalized_vector_of_vector>,
0882             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
0883                                                const_iterator2, value_type> {
0884         public:
0885             typedef typename generalized_vector_of_vector::difference_type difference_type;
0886             typedef typename generalized_vector_of_vector::value_type value_type;
0887             typedef typename generalized_vector_of_vector::const_reference reference;
0888             typedef const typename generalized_vector_of_vector::pointer pointer;
0889 
0890             typedef const_iterator1 dual_iterator_type;
0891             typedef const_reverse_iterator1 dual_reverse_iterator_type;
0892 
0893             // Construction and destruction
0894             BOOST_UBLAS_INLINE
0895             const_iterator2 ():
0896                 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
0897             BOOST_UBLAS_INLINE
0898             const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it):
0899                 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
0900             BOOST_UBLAS_INLINE
0901             const_iterator2 (const iterator2 &it):
0902                 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
0903 
0904             // Arithmetic
0905             BOOST_UBLAS_INLINE
0906             const_iterator2 &operator ++ () {
0907                 if (rank_ == 1 && layout_type::fast_j ())
0908                     ++ it_;
0909                 else {
0910                     const self_type &m = (*this) ();
0911                     j_ = index2 () + 1;
0912                     if (rank_ == 1 && ++ itv_ == m.end2 ().itv_) 
0913                         *this = m.find2 (rank_, i_, j_, 1);
0914                     else if (rank_ == 1) {
0915                         it_ = (*itv_).begin ();
0916                         if (it_ == (*itv_).end () || index1 () != i_)
0917                             *this = m.find2 (rank_, i_, j_, 1);
0918                     }
0919                 }
0920                 return *this;
0921             }
0922             BOOST_UBLAS_INLINE
0923             const_iterator2 &operator -- () {
0924                 if (rank_ == 1 && layout_type::fast_j ())
0925                     -- it_;
0926                 else {
0927                     const self_type &m = (*this) ();
0928                     j_ = index2 () - 1;
0929                     if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
0930                         *this = m.find2 (rank_, i_, j_, -1);
0931                     else if (rank_ == 1) {
0932                         it_ = (*itv_).begin ();
0933                         if (it_ == (*itv_).end () || index1 () != i_)
0934                             *this = m.find2 (rank_, i_, j_, -1);
0935                     }
0936                 }
0937                 return *this;
0938             }
0939 
0940             // Dereference
0941             BOOST_UBLAS_INLINE
0942             const_reference operator * () const {
0943                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
0944                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
0945                 if (rank_ == 1) {
0946                     return *it_;
0947                 } else {
0948                     return (*this) () (i_, j_);
0949                 }
0950             }
0951 
0952 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
0953             BOOST_UBLAS_INLINE
0954 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0955             typename self_type::
0956 #endif
0957             const_iterator1 begin () const {
0958                 const self_type &m = (*this) ();
0959                 return m.find1 (1, 0, index2 ());
0960             }
0961             BOOST_UBLAS_INLINE
0962 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0963             typename self_type::
0964 #endif
0965             const_iterator1 cbegin () const {
0966                 return begin ();
0967             }
0968             BOOST_UBLAS_INLINE
0969 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0970             typename self_type::
0971 #endif
0972             const_iterator1 end () const {
0973                 const self_type &m = (*this) ();
0974                 return m.find1 (1, m.size1 (), index2 ());
0975             }
0976             BOOST_UBLAS_INLINE
0977 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0978             typename self_type::
0979 #endif
0980             const_iterator1 cend () const {
0981                 return end ();
0982             }
0983             BOOST_UBLAS_INLINE
0984 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0985             typename self_type::
0986 #endif
0987             const_reverse_iterator1 rbegin () const {
0988                 return const_reverse_iterator1 (end ());
0989             }
0990             BOOST_UBLAS_INLINE
0991 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0992             typename self_type::
0993 #endif
0994             const_reverse_iterator1 crbegin () const {
0995                 return rbegin ();
0996             }
0997             BOOST_UBLAS_INLINE
0998 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
0999             typename self_type::
1000 #endif
1001             const_reverse_iterator1 rend () const {
1002                 return const_reverse_iterator1 (begin ());
1003             }
1004             BOOST_UBLAS_INLINE
1005 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1006             typename self_type::
1007 #endif
1008             const_reverse_iterator1 crend () const {
1009                 return rend ();
1010             }
1011 #endif
1012 
1013             // Indices
1014             BOOST_UBLAS_INLINE
1015             size_type index1 () const {
1016                 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
1017                 if (rank_ == 1) {
1018                     BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
1019                     return layout_type::index_M (itv_.index (), it_.index ());
1020                 } else {
1021                     return i_;
1022                 }
1023             }
1024             BOOST_UBLAS_INLINE
1025             size_type index2 () const {
1026                 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
1027                 if (rank_ == 1) {
1028                     BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
1029                     return layout_type::index_m (itv_.index (), it_.index ());
1030                 } else {
1031                     return j_;
1032                 }
1033             }
1034 
1035             // Assignment 
1036             BOOST_UBLAS_INLINE
1037             const_iterator2 &operator = (const const_iterator2 &it) {
1038                 container_const_reference<self_type>::assign (&it ());
1039                 rank_ = it.rank_;
1040                 i_ = it.i_;
1041                 j_ = it.j_;
1042                 itv_ = it.itv_;
1043                 it_ = it.it_;
1044                 return *this;
1045             }
1046 
1047             // Comparison
1048             BOOST_UBLAS_INLINE
1049             bool operator == (const const_iterator2 &it) const {
1050                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1051                 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
1052                 if (rank_ == 1 || it.rank_ == 1) {
1053                     return it_ == it.it_;
1054                 } else {
1055                     return i_ == it.i_ && j_ == it.j_;
1056                 }
1057             }
1058 
1059         private:
1060             int rank_;
1061             size_type i_;
1062             size_type j_;
1063             const_vectoriterator_type itv_;
1064             const_subiterator_type it_;
1065         };
1066 
1067         BOOST_UBLAS_INLINE
1068         const_iterator2 begin2 () const {
1069             return find2 (0, 0, 0);
1070         }
1071         BOOST_UBLAS_INLINE
1072         const_iterator2 cbegin2 () const {
1073             return begin2 ();
1074         }
1075         BOOST_UBLAS_INLINE
1076         const_iterator2 end2 () const {
1077             return find2 (0, 0, size2_);
1078         }
1079         BOOST_UBLAS_INLINE
1080         const_iterator2 cend2 () const {
1081             return end2 ();
1082         }
1083 
1084         class iterator2:
1085             public container_reference<generalized_vector_of_vector>,
1086             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
1087                                                iterator2, value_type> {
1088         public:
1089             typedef typename generalized_vector_of_vector::difference_type difference_type;
1090             typedef typename generalized_vector_of_vector::value_type value_type;
1091             typedef typename generalized_vector_of_vector::true_reference reference;
1092             typedef typename generalized_vector_of_vector::pointer pointer;
1093 
1094             typedef iterator1 dual_iterator_type;
1095             typedef reverse_iterator1 dual_reverse_iterator_type;
1096 
1097             // Construction and destruction
1098             BOOST_UBLAS_INLINE
1099             iterator2 ():
1100                 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
1101             BOOST_UBLAS_INLINE
1102             iterator2 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it):
1103                 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
1104 
1105             // Arithmetic
1106             BOOST_UBLAS_INLINE
1107             iterator2 &operator ++ () {
1108                 if (rank_ == 1 && layout_type::fast_j ())
1109                     ++ it_;
1110                 else {
1111                     self_type &m = (*this) ();
1112                     j_ = index2 () + 1;
1113                     if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
1114                         *this = m.find2 (rank_, i_, j_, 1);
1115                     else if (rank_ == 1) {
1116                         it_ = (*itv_).begin ();
1117                         if (it_ == (*itv_).end () || index1 () != i_)
1118                             *this = m.find2 (rank_, i_, j_, 1);
1119                     }
1120                 }
1121                 return *this;
1122             }
1123             BOOST_UBLAS_INLINE
1124             iterator2 &operator -- () {
1125                 if (rank_ == 1 && layout_type::fast_j ())
1126                     -- it_;
1127                 else {
1128                     self_type &m = (*this) ();
1129                     j_ = index2 () - 1;
1130                     if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
1131                         *this = m.find2 (rank_, i_, j_, -1);
1132                     else if (rank_ == 1) {
1133                         it_ = (*itv_).begin ();
1134                         if (it_ == (*itv_).end () || index1 () != i_)
1135                             *this = m.find2 (rank_, i_, j_, -1);
1136                     } 
1137                 }
1138                 return *this;
1139             }
1140 
1141             // Dereference
1142             BOOST_UBLAS_INLINE
1143             true_reference operator * () const {
1144                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1145                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1146                 if (rank_ == 1) {
1147                     return *it_;
1148                 } else {
1149                     return (*this) ().at_element (i_, j_);
1150                 }
1151             }
1152 
1153 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1154             BOOST_UBLAS_INLINE
1155 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1156             typename self_type::
1157 #endif
1158             iterator1 begin () const {
1159                 self_type &m = (*this) ();
1160                 return m.find1 (1, 0, index2 ());
1161             }
1162             BOOST_UBLAS_INLINE
1163 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1164             typename self_type::
1165 #endif
1166             iterator1 end () const {
1167                 self_type &m = (*this) ();
1168                 return m.find1 (1, m.size1 (), index2 ());
1169             }
1170             BOOST_UBLAS_INLINE
1171 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1172             typename self_type::
1173 #endif
1174             reverse_iterator1 rbegin () const {
1175                 return reverse_iterator1 (end ());
1176             }
1177             BOOST_UBLAS_INLINE
1178 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1179             typename self_type::
1180 #endif
1181             reverse_iterator1 rend () const {
1182                 return reverse_iterator1 (begin ());
1183             }
1184 #endif
1185 
1186             // Indices
1187             BOOST_UBLAS_INLINE
1188             size_type index1 () const {
1189                 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
1190                 if (rank_ == 1) {
1191                     BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
1192                     return layout_type::index_M (itv_.index (), it_.index ());
1193                 } else {
1194                     return i_;
1195                 }
1196             }
1197             BOOST_UBLAS_INLINE
1198             size_type index2 () const {
1199                 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
1200                 if (rank_ == 1) {
1201                     BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
1202                     return layout_type::index_m (itv_.index (), it_.index ());
1203                 } else {
1204                     return j_;
1205                 }
1206             }
1207 
1208             // Assignment 
1209             BOOST_UBLAS_INLINE
1210             iterator2 &operator = (const iterator2 &it) {
1211                 container_reference<self_type>::assign (&it ());
1212                 rank_ = it.rank_;
1213                 i_ = it.i_;
1214                 j_ = it.j_;
1215                 itv_ = it.itv_;
1216                 it_ = it.it_;
1217                 return *this;
1218             }
1219 
1220             // Comparison
1221             BOOST_UBLAS_INLINE
1222             bool operator == (const iterator2 &it) const {
1223                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1224                 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
1225                 if (rank_ == 1 || it.rank_ == 1) {
1226                     return it_ == it.it_;
1227                 } else {
1228                     return i_ == it.i_ && j_ == it.j_;
1229                 }
1230             }
1231 
1232         private:
1233             int rank_;
1234             size_type i_;
1235             size_type j_;
1236             vectoriterator_type itv_;
1237             subiterator_type it_;
1238 
1239             friend class const_iterator2;
1240         };
1241 
1242         BOOST_UBLAS_INLINE
1243         iterator2 begin2 () {
1244             return find2 (0, 0, 0);
1245         }
1246         BOOST_UBLAS_INLINE
1247         iterator2 end2 () {
1248             return find2 (0, 0, size2_);
1249         }
1250 
1251         // Reverse iterators
1252 
1253         BOOST_UBLAS_INLINE
1254         const_reverse_iterator1 rbegin1 () const {
1255             return const_reverse_iterator1 (end1 ());
1256         }
1257         BOOST_UBLAS_INLINE
1258         const_reverse_iterator1 crbegin1 () const {
1259             return rbegin1 ();
1260         }
1261         BOOST_UBLAS_INLINE
1262         const_reverse_iterator1 rend1 () const {
1263             return const_reverse_iterator1 (begin1 ());
1264         }
1265         BOOST_UBLAS_INLINE
1266         const_reverse_iterator1 crend1 () const {
1267             return rend1 ();
1268         }
1269 
1270         BOOST_UBLAS_INLINE
1271         reverse_iterator1 rbegin1 () {
1272             return reverse_iterator1 (end1 ());
1273         }
1274         BOOST_UBLAS_INLINE
1275         reverse_iterator1 rend1 () {
1276             return reverse_iterator1 (begin1 ());
1277         }
1278 
1279         BOOST_UBLAS_INLINE
1280         const_reverse_iterator2 rbegin2 () const {
1281             return const_reverse_iterator2 (end2 ());
1282         }
1283         BOOST_UBLAS_INLINE
1284         const_reverse_iterator2 crbegin2 () const {
1285             return rbegin2 ();
1286         }
1287         BOOST_UBLAS_INLINE
1288         const_reverse_iterator2 rend2 () const {
1289             return const_reverse_iterator2 (begin2 ());
1290         }
1291         BOOST_UBLAS_INLINE
1292         const_reverse_iterator2 crend2 () const {
1293             return rend2 ();
1294         }
1295 
1296         BOOST_UBLAS_INLINE
1297         reverse_iterator2 rbegin2 () {
1298             return reverse_iterator2 (end2 ());
1299         }
1300         BOOST_UBLAS_INLINE
1301         reverse_iterator2 rend2 () {
1302             return reverse_iterator2 (begin2 ());
1303         }
1304 
1305          // Serialization
1306         template<class Archive>
1307         void serialize(Archive & ar, const unsigned int /* file_version */){
1308         
1309             // we need to copy to a collection_size_type to get a portable
1310             // and efficient serialization
1311             serialization::collection_size_type s1 (size1_);
1312             serialization::collection_size_type s2 (size2_);
1313           
1314             // serialize the sizes
1315             ar & serialization::make_nvp("size1",s1)
1316                & serialization::make_nvp("size2",s2);
1317 
1318             // copy the values back if loading
1319             if (Archive::is_loading::value) {
1320                 size1_ = s1;
1321                 size2_ = s2;
1322             }
1323 
1324             ar & serialization::make_nvp("data", data_);
1325 
1326             storage_invariants();
1327         }
1328 
1329     private:
1330         void storage_invariants () const
1331         {
1332             BOOST_UBLAS_CHECK (layout_type::size_M (size1_, size2_) + 1 == data_.size (), internal_logic ());
1333             BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
1334 
1335         }
1336         size_type size1_;
1337         size_type size2_;
1338         array_type data_;
1339         static const value_type zero_;
1340     };
1341 
1342     template<class T, class L, class A>
1343     const typename generalized_vector_of_vector<T, L, A>::value_type generalized_vector_of_vector<T, L, A>::zero_ = value_type/*zero*/();
1344 
1345 }}}
1346 
1347 #endif