os/ossrv/ossrv_pub/boost_apis/boost/numeric/ublas/matrix.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 //
     2 //  Copyright (c) 2000-2002
     3 //  Joerg Walter, Mathias Koch
     4 //
     5 //  Permission to use, copy, modify, distribute and sell this software
     6 //  and its documentation for any purpose is hereby granted without fee,
     7 //  provided that the above copyright notice appear in all copies and
     8 //  that both that copyright notice and this permission notice appear
     9 //  in supporting documentation.  The authors make no representations
    10 //  about the suitability of this software for any purpose.
    11 //  It is provided "as is" without express or implied warranty.
    12 //
    13 //  The authors gratefully acknowledge the support of
    14 //  GeNeSys mbH & Co. KG in producing this work.
    15 //
    16 
    17 #ifndef _BOOST_UBLAS_MATRIX_
    18 #define _BOOST_UBLAS_MATRIX_
    19 
    20 #include <boost/numeric/ublas/vector.hpp>
    21 #include <boost/numeric/ublas/matrix_expression.hpp>
    22 #include <boost/numeric/ublas/detail/matrix_assign.hpp>
    23 
    24 // Iterators based on ideas of Jeremy Siek
    25 
    26 namespace boost { namespace numeric { namespace ublas {
    27 
    28     namespace detail {
    29         using namespace boost::numeric::ublas;
    30 
    31         // Matrix resizing algorithm
    32         template <class L, class M>
    33         BOOST_UBLAS_INLINE
    34         void matrix_resize_preserve (M& m, M& temporary) {
    35             typedef L layout_type;
    36             typedef typename M::size_type size_type;
    37             const size_type msize1 (m.size1 ());        // original size
    38             const size_type msize2 (m.size2 ());
    39             const size_type size1 (temporary.size1 ());    // new size is specified by temporary
    40             const size_type size2 (temporary.size2 ());
    41             // Common elements to preserve
    42             const size_type size1_min = (std::min) (size1, msize1);
    43             const size_type size2_min = (std::min) (size2, msize2);
    44             // Order loop for i-major and j-minor sizes
    45             const size_type i_size = layout_type::size1 (size1_min, size2_min);
    46             const size_type j_size = layout_type::size2 (size1_min, size2_min);
    47             for (size_type i = 0; i != i_size; ++i) {    // indexing copy over major
    48                 for (size_type j = 0; j != j_size; ++j) {
    49                     const size_type element1 = layout_type::element1(i,i_size, j,j_size);
    50                     const size_type element2 = layout_type::element2(i,i_size, j,j_size);
    51                     temporary.data () [layout_type::element (element1, size1, element2, size2)] =
    52                             m.data() [layout_type::element (element1, msize1, element2, msize2)];
    53                 }
    54             }
    55             m.assign_temporary (temporary);
    56         }
    57     }
    58 
    59 
    60     // Array based matrix class
    61     template<class T, class L, class A>
    62     class matrix:
    63         public matrix_container<matrix<T, L, A> > {
    64 
    65         typedef T *pointer;
    66         typedef L layout_type;
    67         typedef matrix<T, L, A> self_type;
    68     public:
    69 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    70         using matrix_container<self_type>::operator ();
    71 #endif
    72         typedef typename A::size_type size_type;
    73         typedef typename A::difference_type difference_type;
    74         typedef T value_type;
    75         typedef const T &const_reference;
    76         typedef T &reference;
    77         typedef A array_type;
    78         typedef const matrix_reference<const self_type> const_closure_type;
    79         typedef matrix_reference<self_type> closure_type;
    80         typedef vector<T, A> vector_temporary_type;
    81         typedef self_type matrix_temporary_type;
    82         typedef dense_tag storage_category;
    83         // This could be better for performance,
    84         // typedef typename unknown_orientation_tag orientation_category;
    85         // but others depend on the orientation information...
    86         typedef typename L::orientation_category orientation_category;
    87 
    88         // Construction and destruction
    89         BOOST_UBLAS_INLINE
    90         matrix ():
    91             matrix_container<self_type> (),
    92             size1_ (0), size2_ (0), data_ () {}
    93         BOOST_UBLAS_INLINE
    94         matrix (size_type size1, size_type size2):
    95             matrix_container<self_type> (),
    96             size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2)) {
    97         }
    98         BOOST_UBLAS_INLINE
    99         matrix (size_type size1, size_type size2, const array_type &data):
   100             matrix_container<self_type> (),
   101             size1_ (size1), size2_ (size2), data_ (data) {}
   102         BOOST_UBLAS_INLINE
   103         matrix (const matrix &m):
   104             matrix_container<self_type> (),
   105             size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
   106         template<class AE>
   107         BOOST_UBLAS_INLINE
   108         matrix (const matrix_expression<AE> &ae):
   109             matrix_container<self_type> (),
   110             size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::storage_size (size1_, size2_)) {
   111             matrix_assign<scalar_assign> (*this, ae);
   112         }
   113 
   114         // Accessors
   115         BOOST_UBLAS_INLINE
   116         size_type size1 () const {
   117             return size1_;
   118         }
   119         BOOST_UBLAS_INLINE
   120         size_type size2 () const {
   121             return size2_;
   122         }
   123 
   124         // Storage accessors
   125         BOOST_UBLAS_INLINE
   126         const array_type &data () const {
   127             return data_;
   128         }
   129         BOOST_UBLAS_INLINE
   130         array_type &data () {
   131             return data_;
   132         }
   133 
   134         // Resizing
   135         BOOST_UBLAS_INLINE
   136         void resize (size_type size1, size_type size2, bool preserve = true) {
   137             if (preserve) {
   138                 self_type temporary (size1, size2);
   139                 detail::matrix_resize_preserve<layout_type> (*this, temporary);
   140             }
   141             else {
   142                 data ().resize (layout_type::storage_size (size1, size2));
   143                 size1_ = size1;
   144                 size2_ = size2;
   145             }
   146         }
   147 
   148         // Element access
   149         BOOST_UBLAS_INLINE
   150         const_reference operator () (size_type i, size_type j) const {
   151             return data () [layout_type::element (i, size1_, j, size2_)];
   152         }
   153         BOOST_UBLAS_INLINE
   154         reference at_element (size_type i, size_type j) {
   155             return data () [layout_type::element (i, size1_, j, size2_)];
   156         }
   157         BOOST_UBLAS_INLINE
   158         reference operator () (size_type i, size_type j) {
   159             return at_element (i, j);
   160         }
   161 
   162         // Element assignment
   163         BOOST_UBLAS_INLINE
   164         reference insert_element (size_type i, size_type j, const_reference t) {
   165             return (at_element (i, j) = t);
   166         }
   167         void erase_element (size_type i, size_type j) {
   168             at_element (i, j) = value_type/*zero*/();
   169         }
   170 
   171         // Zeroing
   172         BOOST_UBLAS_INLINE
   173         void clear () {
   174             std::fill (data ().begin (), data ().end (), value_type/*zero*/());
   175         }
   176 
   177         // Assignment
   178         BOOST_UBLAS_INLINE
   179         matrix &operator = (const matrix &m) {
   180             size1_ = m.size1_;
   181             size2_ = m.size2_;
   182             data () = m.data ();
   183             return *this;
   184         }
   185         template<class C>          // Container assignment without temporary
   186         BOOST_UBLAS_INLINE
   187         matrix &operator = (const matrix_container<C> &m) {
   188             resize (m ().size1 (), m ().size2 (), false);
   189             assign (m);
   190             return *this;
   191         }
   192         BOOST_UBLAS_INLINE
   193         matrix &assign_temporary (matrix &m) {
   194             swap (m);
   195             return *this;
   196         }
   197         template<class AE>
   198         BOOST_UBLAS_INLINE
   199         matrix &operator = (const matrix_expression<AE> &ae) {
   200             self_type temporary (ae);
   201             return assign_temporary (temporary);
   202         }
   203         template<class AE>
   204         BOOST_UBLAS_INLINE
   205         matrix &assign (const matrix_expression<AE> &ae) {
   206             matrix_assign<scalar_assign> (*this, ae);
   207             return *this;
   208         }
   209         template<class AE>
   210         BOOST_UBLAS_INLINE
   211         matrix& operator += (const matrix_expression<AE> &ae) {
   212             self_type temporary (*this + ae);
   213             return assign_temporary (temporary);
   214         }
   215         template<class C>          // Container assignment without temporary
   216         BOOST_UBLAS_INLINE
   217         matrix &operator += (const matrix_container<C> &m) {
   218             plus_assign (m);
   219             return *this;
   220         }
   221         template<class AE>
   222         BOOST_UBLAS_INLINE
   223         matrix &plus_assign (const matrix_expression<AE> &ae) {
   224             matrix_assign<scalar_plus_assign> (*this, ae);
   225             return *this;
   226         }
   227         template<class AE>
   228         BOOST_UBLAS_INLINE
   229         matrix& operator -= (const matrix_expression<AE> &ae) {
   230             self_type temporary (*this - ae);
   231             return assign_temporary (temporary);
   232         }
   233         template<class C>          // Container assignment without temporary
   234         BOOST_UBLAS_INLINE
   235         matrix &operator -= (const matrix_container<C> &m) {
   236             minus_assign (m);
   237             return *this;
   238         }
   239         template<class AE>
   240         BOOST_UBLAS_INLINE
   241         matrix &minus_assign (const matrix_expression<AE> &ae) {
   242             matrix_assign<scalar_minus_assign> (*this, ae);
   243             return *this;
   244         }
   245         template<class AT>
   246         BOOST_UBLAS_INLINE
   247         matrix& operator *= (const AT &at) {
   248             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
   249             return *this;
   250         }
   251         template<class AT>
   252         BOOST_UBLAS_INLINE
   253         matrix& operator /= (const AT &at) {
   254             matrix_assign_scalar<scalar_divides_assign> (*this, at);
   255             return *this;
   256         }
   257 
   258         // Swapping
   259         BOOST_UBLAS_INLINE
   260         void swap (matrix &m) {
   261             if (this != &m) {
   262                 std::swap (size1_, m.size1_);
   263                 std::swap (size2_, m.size2_);
   264                 data ().swap (m.data ());
   265             }
   266         }
   267         BOOST_UBLAS_INLINE
   268         friend void swap (matrix &m1, matrix &m2) {
   269             m1.swap (m2);
   270         }
   271 
   272         // Iterator types
   273     private:
   274         // Use the storage array iterator
   275         typedef typename A::const_iterator const_subiterator_type;
   276         typedef typename A::iterator subiterator_type;
   277 
   278     public:
   279 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
   280         typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
   281         typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
   282         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
   283         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
   284 #else
   285         class const_iterator1;
   286         class iterator1;
   287         class const_iterator2;
   288         class iterator2;
   289 #endif
   290         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
   291         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
   292         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
   293         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
   294 
   295         // Element lookup
   296         BOOST_UBLAS_INLINE
   297         const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
   298 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
   299             return const_iterator1 (*this, i, j);
   300 #else
   301             return const_iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
   302 #endif
   303         }
   304         BOOST_UBLAS_INLINE
   305         iterator1 find1 (int /* rank */, size_type i, size_type j) {
   306 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
   307             return iterator1 (*this, i, j);
   308 #else
   309             return iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
   310 #endif
   311         }
   312         BOOST_UBLAS_INLINE
   313         const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
   314 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
   315             return const_iterator2 (*this, i, j);
   316 #else
   317             return const_iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
   318 #endif
   319         }
   320         BOOST_UBLAS_INLINE
   321         iterator2 find2 (int /* rank */, size_type i, size_type j) {
   322 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
   323             return iterator2 (*this, i, j);
   324 #else
   325             return iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
   326 #endif
   327         }
   328 
   329 
   330 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
   331         class const_iterator1:
   332             public container_const_reference<matrix>,
   333             public random_access_iterator_base<dense_random_access_iterator_tag,
   334                                                const_iterator1, value_type> {
   335         public:
   336             typedef typename matrix::value_type value_type;
   337             typedef typename matrix::difference_type difference_type;
   338             typedef typename matrix::const_reference reference;
   339             typedef const typename matrix::pointer pointer;
   340 
   341             typedef const_iterator2 dual_iterator_type;
   342             typedef const_reverse_iterator2 dual_reverse_iterator_type;
   343 
   344             // Construction and destruction
   345             BOOST_UBLAS_INLINE
   346             const_iterator1 ():
   347                 container_const_reference<self_type> (), it_ () {}
   348             BOOST_UBLAS_INLINE
   349             const_iterator1 (const self_type &m, const const_subiterator_type &it):
   350                 container_const_reference<self_type> (m), it_ (it) {}
   351             BOOST_UBLAS_INLINE
   352             const_iterator1 (const iterator1 &it):
   353                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
   354 
   355             // Arithmetic
   356             BOOST_UBLAS_INLINE
   357             const_iterator1 &operator ++ () {
   358                 layout_type::increment1 (it_, (*this) ().size1 (), (*this) ().size2 ());
   359                 return *this;
   360             }
   361             BOOST_UBLAS_INLINE
   362             const_iterator1 &operator -- () {
   363                 layout_type::decrement1 (it_, (*this) ().size1 (), (*this) ().size2 ());
   364                 return *this;
   365             }
   366             BOOST_UBLAS_INLINE
   367             const_iterator1 &operator += (difference_type n) {
   368                 it_ += n * layout_type::one1 ((*this) ().size1 (), (*this) ().size2 ());
   369                 return *this;
   370             }
   371             BOOST_UBLAS_INLINE
   372             const_iterator1 &operator -= (difference_type n) {
   373                 it_ -= n * layout_type::one1 ((*this) ().size1 (), (*this) ().size2 ());
   374                 return *this;
   375             }
   376             BOOST_UBLAS_INLINE
   377             difference_type operator - (const const_iterator1 &it) const {
   378                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   379                 return layout_type::distance1 (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
   380             }
   381 
   382             // Dereference
   383             BOOST_UBLAS_INLINE
   384             const_reference operator * () const {
   385                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
   386                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
   387                 return *it_;
   388             }
   389             BOOST_UBLAS_INLINE
   390             const_reference operator [] (difference_type n) const {
   391                 return *(*this + n);
   392             }
   393 
   394 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
   395             BOOST_UBLAS_INLINE
   396 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   397             typename self_type::
   398 #endif
   399             const_iterator2 begin () const {
   400                 const self_type &m = (*this) ();
   401                 return m.find2 (1, index1 (), 0);
   402             }
   403             BOOST_UBLAS_INLINE
   404 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   405             typename self_type::
   406 #endif
   407             const_iterator2 end () const {
   408                 const self_type &m = (*this) ();
   409                 return m.find2 (1, index1 (), m.size2 ());
   410             }
   411             BOOST_UBLAS_INLINE
   412 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   413             typename self_type::
   414 #endif
   415             const_reverse_iterator2 rbegin () const {
   416                 return const_reverse_iterator2 (end ());
   417             }
   418             BOOST_UBLAS_INLINE
   419 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   420             typename self_type::
   421 #endif
   422             const_reverse_iterator2 rend () const {
   423                 return const_reverse_iterator2 (begin ());
   424             }
   425 #endif
   426 
   427             // Indices
   428             BOOST_UBLAS_INLINE
   429             size_type index1 () const {
   430                 const self_type &m = (*this) ();
   431                 return layout_type::index1 (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
   432             }
   433             BOOST_UBLAS_INLINE
   434             size_type index2 () const {
   435                 const self_type &m = (*this) ();
   436                 return layout_type::index2 (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
   437             }
   438 
   439             // Assignment
   440             BOOST_UBLAS_INLINE
   441             const_iterator1 &operator = (const const_iterator1 &it) {
   442                 container_const_reference<self_type>::assign (&it ());
   443                 it_ = it.it_;
   444                 return *this;
   445             }
   446 
   447             // Comparison
   448             BOOST_UBLAS_INLINE
   449             bool operator == (const const_iterator1 &it) const {
   450                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   451                 return it_ == it.it_;
   452             }
   453             BOOST_UBLAS_INLINE
   454             bool operator < (const const_iterator1 &it) const {
   455                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   456                 return it_ < it.it_;
   457             }
   458 
   459         private:
   460             const_subiterator_type it_;
   461 
   462             friend class iterator1;
   463         };
   464 #endif
   465 
   466         BOOST_UBLAS_INLINE
   467         const_iterator1 begin1 () const {
   468             return find1 (0, 0, 0);
   469         }
   470         BOOST_UBLAS_INLINE
   471         const_iterator1 end1 () const {
   472             return find1 (0, size1_, 0);
   473         }
   474 
   475 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
   476         class iterator1:
   477             public container_reference<matrix>,
   478             public random_access_iterator_base<dense_random_access_iterator_tag,
   479                                                iterator1, value_type> {
   480         public:
   481             typedef typename matrix::value_type value_type;
   482             typedef typename matrix::difference_type difference_type;
   483             typedef typename matrix::reference reference;
   484             typedef typename matrix::pointer pointer;
   485 
   486             typedef iterator2 dual_iterator_type;
   487             typedef reverse_iterator2 dual_reverse_iterator_type;
   488 
   489             // Construction and destruction
   490             BOOST_UBLAS_INLINE
   491             iterator1 ():
   492                 container_reference<self_type> (), it_ () {}
   493             BOOST_UBLAS_INLINE
   494             iterator1 (self_type &m, const subiterator_type &it):
   495                 container_reference<self_type> (m), it_ (it) {}
   496 
   497             // Arithmetic
   498             BOOST_UBLAS_INLINE
   499             iterator1 &operator ++ () {
   500                 layout_type::increment1 (it_, (*this) ().size1 (), (*this) ().size2 ());
   501                 return *this;
   502             }
   503             BOOST_UBLAS_INLINE
   504             iterator1 &operator -- () {
   505                 layout_type::decrement1 (it_, (*this) ().size1 (), (*this) ().size2 ());
   506                 return *this;
   507             }
   508             BOOST_UBLAS_INLINE
   509             iterator1 &operator += (difference_type n) {
   510                 it_ += n * layout_type::one1 ((*this) ().size1 (), (*this) ().size2 ());
   511                 return *this;
   512             }
   513             BOOST_UBLAS_INLINE
   514             iterator1 &operator -= (difference_type n) {
   515                 it_ -= n * layout_type::one1 ((*this) ().size1 (), (*this) ().size2 ());
   516                 return *this;
   517             }
   518             BOOST_UBLAS_INLINE
   519             difference_type operator - (const iterator1 &it) const {
   520                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   521                 return layout_type::distance1 (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
   522             }
   523 
   524             // Dereference
   525             BOOST_UBLAS_INLINE
   526             reference operator * () const {
   527                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
   528                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
   529                 return *it_;
   530             }
   531             BOOST_UBLAS_INLINE
   532             reference operator [] (difference_type n) const {
   533                 return *(*this + n);
   534             }
   535 
   536 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
   537             BOOST_UBLAS_INLINE
   538 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   539             typename self_type::
   540 #endif
   541             iterator2 begin () const {
   542                 self_type &m = (*this) ();
   543                 return m.find2 (1, index1 (), 0);
   544             }
   545             BOOST_UBLAS_INLINE
   546 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   547             typename self_type::
   548 #endif
   549             iterator2 end () const {
   550                 self_type &m = (*this) ();
   551                 return m.find2 (1, index1 (), m.size2 ());
   552             }
   553             BOOST_UBLAS_INLINE
   554 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   555             typename self_type::
   556 #endif
   557             reverse_iterator2 rbegin () const {
   558                 return reverse_iterator2 (end ());
   559             }
   560             BOOST_UBLAS_INLINE
   561 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   562             typename self_type::
   563 #endif
   564             reverse_iterator2 rend () const {
   565                 return reverse_iterator2 (begin ());
   566             }
   567 #endif
   568 
   569             // Indices
   570             BOOST_UBLAS_INLINE
   571             size_type index1 () const {
   572                 self_type &m = (*this) ();
   573                 return layout_type::index1 (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
   574             }
   575             BOOST_UBLAS_INLINE
   576             size_type index2 () const {
   577                 self_type &m = (*this) ();
   578                 return layout_type::index2 (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
   579             }
   580 
   581             // Assignment
   582             BOOST_UBLAS_INLINE
   583             iterator1 &operator = (const iterator1 &it) {
   584                 container_reference<self_type>::assign (&it ());
   585                 it_ = it.it_;
   586                 return *this;
   587             }
   588 
   589             // Comparison
   590             BOOST_UBLAS_INLINE
   591             bool operator == (const iterator1 &it) const {
   592                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   593                 return it_ == it.it_;
   594             }
   595             BOOST_UBLAS_INLINE
   596             bool operator < (const iterator1 &it) const {
   597                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   598                 return it_ < it.it_;
   599             }
   600 
   601         private:
   602             subiterator_type it_;
   603 
   604             friend class const_iterator1;
   605         };
   606 #endif
   607 
   608         BOOST_UBLAS_INLINE
   609         iterator1 begin1 () {
   610             return find1 (0, 0, 0);
   611         }
   612         BOOST_UBLAS_INLINE
   613         iterator1 end1 () {
   614             return find1 (0, size1_, 0);
   615         }
   616 
   617 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
   618         class const_iterator2:
   619             public container_const_reference<matrix>,
   620             public random_access_iterator_base<dense_random_access_iterator_tag,
   621                                                const_iterator2, value_type> {
   622         public:
   623             typedef typename matrix::value_type value_type;
   624             typedef typename matrix::difference_type difference_type;
   625             typedef typename matrix::const_reference reference;
   626             typedef const typename matrix::pointer pointer;
   627 
   628             typedef const_iterator1 dual_iterator_type;
   629             typedef const_reverse_iterator1 dual_reverse_iterator_type;
   630 
   631             // Construction and destruction
   632             BOOST_UBLAS_INLINE
   633             const_iterator2 ():
   634                 container_const_reference<self_type> (), it_ () {}
   635             BOOST_UBLAS_INLINE
   636             const_iterator2 (const self_type &m, const const_subiterator_type &it):
   637                 container_const_reference<self_type> (m), it_ (it) {}
   638             BOOST_UBLAS_INLINE
   639             const_iterator2 (const iterator2 &it):
   640                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
   641 
   642             // Arithmetic
   643             BOOST_UBLAS_INLINE
   644             const_iterator2 &operator ++ () {
   645                 layout_type::increment2 (it_, (*this) ().size1 (), (*this) ().size2 ());
   646                 return *this;
   647             }
   648             BOOST_UBLAS_INLINE
   649             const_iterator2 &operator -- () {
   650                 layout_type::decrement2 (it_, (*this) ().size1 (), (*this) ().size2 ());
   651                 return *this;
   652             }
   653             BOOST_UBLAS_INLINE
   654             const_iterator2 &operator += (difference_type n) {
   655                 it_ += n * layout_type::one2 ((*this) ().size1 (), (*this) ().size2 ());
   656                 return *this;
   657             }
   658             BOOST_UBLAS_INLINE
   659             const_iterator2 &operator -= (difference_type n) {
   660                 it_ -= n * layout_type::one2 ((*this) ().size1 (), (*this) ().size2 ());
   661                 return *this;
   662             }
   663             BOOST_UBLAS_INLINE
   664             difference_type operator - (const const_iterator2 &it) const {
   665                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   666                 return layout_type::distance2 (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
   667             }
   668 
   669             // Dereference
   670             BOOST_UBLAS_INLINE
   671             const_reference operator * () const {
   672                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
   673                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
   674                 return *it_;
   675             }
   676             BOOST_UBLAS_INLINE
   677             const_reference operator [] (difference_type n) const {
   678                 return *(*this + n);
   679             }
   680 
   681 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
   682             BOOST_UBLAS_INLINE
   683 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   684             typename self_type::
   685 #endif
   686             const_iterator1 begin () const {
   687                 const self_type &m = (*this) ();
   688                 return m.find1 (1, 0, index2 ());
   689             }
   690             BOOST_UBLAS_INLINE
   691 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   692             typename self_type::
   693 #endif
   694             const_iterator1 end () const {
   695                 const self_type &m = (*this) ();
   696                 return m.find1 (1, m.size1 (), index2 ());
   697             }
   698             BOOST_UBLAS_INLINE
   699 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   700             typename self_type::
   701 #endif
   702             const_reverse_iterator1 rbegin () const {
   703                 return const_reverse_iterator1 (end ());
   704             }
   705             BOOST_UBLAS_INLINE
   706 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   707             typename self_type::
   708 #endif
   709             const_reverse_iterator1 rend () const {
   710                 return const_reverse_iterator1 (begin ());
   711             }
   712 #endif
   713 
   714             // Indices
   715             BOOST_UBLAS_INLINE
   716             size_type index1 () const {
   717                 const self_type &m = (*this) ();
   718                 return layout_type::index1 (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
   719             }
   720             BOOST_UBLAS_INLINE
   721             size_type index2 () const {
   722                 const self_type &m = (*this) ();
   723                 return layout_type::index2 (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
   724             }
   725 
   726             // Assignment
   727             BOOST_UBLAS_INLINE
   728             const_iterator2 &operator = (const const_iterator2 &it) {
   729                 container_const_reference<self_type>::assign (&it ());
   730                 it_ = it.it_;
   731                 return *this;
   732             }
   733 
   734             // Comparison
   735             BOOST_UBLAS_INLINE
   736             bool operator == (const const_iterator2 &it) const {
   737                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   738                 return it_ == it.it_;
   739             }
   740             BOOST_UBLAS_INLINE
   741             bool operator < (const const_iterator2 &it) const {
   742                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   743                 return it_ < it.it_;
   744             }
   745 
   746         private:
   747             const_subiterator_type it_;
   748 
   749             friend class iterator2;
   750         };
   751 #endif
   752 
   753         BOOST_UBLAS_INLINE
   754         const_iterator2 begin2 () const {
   755             return find2 (0, 0, 0);
   756         }
   757         BOOST_UBLAS_INLINE
   758         const_iterator2 end2 () const {
   759             return find2 (0, 0, size2_);
   760         }
   761 
   762 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
   763         class iterator2:
   764             public container_reference<matrix>,
   765             public random_access_iterator_base<dense_random_access_iterator_tag,
   766                                                iterator2, value_type> {
   767         public:
   768             typedef typename matrix::value_type value_type;
   769             typedef typename matrix::difference_type difference_type;
   770             typedef typename matrix::reference reference;
   771             typedef typename matrix::pointer pointer;
   772 
   773             typedef iterator1 dual_iterator_type;
   774             typedef reverse_iterator1 dual_reverse_iterator_type;
   775 
   776             // Construction and destruction
   777             BOOST_UBLAS_INLINE
   778             iterator2 ():
   779                 container_reference<self_type> (), it_ () {}
   780             BOOST_UBLAS_INLINE
   781             iterator2 (self_type &m, const subiterator_type &it):
   782                 container_reference<self_type> (m), it_ (it) {}
   783 
   784             // Arithmetic
   785             BOOST_UBLAS_INLINE
   786             iterator2 &operator ++ () {
   787                 layout_type::increment2 (it_, (*this) ().size1 (), (*this) ().size2 ());
   788                 return *this;
   789             }
   790             BOOST_UBLAS_INLINE
   791             iterator2 &operator -- () {
   792                 layout_type::decrement2 (it_, (*this) ().size1 (), (*this) ().size2 ());
   793                 return *this;
   794             }
   795             BOOST_UBLAS_INLINE
   796             iterator2 &operator += (difference_type n) {
   797                 it_ += n * layout_type::one2 ((*this) ().size1 (), (*this) ().size2 ());
   798                 return *this;
   799             }
   800             BOOST_UBLAS_INLINE
   801             iterator2 &operator -= (difference_type n) {
   802                 it_ -= n * layout_type::one2 ((*this) ().size1 (), (*this) ().size2 ());
   803                 return *this;
   804             }
   805             BOOST_UBLAS_INLINE
   806             difference_type operator - (const iterator2 &it) const {
   807                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   808                 return layout_type::distance2 (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
   809             }
   810 
   811             // Dereference
   812             BOOST_UBLAS_INLINE
   813             reference operator * () const {
   814                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
   815                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
   816                 return *it_;
   817             }
   818             BOOST_UBLAS_INLINE
   819             reference operator [] (difference_type n) const {
   820                 return *(*this + n);
   821             }
   822 
   823 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
   824             BOOST_UBLAS_INLINE
   825 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   826             typename self_type::
   827 #endif
   828             iterator1 begin () const {
   829                 self_type &m = (*this) ();
   830                 return m.find1 (1, 0, index2 ());
   831             }
   832             BOOST_UBLAS_INLINE
   833 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   834             typename self_type::
   835 #endif
   836             iterator1 end () const {
   837                 self_type &m = (*this) ();
   838                 return m.find1 (1, m.size1 (), index2 ());
   839             }
   840             BOOST_UBLAS_INLINE
   841 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   842             typename self_type::
   843 #endif
   844             reverse_iterator1 rbegin () const {
   845                 return reverse_iterator1 (end ());
   846             }
   847             BOOST_UBLAS_INLINE
   848 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
   849             typename self_type::
   850 #endif
   851             reverse_iterator1 rend () const {
   852                 return reverse_iterator1 (begin ());
   853             }
   854 #endif
   855 
   856             // Indices
   857             BOOST_UBLAS_INLINE
   858             size_type index1 () const {
   859                 self_type &m = (*this) ();
   860                 return layout_type::index1 (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
   861             }
   862             BOOST_UBLAS_INLINE
   863             size_type index2 () const {
   864                 self_type &m = (*this) ();
   865                 return layout_type::index2 (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
   866             }
   867 
   868             // Assignment
   869             BOOST_UBLAS_INLINE
   870             iterator2 &operator = (const iterator2 &it) {
   871                 container_reference<self_type>::assign (&it ());
   872                 it_ = it.it_;
   873                 return *this;
   874             }
   875 
   876             // Comparison
   877             BOOST_UBLAS_INLINE
   878             bool operator == (const iterator2 &it) const {
   879                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   880                 return it_ == it.it_;
   881             }
   882             BOOST_UBLAS_INLINE
   883             bool operator < (const iterator2 &it) const {
   884                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
   885                 return it_ < it.it_;
   886             }
   887 
   888         private:
   889             subiterator_type it_;
   890 
   891             friend class const_iterator2;
   892         };
   893 #endif
   894 
   895         BOOST_UBLAS_INLINE
   896         iterator2 begin2 () {
   897             return find2 (0, 0, 0);
   898         }
   899         BOOST_UBLAS_INLINE
   900         iterator2 end2 () {
   901             return find2 (0, 0, size2_);
   902         }
   903 
   904         // Reverse iterators
   905 
   906         BOOST_UBLAS_INLINE
   907         const_reverse_iterator1 rbegin1 () const {
   908             return const_reverse_iterator1 (end1 ());
   909         }
   910         BOOST_UBLAS_INLINE
   911         const_reverse_iterator1 rend1 () const {
   912             return const_reverse_iterator1 (begin1 ());
   913         }
   914 
   915         BOOST_UBLAS_INLINE
   916         reverse_iterator1 rbegin1 () {
   917             return reverse_iterator1 (end1 ());
   918         }
   919         BOOST_UBLAS_INLINE
   920         reverse_iterator1 rend1 () {
   921             return reverse_iterator1 (begin1 ());
   922         }
   923 
   924         BOOST_UBLAS_INLINE
   925         const_reverse_iterator2 rbegin2 () const {
   926             return const_reverse_iterator2 (end2 ());
   927         }
   928         BOOST_UBLAS_INLINE
   929         const_reverse_iterator2 rend2 () const {
   930             return const_reverse_iterator2 (begin2 ());
   931         }
   932 
   933         BOOST_UBLAS_INLINE
   934         reverse_iterator2 rbegin2 () {
   935             return reverse_iterator2 (end2 ());
   936         }
   937         BOOST_UBLAS_INLINE
   938         reverse_iterator2 rend2 () {
   939             return reverse_iterator2 (begin2 ());
   940         }
   941 
   942     private:
   943         size_type size1_;
   944         size_type size2_;
   945         array_type data_;
   946     };
   947 
   948 
   949     // Bounded matrix class
   950     template<class T, std::size_t M, std::size_t N, class L>
   951     class bounded_matrix:
   952         public matrix<T, L, bounded_array<T, M * N> > {
   953 
   954         typedef matrix<T, L, bounded_array<T, M * N> > matrix_type;
   955     public:
   956         typedef typename matrix_type::size_type size_type;
   957         static const size_type max_size1 = M;
   958         static const size_type max_size2 = N;
   959 
   960         // Construction and destruction
   961         BOOST_UBLAS_INLINE
   962         bounded_matrix ():
   963             matrix_type (M, N) {}
   964         BOOST_UBLAS_INLINE
   965         bounded_matrix (size_type size1, size_type size2):
   966             matrix_type (size1, size2) {}
   967         BOOST_UBLAS_INLINE
   968         bounded_matrix (const bounded_matrix &m):
   969             matrix_type (m) {}
   970         template<class A2>              // Allow matrix<T, L, bounded_array<M,N> > construction
   971         BOOST_UBLAS_INLINE
   972         bounded_matrix (const matrix<T, L, A2> &m):
   973             matrix_type (m) {}
   974         template<class AE>
   975         BOOST_UBLAS_INLINE
   976         bounded_matrix (const matrix_expression<AE> &ae):
   977             matrix_type (ae) {}
   978         BOOST_UBLAS_INLINE
   979         ~bounded_matrix () {}
   980 
   981         // Assignment
   982         BOOST_UBLAS_INLINE
   983         bounded_matrix &operator = (const bounded_matrix &m) {
   984             matrix_type::operator = (m);
   985             return *this;
   986         }
   987         template<class L2, class A2>        // Generic matrix assignment
   988         BOOST_UBLAS_INLINE
   989         bounded_matrix &operator = (const matrix<T, L2, A2> &m) {
   990             matrix_type::operator = (m);
   991             return *this;
   992         }
   993         template<class C>          // Container assignment without temporary
   994         BOOST_UBLAS_INLINE
   995         bounded_matrix &operator = (const matrix_container<C> &m) {
   996             matrix_type::operator = (m);
   997             return *this;
   998         }
   999         template<class AE>
  1000         BOOST_UBLAS_INLINE
  1001         bounded_matrix &operator = (const matrix_expression<AE> &ae) {
  1002             matrix_type::operator = (ae);
  1003             return *this;
  1004         }
  1005     };
  1006 
  1007 
  1008     // Array based matrix class
  1009     template<class T, class L, class A>
  1010     class vector_of_vector:
  1011         public matrix_container<vector_of_vector<T, L, A> > {
  1012 
  1013         typedef T *pointer;
  1014         typedef L layout_type;
  1015         typedef vector_of_vector<T, L, A> self_type;
  1016     public:
  1017 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  1018         using matrix_container<self_type>::operator ();
  1019 #endif
  1020         typedef typename A::size_type size_type;
  1021         typedef typename A::difference_type difference_type;
  1022         typedef T value_type;
  1023         typedef const T &const_reference;
  1024         typedef T &reference;
  1025         typedef A array_type;
  1026         typedef const matrix_reference<const self_type> const_closure_type;
  1027         typedef matrix_reference<self_type> closure_type;
  1028         typedef vector<T, typename A::value_type> vector_temporary_type;
  1029         typedef self_type matrix_temporary_type;
  1030         typedef dense_tag storage_category;
  1031         // This could be better for performance,
  1032         // typedef typename unknown_orientation_tag orientation_category;
  1033         // but others depend on the orientation information...
  1034         typedef typename L::orientation_category orientation_category;
  1035 
  1036         // Construction and destruction
  1037         BOOST_UBLAS_INLINE
  1038         vector_of_vector ():
  1039             matrix_container<self_type> (),
  1040             size1_ (0), size2_ (0), data_ (1) {}
  1041         BOOST_UBLAS_INLINE
  1042         vector_of_vector (size_type size1, size_type size2):
  1043             matrix_container<self_type> (),
  1044             size1_ (size1), size2_ (size2), data_ (1) {
  1045             resize (size1, size2, true);
  1046         }
  1047         BOOST_UBLAS_INLINE
  1048         vector_of_vector (const vector_of_vector &m):
  1049             matrix_container<self_type> (),
  1050             size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
  1051         template<class AE>
  1052         BOOST_UBLAS_INLINE
  1053         vector_of_vector (const matrix_expression<AE> &ae):
  1054             matrix_container<self_type> (),
  1055             size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size1 (size1_, size2_) + 1) {
  1056             for (size_type k = 0; k < layout_type::size1 (size1_, size2_); ++ k)
  1057                 data ()[k].resize (layout_type::size2 (size1_, size2_));
  1058             matrix_assign<scalar_assign> (*this, ae);
  1059         }
  1060 
  1061         // Accessors
  1062         BOOST_UBLAS_INLINE
  1063         size_type size1 () const {
  1064             return size1_;
  1065         }
  1066         BOOST_UBLAS_INLINE
  1067         size_type size2 () const { 
  1068             return size2_;
  1069         }
  1070 
  1071         // Storage accessors
  1072         BOOST_UBLAS_INLINE
  1073         const array_type &data () const {
  1074             return data_;
  1075         }
  1076         BOOST_UBLAS_INLINE
  1077         array_type &data () {
  1078             return data_;
  1079         }
  1080 
  1081         // Resizing
  1082         BOOST_UBLAS_INLINE
  1083         void resize (size_type size1, size_type size2, bool preserve = true) {
  1084             size1_ = size1;
  1085             size2_ = size2;
  1086             if (preserve)
  1087                 data ().resize (layout_type::size1 (size1, size2) + 1, typename array_type::value_type ());
  1088             else
  1089                 data ().resize (layout_type::size1 (size1, size2) + 1);
  1090             for (size_type k = 0; k < layout_type::size1 (size1, size2); ++ k) {
  1091                 if (preserve)
  1092                     data () [k].resize (layout_type::size2 (size1, size2), value_type ());
  1093                 else
  1094                     data () [k].resize (layout_type::size2 (size1, size2));
  1095             }
  1096         }
  1097 
  1098         // Element access
  1099         BOOST_UBLAS_INLINE
  1100         const_reference operator () (size_type i, size_type j) const {
  1101             return data () [layout_type::element1 (i, size1_, j, size2_)] [layout_type::element2 (i, size1_, j, size2_)]; 
  1102         }
  1103         BOOST_UBLAS_INLINE
  1104         reference at_element (size_type i, size_type j) {
  1105             return data () [layout_type::element1 (i, size1_, j, size2_)] [layout_type::element2 (i, size1_, j, size2_)]; 
  1106         }
  1107         BOOST_UBLAS_INLINE
  1108         reference operator () (size_type i, size_type j) {
  1109             return at_element (i, j); 
  1110         }
  1111 
  1112         // Element assignment
  1113         BOOST_UBLAS_INLINE
  1114         reference insert_element (size_type i, size_type j, const_reference t) {
  1115             return (at_element (i, j) = t); 
  1116         }
  1117         BOOST_UBLAS_INLINE
  1118         void erase_element (size_type i, size_type j) {
  1119             at_element (i, j) = value_type/*zero*/(); 
  1120         }
  1121         
  1122         // Zeroing
  1123         BOOST_UBLAS_INLINE
  1124         void clear () {
  1125             for (size_type k = 0; k < layout_type::size1 (size1_, size2_); ++ k)
  1126                 std::fill (data () [k].begin (), data () [k].end (), value_type/*zero*/());
  1127         }
  1128 
  1129         // Assignment
  1130         BOOST_UBLAS_INLINE
  1131         vector_of_vector &operator = (const vector_of_vector &m) {
  1132             size1_ = m.size1_;
  1133             size2_ = m.size2_;
  1134             data () = m.data ();
  1135             return *this;
  1136         }
  1137         BOOST_UBLAS_INLINE
  1138         vector_of_vector &assign_temporary (vector_of_vector &m) { 
  1139             swap (m);
  1140             return *this;
  1141         }
  1142         template<class AE>
  1143         BOOST_UBLAS_INLINE
  1144         vector_of_vector &operator = (const matrix_expression<AE> &ae) { 
  1145             self_type temporary (ae);
  1146             return assign_temporary (temporary);
  1147         }
  1148         template<class C>          // Container assignment without temporary
  1149         BOOST_UBLAS_INLINE
  1150         vector_of_vector &operator = (const matrix_container<C> &m) {
  1151             resize (m ().size1 (), m ().size2 (), false);
  1152             assign (m);
  1153             return *this;
  1154         }
  1155         template<class AE>
  1156         BOOST_UBLAS_INLINE
  1157         vector_of_vector &assign (const matrix_expression<AE> &ae) { 
  1158             matrix_assign<scalar_assign> (*this, ae); 
  1159             return *this;
  1160         }
  1161         template<class AE>
  1162         BOOST_UBLAS_INLINE
  1163         vector_of_vector& operator += (const matrix_expression<AE> &ae) {
  1164             self_type temporary (*this + ae);
  1165             return assign_temporary (temporary);
  1166         }
  1167         template<class C>          // Container assignment without temporary
  1168         BOOST_UBLAS_INLINE
  1169         vector_of_vector &operator += (const matrix_container<C> &m) {
  1170             plus_assign (m);
  1171             return *this;
  1172         }
  1173         template<class AE>
  1174         BOOST_UBLAS_INLINE
  1175         vector_of_vector &plus_assign (const matrix_expression<AE> &ae) { 
  1176             matrix_assign<scalar_plus_assign> (*this, ae); 
  1177             return *this;
  1178         }
  1179         template<class AE>
  1180         BOOST_UBLAS_INLINE
  1181         vector_of_vector& operator -= (const matrix_expression<AE> &ae) {
  1182             self_type temporary (*this - ae);
  1183             return assign_temporary (temporary);
  1184         }
  1185         template<class C>          // Container assignment without temporary
  1186         BOOST_UBLAS_INLINE
  1187         vector_of_vector &operator -= (const matrix_container<C> &m) {
  1188             minus_assign (m);
  1189             return *this;
  1190         }
  1191         template<class AE>
  1192         BOOST_UBLAS_INLINE
  1193         vector_of_vector &minus_assign (const matrix_expression<AE> &ae) {
  1194             matrix_assign<scalar_minus_assign> (*this, ae); 
  1195             return *this;
  1196         }
  1197         template<class AT>
  1198         BOOST_UBLAS_INLINE
  1199         vector_of_vector& operator *= (const AT &at) {
  1200             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  1201             return *this;
  1202         }
  1203         template<class AT>
  1204         BOOST_UBLAS_INLINE
  1205         vector_of_vector& operator /= (const AT &at) {
  1206             matrix_assign_scalar<scalar_divides_assign> (*this, at);
  1207             return *this;
  1208         }
  1209 
  1210         // Swapping
  1211         BOOST_UBLAS_INLINE
  1212         void swap (vector_of_vector &m) {
  1213             if (this != &m) {
  1214                 std::swap (size1_, m.size1_);
  1215                 std::swap (size2_, m.size2_);
  1216                 data ().swap (m.data ());
  1217             }
  1218         }
  1219         BOOST_UBLAS_INLINE
  1220         friend void swap (vector_of_vector &m1, vector_of_vector &m2) {
  1221             m1.swap (m2);
  1222         }
  1223 
  1224         // Iterator types
  1225     private:
  1226         // Use the vector iterator
  1227         typedef typename A::value_type::const_iterator const_subiterator_type;
  1228         typedef typename A::value_type::iterator subiterator_type;
  1229     public:
  1230 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1231         typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
  1232         typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
  1233         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
  1234         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
  1235 #else
  1236         class const_iterator1;
  1237         class iterator1;
  1238         class const_iterator2;
  1239         class iterator2;
  1240 #endif
  1241         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  1242         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  1243         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  1244         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  1245 
  1246         // Element lookup
  1247         BOOST_UBLAS_INLINE
  1248         const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
  1249 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1250             return const_iterator1 (*this, i, j);
  1251 #else
  1252             return const_iterator1 (*this, i, j, data () [layout_type::address1 (i, size1_, j, size2_)].begin ()  + layout_type::address2 (i, size1_, j, size2_));
  1253 #endif
  1254         }
  1255         BOOST_UBLAS_INLINE
  1256         iterator1 find1 (int /*rank*/, size_type i, size_type j) {
  1257 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1258             return iterator1 (*this, i, j);
  1259 #else
  1260             return iterator1 (*this, i, j, data () [layout_type::address1 (i, size1_, j, size2_)].begin ()  + layout_type::address2 (i, size1_, j, size2_));
  1261 #endif
  1262         }
  1263         BOOST_UBLAS_INLINE
  1264         const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
  1265 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1266             return const_iterator2 (*this, i, j);
  1267 #else
  1268             return const_iterator2 (*this, i, j, data () [layout_type::address1 (i, size1_, j, size2_)].begin ()  + layout_type::address2 (i, size1_, j, size2_));
  1269 #endif
  1270         }
  1271         BOOST_UBLAS_INLINE
  1272         iterator2 find2 (int /*rank*/, size_type i, size_type j) {
  1273 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1274             return iterator2 (*this, i, j);
  1275 #else
  1276             return iterator2 (*this, i, j, data () [layout_type::address1 (i, size1_, j, size2_)].begin () + layout_type::address2 (i, size1_, j, size2_));
  1277 #endif
  1278         }
  1279 
  1280 
  1281 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1282         class const_iterator1:
  1283             public container_const_reference<vector_of_vector>,
  1284             public random_access_iterator_base<dense_random_access_iterator_tag,
  1285                                                const_iterator1, value_type> {
  1286         public:
  1287             typedef typename vector_of_vector::value_type value_type;
  1288             typedef typename vector_of_vector::difference_type difference_type;
  1289             typedef typename vector_of_vector::const_reference reference;
  1290             typedef const typename vector_of_vector::pointer pointer;
  1291 
  1292             typedef const_iterator2 dual_iterator_type;
  1293             typedef const_reverse_iterator2 dual_reverse_iterator_type;
  1294 
  1295             // Construction and destruction
  1296             BOOST_UBLAS_INLINE
  1297             const_iterator1 ():
  1298                 container_const_reference<self_type> (), i_ (), j_ (), it_ () {}
  1299             BOOST_UBLAS_INLINE
  1300             const_iterator1 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it):
  1301                 container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
  1302             BOOST_UBLAS_INLINE
  1303             const_iterator1 (const iterator1 &it):
  1304                 container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
  1305 
  1306             // Arithmetic
  1307             BOOST_UBLAS_INLINE
  1308             const_iterator1 &operator ++ () {
  1309                 ++ i_;
  1310                 const self_type &m = (*this) ();
  1311                 if (layout_type::fast1 ())
  1312                     ++ it_;
  1313                 else 
  1314                     it_ = m.find1 (1, i_, j_).it_;
  1315                 return *this;
  1316             }
  1317             BOOST_UBLAS_INLINE
  1318             const_iterator1 &operator -- () {
  1319                 -- i_;
  1320                 const self_type &m = (*this) ();
  1321                 if (layout_type::fast1 ())
  1322                     -- it_;
  1323                 else
  1324                     it_ = m.find1 (1, i_, j_).it_;
  1325                 return *this;
  1326             }
  1327             BOOST_UBLAS_INLINE
  1328             const_iterator1 &operator += (difference_type n) {
  1329                 i_ += n;
  1330                 const self_type &m = (*this) ();
  1331                 it_ = m.find1 (1, i_, j_).it_;
  1332                 return *this;
  1333             }
  1334             BOOST_UBLAS_INLINE
  1335             const_iterator1 &operator -= (difference_type n) {
  1336                 i_ -= n;
  1337                 const self_type &m = (*this) ();
  1338                 it_ = m.find1 (1, i_, j_).it_;
  1339                 return *this;
  1340             }
  1341             BOOST_UBLAS_INLINE
  1342             difference_type operator - (const const_iterator1 &it) const {
  1343                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1344                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
  1345                 return index1 () - it.index1 ();
  1346             }
  1347 
  1348             // Dereference
  1349             BOOST_UBLAS_INLINE
  1350             const_reference operator * () const {
  1351                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  1352                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  1353                 return *it_;
  1354             }
  1355             BOOST_UBLAS_INLINE
  1356             const_reference operator [] (difference_type n) const {
  1357                 return *(*this + n);
  1358             }
  1359 
  1360 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1361             BOOST_UBLAS_INLINE
  1362 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1363             typename self_type::
  1364 #endif
  1365             const_iterator2 begin () const {
  1366                 const self_type &m = (*this) ();
  1367                 return m.find2 (1, index1 (), 0);
  1368             }
  1369             BOOST_UBLAS_INLINE
  1370 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1371             typename self_type::
  1372 #endif
  1373             const_iterator2 end () const {
  1374                 const self_type &m = (*this) ();
  1375                 return m.find2 (1, index1 (), m.size2 ());
  1376             }
  1377             BOOST_UBLAS_INLINE
  1378 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1379             typename self_type::
  1380 #endif
  1381             const_reverse_iterator2 rbegin () const {
  1382                 return const_reverse_iterator2 (end ());
  1383             }
  1384             BOOST_UBLAS_INLINE
  1385 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1386             typename self_type::
  1387 #endif
  1388             const_reverse_iterator2 rend () const {
  1389                 return const_reverse_iterator2 (begin ());
  1390             }
  1391 #endif
  1392 
  1393             // Indices
  1394             BOOST_UBLAS_INLINE
  1395             size_type index1 () const {
  1396                 return i_;
  1397             }
  1398             BOOST_UBLAS_INLINE
  1399             size_type index2 () const {
  1400                 return j_;
  1401             }
  1402 
  1403             // Assignment
  1404             BOOST_UBLAS_INLINE
  1405             const_iterator1 &operator = (const const_iterator1 &it) {
  1406                 container_const_reference<self_type>::assign (&it ());
  1407                 it_ = it.it_;
  1408                 return *this;
  1409             }
  1410 
  1411             // Comparison
  1412             BOOST_UBLAS_INLINE
  1413             bool operator == (const const_iterator1 &it) const {
  1414                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1415                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
  1416                 return it_ == it.it_;
  1417             }
  1418             BOOST_UBLAS_INLINE
  1419             bool operator < (const const_iterator1 &it) const {
  1420                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1421                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
  1422                 return it_ < it.it_;
  1423             }
  1424 
  1425         private:
  1426             size_type i_;
  1427             size_type j_;
  1428             const_subiterator_type it_;
  1429 
  1430             friend class iterator1;
  1431         };
  1432 #endif
  1433 
  1434         BOOST_UBLAS_INLINE
  1435         const_iterator1 begin1 () const {
  1436             return find1 (0, 0, 0);
  1437         }
  1438         BOOST_UBLAS_INLINE
  1439         const_iterator1 end1 () const {
  1440             return find1 (0, size1_, 0);
  1441         }
  1442 
  1443 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1444         class iterator1:
  1445             public container_reference<vector_of_vector>,
  1446             public random_access_iterator_base<dense_random_access_iterator_tag,
  1447                                                iterator1, value_type> {
  1448         public:
  1449             typedef typename vector_of_vector::value_type value_type;
  1450             typedef typename vector_of_vector::difference_type difference_type;
  1451             typedef typename vector_of_vector::reference reference;
  1452             typedef typename vector_of_vector::pointer pointer;
  1453 
  1454             typedef iterator2 dual_iterator_type;
  1455             typedef reverse_iterator2 dual_reverse_iterator_type;
  1456 
  1457             // Construction and destruction
  1458             BOOST_UBLAS_INLINE
  1459             iterator1 ():
  1460                 container_reference<self_type> (), i_ (), j_ (), it_ () {}
  1461             BOOST_UBLAS_INLINE
  1462             iterator1 (self_type &m, size_type i, size_type j, const subiterator_type &it):
  1463                 container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
  1464 
  1465             // Arithmetic
  1466             BOOST_UBLAS_INLINE
  1467             iterator1 &operator ++ () {
  1468                 ++ i_;
  1469                 self_type &m = (*this) ();
  1470                 if (layout_type::fast1 ())
  1471                     ++ it_;
  1472                 else
  1473                     it_ = m.find1 (1, i_, j_).it_;
  1474                 return *this;
  1475             }
  1476             BOOST_UBLAS_INLINE
  1477             iterator1 &operator -- () {
  1478                 -- i_;
  1479                 self_type &m = (*this) ();
  1480                 if (layout_type::fast1 ())
  1481                     -- it_;
  1482                 else
  1483                     it_ = m.find1 (1, i_, j_).it_;
  1484                 return *this;
  1485             }
  1486             BOOST_UBLAS_INLINE
  1487             iterator1 &operator += (difference_type n) {
  1488                 i_ += n;
  1489                 self_type &m = (*this) ();
  1490                 it_ = m.find1 (1, i_, j_).it_;
  1491                 return *this;
  1492             }
  1493             BOOST_UBLAS_INLINE
  1494             iterator1 &operator -= (difference_type n) {
  1495                 i_ -= n;
  1496                 self_type &m = (*this) ();
  1497                 it_ = m.find1 (1, i_, j_).it_;
  1498                 return *this;
  1499             }
  1500             BOOST_UBLAS_INLINE
  1501             difference_type operator - (const iterator1 &it) const {
  1502                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1503                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
  1504                 return index1 () - it.index1 ();
  1505             }
  1506 
  1507             // Dereference
  1508             BOOST_UBLAS_INLINE
  1509             reference operator * () const {
  1510                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  1511                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  1512                 return *it_;
  1513             }
  1514             BOOST_UBLAS_INLINE
  1515             reference operator [] (difference_type n) const {
  1516                 return *(*this + n);
  1517             }
  1518 
  1519 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1520             BOOST_UBLAS_INLINE
  1521 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1522             typename self_type::
  1523 #endif
  1524             iterator2 begin () const {
  1525                 self_type &m = (*this) ();
  1526                 return m.find2 (1, index1 (), 0);
  1527             }
  1528             BOOST_UBLAS_INLINE
  1529 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1530             typename self_type::
  1531 #endif
  1532             iterator2 end () const {
  1533                 self_type &m = (*this) ();
  1534                 return m.find2 (1, index1 (), m.size2 ());
  1535             }
  1536             BOOST_UBLAS_INLINE
  1537 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1538             typename self_type::
  1539 #endif
  1540             reverse_iterator2 rbegin () const {
  1541                 return reverse_iterator2 (end ());
  1542             }
  1543             BOOST_UBLAS_INLINE
  1544 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1545             typename self_type::
  1546 #endif
  1547             reverse_iterator2 rend () const {
  1548                 return reverse_iterator2 (begin ());
  1549             }
  1550 #endif
  1551 
  1552             // Indices
  1553             BOOST_UBLAS_INLINE
  1554             size_type index1 () const {
  1555                 return i_;
  1556             }
  1557             BOOST_UBLAS_INLINE
  1558             size_type index2 () const {
  1559                 return j_;
  1560             }
  1561 
  1562             // Assignment
  1563             BOOST_UBLAS_INLINE
  1564             iterator1 &operator = (const iterator1 &it) {
  1565                 container_reference<self_type>::assign (&it ());
  1566                 it_ = it.it_;
  1567                 return *this;
  1568             }
  1569 
  1570             // Comparison
  1571             BOOST_UBLAS_INLINE
  1572             bool operator == (const iterator1 &it) const {
  1573                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1574                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
  1575                 return it_ == it.it_;
  1576             }
  1577             BOOST_UBLAS_INLINE
  1578             bool operator < (const iterator1 &it) const {
  1579                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1580                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
  1581                 return it_ < it.it_;
  1582             }
  1583 
  1584         private:
  1585             size_type i_;
  1586             size_type j_;
  1587             subiterator_type it_;
  1588 
  1589             friend class const_iterator1;
  1590         };
  1591 #endif
  1592 
  1593         BOOST_UBLAS_INLINE
  1594         iterator1 begin1 () {
  1595             return find1 (0, 0, 0);
  1596         }
  1597         BOOST_UBLAS_INLINE
  1598         iterator1 end1 () {
  1599             return find1 (0, size1_, 0);
  1600         }
  1601 
  1602 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1603         class const_iterator2:
  1604             public container_const_reference<vector_of_vector>,
  1605             public random_access_iterator_base<dense_random_access_iterator_tag,
  1606                                                const_iterator2, value_type> {
  1607         public:
  1608             typedef typename vector_of_vector::value_type value_type;
  1609             typedef typename vector_of_vector::difference_type difference_type;
  1610             typedef typename vector_of_vector::const_reference reference;
  1611             typedef const typename vector_of_vector::pointer pointer;
  1612 
  1613             typedef const_iterator1 dual_iterator_type;
  1614             typedef const_reverse_iterator1 dual_reverse_iterator_type;
  1615 
  1616             // Construction and destruction
  1617             BOOST_UBLAS_INLINE
  1618             const_iterator2 ():
  1619                 container_const_reference<self_type> (), i_ (), j_ (), it_ () {}
  1620             BOOST_UBLAS_INLINE
  1621             const_iterator2 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it):
  1622                 container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
  1623             BOOST_UBLAS_INLINE
  1624             const_iterator2 (const iterator2 &it):
  1625                 container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
  1626 
  1627             // Arithmetic
  1628             BOOST_UBLAS_INLINE
  1629             const_iterator2 &operator ++ () {
  1630                 ++ j_;
  1631                 const self_type &m = (*this) ();
  1632                 if (layout_type::fast2 ())
  1633                     ++ it_;
  1634                 else
  1635                     it_ = m.find2 (1, i_, j_).it_;
  1636                 return *this;
  1637             }
  1638             BOOST_UBLAS_INLINE
  1639             const_iterator2 &operator -- () {
  1640                 -- j_;
  1641                 const self_type &m = (*this) ();
  1642                 if (layout_type::fast2 ())
  1643                     -- it_;
  1644                 else
  1645                     it_ = m.find2 (1, i_, j_).it_;
  1646                 return *this;
  1647             }
  1648             BOOST_UBLAS_INLINE
  1649             const_iterator2 &operator += (difference_type n) {
  1650                 j_ += n;
  1651                 const self_type &m = (*this) ();
  1652                 it_ = m.find2 (1, i_, j_).it_;
  1653                 return *this;
  1654             }
  1655             BOOST_UBLAS_INLINE
  1656             const_iterator2 &operator -= (difference_type n) {
  1657                 j_ -= n;
  1658                 const self_type &m = (*this) ();
  1659                 it_ = m.find2 (1, i_, j_).it_;
  1660                 return *this;
  1661             }
  1662             BOOST_UBLAS_INLINE
  1663             difference_type operator - (const const_iterator2 &it) const {
  1664                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1665                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
  1666                 return index2 () - it.index2 ();
  1667             }
  1668 
  1669             // Dereference
  1670             BOOST_UBLAS_INLINE
  1671             const_reference operator * () const {
  1672                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  1673                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  1674                 return *it_;
  1675             }
  1676             BOOST_UBLAS_INLINE
  1677             const_reference operator [] (difference_type n) const {
  1678                 return *(*this + n);
  1679             }
  1680 
  1681 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1682             BOOST_UBLAS_INLINE
  1683 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1684             typename self_type::
  1685 #endif
  1686             const_iterator1 begin () const {
  1687                 const self_type &m = (*this) ();
  1688                 return m.find1 (1, 0, index2 ());
  1689             }
  1690             BOOST_UBLAS_INLINE
  1691 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1692             typename self_type::
  1693 #endif
  1694             const_iterator1 end () const {
  1695                 const self_type &m = (*this) ();
  1696                 return m.find1 (1, m.size1 (), index2 ());
  1697             }
  1698             BOOST_UBLAS_INLINE
  1699 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1700             typename self_type::
  1701 #endif
  1702             const_reverse_iterator1 rbegin () const {
  1703                 return const_reverse_iterator1 (end ());
  1704             }
  1705             BOOST_UBLAS_INLINE
  1706 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1707             typename self_type::
  1708 #endif
  1709             const_reverse_iterator1 rend () const {
  1710                 return const_reverse_iterator1 (begin ());
  1711             }
  1712 #endif
  1713 
  1714             // Indices
  1715             BOOST_UBLAS_INLINE
  1716             size_type index1 () const {
  1717                 return i_;
  1718             }
  1719             BOOST_UBLAS_INLINE
  1720             size_type index2 () const {
  1721                 return j_;
  1722             }
  1723 
  1724             // Assignment
  1725             BOOST_UBLAS_INLINE
  1726             const_iterator2 &operator = (const const_iterator2 &it) {
  1727                 container_const_reference<self_type>::assign (&it ());
  1728                 it_ = it.it_;
  1729                 return *this;
  1730             }
  1731 
  1732             // Comparison
  1733             BOOST_UBLAS_INLINE
  1734             bool operator == (const const_iterator2 &it) const {
  1735                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1736                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
  1737                 return it_ == it.it_;
  1738             }
  1739             BOOST_UBLAS_INLINE
  1740             bool operator < (const const_iterator2 &it) const {
  1741                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1742                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
  1743                 return it_ < it.it_;
  1744             }
  1745 
  1746         private:
  1747             size_type i_;
  1748             size_type j_;
  1749             const_subiterator_type it_;
  1750 
  1751             friend class iterator2;
  1752         };
  1753 #endif
  1754 
  1755         BOOST_UBLAS_INLINE
  1756         const_iterator2 begin2 () const {
  1757             return find2 (0, 0, 0);
  1758         }
  1759         BOOST_UBLAS_INLINE
  1760         const_iterator2 end2 () const {
  1761             return find2 (0, 0, size2_);
  1762         }
  1763 
  1764 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  1765         class iterator2:
  1766             public container_reference<vector_of_vector>,
  1767             public random_access_iterator_base<dense_random_access_iterator_tag,
  1768                                                iterator2, value_type> {
  1769         public:
  1770             typedef typename vector_of_vector::value_type value_type;
  1771             typedef typename vector_of_vector::difference_type difference_type;
  1772             typedef typename vector_of_vector::reference reference;
  1773             typedef typename vector_of_vector::pointer pointer;
  1774 
  1775             typedef iterator1 dual_iterator_type;
  1776             typedef reverse_iterator1 dual_reverse_iterator_type;
  1777 
  1778             // Construction and destruction
  1779             BOOST_UBLAS_INLINE
  1780             iterator2 ():
  1781                 container_reference<self_type> (), i_ (), j_ (), it_ () {}
  1782             BOOST_UBLAS_INLINE
  1783             iterator2 (self_type &m, size_type i, size_type j, const subiterator_type &it):
  1784                 container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
  1785 
  1786             // Arithmetic
  1787             BOOST_UBLAS_INLINE
  1788             iterator2 &operator ++ () {
  1789                 ++ j_;
  1790                 self_type &m = (*this) ();
  1791                 if (layout_type::fast2 ())
  1792                     ++ it_;
  1793                 else
  1794                     it_ = m.find2 (1, i_, j_).it_;
  1795                 return *this;
  1796             }
  1797             BOOST_UBLAS_INLINE
  1798             iterator2 &operator -- () {
  1799                 -- j_;
  1800                 self_type &m = (*this) ();
  1801                 if (layout_type::fast2 ())
  1802                     -- it_;
  1803                 else
  1804                     it_ = m.find2 (1, i_, j_).it_;
  1805                 return *this;
  1806             }
  1807             BOOST_UBLAS_INLINE
  1808             iterator2 &operator += (difference_type n) {
  1809                 j_ += n;
  1810                 self_type &m = (*this) ();
  1811                 it_ = m.find2 (1, i_, j_).it_;
  1812                 return *this;
  1813             }
  1814             BOOST_UBLAS_INLINE
  1815             iterator2 &operator -= (difference_type n) {
  1816                 j_ -= n;
  1817                 self_type &m = (*this) ();
  1818                 it_ = m.find2 (1, i_, j_).it_;
  1819                 return *this;
  1820             }
  1821             BOOST_UBLAS_INLINE
  1822             difference_type operator - (const iterator2 &it) const {
  1823                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1824                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
  1825                 return index2 () - it.index2 ();
  1826             }
  1827 
  1828             // Dereference
  1829             BOOST_UBLAS_INLINE
  1830             reference operator * () const {
  1831                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  1832                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  1833                 return *it_;
  1834             }
  1835             BOOST_UBLAS_INLINE
  1836             reference operator [] (difference_type n) const {
  1837                 return *(*this + n);
  1838             }
  1839 
  1840 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  1841             BOOST_UBLAS_INLINE
  1842 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1843             typename self_type::
  1844 #endif
  1845             iterator1 begin () const {
  1846                 self_type &m = (*this) ();
  1847                 return m.find1 (1, 0, index2 ());
  1848             }
  1849             BOOST_UBLAS_INLINE
  1850 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1851             typename self_type::
  1852 #endif
  1853             iterator1 end () const {
  1854                 self_type &m = (*this) ();
  1855                 return m.find1 (1, m.size1 (), index2 ());
  1856             }
  1857             BOOST_UBLAS_INLINE
  1858 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1859             typename self_type::
  1860 #endif
  1861             reverse_iterator1 rbegin () const {
  1862                 return reverse_iterator1 (end ());
  1863             }
  1864             BOOST_UBLAS_INLINE
  1865 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  1866             typename self_type::
  1867 #endif
  1868             reverse_iterator1 rend () const {
  1869                 return reverse_iterator1 (begin ());
  1870             }
  1871 #endif
  1872 
  1873             // Indices
  1874             BOOST_UBLAS_INLINE
  1875             size_type index1 () const {
  1876                 return i_;
  1877             }
  1878             BOOST_UBLAS_INLINE
  1879             size_type index2 () const {
  1880                 return j_;
  1881             }
  1882 
  1883             // Assignment
  1884             BOOST_UBLAS_INLINE
  1885             iterator2 &operator = (const iterator2 &it) {
  1886                 container_reference<self_type>::assign (&it ());
  1887                 it_ = it.it_;
  1888                 return *this;
  1889             }
  1890 
  1891             // Comparison
  1892             BOOST_UBLAS_INLINE
  1893             bool operator == (const iterator2 &it) const {
  1894                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1895                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
  1896                 return it_ == it.it_;
  1897             }
  1898             BOOST_UBLAS_INLINE
  1899             bool operator < (const iterator2 &it) const {
  1900                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  1901                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
  1902                 return it_ < it.it_;
  1903             }
  1904 
  1905         private:
  1906             size_type i_;
  1907             size_type j_;
  1908             subiterator_type it_;
  1909 
  1910             friend class const_iterator2;
  1911         };
  1912 #endif
  1913 
  1914         BOOST_UBLAS_INLINE
  1915         iterator2 begin2 () {
  1916             return find2 (0, 0, 0);
  1917         }
  1918         BOOST_UBLAS_INLINE
  1919         iterator2 end2 () {
  1920             return find2 (0, 0, size2_);
  1921         }
  1922 
  1923         // Reverse iterators
  1924 
  1925         BOOST_UBLAS_INLINE
  1926         const_reverse_iterator1 rbegin1 () const {
  1927             return const_reverse_iterator1 (end1 ());
  1928         }
  1929         BOOST_UBLAS_INLINE
  1930         const_reverse_iterator1 rend1 () const {
  1931             return const_reverse_iterator1 (begin1 ());
  1932         }
  1933 
  1934         BOOST_UBLAS_INLINE
  1935         reverse_iterator1 rbegin1 () {
  1936             return reverse_iterator1 (end1 ());
  1937         }
  1938         BOOST_UBLAS_INLINE
  1939         reverse_iterator1 rend1 () {
  1940             return reverse_iterator1 (begin1 ());
  1941         }
  1942 
  1943         BOOST_UBLAS_INLINE
  1944         const_reverse_iterator2 rbegin2 () const {
  1945             return const_reverse_iterator2 (end2 ());
  1946         }
  1947         BOOST_UBLAS_INLINE
  1948         const_reverse_iterator2 rend2 () const {
  1949             return const_reverse_iterator2 (begin2 ());
  1950         }
  1951 
  1952         BOOST_UBLAS_INLINE
  1953         reverse_iterator2 rbegin2 () {
  1954             return reverse_iterator2 (end2 ());
  1955         }
  1956         BOOST_UBLAS_INLINE
  1957         reverse_iterator2 rend2 () {
  1958             return reverse_iterator2 (begin2 ());
  1959         }
  1960 
  1961     private:
  1962         size_type size1_;
  1963         size_type size2_;
  1964         array_type data_;
  1965     };
  1966 
  1967 
  1968     // Zero matrix class
  1969     template<class T>
  1970     class zero_matrix:
  1971         public matrix_container<zero_matrix<T> > {
  1972 
  1973         typedef const T *const_pointer;
  1974         typedef zero_matrix<T> self_type;
  1975     public:
  1976 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  1977         using matrix_container<self_type>::operator ();
  1978 #endif
  1979         typedef std::size_t size_type;
  1980         typedef std::ptrdiff_t difference_type;
  1981         typedef T value_type;
  1982         typedef const T &const_reference;
  1983         typedef T &reference;
  1984         typedef const matrix_reference<const self_type> const_closure_type;
  1985         typedef matrix_reference<self_type> closure_type;
  1986         typedef sparse_tag storage_category;
  1987         typedef unknown_orientation_tag orientation_category;
  1988 
  1989         // Construction and destruction
  1990         BOOST_UBLAS_INLINE
  1991         zero_matrix ():
  1992             matrix_container<self_type> (),
  1993             size1_ (0), size2_ (0) {}
  1994         BOOST_UBLAS_INLINE
  1995         zero_matrix (size_type size):
  1996             matrix_container<self_type> (),
  1997             size1_ (size), size2_ (size) {}
  1998         BOOST_UBLAS_INLINE
  1999         zero_matrix (size_type size1, size_type size2):
  2000             matrix_container<self_type> (),
  2001             size1_ (size1), size2_ (size2) {}
  2002         BOOST_UBLAS_INLINE
  2003         zero_matrix (const zero_matrix &m):
  2004             matrix_container<self_type> (),
  2005             size1_ (m.size1_), size2_ (m.size2_) {}
  2006 
  2007         // Accessors
  2008         BOOST_UBLAS_INLINE
  2009         size_type size1 () const {
  2010             return size1_;
  2011         }
  2012         BOOST_UBLAS_INLINE
  2013         size_type size2 () const {
  2014             return size2_;
  2015         }
  2016 
  2017         // Resizing
  2018         BOOST_UBLAS_INLINE
  2019         void resize (size_type size, bool preserve = true) {
  2020             size1_ = size;
  2021             size2_ = size;
  2022         }
  2023         BOOST_UBLAS_INLINE
  2024         void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
  2025             size1_ = size1;
  2026             size2_ = size2;
  2027         }
  2028 
  2029         // Element access
  2030         BOOST_UBLAS_INLINE
  2031         const_reference operator () (size_type /* i */, size_type /* j */) const {
  2032             return zero_;
  2033         }
  2034 
  2035         // Assignment
  2036         BOOST_UBLAS_INLINE
  2037         zero_matrix &operator = (const zero_matrix &m) {
  2038             size1_ = m.size1_;
  2039             size2_ = m.size2_;
  2040             return *this;
  2041         }
  2042         BOOST_UBLAS_INLINE
  2043         zero_matrix &assign_temporary (zero_matrix &m) {
  2044             swap (m);
  2045             return *this;
  2046         }
  2047 
  2048         // Swapping
  2049         BOOST_UBLAS_INLINE
  2050         void swap (zero_matrix &m) {
  2051             if (this != &m) {
  2052                 std::swap (size1_, m.size1_);
  2053                 std::swap (size2_, m.size2_);
  2054             }
  2055         }
  2056         BOOST_UBLAS_INLINE
  2057         friend void swap (zero_matrix &m1, zero_matrix &m2) {
  2058             m1.swap (m2);
  2059         }
  2060 
  2061         // Iterator types
  2062     public:
  2063         class const_iterator1;
  2064         class const_iterator2;
  2065         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  2066         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  2067 
  2068         // Element lookup
  2069         BOOST_UBLAS_INLINE
  2070         const_iterator1 find1 (int /*rank*/, size_type /*i*/, size_type /*j*/) const {
  2071             return const_iterator1 (*this);
  2072         }
  2073         BOOST_UBLAS_INLINE
  2074         const_iterator2 find2 (int /*rank*/, size_type /*i*/, size_type /*j*/) const {
  2075             return const_iterator2 (*this);
  2076         }
  2077 
  2078         class const_iterator1:
  2079             public container_const_reference<zero_matrix>,
  2080             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  2081                                                const_iterator1, value_type> {
  2082         public:
  2083             typedef typename zero_matrix::value_type value_type;
  2084             typedef typename zero_matrix::difference_type difference_type;
  2085             typedef typename zero_matrix::const_reference reference;
  2086             typedef typename zero_matrix::const_pointer pointer;
  2087 
  2088             typedef const_iterator2 dual_iterator_type;
  2089             typedef const_reverse_iterator2 dual_reverse_iterator_type;
  2090 
  2091             // Construction and destruction
  2092             BOOST_UBLAS_INLINE
  2093             const_iterator1 ():
  2094                 container_const_reference<self_type> () {}
  2095             BOOST_UBLAS_INLINE
  2096             const_iterator1 (const self_type &m):
  2097                 container_const_reference<self_type> (m) {}
  2098 
  2099             // Arithmetic
  2100             BOOST_UBLAS_INLINE
  2101             const_iterator1 &operator ++ () {
  2102                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
  2103                 return *this;
  2104             }
  2105             BOOST_UBLAS_INLINE
  2106             const_iterator1 &operator -- () {
  2107                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
  2108                 return *this;
  2109             }
  2110 
  2111             // Dereference
  2112             BOOST_UBLAS_INLINE
  2113             const_reference operator * () const {
  2114                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
  2115                 return zero_;   // arbitary return value
  2116             }
  2117 
  2118 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  2119             BOOST_UBLAS_INLINE
  2120 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2121             typename self_type::
  2122 #endif
  2123             const_iterator2 begin () const {
  2124                 return const_iterator2 ((*this) ());
  2125             }
  2126             BOOST_UBLAS_INLINE
  2127 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2128             typename self_type::
  2129 #endif
  2130             const_iterator2 end () const {
  2131                 return const_iterator2 ((*this) ());
  2132             }
  2133             BOOST_UBLAS_INLINE
  2134 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2135             typename self_type::
  2136 #endif
  2137             const_reverse_iterator2 rbegin () const {
  2138                 return const_reverse_iterator2 (end ());
  2139             }
  2140             BOOST_UBLAS_INLINE
  2141 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2142             typename self_type::
  2143 #endif
  2144             const_reverse_iterator2 rend () const {
  2145                 return const_reverse_iterator2 (begin ());
  2146             }
  2147 #endif
  2148 
  2149             // Indices
  2150             BOOST_UBLAS_INLINE
  2151             size_type index1 () const {
  2152                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
  2153                 return 0;   // arbitary return value
  2154             }
  2155             BOOST_UBLAS_INLINE
  2156             size_type index2 () const {
  2157                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
  2158                 return 0;   // arbitary return value
  2159             }
  2160 
  2161             // Assignment
  2162             BOOST_UBLAS_INLINE
  2163             const_iterator1 &operator = (const const_iterator1 &it) {
  2164                 container_const_reference<self_type>::assign (&it ());
  2165                 return *this;
  2166             }
  2167 
  2168             // Comparison
  2169             BOOST_UBLAS_INLINE
  2170             bool operator == (const const_iterator1 &it) const {
  2171                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2172                 return true;
  2173             }
  2174         };
  2175 
  2176         typedef const_iterator1 iterator1;
  2177 
  2178         BOOST_UBLAS_INLINE
  2179         const_iterator1 begin1 () const {
  2180             return const_iterator1 (*this);
  2181         }
  2182         BOOST_UBLAS_INLINE
  2183         const_iterator1 end1 () const {
  2184             return const_iterator1 (*this);
  2185         }
  2186 
  2187         class const_iterator2:
  2188             public container_const_reference<zero_matrix>,
  2189             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  2190                                                const_iterator2, value_type> {
  2191         public:
  2192             typedef typename zero_matrix::value_type value_type;
  2193             typedef typename zero_matrix::difference_type difference_type;
  2194             typedef typename zero_matrix::const_reference reference;
  2195             typedef typename zero_matrix::const_pointer pointer;
  2196 
  2197             typedef const_iterator1 dual_iterator_type;
  2198             typedef const_reverse_iterator1 dual_reverse_iterator_type;
  2199 
  2200             // Construction and destruction
  2201             BOOST_UBLAS_INLINE
  2202             const_iterator2 ():
  2203                 container_const_reference<self_type> () {}
  2204             BOOST_UBLAS_INLINE
  2205             const_iterator2 (const self_type &m):
  2206                 container_const_reference<self_type> (m) {}
  2207 
  2208             // Arithmetic
  2209             BOOST_UBLAS_INLINE
  2210             const_iterator2 &operator ++ () {
  2211                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
  2212                 return *this;
  2213             }
  2214             BOOST_UBLAS_INLINE
  2215             const_iterator2 &operator -- () {
  2216                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
  2217                 return *this;
  2218             }
  2219 
  2220             // Dereference
  2221             BOOST_UBLAS_INLINE
  2222             const_reference operator * () const {
  2223                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
  2224                 return zero_;   // arbitary return value
  2225             }
  2226 
  2227 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  2228             BOOST_UBLAS_INLINE
  2229 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2230             typename self_type::
  2231 #endif
  2232             const_iterator1 begin () const {
  2233                 return const_iterator1 ((*this) ());
  2234             }
  2235             BOOST_UBLAS_INLINE
  2236 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2237             typename self_type::
  2238 #endif
  2239             const_iterator1 end () const {
  2240                 return const_iterator1 ((*this) ());
  2241             }
  2242             BOOST_UBLAS_INLINE
  2243 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2244             typename self_type::
  2245 #endif
  2246             const_reverse_iterator1 rbegin () const {
  2247                 return const_reverse_iterator1 (end ());
  2248             }
  2249             BOOST_UBLAS_INLINE
  2250 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2251             typename self_type::
  2252 #endif
  2253             const_reverse_iterator1 rend () const {
  2254                 return const_reverse_iterator1 (begin ());
  2255             }
  2256 #endif
  2257 
  2258             // Indices
  2259             BOOST_UBLAS_INLINE
  2260             size_type index1 () const {
  2261                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
  2262                 return 0;   // arbitary return value
  2263             }
  2264             BOOST_UBLAS_INLINE
  2265             size_type index2 () const {
  2266                 BOOST_UBLAS_CHECK_FALSE (bad_index ());
  2267                 return 0;   // arbitary return value
  2268             }
  2269 
  2270             // Assignment
  2271             BOOST_UBLAS_INLINE
  2272             const_iterator2 &operator = (const const_iterator2 &it) {
  2273                 container_const_reference<self_type>::assign (&it ());
  2274                 return *this;
  2275             }
  2276 
  2277             // Comparison
  2278             BOOST_UBLAS_INLINE
  2279             bool operator == (const const_iterator2 &it) const {
  2280                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2281                 return true;
  2282             }
  2283         };
  2284 
  2285         typedef const_iterator2 iterator2;
  2286 
  2287         BOOST_UBLAS_INLINE
  2288         const_iterator2 begin2 () const {
  2289             return find2 (0, 0, 0);
  2290         }
  2291         BOOST_UBLAS_INLINE
  2292         const_iterator2 end2 () const {
  2293             return find2 (0, 0, size2_);
  2294         }
  2295 
  2296         // Reverse iterators
  2297 
  2298         BOOST_UBLAS_INLINE
  2299         const_reverse_iterator1 rbegin1 () const {
  2300             return const_reverse_iterator1 (end1 ());
  2301         }
  2302         BOOST_UBLAS_INLINE
  2303         const_reverse_iterator1 rend1 () const {
  2304             return const_reverse_iterator1 (begin1 ());
  2305         }
  2306 
  2307         BOOST_UBLAS_INLINE
  2308         const_reverse_iterator2 rbegin2 () const {
  2309             return const_reverse_iterator2 (end2 ());
  2310         }
  2311         BOOST_UBLAS_INLINE
  2312         const_reverse_iterator2 rend2 () const {
  2313             return const_reverse_iterator2 (begin2 ());
  2314         }
  2315 
  2316     private:
  2317         size_type size1_;
  2318         size_type size2_;
  2319         static const value_type zero_;
  2320     };
  2321 
  2322     template<class T>
  2323     const typename zero_matrix<T>::value_type zero_matrix<T>::zero_ (0);
  2324 
  2325 
  2326     // Identity matrix class
  2327     template<class T>
  2328     class identity_matrix:
  2329         public matrix_container<identity_matrix<T> > {
  2330 
  2331         typedef const T *const_pointer;
  2332         typedef identity_matrix<T> self_type;
  2333     public:
  2334 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  2335         using matrix_container<self_type>::operator ();
  2336 #endif
  2337         typedef std::size_t size_type;
  2338         typedef std::ptrdiff_t difference_type;
  2339         typedef T value_type;
  2340         typedef const T &const_reference;
  2341         typedef T &reference;
  2342         typedef const matrix_reference<const self_type> const_closure_type;
  2343         typedef matrix_reference<self_type> closure_type;
  2344         typedef sparse_tag storage_category;
  2345         typedef unknown_orientation_tag orientation_category;
  2346 
  2347         // Construction and destruction
  2348         BOOST_UBLAS_INLINE
  2349         identity_matrix ():
  2350             matrix_container<self_type> (),
  2351             size1_ (0), size2_ (0), size_common_ (0) {}
  2352         BOOST_UBLAS_INLINE
  2353         identity_matrix (size_type size):
  2354             matrix_container<self_type> (),
  2355             size1_ (size), size2_ (size), size_common_ ((std::min) (size1_, size2_)) {}
  2356         BOOST_UBLAS_INLINE
  2357         identity_matrix (size_type size1, size_type size2):
  2358             matrix_container<self_type> (),
  2359             size1_ (size1), size2_ (size2), size_common_ ((std::min) (size1_, size2_)) {}
  2360         BOOST_UBLAS_INLINE
  2361         identity_matrix (const identity_matrix &m):
  2362             matrix_container<self_type> (),
  2363             size1_ (m.size1_), size2_ (m.size2_), size_common_ ((std::min) (size1_, size2_)) {}
  2364 
  2365         // Accessors
  2366         BOOST_UBLAS_INLINE
  2367         size_type size1 () const {
  2368             return size1_;
  2369         }
  2370         BOOST_UBLAS_INLINE
  2371         size_type size2 () const {
  2372             return size2_;
  2373         }
  2374 
  2375         // Resizing
  2376         BOOST_UBLAS_INLINE
  2377         void resize (size_type size, bool preserve = true) {
  2378             size1_ = size;
  2379             size2_ = size;
  2380         }
  2381         BOOST_UBLAS_INLINE
  2382         void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
  2383             size1_ = size1;
  2384             size2_ = size2;
  2385         }
  2386 
  2387         // Element access
  2388         BOOST_UBLAS_INLINE
  2389         const_reference operator () (size_type i, size_type j) const {
  2390             if (i == j)
  2391                 return one_;
  2392             else
  2393                 return zero_;
  2394         }
  2395 
  2396         // Assignment
  2397         BOOST_UBLAS_INLINE
  2398         identity_matrix &operator = (const identity_matrix &m) {
  2399             size1_ = m.size1_;
  2400             size2_ = m.size2_;
  2401             return *this;
  2402         }
  2403         BOOST_UBLAS_INLINE
  2404         identity_matrix &assign_temporary (identity_matrix &m) { 
  2405             swap (m);
  2406             return *this;
  2407         }
  2408 
  2409         // Swapping
  2410         BOOST_UBLAS_INLINE
  2411         void swap (identity_matrix &m) {
  2412             if (this != &m) {
  2413                 std::swap (size1_, m.size1_);
  2414                 std::swap (size2_, m.size2_);
  2415             }
  2416         }
  2417         BOOST_UBLAS_INLINE
  2418         friend void swap (identity_matrix &m1, identity_matrix &m2) {
  2419             m1.swap (m2);
  2420         }
  2421 
  2422         // Iterator types
  2423     private:
  2424         // Use an index
  2425         typedef size_type const_subiterator_type;
  2426 
  2427     public:
  2428         class const_iterator1;
  2429         class const_iterator2;
  2430         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  2431         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  2432 
  2433         // Element lookup
  2434         BOOST_UBLAS_INLINE
  2435         const_iterator1 find1 (int rank, size_type i, size_type j) const {
  2436             if (rank == 1) {
  2437                 i = (std::max) (i, j);
  2438                 i = (std::min) (i, j + 1);
  2439             }
  2440             return const_iterator1 (*this, i);
  2441         }
  2442         BOOST_UBLAS_INLINE
  2443         const_iterator2 find2 (int rank, size_type i, size_type j) const {
  2444             if (rank == 1) {
  2445                 j = (std::max) (j, i);
  2446                 j = (std::min) (j, i + 1);
  2447             }
  2448             return const_iterator2 (*this, j);
  2449         }
  2450 
  2451 
  2452         class const_iterator1:
  2453             public container_const_reference<identity_matrix>,
  2454             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  2455                                                const_iterator1, value_type> {
  2456         public:
  2457             typedef typename identity_matrix::value_type value_type;
  2458             typedef typename identity_matrix::difference_type difference_type;
  2459             typedef typename identity_matrix::const_reference reference;
  2460             typedef typename identity_matrix::const_pointer pointer;
  2461 
  2462             typedef const_iterator2 dual_iterator_type;
  2463             typedef const_reverse_iterator2 dual_reverse_iterator_type;
  2464 
  2465             // Construction and destruction
  2466             BOOST_UBLAS_INLINE
  2467             const_iterator1 ():
  2468                 container_const_reference<self_type> (), it_ () {}
  2469             BOOST_UBLAS_INLINE
  2470             const_iterator1 (const self_type &m, const const_subiterator_type &it):
  2471                 container_const_reference<self_type> (m), it_ (it) {}
  2472 
  2473             // Arithmetic
  2474             BOOST_UBLAS_INLINE
  2475             const_iterator1 &operator ++ () {
  2476                 BOOST_UBLAS_CHECK (it_ < (*this) ().size1 (), bad_index ());
  2477                 ++it_;
  2478                 return *this;
  2479             }
  2480             BOOST_UBLAS_INLINE
  2481             const_iterator1 &operator -- () {
  2482                 BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
  2483                 --it_;
  2484                 return *this;
  2485             }
  2486 
  2487             // Dereference
  2488             BOOST_UBLAS_INLINE
  2489             const_reference operator * () const {
  2490                 return one_;
  2491             }
  2492 
  2493 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  2494             BOOST_UBLAS_INLINE
  2495 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2496             typename self_type::
  2497 #endif
  2498             const_iterator2 begin () const {
  2499                 return const_iterator2 ((*this) (), it_); 
  2500             }
  2501             BOOST_UBLAS_INLINE
  2502 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2503             typename self_type::
  2504 #endif
  2505             const_iterator2 end () const {
  2506                 return const_iterator2 ((*this) (), it_ + 1); 
  2507             }
  2508             BOOST_UBLAS_INLINE
  2509 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2510             typename self_type::
  2511 #endif
  2512             const_reverse_iterator2 rbegin () const {
  2513                 return const_reverse_iterator2 (end ());
  2514             }
  2515             BOOST_UBLAS_INLINE
  2516 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2517             typename self_type::
  2518 #endif
  2519             const_reverse_iterator2 rend () const {
  2520                 return const_reverse_iterator2 (begin ());
  2521             }
  2522 #endif
  2523 
  2524             // Indices
  2525             BOOST_UBLAS_INLINE
  2526             size_type index1 () const {
  2527                 return it_;
  2528             }
  2529             BOOST_UBLAS_INLINE
  2530             size_type index2 () const {
  2531                 return it_;
  2532             }
  2533 
  2534             // Assignment
  2535             BOOST_UBLAS_INLINE
  2536             const_iterator1 &operator = (const const_iterator1 &it) {
  2537                 container_const_reference<self_type>::assign (&it ());
  2538                 it_ = it.it_;
  2539                 return *this;
  2540             }
  2541 
  2542             // Comparison
  2543             BOOST_UBLAS_INLINE
  2544             bool operator == (const const_iterator1 &it) const {
  2545                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2546                 return it_ == it.it_;
  2547             }
  2548 
  2549         private:
  2550             const_subiterator_type it_;
  2551         };
  2552 
  2553         typedef const_iterator1 iterator1;
  2554 
  2555         BOOST_UBLAS_INLINE
  2556         const_iterator1 begin1 () const {
  2557             return const_iterator1 (*this, 0);
  2558         }
  2559         BOOST_UBLAS_INLINE
  2560         const_iterator1 end1 () const {
  2561             return const_iterator1 (*this, size_common_);
  2562         }
  2563 
  2564         class const_iterator2:
  2565             public container_const_reference<identity_matrix>,
  2566             public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
  2567                                                const_iterator2, value_type> {
  2568         public:
  2569             typedef typename identity_matrix::value_type value_type;
  2570             typedef typename identity_matrix::difference_type difference_type;
  2571             typedef typename identity_matrix::const_reference reference;
  2572             typedef typename identity_matrix::const_pointer pointer;
  2573 
  2574             typedef const_iterator1 dual_iterator_type;
  2575             typedef const_reverse_iterator1 dual_reverse_iterator_type;
  2576 
  2577             // Construction and destruction
  2578             BOOST_UBLAS_INLINE
  2579             const_iterator2 ():
  2580                 container_const_reference<self_type> (), it_ () {}
  2581             BOOST_UBLAS_INLINE
  2582             const_iterator2 (const self_type &m, const const_subiterator_type &it):
  2583                 container_const_reference<self_type> (m), it_ (it) {}
  2584 
  2585             // Arithmetic
  2586             BOOST_UBLAS_INLINE
  2587             const_iterator2 &operator ++ () {
  2588                 BOOST_UBLAS_CHECK (it_ < (*this) ().size_common_, bad_index ());
  2589                 ++it_;
  2590                 return *this;
  2591             }
  2592             BOOST_UBLAS_INLINE
  2593             const_iterator2 &operator -- () {
  2594                 BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
  2595                 --it_;
  2596                 return *this;
  2597             }
  2598 
  2599             // Dereference
  2600             BOOST_UBLAS_INLINE
  2601             const_reference operator * () const {
  2602                 return one_;
  2603             }
  2604 
  2605 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  2606             BOOST_UBLAS_INLINE
  2607 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2608             typename self_type::
  2609 #endif
  2610             const_iterator1 begin () const {
  2611                 return const_iterator1 ((*this) (), it_); 
  2612             }
  2613             BOOST_UBLAS_INLINE
  2614 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2615             typename self_type::
  2616 #endif
  2617             const_iterator1 end () const {
  2618                 return const_iterator1 ((*this) (), it_ + 1); 
  2619             }
  2620             BOOST_UBLAS_INLINE
  2621 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2622             typename self_type::
  2623 #endif
  2624             const_reverse_iterator1 rbegin () const {
  2625                 return const_reverse_iterator1 (end ());
  2626             }
  2627             BOOST_UBLAS_INLINE
  2628 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2629             typename self_type::
  2630 #endif
  2631             const_reverse_iterator1 rend () const {
  2632                 return const_reverse_iterator1 (begin ());
  2633             }
  2634 #endif
  2635 
  2636             // Indices
  2637             BOOST_UBLAS_INLINE
  2638             size_type index1 () const {
  2639                 return it_;
  2640             }
  2641             BOOST_UBLAS_INLINE
  2642             size_type index2 () const {
  2643                 return it_;
  2644             }
  2645 
  2646             // Assignment
  2647             BOOST_UBLAS_INLINE
  2648             const_iterator2 &operator = (const const_iterator2 &it) {
  2649                 container_const_reference<self_type>::assign (&it ());
  2650                 it_ = it.it_;
  2651                 return *this;
  2652             }
  2653 
  2654             // Comparison
  2655             BOOST_UBLAS_INLINE
  2656             bool operator == (const const_iterator2 &it) const {
  2657                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2658                 return it_ == it.it_;
  2659             }
  2660 
  2661         private:
  2662             const_subiterator_type it_;
  2663         };
  2664 
  2665         typedef const_iterator2 iterator2;
  2666 
  2667         BOOST_UBLAS_INLINE
  2668         const_iterator2 begin2 () const {
  2669             return const_iterator2 (*this, 0);
  2670         }
  2671         BOOST_UBLAS_INLINE
  2672         const_iterator2 end2 () const {
  2673             return const_iterator2 (*this, size_common_);
  2674         }
  2675 
  2676         // Reverse iterators
  2677 
  2678         BOOST_UBLAS_INLINE
  2679         const_reverse_iterator1 rbegin1 () const {
  2680             return const_reverse_iterator1 (end1 ());
  2681         }
  2682         BOOST_UBLAS_INLINE
  2683         const_reverse_iterator1 rend1 () const {
  2684             return const_reverse_iterator1 (begin1 ());
  2685         }
  2686 
  2687         BOOST_UBLAS_INLINE
  2688         const_reverse_iterator2 rbegin2 () const {
  2689             return const_reverse_iterator2 (end2 ());
  2690         }
  2691         BOOST_UBLAS_INLINE
  2692         const_reverse_iterator2 rend2 () const {
  2693             return const_reverse_iterator2 (begin2 ());
  2694         }
  2695 
  2696     private:
  2697         size_type size1_;
  2698         size_type size2_;
  2699         size_type size_common_;
  2700         static const value_type zero_;
  2701         static const value_type one_;
  2702     };
  2703 
  2704     template<class T>
  2705     const typename identity_matrix<T>::value_type identity_matrix<T>::zero_ (0);
  2706     template<class T>
  2707     const typename identity_matrix<T>::value_type identity_matrix<T>::one_ (1);
  2708 
  2709 
  2710     // Scalar matrix class
  2711     template<class T>
  2712     class scalar_matrix:
  2713         public matrix_container<scalar_matrix<T> > {
  2714 
  2715         typedef const T *const_pointer;
  2716         typedef scalar_matrix<T> self_type;
  2717     public:
  2718 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  2719         using matrix_container<self_type>::operator ();
  2720 #endif
  2721         typedef std::size_t size_type;
  2722         typedef std::ptrdiff_t difference_type;
  2723         typedef T value_type;
  2724         typedef const T &const_reference;
  2725         typedef T &reference;
  2726         typedef const matrix_reference<const self_type> const_closure_type;
  2727         typedef dense_tag storage_category;
  2728         typedef unknown_orientation_tag orientation_category;
  2729 
  2730         // Construction and destruction
  2731         BOOST_UBLAS_INLINE
  2732         scalar_matrix ():
  2733             matrix_container<self_type> (),
  2734             size1_ (0), size2_ (0), value_ () {}
  2735         BOOST_UBLAS_INLINE
  2736         scalar_matrix (size_type size1, size_type size2, const value_type &value = value_type(1)):
  2737             matrix_container<self_type> (),
  2738             size1_ (size1), size2_ (size2), value_ (value) {}
  2739         BOOST_UBLAS_INLINE
  2740         scalar_matrix (const scalar_matrix &m):
  2741             matrix_container<self_type> (),
  2742             size1_ (m.size1_), size2_ (m.size2_), value_ (m.value_) {}
  2743 
  2744         // Accessors
  2745         BOOST_UBLAS_INLINE
  2746         size_type size1 () const {
  2747             return size1_;
  2748         }
  2749         BOOST_UBLAS_INLINE
  2750         size_type size2 () const {
  2751             return size2_;
  2752         }
  2753 
  2754         // Resizing
  2755         BOOST_UBLAS_INLINE
  2756         void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
  2757             size1_ = size1;
  2758             size2_ = size2;
  2759         }
  2760 
  2761         // Element access
  2762         BOOST_UBLAS_INLINE
  2763         const_reference operator () (size_type /*i*/, size_type /*j*/) const {
  2764             return value_; 
  2765         }
  2766 
  2767         // Assignment
  2768         BOOST_UBLAS_INLINE
  2769         scalar_matrix &operator = (const scalar_matrix &m) {
  2770             size1_ = m.size1_;
  2771             size2_ = m.size2_;
  2772             value_ = m.value_;
  2773             return *this;
  2774         }
  2775         BOOST_UBLAS_INLINE
  2776         scalar_matrix &assign_temporary (scalar_matrix &m) { 
  2777             swap (m);
  2778             return *this;
  2779         }
  2780 
  2781         // Swapping
  2782         BOOST_UBLAS_INLINE
  2783         void swap (scalar_matrix &m) {
  2784             if (this != &m) {
  2785                 std::swap (size1_, m.size1_);
  2786                 std::swap (size2_, m.size2_);
  2787                 std::swap (value_, m.value_);
  2788             }
  2789         }
  2790         BOOST_UBLAS_INLINE
  2791         friend void swap (scalar_matrix &m1, scalar_matrix &m2) {
  2792             m1.swap (m2);
  2793         }
  2794 
  2795         // Iterator types
  2796     private:
  2797         // Use an index
  2798         typedef size_type const_subiterator_type;
  2799 
  2800     public:
  2801 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  2802         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
  2803         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
  2804         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
  2805         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
  2806 #else
  2807         class const_iterator1;
  2808         class const_iterator2;
  2809 #endif
  2810         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  2811         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  2812 
  2813         // Element lookup
  2814         BOOST_UBLAS_INLINE
  2815         const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
  2816             return const_iterator1 (*this, i, j);
  2817         }
  2818         BOOST_UBLAS_INLINE
  2819         const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
  2820             return const_iterator2 (*this, i, j);
  2821         }   
  2822 
  2823 
  2824 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  2825         class const_iterator1:
  2826             public container_const_reference<scalar_matrix>,
  2827             public random_access_iterator_base<dense_random_access_iterator_tag,
  2828                                                const_iterator1, value_type> {
  2829         public:
  2830             typedef typename scalar_matrix::value_type value_type;
  2831             typedef typename scalar_matrix::difference_type difference_type;
  2832             typedef typename scalar_matrix::const_reference reference;
  2833             typedef typename scalar_matrix::const_pointer pointer;
  2834 
  2835             typedef const_iterator2 dual_iterator_type;
  2836             typedef const_reverse_iterator2 dual_reverse_iterator_type;
  2837 
  2838             // Construction and destruction
  2839             BOOST_UBLAS_INLINE
  2840             const_iterator1 ():
  2841                 container_const_reference<scalar_matrix> (), it1_ (), it2_ () {}
  2842             BOOST_UBLAS_INLINE
  2843             const_iterator1 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2):
  2844                 container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {}
  2845 
  2846             // Arithmetic
  2847             BOOST_UBLAS_INLINE
  2848             const_iterator1 &operator ++ () {
  2849                 ++ it1_;
  2850                 return *this;
  2851             }
  2852             BOOST_UBLAS_INLINE
  2853             const_iterator1 &operator -- () {
  2854                 -- it1_;
  2855                 return *this;
  2856             }
  2857             BOOST_UBLAS_INLINE
  2858             const_iterator1 &operator += (difference_type n) {
  2859                 it1_ += n;
  2860                 return *this;
  2861             }
  2862             BOOST_UBLAS_INLINE
  2863             const_iterator1 &operator -= (difference_type n) {
  2864                 it1_ -= n;
  2865                 return *this;
  2866             }
  2867             BOOST_UBLAS_INLINE
  2868             difference_type operator - (const const_iterator1 &it) const {
  2869                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2870                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  2871                 return it1_ - it.it1_;
  2872             }
  2873 
  2874             // Dereference
  2875             BOOST_UBLAS_INLINE
  2876             const_reference operator * () const {
  2877                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  2878                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  2879                 return (*this) () (index1 (), index2 ());
  2880             }
  2881             BOOST_UBLAS_INLINE
  2882             const_reference operator [] (difference_type n) const {
  2883                 return *(*this + n);
  2884             }
  2885 
  2886 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  2887             BOOST_UBLAS_INLINE
  2888 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2889             typename self_type::
  2890 #endif
  2891             const_iterator2 begin () const {
  2892                 const scalar_matrix &m = (*this) ();
  2893                 return m.find2 (1, index1 (), 0);
  2894             }
  2895             BOOST_UBLAS_INLINE
  2896 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2897             typename self_type::
  2898 #endif
  2899             const_iterator2 end () const {
  2900                 const scalar_matrix &m = (*this) ();
  2901                 return m.find2 (1, index1 (), m.size2 ());
  2902             }
  2903             BOOST_UBLAS_INLINE
  2904 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2905             typename self_type::
  2906 #endif
  2907             const_reverse_iterator2 rbegin () const {
  2908                 return const_reverse_iterator2 (end ());
  2909             }
  2910             BOOST_UBLAS_INLINE
  2911 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  2912             typename self_type::
  2913 #endif
  2914             const_reverse_iterator2 rend () const {
  2915                 return const_reverse_iterator2 (begin ());
  2916             }
  2917 #endif
  2918 
  2919             // Indices
  2920             BOOST_UBLAS_INLINE
  2921             size_type index1 () const {
  2922                 return it1_;
  2923             }
  2924             BOOST_UBLAS_INLINE
  2925             size_type index2 () const {
  2926                 return it2_;
  2927             }
  2928 
  2929             // Assignment
  2930             BOOST_UBLAS_INLINE
  2931             const_iterator1 &operator = (const const_iterator1 &it) {
  2932                 container_const_reference<scalar_matrix>::assign (&it ());
  2933                 it1_ = it.it1_;
  2934                 it2_ = it.it2_;
  2935                 return *this;
  2936             }
  2937 
  2938             // Comparison
  2939             BOOST_UBLAS_INLINE
  2940             bool operator == (const const_iterator1 &it) const {
  2941                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2942                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  2943                 return it1_ == it.it1_;
  2944             }
  2945             BOOST_UBLAS_INLINE
  2946             bool operator < (const const_iterator1 &it) const {
  2947                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  2948                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
  2949                 return it1_ < it.it1_;
  2950             }
  2951 
  2952         private:
  2953             const_subiterator_type it1_;
  2954             const_subiterator_type it2_;
  2955         };
  2956 
  2957         typedef const_iterator1 iterator1;
  2958 #endif
  2959 
  2960         BOOST_UBLAS_INLINE
  2961         const_iterator1 begin1 () const {
  2962             return find1 (0, 0, 0);
  2963         }
  2964         BOOST_UBLAS_INLINE
  2965         const_iterator1 end1 () const {
  2966             return find1 (0, size1_, 0);
  2967         }
  2968 
  2969 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  2970         class const_iterator2:
  2971             public container_const_reference<scalar_matrix>,
  2972             public random_access_iterator_base<dense_random_access_iterator_tag,
  2973                                                const_iterator2, value_type> {
  2974         public:
  2975             typedef typename scalar_matrix::value_type value_type;
  2976             typedef typename scalar_matrix::difference_type difference_type;
  2977             typedef typename scalar_matrix::const_reference reference;
  2978             typedef typename scalar_matrix::const_pointer pointer;
  2979 
  2980             typedef const_iterator1 dual_iterator_type;
  2981             typedef const_reverse_iterator1 dual_reverse_iterator_type;
  2982 
  2983             // Construction and destruction
  2984             BOOST_UBLAS_INLINE
  2985             const_iterator2 ():
  2986                 container_const_reference<scalar_matrix> (), it1_ (), it2_ () {}
  2987             BOOST_UBLAS_INLINE
  2988             const_iterator2 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2):
  2989                 container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {}
  2990 
  2991             // Arithmetic
  2992             BOOST_UBLAS_INLINE
  2993             const_iterator2 &operator ++ () {
  2994                 ++ it2_;
  2995                 return *this;
  2996             }
  2997             BOOST_UBLAS_INLINE
  2998             const_iterator2 &operator -- () {
  2999                 -- it2_;
  3000                 return *this;
  3001             }
  3002             BOOST_UBLAS_INLINE
  3003             const_iterator2 &operator += (difference_type n) {
  3004                 it2_ += n;
  3005                 return *this;
  3006             }
  3007             BOOST_UBLAS_INLINE
  3008             const_iterator2 &operator -= (difference_type n) {
  3009                 it2_ -= n;
  3010                 return *this;
  3011             }
  3012             BOOST_UBLAS_INLINE
  3013             difference_type operator - (const const_iterator2 &it) const {
  3014                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3015                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  3016                 return it2_ - it.it2_;
  3017             }
  3018 
  3019             // Dereference
  3020             BOOST_UBLAS_INLINE
  3021             const_reference operator * () const {
  3022                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  3023                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  3024                 return (*this) () (index1 (), index2 ());
  3025             }
  3026             BOOST_UBLAS_INLINE
  3027             const_reference operator [] (difference_type n) const {
  3028                 return *(*this + n);
  3029             }
  3030 
  3031 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  3032             BOOST_UBLAS_INLINE
  3033 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3034             typename self_type::
  3035 #endif
  3036             const_iterator1 begin () const {
  3037                 const scalar_matrix &m = (*this) ();
  3038                 return m.find1 (1, 0, index2 ());
  3039             }
  3040             BOOST_UBLAS_INLINE
  3041 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3042             typename self_type::
  3043 #endif
  3044             const_iterator1 end () const {
  3045                 const scalar_matrix &m = (*this) ();
  3046                 return m.find1 (1, m.size1 (), index2 ());
  3047             }
  3048             BOOST_UBLAS_INLINE
  3049 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3050             typename self_type::
  3051 #endif
  3052             const_reverse_iterator1 rbegin () const {
  3053                 return const_reverse_iterator1 (end ());
  3054             }
  3055             BOOST_UBLAS_INLINE
  3056 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3057             typename self_type::
  3058 #endif
  3059             const_reverse_iterator1 rend () const {
  3060                 return const_reverse_iterator1 (begin ());
  3061             }
  3062 #endif
  3063 
  3064             // Indices
  3065             BOOST_UBLAS_INLINE
  3066             size_type index1 () const {
  3067                 return it1_;
  3068             }
  3069             BOOST_UBLAS_INLINE
  3070             size_type index2 () const {
  3071                 return it2_;
  3072             }
  3073 
  3074             // Assignment
  3075             BOOST_UBLAS_INLINE
  3076             const_iterator2 &operator = (const const_iterator2 &it) {
  3077                 container_const_reference<scalar_matrix>::assign (&it ());
  3078                 it1_ = it.it1_;
  3079                 it2_ = it.it2_;
  3080                 return *this;
  3081             }
  3082 
  3083             // Comparison
  3084             BOOST_UBLAS_INLINE
  3085             bool operator == (const const_iterator2 &it) const {
  3086                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3087                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  3088                 return it2_ == it.it2_;
  3089             }
  3090             BOOST_UBLAS_INLINE
  3091             bool operator < (const const_iterator2 &it) const {
  3092                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3093                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
  3094                 return it2_ < it.it2_;
  3095             }
  3096 
  3097         private:
  3098             const_subiterator_type it1_;
  3099             const_subiterator_type it2_;
  3100         };
  3101 
  3102         typedef const_iterator2 iterator2;
  3103 #endif
  3104 
  3105         BOOST_UBLAS_INLINE
  3106         const_iterator2 begin2 () const {
  3107             return find2 (0, 0, 0);
  3108         }
  3109         BOOST_UBLAS_INLINE
  3110         const_iterator2 end2 () const {
  3111             return find2 (0, 0, size2_);
  3112         }
  3113 
  3114         // Reverse iterators
  3115 
  3116         BOOST_UBLAS_INLINE
  3117         const_reverse_iterator1 rbegin1 () const {
  3118             return const_reverse_iterator1 (end1 ());
  3119         }
  3120         BOOST_UBLAS_INLINE
  3121         const_reverse_iterator1 rend1 () const {
  3122             return const_reverse_iterator1 (begin1 ());
  3123         }
  3124 
  3125         BOOST_UBLAS_INLINE
  3126         const_reverse_iterator2 rbegin2 () const {
  3127             return const_reverse_iterator2 (end2 ());
  3128         }
  3129         BOOST_UBLAS_INLINE
  3130         const_reverse_iterator2 rend2 () const {
  3131             return const_reverse_iterator2 (begin2 ());
  3132         }
  3133 
  3134     private:
  3135         size_type size1_;
  3136         size_type size2_;
  3137         value_type value_;
  3138     };
  3139 
  3140 
  3141     // Array based matrix class
  3142     template<class T, std::size_t N, std::size_t M>
  3143     class c_matrix:
  3144         public matrix_container<c_matrix<T, N, M> > {
  3145 
  3146         typedef c_matrix<T, N, M> self_type;
  3147     public:
  3148 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
  3149         using matrix_container<self_type>::operator ();
  3150 #endif
  3151         typedef std::size_t size_type;
  3152         typedef std::ptrdiff_t difference_type;
  3153         typedef T value_type;
  3154         typedef const T &const_reference;
  3155         typedef T &reference;
  3156         typedef const T *const_pointer;
  3157         typedef T *pointer;
  3158         typedef const matrix_reference<const self_type> const_closure_type;
  3159         typedef matrix_reference<self_type> closure_type;
  3160         typedef c_vector<T, N * M> vector_temporary_type;     // vector able to store all elements of c_matrix
  3161         typedef self_type matrix_temporary_type;
  3162         typedef dense_tag storage_category;
  3163         // This could be better for performance,
  3164         // typedef typename unknown_orientation_tag orientation_category;
  3165         // but others depend on the orientation information...
  3166         typedef row_major_tag orientation_category;
  3167 
  3168         // Construction and destruction
  3169         BOOST_UBLAS_INLINE
  3170         c_matrix ():
  3171             size1_ (N), size2_ (M) /* , data_ () */ {
  3172         }
  3173         BOOST_UBLAS_INLINE
  3174         c_matrix (size_type size1, size_type size2):
  3175             size1_ (size1), size2_ (size2) /* , data_ () */ {
  3176             if (size1_ > N || size2_ > M)
  3177                 bad_size ().raise ();
  3178         }
  3179         BOOST_UBLAS_INLINE
  3180         c_matrix (const c_matrix &m):
  3181             size1_ (m.size1_), size2_ (m.size2_) /* , data_ () */ {
  3182             if (size1_ > N || size2_ > M)
  3183                 bad_size ().raise ();
  3184             *this = m;
  3185         }
  3186         template<class AE>
  3187         BOOST_UBLAS_INLINE
  3188         c_matrix (const matrix_expression<AE> &ae):
  3189             size1_ (ae ().size1 ()), size2_ (ae ().size2 ()) /* , data_ () */ {
  3190             if (size1_ > N || size2_ > M)
  3191                 bad_size ().raise ();
  3192             matrix_assign<scalar_assign> (*this, ae);
  3193         }
  3194 
  3195         // Accessors
  3196         BOOST_UBLAS_INLINE
  3197         size_type size1 () const {
  3198             return size1_;
  3199         }
  3200         BOOST_UBLAS_INLINE
  3201         size_type size2 () const {
  3202             return size2_;
  3203         }
  3204         BOOST_UBLAS_INLINE
  3205         const_pointer data () const {
  3206             return reinterpret_cast<const_pointer> (data_);
  3207         }
  3208         BOOST_UBLAS_INLINE
  3209         pointer data () {
  3210             return reinterpret_cast<pointer> (data_);
  3211         }
  3212 
  3213         // Resizing
  3214         BOOST_UBLAS_INLINE
  3215         void resize (size_type size1, size_type size2, bool preserve = true) {
  3216             if (size1 > N || size2 > M)
  3217                 bad_size ().raise ();
  3218             if (preserve) {
  3219                 self_type temporary (size1, size2);
  3220                 // Common elements to preserve
  3221                 const size_type size1_min = (std::min) (size1, size1_);
  3222                 const size_type size2_min = (std::min) (size2, size2_);
  3223                 for (size_type i = 0; i != size1_min; ++i) {    // indexing copy over major
  3224                     for (size_type j = 0; j != size2_min; ++j) {
  3225                         temporary.data_[i][j] = data_[i][j];
  3226                     }
  3227                 }
  3228                 assign_temporary (temporary);
  3229             }
  3230             else {
  3231                 size1_ = size1;
  3232                 size2_ = size2;
  3233             }
  3234         }
  3235 
  3236         // Element access
  3237         BOOST_UBLAS_INLINE
  3238         const_reference operator () (size_type i, size_type j) const {
  3239             BOOST_UBLAS_CHECK (i < size1_, bad_index ());
  3240             BOOST_UBLAS_CHECK (j < size2_, bad_index ());
  3241             return data_ [i] [j];
  3242         }
  3243         BOOST_UBLAS_INLINE
  3244         reference at_element (size_type i, size_type j) {
  3245             BOOST_UBLAS_CHECK (i < size1_, bad_index ());
  3246             BOOST_UBLAS_CHECK (j < size2_, bad_index ());
  3247             return data_ [i] [j];
  3248         }
  3249         BOOST_UBLAS_INLINE
  3250         reference operator () (size_type i, size_type j) {
  3251             return at_element (i, j);
  3252         }
  3253 
  3254         // Element assignment
  3255         BOOST_UBLAS_INLINE
  3256         reference insert_element (size_type i, size_type j, const_reference t) {
  3257             return (at_element (i, j) = t);
  3258         }
  3259         
  3260         // Zeroing
  3261         BOOST_UBLAS_INLINE
  3262         void clear () {
  3263             for (size_type i = 0; i < size1_; ++ i)
  3264                 std::fill (data_ [i], data_ [i] + size2_, value_type/*zero*/());
  3265         }
  3266 
  3267         // Assignment
  3268         BOOST_UBLAS_INLINE
  3269         c_matrix &operator = (const c_matrix &m) {
  3270             size1_ = m.size1_;
  3271             size2_ = m.size2_;
  3272             for (size_type i = 0; i < m.size1_; ++ i)
  3273                 std::copy (m.data_ [i], m.data_ [i] + m.size2_, data_ [i]);
  3274             return *this;
  3275         }
  3276         template<class C>          // Container assignment without temporary
  3277         BOOST_UBLAS_INLINE
  3278         c_matrix &operator = (const matrix_container<C> &m) {
  3279             resize (m ().size1 (), m ().size2 (), false);
  3280             assign (m);
  3281             return *this;
  3282         }
  3283         BOOST_UBLAS_INLINE
  3284         c_matrix &assign_temporary (c_matrix &m) {
  3285             swap (m);
  3286             return *this;
  3287         }
  3288         template<class AE>
  3289         BOOST_UBLAS_INLINE
  3290         c_matrix &operator = (const matrix_expression<AE> &ae) { 
  3291             self_type temporary (ae);
  3292             return assign_temporary (temporary);
  3293         }
  3294         template<class AE>
  3295         BOOST_UBLAS_INLINE
  3296         c_matrix &assign (const matrix_expression<AE> &ae) { 
  3297             matrix_assign<scalar_assign> (*this, ae); 
  3298             return *this;
  3299         }
  3300         template<class AE>
  3301         BOOST_UBLAS_INLINE
  3302         c_matrix& operator += (const matrix_expression<AE> &ae) {
  3303             self_type temporary (*this + ae);
  3304             return assign_temporary (temporary);
  3305         }
  3306         template<class C>          // Container assignment without temporary
  3307         BOOST_UBLAS_INLINE
  3308         c_matrix &operator += (const matrix_container<C> &m) {
  3309             plus_assign (m);
  3310             return *this;
  3311         }
  3312         template<class AE>
  3313         BOOST_UBLAS_INLINE
  3314         c_matrix &plus_assign (const matrix_expression<AE> &ae) { 
  3315             matrix_assign<scalar_plus_assign> (*this, ae); 
  3316             return *this;
  3317         }
  3318         template<class AE>
  3319         BOOST_UBLAS_INLINE
  3320         c_matrix& operator -= (const matrix_expression<AE> &ae) {
  3321             self_type temporary (*this - ae);
  3322             return assign_temporary (temporary);
  3323         }
  3324         template<class C>          // Container assignment without temporary
  3325         BOOST_UBLAS_INLINE
  3326         c_matrix &operator -= (const matrix_container<C> &m) {
  3327             minus_assign (m);
  3328             return *this;
  3329         }
  3330         template<class AE>
  3331         BOOST_UBLAS_INLINE
  3332         c_matrix &minus_assign (const matrix_expression<AE> &ae) { 
  3333             matrix_assign<scalar_minus_assign> (*this, ae); 
  3334             return *this;
  3335         }
  3336         template<class AT>
  3337         BOOST_UBLAS_INLINE
  3338         c_matrix& operator *= (const AT &at) {
  3339             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
  3340             return *this;
  3341         }
  3342         template<class AT>
  3343         BOOST_UBLAS_INLINE
  3344         c_matrix& operator /= (const AT &at) {
  3345             matrix_assign_scalar<scalar_divides_assign> (*this, at);
  3346             return *this;
  3347         }
  3348 
  3349         // Swapping
  3350         BOOST_UBLAS_INLINE
  3351         void swap (c_matrix &m) {
  3352             if (this != &m) {
  3353                 BOOST_UBLAS_CHECK (size1_ == m.size1_, bad_size ());
  3354                 BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ());
  3355                 std::swap (size1_, m.size1_);
  3356                 std::swap (size2_, m.size2_);
  3357                 for (size_type i = 0; i < size1_; ++ i)
  3358                     std::swap_ranges (data_ [i], data_ [i] + size2_, m.data_ [i]);
  3359             }
  3360         }
  3361         BOOST_UBLAS_INLINE
  3362         friend void swap (c_matrix &m1, c_matrix &m2) {
  3363             m1.swap (m2);
  3364         }
  3365 
  3366         // Iterator types
  3367     private:
  3368         // Use pointers for iterator
  3369         typedef const_pointer const_subiterator_type;
  3370         typedef pointer subiterator_type;
  3371 
  3372     public:
  3373 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  3374         typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
  3375         typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
  3376         typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
  3377         typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
  3378 #else
  3379         class const_iterator1;
  3380         class iterator1;
  3381         class const_iterator2;
  3382         class iterator2;
  3383 #endif
  3384         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
  3385         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
  3386         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
  3387         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
  3388 
  3389         // Element lookup
  3390         BOOST_UBLAS_INLINE
  3391         const_iterator1 find1 (int rank, size_type i, size_type j) const {
  3392 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  3393             return const_iterator1 (*this, i, j);
  3394 #else
  3395             return const_iterator1 (*this, &data_ [i] [j]);
  3396 #endif
  3397         }
  3398         BOOST_UBLAS_INLINE
  3399         iterator1 find1 (int rank, size_type i, size_type j) {
  3400 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  3401             return iterator1 (*this, i, j);
  3402 #else
  3403             return iterator1 (*this, &data_ [i] [j]);
  3404 #endif
  3405         }
  3406         BOOST_UBLAS_INLINE
  3407         const_iterator2 find2 (int rank, size_type i, size_type j) const {
  3408 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  3409             return const_iterator2 (*this, i, j);
  3410 #else
  3411             return const_iterator2 (*this, &data_ [i] [j]);
  3412 #endif
  3413         }
  3414         BOOST_UBLAS_INLINE
  3415         iterator2 find2 (int rank, size_type i, size_type j) {
  3416 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
  3417             return iterator2 (*this, i, j);
  3418 #else
  3419             return iterator2 (*this, &data_ [i] [j]);
  3420 #endif
  3421         }
  3422 
  3423 
  3424 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  3425         class const_iterator1:
  3426             public container_const_reference<c_matrix>,
  3427             public random_access_iterator_base<dense_random_access_iterator_tag,
  3428                                                const_iterator1, value_type> {
  3429         public:
  3430             typedef typename c_matrix::difference_type difference_type;
  3431             typedef typename c_matrix::value_type value_type;
  3432             typedef typename c_matrix::const_reference reference;
  3433             typedef typename c_matrix::const_pointer pointer;
  3434 
  3435             typedef const_iterator2 dual_iterator_type;
  3436             typedef const_reverse_iterator2 dual_reverse_iterator_type;
  3437 
  3438             // Construction and destruction
  3439             BOOST_UBLAS_INLINE
  3440             const_iterator1 ():
  3441                 container_const_reference<self_type> (), it_ () {}
  3442             BOOST_UBLAS_INLINE
  3443             const_iterator1 (const self_type &m, const const_subiterator_type &it):
  3444                 container_const_reference<self_type> (m), it_ (it) {}
  3445             BOOST_UBLAS_INLINE
  3446             const_iterator1 (const iterator1 &it):
  3447                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
  3448 
  3449             // Arithmetic
  3450             BOOST_UBLAS_INLINE
  3451             const_iterator1 &operator ++ () {
  3452                 it_ += M;
  3453                 return *this;
  3454             }
  3455             BOOST_UBLAS_INLINE
  3456             const_iterator1 &operator -- () {
  3457                 it_ -= M;
  3458                 return *this;
  3459             }
  3460             BOOST_UBLAS_INLINE
  3461             const_iterator1 &operator += (difference_type n) {
  3462                 it_ += n * M;
  3463                 return *this;
  3464             }
  3465             BOOST_UBLAS_INLINE
  3466             const_iterator1 &operator -= (difference_type n) {
  3467                 it_ -= n * M;
  3468                 return *this;
  3469             }
  3470             BOOST_UBLAS_INLINE
  3471             difference_type operator - (const const_iterator1 &it) const {
  3472                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3473                 return (it_ - it.it_) / M;
  3474             }
  3475 
  3476             // Dereference
  3477             BOOST_UBLAS_INLINE
  3478             const_reference operator * () const {
  3479                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  3480                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  3481                 return *it_;
  3482             }
  3483             BOOST_UBLAS_INLINE
  3484             const_reference operator [] (difference_type n) const {
  3485                 return *(*this + n);
  3486             }
  3487 
  3488 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  3489             BOOST_UBLAS_INLINE
  3490 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3491             typename self_type::
  3492 #endif
  3493             const_iterator2 begin () const {
  3494                 const self_type &m = (*this) ();
  3495                 return m.find2 (1, index1 (), 0);
  3496             }
  3497             BOOST_UBLAS_INLINE
  3498 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3499             typename self_type::
  3500 #endif
  3501             const_iterator2 end () const {
  3502                 const self_type &m = (*this) ();
  3503                 return m.find2 (1, index1 (), m.size2 ());
  3504             }
  3505             BOOST_UBLAS_INLINE
  3506 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3507             typename self_type::
  3508 #endif
  3509             const_reverse_iterator2 rbegin () const {
  3510                 return const_reverse_iterator2 (end ());
  3511             }
  3512             BOOST_UBLAS_INLINE
  3513 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3514             typename self_type::
  3515 #endif
  3516             const_reverse_iterator2 rend () const {
  3517                 return const_reverse_iterator2 (begin ());
  3518             }
  3519 #endif
  3520 
  3521             // Indices
  3522             BOOST_UBLAS_INLINE
  3523             size_type index1 () const {
  3524                 const self_type &m = (*this) ();
  3525                 return (it_ - m.begin1 ().it_) / M;
  3526             }
  3527             BOOST_UBLAS_INLINE
  3528             size_type index2 () const {
  3529                 const self_type &m = (*this) ();
  3530                 return (it_ - m.begin1 ().it_) % M;
  3531             }
  3532 
  3533             // Assignment
  3534             BOOST_UBLAS_INLINE
  3535             const_iterator1 &operator = (const const_iterator1 &it) {
  3536                 container_const_reference<self_type>::assign (&it ());
  3537                 it_ = it.it_;
  3538                 return *this;
  3539             }
  3540 
  3541             // Comparison
  3542             BOOST_UBLAS_INLINE
  3543             bool operator == (const const_iterator1 &it) const {
  3544                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3545                 return it_ == it.it_;
  3546             }
  3547             BOOST_UBLAS_INLINE
  3548             bool operator < (const const_iterator1 &it) const {
  3549                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3550                 return it_ < it.it_;
  3551             }
  3552 
  3553         private:
  3554             const_subiterator_type it_;
  3555 
  3556             friend class iterator1;
  3557         };
  3558 #endif
  3559 
  3560         BOOST_UBLAS_INLINE
  3561         const_iterator1 begin1 () const {
  3562             return find1 (0, 0, 0);
  3563         }
  3564         BOOST_UBLAS_INLINE
  3565         const_iterator1 end1 () const {
  3566             return find1 (0, size1_, 0);
  3567         }
  3568 
  3569 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  3570         class iterator1:
  3571             public container_reference<c_matrix>,
  3572             public random_access_iterator_base<dense_random_access_iterator_tag,
  3573                                                iterator1, value_type> {
  3574         public:
  3575 
  3576             typedef typename c_matrix::difference_type difference_type;
  3577             typedef typename c_matrix::value_type value_type;
  3578             typedef typename c_matrix::reference reference;
  3579             typedef typename c_matrix::pointer pointer;
  3580 
  3581             typedef iterator2 dual_iterator_type;
  3582             typedef reverse_iterator2 dual_reverse_iterator_type;
  3583 
  3584             // Construction and destruction
  3585             BOOST_UBLAS_INLINE
  3586             iterator1 ():
  3587                 container_reference<self_type> (), it_ () {}
  3588             BOOST_UBLAS_INLINE
  3589             iterator1 (self_type &m, const subiterator_type &it):
  3590                 container_reference<self_type> (m), it_ (it) {}
  3591 
  3592             // Arithmetic
  3593             BOOST_UBLAS_INLINE
  3594             iterator1 &operator ++ () {
  3595                 it_ += M;
  3596                 return *this;
  3597             }
  3598             BOOST_UBLAS_INLINE
  3599             iterator1 &operator -- () {
  3600                 it_ -= M;
  3601                 return *this;
  3602             }
  3603             BOOST_UBLAS_INLINE
  3604             iterator1 &operator += (difference_type n) {
  3605                 it_ += n * M;
  3606                 return *this;
  3607             }
  3608             BOOST_UBLAS_INLINE
  3609             iterator1 &operator -= (difference_type n) {
  3610                 it_ -= n * M;
  3611                 return *this;
  3612             }
  3613             BOOST_UBLAS_INLINE
  3614             difference_type operator - (const iterator1 &it) const {
  3615                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3616                 return (it_ - it.it_) / M;
  3617             }
  3618 
  3619             // Dereference
  3620             BOOST_UBLAS_INLINE
  3621             reference operator * () const {
  3622                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  3623                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  3624                 return *it_;
  3625             }
  3626             BOOST_UBLAS_INLINE
  3627             reference operator [] (difference_type n) const {
  3628                 return *(*this + n);
  3629             }
  3630 
  3631 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  3632             BOOST_UBLAS_INLINE
  3633 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3634             typename self_type::
  3635 #endif
  3636             iterator2 begin () const {
  3637                 self_type &m = (*this) ();
  3638                 return m.find2 (1, index1 (), 0);
  3639             }
  3640             BOOST_UBLAS_INLINE
  3641 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3642             typename self_type::
  3643 #endif
  3644             iterator2 end () const {
  3645                 self_type &m = (*this) ();
  3646                 return m.find2 (1, index1 (), m.size2 ());
  3647             }
  3648             BOOST_UBLAS_INLINE
  3649 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3650             typename self_type::
  3651 #endif
  3652             reverse_iterator2 rbegin () const {
  3653                 return reverse_iterator2 (end ());
  3654             }
  3655             BOOST_UBLAS_INLINE
  3656 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3657             typename self_type::
  3658 #endif
  3659             reverse_iterator2 rend () const {
  3660                 return reverse_iterator2 (begin ());
  3661             }
  3662 #endif
  3663 
  3664             // Indices
  3665             BOOST_UBLAS_INLINE
  3666             size_type index1 () const {
  3667                 const self_type &m = (*this) ();
  3668                 return (it_ - m.begin1 ().it_) / M;
  3669             }
  3670             BOOST_UBLAS_INLINE
  3671             size_type index2 () const {
  3672                 const self_type &m = (*this) ();
  3673                 return (it_ - m.begin1 ().it_) % M;
  3674             }
  3675 
  3676             // Assignment
  3677             BOOST_UBLAS_INLINE
  3678             iterator1 &operator = (const iterator1 &it) {
  3679                 container_reference<self_type>::assign (&it ());
  3680                 it_ = it.it_;
  3681                 return *this;
  3682             }
  3683 
  3684             // Comparison
  3685             BOOST_UBLAS_INLINE
  3686             bool operator == (const iterator1 &it) const {
  3687                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3688                 return it_ == it.it_;
  3689             }
  3690             BOOST_UBLAS_INLINE
  3691             bool operator < (const iterator1 &it) const {
  3692                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3693                 return it_ < it.it_;
  3694             }
  3695 
  3696         private:
  3697             subiterator_type it_;
  3698 
  3699             friend class const_iterator1;
  3700         };
  3701 #endif
  3702 
  3703         BOOST_UBLAS_INLINE
  3704         iterator1 begin1 () {
  3705             return find1 (0, 0, 0);
  3706         }
  3707         BOOST_UBLAS_INLINE
  3708         iterator1 end1 () {
  3709             return find1 (0, size1_, 0);
  3710         }
  3711 
  3712 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  3713         class const_iterator2:
  3714             public container_const_reference<c_matrix>,
  3715             public random_access_iterator_base<dense_random_access_iterator_tag,
  3716                                                const_iterator2, value_type> {
  3717         public:
  3718             typedef typename c_matrix::difference_type difference_type;
  3719             typedef typename c_matrix::value_type value_type;
  3720             typedef typename c_matrix::const_reference reference;
  3721             typedef typename c_matrix::const_reference pointer;
  3722 
  3723             typedef const_iterator1 dual_iterator_type;
  3724             typedef const_reverse_iterator1 dual_reverse_iterator_type;
  3725 
  3726             // Construction and destruction
  3727             BOOST_UBLAS_INLINE
  3728             const_iterator2 ():
  3729                 container_const_reference<self_type> (), it_ () {}
  3730             BOOST_UBLAS_INLINE
  3731             const_iterator2 (const self_type &m, const const_subiterator_type &it):
  3732                 container_const_reference<self_type> (m), it_ (it) {}
  3733             BOOST_UBLAS_INLINE
  3734             const_iterator2 (const iterator2 &it):
  3735                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
  3736 
  3737             // Arithmetic
  3738             BOOST_UBLAS_INLINE
  3739             const_iterator2 &operator ++ () {
  3740                 ++ it_;
  3741                 return *this;
  3742             }
  3743             BOOST_UBLAS_INLINE
  3744             const_iterator2 &operator -- () {
  3745                 -- it_;
  3746                 return *this;
  3747             }
  3748             BOOST_UBLAS_INLINE
  3749             const_iterator2 &operator += (difference_type n) {
  3750                 it_ += n;
  3751                 return *this;
  3752             }
  3753             BOOST_UBLAS_INLINE
  3754             const_iterator2 &operator -= (difference_type n) {
  3755                 it_ -= n;
  3756                 return *this;
  3757             }
  3758             BOOST_UBLAS_INLINE
  3759             difference_type operator - (const const_iterator2 &it) const {
  3760                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3761                 return it_ - it.it_;
  3762             }
  3763 
  3764             // Dereference
  3765             BOOST_UBLAS_INLINE
  3766             const_reference operator * () const {
  3767                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  3768                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  3769                 return *it_;
  3770             }
  3771             BOOST_UBLAS_INLINE
  3772             const_reference operator [] (difference_type n) const {
  3773                 return *(*this + n);
  3774             }
  3775 
  3776 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  3777             BOOST_UBLAS_INLINE
  3778 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3779             typename self_type::
  3780 #endif
  3781             const_iterator1 begin () const {
  3782                 const self_type &m = (*this) ();
  3783                 return m.find1 (1, 0, index2 ());
  3784             }
  3785             BOOST_UBLAS_INLINE
  3786 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3787             typename self_type::
  3788 #endif
  3789             const_iterator1 end () const {
  3790                 const self_type &m = (*this) ();
  3791                 return m.find1 (1, m.size1 (), index2 ());
  3792             }
  3793             BOOST_UBLAS_INLINE
  3794 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3795             typename self_type::
  3796 #endif
  3797             const_reverse_iterator1 rbegin () const {
  3798                 return const_reverse_iterator1 (end ());
  3799             }
  3800             BOOST_UBLAS_INLINE
  3801 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3802             typename self_type::
  3803 #endif
  3804             const_reverse_iterator1 rend () const {
  3805                 return const_reverse_iterator1 (begin ());
  3806             }
  3807 #endif
  3808 
  3809             // Indices
  3810             BOOST_UBLAS_INLINE
  3811             size_type index1 () const {
  3812                 const self_type &m = (*this) ();
  3813                 return (it_ - m.begin2 ().it_) / M;
  3814             }
  3815             BOOST_UBLAS_INLINE
  3816             size_type index2 () const {
  3817                 const self_type &m = (*this) ();
  3818                 return (it_ - m.begin2 ().it_) % M;
  3819             }
  3820 
  3821             // Assignment
  3822             BOOST_UBLAS_INLINE
  3823             const_iterator2 &operator = (const const_iterator2 &it) {
  3824                 container_const_reference<self_type>::assign (&it ());
  3825                 it_ = it.it_;
  3826                 return *this;
  3827             }
  3828 
  3829             // Comparison
  3830             BOOST_UBLAS_INLINE
  3831             bool operator == (const const_iterator2 &it) const {
  3832                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3833                 return it_ == it.it_;
  3834             }
  3835             BOOST_UBLAS_INLINE
  3836             bool operator < (const const_iterator2 &it) const {
  3837                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3838                 return it_ < it.it_;
  3839             }
  3840 
  3841         private:
  3842             const_subiterator_type it_;
  3843 
  3844             friend class iterator2;
  3845         };
  3846 #endif
  3847 
  3848         BOOST_UBLAS_INLINE
  3849         const_iterator2 begin2 () const {
  3850             return find2 (0, 0, 0);
  3851         }
  3852         BOOST_UBLAS_INLINE
  3853         const_iterator2 end2 () const {
  3854             return find2 (0, 0, size2_);
  3855         }
  3856 
  3857 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
  3858         class iterator2:
  3859             public container_reference<c_matrix>,
  3860             public random_access_iterator_base<dense_random_access_iterator_tag,
  3861                                                iterator2, value_type> {
  3862         public:
  3863             typedef typename c_matrix::difference_type difference_type;
  3864             typedef typename c_matrix::value_type value_type;
  3865             typedef typename c_matrix::reference reference;
  3866             typedef typename c_matrix::pointer pointer;
  3867 
  3868             typedef iterator1 dual_iterator_type;
  3869             typedef reverse_iterator1 dual_reverse_iterator_type;
  3870 
  3871             // Construction and destruction
  3872             BOOST_UBLAS_INLINE
  3873             iterator2 ():
  3874                 container_reference<self_type> (), it_ () {}
  3875             BOOST_UBLAS_INLINE
  3876             iterator2 (self_type &m, const subiterator_type &it):
  3877                 container_reference<self_type> (m), it_ (it) {}
  3878 
  3879             // Arithmetic
  3880             BOOST_UBLAS_INLINE
  3881             iterator2 &operator ++ () {
  3882                 ++ it_;
  3883                 return *this;
  3884             }
  3885             BOOST_UBLAS_INLINE
  3886             iterator2 &operator -- () {
  3887                 -- it_;
  3888                 return *this;
  3889             }
  3890             BOOST_UBLAS_INLINE
  3891             iterator2 &operator += (difference_type n) {
  3892                 it_ += n;
  3893                 return *this;
  3894             }
  3895             BOOST_UBLAS_INLINE
  3896             iterator2 &operator -= (difference_type n) {
  3897                 it_ -= n;
  3898                 return *this;
  3899             }
  3900             BOOST_UBLAS_INLINE
  3901             difference_type operator - (const iterator2 &it) const {
  3902                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3903                 return it_ - it.it_;
  3904             }
  3905 
  3906             // Dereference
  3907             BOOST_UBLAS_INLINE
  3908             reference operator * () const {
  3909                 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
  3910                 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
  3911                 return *it_;
  3912             }
  3913             BOOST_UBLAS_INLINE
  3914             reference operator [] (difference_type n) const {
  3915                 return *(*this + n);
  3916             }
  3917 
  3918 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
  3919             BOOST_UBLAS_INLINE
  3920 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3921             typename self_type::
  3922 #endif
  3923             iterator1 begin () const {
  3924                 self_type &m = (*this) ();
  3925                 return m.find1 (1, 0, index2 ());
  3926             }
  3927             BOOST_UBLAS_INLINE
  3928 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3929             typename self_type::
  3930 #endif
  3931             iterator1 end () const {
  3932                 self_type &m = (*this) ();
  3933                 return m.find1 (1, m.size1 (), index2 ());
  3934             }
  3935             BOOST_UBLAS_INLINE
  3936 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3937             typename self_type::
  3938 #endif
  3939             reverse_iterator1 rbegin () const {
  3940                 return reverse_iterator1 (end ());
  3941             }
  3942             BOOST_UBLAS_INLINE
  3943 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
  3944             typename self_type::
  3945 #endif
  3946             reverse_iterator1 rend () const {
  3947                 return reverse_iterator1 (begin ());
  3948             }
  3949 #endif
  3950 
  3951             // Indices
  3952             BOOST_UBLAS_INLINE
  3953             size_type index1 () const {
  3954                 const self_type &m = (*this) ();
  3955                 return (it_ - m.begin2 ().it_) / M;
  3956             }
  3957             BOOST_UBLAS_INLINE
  3958             size_type index2 () const {
  3959                 const self_type &m = (*this) ();
  3960                 return (it_ - m.begin2 ().it_) % M;
  3961             }
  3962 
  3963             // Assignment
  3964             BOOST_UBLAS_INLINE
  3965             iterator2 &operator = (const iterator2 &it) {
  3966                 container_reference<self_type>::assign (&it ());
  3967                 it_ = it.it_;
  3968                 return *this;
  3969             }
  3970 
  3971             // Comparison
  3972             BOOST_UBLAS_INLINE
  3973             bool operator == (const iterator2 &it) const {
  3974                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3975                 return it_ == it.it_;
  3976             }
  3977             BOOST_UBLAS_INLINE
  3978             bool operator < (const iterator2 &it) const {
  3979                 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
  3980                 return it_ < it.it_;
  3981             }
  3982 
  3983         private:
  3984             subiterator_type it_;
  3985 
  3986             friend class const_iterator2;
  3987         };
  3988 #endif
  3989 
  3990         BOOST_UBLAS_INLINE
  3991         iterator2 begin2 () {
  3992             return find2 (0, 0, 0);
  3993         }
  3994         BOOST_UBLAS_INLINE
  3995         iterator2 end2 () {
  3996             return find2 (0, 0, size2_);
  3997         }
  3998 
  3999         // Reverse iterators
  4000 
  4001         BOOST_UBLAS_INLINE
  4002         const_reverse_iterator1 rbegin1 () const {
  4003             return const_reverse_iterator1 (end1 ());
  4004         }
  4005         BOOST_UBLAS_INLINE
  4006         const_reverse_iterator1 rend1 () const {
  4007             return const_reverse_iterator1 (begin1 ());
  4008         }
  4009 
  4010         BOOST_UBLAS_INLINE
  4011         reverse_iterator1 rbegin1 () {
  4012             return reverse_iterator1 (end1 ());
  4013         }
  4014         BOOST_UBLAS_INLINE
  4015         reverse_iterator1 rend1 () {
  4016             return reverse_iterator1 (begin1 ());
  4017         }
  4018 
  4019         BOOST_UBLAS_INLINE
  4020         const_reverse_iterator2 rbegin2 () const {
  4021             return const_reverse_iterator2 (end2 ());
  4022         }
  4023         BOOST_UBLAS_INLINE
  4024         const_reverse_iterator2 rend2 () const {
  4025             return const_reverse_iterator2 (begin2 ());
  4026         }
  4027 
  4028         BOOST_UBLAS_INLINE
  4029         reverse_iterator2 rbegin2 () {
  4030             return reverse_iterator2 (end2 ());
  4031         }
  4032         BOOST_UBLAS_INLINE
  4033         reverse_iterator2 rend2 () {
  4034             return reverse_iterator2 (begin2 ());
  4035         }
  4036 
  4037     private:
  4038         size_type size1_;
  4039         size_type size2_;
  4040         value_type data_ [N] [M];
  4041     };
  4042 
  4043 }}}
  4044 
  4045 #endif