- Main Page
- Related Pages
- Classes
- Files

- File List

# vector_of_vector.hpp

    00001 //
    00002 //  Copyright (c) 2003
    00003 //  Gunter Winkler, Joerg Walter
    00004 //
    00005 //  Distributed under the Boost Software License, Version 1.0. (See
    00006 //  accompanying file LICENSE_1_0.txt or copy at
    00007 //  http://www.boost.org/LICENSE_1_0.txt)
    00008 //
    00009 //  The authors gratefully acknowledge the support of
    00010 //  GeNeSys mbH & Co. KG in producing this work.
    00011 //
    00012
    00013 #ifndef _BOOST_UBLAS_VECTOR_OF_VECTOR_
    00014 #define _BOOST_UBLAS_VECTOR_OF_VECTOR_
    00015
    00016 #include <boost/type_traits.hpp>
    00017
    00018 #include <boost/numeric/ublas/storage_sparse.hpp>
    00019 #include <boost/numeric/ublas/matrix_sparse.hpp>
    00020
    00021 // Iterators based on ideas of Jeremy Siek
    00022
    00023 namespace boost { namespace numeric { namespace ublas {
    00024
    00025     // uBLAS sparse vector based sparse matrix class
    00026     // FIXME outer vector can be sparse type but it is completely filled
    00027     template<class T, class L, class A>
    00028     class generalized_vector_of_vector:
    00029         public matrix_container<generalized_vector_of_vector<T, L, A> > {
    00030
    00031         typedef T &true_reference;
    00032         typedef T *pointer;
    00033         typedef const T *const_pointer;
    00034         typedef L layout_type;
    00035         typedef generalized_vector_of_vector<T, L, A> self_type;
    00036     public:
    00037 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    00038         using matrix_container<self_type>::operator ();
    00039 #endif
    00040         typedef typename A::size_type size_type;
    00041         typedef typename A::difference_type difference_type;
    00042         typedef T value_type;
    00043         typedef const T &const_reference;
    00044 #ifndef BOOST_UBLAS_STRICT_VECTOR_SPARSE
    00045         typedef T &reference;
    00046 #else
    00047         typedef sparse_matrix_element<self_type> reference;
    00048 #endif
    00049         typedef A array_type;
    00050         typedef const matrix_reference<const self_type> const_closure_type;
    00051         typedef matrix_reference<self_type> closure_type;
    00052         typedef typename A::value_type vector_data_value_type;
    00053         typedef vector_data_value_type vector_temporary_type;
    00054         typedef self_type matrix_temporary_type;
    00055         typedef sparse_tag storage_category;
    00056         typedef typename L::orientation_category orientation_category;
    00057
    00058         // Construction and destruction
    00059         BOOST_UBLAS_INLINE
    00060         generalized_vector_of_vector ():
    00061             matrix_container<self_type> (),
    00062             size1_ (0), size2_ (0), data_ (1) {
    00063             const size_type sizeM = layout_type::size_M (size1_, size2_);
    00064              // create size1+1 empty vector elements
    00065             data_.insert_element (sizeM, vector_data_value_type ());
    00066             storage_invariants ();
    00067         }
    00068         BOOST_UBLAS_INLINE
    00069         generalized_vector_of_vector (size_type size1, size_type size2, size_type non_zeros = 0):
    00070             matrix_container<self_type> (),
    00071             size1_ (size1), size2_ (size2), data_ (layout_type::size_M (size1_, size2_) + 1) {
    00072             const size_type sizeM = layout_type::size_M (size1_, size2_);
    00073             const size_type sizem = layout_type::size_m (size1_, size2_);
    00074             for (size_type i = 0; i < sizeM; ++ i) // create size1 vector elements
    00075                 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
    00076             data_.insert_element (sizeM, vector_data_value_type ());
    00077             storage_invariants ();
    00078         }
    00079         BOOST_UBLAS_INLINE
    00080         generalized_vector_of_vector (const generalized_vector_of_vector &m):
    00081             matrix_container<self_type> (),
    00082             size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {
    00083             storage_invariants ();
    00084         }
    00085         template<class AE>
    00086         BOOST_UBLAS_INLINE
    00087         generalized_vector_of_vector (const matrix_expression<AE> &ae, size_type non_zeros = 0):
    00088             matrix_container<self_type> (),
    00089             size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size_M (size1_, size2_) + 1) {
    00090             const size_type sizeM = layout_type::size_M (size1_, size2_);
    00091             const size_type sizem = layout_type::size_m (size1_, size2_);
    00092             for (size_type i = 0; i < sizeM; ++ i) // create size1 vector elements
    00093                 data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
    00094             data_.insert_element (sizeM, vector_data_value_type ());
    00095             storage_invariants ();
    00096             matrix_assign<scalar_assign> (*this, ae);
    00097         }
    00098
    00099         // Accessors
    00100         BOOST_UBLAS_INLINE
    00101         size_type size1 () const {
    00102             return size1_;
    00103         }
    00104         BOOST_UBLAS_INLINE
    00105         size_type size2 () const {
    00106             return size2_;
    00107         }
    00108         BOOST_UBLAS_INLINE
    00109         size_type nnz_capacity () const {
    00110             size_type non_zeros = 0;
    00111             for (const_vectoriterator_type itv = data_.begin (); itv != data_.end (); ++ itv)
    00112                 non_zeros += (*itv).nnz_capacity ();
    00113             return non_zeros;
    00114         }
    00115         BOOST_UBLAS_INLINE
    00116         size_type nnz () const {
    00117             size_type non_zeros = 0;
    00118             for (const_vectoriterator_type itv = data_.begin (); itv != data_.end (); ++ itv)
    00119                 non_zeros += (*itv).nnz ();
    00120             return non_zeros;
    00121         }
    00122
    00123         // Storage accessors
    00124         BOOST_UBLAS_INLINE
    00125         const array_type &data () const {
    00126             return data_;
    00127         }
    00128         BOOST_UBLAS_INLINE
    00129         array_type &data () {
    00130             return data_;
    00131         }
    00132
    00133         // Resizing
    00134         BOOST_UBLAS_INLINE
    00135         void resize (size_type size1, size_type size2, bool preserve = true) {
    00136             const size_type oldM = layout_type::size_M (size1_, size2_);
    00137             size1_ = size1;
    00138             size2_ = size2;
    00139             const size_type sizeM = layout_type::size_M (size1_, size2_);
    00140             const size_type sizem = layout_type::size_m (size1_, size2_);
    00141             data ().resize (sizeM + 1, preserve);
    00142             if (preserve) {
    00143                 for (size_type i = 0; (i <= oldM) && (i < sizeM); ++ i)
    00144                     ref (data () [i]).resize (sizem, preserve);
    00145                 for (size_type i = oldM+1; i < sizeM; ++ i) // create new vector elements
    00146                     data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
    00147                 if (sizeM > oldM) {
    00148                     data_.insert_element (sizeM, vector_data_value_type ());
    00149                 } else {
    00150                     ref (data () [sizeM]).resize (0, false);
    00151                 }
    00152             } else {
    00153                 for (size_type i = 0; i < sizeM; ++ i)
    00154                     data_.insert_element (i, vector_data_value_type ()) .resize (sizem, false);
    00155                 data_.insert_element (sizeM, vector_data_value_type ());
    00156             }
    00157             storage_invariants ();
    00158         }
    00159
    00160         // Element support
    00161         BOOST_UBLAS_INLINE
    00162         pointer find_element (size_type i, size_type j) {
    00163             return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i, j));
    00164         }
    00165         BOOST_UBLAS_INLINE
    00166         const_pointer find_element (size_type i, size_type j) const {
    00167             const size_type elementM = layout_type::index_M (i, j);
    00168             const size_type elementm = layout_type::index_m (i, j);
    00169             // optimise: check the storage_type and index directly if element always exists
    00170             if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) {
    00171                 return & (data () [elementM] [elementm]);
    00172             }
    00173             else {
    00174                 const typename array_type::value_type *pv = data ().find_element (elementM);
    00175                 if (!pv)
    00176                     return 0;
    00177                 return pv->find_element (elementm);
    00178             }
    00179         }
    00180
    00181         // Element access
    00182         BOOST_UBLAS_INLINE
    00183         const_reference operator () (size_type i, size_type j) const {
    00184             const_pointer p = find_element (i, j);
    00185             // optimise: check the storage_type and index directly if element always exists
    00186             if (boost::is_convertible<typename array_type::storage_category, packed_tag>::value) {
    00187                 BOOST_UBLAS_CHECK (p, internal_logic () );
    00188                 return *p;
    00189             }
    00190             else {
    00191                 if (p)
    00192                     return *p;
    00193                 else
    00194                     return zero_;
    00195             }
    00196         }
    00197         BOOST_UBLAS_INLINE
    00198         reference operator () (size_type i, size_type j) {
    00199 #ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
    00200             return at_element (i, j);
    00201 #else
    00202             return reference (*this, i, j);
    00203 #endif
    00204         }
    00205
    00206         // Assignment
    00207         BOOST_UBLAS_INLINE
    00208         generalized_vector_of_vector &operator = (const generalized_vector_of_vector &m) {
    00209             if (this != &m) {
    00210                 size1_ = m.size1_;
    00211                 size2_ = m.size2_;
    00212                 data () = m.data ();
    00213             }
    00214             storage_invariants ();
    00215             return *this;
    00216         }
    00217         BOOST_UBLAS_INLINE
    00218         generalized_vector_of_vector &assign_temporary (generalized_vector_of_vector &m) {
    00219             swap (m);
    00220             return *this;
    00221         }
    00222         template<class AE>
    00223         BOOST_UBLAS_INLINE
    00224         generalized_vector_of_vector &operator = (const matrix_expression<AE> &ae) {
    00225             self_type temporary (ae);
    00226             return assign_temporary (temporary);
    00227         }
    00228         template<class AE>
    00229         BOOST_UBLAS_INLINE
    00230         generalized_vector_of_vector &assign (const matrix_expression<AE> &ae) {
    00231             matrix_assign<scalar_assign> (*this, ae);
    00232             return *this;
    00233         }
    00234         template<class AE>
    00235         BOOST_UBLAS_INLINE
    00236         generalized_vector_of_vector& operator += (const matrix_expression<AE> &ae) {
    00237             self_type temporary (*this + ae);
    00238             return assign_temporary (temporary);
    00239         }
    00240         template<class AE>
    00241         BOOST_UBLAS_INLINE
    00242         generalized_vector_of_vector &plus_assign (const matrix_expression<AE> &ae) {
    00243             matrix_assign<scalar_plus_assign> (*this, ae);
    00244             return *this;
    00245         }
    00246         template<class AE>
    00247         BOOST_UBLAS_INLINE
    00248         generalized_vector_of_vector& operator -= (const matrix_expression<AE> &ae) {
    00249             self_type temporary (*this - ae);
    00250             return assign_temporary (temporary);
    00251         }
    00252         template<class AE>
    00253         BOOST_UBLAS_INLINE
    00254         generalized_vector_of_vector &minus_assign (const matrix_expression<AE> &ae) {
    00255             matrix_assign<scalar_minus_assign> (*this, ae);
    00256             return *this;
    00257         }
    00258         template<class AT>
    00259         BOOST_UBLAS_INLINE
    00260         generalized_vector_of_vector& operator *= (const AT &at) {
    00261             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
    00262             return *this;
    00263         }
    00264         template<class AT>
    00265         BOOST_UBLAS_INLINE
    00266         generalized_vector_of_vector& operator /= (const AT &at) {
    00267             matrix_assign_scalar<scalar_divides_assign> (*this, at);
    00268             return *this;
    00269         }
    00270
    00271         // Swapping
    00272         BOOST_UBLAS_INLINE
    00273         void swap (generalized_vector_of_vector &m) {
    00274             if (this != &m) {
    00275                 std::swap (size1_, m.size1_);
    00276                 std::swap (size2_, m.size2_);
    00277                 data ().swap (m.data ());
    00278             }
    00279             storage_invariants ();
    00280         }
    00281         BOOST_UBLAS_INLINE
    00282         friend void swap (generalized_vector_of_vector &m1, generalized_vector_of_vector &m2) {
    00283             m1.swap (m2);
    00284         }
    00285
    00286         // Sorting
    00287         void sort () {
    00288             vectoriterator_type itv (data ().begin ());
    00289             vectoriterator_type itv_end (data ().end ());
    00290             while (itv != itv_end) {
    00291                 (*itv).sort ();
    00292                 ++ itv;
    00293             }
    00294         }
    00295
    00296         // Element insertion and erasure
    00297         BOOST_UBLAS_INLINE
    00298         true_reference insert_element (size_type i, size_type j, const_reference t) {
    00299             const size_type elementM = layout_type::index_M (i, j);
    00300             const size_type elementm = layout_type::index_m (i, j);
    00301             vector_data_value_type& vd (ref (data () [elementM]));
    00302             storage_invariants ();
    00303             return vd.insert_element (elementm, t);
    00304         }
    00305         BOOST_UBLAS_INLINE
    00306         void append_element (size_type i, size_type j, const_reference t) {
    00307             const size_type elementM = layout_type::index_M (i, j);
    00308             const size_type elementm = layout_type::index_m (i, j);
    00309             vector_data_value_type& vd (ref (data () [elementM]));
    00310             storage_invariants ();
    00311             return vd.append_element (elementm, t);
    00312         }
    00313         BOOST_UBLAS_INLINE
    00314         void erase_element (size_type i, size_type j) {
    00315             vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
    00316             if (itv == data ().end ())
    00317                 return;
    00318             (*itv).erase_element (layout_type::index_m (i, j));
    00319             storage_invariants ();
    00320         }
    00321         BOOST_UBLAS_INLINE
    00322         void clear () {
    00323             const size_type sizeM = layout_type::size_M (size1_, size2_);
    00324             // FIXME should clear data () if this is done via value_type/*zero*/() then it is not size preserving
    00325             for (size_type i = 0; i < sizeM; ++ i)
    00326                 ref (data () [i]).clear ();
    00327             storage_invariants ();
    00328         }
    00329
    00330         // Iterator types
    00331     private:
    00332         // Use vector iterator
    00333         typedef typename A::const_iterator const_vectoriterator_type;
    00334         typedef typename A::iterator vectoriterator_type;
    00335         typedef typename A::value_type::const_iterator const_subiterator_type;
    00336         typedef typename A::value_type::iterator subiterator_type;
    00337
    00338         BOOST_UBLAS_INLINE
    00339         true_reference at_element (size_type i, size_type j) {
    00340             return ref (ref (data () [layout_type::index_M (i, j)]) [layout_type::index_m (i, j)]);
    00341         }
    00342
    00343     public:
    00344         class const_iterator1;
    00345         class iterator1;
    00346         class const_iterator2;
    00347         class iterator2;
    00348         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    00349         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
    00350         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    00351         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
    00352
    00353         // Element lookup
    00354         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
    00355         const_iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) const {
    00356             for (;;) {
    00357                 const_vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
    00358                 const_vectoriterator_type itv_end (data ().end ());
    00359                 if (itv == itv_end)
    00360                     return const_iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
    00361
    00362                 const_subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
    00363                 const_subiterator_type it_end ((*itv).end ());
    00364                 if (rank == 0)
    00365                     return const_iterator1 (*this, rank, i, j, itv, it);
    00366                 if (it != it_end && it.index () == layout_type::index_m (i, j))
    00367                     return const_iterator1 (*this, rank, i, j, itv, it);
    00368                 if (direction > 0) {
    00369                     if (layout_type::fast_i ()) {
    00370                         if (it == it_end)
    00371                             return const_iterator1 (*this, rank, i, j, itv, it);
    00372                         i = it.index ();
    00373                     } else {
    00374                         if (i >= size1_)
    00375                             return const_iterator1 (*this, rank, i, j, itv, it);
    00376                         ++ i;
    00377                     }
    00378                 } else /* if (direction < 0)  */ {
    00379                     if (layout_type::fast_i ()) {
    00380                         if (it == (*itv).begin ())
    00381                             return const_iterator1 (*this, rank, i, j, itv, it);
    00382                         --it;
    00383                         i = it.index ();
    00384                     } else {
    00385                         if (i == 0)
    00386                             return const_iterator1 (*this, rank, i, j, itv, it);
    00387                         -- i;
    00388                     }
    00389                 }
    00390             }
    00391         }
    00392         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
    00393         iterator1 find1 (int rank, size_type i, size_type j, int direction = 1) {
    00394             for (;;) {
    00395                 vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
    00396                 vectoriterator_type itv_end (data ().end ());
    00397                 if (itv == itv_end)
    00398                     return iterator1 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
    00399
    00400                 subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
    00401                 subiterator_type it_end ((*itv).end ());
    00402                 if (rank == 0)
    00403                     return iterator1 (*this, rank, i, j, itv, it);
    00404                 if (it != it_end && it.index () == layout_type::index_m (i, j))
    00405                     return iterator1 (*this, rank, i, j, itv, it);
    00406                 if (direction > 0) {
    00407                     if (layout_type::fast_i ()) {
    00408                         if (it == it_end)
    00409                             return iterator1 (*this, rank, i, j, itv, it);
    00410                         i = it.index ();
    00411                     } else {
    00412                         if (i >= size1_)
    00413                             return iterator1 (*this, rank, i, j, itv, it);
    00414                         ++ i;
    00415                     }
    00416                 } else /* if (direction < 0)  */ {
    00417                     if (layout_type::fast_i ()) {
    00418                         if (it == (*itv).begin ())
    00419                             return iterator1 (*this, rank, i, j, itv, it);
    00420                         --it;
    00421                         i = it.index ();
    00422                     } else {
    00423                         if (i == 0)
    00424                             return iterator1 (*this, rank, i, j, itv, it);
    00425                         -- i;
    00426                     }
    00427                 }
    00428             }
    00429         }
    00430         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
    00431         const_iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) const {
    00432             for (;;) {
    00433                 const_vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
    00434                 const_vectoriterator_type itv_end (data ().end ());
    00435                 if (itv == itv_end)
    00436                     return const_iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
    00437
    00438                 const_subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
    00439                 const_subiterator_type it_end ((*itv).end ());
    00440                 if (rank == 0)
    00441                     return const_iterator2 (*this, rank, i, j, itv, it);
    00442                 if (it != it_end && it.index () == layout_type::index_m (i, j))
    00443                     return const_iterator2 (*this, rank, i, j, itv, it);
    00444                 if (direction > 0) {
    00445                     if (layout_type::fast_j ()) {
    00446                         if (it == it_end)
    00447                             return const_iterator2 (*this, rank, i, j, itv, it);
    00448                         j = it.index ();
    00449                     } else {
    00450                         if (j >= size2_)
    00451                             return const_iterator2 (*this, rank, i, j, itv, it);
    00452                         ++ j;
    00453                     }
    00454                 } else /* if (direction < 0)  */ {
    00455                     if (layout_type::fast_j ()) {
    00456                         if (it == (*itv).begin ())
    00457                             return const_iterator2 (*this, rank, i, j, itv, it);
    00458                         --it;
    00459                         j = it.index ();
    00460                     } else {
    00461                         if (j == 0)
    00462                             return const_iterator2 (*this, rank, i, j, itv, it);
    00463                         -- j;
    00464                     }
    00465                 }
    00466             }
    00467         }
    00468         // BOOST_UBLAS_INLINE This function seems to be big. So we do not let the compiler inline it.
    00469         iterator2 find2 (int rank, size_type i, size_type j, int direction = 1) {
    00470             for (;;) {
    00471                 vectoriterator_type itv (data ().find (layout_type::index_M (i, j)));
    00472                 vectoriterator_type itv_end (data ().end ());
    00473                 if (itv == itv_end)
    00474                     return iterator2 (*this, rank, i, j, itv_end, (*(-- itv)).end ());
    00475
    00476                 subiterator_type it ((*itv).find (layout_type::index_m (i, j)));
    00477                 subiterator_type it_end ((*itv).end ());
    00478                 if (rank == 0)
    00479                     return iterator2 (*this, rank, i, j, itv, it);
    00480                 if (it != it_end && it.index () == layout_type::index_m (i, j))
    00481                     return iterator2 (*this, rank, i, j, itv, it);
    00482                 if (direction > 0) {
    00483                     if (layout_type::fast_j ()) {
    00484                         if (it == it_end)
    00485                             return iterator2 (*this, rank, i, j, itv, it);
    00486                         j = it.index ();
    00487                     } else {
    00488                         if (j >= size2_)
    00489                             return iterator2 (*this, rank, i, j, itv, it);
    00490                         ++ j;
    00491                     }
    00492                 } else /* if (direction < 0)  */ {
    00493                     if (layout_type::fast_j ()) {
    00494                         if (it == (*itv).begin ())
    00495                             return iterator2 (*this, rank, i, j, itv, it);
    00496                         --it;
    00497                         j = it.index ();
    00498                     } else {
    00499                         if (j == 0)
    00500                             return iterator2 (*this, rank, i, j, itv, it);
    00501                         -- j;
    00502                     }
    00503                 }
    00504             }
    00505         }
    00506
    00507
    00508         class const_iterator1:
    00509             public container_const_reference<generalized_vector_of_vector>,
    00510             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
    00511                                                const_iterator1, value_type> {
    00512         public:
    00513             typedef typename generalized_vector_of_vector::difference_type difference_type;
    00514             typedef typename generalized_vector_of_vector::value_type value_type;
    00515             typedef typename generalized_vector_of_vector::const_reference reference;
    00516             typedef const typename generalized_vector_of_vector::pointer pointer;
    00517
    00518             typedef const_iterator2 dual_iterator_type;
    00519             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    00520
    00521             // Construction and destruction
    00522             BOOST_UBLAS_INLINE
    00523             const_iterator1 ():
    00524                 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
    00525             BOOST_UBLAS_INLINE
    00526             const_iterator1 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it):
    00527                 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
    00528             BOOST_UBLAS_INLINE
    00529             const_iterator1 (const iterator1 &it):
    00530                 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
    00531
    00532             // Arithmetic
    00533             BOOST_UBLAS_INLINE
    00534             const_iterator1 &operator ++ () {
    00535                 if (rank_ == 1 && layout_type::fast_i ())
    00536                     ++ it_;
    00537                 else {
    00538                     const self_type &m = (*this) ();
    00539                     i_ = index1 () + 1;
    00540                     if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
    00541                         *this = m.find1 (rank_, i_, j_, 1);
    00542                     else if (rank_ == 1) {
    00543                         it_ = (*itv_).begin ();
    00544                         if (it_ == (*itv_).end () || index2 () != j_)
    00545                             *this = m.find1 (rank_, i_, j_, 1);
    00546                     }
    00547                 }
    00548                 return *this;
    00549             }
    00550             BOOST_UBLAS_INLINE
    00551             const_iterator1 &operator -- () {
    00552                 if (rank_ == 1 && layout_type::fast_i ())
    00553                     -- it_;
    00554                 else {
    00555                     const self_type &m = (*this) ();
    00556                     i_ = index1 () - 1;
    00557                     if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
    00558                         *this = m.find1 (rank_, i_, j_, -1);
    00559                     else if (rank_ == 1) {
    00560                         it_ = (*itv_).begin ();
    00561                         if (it_ == (*itv_).end () || index2 () != j_)
    00562                             *this = m.find1 (rank_, i_, j_, -1);
    00563                     }
    00564                 }
    00565                 return *this;
    00566             }
    00567
    00568             // Dereference
    00569             BOOST_UBLAS_INLINE
    00570             const_reference operator * () const {
    00571                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    00572                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    00573                 if (rank_ == 1) {
    00574                     return *it_;
    00575                 } else {
    00576                     return (*this) () (i_, j_);
    00577                 }
    00578             }
    00579
    00580 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00581             BOOST_UBLAS_INLINE
    00582 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00583             typename self_type::
    00584 #endif
    00585             const_iterator2 begin () const {
    00586                 const self_type &m = (*this) ();
    00587                 return m.find2 (1, index1 (), 0);
    00588             }
    00589             BOOST_UBLAS_INLINE
    00590 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00591             typename self_type::
    00592 #endif
    00593             const_iterator2 end () const {
    00594                 const self_type &m = (*this) ();
    00595                 return m.find2 (1, index1 (), m.size2 ());
    00596             }
    00597             BOOST_UBLAS_INLINE
    00598 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00599             typename self_type::
    00600 #endif
    00601             const_reverse_iterator2 rbegin () const {
    00602                 return const_reverse_iterator2 (end ());
    00603             }
    00604             BOOST_UBLAS_INLINE
    00605 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00606             typename self_type::
    00607 #endif
    00608             const_reverse_iterator2 rend () const {
    00609                 return const_reverse_iterator2 (begin ());
    00610             }
    00611 #endif
    00612
    00613             // Indices
    00614             BOOST_UBLAS_INLINE
    00615             size_type index1 () const {
    00616                 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
    00617                 if (rank_ == 1) {
    00618                     BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
    00619                     return layout_type::index_M (itv_.index (), it_.index ());
    00620                 } else {
    00621                     return i_;
    00622                 }
    00623             }
    00624             BOOST_UBLAS_INLINE
    00625             size_type index2 () const {
    00626                 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
    00627                 if (rank_ == 1) {
    00628                     BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
    00629                     return layout_type::index_m (itv_.index (), it_.index ());
    00630                 } else {
    00631                     return j_;
    00632                 }
    00633             }
    00634
    00635             // Assignment
    00636             BOOST_UBLAS_INLINE
    00637             const_iterator1 &operator = (const const_iterator1 &it) {
    00638                 container_const_reference<self_type>::assign (&it ());
    00639                 rank_ = it.rank_;
    00640                 i_ = it.i_;
    00641                 j_ = it.j_;
    00642                 itv_ = it.itv_;
    00643                 it_ = it.it_;
    00644                 return *this;
    00645             }
    00646
    00647             // Comparison
    00648             BOOST_UBLAS_INLINE
    00649             bool operator == (const const_iterator1 &it) const {
    00650                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00651                 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
    00652                 if (rank_ == 1 || it.rank_ == 1) {
    00653                     return it_ == it.it_;
    00654                 } else {
    00655                     return i_ == it.i_ && j_ == it.j_;
    00656                 }
    00657             }
    00658
    00659         private:
    00660             int rank_;
    00661             size_type i_;
    00662             size_type j_;
    00663             const_vectoriterator_type itv_;
    00664             const_subiterator_type it_;
    00665         };
    00666
    00667         BOOST_UBLAS_INLINE
    00668         const_iterator1 begin1 () const {
    00669             return find1 (0, 0, 0);
    00670         }
    00671         BOOST_UBLAS_INLINE
    00672         const_iterator1 end1 () const {
    00673             return find1 (0, size1_, 0);
    00674         }
    00675
    00676         class iterator1:
    00677             public container_reference<generalized_vector_of_vector>,
    00678             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
    00679                                                iterator1, value_type> {
    00680         public:
    00681             typedef typename generalized_vector_of_vector::difference_type difference_type;
    00682             typedef typename generalized_vector_of_vector::value_type value_type;
    00683             typedef typename generalized_vector_of_vector::true_reference reference;
    00684             typedef typename generalized_vector_of_vector::pointer pointer;
    00685
    00686             typedef iterator2 dual_iterator_type;
    00687             typedef reverse_iterator2 dual_reverse_iterator_type;
    00688
    00689             // Construction and destruction
    00690             BOOST_UBLAS_INLINE
    00691             iterator1 ():
    00692                 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
    00693             BOOST_UBLAS_INLINE
    00694             iterator1 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it):
    00695                 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
    00696
    00697             // Arithmetic
    00698             BOOST_UBLAS_INLINE
    00699             iterator1 &operator ++ () {
    00700                 if (rank_ == 1 && layout_type::fast_i ())
    00701                     ++ it_;
    00702                 else {
    00703                     self_type &m = (*this) ();
    00704                     i_ = index1 () + 1;
    00705                     if (rank_ == 1 && ++ itv_ == m.end1 ().itv_)
    00706                         *this = m.find1 (rank_, i_, j_, 1);
    00707                     else if (rank_ == 1) {
    00708                         it_ = (*itv_).begin ();
    00709                         if (it_ == (*itv_).end () || index2 () != j_)
    00710                             *this = m.find1 (rank_, i_, j_, 1);
    00711                     }
    00712                 }
    00713                 return *this;
    00714             }
    00715             BOOST_UBLAS_INLINE
    00716             iterator1 &operator -- () {
    00717                 if (rank_ == 1 && layout_type::fast_i ())
    00718                     -- it_;
    00719                 else {
    00720                     self_type &m = (*this) ();
    00721                     i_ = index1 () - 1;
    00722                     if (rank_ == 1 && -- itv_ == m.end1 ().itv_)
    00723                         *this = m.find1 (rank_, i_, j_, -1);
    00724                     else if (rank_ == 1) {
    00725                         it_ = (*itv_).begin ();
    00726                         if (it_ == (*itv_).end () || index2 () != j_)
    00727                             *this = m.find1 (rank_, i_, j_, -1);
    00728                     }
    00729                 }
    00730                 return *this;
    00731             }
    00732
    00733             // Dereference
    00734             BOOST_UBLAS_INLINE
    00735             true_reference operator * () const {
    00736                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    00737                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    00738                 if (rank_ == 1) {
    00739                     return *it_;
    00740                 } else {
    00741                     return (*this) ().at_element (i_, j_);
    00742                 }
    00743             }
    00744
    00745 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00746             BOOST_UBLAS_INLINE
    00747 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00748             typename self_type::
    00749 #endif
    00750             iterator2 begin () const {
    00751                 self_type &m = (*this) ();
    00752                 return m.find2 (1, index1 (), 0);
    00753             }
    00754             BOOST_UBLAS_INLINE
    00755 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00756             typename self_type::
    00757 #endif
    00758             iterator2 end () const {
    00759                 self_type &m = (*this) ();
    00760                 return m.find2 (1, index1 (), m.size2 ());
    00761             }
    00762             BOOST_UBLAS_INLINE
    00763 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00764             typename self_type::
    00765 #endif
    00766             reverse_iterator2 rbegin () const {
    00767                 return reverse_iterator2 (end ());
    00768             }
    00769             BOOST_UBLAS_INLINE
    00770 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00771             typename self_type::
    00772 #endif
    00773             reverse_iterator2 rend () const {
    00774                 return reverse_iterator2 (begin ());
    00775             }
    00776 #endif
    00777
    00778             // Indices
    00779             BOOST_UBLAS_INLINE
    00780             size_type index1 () const {
    00781                 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
    00782                 if (rank_ == 1) {
    00783                     BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
    00784                     return layout_type::index_M (itv_.index (), it_.index ());
    00785                 } else {
    00786                     return i_;
    00787                 }
    00788             }
    00789             BOOST_UBLAS_INLINE
    00790             size_type index2 () const {
    00791                 BOOST_UBLAS_CHECK (*this != (*this) ().find1 (0, (*this) ().size1 (), j_), bad_index ());
    00792                 if (rank_ == 1) {
    00793                     BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
    00794                     return layout_type::index_m (itv_.index (), it_.index ());
    00795                 } else {
    00796                     return j_;
    00797                 }
    00798             }
    00799
    00800             // Assignment
    00801             BOOST_UBLAS_INLINE
    00802             iterator1 &operator = (const iterator1 &it) {
    00803                 container_reference<self_type>::assign (&it ());
    00804                 rank_ = it.rank_;
    00805                 i_ = it.i_;
    00806                 j_ = it.j_;
    00807                 itv_ = it.itv_;
    00808                 it_ = it.it_;
    00809                 return *this;
    00810             }
    00811
    00812             // Comparison
    00813             BOOST_UBLAS_INLINE
    00814             bool operator == (const iterator1 &it) const {
    00815                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00816                 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
    00817                 if (rank_ == 1 || it.rank_ == 1) {
    00818                     return it_ == it.it_;
    00819                 } else {
    00820                     return i_ == it.i_ && j_ == it.j_;
    00821                 }
    00822             }
    00823
    00824         private:
    00825             int rank_;
    00826             size_type i_;
    00827             size_type j_;
    00828             vectoriterator_type itv_;
    00829             subiterator_type it_;
    00830
    00831             friend class const_iterator1;
    00832         };
    00833
    00834         BOOST_UBLAS_INLINE
    00835         iterator1 begin1 () {
    00836             return find1 (0, 0, 0);
    00837         }
    00838         BOOST_UBLAS_INLINE
    00839         iterator1 end1 () {
    00840             return find1 (0, size1_, 0);
    00841         }
    00842
    00843         class const_iterator2:
    00844             public container_const_reference<generalized_vector_of_vector>,
    00845             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
    00846                                                const_iterator2, value_type> {
    00847         public:
    00848             typedef typename generalized_vector_of_vector::difference_type difference_type;
    00849             typedef typename generalized_vector_of_vector::value_type value_type;
    00850             typedef typename generalized_vector_of_vector::const_reference reference;
    00851             typedef const typename generalized_vector_of_vector::pointer pointer;
    00852
    00853             typedef const_iterator1 dual_iterator_type;
    00854             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    00855
    00856             // Construction and destruction
    00857             BOOST_UBLAS_INLINE
    00858             const_iterator2 ():
    00859                 container_const_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
    00860             BOOST_UBLAS_INLINE
    00861             const_iterator2 (const self_type &m, int rank, size_type i, size_type j, const const_vectoriterator_type &itv, const const_subiterator_type &it):
    00862                 container_const_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
    00863             BOOST_UBLAS_INLINE
    00864             const_iterator2 (const iterator2 &it):
    00865                 container_const_reference<self_type> (it ()), rank_ (it.rank_), i_ (it.i_), j_ (it.j_), itv_ (it.itv_), it_ (it.it_) {}
    00866
    00867             // Arithmetic
    00868             BOOST_UBLAS_INLINE
    00869             const_iterator2 &operator ++ () {
    00870                 if (rank_ == 1 && layout_type::fast_j ())
    00871                     ++ it_;
    00872                 else {
    00873                     const self_type &m = (*this) ();
    00874                     j_ = index2 () + 1;
    00875                     if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
    00876                         *this = m.find2 (rank_, i_, j_, 1);
    00877                     else if (rank_ == 1) {
    00878                         it_ = (*itv_).begin ();
    00879                         if (it_ == (*itv_).end () || index1 () != i_)
    00880                             *this = m.find2 (rank_, i_, j_, 1);
    00881                     }
    00882                 }
    00883                 return *this;
    00884             }
    00885             BOOST_UBLAS_INLINE
    00886             const_iterator2 &operator -- () {
    00887                 if (rank_ == 1 && layout_type::fast_j ())
    00888                     -- it_;
    00889                 else {
    00890                     const self_type &m = (*this) ();
    00891                     j_ = index2 () - 1;
    00892                     if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
    00893                         *this = m.find2 (rank_, i_, j_, -1);
    00894                     else if (rank_ == 1) {
    00895                         it_ = (*itv_).begin ();
    00896                         if (it_ == (*itv_).end () || index1 () != i_)
    00897                             *this = m.find2 (rank_, i_, j_, -1);
    00898                     }
    00899                 }
    00900                 return *this;
    00901             }
    00902
    00903             // Dereference
    00904             BOOST_UBLAS_INLINE
    00905             const_reference operator * () const {
    00906                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    00907                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    00908                 if (rank_ == 1) {
    00909                     return *it_;
    00910                 } else {
    00911                     return (*this) () (i_, j_);
    00912                 }
    00913             }
    00914
    00915 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00916             BOOST_UBLAS_INLINE
    00917 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00918             typename self_type::
    00919 #endif
    00920             const_iterator1 begin () const {
    00921                 const self_type &m = (*this) ();
    00922                 return m.find1 (1, 0, index2 ());
    00923             }
    00924             BOOST_UBLAS_INLINE
    00925 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00926             typename self_type::
    00927 #endif
    00928             const_iterator1 end () const {
    00929                 const self_type &m = (*this) ();
    00930                 return m.find1 (1, m.size1 (), index2 ());
    00931             }
    00932             BOOST_UBLAS_INLINE
    00933 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00934             typename self_type::
    00935 #endif
    00936             const_reverse_iterator1 rbegin () const {
    00937                 return const_reverse_iterator1 (end ());
    00938             }
    00939             BOOST_UBLAS_INLINE
    00940 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00941             typename self_type::
    00942 #endif
    00943             const_reverse_iterator1 rend () const {
    00944                 return const_reverse_iterator1 (begin ());
    00945             }
    00946 #endif
    00947
    00948             // Indices
    00949             BOOST_UBLAS_INLINE
    00950             size_type index1 () const {
    00951                 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
    00952                 if (rank_ == 1) {
    00953                     BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
    00954                     return layout_type::index_M (itv_.index (), it_.index ());
    00955                 } else {
    00956                     return i_;
    00957                 }
    00958             }
    00959             BOOST_UBLAS_INLINE
    00960             size_type index2 () const {
    00961                 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
    00962                 if (rank_ == 1) {
    00963                     BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
    00964                     return layout_type::index_m (itv_.index (), it_.index ());
    00965                 } else {
    00966                     return j_;
    00967                 }
    00968             }
    00969
    00970             // Assignment
    00971             BOOST_UBLAS_INLINE
    00972             const_iterator2 &operator = (const const_iterator2 &it) {
    00973                 container_const_reference<self_type>::assign (&it ());
    00974                 rank_ = it.rank_;
    00975                 i_ = it.i_;
    00976                 j_ = it.j_;
    00977                 itv_ = it.itv_;
    00978                 it_ = it.it_;
    00979                 return *this;
    00980             }
    00981
    00982             // Comparison
    00983             BOOST_UBLAS_INLINE
    00984             bool operator == (const const_iterator2 &it) const {
    00985                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00986                 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
    00987                 if (rank_ == 1 || it.rank_ == 1) {
    00988                     return it_ == it.it_;
    00989                 } else {
    00990                     return i_ == it.i_ && j_ == it.j_;
    00991                 }
    00992             }
    00993
    00994         private:
    00995             int rank_;
    00996             size_type i_;
    00997             size_type j_;
    00998             const_vectoriterator_type itv_;
    00999             const_subiterator_type it_;
    01000         };
    01001
    01002         BOOST_UBLAS_INLINE
    01003         const_iterator2 begin2 () const {
    01004             return find2 (0, 0, 0);
    01005         }
    01006         BOOST_UBLAS_INLINE
    01007         const_iterator2 end2 () const {
    01008             return find2 (0, 0, size2_);
    01009         }
    01010
    01011         class iterator2:
    01012             public container_reference<generalized_vector_of_vector>,
    01013             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
    01014                                                iterator2, value_type> {
    01015         public:
    01016             typedef typename generalized_vector_of_vector::difference_type difference_type;
    01017             typedef typename generalized_vector_of_vector::value_type value_type;
    01018             typedef typename generalized_vector_of_vector::true_reference reference;
    01019             typedef typename generalized_vector_of_vector::pointer pointer;
    01020
    01021             typedef iterator1 dual_iterator_type;
    01022             typedef reverse_iterator1 dual_reverse_iterator_type;
    01023
    01024             // Construction and destruction
    01025             BOOST_UBLAS_INLINE
    01026             iterator2 ():
    01027                 container_reference<self_type> (), rank_ (), i_ (), j_ (), itv_ (), it_ () {}
    01028             BOOST_UBLAS_INLINE
    01029             iterator2 (self_type &m, int rank, size_type i, size_type j, const vectoriterator_type &itv, const subiterator_type &it):
    01030                 container_reference<self_type> (m), rank_ (rank), i_ (i), j_ (j), itv_ (itv), it_ (it) {}
    01031
    01032             // Arithmetic
    01033             BOOST_UBLAS_INLINE
    01034             iterator2 &operator ++ () {
    01035                 if (rank_ == 1 && layout_type::fast_j ())
    01036                     ++ it_;
    01037                 else {
    01038                     self_type &m = (*this) ();
    01039                     j_ = index2 () + 1;
    01040                     if (rank_ == 1 && ++ itv_ == m.end2 ().itv_)
    01041                         *this = m.find2 (rank_, i_, j_, 1);
    01042                     else if (rank_ == 1) {
    01043                         it_ = (*itv_).begin ();
    01044                         if (it_ == (*itv_).end () || index1 () != i_)
    01045                             *this = m.find2 (rank_, i_, j_, 1);
    01046                     }
    01047                 }
    01048                 return *this;
    01049             }
    01050             BOOST_UBLAS_INLINE
    01051             iterator2 &operator -- () {
    01052                 if (rank_ == 1 && layout_type::fast_j ())
    01053                     -- it_;
    01054                 else {
    01055                     self_type &m = (*this) ();
    01056                     j_ = index2 () - 1;
    01057                     if (rank_ == 1 && -- itv_ == m.end2 ().itv_)
    01058                         *this = m.find2 (rank_, i_, j_, -1);
    01059                     else if (rank_ == 1) {
    01060                         it_ = (*itv_).begin ();
    01061                         if (it_ == (*itv_).end () || index1 () != i_)
    01062                             *this = m.find2 (rank_, i_, j_, -1);
    01063                     }
    01064                 }
    01065                 return *this;
    01066             }
    01067
    01068             // Dereference
    01069             BOOST_UBLAS_INLINE
    01070             true_reference operator * () const {
    01071                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    01072                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    01073                 if (rank_ == 1) {
    01074                     return *it_;
    01075                 } else {
    01076                     return (*this) ().at_element (i_, j_);
    01077                 }
    01078             }
    01079
    01080 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    01081             BOOST_UBLAS_INLINE
    01082 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01083             typename self_type::
    01084 #endif
    01085             iterator1 begin () const {
    01086                 self_type &m = (*this) ();
    01087                 return m.find1 (1, 0, index2 ());
    01088             }
    01089             BOOST_UBLAS_INLINE
    01090 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01091             typename self_type::
    01092 #endif
    01093             iterator1 end () const {
    01094                 self_type &m = (*this) ();
    01095                 return m.find1 (1, m.size1 (), index2 ());
    01096             }
    01097             BOOST_UBLAS_INLINE
    01098 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01099             typename self_type::
    01100 #endif
    01101             reverse_iterator1 rbegin () const {
    01102                 return reverse_iterator1 (end ());
    01103             }
    01104             BOOST_UBLAS_INLINE
    01105 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01106             typename self_type::
    01107 #endif
    01108             reverse_iterator1 rend () const {
    01109                 return reverse_iterator1 (begin ());
    01110             }
    01111 #endif
    01112
    01113             // Indices
    01114             BOOST_UBLAS_INLINE
    01115             size_type index1 () const {
    01116                 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
    01117                 if (rank_ == 1) {
    01118                     BOOST_UBLAS_CHECK (layout_type::index_M (itv_.index (), it_.index ()) < (*this) ().size1 (), bad_index ());
    01119                     return layout_type::index_M (itv_.index (), it_.index ());
    01120                 } else {
    01121                     return i_;
    01122                 }
    01123             }
    01124             BOOST_UBLAS_INLINE
    01125             size_type index2 () const {
    01126                 BOOST_UBLAS_CHECK (*this != (*this) ().find2 (0, i_, (*this) ().size2 ()), bad_index ());
    01127                 if (rank_ == 1) {
    01128                     BOOST_UBLAS_CHECK (layout_type::index_m (itv_.index (), it_.index ()) < (*this) ().size2 (), bad_index ());
    01129                     return layout_type::index_m (itv_.index (), it_.index ());
    01130                 } else {
    01131                     return j_;
    01132                 }
    01133             }
    01134
    01135             // Assignment
    01136             BOOST_UBLAS_INLINE
    01137             iterator2 &operator = (const iterator2 &it) {
    01138                 container_reference<self_type>::assign (&it ());
    01139                 rank_ = it.rank_;
    01140                 i_ = it.i_;
    01141                 j_ = it.j_;
    01142                 itv_ = it.itv_;
    01143                 it_ = it.it_;
    01144                 return *this;
    01145             }
    01146
    01147             // Comparison
    01148             BOOST_UBLAS_INLINE
    01149             bool operator == (const iterator2 &it) const {
    01150                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01151                 // BOOST_UBLAS_CHECK (rank_ == it.rank_, internal_logic ());
    01152                 if (rank_ == 1 || it.rank_ == 1) {
    01153                     return it_ == it.it_;
    01154                 } else {
    01155                     return i_ == it.i_ && j_ == it.j_;
    01156                 }
    01157             }
    01158
    01159         private:
    01160             int rank_;
    01161             size_type i_;
    01162             size_type j_;
    01163             vectoriterator_type itv_;
    01164             subiterator_type it_;
    01165
    01166             friend class const_iterator2;
    01167         };
    01168
    01169         BOOST_UBLAS_INLINE
    01170         iterator2 begin2 () {
    01171             return find2 (0, 0, 0);
    01172         }
    01173         BOOST_UBLAS_INLINE
    01174         iterator2 end2 () {
    01175             return find2 (0, 0, size2_);
    01176         }
    01177
    01178         // Reverse iterators
    01179
    01180         BOOST_UBLAS_INLINE
    01181         const_reverse_iterator1 rbegin1 () const {
    01182             return const_reverse_iterator1 (end1 ());
    01183         }
    01184         BOOST_UBLAS_INLINE
    01185         const_reverse_iterator1 rend1 () const {
    01186             return const_reverse_iterator1 (begin1 ());
    01187         }
    01188
    01189         BOOST_UBLAS_INLINE
    01190         reverse_iterator1 rbegin1 () {
    01191             return reverse_iterator1 (end1 ());
    01192         }
    01193         BOOST_UBLAS_INLINE
    01194         reverse_iterator1 rend1 () {
    01195             return reverse_iterator1 (begin1 ());
    01196         }
    01197
    01198         BOOST_UBLAS_INLINE
    01199         const_reverse_iterator2 rbegin2 () const {
    01200             return const_reverse_iterator2 (end2 ());
    01201         }
    01202         BOOST_UBLAS_INLINE
    01203         const_reverse_iterator2 rend2 () const {
    01204             return const_reverse_iterator2 (begin2 ());
    01205         }
    01206
    01207         BOOST_UBLAS_INLINE
    01208         reverse_iterator2 rbegin2 () {
    01209             return reverse_iterator2 (end2 ());
    01210         }
    01211         BOOST_UBLAS_INLINE
    01212         reverse_iterator2 rend2 () {
    01213             return reverse_iterator2 (begin2 ());
    01214         }
    01215
    01216          // Serialization
    01217         template<class Archive>
    01218         void serialize(Archive & ar, const unsigned int /* file_version */){
    01219
    01220             // we need to copy to a collection_size_type to get a portable
    01221             // and efficient serialization
    01222             serialization::collection_size_type s1 (size1_);
    01223             serialization::collection_size_type s2 (size2_);
    01224
    01225             // serialize the sizes
    01226             ar & serialization::make_nvp("size1",s1)
    01227                & serialization::make_nvp("size2",s2);
    01228
    01229             // copy the values back if loading
    01230             if (Archive::is_loading::value) {
    01231                 size1_ = s1;
    01232                 size2_ = s2;
    01233             }
    01234
    01235             ar & serialization::make_nvp("data", data_);
    01236
    01237             storage_invariants();
    01238         }
    01239
    01240     private:
    01241         void storage_invariants () const
    01242         {
    01243             BOOST_UBLAS_CHECK (layout_type::size_M (size1_, size2_) + 1 == data_.size (), internal_logic ());
    01244             BOOST_UBLAS_CHECK (data ().begin () != data ().end (), internal_logic ());
    01245
    01246         }
    01247         size_type size1_;
    01248         size_type size2_;
    01249         array_type data_;
    01250         static const value_type zero_;
    01251     };
    01252
    01253     template<class T, class L, class A>
    01254     const typename generalized_vector_of_vector<T, L, A>::value_type generalized_vector_of_vector<T, L, A>::zero_ = value_type/*zero*/();
    01255
    01256 }}}
    01257
    01258 #endif