Boost.uBlas 1.49
Linear Algebra in C++: matrices, vectors and numeric algorithms

matrix.hpp

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