- Main Page
- Related Pages
- Classes
- Files

- File List

# matrix.hpp

    00001 //
    00002 //  Copyright (c) 2000-2010
    00003 //  Joerg Walter, Mathias Koch, Gunter Winkler, David Bellot
    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_MATRIX_
    00014 #define _BOOST_UBLAS_MATRIX_
    00015
    00016 #include <boost/numeric/ublas/vector.hpp>
    00017 #include <boost/numeric/ublas/matrix_expression.hpp>
    00018 #include <boost/numeric/ublas/detail/matrix_assign.hpp>
    00019 #include <boost/serialization/collection_size_type.hpp>
    00020 #include <boost/serialization/array.hpp>
    00021 #include <boost/serialization/nvp.hpp>
    00022
    00023 // Iterators based on ideas of Jeremy Siek
    00024
    00025 namespace boost { namespace numeric {
    00026
    00040         namespace ublas {
    00041
    00042     namespace detail {
    00043         using namespace boost::numeric::ublas;
    00044
    00045         // Matrix resizing algorithm
    00046         template <class L, class M>
    00047         BOOST_UBLAS_INLINE
    00048         void matrix_resize_preserve (M& m, M& temporary) {
    00049             typedef L layout_type;
    00050             typedef typename M::size_type size_type;
    00051             const size_type msize1 (m.size1 ());        // original size
    00052             const size_type msize2 (m.size2 ());
    00053             const size_type size1 (temporary.size1 ());    // new size is specified by temporary
    00054             const size_type size2 (temporary.size2 ());
    00055             // Common elements to preserve
    00056             const size_type size1_min = (std::min) (size1, msize1);
    00057             const size_type size2_min = (std::min) (size2, msize2);
    00058             // Order for major and minor sizes
    00059             const size_type major_size = layout_type::size_M (size1_min, size2_min);
    00060             const size_type minor_size = layout_type::size_m (size1_min, size2_min);
    00061             // Indexing copy over major
    00062             for (size_type major = 0; major != major_size; ++major) {
    00063                 for (size_type minor = 0; minor != minor_size; ++minor) {
    00064                         // find indexes - use invertability of element_ functions
    00065                     const size_type i1 = layout_type::index_M(major, minor);
    00066                     const size_type i2 = layout_type::index_m(major, minor);
    00067                     temporary.data () [layout_type::element (i1, size1, i2, size2)] =
    00068                             m.data() [layout_type::element (i1, msize1, i2, msize2)];
    00069                 }
    00070             }
    00071             m.assign_temporary (temporary);
    00072         }
    00073     }
    00074
    00089     template<class T, class L, class A>
    00090     class matrix:
    00091         public matrix_container<matrix<T, L, A> > {
    00092
    00093         typedef T *pointer;
    00094         typedef L layout_type;
    00095         typedef matrix<T, L, A> self_type;
    00096     public:
    00097 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    00098         using matrix_container<self_type>::operator ();
    00099 #endif
    00100         typedef typename A::size_type size_type;
    00101         typedef typename A::difference_type difference_type;
    00102         typedef T value_type;
    00103         typedef const T &const_reference;
    00104         typedef T &reference;
    00105         typedef A array_type;
    00106         typedef const matrix_reference<const self_type> const_closure_type;
    00107         typedef matrix_reference<self_type> closure_type;
    00108         typedef vector<T, A> vector_temporary_type;
    00109         typedef self_type matrix_temporary_type;
    00110         typedef dense_tag storage_category;
    00111         // This could be better for performance,
    00112         // typedef typename unknown_orientation_tag orientation_category;
    00113         // but others depend on the orientation information...
    00114         typedef typename L::orientation_category orientation_category;
    00115
    00116         // Construction and destruction
    00117         BOOST_UBLAS_INLINE
    00118         matrix ():
    00119             matrix_container<self_type> (),
    00120             size1_ (0), size2_ (0), data_ () {}
    00121         BOOST_UBLAS_INLINE
    00122         matrix (size_type size1, size_type size2):
    00123             matrix_container<self_type> (),
    00124             size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2)) {
    00125         }
    00126         matrix (size_type size1, size_type size2, const value_type &init):
    00127             matrix_container<self_type> (),
    00128             size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2), init) {
    00129         }
    00130         BOOST_UBLAS_INLINE
    00131         matrix (size_type size1, size_type size2, const array_type &data):
    00132             matrix_container<self_type> (),
    00133             size1_ (size1), size2_ (size2), data_ (data) {}
    00134         BOOST_UBLAS_INLINE
    00135         matrix (const matrix &m):
    00136             matrix_container<self_type> (),
    00137             size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
    00138         template<class AE>
    00139         BOOST_UBLAS_INLINE
    00140         matrix (const matrix_expression<AE> &ae):
    00141             matrix_container<self_type> (),
    00142             size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::storage_size (size1_, size2_)) {
    00143             matrix_assign<scalar_assign> (*this, ae);
    00144         }
    00145
    00146         // Accessors
    00147         BOOST_UBLAS_INLINE
    00148         size_type size1 () const {
    00149             return size1_;
    00150         }
    00151         BOOST_UBLAS_INLINE
    00152         size_type size2 () const {
    00153             return size2_;
    00154         }
    00155
    00156         // Storage accessors
    00157         BOOST_UBLAS_INLINE
    00158         const array_type &data () const {
    00159             return data_;
    00160         }
    00161         BOOST_UBLAS_INLINE
    00162         array_type &data () {
    00163             return data_;
    00164         }
    00165
    00166         // Resizing
    00167         BOOST_UBLAS_INLINE
    00168         void resize (size_type size1, size_type size2, bool preserve = true) {
    00169             if (preserve) {
    00170                 self_type temporary (size1, size2);
    00171                 detail::matrix_resize_preserve<layout_type> (*this, temporary);
    00172             }
    00173             else {
    00174                 data ().resize (layout_type::storage_size (size1, size2));
    00175                 size1_ = size1;
    00176                 size2_ = size2;
    00177             }
    00178         }
    00179
    00180         // Element access
    00181         BOOST_UBLAS_INLINE
    00182         const_reference operator () (size_type i, size_type j) const {
    00183             return data () [layout_type::element (i, size1_, j, size2_)];
    00184         }
    00185         BOOST_UBLAS_INLINE
    00186         reference at_element (size_type i, size_type j) {
    00187             return data () [layout_type::element (i, size1_, j, size2_)];
    00188         }
    00189         BOOST_UBLAS_INLINE
    00190         reference operator () (size_type i, size_type j) {
    00191             return at_element (i, j);
    00192         }
    00193
    00194         // Element assignment
    00195         BOOST_UBLAS_INLINE
    00196         reference insert_element (size_type i, size_type j, const_reference t) {
    00197             return (at_element (i, j) = t);
    00198         }
    00199         void erase_element (size_type i, size_type j) {
    00200             at_element (i, j) = value_type/*zero*/();
    00201         }
    00202
    00203         // Zeroing
    00204         BOOST_UBLAS_INLINE
    00205         void clear () {
    00206             std::fill (data ().begin (), data ().end (), value_type/*zero*/());
    00207         }
    00208
    00209         // Assignment
    00210 #ifdef BOOST_UBLAS_MOVE_SEMANTICS
    00211
    00213         BOOST_UBLAS_INLINE
    00214         matrix &operator = (matrix m) {
    00215             assign_temporary(m);
    00216             return *this;
    00217         }
    00218 #else
    00219         BOOST_UBLAS_INLINE
    00220         matrix &operator = (const matrix &m) {
    00221             size1_ = m.size1_;
    00222             size2_ = m.size2_;
    00223             data () = m.data ();
    00224             return *this;
    00225         }
    00226 #endif
    00227         template<class C>          // Container assignment without temporary
    00228         BOOST_UBLAS_INLINE
    00229         matrix &operator = (const matrix_container<C> &m) {
    00230             resize (m ().size1 (), m ().size2 (), false);
    00231             assign (m);
    00232             return *this;
    00233         }
    00234         BOOST_UBLAS_INLINE
    00235         matrix &assign_temporary (matrix &m) {
    00236             swap (m);
    00237             return *this;
    00238         }
    00239         template<class AE>
    00240         BOOST_UBLAS_INLINE
    00241         matrix &operator = (const matrix_expression<AE> &ae) {
    00242             self_type temporary (ae);
    00243             return assign_temporary (temporary);
    00244         }
    00245         template<class AE>
    00246         BOOST_UBLAS_INLINE
    00247         matrix &assign (const matrix_expression<AE> &ae) {
    00248             matrix_assign<scalar_assign> (*this, ae);
    00249             return *this;
    00250         }
    00251         template<class AE>
    00252         BOOST_UBLAS_INLINE
    00253         matrix& operator += (const matrix_expression<AE> &ae) {
    00254             self_type temporary (*this + ae);
    00255             return assign_temporary (temporary);
    00256         }
    00257         template<class C>          // Container assignment without temporary
    00258         BOOST_UBLAS_INLINE
    00259         matrix &operator += (const matrix_container<C> &m) {
    00260             plus_assign (m);
    00261             return *this;
    00262         }
    00263         template<class AE>
    00264         BOOST_UBLAS_INLINE
    00265         matrix &plus_assign (const matrix_expression<AE> &ae) {
    00266             matrix_assign<scalar_plus_assign> (*this, ae);
    00267             return *this;
    00268         }
    00269         template<class AE>
    00270         BOOST_UBLAS_INLINE
    00271         matrix& operator -= (const matrix_expression<AE> &ae) {
    00272             self_type temporary (*this - ae);
    00273             return assign_temporary (temporary);
    00274         }
    00275         template<class C>          // Container assignment without temporary
    00276         BOOST_UBLAS_INLINE
    00277         matrix &operator -= (const matrix_container<C> &m) {
    00278             minus_assign (m);
    00279             return *this;
    00280         }
    00281         template<class AE>
    00282         BOOST_UBLAS_INLINE
    00283         matrix &minus_assign (const matrix_expression<AE> &ae) {
    00284             matrix_assign<scalar_minus_assign> (*this, ae);
    00285             return *this;
    00286         }
    00287         template<class AT>
    00288         BOOST_UBLAS_INLINE
    00289         matrix& operator *= (const AT &at) {
    00290             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
    00291             return *this;
    00292         }
    00293         template<class AT>
    00294         BOOST_UBLAS_INLINE
    00295         matrix& operator /= (const AT &at) {
    00296             matrix_assign_scalar<scalar_divides_assign> (*this, at);
    00297             return *this;
    00298         }
    00299
    00300         // Swapping
    00301         BOOST_UBLAS_INLINE
    00302         void swap (matrix &m) {
    00303             if (this != &m) {
    00304                 std::swap (size1_, m.size1_);
    00305                 std::swap (size2_, m.size2_);
    00306                 data ().swap (m.data ());
    00307             }
    00308         }
    00309         BOOST_UBLAS_INLINE
    00310         friend void swap (matrix &m1, matrix &m2) {
    00311             m1.swap (m2);
    00312         }
    00313
    00314         // Iterator types
    00315     private:
    00316         // Use the storage array iterator
    00317         typedef typename A::const_iterator const_subiterator_type;
    00318         typedef typename A::iterator subiterator_type;
    00319
    00320     public:
    00321 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00322         typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
    00323         typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
    00324         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
    00325         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
    00326 #else
    00327         class const_iterator1;
    00328         class iterator1;
    00329         class const_iterator2;
    00330         class iterator2;
    00331 #endif
    00332         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    00333         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
    00334         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    00335         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
    00336
    00337         // Element lookup
    00338         BOOST_UBLAS_INLINE
    00339         const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
    00340 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00341             return const_iterator1 (*this, i, j);
    00342 #else
    00343             return const_iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
    00344 #endif
    00345         }
    00346         BOOST_UBLAS_INLINE
    00347         iterator1 find1 (int /* rank */, size_type i, size_type j) {
    00348 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00349             return iterator1 (*this, i, j);
    00350 #else
    00351             return iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
    00352 #endif
    00353         }
    00354         BOOST_UBLAS_INLINE
    00355         const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
    00356 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00357             return const_iterator2 (*this, i, j);
    00358 #else
    00359             return const_iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
    00360 #endif
    00361         }
    00362         BOOST_UBLAS_INLINE
    00363         iterator2 find2 (int /* rank */, size_type i, size_type j) {
    00364 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00365             return iterator2 (*this, i, j);
    00366 #else
    00367             return iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
    00368 #endif
    00369         }
    00370
    00371
    00372 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00373         class const_iterator1:
    00374             public container_const_reference<matrix>,
    00375             public random_access_iterator_base<dense_random_access_iterator_tag,
    00376                                                const_iterator1, value_type> {
    00377         public:
    00378             typedef typename matrix::value_type value_type;
    00379             typedef typename matrix::difference_type difference_type;
    00380             typedef typename matrix::const_reference reference;
    00381             typedef const typename matrix::pointer pointer;
    00382
    00383             typedef const_iterator2 dual_iterator_type;
    00384             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    00385
    00386             // Construction and destruction
    00387             BOOST_UBLAS_INLINE
    00388             const_iterator1 ():
    00389                 container_const_reference<self_type> (), it_ () {}
    00390             BOOST_UBLAS_INLINE
    00391             const_iterator1 (const self_type &m, const const_subiterator_type &it):
    00392                 container_const_reference<self_type> (m), it_ (it) {}
    00393             BOOST_UBLAS_INLINE
    00394             const_iterator1 (const iterator1 &it):
    00395                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
    00396
    00397             // Arithmetic
    00398             BOOST_UBLAS_INLINE
    00399             const_iterator1 &operator ++ () {
    00400                 layout_type::increment_i (it_, (*this) ().size1 (), (*this) ().size2 ());
    00401                 return *this;
    00402             }
    00403             BOOST_UBLAS_INLINE
    00404             const_iterator1 &operator -- () {
    00405                 layout_type::decrement_i (it_, (*this) ().size1 (), (*this) ().size2 ());
    00406                 return *this;
    00407             }
    00408             BOOST_UBLAS_INLINE
    00409             const_iterator1 &operator += (difference_type n) {
    00410                 layout_type::increment_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
    00411                 return *this;
    00412             }
    00413             BOOST_UBLAS_INLINE
    00414             const_iterator1 &operator -= (difference_type n) {
    00415                 layout_type::decrement_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
    00416                 return *this;
    00417             }
    00418             BOOST_UBLAS_INLINE
    00419             difference_type operator - (const const_iterator1 &it) const {
    00420                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00421                 return layout_type::distance_i (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
    00422             }
    00423
    00424             // Dereference
    00425             BOOST_UBLAS_INLINE
    00426             const_reference operator * () const {
    00427                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    00428                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    00429                 return *it_;
    00430             }
    00431             BOOST_UBLAS_INLINE
    00432             const_reference operator [] (difference_type n) const {
    00433                 return *(*this + n);
    00434             }
    00435
    00436 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00437             BOOST_UBLAS_INLINE
    00438 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00439             typename self_type::
    00440 #endif
    00441             const_iterator2 begin () const {
    00442                 const self_type &m = (*this) ();
    00443                 return m.find2 (1, index1 (), 0);
    00444             }
    00445             BOOST_UBLAS_INLINE
    00446 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00447             typename self_type::
    00448 #endif
    00449             const_iterator2 end () const {
    00450                 const self_type &m = (*this) ();
    00451                 return m.find2 (1, index1 (), m.size2 ());
    00452             }
    00453             BOOST_UBLAS_INLINE
    00454 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00455             typename self_type::
    00456 #endif
    00457             const_reverse_iterator2 rbegin () const {
    00458                 return const_reverse_iterator2 (end ());
    00459             }
    00460             BOOST_UBLAS_INLINE
    00461 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00462             typename self_type::
    00463 #endif
    00464             const_reverse_iterator2 rend () const {
    00465                 return const_reverse_iterator2 (begin ());
    00466             }
    00467 #endif
    00468
    00469             // Indices
    00470             BOOST_UBLAS_INLINE
    00471             size_type index1 () const {
    00472                 const self_type &m = (*this) ();
    00473                 return layout_type::index_i (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
    00474             }
    00475             BOOST_UBLAS_INLINE
    00476             size_type index2 () const {
    00477                 const self_type &m = (*this) ();
    00478                 return layout_type::index_j (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
    00479             }
    00480
    00481             // Assignment
    00482             BOOST_UBLAS_INLINE
    00483             const_iterator1 &operator = (const const_iterator1 &it) {
    00484                 container_const_reference<self_type>::assign (&it ());
    00485                 it_ = it.it_;
    00486                 return *this;
    00487             }
    00488
    00489             // Comparison
    00490             BOOST_UBLAS_INLINE
    00491             bool operator == (const const_iterator1 &it) const {
    00492                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00493                 return it_ == it.it_;
    00494             }
    00495             BOOST_UBLAS_INLINE
    00496             bool operator < (const const_iterator1 &it) const {
    00497                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00498                 return it_ < it.it_;
    00499             }
    00500
    00501         private:
    00502             const_subiterator_type it_;
    00503
    00504             friend class iterator1;
    00505         };
    00506 #endif
    00507
    00508         BOOST_UBLAS_INLINE
    00509         const_iterator1 begin1 () const {
    00510             return find1 (0, 0, 0);
    00511         }
    00512         BOOST_UBLAS_INLINE
    00513         const_iterator1 end1 () const {
    00514             return find1 (0, size1_, 0);
    00515         }
    00516
    00517 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00518         class iterator1:
    00519             public container_reference<matrix>,
    00520             public random_access_iterator_base<dense_random_access_iterator_tag,
    00521                                                iterator1, value_type> {
    00522         public:
    00523             typedef typename matrix::value_type value_type;
    00524             typedef typename matrix::difference_type difference_type;
    00525             typedef typename matrix::reference reference;
    00526             typedef typename matrix::pointer pointer;
    00527
    00528             typedef iterator2 dual_iterator_type;
    00529             typedef reverse_iterator2 dual_reverse_iterator_type;
    00530
    00531             // Construction and destruction
    00532             BOOST_UBLAS_INLINE
    00533             iterator1 ():
    00534                 container_reference<self_type> (), it_ () {}
    00535             BOOST_UBLAS_INLINE
    00536             iterator1 (self_type &m, const subiterator_type &it):
    00537                 container_reference<self_type> (m), it_ (it) {}
    00538
    00539             // Arithmetic
    00540             BOOST_UBLAS_INLINE
    00541             iterator1 &operator ++ () {
    00542                 layout_type::increment_i (it_, (*this) ().size1 (), (*this) ().size2 ());
    00543                 return *this;
    00544             }
    00545             BOOST_UBLAS_INLINE
    00546             iterator1 &operator -- () {
    00547                 layout_type::decrement_i (it_, (*this) ().size1 (), (*this) ().size2 ());
    00548                 return *this;
    00549             }
    00550             BOOST_UBLAS_INLINE
    00551             iterator1 &operator += (difference_type n) {
    00552                 layout_type::increment_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
    00553                 return *this;
    00554             }
    00555             BOOST_UBLAS_INLINE
    00556             iterator1 &operator -= (difference_type n) {
    00557                 layout_type::decrement_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
    00558                 return *this;
    00559             }
    00560             BOOST_UBLAS_INLINE
    00561             difference_type operator - (const iterator1 &it) const {
    00562                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00563                 return layout_type::distance_i (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
    00564             }
    00565
    00566             // Dereference
    00567             BOOST_UBLAS_INLINE
    00568             reference operator * () const {
    00569                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    00570                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    00571                 return *it_;
    00572             }
    00573             BOOST_UBLAS_INLINE
    00574             reference operator [] (difference_type n) const {
    00575                 return *(*this + n);
    00576             }
    00577
    00578 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00579             BOOST_UBLAS_INLINE
    00580 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00581             typename self_type::
    00582 #endif
    00583             iterator2 begin () const {
    00584                 self_type &m = (*this) ();
    00585                 return m.find2 (1, index1 (), 0);
    00586             }
    00587             BOOST_UBLAS_INLINE
    00588 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00589             typename self_type::
    00590 #endif
    00591             iterator2 end () const {
    00592                 self_type &m = (*this) ();
    00593                 return m.find2 (1, index1 (), m.size2 ());
    00594             }
    00595             BOOST_UBLAS_INLINE
    00596 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00597             typename self_type::
    00598 #endif
    00599             reverse_iterator2 rbegin () const {
    00600                 return reverse_iterator2 (end ());
    00601             }
    00602             BOOST_UBLAS_INLINE
    00603 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00604             typename self_type::
    00605 #endif
    00606             reverse_iterator2 rend () const {
    00607                 return reverse_iterator2 (begin ());
    00608             }
    00609 #endif
    00610
    00611             // Indices
    00612             BOOST_UBLAS_INLINE
    00613             size_type index1 () const {
    00614                 self_type &m = (*this) ();
    00615                 return layout_type::index_i (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
    00616             }
    00617             BOOST_UBLAS_INLINE
    00618             size_type index2 () const {
    00619                 self_type &m = (*this) ();
    00620                 return layout_type::index_j (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
    00621             }
    00622
    00623             // Assignment
    00624             BOOST_UBLAS_INLINE
    00625             iterator1 &operator = (const iterator1 &it) {
    00626                 container_reference<self_type>::assign (&it ());
    00627                 it_ = it.it_;
    00628                 return *this;
    00629             }
    00630
    00631             // Comparison
    00632             BOOST_UBLAS_INLINE
    00633             bool operator == (const iterator1 &it) const {
    00634                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00635                 return it_ == it.it_;
    00636             }
    00637             BOOST_UBLAS_INLINE
    00638             bool operator < (const iterator1 &it) const {
    00639                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00640                 return it_ < it.it_;
    00641             }
    00642
    00643         private:
    00644             subiterator_type it_;
    00645
    00646             friend class const_iterator1;
    00647         };
    00648 #endif
    00649
    00650         BOOST_UBLAS_INLINE
    00651         iterator1 begin1 () {
    00652             return find1 (0, 0, 0);
    00653         }
    00654         BOOST_UBLAS_INLINE
    00655         iterator1 end1 () {
    00656             return find1 (0, size1_, 0);
    00657         }
    00658
    00659 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00660         class const_iterator2:
    00661             public container_const_reference<matrix>,
    00662             public random_access_iterator_base<dense_random_access_iterator_tag,
    00663                                                const_iterator2, value_type> {
    00664         public:
    00665             typedef typename matrix::value_type value_type;
    00666             typedef typename matrix::difference_type difference_type;
    00667             typedef typename matrix::const_reference reference;
    00668             typedef const typename matrix::pointer pointer;
    00669
    00670             typedef const_iterator1 dual_iterator_type;
    00671             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    00672
    00673             // Construction and destruction
    00674             BOOST_UBLAS_INLINE
    00675             const_iterator2 ():
    00676                 container_const_reference<self_type> (), it_ () {}
    00677             BOOST_UBLAS_INLINE
    00678             const_iterator2 (const self_type &m, const const_subiterator_type &it):
    00679                 container_const_reference<self_type> (m), it_ (it) {}
    00680             BOOST_UBLAS_INLINE
    00681             const_iterator2 (const iterator2 &it):
    00682                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
    00683
    00684             // Arithmetic
    00685             BOOST_UBLAS_INLINE
    00686             const_iterator2 &operator ++ () {
    00687                 layout_type::increment_j (it_, (*this) ().size1 (), (*this) ().size2 ());
    00688                 return *this;
    00689             }
    00690             BOOST_UBLAS_INLINE
    00691             const_iterator2 &operator -- () {
    00692                 layout_type::decrement_j (it_, (*this) ().size1 (), (*this) ().size2 ());
    00693                 return *this;
    00694             }
    00695             BOOST_UBLAS_INLINE
    00696             const_iterator2 &operator += (difference_type n) {
    00697                 layout_type::increment_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
    00698                 return *this;
    00699             }
    00700             BOOST_UBLAS_INLINE
    00701             const_iterator2 &operator -= (difference_type n) {
    00702                 layout_type::decrement_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
    00703                 return *this;
    00704             }
    00705             BOOST_UBLAS_INLINE
    00706             difference_type operator - (const const_iterator2 &it) const {
    00707                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00708                 return layout_type::distance_j (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
    00709             }
    00710
    00711             // Dereference
    00712             BOOST_UBLAS_INLINE
    00713             const_reference operator * () const {
    00714                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    00715                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    00716                 return *it_;
    00717             }
    00718             BOOST_UBLAS_INLINE
    00719             const_reference operator [] (difference_type n) const {
    00720                 return *(*this + n);
    00721             }
    00722
    00723 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00724             BOOST_UBLAS_INLINE
    00725 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00726             typename self_type::
    00727 #endif
    00728             const_iterator1 begin () const {
    00729                 const self_type &m = (*this) ();
    00730                 return m.find1 (1, 0, index2 ());
    00731             }
    00732             BOOST_UBLAS_INLINE
    00733 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00734             typename self_type::
    00735 #endif
    00736             const_iterator1 end () const {
    00737                 const self_type &m = (*this) ();
    00738                 return m.find1 (1, m.size1 (), index2 ());
    00739             }
    00740             BOOST_UBLAS_INLINE
    00741 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00742             typename self_type::
    00743 #endif
    00744             const_reverse_iterator1 rbegin () const {
    00745                 return const_reverse_iterator1 (end ());
    00746             }
    00747             BOOST_UBLAS_INLINE
    00748 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00749             typename self_type::
    00750 #endif
    00751             const_reverse_iterator1 rend () const {
    00752                 return const_reverse_iterator1 (begin ());
    00753             }
    00754 #endif
    00755
    00756             // Indices
    00757             BOOST_UBLAS_INLINE
    00758             size_type index1 () const {
    00759                 const self_type &m = (*this) ();
    00760                 return layout_type::index_i (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
    00761             }
    00762             BOOST_UBLAS_INLINE
    00763             size_type index2 () const {
    00764                 const self_type &m = (*this) ();
    00765                 return layout_type::index_j (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
    00766             }
    00767
    00768             // Assignment
    00769             BOOST_UBLAS_INLINE
    00770             const_iterator2 &operator = (const const_iterator2 &it) {
    00771                 container_const_reference<self_type>::assign (&it ());
    00772                 it_ = it.it_;
    00773                 return *this;
    00774             }
    00775
    00776             // Comparison
    00777             BOOST_UBLAS_INLINE
    00778             bool operator == (const const_iterator2 &it) const {
    00779                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00780                 return it_ == it.it_;
    00781             }
    00782             BOOST_UBLAS_INLINE
    00783             bool operator < (const const_iterator2 &it) const {
    00784                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00785                 return it_ < it.it_;
    00786             }
    00787
    00788         private:
    00789             const_subiterator_type it_;
    00790
    00791             friend class iterator2;
    00792         };
    00793 #endif
    00794
    00795         BOOST_UBLAS_INLINE
    00796         const_iterator2 begin2 () const {
    00797             return find2 (0, 0, 0);
    00798         }
    00799         BOOST_UBLAS_INLINE
    00800         const_iterator2 end2 () const {
    00801             return find2 (0, 0, size2_);
    00802         }
    00803
    00804 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00805         class iterator2:
    00806             public container_reference<matrix>,
    00807             public random_access_iterator_base<dense_random_access_iterator_tag,
    00808                                                iterator2, value_type> {
    00809         public:
    00810             typedef typename matrix::value_type value_type;
    00811             typedef typename matrix::difference_type difference_type;
    00812             typedef typename matrix::reference reference;
    00813             typedef typename matrix::pointer pointer;
    00814
    00815             typedef iterator1 dual_iterator_type;
    00816             typedef reverse_iterator1 dual_reverse_iterator_type;
    00817
    00818             // Construction and destruction
    00819             BOOST_UBLAS_INLINE
    00820             iterator2 ():
    00821                 container_reference<self_type> (), it_ () {}
    00822             BOOST_UBLAS_INLINE
    00823             iterator2 (self_type &m, const subiterator_type &it):
    00824                 container_reference<self_type> (m), it_ (it) {}
    00825
    00826             // Arithmetic
    00827             BOOST_UBLAS_INLINE
    00828             iterator2 &operator ++ () {
    00829                 layout_type::increment_j (it_, (*this) ().size1 (), (*this) ().size2 ());
    00830                 return *this;
    00831             }
    00832             BOOST_UBLAS_INLINE
    00833             iterator2 &operator -- () {
    00834                 layout_type::decrement_j (it_, (*this) ().size1 (), (*this) ().size2 ());
    00835                 return *this;
    00836             }
    00837             BOOST_UBLAS_INLINE
    00838             iterator2 &operator += (difference_type n) {
    00839                 layout_type::increment_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
    00840                 return *this;
    00841             }
    00842             BOOST_UBLAS_INLINE
    00843             iterator2 &operator -= (difference_type n) {
    00844                 layout_type::decrement_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
    00845                 return *this;
    00846             }
    00847             BOOST_UBLAS_INLINE
    00848             difference_type operator - (const iterator2 &it) const {
    00849                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00850                 return layout_type::distance_j (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
    00851             }
    00852
    00853             // Dereference
    00854             BOOST_UBLAS_INLINE
    00855             reference operator * () const {
    00856                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    00857                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    00858                 return *it_;
    00859             }
    00860             BOOST_UBLAS_INLINE
    00861             reference operator [] (difference_type n) const {
    00862                 return *(*this + n);
    00863             }
    00864
    00865 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00866             BOOST_UBLAS_INLINE
    00867 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00868             typename self_type::
    00869 #endif
    00870             iterator1 begin () const {
    00871                 self_type &m = (*this) ();
    00872                 return m.find1 (1, 0, index2 ());
    00873             }
    00874             BOOST_UBLAS_INLINE
    00875 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00876             typename self_type::
    00877 #endif
    00878             iterator1 end () const {
    00879                 self_type &m = (*this) ();
    00880                 return m.find1 (1, m.size1 (), index2 ());
    00881             }
    00882             BOOST_UBLAS_INLINE
    00883 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00884             typename self_type::
    00885 #endif
    00886             reverse_iterator1 rbegin () const {
    00887                 return reverse_iterator1 (end ());
    00888             }
    00889             BOOST_UBLAS_INLINE
    00890 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00891             typename self_type::
    00892 #endif
    00893             reverse_iterator1 rend () const {
    00894                 return reverse_iterator1 (begin ());
    00895             }
    00896 #endif
    00897
    00898             // Indices
    00899             BOOST_UBLAS_INLINE
    00900             size_type index1 () const {
    00901                 self_type &m = (*this) ();
    00902                 return layout_type::index_i (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
    00903             }
    00904             BOOST_UBLAS_INLINE
    00905             size_type index2 () const {
    00906                 self_type &m = (*this) ();
    00907                 return layout_type::index_j (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
    00908             }
    00909
    00910             // Assignment
    00911             BOOST_UBLAS_INLINE
    00912             iterator2 &operator = (const iterator2 &it) {
    00913                 container_reference<self_type>::assign (&it ());
    00914                 it_ = it.it_;
    00915                 return *this;
    00916             }
    00917
    00918             // Comparison
    00919             BOOST_UBLAS_INLINE
    00920             bool operator == (const iterator2 &it) const {
    00921                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00922                 return it_ == it.it_;
    00923             }
    00924             BOOST_UBLAS_INLINE
    00925             bool operator < (const iterator2 &it) const {
    00926                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    00927                 return it_ < it.it_;
    00928             }
    00929
    00930         private:
    00931             subiterator_type it_;
    00932
    00933             friend class const_iterator2;
    00934         };
    00935 #endif
    00936
    00937         BOOST_UBLAS_INLINE
    00938         iterator2 begin2 () {
    00939             return find2 (0, 0, 0);
    00940         }
    00941         BOOST_UBLAS_INLINE
    00942         iterator2 end2 () {
    00943             return find2 (0, 0, size2_);
    00944         }
    00945
    00946         // Reverse iterators
    00947
    00948         BOOST_UBLAS_INLINE
    00949         const_reverse_iterator1 rbegin1 () const {
    00950             return const_reverse_iterator1 (end1 ());
    00951         }
    00952         BOOST_UBLAS_INLINE
    00953         const_reverse_iterator1 rend1 () const {
    00954             return const_reverse_iterator1 (begin1 ());
    00955         }
    00956
    00957         BOOST_UBLAS_INLINE
    00958         reverse_iterator1 rbegin1 () {
    00959             return reverse_iterator1 (end1 ());
    00960         }
    00961         BOOST_UBLAS_INLINE
    00962         reverse_iterator1 rend1 () {
    00963             return reverse_iterator1 (begin1 ());
    00964         }
    00965
    00966         BOOST_UBLAS_INLINE
    00967         const_reverse_iterator2 rbegin2 () const {
    00968             return const_reverse_iterator2 (end2 ());
    00969         }
    00970         BOOST_UBLAS_INLINE
    00971         const_reverse_iterator2 rend2 () const {
    00972             return const_reverse_iterator2 (begin2 ());
    00973         }
    00974
    00975         BOOST_UBLAS_INLINE
    00976         reverse_iterator2 rbegin2 () {
    00977             return reverse_iterator2 (end2 ());
    00978         }
    00979         BOOST_UBLAS_INLINE
    00980         reverse_iterator2 rend2 () {
    00981             return reverse_iterator2 (begin2 ());
    00982         }
    00983
    00984         // Serialization
    00985         template<class Archive>
    00986         void serialize(Archive & ar, const unsigned int /* file_version */){
    00987
    00988             // we need to copy to a collection_size_type to get a portable
    00989             // and efficient serialization
    00990             serialization::collection_size_type s1 (size1_);
    00991             serialization::collection_size_type s2 (size2_);
    00992
    00993             // serialize the sizes
    00994             ar & serialization::make_nvp("size1",s1)
    00995                & serialization::make_nvp("size2",s2);
    00996
    00997             // copy the values back if loading
    00998             if (Archive::is_loading::value) {
    00999                 size1_ = s1;
    01000                 size2_ = s2;
    01001             }
    01002             ar & serialization::make_nvp("data",data_);
    01003         }
    01004
    01005     private:
    01006         size_type size1_;
    01007         size_type size2_;
    01008         array_type data_;
    01009     };
    01010
    01027     template<class T, std::size_t M, std::size_t N, class L>
    01028     class bounded_matrix:
    01029         public matrix<T, L, bounded_array<T, M * N> > {
    01030
    01031         typedef matrix<T, L, bounded_array<T, M * N> > matrix_type;
    01032     public:
    01033         typedef typename matrix_type::size_type size_type;
    01034         static const size_type max_size1 = M;
    01035         static const size_type max_size2 = N;
    01036
    01037         // Construction and destruction
    01038         BOOST_UBLAS_INLINE
    01039         bounded_matrix ():
    01040             matrix_type (M, N) {}
    01041         BOOST_UBLAS_INLINE
    01042         bounded_matrix (size_type size1, size_type size2):
    01043             matrix_type (size1, size2) {}
    01044         BOOST_UBLAS_INLINE
    01045         bounded_matrix (const bounded_matrix &m):
    01046             matrix_type (m) {}
    01047         template<class A2>              // Allow matrix<T, L, bounded_array<M,N> > construction
    01048         BOOST_UBLAS_INLINE
    01049         bounded_matrix (const matrix<T, L, A2> &m):
    01050             matrix_type (m) {}
    01051         template<class AE>
    01052         BOOST_UBLAS_INLINE
    01053         bounded_matrix (const matrix_expression<AE> &ae):
    01054             matrix_type (ae) {}
    01055         BOOST_UBLAS_INLINE
    01056         ~bounded_matrix () {}
    01057
    01058         // Assignment
    01059 #ifdef BOOST_UBLAS_MOVE_SEMANTICS
    01060
    01062         BOOST_UBLAS_INLINE
    01063         bounded_matrix &operator = (bounded_matrix m) {
    01064             matrix_type::operator = (m);
    01065             return *this;
    01066         }
    01067 #else
    01068         BOOST_UBLAS_INLINE
    01069         bounded_matrix &operator = (const bounded_matrix &m) {
    01070             matrix_type::operator = (m);
    01071             return *this;
    01072         }
    01073 #endif
    01074         template<class L2, class A2>        // Generic matrix assignment
    01075         BOOST_UBLAS_INLINE
    01076         bounded_matrix &operator = (const matrix<T, L2, A2> &m) {
    01077             matrix_type::operator = (m);
    01078             return *this;
    01079         }
    01080         template<class C>          // Container assignment without temporary
    01081         BOOST_UBLAS_INLINE
    01082         bounded_matrix &operator = (const matrix_container<C> &m) {
    01083             matrix_type::operator = (m);
    01084             return *this;
    01085         }
    01086         template<class AE>
    01087         BOOST_UBLAS_INLINE
    01088         bounded_matrix &operator = (const matrix_expression<AE> &ae) {
    01089             matrix_type::operator = (ae);
    01090             return *this;
    01091         }
    01092     };
    01093
    01109     template<class T, class L, class A>
    01110     class vector_of_vector:
    01111         public matrix_container<vector_of_vector<T, L, A> > {
    01112
    01113         typedef T *pointer;
    01114         typedef L layout_type;
    01115         typedef vector_of_vector<T, L, A> self_type;
    01116     public:
    01117 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    01118         using matrix_container<self_type>::operator ();
    01119 #endif
    01120         typedef typename A::size_type size_type;
    01121         typedef typename A::difference_type difference_type;
    01122         typedef T value_type;
    01123         typedef const T &const_reference;
    01124         typedef T &reference;
    01125         typedef A array_type;
    01126         typedef const matrix_reference<const self_type> const_closure_type;
    01127         typedef matrix_reference<self_type> closure_type;
    01128         typedef vector<T, typename A::value_type> vector_temporary_type;
    01129         typedef self_type matrix_temporary_type;
    01130         typedef dense_tag storage_category;
    01131         // This could be better for performance,
    01132         // typedef typename unknown_orientation_tag orientation_category;
    01133         // but others depend on the orientation information...
    01134         typedef typename L::orientation_category orientation_category;
    01135
    01136         // Construction and destruction
    01137         BOOST_UBLAS_INLINE
    01138         vector_of_vector ():
    01139             matrix_container<self_type> (),
    01140             size1_ (0), size2_ (0), data_ (1) {}
    01141         BOOST_UBLAS_INLINE
    01142         vector_of_vector (size_type size1, size_type size2):
    01143             matrix_container<self_type> (),
    01144             size1_ (size1), size2_ (size2), data_ (1) {
    01145             resize (size1, size2, true);
    01146         }
    01147         BOOST_UBLAS_INLINE
    01148         vector_of_vector (const vector_of_vector &m):
    01149             matrix_container<self_type> (),
    01150             size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
    01151         template<class AE>
    01152         BOOST_UBLAS_INLINE
    01153         vector_of_vector (const matrix_expression<AE> &ae):
    01154             matrix_container<self_type> (),
    01155             size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size_M (size1_, size2_) + 1) {
    01156             for (size_type k = 0; k < layout_type::size_M (size1_, size2_); ++ k)
    01157                 data ()[k].resize (layout_type::size_m (size1_, size2_));
    01158             matrix_assign<scalar_assign> (*this, ae);
    01159         }
    01160
    01161         // Accessors
    01162         BOOST_UBLAS_INLINE
    01163         size_type size1 () const {
    01164             return size1_;
    01165         }
    01166         BOOST_UBLAS_INLINE
    01167         size_type size2 () const {
    01168             return size2_;
    01169         }
    01170
    01171         // Storage accessors
    01172         BOOST_UBLAS_INLINE
    01173         const array_type &data () const {
    01174             return data_;
    01175         }
    01176         BOOST_UBLAS_INLINE
    01177         array_type &data () {
    01178             return data_;
    01179         }
    01180
    01181         // Resizing
    01182         BOOST_UBLAS_INLINE
    01183         void resize (size_type size1, size_type size2, bool preserve = true) {
    01184             size1_ = size1;
    01185             size2_ = size2;
    01186             if (preserve)
    01187                 data ().resize (layout_type::size_M (size1, size2) + 1, typename array_type::value_type ());
    01188             else
    01189                 data ().resize (layout_type::size_M (size1, size2) + 1);
    01190             for (size_type k = 0; k < layout_type::size_M (size1, size2); ++ k) {
    01191                 if (preserve)
    01192                     data () [k].resize (layout_type::size_m (size1, size2), value_type ());
    01193                 else
    01194                     data () [k].resize (layout_type::size_m (size1, size2));
    01195             }
    01196         }
    01197
    01198         // Element access
    01199         BOOST_UBLAS_INLINE
    01200         const_reference operator () (size_type i, size_type j) const {
    01201             return data () [layout_type::index_M (i, j)] [layout_type::index_m (i, j)];
    01202         }
    01203         BOOST_UBLAS_INLINE
    01204         reference at_element (size_type i, size_type j) {
    01205             return data () [layout_type::index_M (i, j)] [layout_type::index_m (i, j)];
    01206         }
    01207         BOOST_UBLAS_INLINE
    01208         reference operator () (size_type i, size_type j) {
    01209             return at_element (i, j);
    01210         }
    01211
    01212         // Element assignment
    01213         BOOST_UBLAS_INLINE
    01214         reference insert_element (size_type i, size_type j, const_reference t) {
    01215             return (at_element (i, j) = t);
    01216         }
    01217         BOOST_UBLAS_INLINE
    01218         void erase_element (size_type i, size_type j) {
    01219             at_element (i, j) = value_type/*zero*/();
    01220         }
    01221
    01222         // Zeroing
    01223         BOOST_UBLAS_INLINE
    01224         void clear () {
    01225             for (size_type k = 0; k < layout_type::size_M (size1_, size2_); ++ k)
    01226                 std::fill (data () [k].begin (), data () [k].end (), value_type/*zero*/());
    01227         }
    01228
    01229         // Assignment
    01230         BOOST_UBLAS_INLINE
    01231         vector_of_vector &operator = (const vector_of_vector &m) {
    01232             size1_ = m.size1_;
    01233             size2_ = m.size2_;
    01234             data () = m.data ();
    01235             return *this;
    01236         }
    01237         BOOST_UBLAS_INLINE
    01238         vector_of_vector &assign_temporary (vector_of_vector &m) {
    01239             swap (m);
    01240             return *this;
    01241         }
    01242         template<class AE>
    01243         BOOST_UBLAS_INLINE
    01244         vector_of_vector &operator = (const matrix_expression<AE> &ae) {
    01245             self_type temporary (ae);
    01246             return assign_temporary (temporary);
    01247         }
    01248         template<class C>          // Container assignment without temporary
    01249         BOOST_UBLAS_INLINE
    01250         vector_of_vector &operator = (const matrix_container<C> &m) {
    01251             resize (m ().size1 (), m ().size2 (), false);
    01252             assign (m);
    01253             return *this;
    01254         }
    01255         template<class AE>
    01256         BOOST_UBLAS_INLINE
    01257         vector_of_vector &assign (const matrix_expression<AE> &ae) {
    01258             matrix_assign<scalar_assign> (*this, ae);
    01259             return *this;
    01260         }
    01261         template<class AE>
    01262         BOOST_UBLAS_INLINE
    01263         vector_of_vector& operator += (const matrix_expression<AE> &ae) {
    01264             self_type temporary (*this + ae);
    01265             return assign_temporary (temporary);
    01266         }
    01267         template<class C>          // Container assignment without temporary
    01268         BOOST_UBLAS_INLINE
    01269         vector_of_vector &operator += (const matrix_container<C> &m) {
    01270             plus_assign (m);
    01271             return *this;
    01272         }
    01273         template<class AE>
    01274         BOOST_UBLAS_INLINE
    01275         vector_of_vector &plus_assign (const matrix_expression<AE> &ae) {
    01276             matrix_assign<scalar_plus_assign> (*this, ae);
    01277             return *this;
    01278         }
    01279         template<class AE>
    01280         BOOST_UBLAS_INLINE
    01281         vector_of_vector& operator -= (const matrix_expression<AE> &ae) {
    01282             self_type temporary (*this - ae);
    01283             return assign_temporary (temporary);
    01284         }
    01285         template<class C>          // Container assignment without temporary
    01286         BOOST_UBLAS_INLINE
    01287         vector_of_vector &operator -= (const matrix_container<C> &m) {
    01288             minus_assign (m);
    01289             return *this;
    01290         }
    01291         template<class AE>
    01292         BOOST_UBLAS_INLINE
    01293         vector_of_vector &minus_assign (const matrix_expression<AE> &ae) {
    01294             matrix_assign<scalar_minus_assign> (*this, ae);
    01295             return *this;
    01296         }
    01297         template<class AT>
    01298         BOOST_UBLAS_INLINE
    01299         vector_of_vector& operator *= (const AT &at) {
    01300             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
    01301             return *this;
    01302         }
    01303         template<class AT>
    01304         BOOST_UBLAS_INLINE
    01305         vector_of_vector& operator /= (const AT &at) {
    01306             matrix_assign_scalar<scalar_divides_assign> (*this, at);
    01307             return *this;
    01308         }
    01309
    01310         // Swapping
    01311         BOOST_UBLAS_INLINE
    01312         void swap (vector_of_vector &m) {
    01313             if (this != &m) {
    01314                 std::swap (size1_, m.size1_);
    01315                 std::swap (size2_, m.size2_);
    01316                 data ().swap (m.data ());
    01317             }
    01318         }
    01319         BOOST_UBLAS_INLINE
    01320         friend void swap (vector_of_vector &m1, vector_of_vector &m2) {
    01321             m1.swap (m2);
    01322         }
    01323
    01324         // Iterator types
    01325     private:
    01326         // Use the vector iterator
    01327         typedef typename A::value_type::const_iterator const_subiterator_type;
    01328         typedef typename A::value_type::iterator subiterator_type;
    01329     public:
    01330 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01331         typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
    01332         typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
    01333         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
    01334         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
    01335 #else
    01336         class const_iterator1;
    01337         class iterator1;
    01338         class const_iterator2;
    01339         class iterator2;
    01340 #endif
    01341         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    01342         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
    01343         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    01344         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
    01345
    01346         // Element lookup
    01347         BOOST_UBLAS_INLINE
    01348         const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
    01349 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01350             return const_iterator1 (*this, i, j);
    01351 #else
    01352             return const_iterator1 (*this, i, j, data () [layout_type::index_M (i, j)].begin ()  + layout_type::index_m (i, j));
    01353 #endif
    01354         }
    01355         BOOST_UBLAS_INLINE
    01356         iterator1 find1 (int /*rank*/, size_type i, size_type j) {
    01357 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01358             return iterator1 (*this, i, j);
    01359 #else
    01360             return iterator1 (*this, i, j, data () [layout_type::index_M (i, j)].begin ()  + layout_type::index_m (i, j));
    01361 #endif
    01362         }
    01363         BOOST_UBLAS_INLINE
    01364         const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
    01365 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01366             return const_iterator2 (*this, i, j);
    01367 #else
    01368             return const_iterator2 (*this, i, j, data () [layout_type::index_M (i, j)].begin ()  + layout_type::index_m (i, j));
    01369 #endif
    01370         }
    01371         BOOST_UBLAS_INLINE
    01372         iterator2 find2 (int /*rank*/, size_type i, size_type j) {
    01373 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01374             return iterator2 (*this, i, j);
    01375 #else
    01376             return iterator2 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j));
    01377 #endif
    01378         }
    01379
    01380
    01381 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01382         class const_iterator1:
    01383             public container_const_reference<vector_of_vector>,
    01384             public random_access_iterator_base<dense_random_access_iterator_tag,
    01385                                                const_iterator1, value_type> {
    01386         public:
    01387             typedef typename vector_of_vector::value_type value_type;
    01388             typedef typename vector_of_vector::difference_type difference_type;
    01389             typedef typename vector_of_vector::const_reference reference;
    01390             typedef const typename vector_of_vector::pointer pointer;
    01391
    01392             typedef const_iterator2 dual_iterator_type;
    01393             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    01394
    01395             // Construction and destruction
    01396             BOOST_UBLAS_INLINE
    01397             const_iterator1 ():
    01398                 container_const_reference<self_type> (), i_ (), j_ (), it_ () {}
    01399             BOOST_UBLAS_INLINE
    01400             const_iterator1 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it):
    01401                 container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
    01402             BOOST_UBLAS_INLINE
    01403             const_iterator1 (const iterator1 &it):
    01404                 container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
    01405
    01406             // Arithmetic
    01407             BOOST_UBLAS_INLINE
    01408             const_iterator1 &operator ++ () {
    01409                 ++ i_;
    01410                 const self_type &m = (*this) ();
    01411                 if (layout_type::fast_i ())
    01412                     ++ it_;
    01413                 else
    01414                     it_ = m.find1 (1, i_, j_).it_;
    01415                 return *this;
    01416             }
    01417             BOOST_UBLAS_INLINE
    01418             const_iterator1 &operator -- () {
    01419                 -- i_;
    01420                 const self_type &m = (*this) ();
    01421                 if (layout_type::fast_i ())
    01422                     -- it_;
    01423                 else
    01424                     it_ = m.find1 (1, i_, j_).it_;
    01425                 return *this;
    01426             }
    01427             BOOST_UBLAS_INLINE
    01428             const_iterator1 &operator += (difference_type n) {
    01429                 i_ += n;
    01430                 const self_type &m = (*this) ();
    01431                 it_ = m.find1 (1, i_, j_).it_;
    01432                 return *this;
    01433             }
    01434             BOOST_UBLAS_INLINE
    01435             const_iterator1 &operator -= (difference_type n) {
    01436                 i_ -= n;
    01437                 const self_type &m = (*this) ();
    01438                 it_ = m.find1 (1, i_, j_).it_;
    01439                 return *this;
    01440             }
    01441             BOOST_UBLAS_INLINE
    01442             difference_type operator - (const const_iterator1 &it) const {
    01443                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01444                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
    01445                 return index1 () - it.index1 ();
    01446             }
    01447
    01448             // Dereference
    01449             BOOST_UBLAS_INLINE
    01450             const_reference operator * () const {
    01451                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    01452                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    01453                 return *it_;
    01454             }
    01455             BOOST_UBLAS_INLINE
    01456             const_reference operator [] (difference_type n) const {
    01457                 return *(*this + n);
    01458             }
    01459
    01460 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    01461             BOOST_UBLAS_INLINE
    01462 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01463             typename self_type::
    01464 #endif
    01465             const_iterator2 begin () const {
    01466                 const self_type &m = (*this) ();
    01467                 return m.find2 (1, index1 (), 0);
    01468             }
    01469             BOOST_UBLAS_INLINE
    01470 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01471             typename self_type::
    01472 #endif
    01473             const_iterator2 end () const {
    01474                 const self_type &m = (*this) ();
    01475                 return m.find2 (1, index1 (), m.size2 ());
    01476             }
    01477             BOOST_UBLAS_INLINE
    01478 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01479             typename self_type::
    01480 #endif
    01481             const_reverse_iterator2 rbegin () const {
    01482                 return const_reverse_iterator2 (end ());
    01483             }
    01484             BOOST_UBLAS_INLINE
    01485 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01486             typename self_type::
    01487 #endif
    01488             const_reverse_iterator2 rend () const {
    01489                 return const_reverse_iterator2 (begin ());
    01490             }
    01491 #endif
    01492
    01493             // Indices
    01494             BOOST_UBLAS_INLINE
    01495             size_type index1 () const {
    01496                 return i_;
    01497             }
    01498             BOOST_UBLAS_INLINE
    01499             size_type index2 () const {
    01500                 return j_;
    01501             }
    01502
    01503             // Assignment
    01504             BOOST_UBLAS_INLINE
    01505             const_iterator1 &operator = (const const_iterator1 &it) {
    01506                 container_const_reference<self_type>::assign (&it ());
    01507                 it_ = it.it_;
    01508                 return *this;
    01509             }
    01510
    01511             // Comparison
    01512             BOOST_UBLAS_INLINE
    01513             bool operator == (const const_iterator1 &it) const {
    01514                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01515                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
    01516                 return it_ == it.it_;
    01517             }
    01518             BOOST_UBLAS_INLINE
    01519             bool operator < (const const_iterator1 &it) const {
    01520                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01521                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
    01522                 return it_ < it.it_;
    01523             }
    01524
    01525         private:
    01526             size_type i_;
    01527             size_type j_;
    01528             const_subiterator_type it_;
    01529
    01530             friend class iterator1;
    01531         };
    01532 #endif
    01533
    01534         BOOST_UBLAS_INLINE
    01535         const_iterator1 begin1 () const {
    01536             return find1 (0, 0, 0);
    01537         }
    01538         BOOST_UBLAS_INLINE
    01539         const_iterator1 end1 () const {
    01540             return find1 (0, size1_, 0);
    01541         }
    01542
    01543 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01544         class iterator1:
    01545             public container_reference<vector_of_vector>,
    01546             public random_access_iterator_base<dense_random_access_iterator_tag,
    01547                                                iterator1, value_type> {
    01548         public:
    01549             typedef typename vector_of_vector::value_type value_type;
    01550             typedef typename vector_of_vector::difference_type difference_type;
    01551             typedef typename vector_of_vector::reference reference;
    01552             typedef typename vector_of_vector::pointer pointer;
    01553
    01554             typedef iterator2 dual_iterator_type;
    01555             typedef reverse_iterator2 dual_reverse_iterator_type;
    01556
    01557             // Construction and destruction
    01558             BOOST_UBLAS_INLINE
    01559             iterator1 ():
    01560                 container_reference<self_type> (), i_ (), j_ (), it_ () {}
    01561             BOOST_UBLAS_INLINE
    01562             iterator1 (self_type &m, size_type i, size_type j, const subiterator_type &it):
    01563                 container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
    01564
    01565             // Arithmetic
    01566             BOOST_UBLAS_INLINE
    01567             iterator1 &operator ++ () {
    01568                 ++ i_;
    01569                 self_type &m = (*this) ();
    01570                 if (layout_type::fast_i ())
    01571                     ++ it_;
    01572                 else
    01573                     it_ = m.find1 (1, i_, j_).it_;
    01574                 return *this;
    01575             }
    01576             BOOST_UBLAS_INLINE
    01577             iterator1 &operator -- () {
    01578                 -- i_;
    01579                 self_type &m = (*this) ();
    01580                 if (layout_type::fast_i ())
    01581                     -- it_;
    01582                 else
    01583                     it_ = m.find1 (1, i_, j_).it_;
    01584                 return *this;
    01585             }
    01586             BOOST_UBLAS_INLINE
    01587             iterator1 &operator += (difference_type n) {
    01588                 i_ += n;
    01589                 self_type &m = (*this) ();
    01590                 it_ = m.find1 (1, i_, j_).it_;
    01591                 return *this;
    01592             }
    01593             BOOST_UBLAS_INLINE
    01594             iterator1 &operator -= (difference_type n) {
    01595                 i_ -= n;
    01596                 self_type &m = (*this) ();
    01597                 it_ = m.find1 (1, i_, j_).it_;
    01598                 return *this;
    01599             }
    01600             BOOST_UBLAS_INLINE
    01601             difference_type operator - (const iterator1 &it) const {
    01602                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01603                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
    01604                 return index1 () - it.index1 ();
    01605             }
    01606
    01607             // Dereference
    01608             BOOST_UBLAS_INLINE
    01609             reference operator * () const {
    01610                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    01611                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    01612                 return *it_;
    01613             }
    01614             BOOST_UBLAS_INLINE
    01615             reference operator [] (difference_type n) const {
    01616                 return *(*this + n);
    01617             }
    01618
    01619 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    01620             BOOST_UBLAS_INLINE
    01621 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01622             typename self_type::
    01623 #endif
    01624             iterator2 begin () const {
    01625                 self_type &m = (*this) ();
    01626                 return m.find2 (1, index1 (), 0);
    01627             }
    01628             BOOST_UBLAS_INLINE
    01629 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01630             typename self_type::
    01631 #endif
    01632             iterator2 end () const {
    01633                 self_type &m = (*this) ();
    01634                 return m.find2 (1, index1 (), m.size2 ());
    01635             }
    01636             BOOST_UBLAS_INLINE
    01637 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01638             typename self_type::
    01639 #endif
    01640             reverse_iterator2 rbegin () const {
    01641                 return reverse_iterator2 (end ());
    01642             }
    01643             BOOST_UBLAS_INLINE
    01644 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01645             typename self_type::
    01646 #endif
    01647             reverse_iterator2 rend () const {
    01648                 return reverse_iterator2 (begin ());
    01649             }
    01650 #endif
    01651
    01652             // Indices
    01653             BOOST_UBLAS_INLINE
    01654             size_type index1 () const {
    01655                 return i_;
    01656             }
    01657             BOOST_UBLAS_INLINE
    01658             size_type index2 () const {
    01659                 return j_;
    01660             }
    01661
    01662             // Assignment
    01663             BOOST_UBLAS_INLINE
    01664             iterator1 &operator = (const iterator1 &it) {
    01665                 container_reference<self_type>::assign (&it ());
    01666                 it_ = it.it_;
    01667                 return *this;
    01668             }
    01669
    01670             // Comparison
    01671             BOOST_UBLAS_INLINE
    01672             bool operator == (const iterator1 &it) const {
    01673                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01674                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
    01675                 return it_ == it.it_;
    01676             }
    01677             BOOST_UBLAS_INLINE
    01678             bool operator < (const iterator1 &it) const {
    01679                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01680                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
    01681                 return it_ < it.it_;
    01682             }
    01683
    01684         private:
    01685             size_type i_;
    01686             size_type j_;
    01687             subiterator_type it_;
    01688
    01689             friend class const_iterator1;
    01690         };
    01691 #endif
    01692
    01693         BOOST_UBLAS_INLINE
    01694         iterator1 begin1 () {
    01695             return find1 (0, 0, 0);
    01696         }
    01697         BOOST_UBLAS_INLINE
    01698         iterator1 end1 () {
    01699             return find1 (0, size1_, 0);
    01700         }
    01701
    01702 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01703         class const_iterator2:
    01704             public container_const_reference<vector_of_vector>,
    01705             public random_access_iterator_base<dense_random_access_iterator_tag,
    01706                                                const_iterator2, value_type> {
    01707         public:
    01708             typedef typename vector_of_vector::value_type value_type;
    01709             typedef typename vector_of_vector::difference_type difference_type;
    01710             typedef typename vector_of_vector::const_reference reference;
    01711             typedef const typename vector_of_vector::pointer pointer;
    01712
    01713             typedef const_iterator1 dual_iterator_type;
    01714             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    01715
    01716             // Construction and destruction
    01717             BOOST_UBLAS_INLINE
    01718             const_iterator2 ():
    01719                 container_const_reference<self_type> (), i_ (), j_ (), it_ () {}
    01720             BOOST_UBLAS_INLINE
    01721             const_iterator2 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it):
    01722                 container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
    01723             BOOST_UBLAS_INLINE
    01724             const_iterator2 (const iterator2 &it):
    01725                 container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
    01726
    01727             // Arithmetic
    01728             BOOST_UBLAS_INLINE
    01729             const_iterator2 &operator ++ () {
    01730                 ++ j_;
    01731                 const self_type &m = (*this) ();
    01732                 if (layout_type::fast_j ())
    01733                     ++ it_;
    01734                 else
    01735                     it_ = m.find2 (1, i_, j_).it_;
    01736                 return *this;
    01737             }
    01738             BOOST_UBLAS_INLINE
    01739             const_iterator2 &operator -- () {
    01740                 -- j_;
    01741                 const self_type &m = (*this) ();
    01742                 if (layout_type::fast_j ())
    01743                     -- it_;
    01744                 else
    01745                     it_ = m.find2 (1, i_, j_).it_;
    01746                 return *this;
    01747             }
    01748             BOOST_UBLAS_INLINE
    01749             const_iterator2 &operator += (difference_type n) {
    01750                 j_ += n;
    01751                 const self_type &m = (*this) ();
    01752                 it_ = m.find2 (1, i_, j_).it_;
    01753                 return *this;
    01754             }
    01755             BOOST_UBLAS_INLINE
    01756             const_iterator2 &operator -= (difference_type n) {
    01757                 j_ -= n;
    01758                 const self_type &m = (*this) ();
    01759                 it_ = m.find2 (1, i_, j_).it_;
    01760                 return *this;
    01761             }
    01762             BOOST_UBLAS_INLINE
    01763             difference_type operator - (const const_iterator2 &it) const {
    01764                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01765                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
    01766                 return index2 () - it.index2 ();
    01767             }
    01768
    01769             // Dereference
    01770             BOOST_UBLAS_INLINE
    01771             const_reference operator * () const {
    01772                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    01773                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    01774                 return *it_;
    01775             }
    01776             BOOST_UBLAS_INLINE
    01777             const_reference operator [] (difference_type n) const {
    01778                 return *(*this + n);
    01779             }
    01780
    01781 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    01782             BOOST_UBLAS_INLINE
    01783 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01784             typename self_type::
    01785 #endif
    01786             const_iterator1 begin () const {
    01787                 const self_type &m = (*this) ();
    01788                 return m.find1 (1, 0, index2 ());
    01789             }
    01790             BOOST_UBLAS_INLINE
    01791 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01792             typename self_type::
    01793 #endif
    01794             const_iterator1 end () const {
    01795                 const self_type &m = (*this) ();
    01796                 return m.find1 (1, m.size1 (), index2 ());
    01797             }
    01798             BOOST_UBLAS_INLINE
    01799 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01800             typename self_type::
    01801 #endif
    01802             const_reverse_iterator1 rbegin () const {
    01803                 return const_reverse_iterator1 (end ());
    01804             }
    01805             BOOST_UBLAS_INLINE
    01806 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01807             typename self_type::
    01808 #endif
    01809             const_reverse_iterator1 rend () const {
    01810                 return const_reverse_iterator1 (begin ());
    01811             }
    01812 #endif
    01813
    01814             // Indices
    01815             BOOST_UBLAS_INLINE
    01816             size_type index1 () const {
    01817                 return i_;
    01818             }
    01819             BOOST_UBLAS_INLINE
    01820             size_type index2 () const {
    01821                 return j_;
    01822             }
    01823
    01824             // Assignment
    01825             BOOST_UBLAS_INLINE
    01826             const_iterator2 &operator = (const const_iterator2 &it) {
    01827                 container_const_reference<self_type>::assign (&it ());
    01828                 it_ = it.it_;
    01829                 return *this;
    01830             }
    01831
    01832             // Comparison
    01833             BOOST_UBLAS_INLINE
    01834             bool operator == (const const_iterator2 &it) const {
    01835                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01836                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
    01837                 return it_ == it.it_;
    01838             }
    01839             BOOST_UBLAS_INLINE
    01840             bool operator < (const const_iterator2 &it) const {
    01841                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01842                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
    01843                 return it_ < it.it_;
    01844             }
    01845
    01846         private:
    01847             size_type i_;
    01848             size_type j_;
    01849             const_subiterator_type it_;
    01850
    01851             friend class iterator2;
    01852         };
    01853 #endif
    01854
    01855         BOOST_UBLAS_INLINE
    01856         const_iterator2 begin2 () const {
    01857             return find2 (0, 0, 0);
    01858         }
    01859         BOOST_UBLAS_INLINE
    01860         const_iterator2 end2 () const {
    01861             return find2 (0, 0, size2_);
    01862         }
    01863
    01864 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01865         class iterator2:
    01866             public container_reference<vector_of_vector>,
    01867             public random_access_iterator_base<dense_random_access_iterator_tag,
    01868                                                iterator2, value_type> {
    01869         public:
    01870             typedef typename vector_of_vector::value_type value_type;
    01871             typedef typename vector_of_vector::difference_type difference_type;
    01872             typedef typename vector_of_vector::reference reference;
    01873             typedef typename vector_of_vector::pointer pointer;
    01874
    01875             typedef iterator1 dual_iterator_type;
    01876             typedef reverse_iterator1 dual_reverse_iterator_type;
    01877
    01878             // Construction and destruction
    01879             BOOST_UBLAS_INLINE
    01880             iterator2 ():
    01881                 container_reference<self_type> (), i_ (), j_ (), it_ () {}
    01882             BOOST_UBLAS_INLINE
    01883             iterator2 (self_type &m, size_type i, size_type j, const subiterator_type &it):
    01884                 container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
    01885
    01886             // Arithmetic
    01887             BOOST_UBLAS_INLINE
    01888             iterator2 &operator ++ () {
    01889                 ++ j_;
    01890                 self_type &m = (*this) ();
    01891                 if (layout_type::fast_j ())
    01892                     ++ it_;
    01893                 else
    01894                     it_ = m.find2 (1, i_, j_).it_;
    01895                 return *this;
    01896             }
    01897             BOOST_UBLAS_INLINE
    01898             iterator2 &operator -- () {
    01899                 -- j_;
    01900                 self_type &m = (*this) ();
    01901                 if (layout_type::fast_j ())
    01902                     -- it_;
    01903                 else
    01904                     it_ = m.find2 (1, i_, j_).it_;
    01905                 return *this;
    01906             }
    01907             BOOST_UBLAS_INLINE
    01908             iterator2 &operator += (difference_type n) {
    01909                 j_ += n;
    01910                 self_type &m = (*this) ();
    01911                 it_ = m.find2 (1, i_, j_).it_;
    01912                 return *this;
    01913             }
    01914             BOOST_UBLAS_INLINE
    01915             iterator2 &operator -= (difference_type n) {
    01916                 j_ -= n;
    01917                 self_type &m = (*this) ();
    01918                 it_ = m.find2 (1, i_, j_).it_;
    01919                 return *this;
    01920             }
    01921             BOOST_UBLAS_INLINE
    01922             difference_type operator - (const iterator2 &it) const {
    01923                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01924                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
    01925                 return index2 () - it.index2 ();
    01926             }
    01927
    01928             // Dereference
    01929             BOOST_UBLAS_INLINE
    01930             reference operator * () const {
    01931                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    01932                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    01933                 return *it_;
    01934             }
    01935             BOOST_UBLAS_INLINE
    01936             reference operator [] (difference_type n) const {
    01937                 return *(*this + n);
    01938             }
    01939
    01940 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    01941             BOOST_UBLAS_INLINE
    01942 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01943             typename self_type::
    01944 #endif
    01945             iterator1 begin () const {
    01946                 self_type &m = (*this) ();
    01947                 return m.find1 (1, 0, index2 ());
    01948             }
    01949             BOOST_UBLAS_INLINE
    01950 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01951             typename self_type::
    01952 #endif
    01953             iterator1 end () const {
    01954                 self_type &m = (*this) ();
    01955                 return m.find1 (1, m.size1 (), index2 ());
    01956             }
    01957             BOOST_UBLAS_INLINE
    01958 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01959             typename self_type::
    01960 #endif
    01961             reverse_iterator1 rbegin () const {
    01962                 return reverse_iterator1 (end ());
    01963             }
    01964             BOOST_UBLAS_INLINE
    01965 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01966             typename self_type::
    01967 #endif
    01968             reverse_iterator1 rend () const {
    01969                 return reverse_iterator1 (begin ());
    01970             }
    01971 #endif
    01972
    01973             // Indices
    01974             BOOST_UBLAS_INLINE
    01975             size_type index1 () const {
    01976                 return i_;
    01977             }
    01978             BOOST_UBLAS_INLINE
    01979             size_type index2 () const {
    01980                 return j_;
    01981             }
    01982
    01983             // Assignment
    01984             BOOST_UBLAS_INLINE
    01985             iterator2 &operator = (const iterator2 &it) {
    01986                 container_reference<self_type>::assign (&it ());
    01987                 it_ = it.it_;
    01988                 return *this;
    01989             }
    01990
    01991             // Comparison
    01992             BOOST_UBLAS_INLINE
    01993             bool operator == (const iterator2 &it) const {
    01994                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    01995                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
    01996                 return it_ == it.it_;
    01997             }
    01998             BOOST_UBLAS_INLINE
    01999             bool operator < (const iterator2 &it) const {
    02000                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    02001                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
    02002                 return it_ < it.it_;
    02003             }
    02004
    02005         private:
    02006             size_type i_;
    02007             size_type j_;
    02008             subiterator_type it_;
    02009
    02010             friend class const_iterator2;
    02011         };
    02012 #endif
    02013
    02014         BOOST_UBLAS_INLINE
    02015         iterator2 begin2 () {
    02016             return find2 (0, 0, 0);
    02017         }
    02018         BOOST_UBLAS_INLINE
    02019         iterator2 end2 () {
    02020             return find2 (0, 0, size2_);
    02021         }
    02022
    02023         // Reverse iterators
    02024
    02025         BOOST_UBLAS_INLINE
    02026         const_reverse_iterator1 rbegin1 () const {
    02027             return const_reverse_iterator1 (end1 ());
    02028         }
    02029         BOOST_UBLAS_INLINE
    02030         const_reverse_iterator1 rend1 () const {
    02031             return const_reverse_iterator1 (begin1 ());
    02032         }
    02033
    02034         BOOST_UBLAS_INLINE
    02035         reverse_iterator1 rbegin1 () {
    02036             return reverse_iterator1 (end1 ());
    02037         }
    02038         BOOST_UBLAS_INLINE
    02039         reverse_iterator1 rend1 () {
    02040             return reverse_iterator1 (begin1 ());
    02041         }
    02042
    02043         BOOST_UBLAS_INLINE
    02044         const_reverse_iterator2 rbegin2 () const {
    02045             return const_reverse_iterator2 (end2 ());
    02046         }
    02047         BOOST_UBLAS_INLINE
    02048         const_reverse_iterator2 rend2 () const {
    02049             return const_reverse_iterator2 (begin2 ());
    02050         }
    02051
    02052         BOOST_UBLAS_INLINE
    02053         reverse_iterator2 rbegin2 () {
    02054             return reverse_iterator2 (end2 ());
    02055         }
    02056         BOOST_UBLAS_INLINE
    02057         reverse_iterator2 rend2 () {
    02058             return reverse_iterator2 (begin2 ());
    02059         }
    02060
    02061         // Serialization
    02062         template<class Archive>
    02063         void serialize(Archive & ar, const unsigned int /* file_version */){
    02064
    02065             // we need to copy to a collection_size_type to get a portable
    02066             // and efficient serialization
    02067             serialization::collection_size_type s1 (size1_);
    02068             serialization::collection_size_type s2 (size2_);
    02069
    02070             // serialize the sizes
    02071             ar & serialization::make_nvp("size1",s1)
    02072                & serialization::make_nvp("size2",s2);
    02073
    02074             // copy the values back if loading
    02075             if (Archive::is_loading::value) {
    02076                 size1_ = s1;
    02077                 size2_ = s2;
    02078             }
    02079             ar & serialization::make_nvp("data",data_);
    02080         }
    02081
    02082     private:
    02083         size_type size1_;
    02084         size_type size2_;
    02085         array_type data_;
    02086     };
    02087
    02088
    02097     template<class T, class ALLOC>
    02098     class zero_matrix:
    02099         public matrix_container<zero_matrix<T, ALLOC> > {
    02100
    02101         typedef const T *const_pointer;
    02102         typedef zero_matrix<T, ALLOC> self_type;
    02103     public:
    02104 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    02105         using matrix_container<self_type>::operator ();
    02106 #endif
    02107         typedef typename ALLOC::size_type size_type;
    02108         typedef typename ALLOC::difference_type difference_type;
    02109         typedef T value_type;
    02110         typedef const T &const_reference;
    02111         typedef T &reference;
    02112         typedef const matrix_reference<const self_type> const_closure_type;
    02113         typedef matrix_reference<self_type> closure_type;
    02114         typedef sparse_tag storage_category;
    02115         typedef unknown_orientation_tag orientation_category;
    02116
    02117         // Construction and destruction
    02118         BOOST_UBLAS_INLINE
    02119         zero_matrix ():
    02120             matrix_container<self_type> (),
    02121             size1_ (0), size2_ (0) {}
    02122         BOOST_UBLAS_INLINE
    02123         zero_matrix (size_type size):
    02124             matrix_container<self_type> (),
    02125             size1_ (size), size2_ (size) {}
    02126         BOOST_UBLAS_INLINE
    02127         zero_matrix (size_type size1, size_type size2):
    02128             matrix_container<self_type> (),
    02129             size1_ (size1), size2_ (size2) {}
    02130         BOOST_UBLAS_INLINE
    02131         zero_matrix (const zero_matrix &m):
    02132             matrix_container<self_type> (),
    02133             size1_ (m.size1_), size2_ (m.size2_) {}
    02134
    02135         // Accessors
    02136         BOOST_UBLAS_INLINE
    02137         size_type size1 () const {
    02138             return size1_;
    02139         }
    02140         BOOST_UBLAS_INLINE
    02141         size_type size2 () const {
    02142             return size2_;
    02143         }
    02144
    02145         // Resizing
    02146         BOOST_UBLAS_INLINE
    02147         void resize (size_type size, bool preserve = true) {
    02148             size1_ = size;
    02149             size2_ = size;
    02150         }
    02151         BOOST_UBLAS_INLINE
    02152         void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
    02153             size1_ = size1;
    02154             size2_ = size2;
    02155         }
    02156
    02157         // Element access
    02158         BOOST_UBLAS_INLINE
    02159         const_reference operator () (size_type /* i */, size_type /* j */) const {
    02160             return zero_;
    02161         }
    02162
    02163         // Assignment
    02164         BOOST_UBLAS_INLINE
    02165         zero_matrix &operator = (const zero_matrix &m) {
    02166             size1_ = m.size1_;
    02167             size2_ = m.size2_;
    02168             return *this;
    02169         }
    02170         BOOST_UBLAS_INLINE
    02171         zero_matrix &assign_temporary (zero_matrix &m) {
    02172             swap (m);
    02173             return *this;
    02174         }
    02175
    02176         // Swapping
    02177         BOOST_UBLAS_INLINE
    02178         void swap (zero_matrix &m) {
    02179             if (this != &m) {
    02180                 std::swap (size1_, m.size1_);
    02181                 std::swap (size2_, m.size2_);
    02182             }
    02183         }
    02184         BOOST_UBLAS_INLINE
    02185         friend void swap (zero_matrix &m1, zero_matrix &m2) {
    02186             m1.swap (m2);
    02187         }
    02188
    02189         // Iterator types
    02190     public:
    02191         class const_iterator1;
    02192         class const_iterator2;
    02193         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    02194         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    02195
    02196         // Element lookup
    02197         BOOST_UBLAS_INLINE
    02198         const_iterator1 find1 (int /*rank*/, size_type /*i*/, size_type /*j*/) const {
    02199             return const_iterator1 (*this);
    02200         }
    02201         BOOST_UBLAS_INLINE
    02202         const_iterator2 find2 (int /*rank*/, size_type /*i*/, size_type /*j*/) const {
    02203             return const_iterator2 (*this);
    02204         }
    02205
    02206         class const_iterator1:
    02207             public container_const_reference<zero_matrix>,
    02208             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
    02209                                                const_iterator1, value_type> {
    02210         public:
    02211             typedef typename zero_matrix::value_type value_type;
    02212             typedef typename zero_matrix::difference_type difference_type;
    02213             typedef typename zero_matrix::const_reference reference;
    02214             typedef typename zero_matrix::const_pointer pointer;
    02215
    02216             typedef const_iterator2 dual_iterator_type;
    02217             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    02218
    02219             // Construction and destruction
    02220             BOOST_UBLAS_INLINE
    02221             const_iterator1 ():
    02222                 container_const_reference<self_type> () {}
    02223             BOOST_UBLAS_INLINE
    02224             const_iterator1 (const self_type &m):
    02225                 container_const_reference<self_type> (m) {}
    02226
    02227             // Arithmetic
    02228             BOOST_UBLAS_INLINE
    02229             const_iterator1 &operator ++ () {
    02230                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
    02231                 return *this;
    02232             }
    02233             BOOST_UBLAS_INLINE
    02234             const_iterator1 &operator -- () {
    02235                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
    02236                 return *this;
    02237             }
    02238
    02239             // Dereference
    02240             BOOST_UBLAS_INLINE
    02241             const_reference operator * () const {
    02242                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
    02243                 return zero_;   // arbitary return value
    02244             }
    02245
    02246 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02247             BOOST_UBLAS_INLINE
    02248 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02249             typename self_type::
    02250 #endif
    02251             const_iterator2 begin () const {
    02252                 return const_iterator2 ((*this) ());
    02253             }
    02254             BOOST_UBLAS_INLINE
    02255 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02256             typename self_type::
    02257 #endif
    02258             const_iterator2 end () const {
    02259                 return const_iterator2 ((*this) ());
    02260             }
    02261             BOOST_UBLAS_INLINE
    02262 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02263             typename self_type::
    02264 #endif
    02265             const_reverse_iterator2 rbegin () const {
    02266                 return const_reverse_iterator2 (end ());
    02267             }
    02268             BOOST_UBLAS_INLINE
    02269 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02270             typename self_type::
    02271 #endif
    02272             const_reverse_iterator2 rend () const {
    02273                 return const_reverse_iterator2 (begin ());
    02274             }
    02275 #endif
    02276
    02277             // Indices
    02278             BOOST_UBLAS_INLINE
    02279             size_type index1 () const {
    02280                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
    02281                 return 0;   // arbitary return value
    02282             }
    02283             BOOST_UBLAS_INLINE
    02284             size_type index2 () const {
    02285                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
    02286                 return 0;   // arbitary return value
    02287             }
    02288
    02289             // Assignment
    02290             BOOST_UBLAS_INLINE
    02291             const_iterator1 &operator = (const const_iterator1 &it) {
    02292                 container_const_reference<self_type>::assign (&it ());
    02293                 return *this;
    02294             }
    02295
    02296             // Comparison
    02297             BOOST_UBLAS_INLINE
    02298             bool operator == (const const_iterator1 &it) const {
    02299                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    02300                 detail::ignore_unused_variable_warning(it);
    02301                 return true;
    02302             }
    02303         };
    02304
    02305         typedef const_iterator1 iterator1;
    02306
    02307         BOOST_UBLAS_INLINE
    02308         const_iterator1 begin1 () const {
    02309             return const_iterator1 (*this);
    02310         }
    02311         BOOST_UBLAS_INLINE
    02312         const_iterator1 end1 () const {
    02313             return const_iterator1 (*this);
    02314         }
    02315
    02316         class const_iterator2:
    02317             public container_const_reference<zero_matrix>,
    02318             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
    02319                                                const_iterator2, value_type> {
    02320         public:
    02321             typedef typename zero_matrix::value_type value_type;
    02322             typedef typename zero_matrix::difference_type difference_type;
    02323             typedef typename zero_matrix::const_reference reference;
    02324             typedef typename zero_matrix::const_pointer pointer;
    02325
    02326             typedef const_iterator1 dual_iterator_type;
    02327             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    02328
    02329             // Construction and destruction
    02330             BOOST_UBLAS_INLINE
    02331             const_iterator2 ():
    02332                 container_const_reference<self_type> () {}
    02333             BOOST_UBLAS_INLINE
    02334             const_iterator2 (const self_type &m):
    02335                 container_const_reference<self_type> (m) {}
    02336
    02337             // Arithmetic
    02338             BOOST_UBLAS_INLINE
    02339             const_iterator2 &operator ++ () {
    02340                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
    02341                 return *this;
    02342             }
    02343             BOOST_UBLAS_INLINE
    02344             const_iterator2 &operator -- () {
    02345                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
    02346                 return *this;
    02347             }
    02348
    02349             // Dereference
    02350             BOOST_UBLAS_INLINE
    02351             const_reference operator * () const {
    02352                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
    02353                 return zero_;   // arbitary return value
    02354             }
    02355
    02356 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02357             BOOST_UBLAS_INLINE
    02358 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02359             typename self_type::
    02360 #endif
    02361             const_iterator1 begin () const {
    02362                 return const_iterator1 ((*this) ());
    02363             }
    02364             BOOST_UBLAS_INLINE
    02365 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02366             typename self_type::
    02367 #endif
    02368             const_iterator1 end () const {
    02369                 return const_iterator1 ((*this) ());
    02370             }
    02371             BOOST_UBLAS_INLINE
    02372 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02373             typename self_type::
    02374 #endif
    02375             const_reverse_iterator1 rbegin () const {
    02376                 return const_reverse_iterator1 (end ());
    02377             }
    02378             BOOST_UBLAS_INLINE
    02379 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02380             typename self_type::
    02381 #endif
    02382             const_reverse_iterator1 rend () const {
    02383                 return const_reverse_iterator1 (begin ());
    02384             }
    02385 #endif
    02386
    02387             // Indices
    02388             BOOST_UBLAS_INLINE
    02389             size_type index1 () const {
    02390                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
    02391                 return 0;   // arbitary return value
    02392             }
    02393             BOOST_UBLAS_INLINE
    02394             size_type index2 () const {
    02395                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
    02396                 return 0;   // arbitary return value
    02397             }
    02398
    02399             // Assignment
    02400             BOOST_UBLAS_INLINE
    02401             const_iterator2 &operator = (const const_iterator2 &it) {
    02402                 container_const_reference<self_type>::assign (&it ());
    02403                 return *this;
    02404             }
    02405
    02406             // Comparison
    02407             BOOST_UBLAS_INLINE
    02408             bool operator == (const const_iterator2 &it) const {
    02409                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    02410                 detail::ignore_unused_variable_warning(it);
    02411                 return true;
    02412             }
    02413         };
    02414
    02415         typedef const_iterator2 iterator2;
    02416
    02417         BOOST_UBLAS_INLINE
    02418         const_iterator2 begin2 () const {
    02419             return find2 (0, 0, 0);
    02420         }
    02421         BOOST_UBLAS_INLINE
    02422         const_iterator2 end2 () const {
    02423             return find2 (0, 0, size2_);
    02424         }
    02425
    02426         // Reverse iterators
    02427
    02428         BOOST_UBLAS_INLINE
    02429         const_reverse_iterator1 rbegin1 () const {
    02430             return const_reverse_iterator1 (end1 ());
    02431         }
    02432         BOOST_UBLAS_INLINE
    02433         const_reverse_iterator1 rend1 () const {
    02434             return const_reverse_iterator1 (begin1 ());
    02435         }
    02436
    02437         BOOST_UBLAS_INLINE
    02438         const_reverse_iterator2 rbegin2 () const {
    02439             return const_reverse_iterator2 (end2 ());
    02440         }
    02441         BOOST_UBLAS_INLINE
    02442         const_reverse_iterator2 rend2 () const {
    02443             return const_reverse_iterator2 (begin2 ());
    02444         }
    02445
    02446          // Serialization
    02447         template<class Archive>
    02448         void serialize(Archive & ar, const unsigned int /* file_version */){
    02449
    02450             // we need to copy to a collection_size_type to get a portable
    02451             // and efficient serialization
    02452             serialization::collection_size_type s1 (size1_);
    02453             serialization::collection_size_type s2 (size2_);
    02454
    02455             // serialize the sizes
    02456             ar & serialization::make_nvp("size1",s1)
    02457                & serialization::make_nvp("size2",s2);
    02458
    02459             // copy the values back if loading
    02460             if (Archive::is_loading::value) {
    02461                 size1_ = s1;
    02462                 size2_ = s2;
    02463             }
    02464         }
    02465
    02466     private:
    02467         size_type size1_;
    02468         size_type size2_;
    02469         static const value_type zero_;
    02470     };
    02471
    02472     template<class T, class ALLOC>
    02473     const typename zero_matrix<T, ALLOC>::value_type zero_matrix<T, ALLOC>::zero_ = T(/*zero*/);
    02474
    02484     template<class T, class ALLOC>
    02485     class identity_matrix:
    02486         public matrix_container<identity_matrix<T, ALLOC> > {
    02487
    02488         typedef const T *const_pointer;
    02489         typedef identity_matrix<T, ALLOC> self_type;
    02490     public:
    02491 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    02492         using matrix_container<self_type>::operator ();
    02493 #endif
    02494         typedef typename ALLOC::size_type size_type;
    02495         typedef typename ALLOC::difference_type difference_type;
    02496         typedef T value_type;
    02497         typedef const T &const_reference;
    02498         typedef T &reference;
    02499         typedef const matrix_reference<const self_type> const_closure_type;
    02500         typedef matrix_reference<self_type> closure_type;
    02501         typedef sparse_tag storage_category;
    02502         typedef unknown_orientation_tag orientation_category;
    02503
    02504         // Construction and destruction
    02505         BOOST_UBLAS_INLINE
    02506         identity_matrix ():
    02507             matrix_container<self_type> (),
    02508             size1_ (0), size2_ (0), size_common_ (0) {}
    02509         BOOST_UBLAS_INLINE
    02510         identity_matrix (size_type size):
    02511             matrix_container<self_type> (),
    02512             size1_ (size), size2_ (size), size_common_ ((std::min) (size1_, size2_)) {}
    02513         BOOST_UBLAS_INLINE
    02514         identity_matrix (size_type size1, size_type size2):
    02515             matrix_container<self_type> (),
    02516             size1_ (size1), size2_ (size2), size_common_ ((std::min) (size1_, size2_)) {}
    02517         BOOST_UBLAS_INLINE
    02518         identity_matrix (const identity_matrix &m):
    02519             matrix_container<self_type> (),
    02520             size1_ (m.size1_), size2_ (m.size2_), size_common_ ((std::min) (size1_, size2_)) {}
    02521
    02522         // Accessors
    02523         BOOST_UBLAS_INLINE
    02524         size_type size1 () const {
    02525             return size1_;
    02526         }
    02527         BOOST_UBLAS_INLINE
    02528         size_type size2 () const {
    02529             return size2_;
    02530         }
    02531
    02532         // Resizing
    02533         BOOST_UBLAS_INLINE
    02534         void resize (size_type size, bool preserve = true) {
    02535             size1_ = size;
    02536             size2_ = size;
    02537             size_common_ = ((std::min)(size1_, size2_));
    02538         }
    02539         BOOST_UBLAS_INLINE
    02540         void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
    02541             size1_ = size1;
    02542             size2_ = size2;
    02543             size_common_ = ((std::min)(size1_, size2_));
    02544         }
    02545
    02546         // Element access
    02547         BOOST_UBLAS_INLINE
    02548         const_reference operator () (size_type i, size_type j) const {
    02549             if (i == j)
    02550                 return one_;
    02551             else
    02552                 return zero_;
    02553         }
    02554
    02555         // Assignment
    02556         BOOST_UBLAS_INLINE
    02557         identity_matrix &operator = (const identity_matrix &m) {
    02558             size1_ = m.size1_;
    02559             size2_ = m.size2_;
    02560             size_common_ = m.size_common_;
    02561             return *this;
    02562         }
    02563         BOOST_UBLAS_INLINE
    02564         identity_matrix &assign_temporary (identity_matrix &m) {
    02565             swap (m);
    02566             return *this;
    02567         }
    02568
    02569         // Swapping
    02570         BOOST_UBLAS_INLINE
    02571         void swap (identity_matrix &m) {
    02572             if (this != &m) {
    02573                 std::swap (size1_, m.size1_);
    02574                 std::swap (size2_, m.size2_);
    02575                 std::swap (size_common_, m.size_common_);
    02576             }
    02577         }
    02578         BOOST_UBLAS_INLINE
    02579         friend void swap (identity_matrix &m1, identity_matrix &m2) {
    02580             m1.swap (m2);
    02581         }
    02582
    02583         // Iterator types
    02584     private:
    02585         // Use an index
    02586         typedef size_type const_subiterator_type;
    02587
    02588     public:
    02589         class const_iterator1;
    02590         class const_iterator2;
    02591         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    02592         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    02593
    02594         // Element lookup
    02595         BOOST_UBLAS_INLINE
    02596         const_iterator1 find1 (int rank, size_type i, size_type j) const {
    02597             if (rank == 1) {
    02598                 i = (std::max) (i, j);
    02599                 i = (std::min) (i, j + 1);
    02600             }
    02601             return const_iterator1 (*this, i);
    02602         }
    02603         BOOST_UBLAS_INLINE
    02604         const_iterator2 find2 (int rank, size_type i, size_type j) const {
    02605             if (rank == 1) {
    02606                 j = (std::max) (j, i);
    02607                 j = (std::min) (j, i + 1);
    02608             }
    02609             return const_iterator2 (*this, j);
    02610         }
    02611
    02612
    02613         class const_iterator1:
    02614             public container_const_reference<identity_matrix>,
    02615             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
    02616                                                const_iterator1, value_type> {
    02617         public:
    02618             typedef typename identity_matrix::value_type value_type;
    02619             typedef typename identity_matrix::difference_type difference_type;
    02620             typedef typename identity_matrix::const_reference reference;
    02621             typedef typename identity_matrix::const_pointer pointer;
    02622
    02623             typedef const_iterator2 dual_iterator_type;
    02624             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    02625
    02626             // Construction and destruction
    02627             BOOST_UBLAS_INLINE
    02628             const_iterator1 ():
    02629                 container_const_reference<self_type> (), it_ () {}
    02630             BOOST_UBLAS_INLINE
    02631             const_iterator1 (const self_type &m, const const_subiterator_type &it):
    02632                 container_const_reference<self_type> (m), it_ (it) {}
    02633
    02634             // Arithmetic
    02635             BOOST_UBLAS_INLINE
    02636             const_iterator1 &operator ++ () {
    02637                 BOOST_UBLAS_CHECK (it_ < (*this) ().size1 (), bad_index ());
    02638                 ++it_;
    02639                 return *this;
    02640             }
    02641             BOOST_UBLAS_INLINE
    02642             const_iterator1 &operator -- () {
    02643                 BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
    02644                 --it_;
    02645                 return *this;
    02646             }
    02647
    02648             // Dereference
    02649             BOOST_UBLAS_INLINE
    02650             const_reference operator * () const {
    02651                 return one_;
    02652             }
    02653
    02654 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02655             BOOST_UBLAS_INLINE
    02656 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02657             typename self_type::
    02658 #endif
    02659             const_iterator2 begin () const {
    02660                 return const_iterator2 ((*this) (), it_);
    02661             }
    02662             BOOST_UBLAS_INLINE
    02663 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02664             typename self_type::
    02665 #endif
    02666             const_iterator2 end () const {
    02667                 return const_iterator2 ((*this) (), it_ + 1);
    02668             }
    02669             BOOST_UBLAS_INLINE
    02670 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02671             typename self_type::
    02672 #endif
    02673             const_reverse_iterator2 rbegin () const {
    02674                 return const_reverse_iterator2 (end ());
    02675             }
    02676             BOOST_UBLAS_INLINE
    02677 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02678             typename self_type::
    02679 #endif
    02680             const_reverse_iterator2 rend () const {
    02681                 return const_reverse_iterator2 (begin ());
    02682             }
    02683 #endif
    02684
    02685             // Indices
    02686             BOOST_UBLAS_INLINE
    02687             size_type index1 () const {
    02688                 return it_;
    02689             }
    02690             BOOST_UBLAS_INLINE
    02691             size_type index2 () const {
    02692                 return it_;
    02693             }
    02694
    02695             // Assignment
    02696             BOOST_UBLAS_INLINE
    02697             const_iterator1 &operator = (const const_iterator1 &it) {
    02698                 container_const_reference<self_type>::assign (&it ());
    02699                 it_ = it.it_;
    02700                 return *this;
    02701             }
    02702
    02703             // Comparison
    02704             BOOST_UBLAS_INLINE
    02705             bool operator == (const const_iterator1 &it) const {
    02706                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    02707                 return it_ == it.it_;
    02708             }
    02709
    02710         private:
    02711             const_subiterator_type it_;
    02712         };
    02713
    02714         typedef const_iterator1 iterator1;
    02715
    02716         BOOST_UBLAS_INLINE
    02717         const_iterator1 begin1 () const {
    02718             return const_iterator1 (*this, 0);
    02719         }
    02720         BOOST_UBLAS_INLINE
    02721         const_iterator1 end1 () const {
    02722             return const_iterator1 (*this, size_common_);
    02723         }
    02724
    02725         class const_iterator2:
    02726             public container_const_reference<identity_matrix>,
    02727             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
    02728                                                const_iterator2, value_type> {
    02729         public:
    02730             typedef typename identity_matrix::value_type value_type;
    02731             typedef typename identity_matrix::difference_type difference_type;
    02732             typedef typename identity_matrix::const_reference reference;
    02733             typedef typename identity_matrix::const_pointer pointer;
    02734
    02735             typedef const_iterator1 dual_iterator_type;
    02736             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    02737
    02738             // Construction and destruction
    02739             BOOST_UBLAS_INLINE
    02740             const_iterator2 ():
    02741                 container_const_reference<self_type> (), it_ () {}
    02742             BOOST_UBLAS_INLINE
    02743             const_iterator2 (const self_type &m, const const_subiterator_type &it):
    02744                 container_const_reference<self_type> (m), it_ (it) {}
    02745
    02746             // Arithmetic
    02747             BOOST_UBLAS_INLINE
    02748             const_iterator2 &operator ++ () {
    02749                 BOOST_UBLAS_CHECK (it_ < (*this) ().size_common_, bad_index ());
    02750                 ++it_;
    02751                 return *this;
    02752             }
    02753             BOOST_UBLAS_INLINE
    02754             const_iterator2 &operator -- () {
    02755                 BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
    02756                 --it_;
    02757                 return *this;
    02758             }
    02759
    02760             // Dereference
    02761             BOOST_UBLAS_INLINE
    02762             const_reference operator * () const {
    02763                 return one_;
    02764             }
    02765
    02766 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02767             BOOST_UBLAS_INLINE
    02768 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02769             typename self_type::
    02770 #endif
    02771             const_iterator1 begin () const {
    02772                 return const_iterator1 ((*this) (), it_);
    02773             }
    02774             BOOST_UBLAS_INLINE
    02775 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02776             typename self_type::
    02777 #endif
    02778             const_iterator1 end () const {
    02779                 return const_iterator1 ((*this) (), it_ + 1);
    02780             }
    02781             BOOST_UBLAS_INLINE
    02782 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02783             typename self_type::
    02784 #endif
    02785             const_reverse_iterator1 rbegin () const {
    02786                 return const_reverse_iterator1 (end ());
    02787             }
    02788             BOOST_UBLAS_INLINE
    02789 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02790             typename self_type::
    02791 #endif
    02792             const_reverse_iterator1 rend () const {
    02793                 return const_reverse_iterator1 (begin ());
    02794             }
    02795 #endif
    02796
    02797             // Indices
    02798             BOOST_UBLAS_INLINE
    02799             size_type index1 () const {
    02800                 return it_;
    02801             }
    02802             BOOST_UBLAS_INLINE
    02803             size_type index2 () const {
    02804                 return it_;
    02805             }
    02806
    02807             // Assignment
    02808             BOOST_UBLAS_INLINE
    02809             const_iterator2 &operator = (const const_iterator2 &it) {
    02810                 container_const_reference<self_type>::assign (&it ());
    02811                 it_ = it.it_;
    02812                 return *this;
    02813             }
    02814
    02815             // Comparison
    02816             BOOST_UBLAS_INLINE
    02817             bool operator == (const const_iterator2 &it) const {
    02818                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    02819                 return it_ == it.it_;
    02820             }
    02821
    02822         private:
    02823             const_subiterator_type it_;
    02824         };
    02825
    02826         typedef const_iterator2 iterator2;
    02827
    02828         BOOST_UBLAS_INLINE
    02829         const_iterator2 begin2 () const {
    02830             return const_iterator2 (*this, 0);
    02831         }
    02832         BOOST_UBLAS_INLINE
    02833         const_iterator2 end2 () const {
    02834             return const_iterator2 (*this, size_common_);
    02835         }
    02836
    02837         // Reverse iterators
    02838
    02839         BOOST_UBLAS_INLINE
    02840         const_reverse_iterator1 rbegin1 () const {
    02841             return const_reverse_iterator1 (end1 ());
    02842         }
    02843         BOOST_UBLAS_INLINE
    02844         const_reverse_iterator1 rend1 () const {
    02845             return const_reverse_iterator1 (begin1 ());
    02846         }
    02847
    02848         BOOST_UBLAS_INLINE
    02849         const_reverse_iterator2 rbegin2 () const {
    02850             return const_reverse_iterator2 (end2 ());
    02851         }
    02852         BOOST_UBLAS_INLINE
    02853         const_reverse_iterator2 rend2 () const {
    02854             return const_reverse_iterator2 (begin2 ());
    02855         }
    02856
    02857          // Serialization
    02858         template<class Archive>
    02859         void serialize(Archive & ar, const unsigned int /* file_version */){
    02860
    02861             // we need to copy to a collection_size_type to get a portable
    02862             // and efficient serialization
    02863             serialization::collection_size_type s1 (size1_);
    02864             serialization::collection_size_type s2 (size2_);
    02865
    02866             // serialize the sizes
    02867             ar & serialization::make_nvp("size1",s1)
    02868                & serialization::make_nvp("size2",s2);
    02869
    02870             // copy the values back if loading
    02871             if (Archive::is_loading::value) {
    02872                 size1_ = s1;
    02873                 size2_ = s2;
    02874                 size_common_ = ((std::min)(size1_, size2_));
    02875             }
    02876         }
    02877
    02878     private:
    02879         size_type size1_;
    02880         size_type size2_;
    02881         size_type size_common_;
    02882         static const value_type zero_;
    02883         static const value_type one_;
    02884     };
    02885
    02886     template<class T, class ALLOC>
    02887     const typename identity_matrix<T, ALLOC>::value_type identity_matrix<T, ALLOC>::zero_ = T(/*zero*/);
    02888     template<class T, class ALLOC>
    02889     const typename identity_matrix<T, ALLOC>::value_type identity_matrix<T, ALLOC>::one_ (1); // ISSUE: need 'one'-traits here
    02890
    02891
    02900     template<class T, class ALLOC>
    02901     class scalar_matrix:
    02902         public matrix_container<scalar_matrix<T, ALLOC> > {
    02903
    02904         typedef const T *const_pointer;
    02905         typedef scalar_matrix<T, ALLOC> self_type;
    02906     public:
    02907 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    02908         using matrix_container<self_type>::operator ();
    02909 #endif
    02910         typedef std::size_t size_type;
    02911         typedef std::ptrdiff_t difference_type;
    02912         typedef T value_type;
    02913         typedef const T &const_reference;
    02914         typedef T &reference;
    02915         typedef const matrix_reference<const self_type> const_closure_type;
    02916         typedef matrix_reference<self_type> closure_type;
    02917         typedef dense_tag storage_category;
    02918         typedef unknown_orientation_tag orientation_category;
    02919
    02920         // Construction and destruction
    02921         BOOST_UBLAS_INLINE
    02922         scalar_matrix ():
    02923             matrix_container<self_type> (),
    02924             size1_ (0), size2_ (0), value_ () {}
    02925         BOOST_UBLAS_INLINE
    02926         scalar_matrix (size_type size1, size_type size2, const value_type &value = value_type(1)):
    02927             matrix_container<self_type> (),
    02928             size1_ (size1), size2_ (size2), value_ (value) {}
    02929         BOOST_UBLAS_INLINE
    02930         scalar_matrix (const scalar_matrix &m):
    02931             matrix_container<self_type> (),
    02932             size1_ (m.size1_), size2_ (m.size2_), value_ (m.value_) {}
    02933
    02934         // Accessors
    02935         BOOST_UBLAS_INLINE
    02936         size_type size1 () const {
    02937             return size1_;
    02938         }
    02939         BOOST_UBLAS_INLINE
    02940         size_type size2 () const {
    02941             return size2_;
    02942         }
    02943
    02944         // Resizing
    02945         BOOST_UBLAS_INLINE
    02946         void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
    02947             size1_ = size1;
    02948             size2_ = size2;
    02949         }
    02950
    02951         // Element access
    02952         BOOST_UBLAS_INLINE
    02953         const_reference operator () (size_type /*i*/, size_type /*j*/) const {
    02954             return value_;
    02955         }
    02956
    02957         // Assignment
    02958         BOOST_UBLAS_INLINE
    02959         scalar_matrix &operator = (const scalar_matrix &m) {
    02960             size1_ = m.size1_;
    02961             size2_ = m.size2_;
    02962             value_ = m.value_;
    02963             return *this;
    02964         }
    02965         BOOST_UBLAS_INLINE
    02966         scalar_matrix &assign_temporary (scalar_matrix &m) {
    02967             swap (m);
    02968             return *this;
    02969         }
    02970
    02971         // Swapping
    02972         BOOST_UBLAS_INLINE
    02973         void swap (scalar_matrix &m) {
    02974             if (this != &m) {
    02975                 std::swap (size1_, m.size1_);
    02976                 std::swap (size2_, m.size2_);
    02977                 std::swap (value_, m.value_);
    02978             }
    02979         }
    02980         BOOST_UBLAS_INLINE
    02981         friend void swap (scalar_matrix &m1, scalar_matrix &m2) {
    02982             m1.swap (m2);
    02983         }
    02984
    02985         // Iterator types
    02986     private:
    02987         // Use an index
    02988         typedef size_type const_subiterator_type;
    02989
    02990     public:
    02991 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02992         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
    02993         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
    02994         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
    02995         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
    02996 #else
    02997         class const_iterator1;
    02998         class const_iterator2;
    02999 #endif
    03000         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    03001         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    03002
    03003         // Element lookup
    03004         BOOST_UBLAS_INLINE
    03005         const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
    03006             return const_iterator1 (*this, i, j);
    03007         }
    03008         BOOST_UBLAS_INLINE
    03009         const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
    03010             return const_iterator2 (*this, i, j);
    03011         }
    03012
    03013
    03014 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03015         class const_iterator1:
    03016             public container_const_reference<scalar_matrix>,
    03017             public random_access_iterator_base<dense_random_access_iterator_tag,
    03018                                                const_iterator1, value_type> {
    03019         public:
    03020             typedef typename scalar_matrix::value_type value_type;
    03021             typedef typename scalar_matrix::difference_type difference_type;
    03022             typedef typename scalar_matrix::const_reference reference;
    03023             typedef typename scalar_matrix::const_pointer pointer;
    03024
    03025             typedef const_iterator2 dual_iterator_type;
    03026             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    03027
    03028             // Construction and destruction
    03029             BOOST_UBLAS_INLINE
    03030             const_iterator1 ():
    03031                 container_const_reference<scalar_matrix> (), it1_ (), it2_ () {}
    03032             BOOST_UBLAS_INLINE
    03033             const_iterator1 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2):
    03034                 container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {}
    03035
    03036             // Arithmetic
    03037             BOOST_UBLAS_INLINE
    03038             const_iterator1 &operator ++ () {
    03039                 ++ it1_;
    03040                 return *this;
    03041             }
    03042             BOOST_UBLAS_INLINE
    03043             const_iterator1 &operator -- () {
    03044                 -- it1_;
    03045                 return *this;
    03046             }
    03047             BOOST_UBLAS_INLINE
    03048             const_iterator1 &operator += (difference_type n) {
    03049                 it1_ += n;
    03050                 return *this;
    03051             }
    03052             BOOST_UBLAS_INLINE
    03053             const_iterator1 &operator -= (difference_type n) {
    03054                 it1_ -= n;
    03055                 return *this;
    03056             }
    03057             BOOST_UBLAS_INLINE
    03058             difference_type operator - (const const_iterator1 &it) const {
    03059                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03060                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03061                 return it1_ - it.it1_;
    03062             }
    03063
    03064             // Dereference
    03065             BOOST_UBLAS_INLINE
    03066             const_reference operator * () const {
    03067                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    03068                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    03069                 return (*this) () (index1 (), index2 ());
    03070             }
    03071             BOOST_UBLAS_INLINE
    03072             const_reference operator [] (difference_type n) const {
    03073                 return *(*this + n);
    03074             }
    03075
    03076 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03077             BOOST_UBLAS_INLINE
    03078 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03079             typename self_type::
    03080 #endif
    03081             const_iterator2 begin () const {
    03082                 const scalar_matrix &m = (*this) ();
    03083                 return m.find2 (1, index1 (), 0);
    03084             }
    03085             BOOST_UBLAS_INLINE
    03086 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03087             typename self_type::
    03088 #endif
    03089             const_iterator2 end () const {
    03090                 const scalar_matrix &m = (*this) ();
    03091                 return m.find2 (1, index1 (), m.size2 ());
    03092             }
    03093             BOOST_UBLAS_INLINE
    03094 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03095             typename self_type::
    03096 #endif
    03097             const_reverse_iterator2 rbegin () const {
    03098                 return const_reverse_iterator2 (end ());
    03099             }
    03100             BOOST_UBLAS_INLINE
    03101 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03102             typename self_type::
    03103 #endif
    03104             const_reverse_iterator2 rend () const {
    03105                 return const_reverse_iterator2 (begin ());
    03106             }
    03107 #endif
    03108
    03109             // Indices
    03110             BOOST_UBLAS_INLINE
    03111             size_type index1 () const {
    03112                 return it1_;
    03113             }
    03114             BOOST_UBLAS_INLINE
    03115             size_type index2 () const {
    03116                 return it2_;
    03117             }
    03118
    03119             // Assignment
    03120             BOOST_UBLAS_INLINE
    03121             const_iterator1 &operator = (const const_iterator1 &it) {
    03122                 container_const_reference<scalar_matrix>::assign (&it ());
    03123                 it1_ = it.it1_;
    03124                 it2_ = it.it2_;
    03125                 return *this;
    03126             }
    03127
    03128             // Comparison
    03129             BOOST_UBLAS_INLINE
    03130             bool operator == (const const_iterator1 &it) const {
    03131                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03132                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03133                 return it1_ == it.it1_;
    03134             }
    03135             BOOST_UBLAS_INLINE
    03136             bool operator < (const const_iterator1 &it) const {
    03137                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03138                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03139                 return it1_ < it.it1_;
    03140             }
    03141
    03142         private:
    03143             const_subiterator_type it1_;
    03144             const_subiterator_type it2_;
    03145         };
    03146
    03147         typedef const_iterator1 iterator1;
    03148 #endif
    03149
    03150         BOOST_UBLAS_INLINE
    03151         const_iterator1 begin1 () const {
    03152             return find1 (0, 0, 0);
    03153         }
    03154         BOOST_UBLAS_INLINE
    03155         const_iterator1 end1 () const {
    03156             return find1 (0, size1_, 0);
    03157         }
    03158
    03159 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03160         class const_iterator2:
    03161             public container_const_reference<scalar_matrix>,
    03162             public random_access_iterator_base<dense_random_access_iterator_tag,
    03163                                                const_iterator2, value_type> {
    03164         public:
    03165             typedef typename scalar_matrix::value_type value_type;
    03166             typedef typename scalar_matrix::difference_type difference_type;
    03167             typedef typename scalar_matrix::const_reference reference;
    03168             typedef typename scalar_matrix::const_pointer pointer;
    03169
    03170             typedef const_iterator1 dual_iterator_type;
    03171             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    03172
    03173             // Construction and destruction
    03174             BOOST_UBLAS_INLINE
    03175             const_iterator2 ():
    03176                 container_const_reference<scalar_matrix> (), it1_ (), it2_ () {}
    03177             BOOST_UBLAS_INLINE
    03178             const_iterator2 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2):
    03179                 container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {}
    03180
    03181             // Arithmetic
    03182             BOOST_UBLAS_INLINE
    03183             const_iterator2 &operator ++ () {
    03184                 ++ it2_;
    03185                 return *this;
    03186             }
    03187             BOOST_UBLAS_INLINE
    03188             const_iterator2 &operator -- () {
    03189                 -- it2_;
    03190                 return *this;
    03191             }
    03192             BOOST_UBLAS_INLINE
    03193             const_iterator2 &operator += (difference_type n) {
    03194                 it2_ += n;
    03195                 return *this;
    03196             }
    03197             BOOST_UBLAS_INLINE
    03198             const_iterator2 &operator -= (difference_type n) {
    03199                 it2_ -= n;
    03200                 return *this;
    03201             }
    03202             BOOST_UBLAS_INLINE
    03203             difference_type operator - (const const_iterator2 &it) const {
    03204                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03205                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    03206                 return it2_ - it.it2_;
    03207             }
    03208
    03209             // Dereference
    03210             BOOST_UBLAS_INLINE
    03211             const_reference operator * () const {
    03212                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    03213                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    03214                 return (*this) () (index1 (), index2 ());
    03215             }
    03216             BOOST_UBLAS_INLINE
    03217             const_reference operator [] (difference_type n) const {
    03218                 return *(*this + n);
    03219             }
    03220
    03221 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03222             BOOST_UBLAS_INLINE
    03223 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03224             typename self_type::
    03225 #endif
    03226             const_iterator1 begin () const {
    03227                 const scalar_matrix &m = (*this) ();
    03228                 return m.find1 (1, 0, index2 ());
    03229             }
    03230             BOOST_UBLAS_INLINE
    03231 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03232             typename self_type::
    03233 #endif
    03234             const_iterator1 end () const {
    03235                 const scalar_matrix &m = (*this) ();
    03236                 return m.find1 (1, m.size1 (), index2 ());
    03237             }
    03238             BOOST_UBLAS_INLINE
    03239 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03240             typename self_type::
    03241 #endif
    03242             const_reverse_iterator1 rbegin () const {
    03243                 return const_reverse_iterator1 (end ());
    03244             }
    03245             BOOST_UBLAS_INLINE
    03246 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03247             typename self_type::
    03248 #endif
    03249             const_reverse_iterator1 rend () const {
    03250                 return const_reverse_iterator1 (begin ());
    03251             }
    03252 #endif
    03253
    03254             // Indices
    03255             BOOST_UBLAS_INLINE
    03256             size_type index1 () const {
    03257                 return it1_;
    03258             }
    03259             BOOST_UBLAS_INLINE
    03260             size_type index2 () const {
    03261                 return it2_;
    03262             }
    03263
    03264             // Assignment
    03265             BOOST_UBLAS_INLINE
    03266             const_iterator2 &operator = (const const_iterator2 &it) {
    03267                 container_const_reference<scalar_matrix>::assign (&it ());
    03268                 it1_ = it.it1_;
    03269                 it2_ = it.it2_;
    03270                 return *this;
    03271             }
    03272
    03273             // Comparison
    03274             BOOST_UBLAS_INLINE
    03275             bool operator == (const const_iterator2 &it) const {
    03276                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03277                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    03278                 return it2_ == it.it2_;
    03279             }
    03280             BOOST_UBLAS_INLINE
    03281             bool operator < (const const_iterator2 &it) const {
    03282                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03283                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    03284                 return it2_ < it.it2_;
    03285             }
    03286
    03287         private:
    03288             const_subiterator_type it1_;
    03289             const_subiterator_type it2_;
    03290         };
    03291
    03292         typedef const_iterator2 iterator2;
    03293 #endif
    03294
    03295         BOOST_UBLAS_INLINE
    03296         const_iterator2 begin2 () const {
    03297             return find2 (0, 0, 0);
    03298         }
    03299         BOOST_UBLAS_INLINE
    03300         const_iterator2 end2 () const {
    03301             return find2 (0, 0, size2_);
    03302         }
    03303
    03304         // Reverse iterators
    03305
    03306         BOOST_UBLAS_INLINE
    03307         const_reverse_iterator1 rbegin1 () const {
    03308             return const_reverse_iterator1 (end1 ());
    03309         }
    03310         BOOST_UBLAS_INLINE
    03311         const_reverse_iterator1 rend1 () const {
    03312             return const_reverse_iterator1 (begin1 ());
    03313         }
    03314
    03315         BOOST_UBLAS_INLINE
    03316         const_reverse_iterator2 rbegin2 () const {
    03317             return const_reverse_iterator2 (end2 ());
    03318         }
    03319         BOOST_UBLAS_INLINE
    03320         const_reverse_iterator2 rend2 () const {
    03321             return const_reverse_iterator2 (begin2 ());
    03322         }
    03323
    03324          // Serialization
    03325         template<class Archive>
    03326         void serialize(Archive & ar, const unsigned int /* file_version */){
    03327
    03328             // we need to copy to a collection_size_type to get a portable
    03329             // and efficient serialization
    03330             serialization::collection_size_type s1 (size1_);
    03331             serialization::collection_size_type s2 (size2_);
    03332
    03333             // serialize the sizes
    03334             ar & serialization::make_nvp("size1",s1)
    03335                & serialization::make_nvp("size2",s2);
    03336
    03337             // copy the values back if loading
    03338             if (Archive::is_loading::value) {
    03339                 size1_ = s1;
    03340                 size2_ = s2;
    03341             }
    03342
    03343             ar & serialization::make_nvp("value", value_);
    03344         }
    03345
    03346     private:
    03347         size_type size1_;
    03348         size_type size2_;
    03349         value_type value_;
    03350     };
    03351
    03352
    03370     template<class T, std::size_t N, std::size_t M>
    03371     class c_matrix:
    03372         public matrix_container<c_matrix<T, N, M> > {
    03373
    03374         typedef c_matrix<T, N, M> self_type;
    03375     public:
    03376 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    03377         using matrix_container<self_type>::operator ();
    03378 #endif
    03379         typedef std::size_t size_type;
    03380         typedef std::ptrdiff_t difference_type;
    03381         typedef T value_type;
    03382         typedef const T &const_reference;
    03383         typedef T &reference;
    03384         typedef const T *const_pointer;
    03385         typedef T *pointer;
    03386         typedef const matrix_reference<const self_type> const_closure_type;
    03387         typedef matrix_reference<self_type> closure_type;
    03388         typedef c_vector<T, N * M> vector_temporary_type;     // vector able to store all elements of c_matrix
    03389         typedef self_type matrix_temporary_type;
    03390         typedef dense_tag storage_category;
    03391         // This could be better for performance,
    03392         // typedef typename unknown_orientation_tag orientation_category;
    03393         // but others depend on the orientation information...
    03394         typedef row_major_tag orientation_category;
    03395
    03396         // Construction and destruction
    03397         BOOST_UBLAS_INLINE
    03398         c_matrix ():
    03399             size1_ (N), size2_ (M) /* , data_ () */ {
    03400         }
    03401         BOOST_UBLAS_INLINE
    03402         c_matrix (size_type size1, size_type size2):
    03403             size1_ (size1), size2_ (size2) /* , data_ () */ {
    03404             if (size1_ > N || size2_ > M)
    03405                 bad_size ().raise ();
    03406         }
    03407         BOOST_UBLAS_INLINE
    03408         c_matrix (const c_matrix &m):
    03409             size1_ (m.size1_), size2_ (m.size2_) /* , data_ () */ {
    03410             if (size1_ > N || size2_ > M)
    03411                 bad_size ().raise ();
    03412             assign(m);
    03413         }
    03414         template<class AE>
    03415         BOOST_UBLAS_INLINE
    03416         c_matrix (const matrix_expression<AE> &ae):
    03417             size1_ (ae ().size1 ()), size2_ (ae ().size2 ()) /* , data_ () */ {
    03418             if (size1_ > N || size2_ > M)
    03419                 bad_size ().raise ();
    03420             matrix_assign<scalar_assign> (*this, ae);
    03421         }
    03422
    03423         // Accessors
    03424         BOOST_UBLAS_INLINE
    03425         size_type size1 () const {
    03426             return size1_;
    03427         }
    03428         BOOST_UBLAS_INLINE
    03429         size_type size2 () const {
    03430             return size2_;
    03431         }
    03432         BOOST_UBLAS_INLINE
    03433         const_pointer data () const {
    03434             return reinterpret_cast<const_pointer> (data_);
    03435         }
    03436         BOOST_UBLAS_INLINE
    03437         pointer data () {
    03438             return reinterpret_cast<pointer> (data_);
    03439         }
    03440
    03441         // Resizing
    03442         BOOST_UBLAS_INLINE
    03443         void resize (size_type size1, size_type size2, bool preserve = true) {
    03444             if (size1 > N || size2 > M)
    03445                 bad_size ().raise ();
    03446             if (preserve) {
    03447                 self_type temporary (size1, size2);
    03448                 // Common elements to preserve
    03449                 const size_type size1_min = (std::min) (size1, size1_);
    03450                 const size_type size2_min = (std::min) (size2, size2_);
    03451                 for (size_type i = 0; i != size1_min; ++i) {    // indexing copy over major
    03452                     for (size_type j = 0; j != size2_min; ++j) {
    03453                         temporary.data_[i][j] = data_[i][j];
    03454                     }
    03455                 }
    03456                 assign_temporary (temporary);
    03457             }
    03458             else {
    03459                 size1_ = size1;
    03460                 size2_ = size2;
    03461             }
    03462         }
    03463
    03464         // Element access
    03465         BOOST_UBLAS_INLINE
    03466         const_reference operator () (size_type i, size_type j) const {
    03467             BOOST_UBLAS_CHECK (i < size1_, bad_index ());
    03468             BOOST_UBLAS_CHECK (j < size2_, bad_index ());
    03469             return data_ [i] [j];
    03470         }
    03471         BOOST_UBLAS_INLINE
    03472         reference at_element (size_type i, size_type j) {
    03473             BOOST_UBLAS_CHECK (i < size1_, bad_index ());
    03474             BOOST_UBLAS_CHECK (j < size2_, bad_index ());
    03475             return data_ [i] [j];
    03476         }
    03477         BOOST_UBLAS_INLINE
    03478         reference operator () (size_type i, size_type j) {
    03479             return at_element (i, j);
    03480         }
    03481
    03482         // Element assignment
    03483         BOOST_UBLAS_INLINE
    03484         reference insert_element (size_type i, size_type j, const_reference t) {
    03485             return (at_element (i, j) = t);
    03486         }
    03487
    03488         // Zeroing
    03489         BOOST_UBLAS_INLINE
    03490         void clear () {
    03491             for (size_type i = 0; i < size1_; ++ i)
    03492                 std::fill (data_ [i], data_ [i] + size2_, value_type/*zero*/());
    03493         }
    03494
    03495         // Assignment
    03496 #ifdef BOOST_UBLAS_MOVE_SEMANTICS
    03497
    03499         BOOST_UBLAS_INLINE
    03500         c_matrix &operator = (c_matrix m) {
    03501             assign_temporary(m);
    03502             return *this;
    03503         }
    03504 #else
    03505         BOOST_UBLAS_INLINE
    03506         c_matrix &operator = (const c_matrix &m) {
    03507             size1_ = m.size1_;
    03508             size2_ = m.size2_;
    03509             for (size_type i = 0; i < m.size1_; ++ i)
    03510                 std::copy (m.data_ [i], m.data_ [i] + m.size2_, data_ [i]);
    03511             return *this;
    03512         }
    03513 #endif
    03514         template<class C>          // Container assignment without temporary
    03515         BOOST_UBLAS_INLINE
    03516         c_matrix &operator = (const matrix_container<C> &m) {
    03517             resize (m ().size1 (), m ().size2 (), false);
    03518             assign (m);
    03519             return *this;
    03520         }
    03521         BOOST_UBLAS_INLINE
    03522         c_matrix &assign_temporary (c_matrix &m) {
    03523             swap (m);
    03524             return *this;
    03525         }
    03526         template<class AE>
    03527         BOOST_UBLAS_INLINE
    03528         c_matrix &operator = (const matrix_expression<AE> &ae) {
    03529             self_type temporary (ae);
    03530             return assign_temporary (temporary);
    03531         }
    03532         template<class AE>
    03533         BOOST_UBLAS_INLINE
    03534         c_matrix &assign (const matrix_expression<AE> &ae) {
    03535             matrix_assign<scalar_assign> (*this, ae);
    03536             return *this;
    03537         }
    03538         template<class AE>
    03539         BOOST_UBLAS_INLINE
    03540         c_matrix& operator += (const matrix_expression<AE> &ae) {
    03541             self_type temporary (*this + ae);
    03542             return assign_temporary (temporary);
    03543         }
    03544         template<class C>          // Container assignment without temporary
    03545         BOOST_UBLAS_INLINE
    03546         c_matrix &operator += (const matrix_container<C> &m) {
    03547             plus_assign (m);
    03548             return *this;
    03549         }
    03550         template<class AE>
    03551         BOOST_UBLAS_INLINE
    03552         c_matrix &plus_assign (const matrix_expression<AE> &ae) {
    03553             matrix_assign<scalar_plus_assign> (*this, ae);
    03554             return *this;
    03555         }
    03556         template<class AE>
    03557         BOOST_UBLAS_INLINE
    03558         c_matrix& operator -= (const matrix_expression<AE> &ae) {
    03559             self_type temporary (*this - ae);
    03560             return assign_temporary (temporary);
    03561         }
    03562         template<class C>          // Container assignment without temporary
    03563         BOOST_UBLAS_INLINE
    03564         c_matrix &operator -= (const matrix_container<C> &m) {
    03565             minus_assign (m);
    03566             return *this;
    03567         }
    03568         template<class AE>
    03569         BOOST_UBLAS_INLINE
    03570         c_matrix &minus_assign (const matrix_expression<AE> &ae) {
    03571             matrix_assign<scalar_minus_assign> (*this, ae);
    03572             return *this;
    03573         }
    03574         template<class AT>
    03575         BOOST_UBLAS_INLINE
    03576         c_matrix& operator *= (const AT &at) {
    03577             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
    03578             return *this;
    03579         }
    03580         template<class AT>
    03581         BOOST_UBLAS_INLINE
    03582         c_matrix& operator /= (const AT &at) {
    03583             matrix_assign_scalar<scalar_divides_assign> (*this, at);
    03584             return *this;
    03585         }
    03586
    03587         // Swapping
    03588         BOOST_UBLAS_INLINE
    03589         void swap (c_matrix &m) {
    03590             if (this != &m) {
    03591                 BOOST_UBLAS_CHECK (size1_ == m.size1_, bad_size ());
    03592                 BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ());
    03593                 std::swap (size1_, m.size1_);
    03594                 std::swap (size2_, m.size2_);
    03595                 for (size_type i = 0; i < size1_; ++ i)
    03596                     std::swap_ranges (data_ [i], data_ [i] + size2_, m.data_ [i]);
    03597             }
    03598         }
    03599         BOOST_UBLAS_INLINE
    03600         friend void swap (c_matrix &m1, c_matrix &m2) {
    03601             m1.swap (m2);
    03602         }
    03603
    03604         // Iterator types
    03605     private:
    03606         // Use pointers for iterator
    03607         typedef const_pointer const_subiterator_type;
    03608         typedef pointer subiterator_type;
    03609
    03610     public:
    03611 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03612         typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
    03613         typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
    03614         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
    03615         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
    03616 #else
    03617         class const_iterator1;
    03618         class iterator1;
    03619         class const_iterator2;
    03620         class iterator2;
    03621 #endif
    03622         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    03623         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
    03624         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    03625         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
    03626
    03627         // Element lookup
    03628         BOOST_UBLAS_INLINE
    03629         const_iterator1 find1 (int rank, size_type i, size_type j) const {
    03630 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03631             return const_iterator1 (*this, i, j);
    03632 #else
    03633             return const_iterator1 (*this, &data_ [i] [j]);
    03634 #endif
    03635         }
    03636         BOOST_UBLAS_INLINE
    03637         iterator1 find1 (int rank, size_type i, size_type j) {
    03638 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03639             return iterator1 (*this, i, j);
    03640 #else
    03641             return iterator1 (*this, &data_ [i] [j]);
    03642 #endif
    03643         }
    03644         BOOST_UBLAS_INLINE
    03645         const_iterator2 find2 (int rank, size_type i, size_type j) const {
    03646 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03647             return const_iterator2 (*this, i, j);
    03648 #else
    03649             return const_iterator2 (*this, &data_ [i] [j]);
    03650 #endif
    03651         }
    03652         BOOST_UBLAS_INLINE
    03653         iterator2 find2 (int rank, size_type i, size_type j) {
    03654 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03655             return iterator2 (*this, i, j);
    03656 #else
    03657             return iterator2 (*this, &data_ [i] [j]);
    03658 #endif
    03659         }
    03660
    03661
    03662 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03663         class const_iterator1:
    03664             public container_const_reference<c_matrix>,
    03665             public random_access_iterator_base<dense_random_access_iterator_tag,
    03666                                                const_iterator1, value_type> {
    03667         public:
    03668             typedef typename c_matrix::difference_type difference_type;
    03669             typedef typename c_matrix::value_type value_type;
    03670             typedef typename c_matrix::const_reference reference;
    03671             typedef typename c_matrix::const_pointer pointer;
    03672
    03673             typedef const_iterator2 dual_iterator_type;
    03674             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    03675
    03676             // Construction and destruction
    03677             BOOST_UBLAS_INLINE
    03678             const_iterator1 ():
    03679                 container_const_reference<self_type> (), it_ () {}
    03680             BOOST_UBLAS_INLINE
    03681             const_iterator1 (const self_type &m, const const_subiterator_type &it):
    03682                 container_const_reference<self_type> (m), it_ (it) {}
    03683             BOOST_UBLAS_INLINE
    03684             const_iterator1 (const iterator1 &it):
    03685                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
    03686
    03687             // Arithmetic
    03688             BOOST_UBLAS_INLINE
    03689             const_iterator1 &operator ++ () {
    03690                 it_ += M;
    03691                 return *this;
    03692             }
    03693             BOOST_UBLAS_INLINE
    03694             const_iterator1 &operator -- () {
    03695                 it_ -= M;
    03696                 return *this;
    03697             }
    03698             BOOST_UBLAS_INLINE
    03699             const_iterator1 &operator += (difference_type n) {
    03700                 it_ += n * M;
    03701                 return *this;
    03702             }
    03703             BOOST_UBLAS_INLINE
    03704             const_iterator1 &operator -= (difference_type n) {
    03705                 it_ -= n * M;
    03706                 return *this;
    03707             }
    03708             BOOST_UBLAS_INLINE
    03709             difference_type operator - (const const_iterator1 &it) const {
    03710                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03711                 return (it_ - it.it_) / M;
    03712             }
    03713
    03714             // Dereference
    03715             BOOST_UBLAS_INLINE
    03716             const_reference operator * () const {
    03717                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    03718                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    03719                 return *it_;
    03720             }
    03721             BOOST_UBLAS_INLINE
    03722             const_reference operator [] (difference_type n) const {
    03723                 return *(*this + n);
    03724             }
    03725
    03726 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03727             BOOST_UBLAS_INLINE
    03728 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03729             typename self_type::
    03730 #endif
    03731             const_iterator2 begin () const {
    03732                 const self_type &m = (*this) ();
    03733                 return m.find2 (1, index1 (), 0);
    03734             }
    03735             BOOST_UBLAS_INLINE
    03736 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03737             typename self_type::
    03738 #endif
    03739             const_iterator2 end () const {
    03740                 const self_type &m = (*this) ();
    03741                 return m.find2 (1, index1 (), m.size2 ());
    03742             }
    03743             BOOST_UBLAS_INLINE
    03744 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03745             typename self_type::
    03746 #endif
    03747             const_reverse_iterator2 rbegin () const {
    03748                 return const_reverse_iterator2 (end ());
    03749             }
    03750             BOOST_UBLAS_INLINE
    03751 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03752             typename self_type::
    03753 #endif
    03754             const_reverse_iterator2 rend () const {
    03755                 return const_reverse_iterator2 (begin ());
    03756             }
    03757 #endif
    03758
    03759             // Indices
    03760             BOOST_UBLAS_INLINE
    03761             size_type index1 () const {
    03762                 const self_type &m = (*this) ();
    03763                 return (it_ - m.begin1 ().it_) / M;
    03764             }
    03765             BOOST_UBLAS_INLINE
    03766             size_type index2 () const {
    03767                 const self_type &m = (*this) ();
    03768                 return (it_ - m.begin1 ().it_) % M;
    03769             }
    03770
    03771             // Assignment
    03772             BOOST_UBLAS_INLINE
    03773             const_iterator1 &operator = (const const_iterator1 &it) {
    03774                 container_const_reference<self_type>::assign (&it ());
    03775                 it_ = it.it_;
    03776                 return *this;
    03777             }
    03778
    03779             // Comparison
    03780             BOOST_UBLAS_INLINE
    03781             bool operator == (const const_iterator1 &it) const {
    03782                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03783                 return it_ == it.it_;
    03784             }
    03785             BOOST_UBLAS_INLINE
    03786             bool operator < (const const_iterator1 &it) const {
    03787                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03788                 return it_ < it.it_;
    03789             }
    03790
    03791         private:
    03792             const_subiterator_type it_;
    03793
    03794             friend class iterator1;
    03795         };
    03796 #endif
    03797
    03798         BOOST_UBLAS_INLINE
    03799         const_iterator1 begin1 () const {
    03800             return find1 (0, 0, 0);
    03801         }
    03802         BOOST_UBLAS_INLINE
    03803         const_iterator1 end1 () const {
    03804             return find1 (0, size1_, 0);
    03805         }
    03806
    03807 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03808         class iterator1:
    03809             public container_reference<c_matrix>,
    03810             public random_access_iterator_base<dense_random_access_iterator_tag,
    03811                                                iterator1, value_type> {
    03812         public:
    03813
    03814             typedef typename c_matrix::difference_type difference_type;
    03815             typedef typename c_matrix::value_type value_type;
    03816             typedef typename c_matrix::reference reference;
    03817             typedef typename c_matrix::pointer pointer;
    03818
    03819             typedef iterator2 dual_iterator_type;
    03820             typedef reverse_iterator2 dual_reverse_iterator_type;
    03821
    03822             // Construction and destruction
    03823             BOOST_UBLAS_INLINE
    03824             iterator1 ():
    03825                 container_reference<self_type> (), it_ () {}
    03826             BOOST_UBLAS_INLINE
    03827             iterator1 (self_type &m, const subiterator_type &it):
    03828                 container_reference<self_type> (m), it_ (it) {}
    03829
    03830             // Arithmetic
    03831             BOOST_UBLAS_INLINE
    03832             iterator1 &operator ++ () {
    03833                 it_ += M;
    03834                 return *this;
    03835             }
    03836             BOOST_UBLAS_INLINE
    03837             iterator1 &operator -- () {
    03838                 it_ -= M;
    03839                 return *this;
    03840             }
    03841             BOOST_UBLAS_INLINE
    03842             iterator1 &operator += (difference_type n) {
    03843                 it_ += n * M;
    03844                 return *this;
    03845             }
    03846             BOOST_UBLAS_INLINE
    03847             iterator1 &operator -= (difference_type n) {
    03848                 it_ -= n * M;
    03849                 return *this;
    03850             }
    03851             BOOST_UBLAS_INLINE
    03852             difference_type operator - (const iterator1 &it) const {
    03853                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03854                 return (it_ - it.it_) / M;
    03855             }
    03856
    03857             // Dereference
    03858             BOOST_UBLAS_INLINE
    03859             reference operator * () const {
    03860                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    03861                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    03862                 return *it_;
    03863             }
    03864             BOOST_UBLAS_INLINE
    03865             reference operator [] (difference_type n) const {
    03866                 return *(*this + n);
    03867             }
    03868
    03869 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03870             BOOST_UBLAS_INLINE
    03871 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03872             typename self_type::
    03873 #endif
    03874             iterator2 begin () const {
    03875                 self_type &m = (*this) ();
    03876                 return m.find2 (1, index1 (), 0);
    03877             }
    03878             BOOST_UBLAS_INLINE
    03879 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03880             typename self_type::
    03881 #endif
    03882             iterator2 end () const {
    03883                 self_type &m = (*this) ();
    03884                 return m.find2 (1, index1 (), m.size2 ());
    03885             }
    03886             BOOST_UBLAS_INLINE
    03887 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03888             typename self_type::
    03889 #endif
    03890             reverse_iterator2 rbegin () const {
    03891                 return reverse_iterator2 (end ());
    03892             }
    03893             BOOST_UBLAS_INLINE
    03894 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03895             typename self_type::
    03896 #endif
    03897             reverse_iterator2 rend () const {
    03898                 return reverse_iterator2 (begin ());
    03899             }
    03900 #endif
    03901
    03902             // Indices
    03903             BOOST_UBLAS_INLINE
    03904             size_type index1 () const {
    03905                 const self_type &m = (*this) ();
    03906                 return (it_ - m.begin1 ().it_) / M;
    03907             }
    03908             BOOST_UBLAS_INLINE
    03909             size_type index2 () const {
    03910                 const self_type &m = (*this) ();
    03911                 return (it_ - m.begin1 ().it_) % M;
    03912             }
    03913
    03914             // Assignment
    03915             BOOST_UBLAS_INLINE
    03916             iterator1 &operator = (const iterator1 &it) {
    03917                 container_reference<self_type>::assign (&it ());
    03918                 it_ = it.it_;
    03919                 return *this;
    03920             }
    03921
    03922             // Comparison
    03923             BOOST_UBLAS_INLINE
    03924             bool operator == (const iterator1 &it) const {
    03925                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03926                 return it_ == it.it_;
    03927             }
    03928             BOOST_UBLAS_INLINE
    03929             bool operator < (const iterator1 &it) const {
    03930                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03931                 return it_ < it.it_;
    03932             }
    03933
    03934         private:
    03935             subiterator_type it_;
    03936
    03937             friend class const_iterator1;
    03938         };
    03939 #endif
    03940
    03941         BOOST_UBLAS_INLINE
    03942         iterator1 begin1 () {
    03943             return find1 (0, 0, 0);
    03944         }
    03945         BOOST_UBLAS_INLINE
    03946         iterator1 end1 () {
    03947             return find1 (0, size1_, 0);
    03948         }
    03949
    03950 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03951         class const_iterator2:
    03952             public container_const_reference<c_matrix>,
    03953             public random_access_iterator_base<dense_random_access_iterator_tag,
    03954                                                const_iterator2, value_type> {
    03955         public:
    03956             typedef typename c_matrix::difference_type difference_type;
    03957             typedef typename c_matrix::value_type value_type;
    03958             typedef typename c_matrix::const_reference reference;
    03959             typedef typename c_matrix::const_reference pointer;
    03960
    03961             typedef const_iterator1 dual_iterator_type;
    03962             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    03963
    03964             // Construction and destruction
    03965             BOOST_UBLAS_INLINE
    03966             const_iterator2 ():
    03967                 container_const_reference<self_type> (), it_ () {}
    03968             BOOST_UBLAS_INLINE
    03969             const_iterator2 (const self_type &m, const const_subiterator_type &it):
    03970                 container_const_reference<self_type> (m), it_ (it) {}
    03971             BOOST_UBLAS_INLINE
    03972             const_iterator2 (const iterator2 &it):
    03973                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
    03974
    03975             // Arithmetic
    03976             BOOST_UBLAS_INLINE
    03977             const_iterator2 &operator ++ () {
    03978                 ++ it_;
    03979                 return *this;
    03980             }
    03981             BOOST_UBLAS_INLINE
    03982             const_iterator2 &operator -- () {
    03983                 -- it_;
    03984                 return *this;
    03985             }
    03986             BOOST_UBLAS_INLINE
    03987             const_iterator2 &operator += (difference_type n) {
    03988                 it_ += n;
    03989                 return *this;
    03990             }
    03991             BOOST_UBLAS_INLINE
    03992             const_iterator2 &operator -= (difference_type n) {
    03993                 it_ -= n;
    03994                 return *this;
    03995             }
    03996             BOOST_UBLAS_INLINE
    03997             difference_type operator - (const const_iterator2 &it) const {
    03998                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    03999                 return it_ - it.it_;
    04000             }
    04001
    04002             // Dereference
    04003             BOOST_UBLAS_INLINE
    04004             const_reference operator * () const {
    04005                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    04006                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    04007                 return *it_;
    04008             }
    04009             BOOST_UBLAS_INLINE
    04010             const_reference operator [] (difference_type n) const {
    04011                 return *(*this + n);
    04012             }
    04013
    04014 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    04015             BOOST_UBLAS_INLINE
    04016 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04017             typename self_type::
    04018 #endif
    04019             const_iterator1 begin () const {
    04020                 const self_type &m = (*this) ();
    04021                 return m.find1 (1, 0, index2 ());
    04022             }
    04023             BOOST_UBLAS_INLINE
    04024 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04025             typename self_type::
    04026 #endif
    04027             const_iterator1 end () const {
    04028                 const self_type &m = (*this) ();
    04029                 return m.find1 (1, m.size1 (), index2 ());
    04030             }
    04031             BOOST_UBLAS_INLINE
    04032 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04033             typename self_type::
    04034 #endif
    04035             const_reverse_iterator1 rbegin () const {
    04036                 return const_reverse_iterator1 (end ());
    04037             }
    04038             BOOST_UBLAS_INLINE
    04039 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04040             typename self_type::
    04041 #endif
    04042             const_reverse_iterator1 rend () const {
    04043                 return const_reverse_iterator1 (begin ());
    04044             }
    04045 #endif
    04046
    04047             // Indices
    04048             BOOST_UBLAS_INLINE
    04049             size_type index1 () const {
    04050                 const self_type &m = (*this) ();
    04051                 return (it_ - m.begin2 ().it_) / M;
    04052             }
    04053             BOOST_UBLAS_INLINE
    04054             size_type index2 () const {
    04055                 const self_type &m = (*this) ();
    04056                 return (it_ - m.begin2 ().it_) % M;
    04057             }
    04058
    04059             // Assignment
    04060             BOOST_UBLAS_INLINE
    04061             const_iterator2 &operator = (const const_iterator2 &it) {
    04062                 container_const_reference<self_type>::assign (&it ());
    04063                 it_ = it.it_;
    04064                 return *this;
    04065             }
    04066
    04067             // Comparison
    04068             BOOST_UBLAS_INLINE
    04069             bool operator == (const const_iterator2 &it) const {
    04070                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    04071                 return it_ == it.it_;
    04072             }
    04073             BOOST_UBLAS_INLINE
    04074             bool operator < (const const_iterator2 &it) const {
    04075                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    04076                 return it_ < it.it_;
    04077             }
    04078
    04079         private:
    04080             const_subiterator_type it_;
    04081
    04082             friend class iterator2;
    04083         };
    04084 #endif
    04085
    04086         BOOST_UBLAS_INLINE
    04087         const_iterator2 begin2 () const {
    04088             return find2 (0, 0, 0);
    04089         }
    04090         BOOST_UBLAS_INLINE
    04091         const_iterator2 end2 () const {
    04092             return find2 (0, 0, size2_);
    04093         }
    04094
    04095 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04096         class iterator2:
    04097             public container_reference<c_matrix>,
    04098             public random_access_iterator_base<dense_random_access_iterator_tag,
    04099                                                iterator2, value_type> {
    04100         public:
    04101             typedef typename c_matrix::difference_type difference_type;
    04102             typedef typename c_matrix::value_type value_type;
    04103             typedef typename c_matrix::reference reference;
    04104             typedef typename c_matrix::pointer pointer;
    04105
    04106             typedef iterator1 dual_iterator_type;
    04107             typedef reverse_iterator1 dual_reverse_iterator_type;
    04108
    04109             // Construction and destruction
    04110             BOOST_UBLAS_INLINE
    04111             iterator2 ():
    04112                 container_reference<self_type> (), it_ () {}
    04113             BOOST_UBLAS_INLINE
    04114             iterator2 (self_type &m, const subiterator_type &it):
    04115                 container_reference<self_type> (m), it_ (it) {}
    04116
    04117             // Arithmetic
    04118             BOOST_UBLAS_INLINE
    04119             iterator2 &operator ++ () {
    04120                 ++ it_;
    04121                 return *this;
    04122             }
    04123             BOOST_UBLAS_INLINE
    04124             iterator2 &operator -- () {
    04125                 -- it_;
    04126                 return *this;
    04127             }
    04128             BOOST_UBLAS_INLINE
    04129             iterator2 &operator += (difference_type n) {
    04130                 it_ += n;
    04131                 return *this;
    04132             }
    04133             BOOST_UBLAS_INLINE
    04134             iterator2 &operator -= (difference_type n) {
    04135                 it_ -= n;
    04136                 return *this;
    04137             }
    04138             BOOST_UBLAS_INLINE
    04139             difference_type operator - (const iterator2 &it) const {
    04140                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    04141                 return it_ - it.it_;
    04142             }
    04143
    04144             // Dereference
    04145             BOOST_UBLAS_INLINE
    04146             reference operator * () const {
    04147                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
    04148                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
    04149                 return *it_;
    04150             }
    04151             BOOST_UBLAS_INLINE
    04152             reference operator [] (difference_type n) const {
    04153                 return *(*this + n);
    04154             }
    04155
    04156 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    04157             BOOST_UBLAS_INLINE
    04158 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04159             typename self_type::
    04160 #endif
    04161             iterator1 begin () const {
    04162                 self_type &m = (*this) ();
    04163                 return m.find1 (1, 0, index2 ());
    04164             }
    04165             BOOST_UBLAS_INLINE
    04166 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04167             typename self_type::
    04168 #endif
    04169             iterator1 end () const {
    04170                 self_type &m = (*this) ();
    04171                 return m.find1 (1, m.size1 (), index2 ());
    04172             }
    04173             BOOST_UBLAS_INLINE
    04174 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04175             typename self_type::
    04176 #endif
    04177             reverse_iterator1 rbegin () const {
    04178                 return reverse_iterator1 (end ());
    04179             }
    04180             BOOST_UBLAS_INLINE
    04181 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04182             typename self_type::
    04183 #endif
    04184             reverse_iterator1 rend () const {
    04185                 return reverse_iterator1 (begin ());
    04186             }
    04187 #endif
    04188
    04189             // Indices
    04190             BOOST_UBLAS_INLINE
    04191             size_type index1 () const {
    04192                 const self_type &m = (*this) ();
    04193                 return (it_ - m.begin2 ().it_) / M;
    04194             }
    04195             BOOST_UBLAS_INLINE
    04196             size_type index2 () const {
    04197                 const self_type &m = (*this) ();
    04198                 return (it_ - m.begin2 ().it_) % M;
    04199             }
    04200
    04201             // Assignment
    04202             BOOST_UBLAS_INLINE
    04203             iterator2 &operator = (const iterator2 &it) {
    04204                 container_reference<self_type>::assign (&it ());
    04205                 it_ = it.it_;
    04206                 return *this;
    04207             }
    04208
    04209             // Comparison
    04210             BOOST_UBLAS_INLINE
    04211             bool operator == (const iterator2 &it) const {
    04212                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    04213                 return it_ == it.it_;
    04214             }
    04215             BOOST_UBLAS_INLINE
    04216             bool operator < (const iterator2 &it) const {
    04217                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
    04218                 return it_ < it.it_;
    04219             }
    04220
    04221         private:
    04222             subiterator_type it_;
    04223
    04224             friend class const_iterator2;
    04225         };
    04226 #endif
    04227
    04228         BOOST_UBLAS_INLINE
    04229         iterator2 begin2 () {
    04230             return find2 (0, 0, 0);
    04231         }
    04232         BOOST_UBLAS_INLINE
    04233         iterator2 end2 () {
    04234             return find2 (0, 0, size2_);
    04235         }
    04236
    04237         // Reverse iterators
    04238
    04239         BOOST_UBLAS_INLINE
    04240         const_reverse_iterator1 rbegin1 () const {
    04241             return const_reverse_iterator1 (end1 ());
    04242         }
    04243         BOOST_UBLAS_INLINE
    04244         const_reverse_iterator1 rend1 () const {
    04245             return const_reverse_iterator1 (begin1 ());
    04246         }
    04247
    04248         BOOST_UBLAS_INLINE
    04249         reverse_iterator1 rbegin1 () {
    04250             return reverse_iterator1 (end1 ());
    04251         }
    04252         BOOST_UBLAS_INLINE
    04253         reverse_iterator1 rend1 () {
    04254             return reverse_iterator1 (begin1 ());
    04255         }
    04256
    04257         BOOST_UBLAS_INLINE
    04258         const_reverse_iterator2 rbegin2 () const {
    04259             return const_reverse_iterator2 (end2 ());
    04260         }
    04261         BOOST_UBLAS_INLINE
    04262         const_reverse_iterator2 rend2 () const {
    04263             return const_reverse_iterator2 (begin2 ());
    04264         }
    04265
    04266         BOOST_UBLAS_INLINE
    04267         reverse_iterator2 rbegin2 () {
    04268             return reverse_iterator2 (end2 ());
    04269         }
    04270         BOOST_UBLAS_INLINE
    04271         reverse_iterator2 rend2 () {
    04272             return reverse_iterator2 (begin2 ());
    04273         }
    04274
    04275          // Serialization
    04276         template<class Archive>
    04277         void serialize(Archive & ar, const unsigned int /* file_version */){
    04278
    04279             // we need to copy to a collection_size_type to get a portable
    04280             // and efficient serialization
    04281             serialization::collection_size_type s1 (size1_);
    04282             serialization::collection_size_type s2 (size2_);
    04283
    04284             // serialize the sizes
    04285             ar & serialization::make_nvp("size1",s1)
    04286                & serialization::make_nvp("size2",s2);
    04287
    04288             // copy the values back if loading
    04289             if (Archive::is_loading::value) {
    04290                 size1_ = s1;
    04291                 size2_ = s2;
    04292             }
    04293             // could probably use make_array( &(data[0][0]), N*M )
    04294             ar & serialization::make_array(data_, N);
    04295         }
    04296
    04297     private:
    04298         size_type size1_;
    04299         size_type size2_;
    04300         value_type data_ [N] [M];
    04301     };
    04302
    04303 }}}
    04304
    04305 #endif