ublas: matrix_proxy.hpp Source File

- Main Page
- Related Pages
- Classes
- Files

- File List

# matrix_proxy.hpp

    00001 //
    00002 //  Copyright (c) 2000-2002
    00003 //  Joerg Walter, Mathias Koch
    00004 //
    00005 //  Distributed under the Boost Software License, Version 1.0. (See
    00006 //  accompanying file LICENSE_1_0.txt or copy at
    00007 //  http://www.boost.org/LICENSE_1_0.txt)
    00008 //
    00009 //  The authors gratefully acknowledge the support of
    00010 //  GeNeSys mbH & Co. KG in producing this work.
    00011 //
    00012
    00013 #ifndef _BOOST_UBLAS_MATRIX_PROXY_
    00014 #define _BOOST_UBLAS_MATRIX_PROXY_
    00015
    00016 #include <boost/numeric/ublas/matrix_expression.hpp>
    00017 #include <boost/numeric/ublas/detail/vector_assign.hpp>
    00018 #include <boost/numeric/ublas/detail/matrix_assign.hpp>
    00019 #include <boost/numeric/ublas/detail/temporary.hpp>
    00020
    00021 // Iterators based on ideas of Jeremy Siek
    00022
    00023 namespace boost { namespace numeric { namespace ublas {
    00024
    00027     template<class M>
    00028     class matrix_row:
    00029         public vector_expression<matrix_row<M> > {
    00030
    00031         typedef matrix_row<M> self_type;
    00032     public:
    00033 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    00034         using vector_expression<self_type>::operator ();
    00035 #endif
    00036         typedef M matrix_type;
    00037         typedef typename M::size_type size_type;
    00038         typedef typename M::difference_type difference_type;
    00039         typedef typename M::value_type value_type;
    00040         typedef typename M::const_reference const_reference;
    00041         typedef typename boost::mpl::if_<boost::is_const<M>,
    00042                                           typename M::const_reference,
    00043                                           typename M::reference>::type reference;
    00044         typedef typename boost::mpl::if_<boost::is_const<M>,
    00045                                           typename M::const_closure_type,
    00046                                           typename M::closure_type>::type matrix_closure_type;
    00047         typedef const self_type const_closure_type;
    00048         typedef self_type closure_type;
    00049         typedef typename storage_restrict_traits<typename M::storage_category,
    00050                                                  dense_proxy_tag>::storage_category storage_category;
    00051
    00052         // Construction and destruction
    00053         BOOST_UBLAS_INLINE
    00054         matrix_row (matrix_type &data, size_type i):
    00055             data_ (data), i_ (i) {
    00056             // Early checking of preconditions here.
    00057             // BOOST_UBLAS_CHECK (i_ < data_.size1 (), bad_index ());
    00058         }
    00059
    00060         // Accessors
    00061         BOOST_UBLAS_INLINE
    00062         size_type size () const {
    00063             return data_.size2 ();
    00064         }
    00065         BOOST_UBLAS_INLINE
    00066         size_type index () const {
    00067             return i_;
    00068         }
    00069
    00070         // Storage accessors
    00071         BOOST_UBLAS_INLINE
    00072         const matrix_closure_type &data () const {
    00073             return data_;
    00074         }
    00075         BOOST_UBLAS_INLINE
    00076         matrix_closure_type &data () {
    00077             return data_;
    00078         }
    00079
    00080         // Element access
    00081 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
    00082         BOOST_UBLAS_INLINE
    00083         const_reference operator () (size_type j) const {
    00084             return data_ (i_, j);
    00085         }
    00086         BOOST_UBLAS_INLINE
    00087         reference operator () (size_type j) {
    00088             return data_ (i_, j);
    00089         }
    00090
    00091         BOOST_UBLAS_INLINE
    00092         const_reference operator [] (size_type j) const {
    00093             return (*this) (j);
    00094         }
    00095         BOOST_UBLAS_INLINE
    00096         reference operator [] (size_type j) {
    00097             return (*this) (j);
    00098         }
    00099 #else
    00100         BOOST_UBLAS_INLINE
    00101         reference operator () (size_type j) const {
    00102             return data_ (i_, j);
    00103         }
    00104
    00105         BOOST_UBLAS_INLINE
    00106         reference operator [] (size_type j) const {
    00107             return (*this) (j);
    00108         }
    00109 #endif
    00110
    00111         // Assignment
    00112         BOOST_UBLAS_INLINE
    00113         matrix_row &operator = (const matrix_row &mr) {
    00114             // ISSUE need a temporary, proxy can be overlaping alias
    00115             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mr));
    00116             return *this;
    00117         }
    00118         BOOST_UBLAS_INLINE
    00119         matrix_row &assign_temporary (matrix_row &mr) {
    00120             // assign elements, proxied container remains the same
    00121             vector_assign<scalar_assign> (*this, mr);
    00122             return *this;
    00123         }
    00124         template<class AE>
    00125         BOOST_UBLAS_INLINE
    00126         matrix_row &operator = (const vector_expression<AE> &ae) {
    00127             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
    00128             return *this;
    00129         }
    00130         template<class AE>
    00131         BOOST_UBLAS_INLINE
    00132         matrix_row &assign (const vector_expression<AE> &ae) {
    00133             vector_assign<scalar_assign> (*this, ae);
    00134             return *this;
    00135         }
    00136         template<class AE>
    00137         BOOST_UBLAS_INLINE
    00138         matrix_row &operator += (const vector_expression<AE> &ae) {
    00139             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
    00140             return *this;
    00141         }
    00142         template<class AE>
    00143         BOOST_UBLAS_INLINE
    00144         matrix_row &plus_assign (const vector_expression<AE> &ae) {
    00145             vector_assign<scalar_plus_assign> (*this, ae);
    00146             return *this;
    00147         }
    00148         template<class AE>
    00149         BOOST_UBLAS_INLINE
    00150         matrix_row &operator -= (const vector_expression<AE> &ae) {
    00151             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
    00152             return *this;
    00153         }
    00154         template<class AE>
    00155         BOOST_UBLAS_INLINE
    00156         matrix_row &minus_assign (const vector_expression<AE> &ae) {
    00157             vector_assign<scalar_minus_assign> (*this, ae);
    00158             return *this;
    00159         }
    00160         template<class AT>
    00161         BOOST_UBLAS_INLINE
    00162         matrix_row &operator *= (const AT &at) {
    00163             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
    00164             return *this;
    00165         }
    00166         template<class AT>
    00167         BOOST_UBLAS_INLINE
    00168         matrix_row &operator /= (const AT &at) {
    00169             vector_assign_scalar<scalar_divides_assign> (*this, at);
    00170             return *this;
    00171         }
    00172
    00173         // Closure comparison
    00174         BOOST_UBLAS_INLINE
    00175         bool same_closure (const matrix_row &mr) const {
    00176             return (*this).data_.same_closure (mr.data_);
    00177         }
    00178
    00179         // Comparison
    00180         BOOST_UBLAS_INLINE
    00181         bool operator == (const matrix_row &mr) const {
    00182             return (*this).data_ == mr.data_ && index () == mr.index ();
    00183         }
    00184
    00185         // Swapping
    00186         BOOST_UBLAS_INLINE
    00187         void swap (matrix_row mr) {
    00188             if (this != &mr) {
    00189                 BOOST_UBLAS_CHECK (size () == mr.size (), bad_size ());
    00190                 // Sparse ranges may be nonconformant now.
    00191                 // std::swap_ranges (begin (), end (), mr.begin ());
    00192                 vector_swap<scalar_swap> (*this, mr);
    00193             }
    00194         }
    00195         BOOST_UBLAS_INLINE
    00196         friend void swap (matrix_row mr1, matrix_row mr2) {
    00197             mr1.swap (mr2);
    00198         }
    00199
    00200         // Iterator types
    00201     private:
    00202         typedef typename M::const_iterator2 const_subiterator_type;
    00203         typedef typename boost::mpl::if_<boost::is_const<M>,
    00204                                           typename M::const_iterator2,
    00205                                           typename M::iterator2>::type subiterator_type;
    00206
    00207     public:
    00208 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00209         typedef indexed_iterator<matrix_row<matrix_type>,
    00210                                  typename subiterator_type::iterator_category> iterator;
    00211         typedef indexed_const_iterator<matrix_row<matrix_type>,
    00212                                        typename const_subiterator_type::iterator_category> const_iterator;
    00213 #else
    00214         class const_iterator;
    00215         class iterator;
    00216 #endif
    00217
    00218         // Element lookup
    00219         BOOST_UBLAS_INLINE
    00220         const_iterator find (size_type j) const {
    00221             const_subiterator_type it2 (data_.find2 (1, i_, j));
    00222 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00223             return const_iterator (*this, it2.index2 ());
    00224 #else
    00225             return const_iterator (*this, it2);
    00226 #endif
    00227         }
    00228         BOOST_UBLAS_INLINE
    00229         iterator find (size_type j) {
    00230             subiterator_type it2 (data_.find2 (1, i_, j));
    00231 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00232             return iterator (*this, it2.index2 ());
    00233 #else
    00234             return iterator (*this, it2);
    00235 #endif
    00236         }
    00237
    00238 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00239         class const_iterator:
    00240             public container_const_reference<matrix_row>,
    00241             public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
    00242                         iterator_base<const_iterator, value_type>::type {
    00243         public:
    00244             typedef typename const_subiterator_type::value_type value_type;
    00245             typedef typename const_subiterator_type::difference_type difference_type;
    00246             typedef typename const_subiterator_type::reference reference;
    00247             typedef typename const_subiterator_type::pointer pointer;
    00248
    00249             // Construction and destruction
    00250             BOOST_UBLAS_INLINE
    00251             const_iterator ():
    00252                 container_const_reference<self_type> (), it_ () {}
    00253             BOOST_UBLAS_INLINE
    00254             const_iterator (const self_type &mr, const const_subiterator_type &it):
    00255                 container_const_reference<self_type> (mr), it_ (it) {}
    00256             BOOST_UBLAS_INLINE
    00257             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
    00258                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
    00259
    00260             // Arithmetic
    00261             BOOST_UBLAS_INLINE
    00262             const_iterator &operator ++ () {
    00263                 ++ it_;
    00264                 return *this;
    00265             }
    00266             BOOST_UBLAS_INLINE
    00267             const_iterator &operator -- () {
    00268                 -- it_;
    00269                 return *this;
    00270             }
    00271             BOOST_UBLAS_INLINE
    00272             const_iterator &operator += (difference_type n) {
    00273                 it_ += n;
    00274                 return *this;
    00275             }
    00276             BOOST_UBLAS_INLINE
    00277             const_iterator &operator -= (difference_type n) {
    00278                 it_ -= n;
    00279                 return *this;
    00280             }
    00281             BOOST_UBLAS_INLINE
    00282             difference_type operator - (const const_iterator &it) const {
    00283                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    00284                 return it_ - it.it_;
    00285             }
    00286
    00287             // Dereference
    00288             BOOST_UBLAS_INLINE
    00289             const_reference operator * () const {
    00290                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
    00291                 return *it_;
    00292             }
    00293             BOOST_UBLAS_INLINE
    00294             const_reference operator [] (difference_type n) const {
    00295                 return *(*this + n);
    00296             }
    00297
    00298             // Index
    00299             BOOST_UBLAS_INLINE
    00300             size_type index () const {
    00301                 return it_.index2 ();
    00302             }
    00303
    00304             // Assignment
    00305             BOOST_UBLAS_INLINE
    00306             const_iterator &operator = (const const_iterator &it) {
    00307                 container_const_reference<self_type>::assign (&it ());
    00308                 it_ = it.it_;
    00309                 return *this;
    00310             }
    00311
    00312             // Comparison
    00313             BOOST_UBLAS_INLINE
    00314             bool operator == (const const_iterator &it) const {
    00315                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00316                 return it_ == it.it_;
    00317             }
    00318             BOOST_UBLAS_INLINE
    00319             bool operator < (const const_iterator &it) const {
    00320                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00321                 return it_ < it.it_;
    00322             }
    00323
    00324         private:
    00325             const_subiterator_type it_;
    00326         };
    00327 #endif
    00328
    00329         BOOST_UBLAS_INLINE
    00330         const_iterator begin () const {
    00331             return find (0);
    00332         }
    00333         BOOST_UBLAS_INLINE
    00334         const_iterator end () const {
    00335             return find (size ());
    00336         }
    00337
    00338 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00339         class iterator:
    00340             public container_reference<matrix_row>,
    00341             public iterator_base_traits<typename subiterator_type::iterator_category>::template
    00342                         iterator_base<iterator, value_type>::type {
    00343         public:
    00344             typedef typename subiterator_type::value_type value_type;
    00345             typedef typename subiterator_type::difference_type difference_type;
    00346             typedef typename subiterator_type::reference reference;
    00347             typedef typename subiterator_type::pointer pointer;
    00348
    00349             // Construction and destruction
    00350             BOOST_UBLAS_INLINE
    00351             iterator ():
    00352                 container_reference<self_type> (), it_ () {}
    00353             BOOST_UBLAS_INLINE
    00354             iterator (self_type &mr, const subiterator_type &it):
    00355                 container_reference<self_type> (mr), it_ (it) {}
    00356
    00357             // Arithmetic
    00358             BOOST_UBLAS_INLINE
    00359             iterator &operator ++ () {
    00360                 ++ it_;
    00361                 return *this;
    00362             }
    00363             BOOST_UBLAS_INLINE
    00364             iterator &operator -- () {
    00365                 -- it_;
    00366                 return *this;
    00367             }
    00368             BOOST_UBLAS_INLINE
    00369             iterator &operator += (difference_type n) {
    00370                 it_ += n;
    00371                 return *this;
    00372             }
    00373             BOOST_UBLAS_INLINE
    00374             iterator &operator -= (difference_type n) {
    00375                 it_ -= n;
    00376                 return *this;
    00377             }
    00378             BOOST_UBLAS_INLINE
    00379             difference_type operator - (const iterator &it) const {
    00380                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    00381                 return it_ - it.it_;
    00382             }
    00383
    00384             // Dereference
    00385             BOOST_UBLAS_INLINE
    00386             reference operator * () const {
    00387                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
    00388                 return *it_;
    00389             }
    00390             BOOST_UBLAS_INLINE
    00391             reference operator [] (difference_type n) const {
    00392                 return *(*this + n);
    00393             }
    00394
    00395             // Index
    00396             BOOST_UBLAS_INLINE
    00397             size_type index () const {
    00398                 return it_.index2 ();
    00399             }
    00400
    00401             // Assignment
    00402             BOOST_UBLAS_INLINE
    00403             iterator &operator = (const iterator &it) {
    00404                 container_reference<self_type>::assign (&it ());
    00405                 it_ = it.it_;
    00406                 return *this;
    00407             }
    00408
    00409             // Comparison
    00410             BOOST_UBLAS_INLINE
    00411             bool operator == (const iterator &it) const {
    00412                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00413                 return it_ == it.it_;
    00414             }
    00415             BOOST_UBLAS_INLINE
    00416             bool operator < (const iterator &it) const {
    00417                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00418                 return it_ < it.it_;
    00419             }
    00420
    00421         private:
    00422             subiterator_type it_;
    00423
    00424             friend class const_iterator;
    00425         };
    00426 #endif
    00427
    00428         BOOST_UBLAS_INLINE
    00429         iterator begin () {
    00430             return find (0);
    00431         }
    00432         BOOST_UBLAS_INLINE
    00433         iterator end () {
    00434             return find (size ());
    00435         }
    00436
    00437         // Reverse iterator
    00438         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
    00439         typedef reverse_iterator_base<iterator> reverse_iterator;
    00440
    00441         BOOST_UBLAS_INLINE
    00442         const_reverse_iterator rbegin () const {
    00443             return const_reverse_iterator (end ());
    00444         }
    00445         BOOST_UBLAS_INLINE
    00446         const_reverse_iterator rend () const {
    00447             return const_reverse_iterator (begin ());
    00448         }
    00449         BOOST_UBLAS_INLINE
    00450         reverse_iterator rbegin () {
    00451             return reverse_iterator (end ());
    00452         }
    00453         BOOST_UBLAS_INLINE
    00454         reverse_iterator rend () {
    00455             return reverse_iterator (begin ());
    00456         }
    00457
    00458     private:
    00459         matrix_closure_type data_;
    00460         size_type i_;
    00461     };
    00462
    00463     // Projections
    00464     template<class M>
    00465     BOOST_UBLAS_INLINE
    00466     matrix_row<M> row (M &data, typename M::size_type i) {
    00467         return matrix_row<M> (data, i);
    00468     }
    00469     template<class M>
    00470     BOOST_UBLAS_INLINE
    00471     const matrix_row<const M> row (const M &data, typename M::size_type i) {
    00472         return matrix_row<const M> (data, i);
    00473     }
    00474
    00475     // Specialize temporary
    00476     template <class M>
    00477     struct vector_temporary_traits< matrix_row<M> >
    00478     : vector_temporary_traits< M > {} ;
    00479     template <class M>
    00480     struct vector_temporary_traits< const matrix_row<M> >
    00481     : vector_temporary_traits< M > {} ;
    00482
    00483     // Matrix based column vector class
    00484     template<class M>
    00485     class matrix_column:
    00486         public vector_expression<matrix_column<M> > {
    00487
    00488         typedef matrix_column<M> self_type;
    00489     public:
    00490 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    00491         using vector_expression<self_type>::operator ();
    00492 #endif
    00493         typedef M matrix_type;
    00494         typedef typename M::size_type size_type;
    00495         typedef typename M::difference_type difference_type;
    00496         typedef typename M::value_type value_type;
    00497         typedef typename M::const_reference const_reference;
    00498         typedef typename boost::mpl::if_<boost::is_const<M>,
    00499                                           typename M::const_reference,
    00500                                           typename M::reference>::type reference;
    00501         typedef typename boost::mpl::if_<boost::is_const<M>,
    00502                                           typename M::const_closure_type,
    00503                                           typename M::closure_type>::type matrix_closure_type;
    00504         typedef const self_type const_closure_type;
    00505         typedef self_type closure_type;
    00506         typedef typename storage_restrict_traits<typename M::storage_category,
    00507                                                  dense_proxy_tag>::storage_category storage_category;
    00508
    00509         // Construction and destruction
    00510         BOOST_UBLAS_INLINE
    00511         matrix_column (matrix_type &data, size_type j):
    00512             data_ (data), j_ (j) {
    00513             // Early checking of preconditions here.
    00514             // BOOST_UBLAS_CHECK (j_ < data_.size2 (), bad_index ());
    00515         }
    00516
    00517         // Accessors
    00518         BOOST_UBLAS_INLINE
    00519         size_type size () const {
    00520             return data_.size1 ();
    00521         }
    00522         BOOST_UBLAS_INLINE
    00523         size_type index () const {
    00524             return j_;
    00525         }
    00526
    00527         // Storage accessors
    00528         BOOST_UBLAS_INLINE
    00529         const matrix_closure_type &data () const {
    00530             return data_;
    00531         }
    00532         BOOST_UBLAS_INLINE
    00533         matrix_closure_type &data () {
    00534             return data_;
    00535         }
    00536
    00537         // Element access
    00538 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
    00539         BOOST_UBLAS_INLINE
    00540         const_reference operator () (size_type i) const {
    00541             return data_ (i, j_);
    00542         }
    00543         BOOST_UBLAS_INLINE
    00544         reference operator () (size_type i) {
    00545             return data_ (i, j_);
    00546         }
    00547
    00548         BOOST_UBLAS_INLINE
    00549         const_reference operator [] (size_type i) const {
    00550             return (*this) (i);
    00551         }
    00552         BOOST_UBLAS_INLINE
    00553         reference operator [] (size_type i) {
    00554             return (*this) (i);
    00555         }
    00556 #else
    00557         BOOST_UBLAS_INLINE
    00558         reference operator () (size_type i) const {
    00559             return data_ (i, j_);
    00560         }
    00561
    00562         BOOST_UBLAS_INLINE
    00563         reference operator [] (size_type i) const {
    00564             return (*this) (i);
    00565         }
    00566 #endif
    00567
    00568         // Assignment
    00569         BOOST_UBLAS_INLINE
    00570         matrix_column &operator = (const matrix_column &mc) {
    00571             // ISSUE need a temporary, proxy can be overlaping alias
    00572             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mc));
    00573             return *this;
    00574         }
    00575         BOOST_UBLAS_INLINE
    00576         matrix_column &assign_temporary (matrix_column &mc) {
    00577             // assign elements, proxied container remains the same
    00578             vector_assign<scalar_assign> (*this, mc);
    00579             return *this;
    00580         }
    00581         template<class AE>
    00582         BOOST_UBLAS_INLINE
    00583         matrix_column &operator = (const vector_expression<AE> &ae) {
    00584             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
    00585             return *this;
    00586         }
    00587         template<class AE>
    00588         BOOST_UBLAS_INLINE
    00589         matrix_column &assign (const vector_expression<AE> &ae) {
    00590             vector_assign<scalar_assign> (*this, ae);
    00591             return *this;
    00592         }
    00593         template<class AE>
    00594         BOOST_UBLAS_INLINE
    00595         matrix_column &operator += (const vector_expression<AE> &ae) {
    00596             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
    00597             return *this;
    00598         }
    00599         template<class AE>
    00600         BOOST_UBLAS_INLINE
    00601         matrix_column &plus_assign (const vector_expression<AE> &ae) {
    00602             vector_assign<scalar_plus_assign> (*this, ae);
    00603             return *this;
    00604         }
    00605         template<class AE>
    00606         BOOST_UBLAS_INLINE
    00607         matrix_column &operator -= (const vector_expression<AE> &ae) {
    00608             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
    00609             return *this;
    00610         }
    00611         template<class AE>
    00612         BOOST_UBLAS_INLINE
    00613         matrix_column &minus_assign (const vector_expression<AE> &ae) {
    00614             vector_assign<scalar_minus_assign> (*this, ae);
    00615             return *this;
    00616         }
    00617         template<class AT>
    00618         BOOST_UBLAS_INLINE
    00619         matrix_column &operator *= (const AT &at) {
    00620             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
    00621             return *this;
    00622         }
    00623         template<class AT>
    00624         BOOST_UBLAS_INLINE
    00625         matrix_column &operator /= (const AT &at) {
    00626             vector_assign_scalar<scalar_divides_assign> (*this, at);
    00627             return *this;
    00628         }
    00629
    00630         // Closure comparison
    00631         BOOST_UBLAS_INLINE
    00632         bool same_closure (const matrix_column &mc) const {
    00633             return (*this).data_.same_closure (mc.data_);
    00634         }
    00635
    00636         // Comparison
    00637         BOOST_UBLAS_INLINE
    00638         bool operator == (const matrix_column &mc) const {
    00639             return (*this).data_ == mc.data_ && index () == mc.index ();
    00640         }
    00641
    00642         // Swapping
    00643         BOOST_UBLAS_INLINE
    00644         void swap (matrix_column mc) {
    00645             if (this != &mc) {
    00646                 BOOST_UBLAS_CHECK (size () == mc.size (), bad_size ());
    00647                 // Sparse ranges may be nonconformant now.
    00648                 // std::swap_ranges (begin (), end (), mc.begin ());
    00649                 vector_swap<scalar_swap> (*this, mc);
    00650             }
    00651         }
    00652         BOOST_UBLAS_INLINE
    00653         friend void swap (matrix_column mc1, matrix_column mc2) {
    00654             mc1.swap (mc2);
    00655         }
    00656
    00657         // Iterator types
    00658     private:
    00659         typedef typename M::const_iterator1 const_subiterator_type;
    00660         typedef typename boost::mpl::if_<boost::is_const<M>,
    00661                                           typename M::const_iterator1,
    00662                                           typename M::iterator1>::type subiterator_type;
    00663
    00664     public:
    00665 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00666         typedef indexed_iterator<matrix_column<matrix_type>,
    00667                                  typename subiterator_type::iterator_category> iterator;
    00668         typedef indexed_const_iterator<matrix_column<matrix_type>,
    00669                                        typename const_subiterator_type::iterator_category> const_iterator;
    00670 #else
    00671         class const_iterator;
    00672         class iterator;
    00673 #endif
    00674
    00675         // Element lookup
    00676         BOOST_UBLAS_INLINE
    00677         const_iterator find (size_type i) const {
    00678             const_subiterator_type it1 (data_.find1 (1, i, j_));
    00679 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00680             return const_iterator (*this, it1.index1 ());
    00681 #else
    00682             return const_iterator (*this, it1);
    00683 #endif
    00684         }
    00685         BOOST_UBLAS_INLINE
    00686         iterator find (size_type i) {
    00687             subiterator_type it1 (data_.find1 (1, i, j_));
    00688 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00689             return iterator (*this, it1.index1 ());
    00690 #else
    00691             return iterator (*this, it1);
    00692 #endif
    00693         }
    00694
    00695 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00696         class const_iterator:
    00697             public container_const_reference<matrix_column>,
    00698             public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
    00699                         iterator_base<const_iterator, value_type>::type {
    00700         public:
    00701             typedef typename const_subiterator_type::value_type value_type;
    00702             typedef typename const_subiterator_type::difference_type difference_type;
    00703             typedef typename const_subiterator_type::reference reference;
    00704             typedef typename const_subiterator_type::pointer pointer;
    00705
    00706             // Construction and destruction
    00707             BOOST_UBLAS_INLINE
    00708             const_iterator ():
    00709                 container_const_reference<self_type> (), it_ () {}
    00710             BOOST_UBLAS_INLINE
    00711             const_iterator (const self_type &mc, const const_subiterator_type &it):
    00712                 container_const_reference<self_type> (mc), it_ (it) {}
    00713             BOOST_UBLAS_INLINE
    00714             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
    00715                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
    00716
    00717             // Arithmetic
    00718             BOOST_UBLAS_INLINE
    00719             const_iterator &operator ++ () {
    00720                 ++ it_;
    00721                 return *this;
    00722             }
    00723             BOOST_UBLAS_INLINE
    00724             const_iterator &operator -- () {
    00725                 -- it_;
    00726                 return *this;
    00727             }
    00728             BOOST_UBLAS_INLINE
    00729             const_iterator &operator += (difference_type n) {
    00730                 it_ += n;
    00731                 return *this;
    00732             }
    00733             BOOST_UBLAS_INLINE
    00734             const_iterator &operator -= (difference_type n) {
    00735                 it_ -= n;
    00736                 return *this;
    00737             }
    00738             BOOST_UBLAS_INLINE
    00739             difference_type operator - (const const_iterator &it) const {
    00740                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    00741                 return it_ - it.it_;
    00742             }
    00743
    00744             // Dereference
    00745             BOOST_UBLAS_INLINE
    00746             const_reference operator * () const {
    00747                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
    00748                 return *it_;
    00749             }
    00750             BOOST_UBLAS_INLINE
    00751             const_reference operator [] (difference_type n) const {
    00752                 return *(*this + n);
    00753             }
    00754
    00755             // Index
    00756             BOOST_UBLAS_INLINE
    00757             size_type index () const {
    00758                 return it_.index1 ();
    00759             }
    00760
    00761             // Assignment
    00762             BOOST_UBLAS_INLINE
    00763             const_iterator &operator = (const const_iterator &it) {
    00764                 container_const_reference<self_type>::assign (&it ());
    00765                 it_ = it.it_;
    00766                 return *this;
    00767             }
    00768
    00769             // Comparison
    00770             BOOST_UBLAS_INLINE
    00771             bool operator == (const const_iterator &it) const {
    00772                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00773                 return it_ == it.it_;
    00774             }
    00775             BOOST_UBLAS_INLINE
    00776             bool operator < (const const_iterator &it) const {
    00777                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00778                 return it_ < it.it_;
    00779             }
    00780
    00781         private:
    00782             const_subiterator_type it_;
    00783         };
    00784 #endif
    00785
    00786         BOOST_UBLAS_INLINE
    00787         const_iterator begin () const {
    00788             return find (0);
    00789         }
    00790         BOOST_UBLAS_INLINE
    00791         const_iterator end () const {
    00792             return find (size ());
    00793         }
    00794
    00795 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00796         class iterator:
    00797             public container_reference<matrix_column>,
    00798             public iterator_base_traits<typename subiterator_type::iterator_category>::template
    00799                         iterator_base<iterator, value_type>::type {
    00800         public:
    00801             typedef typename subiterator_type::value_type value_type;
    00802             typedef typename subiterator_type::difference_type difference_type;
    00803             typedef typename subiterator_type::reference reference;
    00804             typedef typename subiterator_type::pointer pointer;
    00805
    00806             // Construction and destruction
    00807             BOOST_UBLAS_INLINE
    00808             iterator ():
    00809                 container_reference<self_type> (), it_ () {}
    00810             BOOST_UBLAS_INLINE
    00811             iterator (self_type &mc, const subiterator_type &it):
    00812                 container_reference<self_type> (mc), it_ (it) {}
    00813
    00814             // Arithmetic
    00815             BOOST_UBLAS_INLINE
    00816             iterator &operator ++ () {
    00817                 ++ it_;
    00818                 return *this;
    00819             }
    00820             BOOST_UBLAS_INLINE
    00821             iterator &operator -- () {
    00822                 -- it_;
    00823                 return *this;
    00824             }
    00825             BOOST_UBLAS_INLINE
    00826             iterator &operator += (difference_type n) {
    00827                 it_ += n;
    00828                 return *this;
    00829             }
    00830             BOOST_UBLAS_INLINE
    00831             iterator &operator -= (difference_type n) {
    00832                 it_ -= n;
    00833                 return *this;
    00834             }
    00835             BOOST_UBLAS_INLINE
    00836             difference_type operator - (const iterator &it) const {
    00837                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    00838                 return it_ - it.it_;
    00839             }
    00840
    00841             // Dereference
    00842             BOOST_UBLAS_INLINE
    00843             reference operator * () const {
    00844                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
    00845                 return *it_;
    00846             }
    00847             BOOST_UBLAS_INLINE
    00848             reference operator [] (difference_type n) const {
    00849                 return *(*this + n);
    00850             }
    00851
    00852             // Index
    00853             BOOST_UBLAS_INLINE
    00854             size_type index () const {
    00855                 return it_.index1 ();
    00856             }
    00857
    00858             // Assignment
    00859             BOOST_UBLAS_INLINE
    00860             iterator &operator = (const iterator &it) {
    00861                 container_reference<self_type>::assign (&it ());
    00862                 it_ = it.it_;
    00863                 return *this;
    00864             }
    00865
    00866             // Comparison
    00867             BOOST_UBLAS_INLINE
    00868             bool operator == (const iterator &it) const {
    00869                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00870                 return it_ == it.it_;
    00871             }
    00872             BOOST_UBLAS_INLINE
    00873             bool operator < (const iterator &it) const {
    00874                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00875                 return it_ < it.it_;
    00876             }
    00877
    00878         private:
    00879             subiterator_type it_;
    00880
    00881             friend class const_iterator;
    00882         };
    00883 #endif
    00884
    00885         BOOST_UBLAS_INLINE
    00886         iterator begin () {
    00887             return find (0);
    00888         }
    00889         BOOST_UBLAS_INLINE
    00890         iterator end () {
    00891             return find (size ());
    00892         }
    00893
    00894         // Reverse iterator
    00895         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
    00896         typedef reverse_iterator_base<iterator> reverse_iterator;
    00897
    00898         BOOST_UBLAS_INLINE
    00899         const_reverse_iterator rbegin () const {
    00900             return const_reverse_iterator (end ());
    00901         }
    00902         BOOST_UBLAS_INLINE
    00903         const_reverse_iterator rend () const {
    00904             return const_reverse_iterator (begin ());
    00905         }
    00906         reverse_iterator rbegin () {
    00907             return reverse_iterator (end ());
    00908         }
    00909         BOOST_UBLAS_INLINE
    00910         reverse_iterator rend () {
    00911             return reverse_iterator (begin ());
    00912         }
    00913
    00914     private:
    00915         matrix_closure_type data_;
    00916         size_type j_;
    00917     };
    00918
    00919     // Projections
    00920     template<class M>
    00921     BOOST_UBLAS_INLINE
    00922     matrix_column<M> column (M &data, typename M::size_type j) {
    00923         return matrix_column<M> (data, j);
    00924     }
    00925     template<class M>
    00926     BOOST_UBLAS_INLINE
    00927     const matrix_column<const M> column (const M &data, typename M::size_type j) {
    00928         return matrix_column<const M> (data, j);
    00929     }
    00930
    00931     // Specialize temporary
    00932     template <class M>
    00933     struct vector_temporary_traits< matrix_column<M> >
    00934     : vector_temporary_traits< M > {} ;
    00935     template <class M>
    00936     struct vector_temporary_traits< const matrix_column<M> >
    00937     : vector_temporary_traits< M > {} ;
    00938
    00939     // Matrix based vector range class
    00940     template<class M>
    00941     class matrix_vector_range:
    00942         public vector_expression<matrix_vector_range<M> > {
    00943
    00944         typedef matrix_vector_range<M> self_type;
    00945     public:
    00946 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    00947         using vector_expression<self_type>::operator ();
    00948 #endif
    00949         typedef M matrix_type;
    00950         typedef typename M::size_type size_type;
    00951         typedef typename M::difference_type difference_type;
    00952         typedef typename M::value_type value_type;
    00953         typedef typename M::const_reference const_reference;
    00954         typedef typename boost::mpl::if_<boost::is_const<M>,
    00955                                           typename M::const_reference,
    00956                                           typename M::reference>::type reference;
    00957         typedef typename boost::mpl::if_<boost::is_const<M>,
    00958                                           typename M::const_closure_type,
    00959                                           typename M::closure_type>::type matrix_closure_type;
    00960         typedef basic_range<size_type, difference_type> range_type;
    00961         typedef const self_type const_closure_type;
    00962         typedef self_type closure_type;
    00963         typedef typename storage_restrict_traits<typename M::storage_category,
    00964                                                  dense_proxy_tag>::storage_category storage_category;
    00965
    00966         // Construction and destruction
    00967         BOOST_UBLAS_INLINE
    00968         matrix_vector_range (matrix_type &data, const range_type &r1, const range_type &r2):
    00969             data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {
    00970             // Early checking of preconditions here.
    00971             // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
    00972             //                     r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
    00973             // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
    00974             //                   r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
    00975             // BOOST_UBLAS_CHECK (r1_.size () == r2_.size (), bad_size ());
    00976         }
    00977
    00978         // Accessors
    00979         BOOST_UBLAS_INLINE
    00980         size_type start1 () const {
    00981             return r1_.start ();
    00982         }
    00983         BOOST_UBLAS_INLINE
    00984         size_type start2 () const {
    00985             return r2_.start ();
    00986         }
    00987         BOOST_UBLAS_INLINE
    00988         size_type size () const {
    00989             return BOOST_UBLAS_SAME (r1_.size (), r2_.size ());
    00990         }
    00991
    00992         // Storage accessors
    00993         BOOST_UBLAS_INLINE
    00994         const matrix_closure_type &data () const {
    00995             return data_;
    00996         }
    00997         BOOST_UBLAS_INLINE
    00998         matrix_closure_type &data () {
    00999             return data_;
    01000         }
    01001
    01002         // Element access
    01003 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
    01004         BOOST_UBLAS_INLINE
    01005         const_reference operator () (size_type i) const {
    01006             return data_ (r1_ (i), r2_ (i));
    01007         }
    01008         BOOST_UBLAS_INLINE
    01009         reference operator () (size_type i) {
    01010             return data_ (r1_ (i), r2_ (i));
    01011         }
    01012
    01013         BOOST_UBLAS_INLINE
    01014         const_reference operator [] (size_type i) const {
    01015             return (*this) (i);
    01016         }
    01017         BOOST_UBLAS_INLINE
    01018         reference operator [] (size_type i) {
    01019             return (*this) (i);
    01020         }
    01021 #else
    01022         BOOST_UBLAS_INLINE
    01023         reference operator () (size_type i) const {
    01024             return data_ (r1_ (i), r2_ (i));
    01025         }
    01026
    01027         BOOST_UBLAS_INLINE
    01028         reference operator [] (size_type i) const {
    01029             return (*this) (i);
    01030         }
    01031 #endif
    01032
    01033         // Assignment
    01034         BOOST_UBLAS_INLINE
    01035         matrix_vector_range &operator = (const matrix_vector_range &mvr) {
    01036             // ISSUE need a temporary, proxy can be overlaping alias
    01037             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvr));
    01038             return *this;
    01039         }
    01040         BOOST_UBLAS_INLINE
    01041         matrix_vector_range &assign_temporary (matrix_vector_range &mvr) {
    01042             // assign elements, proxied container remains the same
    01043             vector_assign<scalar_assign> (*this, mvr);
    01044             return *this;
    01045         }
    01046         template<class AE>
    01047         BOOST_UBLAS_INLINE
    01048         matrix_vector_range &operator = (const vector_expression<AE> &ae) {
    01049             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
    01050             return *this;
    01051         }
    01052         template<class AE>
    01053         BOOST_UBLAS_INLINE
    01054         matrix_vector_range &assign (const vector_expression<AE> &ae) {
    01055             vector_assign<scalar_assign> (*this, ae);
    01056             return *this;
    01057         }
    01058         template<class AE>
    01059         BOOST_UBLAS_INLINE
    01060         matrix_vector_range &operator += (const vector_expression<AE> &ae) {
    01061             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
    01062             return *this;
    01063         }
    01064         template<class AE>
    01065         BOOST_UBLAS_INLINE
    01066         matrix_vector_range &plus_assign (const vector_expression<AE> &ae) {
    01067             vector_assign<scalar_plus_assign> (*this, ae);
    01068             return *this;
    01069         }
    01070         template<class AE>
    01071         BOOST_UBLAS_INLINE
    01072         matrix_vector_range &operator -= (const vector_expression<AE> &ae) {
    01073             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
    01074             return *this;
    01075         }
    01076         template<class AE>
    01077         BOOST_UBLAS_INLINE
    01078         matrix_vector_range &minus_assign (const vector_expression<AE> &ae) {
    01079             vector_assign<scalar_minus_assign> (*this, ae);
    01080             return *this;
    01081         }
    01082         template<class AT>
    01083         BOOST_UBLAS_INLINE
    01084         matrix_vector_range &operator *= (const AT &at) {
    01085             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
    01086             return *this;
    01087         }
    01088         template<class AT>
    01089         BOOST_UBLAS_INLINE
    01090         matrix_vector_range &operator /= (const AT &at) {
    01091             vector_assign_scalar<scalar_divides_assign> (*this, at);
    01092             return *this;
    01093         }
    01094
    01095         // Closure comparison
    01096         BOOST_UBLAS_INLINE
    01097         bool same_closure (const matrix_vector_range &mvr) const {
    01098             return (*this).data_.same_closure (mvr.data_);
    01099         }
    01100
    01101         // Comparison
    01102         BOOST_UBLAS_INLINE
    01103         bool operator == (const matrix_vector_range &mvr) const {
    01104             return (*this).data_ == mvr.data_ && r1_ == mvr.r1_ && r2_ == mvr.r2_;
    01105         }
    01106
    01107         // Swapping
    01108         BOOST_UBLAS_INLINE
    01109         void swap (matrix_vector_range mvr) {
    01110             if (this != &mvr) {
    01111                 BOOST_UBLAS_CHECK (size () == mvr.size (), bad_size ());
    01112                 // Sparse ranges may be nonconformant now.
    01113                 // std::swap_ranges (begin (), end (), mvr.begin ());
    01114                 vector_swap<scalar_swap> (*this, mvr);
    01115             }
    01116         }
    01117         BOOST_UBLAS_INLINE
    01118         friend void swap (matrix_vector_range mvr1, matrix_vector_range mvr2) {
    01119             mvr1.swap (mvr2);
    01120         }
    01121
    01122         // Iterator types
    01123     private:
    01124         // Use range as an index - FIXME this fails for packed assignment
    01125         typedef typename range_type::const_iterator const_subiterator1_type;
    01126         typedef typename range_type::const_iterator subiterator1_type;
    01127         typedef typename range_type::const_iterator const_subiterator2_type;
    01128         typedef typename range_type::const_iterator subiterator2_type;
    01129
    01130     public:
    01131         class const_iterator;
    01132         class iterator;
    01133
    01134         // Element lookup
    01135         BOOST_UBLAS_INLINE
    01136         const_iterator find (size_type i) const {
    01137             return const_iterator (*this, r1_.begin () + i, r2_.begin () + i);
    01138         }
    01139         BOOST_UBLAS_INLINE
    01140         iterator find (size_type i) {
    01141             return iterator (*this, r1_.begin () + i, r2_.begin () + i);
    01142         }
    01143
    01144         class const_iterator:
    01145             public container_const_reference<matrix_vector_range>,
    01146             public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
    01147                         iterator_base<const_iterator, value_type>::type {
    01148         public:
    01149             // FIXME Iterator can never be different code was:
    01150             // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
    01151             BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
    01152
    01153             typedef typename matrix_vector_range::value_type value_type;
    01154             typedef typename matrix_vector_range::difference_type difference_type;
    01155             typedef typename matrix_vector_range::const_reference reference;
    01156             typedef const typename matrix_vector_range::value_type *pointer;
    01157
    01158             // Construction and destruction
    01159             BOOST_UBLAS_INLINE
    01160             const_iterator ():
    01161                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    01162             BOOST_UBLAS_INLINE
    01163             const_iterator (const self_type &mvr, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
    01164                 container_const_reference<self_type> (mvr), it1_ (it1), it2_ (it2) {}
    01165             BOOST_UBLAS_INLINE
    01166             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
    01167                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
    01168
    01169             // Arithmetic
    01170             BOOST_UBLAS_INLINE
    01171             const_iterator &operator ++ () {
    01172                 ++ it1_;
    01173                 ++ it2_;
    01174                 return *this;
    01175             }
    01176             BOOST_UBLAS_INLINE
    01177             const_iterator &operator -- () {
    01178                 -- it1_;
    01179                 -- it2_;
    01180                 return *this;
    01181             }
    01182             BOOST_UBLAS_INLINE
    01183             const_iterator &operator += (difference_type n) {
    01184                 it1_ += n;
    01185                 it2_ += n;
    01186                 return *this;
    01187             }
    01188             BOOST_UBLAS_INLINE
    01189             const_iterator &operator -= (difference_type n) {
    01190                 it1_ -= n;
    01191                 it2_ -= n;
    01192                 return *this;
    01193             }
    01194             BOOST_UBLAS_INLINE
    01195             difference_type operator - (const const_iterator &it) const {
    01196                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    01197                 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
    01198             }
    01199
    01200             // Dereference
    01201             BOOST_UBLAS_INLINE
    01202             const_reference operator * () const {
    01203                 // FIXME replace find with at_element
    01204                 return (*this) ().data_ (*it1_, *it2_);
    01205             }
    01206             BOOST_UBLAS_INLINE
    01207             const_reference operator [] (difference_type n) const {
    01208                 return *(*this + n);
    01209             }
    01210
    01211             // Index
    01212             BOOST_UBLAS_INLINE
    01213             size_type  index () const {
    01214                 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
    01215             }
    01216
    01217             // Assignment
    01218             BOOST_UBLAS_INLINE
    01219             const_iterator &operator = (const const_iterator &it) {
    01220                 container_const_reference<self_type>::assign (&it ());
    01221                 it1_ = it.it1_;
    01222                 it2_ = it.it2_;
    01223                 return *this;
    01224             }
    01225
    01226             // Comparison
    01227             BOOST_UBLAS_INLINE
    01228             bool operator == (const const_iterator &it) const {
    01229                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01230                 return it1_ == it.it1_ && it2_ == it.it2_;
    01231             }
    01232             BOOST_UBLAS_INLINE
    01233             bool operator < (const const_iterator &it) const {
    01234                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01235                 return it1_ < it.it1_ && it2_ < it.it2_;
    01236             }
    01237
    01238         private:
    01239             const_subiterator1_type it1_;
    01240             const_subiterator2_type it2_;
    01241         };
    01242
    01243         BOOST_UBLAS_INLINE
    01244         const_iterator begin () const {
    01245             return find (0);
    01246         }
    01247         BOOST_UBLAS_INLINE
    01248         const_iterator end () const {
    01249             return find (size ());
    01250         }
    01251
    01252         class iterator:
    01253             public container_reference<matrix_vector_range>,
    01254             public iterator_base_traits<typename M::iterator1::iterator_category>::template
    01255                         iterator_base<iterator, value_type>::type {
    01256         public:
    01257             // FIXME Iterator can never be different code was:
    01258             // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
    01259             BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
    01260
    01261             typedef typename matrix_vector_range::value_type value_type;
    01262             typedef typename matrix_vector_range::difference_type difference_type;
    01263             typedef typename matrix_vector_range::reference reference;
    01264             typedef typename matrix_vector_range::value_type *pointer;
    01265
    01266             // Construction and destruction
    01267             BOOST_UBLAS_INLINE
    01268             iterator ():
    01269                 container_reference<self_type> (), it1_ (), it2_ () {}
    01270             BOOST_UBLAS_INLINE
    01271             iterator (self_type &mvr, const subiterator1_type &it1, const subiterator2_type &it2):
    01272                 container_reference<self_type> (mvr), it1_ (it1), it2_ (it2) {}
    01273
    01274             // Arithmetic
    01275             BOOST_UBLAS_INLINE
    01276             iterator &operator ++ () {
    01277                 ++ it1_;
    01278                 ++ it2_;
    01279                 return *this;
    01280             }
    01281             BOOST_UBLAS_INLINE
    01282             iterator &operator -- () {
    01283                 -- it1_;
    01284                 -- it2_;
    01285                 return *this;
    01286             }
    01287             BOOST_UBLAS_INLINE
    01288             iterator &operator += (difference_type n) {
    01289                 it1_ += n;
    01290                 it2_ += n;
    01291                 return *this;
    01292             }
    01293             BOOST_UBLAS_INLINE
    01294             iterator &operator -= (difference_type n) {
    01295                 it1_ -= n;
    01296                 it2_ -= n;
    01297                 return *this;
    01298             }
    01299             BOOST_UBLAS_INLINE
    01300             difference_type operator - (const iterator &it) const {
    01301                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    01302                 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
    01303             }
    01304
    01305             // Dereference
    01306             BOOST_UBLAS_INLINE
    01307             reference operator * () const {
    01308                 // FIXME replace find with at_element
    01309                 return (*this) ().data_ (*it1_, *it2_);
    01310             }
    01311             BOOST_UBLAS_INLINE
    01312             reference operator [] (difference_type n) const {
    01313                 return *(*this + n);
    01314             }
    01315
    01316             // Index
    01317             BOOST_UBLAS_INLINE
    01318             size_type index () const {
    01319                 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
    01320             }
    01321
    01322             // Assignment
    01323             BOOST_UBLAS_INLINE
    01324             iterator &operator = (const iterator &it) {
    01325                 container_reference<self_type>::assign (&it ());
    01326                 it1_ = it.it1_;
    01327                 it2_ = it.it2_;
    01328                 return *this;
    01329             }
    01330
    01331             // Comparison
    01332             BOOST_UBLAS_INLINE
    01333             bool operator == (const iterator &it) const {
    01334                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01335                 return it1_ == it.it1_ && it2_ == it.it2_;
    01336             }
    01337             BOOST_UBLAS_INLINE
    01338             bool operator < (const iterator &it) const {
    01339                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01340                 return it1_ < it.it1_ && it2_ < it.it2_;
    01341             }
    01342
    01343         private:
    01344             subiterator1_type it1_;
    01345             subiterator2_type it2_;
    01346
    01347             friend class const_iterator;
    01348         };
    01349
    01350         BOOST_UBLAS_INLINE
    01351         iterator begin () {
    01352             return find (0);
    01353         }
    01354         BOOST_UBLAS_INLINE
    01355         iterator end () {
    01356             return find (size ());
    01357         }
    01358
    01359         // Reverse iterator
    01360         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
    01361         typedef reverse_iterator_base<iterator> reverse_iterator;
    01362
    01363         BOOST_UBLAS_INLINE
    01364         const_reverse_iterator rbegin () const {
    01365             return const_reverse_iterator (end ());
    01366         }
    01367         BOOST_UBLAS_INLINE
    01368         const_reverse_iterator rend () const {
    01369             return const_reverse_iterator (begin ());
    01370         }
    01371         BOOST_UBLAS_INLINE
    01372         reverse_iterator rbegin () {
    01373             return reverse_iterator (end ());
    01374         }
    01375         BOOST_UBLAS_INLINE
    01376         reverse_iterator rend () {
    01377             return reverse_iterator (begin ());
    01378         }
    01379
    01380     private:
    01381         matrix_closure_type data_;
    01382         range_type r1_;
    01383         range_type r2_;
    01384     };
    01385
    01386     // Specialize temporary
    01387     template <class M>
    01388     struct vector_temporary_traits< matrix_vector_range<M> >
    01389     : vector_temporary_traits< M > {} ;
    01390     template <class M>
    01391     struct vector_temporary_traits< const matrix_vector_range<M> >
    01392     : vector_temporary_traits< M > {} ;
    01393
    01394     // Matrix based vector slice class
    01395     template<class M>
    01396     class matrix_vector_slice:
    01397         public vector_expression<matrix_vector_slice<M> > {
    01398
    01399         typedef matrix_vector_slice<M> self_type;
    01400     public:
    01401 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    01402         using vector_expression<self_type>::operator ();
    01403 #endif
    01404         typedef M matrix_type;
    01405         typedef typename M::size_type size_type;
    01406         typedef typename M::difference_type difference_type;
    01407         typedef typename M::value_type value_type;
    01408         typedef typename M::const_reference const_reference;
    01409         typedef typename boost::mpl::if_<boost::is_const<M>,
    01410                                           typename M::const_reference,
    01411                                           typename M::reference>::type reference;
    01412         typedef typename boost::mpl::if_<boost::is_const<M>,
    01413                                           typename M::const_closure_type,
    01414                                           typename M::closure_type>::type matrix_closure_type;
    01415         typedef basic_range<size_type, difference_type> range_type;
    01416         typedef basic_slice<size_type, difference_type> slice_type;
    01417         typedef const self_type const_closure_type;
    01418         typedef self_type closure_type;
    01419         typedef typename storage_restrict_traits<typename M::storage_category,
    01420                                                  dense_proxy_tag>::storage_category storage_category;
    01421
    01422         // Construction and destruction
    01423         BOOST_UBLAS_INLINE
    01424         matrix_vector_slice (matrix_type &data, const slice_type &s1, const slice_type &s2):
    01425             data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {
    01426             // Early checking of preconditions here.
    01427             // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
    01428             //                    s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
    01429             // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
    01430             //                    s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
    01431         }
    01432
    01433         // Accessors
    01434         BOOST_UBLAS_INLINE
    01435         size_type start1 () const {
    01436             return s1_.start ();
    01437         }
    01438         BOOST_UBLAS_INLINE
    01439         size_type start2 () const {
    01440             return s2_.start ();
    01441         }
    01442         BOOST_UBLAS_INLINE
    01443         difference_type stride1 () const {
    01444             return s1_.stride ();
    01445         }
    01446         BOOST_UBLAS_INLINE
    01447         difference_type stride2 () const {
    01448             return s2_.stride ();
    01449         }
    01450         BOOST_UBLAS_INLINE
    01451         size_type size () const {
    01452             return BOOST_UBLAS_SAME (s1_.size (), s2_.size ());
    01453         }
    01454
    01455         // Storage accessors
    01456         BOOST_UBLAS_INLINE
    01457         const matrix_closure_type &data () const {
    01458             return data_;
    01459         }
    01460         BOOST_UBLAS_INLINE
    01461         matrix_closure_type &data () {
    01462             return data_;
    01463         }
    01464
    01465         // Element access
    01466 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
    01467         BOOST_UBLAS_INLINE
    01468         const_reference operator () (size_type i) const {
    01469             return data_ (s1_ (i), s2_ (i));
    01470         }
    01471         BOOST_UBLAS_INLINE
    01472         reference operator () (size_type i) {
    01473             return data_ (s1_ (i), s2_ (i));
    01474         }
    01475
    01476         BOOST_UBLAS_INLINE
    01477         const_reference operator [] (size_type i) const {
    01478             return (*this) (i);
    01479         }
    01480         BOOST_UBLAS_INLINE
    01481         reference operator [] (size_type i) {
    01482             return (*this) (i);
    01483         }
    01484 #else
    01485         BOOST_UBLAS_INLINE
    01486         reference operator () (size_type i) const {
    01487             return data_ (s1_ (i), s2_ (i));
    01488         }
    01489
    01490         BOOST_UBLAS_INLINE
    01491         reference operator [] (size_type i) const {
    01492             return (*this) (i);
    01493         }
    01494 #endif
    01495
    01496         // Assignment
    01497         BOOST_UBLAS_INLINE
    01498         matrix_vector_slice &operator = (const matrix_vector_slice &mvs) {
    01499             // ISSUE need a temporary, proxy can be overlaping alias
    01500             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvs));
    01501             return *this;
    01502         }
    01503         BOOST_UBLAS_INLINE
    01504         matrix_vector_slice &assign_temporary (matrix_vector_slice &mvs) {
    01505             // assign elements, proxied container remains the same
    01506             vector_assign<scalar_assign> (*this, mvs);
    01507             return *this;
    01508         }
    01509         template<class AE>
    01510         BOOST_UBLAS_INLINE
    01511         matrix_vector_slice &operator = (const vector_expression<AE> &ae) {
    01512             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
    01513             return *this;
    01514         }
    01515         template<class AE>
    01516         BOOST_UBLAS_INLINE
    01517         matrix_vector_slice &assign (const vector_expression<AE> &ae) {
    01518             vector_assign<scalar_assign> (*this, ae);
    01519             return *this;
    01520         }
    01521         template<class AE>
    01522         BOOST_UBLAS_INLINE
    01523         matrix_vector_slice &operator += (const vector_expression<AE> &ae) {
    01524             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
    01525             return *this;
    01526         }
    01527         template<class AE>
    01528         BOOST_UBLAS_INLINE
    01529         matrix_vector_slice &plus_assign (const vector_expression<AE> &ae) {
    01530             vector_assign<scalar_plus_assign> (*this, ae);
    01531             return *this;
    01532         }
    01533         template<class AE>
    01534         BOOST_UBLAS_INLINE
    01535         matrix_vector_slice &operator -= (const vector_expression<AE> &ae) {
    01536             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
    01537             return *this;
    01538         }
    01539         template<class AE>
    01540         BOOST_UBLAS_INLINE
    01541         matrix_vector_slice &minus_assign (const vector_expression<AE> &ae) {
    01542             vector_assign<scalar_minus_assign> (*this, ae);
    01543             return *this;
    01544         }
    01545         template<class AT>
    01546         BOOST_UBLAS_INLINE
    01547         matrix_vector_slice &operator *= (const AT &at) {
    01548             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
    01549             return *this;
    01550         }
    01551         template<class AT>
    01552         BOOST_UBLAS_INLINE
    01553         matrix_vector_slice &operator /= (const AT &at) {
    01554             vector_assign_scalar<scalar_divides_assign> (*this, at);
    01555             return *this;
    01556         }
    01557
    01558         // Closure comparison
    01559         BOOST_UBLAS_INLINE
    01560         bool same_closure (const matrix_vector_slice &mvs) const {
    01561             return (*this).data_.same_closure (mvs.data_);
    01562         }
    01563
    01564         // Comparison
    01565         BOOST_UBLAS_INLINE
    01566         bool operator == (const matrix_vector_slice &mvs) const {
    01567             return (*this).data_ == mvs.data_ && s1_ == mvs.s1_ && s2_ == mvs.s2_;
    01568         }
    01569
    01570         // Swapping
    01571         BOOST_UBLAS_INLINE
    01572         void swap (matrix_vector_slice mvs) {
    01573             if (this != &mvs) {
    01574                 BOOST_UBLAS_CHECK (size () == mvs.size (), bad_size ());
    01575                 // Sparse ranges may be nonconformant now.
    01576                 // std::swap_ranges (begin (), end (), mvs.begin ());
    01577                 vector_swap<scalar_swap> (*this, mvs);
    01578             }
    01579         }
    01580         BOOST_UBLAS_INLINE
    01581         friend void swap (matrix_vector_slice mvs1, matrix_vector_slice mvs2) {
    01582             mvs1.swap (mvs2);
    01583         }
    01584
    01585         // Iterator types
    01586     private:
    01587         // Use slice as an index - FIXME this fails for packed assignment
    01588         typedef typename slice_type::const_iterator const_subiterator1_type;
    01589         typedef typename slice_type::const_iterator subiterator1_type;
    01590         typedef typename slice_type::const_iterator const_subiterator2_type;
    01591         typedef typename slice_type::const_iterator subiterator2_type;
    01592
    01593     public:
    01594         class const_iterator;
    01595         class iterator;
    01596
    01597         // Element lookup
    01598         BOOST_UBLAS_INLINE
    01599         const_iterator find (size_type i) const {
    01600             return const_iterator (*this, s1_.begin () + i, s2_.begin () + i);
    01601         }
    01602         BOOST_UBLAS_INLINE
    01603         iterator find (size_type i) {
    01604             return iterator (*this, s1_.begin () + i, s2_.begin () + i);
    01605         }
    01606
    01607         // Iterators simply are indices.
    01608
    01609         class const_iterator:
    01610             public container_const_reference<matrix_vector_slice>,
    01611             public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
    01612                         iterator_base<const_iterator, value_type>::type {
    01613         public:
    01614             // FIXME Iterator can never be different code was:
    01615             // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
    01616             BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
    01617
    01618             typedef typename matrix_vector_slice::value_type value_type;
    01619             typedef typename matrix_vector_slice::difference_type difference_type;
    01620             typedef typename matrix_vector_slice::const_reference reference;
    01621             typedef const typename matrix_vector_slice::value_type *pointer;
    01622
    01623             // Construction and destruction
    01624             BOOST_UBLAS_INLINE
    01625             const_iterator ():
    01626                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    01627             BOOST_UBLAS_INLINE
    01628             const_iterator (const self_type &mvs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
    01629                 container_const_reference<self_type> (mvs), it1_ (it1), it2_ (it2) {}
    01630             BOOST_UBLAS_INLINE
    01631             const_iterator (const typename self_type::iterator &it):  // ISSUE vector:: stops VC8 using std::iterator here
    01632                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
    01633
    01634             // Arithmetic
    01635             BOOST_UBLAS_INLINE
    01636             const_iterator &operator ++ () {
    01637                 ++ it1_;
    01638                 ++ it2_;
    01639                 return *this;
    01640             }
    01641             BOOST_UBLAS_INLINE
    01642             const_iterator &operator -- () {
    01643                 -- it1_;
    01644                 -- it2_;
    01645                 return *this;
    01646             }
    01647             BOOST_UBLAS_INLINE
    01648             const_iterator &operator += (difference_type n) {
    01649                 it1_ += n;
    01650                 it2_ += n;
    01651                 return *this;
    01652             }
    01653             BOOST_UBLAS_INLINE
    01654             const_iterator &operator -= (difference_type n) {
    01655                 it1_ -= n;
    01656                 it2_ -= n;
    01657                 return *this;
    01658             }
    01659             BOOST_UBLAS_INLINE
    01660             difference_type operator - (const const_iterator &it) const {
    01661                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    01662                 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
    01663             }
    01664
    01665             // Dereference
    01666             BOOST_UBLAS_INLINE
    01667             const_reference operator * () const {
    01668                 // FIXME replace find with at_element
    01669                 return (*this) ().data_ (*it1_, *it2_);
    01670             }
    01671             BOOST_UBLAS_INLINE
    01672             const_reference operator [] (difference_type n) const {
    01673                 return *(*this + n);
    01674             }
    01675
    01676             // Index
    01677             BOOST_UBLAS_INLINE
    01678             size_type  index () const {
    01679                 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
    01680             }
    01681
    01682             // Assignment
    01683             BOOST_UBLAS_INLINE
    01684             const_iterator &operator = (const const_iterator &it) {
    01685                 container_const_reference<self_type>::assign (&it ());
    01686                 it1_ = it.it1_;
    01687                 it2_ = it.it2_;
    01688                 return *this;
    01689             }
    01690
    01691             // Comparison
    01692             BOOST_UBLAS_INLINE
    01693             bool operator == (const const_iterator &it) const {
    01694                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01695                 return it1_ == it.it1_ && it2_ == it.it2_;
    01696             }
    01697             BOOST_UBLAS_INLINE
    01698             bool operator < (const const_iterator &it) const {
    01699                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01700                 return it1_ < it.it1_ && it2_ < it.it2_;
    01701             }
    01702
    01703         private:
    01704             const_subiterator1_type it1_;
    01705             const_subiterator2_type it2_;
    01706         };
    01707
    01708         BOOST_UBLAS_INLINE
    01709         const_iterator begin () const {
    01710             return find (0);
    01711         }
    01712         BOOST_UBLAS_INLINE
    01713         const_iterator end () const {
    01714             return find (size ());
    01715         }
    01716
    01717         class iterator:
    01718             public container_reference<matrix_vector_slice>,
    01719             public iterator_base_traits<typename M::iterator1::iterator_category>::template
    01720                         iterator_base<iterator, value_type>::type {
    01721         public:
    01722             // FIXME Iterator can never be different code was:
    01723             // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
    01724             BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
    01725
    01726             typedef typename matrix_vector_slice::value_type value_type;
    01727             typedef typename matrix_vector_slice::difference_type difference_type;
    01728             typedef typename matrix_vector_slice::reference reference;
    01729             typedef typename matrix_vector_slice::value_type *pointer;
    01730
    01731             // Construction and destruction
    01732             BOOST_UBLAS_INLINE
    01733             iterator ():
    01734                 container_reference<self_type> (), it1_ (), it2_ () {}
    01735             BOOST_UBLAS_INLINE
    01736             iterator (self_type &mvs, const subiterator1_type &it1, const subiterator2_type &it2):
    01737                 container_reference<self_type> (mvs), it1_ (it1), it2_ (it2) {}
    01738
    01739             // Arithmetic
    01740             BOOST_UBLAS_INLINE
    01741             iterator &operator ++ () {
    01742                 ++ it1_;
    01743                 ++ it2_;
    01744                 return *this;
    01745             }
    01746             BOOST_UBLAS_INLINE
    01747             iterator &operator -- () {
    01748                 -- it1_;
    01749                 -- it2_;
    01750                 return *this;
    01751             }
    01752             BOOST_UBLAS_INLINE
    01753             iterator &operator += (difference_type n) {
    01754                 it1_ += n;
    01755                 it2_ += n;
    01756                 return *this;
    01757             }
    01758             BOOST_UBLAS_INLINE
    01759             iterator &operator -= (difference_type n) {
    01760                 it1_ -= n;
    01761                 it2_ -= n;
    01762                 return *this;
    01763             }
    01764             BOOST_UBLAS_INLINE
    01765             difference_type operator - (const iterator &it) const {
    01766                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    01767                 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
    01768             }
    01769
    01770             // Dereference
    01771             BOOST_UBLAS_INLINE
    01772             reference operator * () const {
    01773                 // FIXME replace find with at_element
    01774                 return (*this) ().data_ (*it1_, *it2_);
    01775             }
    01776             BOOST_UBLAS_INLINE
    01777             reference operator [] (difference_type n) const {
    01778                 return *(*this + n);
    01779             }
    01780
    01781             // Index
    01782             BOOST_UBLAS_INLINE
    01783             size_type index () const {
    01784                 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
    01785             }
    01786
    01787             // Assignment
    01788             BOOST_UBLAS_INLINE
    01789             iterator &operator = (const iterator &it) {
    01790                 container_reference<self_type>::assign (&it ());
    01791                 it1_ = it.it1_;
    01792                 it2_ = it.it2_;
    01793                 return *this;
    01794             }
    01795
    01796             // Comparison
    01797             BOOST_UBLAS_INLINE
    01798             bool operator == (const iterator &it) const {
    01799                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01800                 return it1_ == it.it1_ && it2_ == it.it2_;
    01801             }
    01802             BOOST_UBLAS_INLINE
    01803             bool operator < (const iterator &it) const {
    01804                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01805                 return it1_ < it.it1_ && it2_ < it.it2_;
    01806             }
    01807
    01808         private:
    01809             subiterator1_type it1_;
    01810             subiterator2_type it2_;
    01811
    01812             friend class const_iterator;
    01813         };
    01814
    01815         BOOST_UBLAS_INLINE
    01816         iterator begin () {
    01817             return find (0);
    01818         }
    01819         BOOST_UBLAS_INLINE
    01820         iterator end () {
    01821             return find (size ());
    01822         }
    01823
    01824         // Reverse iterator
    01825         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
    01826         typedef reverse_iterator_base<iterator> reverse_iterator;
    01827
    01828         BOOST_UBLAS_INLINE
    01829         const_reverse_iterator rbegin () const {
    01830             return const_reverse_iterator (end ());
    01831         }
    01832         BOOST_UBLAS_INLINE
    01833         const_reverse_iterator rend () const {
    01834             return const_reverse_iterator (begin ());
    01835         }
    01836         BOOST_UBLAS_INLINE
    01837         reverse_iterator rbegin () {
    01838             return reverse_iterator (end ());
    01839         }
    01840         BOOST_UBLAS_INLINE
    01841         reverse_iterator rend () {
    01842             return reverse_iterator (begin ());
    01843         }
    01844
    01845     private:
    01846         matrix_closure_type data_;
    01847         slice_type s1_;
    01848         slice_type s2_;
    01849     };
    01850
    01851     // Specialize temporary
    01852     template <class M>
    01853     struct vector_temporary_traits< matrix_vector_slice<M> >
    01854     : vector_temporary_traits< M > {} ;
    01855     template <class M>
    01856     struct vector_temporary_traits< const matrix_vector_slice<M> >
    01857     : vector_temporary_traits< M > {} ;
    01858
    01859     // Matrix based vector indirection class
    01860
    01861     template<class M, class IA>
    01862     class matrix_vector_indirect:
    01863         public vector_expression<matrix_vector_indirect<M, IA> > {
    01864
    01865         typedef matrix_vector_indirect<M, IA> self_type;
    01866     public:
    01867 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    01868         using vector_expression<self_type>::operator ();
    01869 #endif
    01870         typedef M matrix_type;
    01871         typedef IA indirect_array_type;
    01872         typedef typename M::size_type size_type;
    01873         typedef typename M::difference_type difference_type;
    01874         typedef typename M::value_type value_type;
    01875         typedef typename M::const_reference const_reference;
    01876         typedef typename boost::mpl::if_<boost::is_const<M>,
    01877                                           typename M::const_reference,
    01878                                           typename M::reference>::type reference;
    01879         typedef typename boost::mpl::if_<boost::is_const<M>,
    01880                                           typename M::const_closure_type,
    01881                                           typename M::closure_type>::type matrix_closure_type;
    01882         typedef const self_type const_closure_type;
    01883         typedef self_type closure_type;
    01884         typedef typename storage_restrict_traits<typename M::storage_category,
    01885                                                  dense_proxy_tag>::storage_category storage_category;
    01886
    01887         // Construction and destruction
    01888         BOOST_UBLAS_INLINE
    01889         matrix_vector_indirect (matrix_type &data, size_type size):
    01890             data_ (data), ia1_ (size), ia2_ (size) {}
    01891         BOOST_UBLAS_INLINE
    01892         matrix_vector_indirect (matrix_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2):
    01893             data_ (data), ia1_ (ia1), ia2_ (ia2) {
    01894             // Early checking of preconditions here.
    01895             // BOOST_UBLAS_CHECK (ia1_.size () == ia2_.size (), bad_size ());
    01896         }
    01897
    01898         // Accessors
    01899         BOOST_UBLAS_INLINE
    01900         size_type size () const {
    01901             return BOOST_UBLAS_SAME (ia1_.size (), ia2_.size ());
    01902         }
    01903         BOOST_UBLAS_INLINE
    01904         const indirect_array_type &indirect1 () const {
    01905             return ia1_;
    01906         }
    01907         BOOST_UBLAS_INLINE
    01908         indirect_array_type &indirect1 () {
    01909             return ia1_;
    01910         }
    01911         BOOST_UBLAS_INLINE
    01912         const indirect_array_type &indirect2 () const {
    01913             return ia2_;
    01914         }
    01915         BOOST_UBLAS_INLINE
    01916         indirect_array_type &indirect2 () {
    01917             return ia2_;
    01918         }
    01919
    01920         // Storage accessors
    01921         BOOST_UBLAS_INLINE
    01922         const matrix_closure_type &data () const {
    01923             return data_;
    01924         }
    01925         BOOST_UBLAS_INLINE
    01926         matrix_closure_type &data () {
    01927             return data_;
    01928         }
    01929
    01930         // Element access
    01931 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
    01932         BOOST_UBLAS_INLINE
    01933         const_reference operator () (size_type i) const {
    01934             return data_ (ia1_ (i), ia2_ (i));
    01935         }
    01936         BOOST_UBLAS_INLINE
    01937         reference operator () (size_type i) {
    01938             return data_ (ia1_ (i), ia2_ (i));
    01939         }
    01940
    01941         BOOST_UBLAS_INLINE
    01942         const_reference operator [] (size_type i) const {
    01943             return (*this) (i);
    01944         }
    01945         BOOST_UBLAS_INLINE
    01946         reference operator [] (size_type i) {
    01947             return (*this) (i);
    01948         }
    01949 #else
    01950         BOOST_UBLAS_INLINE
    01951         reference operator () (size_type i) const {
    01952             return data_ (ia1_ (i), ia2_ (i));
    01953         }
    01954
    01955         BOOST_UBLAS_INLINE
    01956         reference operator [] (size_type i) const {
    01957             return (*this) (i);
    01958         }
    01959 #endif
    01960
    01961         // Assignment
    01962         BOOST_UBLAS_INLINE
    01963         matrix_vector_indirect &operator = (const matrix_vector_indirect &mvi) {
    01964             // ISSUE need a temporary, proxy can be overlaping alias
    01965             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvi));
    01966             return *this;
    01967         }
    01968         BOOST_UBLAS_INLINE
    01969         matrix_vector_indirect &assign_temporary (matrix_vector_indirect &mvi) {
    01970             // assign elements, proxied container remains the same
    01971             vector_assign<scalar_assign> (*this, mvi);
    01972             return *this;
    01973         }
    01974         template<class AE>
    01975         BOOST_UBLAS_INLINE
    01976         matrix_vector_indirect &operator = (const vector_expression<AE> &ae) {
    01977             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
    01978             return *this;
    01979         }
    01980         template<class AE>
    01981         BOOST_UBLAS_INLINE
    01982         matrix_vector_indirect &assign (const vector_expression<AE> &ae) {
    01983             vector_assign<scalar_assign> (*this, ae);
    01984             return *this;
    01985         }
    01986         template<class AE>
    01987         BOOST_UBLAS_INLINE
    01988         matrix_vector_indirect &operator += (const vector_expression<AE> &ae) {
    01989             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
    01990             return *this;
    01991         }
    01992         template<class AE>
    01993         BOOST_UBLAS_INLINE
    01994         matrix_vector_indirect &plus_assign (const vector_expression<AE> &ae) {
    01995             vector_assign<scalar_plus_assign> (*this, ae);
    01996             return *this;
    01997         }
    01998         template<class AE>
    01999         BOOST_UBLAS_INLINE
    02000         matrix_vector_indirect &operator -= (const vector_expression<AE> &ae) {
    02001             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
    02002             return *this;
    02003         }
    02004         template<class AE>
    02005         BOOST_UBLAS_INLINE
    02006         matrix_vector_indirect &minus_assign (const vector_expression<AE> &ae) {
    02007             vector_assign<scalar_minus_assign> (*this, ae);
    02008             return *this;
    02009         }
    02010         template<class AT>
    02011         BOOST_UBLAS_INLINE
    02012         matrix_vector_indirect &operator *= (const AT &at) {
    02013             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
    02014             return *this;
    02015         }
    02016         template<class AT>
    02017         BOOST_UBLAS_INLINE
    02018         matrix_vector_indirect &operator /= (const AT &at) {
    02019             vector_assign_scalar<scalar_divides_assign> (*this, at);
    02020             return *this;
    02021         }
    02022
    02023         // Closure comparison
    02024         BOOST_UBLAS_INLINE
    02025         bool same_closure (const matrix_vector_indirect &mvi) const {
    02026             return (*this).data_.same_closure (mvi.data_);
    02027         }
    02028
    02029         // Comparison
    02030         BOOST_UBLAS_INLINE
    02031         bool operator == (const matrix_vector_indirect &mvi) const {
    02032             return (*this).data_ == mvi.data_ && ia1_ == mvi.ia1_ && ia2_ == mvi.ia2_;
    02033         }
    02034
    02035         // Swapping
    02036         BOOST_UBLAS_INLINE
    02037         void swap (matrix_vector_indirect mvi) {
    02038             if (this != &mvi) {
    02039                 BOOST_UBLAS_CHECK (size () == mvi.size (), bad_size ());
    02040                 // Sparse ranges may be nonconformant now.
    02041                 // std::swap_ranges (begin (), end (), mvi.begin ());
    02042                 vector_swap<scalar_swap> (*this, mvi);
    02043             }
    02044         }
    02045         BOOST_UBLAS_INLINE
    02046         friend void swap (matrix_vector_indirect mvi1, matrix_vector_indirect mvi2) {
    02047             mvi1.swap (mvi2);
    02048         }
    02049
    02050         // Iterator types
    02051     private:
    02052         // Use indirect array as an index - FIXME this fails for packed assignment
    02053         typedef typename IA::const_iterator const_subiterator1_type;
    02054         typedef typename IA::const_iterator subiterator1_type;
    02055         typedef typename IA::const_iterator const_subiterator2_type;
    02056         typedef typename IA::const_iterator subiterator2_type;
    02057
    02058     public:
    02059         class const_iterator;
    02060         class iterator;
    02061
    02062         // Element lookup
    02063         BOOST_UBLAS_INLINE
    02064         const_iterator find (size_type i) const {
    02065             return const_iterator (*this, ia1_.begin () + i, ia2_.begin () + i);
    02066         }
    02067         BOOST_UBLAS_INLINE
    02068         iterator find (size_type i) {
    02069             return iterator (*this, ia1_.begin () + i, ia2_.begin () + i);
    02070         }
    02071
    02072         // Iterators simply are indices.
    02073
    02074         class const_iterator:
    02075             public container_const_reference<matrix_vector_indirect>,
    02076             public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
    02077                         iterator_base<const_iterator, value_type>::type {
    02078         public:
    02079             // FIXME Iterator can never be different code was:
    02080             // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
    02081             BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
    02082
    02083             typedef typename matrix_vector_indirect::value_type value_type;
    02084             typedef typename matrix_vector_indirect::difference_type difference_type;
    02085             typedef typename matrix_vector_indirect::const_reference reference;
    02086             typedef const typename matrix_vector_indirect::value_type *pointer;
    02087
    02088             // Construction and destruction
    02089             BOOST_UBLAS_INLINE
    02090             const_iterator ():
    02091                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    02092             BOOST_UBLAS_INLINE
    02093             const_iterator (const self_type &mvi, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
    02094                 container_const_reference<self_type> (mvi), it1_ (it1), it2_ (it2) {}
    02095             BOOST_UBLAS_INLINE
    02096             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
    02097                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
    02098
    02099             // Arithmetic
    02100             BOOST_UBLAS_INLINE
    02101             const_iterator &operator ++ () {
    02102                 ++ it1_;
    02103                 ++ it2_;
    02104                 return *this;
    02105             }
    02106             BOOST_UBLAS_INLINE
    02107             const_iterator &operator -- () {
    02108                 -- it1_;
    02109                 -- it2_;
    02110                 return *this;
    02111             }
    02112             BOOST_UBLAS_INLINE
    02113             const_iterator &operator += (difference_type n) {
    02114                 it1_ += n;
    02115                 it2_ += n;
    02116                 return *this;
    02117             }
    02118             BOOST_UBLAS_INLINE
    02119             const_iterator &operator -= (difference_type n) {
    02120                 it1_ -= n;
    02121                 it2_ -= n;
    02122                 return *this;
    02123             }
    02124             BOOST_UBLAS_INLINE
    02125             difference_type operator - (const const_iterator &it) const {
    02126                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    02127                 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
    02128             }
    02129
    02130             // Dereference
    02131             BOOST_UBLAS_INLINE
    02132             const_reference operator * () const {
    02133                 // FIXME replace find with at_element
    02134                 return (*this) ().data_ (*it1_, *it2_);
    02135             }
    02136             BOOST_UBLAS_INLINE
    02137             const_reference operator [] (difference_type n) const {
    02138                 return *(*this + n);
    02139             }
    02140
    02141             // Index
    02142             BOOST_UBLAS_INLINE
    02143             size_type  index () const {
    02144                 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
    02145             }
    02146
    02147             // Assignment
    02148             BOOST_UBLAS_INLINE
    02149             const_iterator &operator = (const const_iterator &it) {
    02150                 container_const_reference<self_type>::assign (&it ());
    02151                 it1_ = it.it1_;
    02152                 it2_ = it.it2_;
    02153                 return *this;
    02154             }
    02155
    02156             // Comparison
    02157             BOOST_UBLAS_INLINE
    02158             bool operator == (const const_iterator &it) const {
    02159                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02160                 return it1_ == it.it1_ && it2_ == it.it2_;
    02161             }
    02162             BOOST_UBLAS_INLINE
    02163             bool operator < (const const_iterator &it) const {
    02164                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02165                 return it1_ < it.it1_ && it2_ < it.it2_;
    02166             }
    02167
    02168         private:
    02169             const_subiterator1_type it1_;
    02170             const_subiterator2_type it2_;
    02171         };
    02172
    02173         BOOST_UBLAS_INLINE
    02174         const_iterator begin () const {
    02175             return find (0);
    02176         }
    02177         BOOST_UBLAS_INLINE
    02178         const_iterator end () const {
    02179             return find (size ());
    02180         }
    02181
    02182         class iterator:
    02183             public container_reference<matrix_vector_indirect>,
    02184             public iterator_base_traits<typename M::iterator1::iterator_category>::template
    02185                         iterator_base<iterator, value_type>::type {
    02186         public:
    02187             // FIXME Iterator can never be different code was:
    02188             // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
    02189             BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
    02190
    02191             typedef typename matrix_vector_indirect::value_type value_type;
    02192             typedef typename matrix_vector_indirect::difference_type difference_type;
    02193             typedef typename matrix_vector_indirect::reference reference;
    02194             typedef typename matrix_vector_indirect::value_type *pointer;
    02195
    02196             // Construction and destruction
    02197             BOOST_UBLAS_INLINE
    02198             iterator ():
    02199                 container_reference<self_type> (), it1_ (), it2_ () {}
    02200             BOOST_UBLAS_INLINE
    02201             iterator (self_type &mvi, const subiterator1_type &it1, const subiterator2_type &it2):
    02202                 container_reference<self_type> (mvi), it1_ (it1), it2_ (it2) {}
    02203
    02204             // Arithmetic
    02205             BOOST_UBLAS_INLINE
    02206             iterator &operator ++ () {
    02207                 ++ it1_;
    02208                 ++ it2_;
    02209                 return *this;
    02210             }
    02211             BOOST_UBLAS_INLINE
    02212             iterator &operator -- () {
    02213                 -- it1_;
    02214                 -- it2_;
    02215                 return *this;
    02216             }
    02217             BOOST_UBLAS_INLINE
    02218             iterator &operator += (difference_type n) {
    02219                 it1_ += n;
    02220                 it2_ += n;
    02221                 return *this;
    02222             }
    02223             BOOST_UBLAS_INLINE
    02224             iterator &operator -= (difference_type n) {
    02225                 it1_ -= n;
    02226                 it2_ -= n;
    02227                 return *this;
    02228             }
    02229             BOOST_UBLAS_INLINE
    02230             difference_type operator - (const iterator &it) const {
    02231                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    02232                 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
    02233             }
    02234
    02235             // Dereference
    02236             BOOST_UBLAS_INLINE
    02237             reference operator * () const {
    02238                 // FIXME replace find with at_element
    02239                 return (*this) ().data_ (*it1_, *it2_);
    02240             }
    02241             BOOST_UBLAS_INLINE
    02242             reference operator [] (difference_type n) const {
    02243                 return *(*this + n);
    02244             }
    02245
    02246             // Index
    02247             BOOST_UBLAS_INLINE
    02248             size_type index () const {
    02249                 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
    02250             }
    02251
    02252             // Assignment
    02253             BOOST_UBLAS_INLINE
    02254             iterator &operator = (const iterator &it) {
    02255                 container_reference<self_type>::assign (&it ());
    02256                 it1_ = it.it1_;
    02257                 it2_ = it.it2_;
    02258                 return *this;
    02259             }
    02260
    02261             // Comparison
    02262             BOOST_UBLAS_INLINE
    02263             bool operator == (const iterator &it) const {
    02264                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02265                 return it1_ == it.it1_ && it2_ == it.it2_;
    02266             }
    02267             BOOST_UBLAS_INLINE
    02268             bool operator < (const iterator &it) const {
    02269                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02270                 return it1_ < it.it1_ && it2_ < it.it2_;
    02271             }
    02272
    02273         private:
    02274             subiterator1_type it1_;
    02275             subiterator2_type it2_;
    02276
    02277             friend class const_iterator;
    02278         };
    02279
    02280         BOOST_UBLAS_INLINE
    02281         iterator begin () {
    02282             return find (0);
    02283         }
    02284         BOOST_UBLAS_INLINE
    02285         iterator end () {
    02286             return find (size ());
    02287         }
    02288
    02289         // Reverse iterator
    02290         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
    02291         typedef reverse_iterator_base<iterator> reverse_iterator;
    02292
    02293         BOOST_UBLAS_INLINE
    02294         const_reverse_iterator rbegin () const {
    02295             return const_reverse_iterator (end ());
    02296         }
    02297         BOOST_UBLAS_INLINE
    02298         const_reverse_iterator rend () const {
    02299             return const_reverse_iterator (begin ());
    02300         }
    02301         BOOST_UBLAS_INLINE
    02302         reverse_iterator rbegin () {
    02303             return reverse_iterator (end ());
    02304         }
    02305         BOOST_UBLAS_INLINE
    02306         reverse_iterator rend () {
    02307             return reverse_iterator (begin ());
    02308         }
    02309
    02310     private:
    02311         matrix_closure_type data_;
    02312         indirect_array_type ia1_;
    02313         indirect_array_type ia2_;
    02314     };
    02315
    02316     // Specialize temporary
    02317     template <class M, class IA>
    02318     struct vector_temporary_traits< matrix_vector_indirect<M,IA> >
    02319     : vector_temporary_traits< M > {} ;
    02320     template <class M, class IA>
    02321     struct vector_temporary_traits< const matrix_vector_indirect<M,IA> >
    02322     : vector_temporary_traits< M > {} ;
    02323
    02324     // Matrix based range class
    02325     template<class M>
    02326     class matrix_range:
    02327         public matrix_expression<matrix_range<M> > {
    02328
    02329         typedef matrix_range<M> self_type;
    02330     public:
    02331 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    02332         using matrix_expression<self_type>::operator ();
    02333 #endif
    02334         typedef M matrix_type;
    02335         typedef typename M::size_type size_type;
    02336         typedef typename M::difference_type difference_type;
    02337         typedef typename M::value_type value_type;
    02338         typedef typename M::const_reference const_reference;
    02339         typedef typename boost::mpl::if_<boost::is_const<M>,
    02340                                           typename M::const_reference,
    02341                                           typename M::reference>::type reference;
    02342         typedef typename boost::mpl::if_<boost::is_const<M>,
    02343                                           typename M::const_closure_type,
    02344                                           typename M::closure_type>::type matrix_closure_type;
    02345         typedef basic_range<size_type, difference_type> range_type;
    02346         typedef const self_type const_closure_type;
    02347         typedef self_type closure_type;
    02348         typedef typename storage_restrict_traits<typename M::storage_category,
    02349                                                  dense_proxy_tag>::storage_category storage_category;
    02350         typedef typename M::orientation_category orientation_category;
    02351
    02352         // Construction and destruction
    02353         BOOST_UBLAS_INLINE
    02354         matrix_range (matrix_type &data, const range_type &r1, const range_type &r2):
    02355             data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {
    02356             // Early checking of preconditions here.
    02357             // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
    02358             //                    r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
    02359             // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
    02360             //                    r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
    02361         }
    02362         BOOST_UBLAS_INLINE
    02363         matrix_range (const matrix_closure_type &data, const range_type &r1, const range_type &r2, int):
    02364             data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {
    02365             // Early checking of preconditions here.
    02366             // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
    02367             //                    r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
    02368             // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
    02369             //                    r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
    02370         }
    02371
    02372         // Accessors
    02373         BOOST_UBLAS_INLINE
    02374         size_type start1 () const {
    02375             return r1_.start ();
    02376         }
    02377         BOOST_UBLAS_INLINE
    02378         size_type size1 () const {
    02379             return r1_.size ();
    02380         }
    02381         BOOST_UBLAS_INLINE
    02382         size_type start2() const {
    02383             return r2_.start ();
    02384         }
    02385         BOOST_UBLAS_INLINE
    02386         size_type size2 () const {
    02387             return r2_.size ();
    02388         }
    02389
    02390         // Storage accessors
    02391         BOOST_UBLAS_INLINE
    02392         const matrix_closure_type &data () const {
    02393             return data_;
    02394         }
    02395         BOOST_UBLAS_INLINE
    02396         matrix_closure_type &data () {
    02397             return data_;
    02398         }
    02399
    02400         // Element access
    02401 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
    02402         BOOST_UBLAS_INLINE
    02403         const_reference operator () (size_type i, size_type j) const {
    02404             return data_ (r1_ (i), r2_ (j));
    02405         }
    02406         BOOST_UBLAS_INLINE
    02407         reference operator () (size_type i, size_type j) {
    02408             return data_ (r1_ (i), r2_ (j));
    02409         }
    02410 #else
    02411         BOOST_UBLAS_INLINE
    02412         reference operator () (size_type i, size_type j) const {
    02413             return data_ (r1_ (i), r2_ (j));
    02414         }
    02415 #endif
    02416
    02417         // ISSUE can this be done in free project function?
    02418         // Although a const function can create a non-const proxy to a non-const object
    02419         // Critical is that matrix_type and data_ (vector_closure_type) are const correct
    02420         BOOST_UBLAS_INLINE
    02421         matrix_range<matrix_type> project (const range_type &r1, const range_type &r2) const {
    02422             return matrix_range<matrix_type>  (data_, r1_.compose (r1.preprocess (data_.size1 ())), r2_.compose (r2.preprocess (data_.size2 ())), 0);
    02423         }
    02424
    02425         // Assignment
    02426         BOOST_UBLAS_INLINE
    02427         matrix_range &operator = (const matrix_range &mr) {
    02428             matrix_assign<scalar_assign> (*this, mr);
    02429             return *this;
    02430         }
    02431         BOOST_UBLAS_INLINE
    02432         matrix_range &assign_temporary (matrix_range &mr) {
    02433             return *this = mr;
    02434         }
    02435         template<class AE>
    02436         BOOST_UBLAS_INLINE
    02437         matrix_range &operator = (const matrix_expression<AE> &ae) {
    02438             matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae));
    02439             return *this;
    02440         }
    02441         template<class AE>
    02442         BOOST_UBLAS_INLINE
    02443         matrix_range &assign (const matrix_expression<AE> &ae) {
    02444             matrix_assign<scalar_assign> (*this, ae);
    02445             return *this;
    02446         }
    02447         template<class AE>
    02448         BOOST_UBLAS_INLINE
    02449         matrix_range& operator += (const matrix_expression<AE> &ae) {
    02450             matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae));
    02451             return *this;
    02452         }
    02453         template<class AE>
    02454         BOOST_UBLAS_INLINE
    02455         matrix_range &plus_assign (const matrix_expression<AE> &ae) {
    02456             matrix_assign<scalar_plus_assign> (*this, ae);
    02457             return *this;
    02458         }
    02459         template<class AE>
    02460         BOOST_UBLAS_INLINE
    02461         matrix_range& operator -= (const matrix_expression<AE> &ae) {
    02462             matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae));
    02463             return *this;
    02464         }
    02465         template<class AE>
    02466         BOOST_UBLAS_INLINE
    02467         matrix_range &minus_assign (const matrix_expression<AE> &ae) {
    02468             matrix_assign<scalar_minus_assign> (*this, ae);
    02469             return *this;
    02470         }
    02471         template<class AT>
    02472         BOOST_UBLAS_INLINE
    02473         matrix_range& operator *= (const AT &at) {
    02474             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
    02475             return *this;
    02476         }
    02477         template<class AT>
    02478         BOOST_UBLAS_INLINE
    02479         matrix_range& operator /= (const AT &at) {
    02480             matrix_assign_scalar<scalar_divides_assign> (*this, at);
    02481             return *this;
    02482         }
    02483
    02484         // Closure comparison
    02485         BOOST_UBLAS_INLINE
    02486         bool same_closure (const matrix_range &mr) const {
    02487             return (*this).data_.same_closure (mr.data_);
    02488         }
    02489
    02490         // Comparison
    02491         BOOST_UBLAS_INLINE
    02492         bool operator == (const matrix_range &mr) const {
    02493             return (*this).data_ == (mr.data_) && r1_ == mr.r1_ && r2_ == mr.r2_;
    02494         }
    02495
    02496         // Swapping
    02497         BOOST_UBLAS_INLINE
    02498         void swap (matrix_range mr) {
    02499             if (this != &mr) {
    02500                 BOOST_UBLAS_CHECK (size1 () == mr.size1 (), bad_size ());
    02501                 BOOST_UBLAS_CHECK (size2 () == mr.size2 (), bad_size ());
    02502                 matrix_swap<scalar_swap> (*this, mr);
    02503             }
    02504         }
    02505         BOOST_UBLAS_INLINE
    02506         friend void swap (matrix_range mr1, matrix_range mr2) {
    02507             mr1.swap (mr2);
    02508         }
    02509
    02510         // Iterator types
    02511     private:
    02512         typedef typename M::const_iterator1 const_subiterator1_type;
    02513         typedef typename boost::mpl::if_<boost::is_const<M>,
    02514                                           typename M::const_iterator1,
    02515                                           typename M::iterator1>::type subiterator1_type;
    02516         typedef typename M::const_iterator2 const_subiterator2_type;
    02517         typedef typename boost::mpl::if_<boost::is_const<M>,
    02518                                           typename M::const_iterator2,
    02519                                           typename M::iterator2>::type subiterator2_type;
    02520
    02521     public:
    02522 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02523         typedef indexed_iterator1<matrix_range<matrix_type>,
    02524                                   typename subiterator1_type::iterator_category> iterator1;
    02525         typedef indexed_iterator2<matrix_range<matrix_type>,
    02526                                   typename subiterator2_type::iterator_category> iterator2;
    02527         typedef indexed_const_iterator1<matrix_range<matrix_type>,
    02528                                         typename const_subiterator1_type::iterator_category> const_iterator1;
    02529         typedef indexed_const_iterator2<matrix_range<matrix_type>,
    02530                                         typename const_subiterator2_type::iterator_category> const_iterator2;
    02531 #else
    02532         class const_iterator1;
    02533         class iterator1;
    02534         class const_iterator2;
    02535         class iterator2;
    02536 #endif
    02537         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    02538         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
    02539         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    02540         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
    02541
    02542         // Element lookup
    02543         BOOST_UBLAS_INLINE
    02544         const_iterator1 find1 (int rank, size_type i, size_type j) const {
    02545             const_subiterator1_type it1 (data_.find1 (rank, start1 () + i, start2 () + j));
    02546 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02547             return const_iterator1 (*this, it1.index1 (), it1.index2 ());
    02548 #else
    02549             return const_iterator1 (*this, it1);
    02550 #endif
    02551         }
    02552         BOOST_UBLAS_INLINE
    02553         iterator1 find1 (int rank, size_type i, size_type j) {
    02554             subiterator1_type it1 (data_.find1 (rank, start1 () + i, start2 () + j));
    02555 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02556             return iterator1 (*this, it1.index1 (), it1.index2 ());
    02557 #else
    02558             return iterator1 (*this, it1);
    02559 #endif
    02560         }
    02561         BOOST_UBLAS_INLINE
    02562         const_iterator2 find2 (int rank, size_type i, size_type j) const {
    02563             const_subiterator2_type it2 (data_.find2 (rank, start1 () + i, start2 () + j));
    02564 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02565             return const_iterator2 (*this, it2.index1 (), it2.index2 ());
    02566 #else
    02567             return const_iterator2 (*this, it2);
    02568 #endif
    02569         }
    02570         BOOST_UBLAS_INLINE
    02571         iterator2 find2 (int rank, size_type i, size_type j) {
    02572             subiterator2_type it2 (data_.find2 (rank, start1 () + i, start2 () + j));
    02573 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02574             return iterator2 (*this, it2.index1 (), it2.index2 ());
    02575 #else
    02576             return iterator2 (*this, it2);
    02577 #endif
    02578         }
    02579
    02580
    02581 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02582         class const_iterator1:
    02583             public container_const_reference<matrix_range>,
    02584             public iterator_base_traits<typename const_subiterator1_type::iterator_category>::template
    02585                         iterator_base<const_iterator1, value_type>::type {
    02586         public:
    02587             typedef typename const_subiterator1_type::value_type value_type;
    02588             typedef typename const_subiterator1_type::difference_type difference_type;
    02589             typedef typename const_subiterator1_type::reference reference;
    02590             typedef typename const_subiterator1_type::pointer pointer;
    02591             typedef const_iterator2 dual_iterator_type;
    02592             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    02593
    02594             // Construction and destruction
    02595             BOOST_UBLAS_INLINE
    02596             const_iterator1 ():
    02597                 container_const_reference<self_type> (), it_ () {}
    02598             BOOST_UBLAS_INLINE
    02599             const_iterator1 (const self_type &mr, const const_subiterator1_type &it):
    02600                 container_const_reference<self_type> (mr), it_ (it) {}
    02601             BOOST_UBLAS_INLINE
    02602             const_iterator1 (const iterator1 &it):
    02603                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
    02604
    02605             // Arithmetic
    02606             BOOST_UBLAS_INLINE
    02607             const_iterator1 &operator ++ () {
    02608                 ++ it_;
    02609                 return *this;
    02610             }
    02611             BOOST_UBLAS_INLINE
    02612             const_iterator1 &operator -- () {
    02613                 -- it_;
    02614                 return *this;
    02615             }
    02616             BOOST_UBLAS_INLINE
    02617             const_iterator1 &operator += (difference_type n) {
    02618                 it_ += n;
    02619                 return *this;
    02620             }
    02621             BOOST_UBLAS_INLINE
    02622             const_iterator1 &operator -= (difference_type n) {
    02623                 it_ -= n;
    02624                 return *this;
    02625             }
    02626             BOOST_UBLAS_INLINE
    02627             difference_type operator - (const const_iterator1 &it) const {
    02628                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02629                 return it_ - it.it_;
    02630             }
    02631
    02632             // Dereference
    02633             BOOST_UBLAS_INLINE
    02634             const_reference operator * () const {
    02635                 return *it_;
    02636             }
    02637             BOOST_UBLAS_INLINE
    02638             const_reference operator [] (difference_type n) const {
    02639                 return *(*this + n);
    02640             }
    02641
    02642 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02643             BOOST_UBLAS_INLINE
    02644 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02645             typename self_type::
    02646 #endif
    02647             const_iterator2 begin () const {
    02648                 const self_type &mr = (*this) ();
    02649                 return mr.find2 (1, index1 (), 0);
    02650             }
    02651             BOOST_UBLAS_INLINE
    02652 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02653             typename self_type::
    02654 #endif
    02655             const_iterator2 end () const {
    02656                 const self_type &mr = (*this) ();
    02657                 return mr.find2 (1, index1 (), mr.size2 ());
    02658             }
    02659             BOOST_UBLAS_INLINE
    02660 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02661             typename self_type::
    02662 #endif
    02663             const_reverse_iterator2 rbegin () const {
    02664                 return const_reverse_iterator2 (end ());
    02665             }
    02666             BOOST_UBLAS_INLINE
    02667 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02668             typename self_type::
    02669 #endif
    02670             const_reverse_iterator2 rend () const {
    02671                 return const_reverse_iterator2 (begin ());
    02672             }
    02673 #endif
    02674
    02675             // Indices
    02676             BOOST_UBLAS_INLINE
    02677             size_type index1 () const {
    02678                 return it_.index1 () - (*this) ().start1 ();
    02679             }
    02680             BOOST_UBLAS_INLINE
    02681             size_type index2 () const {
    02682                 return it_.index2 () - (*this) ().start2 ();
    02683             }
    02684
    02685             // Assignment
    02686             BOOST_UBLAS_INLINE
    02687             const_iterator1 &operator = (const const_iterator1 &it) {
    02688                 container_const_reference<self_type>::assign (&it ());
    02689                 it_ = it.it_;
    02690                 return *this;
    02691             }
    02692
    02693             // Comparison
    02694             BOOST_UBLAS_INLINE
    02695             bool operator == (const const_iterator1 &it) const {
    02696                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02697                 return it_ == it.it_;
    02698             }
    02699             BOOST_UBLAS_INLINE
    02700             bool operator < (const const_iterator1 &it) const {
    02701                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02702                 return it_ < it.it_;
    02703             }
    02704
    02705         private:
    02706             const_subiterator1_type it_;
    02707         };
    02708 #endif
    02709
    02710         BOOST_UBLAS_INLINE
    02711         const_iterator1 begin1 () const {
    02712             return find1 (0, 0, 0);
    02713         }
    02714         BOOST_UBLAS_INLINE
    02715         const_iterator1 end1 () const {
    02716             return find1 (0, size1 (), 0);
    02717         }
    02718
    02719 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02720         class iterator1:
    02721             public container_reference<matrix_range>,
    02722             public iterator_base_traits<typename subiterator1_type::iterator_category>::template
    02723                         iterator_base<iterator1, value_type>::type {
    02724         public:
    02725             typedef typename subiterator1_type::value_type value_type;
    02726             typedef typename subiterator1_type::difference_type difference_type;
    02727             typedef typename subiterator1_type::reference reference;
    02728             typedef typename subiterator1_type::pointer pointer;
    02729             typedef iterator2 dual_iterator_type;
    02730             typedef reverse_iterator2 dual_reverse_iterator_type;
    02731
    02732             // Construction and destruction
    02733             BOOST_UBLAS_INLINE
    02734             iterator1 ():
    02735                 container_reference<self_type> (), it_ () {}
    02736             BOOST_UBLAS_INLINE
    02737             iterator1 (self_type &mr, const subiterator1_type &it):
    02738                 container_reference<self_type> (mr), it_ (it) {}
    02739
    02740             // Arithmetic
    02741             BOOST_UBLAS_INLINE
    02742             iterator1 &operator ++ () {
    02743                 ++ it_;
    02744                 return *this;
    02745             }
    02746             BOOST_UBLAS_INLINE
    02747             iterator1 &operator -- () {
    02748                 -- it_;
    02749                 return *this;
    02750             }
    02751             BOOST_UBLAS_INLINE
    02752             iterator1 &operator += (difference_type n) {
    02753                 it_ += n;
    02754                 return *this;
    02755             }
    02756             BOOST_UBLAS_INLINE
    02757             iterator1 &operator -= (difference_type n) {
    02758                 it_ -= n;
    02759                 return *this;
    02760             }
    02761             BOOST_UBLAS_INLINE
    02762             difference_type operator - (const iterator1 &it) const {
    02763                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    02764                 return it_ - it.it_;
    02765             }
    02766
    02767             // Dereference
    02768             BOOST_UBLAS_INLINE
    02769             reference operator * () const {
    02770                 return *it_;
    02771             }
    02772             BOOST_UBLAS_INLINE
    02773             reference operator [] (difference_type n) const {
    02774                 return *(*this + n);
    02775             }
    02776
    02777 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02778             BOOST_UBLAS_INLINE
    02779 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02780             typename self_type::
    02781 #endif
    02782             iterator2 begin () const {
    02783                 self_type &mr = (*this) ();
    02784                 return mr.find2 (1, index1 (), 0);
    02785             }
    02786             BOOST_UBLAS_INLINE
    02787 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02788             typename self_type::
    02789 #endif
    02790             iterator2 end () const {
    02791                 self_type &mr = (*this) ();
    02792                 return mr.find2 (1, index1 (), mr.size2 ());
    02793             }
    02794             BOOST_UBLAS_INLINE
    02795 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02796             typename self_type::
    02797 #endif
    02798             reverse_iterator2 rbegin () const {
    02799                 return reverse_iterator2 (end ());
    02800             }
    02801             BOOST_UBLAS_INLINE
    02802 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02803             typename self_type::
    02804 #endif
    02805             reverse_iterator2 rend () const {
    02806                 return reverse_iterator2 (begin ());
    02807             }
    02808 #endif
    02809
    02810             // Indices
    02811             BOOST_UBLAS_INLINE
    02812             size_type index1 () const {
    02813                 return it_.index1 () - (*this) ().start1 ();
    02814             }
    02815             BOOST_UBLAS_INLINE
    02816             size_type index2 () const {
    02817                 return it_.index2 () - (*this) ().start2 ();
    02818             }
    02819
    02820             // Assignment
    02821             BOOST_UBLAS_INLINE
    02822             iterator1 &operator = (const iterator1 &it) {
    02823                 container_reference<self_type>::assign (&it ());
    02824                 it_ = it.it_;
    02825                 return *this;
    02826             }
    02827
    02828             // Comparison
    02829             BOOST_UBLAS_INLINE
    02830             bool operator == (const iterator1 &it) const {
    02831                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02832                 return it_ == it.it_;
    02833             }
    02834             BOOST_UBLAS_INLINE
    02835             bool operator < (const iterator1 &it) const {
    02836                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02837                 return it_ < it.it_;
    02838             }
    02839
    02840         private:
    02841             subiterator1_type it_;
    02842
    02843             friend class const_iterator1;
    02844         };
    02845 #endif
    02846
    02847         BOOST_UBLAS_INLINE
    02848         iterator1 begin1 () {
    02849             return find1 (0, 0, 0);
    02850         }
    02851         BOOST_UBLAS_INLINE
    02852         iterator1 end1 () {
    02853             return find1 (0, size1 (), 0);
    02854         }
    02855
    02856 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02857         class const_iterator2:
    02858             public container_const_reference<matrix_range>,
    02859             public iterator_base_traits<typename const_subiterator2_type::iterator_category>::template
    02860                         iterator_base<const_iterator2, value_type>::type {
    02861         public:
    02862             typedef typename const_subiterator2_type::value_type value_type;
    02863             typedef typename const_subiterator2_type::difference_type difference_type;
    02864             typedef typename const_subiterator2_type::reference reference;
    02865             typedef typename const_subiterator2_type::pointer pointer;
    02866             typedef const_iterator1 dual_iterator_type;
    02867             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    02868
    02869             // Construction and destruction
    02870             BOOST_UBLAS_INLINE
    02871             const_iterator2 ():
    02872                 container_const_reference<self_type> (), it_ () {}
    02873             BOOST_UBLAS_INLINE
    02874             const_iterator2 (const self_type &mr, const const_subiterator2_type &it):
    02875                 container_const_reference<self_type> (mr), it_ (it) {}
    02876             BOOST_UBLAS_INLINE
    02877             const_iterator2 (const iterator2 &it):
    02878                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
    02879
    02880             // Arithmetic
    02881             BOOST_UBLAS_INLINE
    02882             const_iterator2 &operator ++ () {
    02883                 ++ it_;
    02884                 return *this;
    02885             }
    02886             BOOST_UBLAS_INLINE
    02887             const_iterator2 &operator -- () {
    02888                 -- it_;
    02889                 return *this;
    02890             }
    02891             BOOST_UBLAS_INLINE
    02892             const_iterator2 &operator += (difference_type n) {
    02893                 it_ += n;
    02894                 return *this;
    02895             }
    02896             BOOST_UBLAS_INLINE
    02897             const_iterator2 &operator -= (difference_type n) {
    02898                 it_ -= n;
    02899                 return *this;
    02900             }
    02901             BOOST_UBLAS_INLINE
    02902             difference_type operator - (const const_iterator2 &it) const {
    02903                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02904                 return it_ - it.it_;
    02905             }
    02906
    02907             // Dereference
    02908             BOOST_UBLAS_INLINE
    02909             const_reference operator * () const {
    02910                 return *it_;
    02911             }
    02912             BOOST_UBLAS_INLINE
    02913             const_reference operator [] (difference_type n) const {
    02914                 return *(*this + n);
    02915             }
    02916
    02917 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02918             BOOST_UBLAS_INLINE
    02919 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02920             typename self_type::
    02921 #endif
    02922             const_iterator1 begin () const {
    02923                 const self_type &mr = (*this) ();
    02924                 return mr.find1 (1, 0, index2 ());
    02925             }
    02926             BOOST_UBLAS_INLINE
    02927 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02928             typename self_type::
    02929 #endif
    02930             const_iterator1 end () const {
    02931                 const self_type &mr = (*this) ();
    02932                 return mr.find1 (1, mr.size1 (), index2 ());
    02933             }
    02934             BOOST_UBLAS_INLINE
    02935 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02936             typename self_type::
    02937 #endif
    02938             const_reverse_iterator1 rbegin () const {
    02939                 return const_reverse_iterator1 (end ());
    02940             }
    02941             BOOST_UBLAS_INLINE
    02942 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02943             typename self_type::
    02944 #endif
    02945             const_reverse_iterator1 rend () const {
    02946                 return const_reverse_iterator1 (begin ());
    02947             }
    02948 #endif
    02949
    02950             // Indices
    02951             BOOST_UBLAS_INLINE
    02952             size_type index1 () const {
    02953                 return it_.index1 () - (*this) ().start1 ();
    02954             }
    02955             BOOST_UBLAS_INLINE
    02956             size_type index2 () const {
    02957                 return it_.index2 () - (*this) ().start2 ();
    02958             }
    02959
    02960             // Assignment
    02961             BOOST_UBLAS_INLINE
    02962             const_iterator2 &operator = (const const_iterator2 &it) {
    02963                 container_const_reference<self_type>::assign (&it ());
    02964                 it_ = it.it_;
    02965                 return *this;
    02966             }
    02967
    02968             // Comparison
    02969             BOOST_UBLAS_INLINE
    02970             bool operator == (const const_iterator2 &it) const {
    02971                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    02972                 return it_ == it.it_;
    02973             }
    02974             BOOST_UBLAS_INLINE
    02975             bool operator < (const const_iterator2 &it) const {
    02976                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    02977                 return it_ < it.it_;
    02978             }
    02979
    02980         private:
    02981             const_subiterator2_type it_;
    02982         };
    02983 #endif
    02984
    02985         BOOST_UBLAS_INLINE
    02986         const_iterator2 begin2 () const {
    02987             return find2 (0, 0, 0);
    02988         }
    02989         BOOST_UBLAS_INLINE
    02990         const_iterator2 end2 () const {
    02991             return find2 (0, 0, size2 ());
    02992         }
    02993
    02994 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02995         class iterator2:
    02996             public container_reference<matrix_range>,
    02997             public iterator_base_traits<typename subiterator2_type::iterator_category>::template
    02998                         iterator_base<iterator2, value_type>::type {
    02999         public:
    03000             typedef typename subiterator2_type::value_type value_type;
    03001             typedef typename subiterator2_type::difference_type difference_type;
    03002             typedef typename subiterator2_type::reference reference;
    03003             typedef typename subiterator2_type::pointer pointer;
    03004             typedef iterator1 dual_iterator_type;
    03005             typedef reverse_iterator1 dual_reverse_iterator_type;
    03006
    03007             // Construction and destruction
    03008             BOOST_UBLAS_INLINE
    03009             iterator2 ():
    03010                 container_reference<self_type> (), it_ () {}
    03011             BOOST_UBLAS_INLINE
    03012             iterator2 (self_type &mr, const subiterator2_type &it):
    03013                 container_reference<self_type> (mr), it_ (it) {}
    03014
    03015             // Arithmetic
    03016             BOOST_UBLAS_INLINE
    03017             iterator2 &operator ++ () {
    03018                 ++ it_;
    03019                 return *this;
    03020             }
    03021             BOOST_UBLAS_INLINE
    03022             iterator2 &operator -- () {
    03023                 -- it_;
    03024                 return *this;
    03025             }
    03026             BOOST_UBLAS_INLINE
    03027             iterator2 &operator += (difference_type n) {
    03028                 it_ += n;
    03029                 return *this;
    03030             }
    03031             BOOST_UBLAS_INLINE
    03032             iterator2 &operator -= (difference_type n) {
    03033                 it_ -= n;
    03034                 return *this;
    03035             }
    03036             BOOST_UBLAS_INLINE
    03037             difference_type operator - (const iterator2 &it) const {
    03038                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03039                 return it_ - it.it_;
    03040             }
    03041
    03042             // Dereference
    03043             BOOST_UBLAS_INLINE
    03044             reference operator * () const {
    03045                 return *it_;
    03046             }
    03047             BOOST_UBLAS_INLINE
    03048             reference operator [] (difference_type n) const {
    03049                 return *(*this + n);
    03050             }
    03051
    03052 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03053             BOOST_UBLAS_INLINE
    03054 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03055             typename self_type::
    03056 #endif
    03057             iterator1 begin () const {
    03058                 self_type &mr = (*this) ();
    03059                 return mr.find1 (1, 0, index2 ());
    03060             }
    03061             BOOST_UBLAS_INLINE
    03062 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03063             typename self_type::
    03064 #endif
    03065             iterator1 end () const {
    03066                 self_type &mr = (*this) ();
    03067                 return mr.find1 (1, mr.size1 (), index2 ());
    03068             }
    03069             BOOST_UBLAS_INLINE
    03070 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03071             typename self_type::
    03072 #endif
    03073             reverse_iterator1 rbegin () const {
    03074                 return reverse_iterator1 (end ());
    03075             }
    03076             BOOST_UBLAS_INLINE
    03077 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03078             typename self_type::
    03079 #endif
    03080             reverse_iterator1 rend () const {
    03081                 return reverse_iterator1 (begin ());
    03082             }
    03083 #endif
    03084
    03085             // Indices
    03086             BOOST_UBLAS_INLINE
    03087             size_type index1 () const {
    03088                 return it_.index1 () - (*this) ().start1 ();
    03089             }
    03090             BOOST_UBLAS_INLINE
    03091             size_type index2 () const {
    03092                 return it_.index2 () - (*this) ().start2 ();
    03093             }
    03094
    03095             // Assignment
    03096             BOOST_UBLAS_INLINE
    03097             iterator2 &operator = (const iterator2 &it) {
    03098                 container_reference<self_type>::assign (&it ());
    03099                 it_ = it.it_;
    03100                 return *this;
    03101             }
    03102
    03103             // Comparison
    03104             BOOST_UBLAS_INLINE
    03105             bool operator == (const iterator2 &it) const {
    03106                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03107                 return it_ == it.it_;
    03108             }
    03109             BOOST_UBLAS_INLINE
    03110             bool operator < (const iterator2 &it) const {
    03111                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03112                 return it_ < it.it_;
    03113             }
    03114
    03115         private:
    03116             subiterator2_type it_;
    03117
    03118             friend class const_iterator2;
    03119         };
    03120 #endif
    03121
    03122         BOOST_UBLAS_INLINE
    03123         iterator2 begin2 () {
    03124             return find2 (0, 0, 0);
    03125         }
    03126         BOOST_UBLAS_INLINE
    03127         iterator2 end2 () {
    03128             return find2 (0, 0, size2 ());
    03129         }
    03130
    03131         // Reverse iterators
    03132
    03133         BOOST_UBLAS_INLINE
    03134         const_reverse_iterator1 rbegin1 () const {
    03135             return const_reverse_iterator1 (end1 ());
    03136         }
    03137         BOOST_UBLAS_INLINE
    03138         const_reverse_iterator1 rend1 () const {
    03139             return const_reverse_iterator1 (begin1 ());
    03140         }
    03141
    03142         BOOST_UBLAS_INLINE
    03143         reverse_iterator1 rbegin1 () {
    03144             return reverse_iterator1 (end1 ());
    03145         }
    03146         BOOST_UBLAS_INLINE
    03147         reverse_iterator1 rend1 () {
    03148             return reverse_iterator1 (begin1 ());
    03149         }
    03150
    03151         BOOST_UBLAS_INLINE
    03152         const_reverse_iterator2 rbegin2 () const {
    03153             return const_reverse_iterator2 (end2 ());
    03154         }
    03155         BOOST_UBLAS_INLINE
    03156         const_reverse_iterator2 rend2 () const {
    03157             return const_reverse_iterator2 (begin2 ());
    03158         }
    03159
    03160         BOOST_UBLAS_INLINE
    03161         reverse_iterator2 rbegin2 () {
    03162             return reverse_iterator2 (end2 ());
    03163         }
    03164         BOOST_UBLAS_INLINE
    03165         reverse_iterator2 rend2 () {
    03166             return reverse_iterator2 (begin2 ());
    03167         }
    03168
    03169     private:
    03170         matrix_closure_type data_;
    03171         range_type r1_;
    03172         range_type r2_;
    03173     };
    03174
    03175     // Simple Projections
    03176     template<class M>
    03177     BOOST_UBLAS_INLINE
    03178     matrix_range<M> subrange (M &data, typename M::size_type start1, typename M::size_type stop1, typename M::size_type start2, typename M::size_type stop2) {
    03179         typedef basic_range<typename M::size_type, typename M::difference_type> range_type;
    03180         return matrix_range<M> (data, range_type (start1, stop1), range_type (start2, stop2));
    03181     }
    03182     template<class M>
    03183     BOOST_UBLAS_INLINE
    03184     matrix_range<const M> subrange (const M &data, typename M::size_type start1, typename M::size_type stop1, typename M::size_type start2, typename M::size_type stop2) {
    03185         typedef basic_range<typename M::size_type, typename M::difference_type> range_type;
    03186         return matrix_range<const M> (data, range_type (start1, stop1), range_type (start2, stop2));
    03187     }
    03188
    03189     // Generic Projections
    03190     template<class M>
    03191     BOOST_UBLAS_INLINE
    03192     matrix_range<M> project (M &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
    03193         return matrix_range<M> (data, r1, r2);
    03194     }
    03195     template<class M>
    03196     BOOST_UBLAS_INLINE
    03197     const matrix_range<const M> project (const M &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
    03198         // ISSUE was: return matrix_range<M> (const_cast<M &> (data), r1, r2);
    03199         return matrix_range<const M> (data, r1, r2);
    03200     }
    03201     template<class M>
    03202     BOOST_UBLAS_INLINE
    03203     matrix_range<M> project (matrix_range<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
    03204         return data.project (r1, r2);
    03205     }
    03206     template<class M>
    03207     BOOST_UBLAS_INLINE
    03208     const matrix_range<M> project (const matrix_range<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
    03209         return data.project (r1, r2);
    03210     }
    03211
    03212     // Specialization of temporary_traits
    03213     template <class M>
    03214     struct matrix_temporary_traits< matrix_range<M> >
    03215     : matrix_temporary_traits< M > {} ;
    03216     template <class M>
    03217     struct matrix_temporary_traits< const matrix_range<M> >
    03218     : matrix_temporary_traits< M > {} ;
    03219
    03220     template <class M>
    03221     struct vector_temporary_traits< matrix_range<M> >
    03222     : vector_temporary_traits< M > {} ;
    03223     template <class M>
    03224     struct vector_temporary_traits< const matrix_range<M> >
    03225     : vector_temporary_traits< M > {} ;
    03226
    03227     // Matrix based slice class
    03228     template<class M>
    03229     class matrix_slice:
    03230         public matrix_expression<matrix_slice<M> > {
    03231
    03232         typedef matrix_slice<M> self_type;
    03233     public:
    03234 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    03235         using matrix_expression<self_type>::operator ();
    03236 #endif
    03237         typedef M matrix_type;
    03238         typedef typename M::size_type size_type;
    03239         typedef typename M::difference_type difference_type;
    03240         typedef typename M::value_type value_type;
    03241         typedef typename M::const_reference const_reference;
    03242         typedef typename boost::mpl::if_<boost::is_const<M>,
    03243                                           typename M::const_reference,
    03244                                           typename M::reference>::type reference;
    03245         typedef typename boost::mpl::if_<boost::is_const<M>,
    03246                                           typename M::const_closure_type,
    03247                                           typename M::closure_type>::type matrix_closure_type;
    03248         typedef basic_range<size_type, difference_type> range_type;
    03249         typedef basic_slice<size_type, difference_type> slice_type;
    03250         typedef const self_type const_closure_type;
    03251         typedef self_type closure_type;
    03252         typedef typename storage_restrict_traits<typename M::storage_category,
    03253                                                  dense_proxy_tag>::storage_category storage_category;
    03254         typedef typename M::orientation_category orientation_category;
    03255
    03256         // Construction and destruction
    03257         BOOST_UBLAS_INLINE
    03258         matrix_slice (matrix_type &data, const slice_type &s1, const slice_type &s2):
    03259             data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {
    03260             // Early checking of preconditions here.
    03261             // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
    03262             //                    s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
    03263             // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
    03264             //                    s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
    03265         }
    03266         BOOST_UBLAS_INLINE
    03267         matrix_slice (const matrix_closure_type &data, const slice_type &s1, const slice_type &s2, int):
    03268             data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {
    03269             // Early checking of preconditions.
    03270             // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
    03271             //                    s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
    03272             // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
    03273             //                    s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
    03274         }
    03275
    03276         // Accessors
    03277         BOOST_UBLAS_INLINE
    03278         size_type start1 () const {
    03279             return s1_.start ();
    03280         }
    03281         BOOST_UBLAS_INLINE
    03282         size_type start2 () const {
    03283             return s2_.start ();
    03284         }
    03285         BOOST_UBLAS_INLINE
    03286         difference_type stride1 () const {
    03287             return s1_.stride ();
    03288         }
    03289         BOOST_UBLAS_INLINE
    03290         difference_type stride2 () const {
    03291             return s2_.stride ();
    03292         }
    03293         BOOST_UBLAS_INLINE
    03294         size_type size1 () const {
    03295             return s1_.size ();
    03296         }
    03297         BOOST_UBLAS_INLINE
    03298         size_type size2 () const {
    03299             return s2_.size ();
    03300         }
    03301
    03302         // Storage accessors
    03303         BOOST_UBLAS_INLINE
    03304         const matrix_closure_type &data () const {
    03305             return data_;
    03306         }
    03307         BOOST_UBLAS_INLINE
    03308         matrix_closure_type &data () {
    03309             return data_;
    03310         }
    03311
    03312         // Element access
    03313 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
    03314         BOOST_UBLAS_INLINE
    03315         const_reference operator () (size_type i, size_type j) const {
    03316             return data_ (s1_ (i), s2_ (j));
    03317         }
    03318         BOOST_UBLAS_INLINE
    03319         reference operator () (size_type i, size_type j) {
    03320             return data_ (s1_ (i), s2_ (j));
    03321         }
    03322 #else
    03323         BOOST_UBLAS_INLINE
    03324         reference operator () (size_type i, size_type j) const {
    03325             return data_ (s1_ (i), s2_ (j));
    03326         }
    03327 #endif
    03328
    03329         // ISSUE can this be done in free project function?
    03330         // Although a const function can create a non-const proxy to a non-const object
    03331         // Critical is that matrix_type and data_ (vector_closure_type) are const correct
    03332         BOOST_UBLAS_INLINE
    03333         matrix_slice<matrix_type> project (const range_type &r1, const range_type &r2) const {
    03334             return matrix_slice<matrix_type>  (data_, s1_.compose (r1.preprocess (data_.size1 ())), s2_.compose (r2.preprocess (data_.size2 ())), 0);
    03335         }
    03336         BOOST_UBLAS_INLINE
    03337         matrix_slice<matrix_type> project (const slice_type &s1, const slice_type &s2) const {
    03338             return matrix_slice<matrix_type>  (data_, s1_.compose (s1.preprocess (data_.size1 ())), s2_.compose (s2.preprocess (data_.size2 ())), 0);
    03339         }
    03340
    03341         // Assignment
    03342         BOOST_UBLAS_INLINE
    03343         matrix_slice &operator = (const matrix_slice &ms) {
    03344             matrix_assign<scalar_assign> (*this, ms);
    03345             return *this;
    03346         }
    03347         BOOST_UBLAS_INLINE
    03348         matrix_slice &assign_temporary (matrix_slice &ms) {
    03349             return *this = ms;
    03350         }
    03351         template<class AE>
    03352         BOOST_UBLAS_INLINE
    03353         matrix_slice &operator = (const matrix_expression<AE> &ae) {
    03354             matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae));
    03355             return *this;
    03356         }
    03357         template<class AE>
    03358         BOOST_UBLAS_INLINE
    03359         matrix_slice &assign (const matrix_expression<AE> &ae) {
    03360             matrix_assign<scalar_assign> (*this, ae);
    03361             return *this;
    03362         }
    03363         template<class AE>
    03364         BOOST_UBLAS_INLINE
    03365         matrix_slice& operator += (const matrix_expression<AE> &ae) {
    03366             matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae));
    03367             return *this;
    03368         }
    03369         template<class AE>
    03370         BOOST_UBLAS_INLINE
    03371         matrix_slice &plus_assign (const matrix_expression<AE> &ae) {
    03372             matrix_assign<scalar_plus_assign> (*this, ae);
    03373             return *this;
    03374         }
    03375         template<class AE>
    03376         BOOST_UBLAS_INLINE
    03377         matrix_slice& operator -= (const matrix_expression<AE> &ae) {
    03378             matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae));
    03379             return *this;
    03380         }
    03381         template<class AE>
    03382         BOOST_UBLAS_INLINE
    03383         matrix_slice &minus_assign (const matrix_expression<AE> &ae) {
    03384             matrix_assign<scalar_minus_assign> (*this, ae);
    03385             return *this;
    03386         }
    03387         template<class AT>
    03388         BOOST_UBLAS_INLINE
    03389         matrix_slice& operator *= (const AT &at) {
    03390             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
    03391             return *this;
    03392         }
    03393         template<class AT>
    03394         BOOST_UBLAS_INLINE
    03395         matrix_slice& operator /= (const AT &at) {
    03396             matrix_assign_scalar<scalar_divides_assign> (*this, at);
    03397             return *this;
    03398         }
    03399
    03400         // Closure comparison
    03401         BOOST_UBLAS_INLINE
    03402         bool same_closure (const matrix_slice &ms) const {
    03403             return (*this).data_.same_closure (ms.data_);
    03404         }
    03405
    03406         // Comparison
    03407         BOOST_UBLAS_INLINE
    03408         bool operator == (const matrix_slice &ms) const {
    03409             return (*this).data_ == ms.data_ && s1_ == ms.s1_ && s2_ == ms.s2_;
    03410         }
    03411
    03412         // Swapping
    03413         BOOST_UBLAS_INLINE
    03414         void swap (matrix_slice ms) {
    03415             if (this != &ms) {
    03416                 BOOST_UBLAS_CHECK (size1 () == ms.size1 (), bad_size ());
    03417                 BOOST_UBLAS_CHECK (size2 () == ms.size2 (), bad_size ());
    03418                 matrix_swap<scalar_swap> (*this, ms);
    03419             }
    03420         }
    03421         BOOST_UBLAS_INLINE
    03422         friend void swap (matrix_slice ms1, matrix_slice ms2) {
    03423             ms1.swap (ms2);
    03424         }
    03425
    03426         // Iterator types
    03427     private:
    03428         // Use slice as an index - FIXME this fails for packed assignment
    03429         typedef typename slice_type::const_iterator const_subiterator1_type;
    03430         typedef typename slice_type::const_iterator subiterator1_type;
    03431         typedef typename slice_type::const_iterator const_subiterator2_type;
    03432         typedef typename slice_type::const_iterator subiterator2_type;
    03433
    03434     public:
    03435 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03436         typedef indexed_iterator1<matrix_slice<matrix_type>,
    03437                                   typename matrix_type::iterator1::iterator_category> iterator1;
    03438         typedef indexed_iterator2<matrix_slice<matrix_type>,
    03439                                   typename matrix_type::iterator2::iterator_category> iterator2;
    03440         typedef indexed_const_iterator1<matrix_slice<matrix_type>,
    03441                                         typename matrix_type::const_iterator1::iterator_category> const_iterator1;
    03442         typedef indexed_const_iterator2<matrix_slice<matrix_type>,
    03443                                         typename matrix_type::const_iterator2::iterator_category> const_iterator2;
    03444 #else
    03445         class const_iterator1;
    03446         class iterator1;
    03447         class const_iterator2;
    03448         class iterator2;
    03449 #endif
    03450         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    03451         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
    03452         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    03453         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
    03454
    03455         // Element lookup
    03456         BOOST_UBLAS_INLINE
    03457         const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
    03458 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03459             return const_iterator1 (*this, i, j);
    03460 #else
    03461             return const_iterator1 (*this, s1_.begin () + i, s2_.begin () + j);
    03462 #endif
    03463         }
    03464         BOOST_UBLAS_INLINE
    03465         iterator1 find1 (int /* rank */, size_type i, size_type j) {
    03466 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03467             return iterator1 (*this, i, j);
    03468 #else
    03469             return iterator1 (*this, s1_.begin () + i, s2_.begin () + j);
    03470 #endif
    03471         }
    03472         BOOST_UBLAS_INLINE
    03473         const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
    03474 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03475             return const_iterator2 (*this, i, j);
    03476 #else
    03477             return const_iterator2 (*this, s1_.begin () + i, s2_.begin () + j);
    03478 #endif
    03479         }
    03480         BOOST_UBLAS_INLINE
    03481         iterator2 find2 (int /* rank */, size_type i, size_type j) {
    03482 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03483             return iterator2 (*this, i, j);
    03484 #else
    03485             return iterator2 (*this, s1_.begin () + i, s2_.begin () + j);
    03486 #endif
    03487         }
    03488
    03489         // Iterators simply are indices.
    03490
    03491 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03492         class const_iterator1:
    03493             public container_const_reference<matrix_slice>,
    03494             public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
    03495                         iterator_base<const_iterator1, value_type>::type {
    03496         public:
    03497             typedef typename M::const_iterator1::value_type value_type;
    03498             typedef typename M::const_iterator1::difference_type difference_type;
    03499             typedef typename M::const_reference reference;    //FIXME due to indexing access
    03500             typedef typename M::const_iterator1::pointer pointer;
    03501             typedef const_iterator2 dual_iterator_type;
    03502             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    03503
    03504             // Construction and destruction
    03505             BOOST_UBLAS_INLINE
    03506             const_iterator1 ():
    03507                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    03508             BOOST_UBLAS_INLINE
    03509             const_iterator1 (const self_type &ms, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
    03510                 container_const_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
    03511             BOOST_UBLAS_INLINE
    03512             const_iterator1 (const iterator1 &it):
    03513                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
    03514
    03515             // Arithmetic
    03516             BOOST_UBLAS_INLINE
    03517             const_iterator1 &operator ++ () {
    03518                 ++ it1_;
    03519                 return *this;
    03520             }
    03521             BOOST_UBLAS_INLINE
    03522             const_iterator1 &operator -- () {
    03523                 -- it1_;
    03524                 return *this;
    03525             }
    03526             BOOST_UBLAS_INLINE
    03527             const_iterator1 &operator += (difference_type n) {
    03528                 it1_ += n;
    03529                 return *this;
    03530             }
    03531             BOOST_UBLAS_INLINE
    03532             const_iterator1 &operator -= (difference_type n) {
    03533                 it1_ -= n;
    03534                 return *this;
    03535             }
    03536             BOOST_UBLAS_INLINE
    03537             difference_type operator - (const const_iterator1 &it) const {
    03538                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03539                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03540                 return it1_ - it.it1_;
    03541             }
    03542
    03543             // Dereference
    03544             BOOST_UBLAS_INLINE
    03545             const_reference operator * () const {
    03546                 // FIXME replace find with at_element
    03547                 return (*this) ().data_ (*it1_, *it2_);
    03548             }
    03549             BOOST_UBLAS_INLINE
    03550             const_reference operator [] (difference_type n) const {
    03551                 return *(*this + n);
    03552             }
    03553
    03554 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03555             BOOST_UBLAS_INLINE
    03556 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03557             typename self_type::
    03558 #endif
    03559             const_iterator2 begin () const {
    03560                 return const_iterator2 ((*this) (), it1_, it2_ ().begin ());
    03561             }
    03562             BOOST_UBLAS_INLINE
    03563 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03564             typename self_type::
    03565 #endif
    03566             const_iterator2 end () const {
    03567                 return const_iterator2 ((*this) (), it1_, it2_ ().end ());
    03568             }
    03569             BOOST_UBLAS_INLINE
    03570 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03571             typename self_type::
    03572 #endif
    03573             const_reverse_iterator2 rbegin () const {
    03574                 return const_reverse_iterator2 (end ());
    03575             }
    03576             BOOST_UBLAS_INLINE
    03577 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03578             typename self_type::
    03579 #endif
    03580             const_reverse_iterator2 rend () const {
    03581                 return const_reverse_iterator2 (begin ());
    03582             }
    03583 #endif
    03584
    03585             // Indices
    03586             BOOST_UBLAS_INLINE
    03587             size_type index1 () const {
    03588                 return it1_.index ();
    03589             }
    03590             BOOST_UBLAS_INLINE
    03591             size_type index2 () const {
    03592                 return it2_.index ();
    03593             }
    03594
    03595             // Assignment
    03596             BOOST_UBLAS_INLINE
    03597             const_iterator1 &operator = (const const_iterator1 &it) {
    03598                 container_const_reference<self_type>::assign (&it ());
    03599                 it1_ = it.it1_;
    03600                 it2_ = it.it2_;
    03601                 return *this;
    03602             }
    03603
    03604             // Comparison
    03605             BOOST_UBLAS_INLINE
    03606             bool operator == (const const_iterator1 &it) const {
    03607                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03608                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03609                 return it1_ == it.it1_;
    03610             }
    03611             BOOST_UBLAS_INLINE
    03612             bool operator < (const const_iterator1 &it) const {
    03613                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03614                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03615                 return it1_ < it.it1_;
    03616             }
    03617
    03618         private:
    03619             const_subiterator1_type it1_;
    03620             const_subiterator2_type it2_;
    03621         };
    03622 #endif
    03623
    03624         BOOST_UBLAS_INLINE
    03625         const_iterator1 begin1 () const {
    03626             return find1 (0, 0, 0);
    03627         }
    03628         BOOST_UBLAS_INLINE
    03629         const_iterator1 end1 () const {
    03630             return find1 (0, size1 (), 0);
    03631         }
    03632
    03633 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03634         class iterator1:
    03635             public container_reference<matrix_slice>,
    03636             public iterator_base_traits<typename M::iterator1::iterator_category>::template
    03637                         iterator_base<iterator1, value_type>::type {
    03638         public:
    03639             typedef typename M::iterator1::value_type value_type;
    03640             typedef typename M::iterator1::difference_type difference_type;
    03641             typedef typename M::reference reference;    //FIXME due to indexing access
    03642             typedef typename M::iterator1::pointer pointer;
    03643             typedef iterator2 dual_iterator_type;
    03644             typedef reverse_iterator2 dual_reverse_iterator_type;
    03645
    03646             // Construction and destruction
    03647             BOOST_UBLAS_INLINE
    03648             iterator1 ():
    03649                 container_reference<self_type> (), it1_ (), it2_ () {}
    03650             BOOST_UBLAS_INLINE
    03651             iterator1 (self_type &ms, const subiterator1_type &it1, const subiterator2_type &it2):
    03652                 container_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
    03653
    03654             // Arithmetic
    03655             BOOST_UBLAS_INLINE
    03656             iterator1 &operator ++ () {
    03657                 ++ it1_;
    03658                 return *this;
    03659             }
    03660             BOOST_UBLAS_INLINE
    03661             iterator1 &operator -- () {
    03662                 -- it1_;
    03663                 return *this;
    03664             }
    03665             BOOST_UBLAS_INLINE
    03666             iterator1 &operator += (difference_type n) {
    03667                 it1_ += n;
    03668                 return *this;
    03669             }
    03670             BOOST_UBLAS_INLINE
    03671             iterator1 &operator -= (difference_type n) {
    03672                 it1_ -= n;
    03673                 return *this;
    03674             }
    03675             BOOST_UBLAS_INLINE
    03676             difference_type operator - (const iterator1 &it) const {
    03677                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03678                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03679                 return it1_ - it.it1_;
    03680             }
    03681
    03682             // Dereference
    03683             BOOST_UBLAS_INLINE
    03684             reference operator * () const {
    03685                 // FIXME replace find with at_element
    03686                 return (*this) ().data_ (*it1_, *it2_);
    03687             }
    03688             BOOST_UBLAS_INLINE
    03689             reference operator [] (difference_type n) const {
    03690                 return *(*this + n);
    03691             }
    03692
    03693 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03694             BOOST_UBLAS_INLINE
    03695 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03696             typename self_type::
    03697 #endif
    03698             iterator2 begin () const {
    03699                 return iterator2 ((*this) (), it1_, it2_ ().begin ());
    03700             }
    03701             BOOST_UBLAS_INLINE
    03702 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03703             typename self_type::
    03704 #endif
    03705             iterator2 end () const {
    03706                 return iterator2 ((*this) (), it1_, it2_ ().end ());
    03707             }
    03708             BOOST_UBLAS_INLINE
    03709 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03710             typename self_type::
    03711 #endif
    03712             reverse_iterator2 rbegin () const {
    03713                 return reverse_iterator2 (end ());
    03714             }
    03715             BOOST_UBLAS_INLINE
    03716 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03717             typename self_type::
    03718 #endif
    03719             reverse_iterator2 rend () const {
    03720                 return reverse_iterator2 (begin ());
    03721             }
    03722 #endif
    03723
    03724             // Indices
    03725             BOOST_UBLAS_INLINE
    03726             size_type index1 () const {
    03727                 return it1_.index ();
    03728             }
    03729             BOOST_UBLAS_INLINE
    03730             size_type index2 () const {
    03731                 return it2_.index ();
    03732             }
    03733
    03734             // Assignment
    03735             BOOST_UBLAS_INLINE
    03736             iterator1 &operator = (const iterator1 &it) {
    03737                 container_reference<self_type>::assign (&it ());
    03738                 it1_ = it.it1_;
    03739                 it2_ = it.it2_;
    03740                 return *this;
    03741             }
    03742
    03743             // Comparison
    03744             BOOST_UBLAS_INLINE
    03745             bool operator == (const iterator1 &it) const {
    03746                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03747                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03748                 return it1_ == it.it1_;
    03749             }
    03750             BOOST_UBLAS_INLINE
    03751             bool operator < (const iterator1 &it) const {
    03752                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03753                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03754                 return it1_ < it.it1_;
    03755             }
    03756
    03757         private:
    03758             subiterator1_type it1_;
    03759             subiterator2_type it2_;
    03760
    03761             friend class const_iterator1;
    03762         };
    03763 #endif
    03764
    03765         BOOST_UBLAS_INLINE
    03766         iterator1 begin1 () {
    03767             return find1 (0, 0, 0);
    03768         }
    03769         BOOST_UBLAS_INLINE
    03770         iterator1 end1 () {
    03771             return find1 (0, size1 (), 0);
    03772         }
    03773
    03774 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03775         class const_iterator2:
    03776             public container_const_reference<matrix_slice>,
    03777             public iterator_base_traits<typename M::const_iterator2::iterator_category>::template
    03778                         iterator_base<const_iterator2, value_type>::type {
    03779         public:
    03780             typedef typename M::const_iterator2::value_type value_type;
    03781             typedef typename M::const_iterator2::difference_type difference_type;
    03782             typedef typename M::const_reference reference;    //FIXME due to indexing access
    03783             typedef typename M::const_iterator2::pointer pointer;
    03784             typedef const_iterator1 dual_iterator_type;
    03785             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    03786
    03787             // Construction and destruction
    03788             BOOST_UBLAS_INLINE
    03789             const_iterator2 ():
    03790                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    03791             BOOST_UBLAS_INLINE
    03792             const_iterator2 (const self_type &ms, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
    03793                 container_const_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
    03794             BOOST_UBLAS_INLINE
    03795             const_iterator2 (const iterator2 &it):
    03796                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
    03797
    03798             // Arithmetic
    03799             BOOST_UBLAS_INLINE
    03800             const_iterator2 &operator ++ () {
    03801                 ++ it2_;
    03802                 return *this;
    03803             }
    03804             BOOST_UBLAS_INLINE
    03805             const_iterator2 &operator -- () {
    03806                 -- it2_;
    03807                 return *this;
    03808             }
    03809             BOOST_UBLAS_INLINE
    03810             const_iterator2 &operator += (difference_type n) {
    03811                 it2_ += n;
    03812                 return *this;
    03813             }
    03814             BOOST_UBLAS_INLINE
    03815             const_iterator2 &operator -= (difference_type n) {
    03816                 it2_ -= n;
    03817                 return *this;
    03818             }
    03819             BOOST_UBLAS_INLINE
    03820             difference_type operator - (const const_iterator2 &it) const {
    03821                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03822                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    03823                 return it2_ - it.it2_;
    03824             }
    03825
    03826             // Dereference
    03827             BOOST_UBLAS_INLINE
    03828             const_reference operator * () const {
    03829                 // FIXME replace find with at_element
    03830                 return (*this) ().data_ (*it1_, *it2_);
    03831             }
    03832             BOOST_UBLAS_INLINE
    03833             const_reference operator [] (difference_type n) const {
    03834                 return *(*this + n);
    03835             }
    03836
    03837 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03838             BOOST_UBLAS_INLINE
    03839 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03840             typename self_type::
    03841 #endif
    03842             const_iterator1 begin () const {
    03843                 return const_iterator1 ((*this) (), it1_ ().begin (), it2_);
    03844             }
    03845             BOOST_UBLAS_INLINE
    03846 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03847             typename self_type::
    03848 #endif
    03849             const_iterator1 end () const {
    03850                 return const_iterator1 ((*this) (), it1_ ().end (), it2_);
    03851             }
    03852             BOOST_UBLAS_INLINE
    03853 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03854             typename self_type::
    03855 #endif
    03856             const_reverse_iterator1 rbegin () const {
    03857                 return const_reverse_iterator1 (end ());
    03858             }
    03859             BOOST_UBLAS_INLINE
    03860 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03861             typename self_type::
    03862 #endif
    03863             const_reverse_iterator1 rend () const {
    03864                 return const_reverse_iterator1 (begin ());
    03865             }
    03866 #endif
    03867
    03868             // Indices
    03869             BOOST_UBLAS_INLINE
    03870             size_type index1 () const {
    03871                 return it1_.index ();
    03872             }
    03873             BOOST_UBLAS_INLINE
    03874             size_type index2 () const {
    03875                 return it2_.index ();
    03876             }
    03877
    03878             // Assignment
    03879             BOOST_UBLAS_INLINE
    03880             const_iterator2 &operator = (const const_iterator2 &it) {
    03881                 container_const_reference<self_type>::assign (&it ());
    03882                 it1_ = it.it1_;
    03883                 it2_ = it.it2_;
    03884                 return *this;
    03885             }
    03886
    03887             // Comparison
    03888             BOOST_UBLAS_INLINE
    03889             bool operator == (const const_iterator2 &it) const {
    03890                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03891                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    03892                 return it2_ == it.it2_;
    03893             }
    03894             BOOST_UBLAS_INLINE
    03895             bool operator < (const const_iterator2 &it) const {
    03896                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03897                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    03898                 return it2_ < it.it2_;
    03899             }
    03900
    03901         private:
    03902             const_subiterator1_type it1_;
    03903             const_subiterator2_type it2_;
    03904         };
    03905 #endif
    03906
    03907         BOOST_UBLAS_INLINE
    03908         const_iterator2 begin2 () const {
    03909             return find2 (0, 0, 0);
    03910         }
    03911         BOOST_UBLAS_INLINE
    03912         const_iterator2 end2 () const {
    03913             return find2 (0, 0, size2 ());
    03914         }
    03915
    03916 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03917         class iterator2:
    03918             public container_reference<matrix_slice>,
    03919             public iterator_base_traits<typename M::iterator2::iterator_category>::template
    03920                         iterator_base<iterator2, value_type>::type {
    03921         public:
    03922             typedef typename M::iterator2::value_type value_type;
    03923             typedef typename M::iterator2::difference_type difference_type;
    03924             typedef typename M::reference reference;    //FIXME due to indexing access
    03925             typedef typename M::iterator2::pointer pointer;
    03926             typedef iterator1 dual_iterator_type;
    03927             typedef reverse_iterator1 dual_reverse_iterator_type;
    03928
    03929             // Construction and destruction
    03930             BOOST_UBLAS_INLINE
    03931             iterator2 ():
    03932                 container_reference<self_type> (), it1_ (), it2_ () {}
    03933             BOOST_UBLAS_INLINE
    03934             iterator2 (self_type &ms, const subiterator1_type &it1, const subiterator2_type &it2):
    03935                 container_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
    03936
    03937             // Arithmetic
    03938             BOOST_UBLAS_INLINE
    03939             iterator2 &operator ++ () {
    03940                 ++ it2_;
    03941                 return *this;
    03942             }
    03943             BOOST_UBLAS_INLINE
    03944             iterator2 &operator -- () {
    03945                 -- it2_;
    03946                 return *this;
    03947             }
    03948             BOOST_UBLAS_INLINE
    03949             iterator2 &operator += (difference_type n) {
    03950                 it2_ += n;
    03951                 return *this;
    03952             }
    03953             BOOST_UBLAS_INLINE
    03954             iterator2 &operator -= (difference_type n) {
    03955                 it2_ -= n;
    03956                 return *this;
    03957             }
    03958             BOOST_UBLAS_INLINE
    03959             difference_type operator - (const iterator2 &it) const {
    03960                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    03961                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    03962                 return it2_ - it.it2_;
    03963             }
    03964
    03965             // Dereference
    03966             BOOST_UBLAS_INLINE
    03967             reference operator * () const {
    03968                 // FIXME replace find with at_element
    03969                 return (*this) ().data_ (*it1_, *it2_);
    03970             }
    03971             BOOST_UBLAS_INLINE
    03972             reference operator [] (difference_type n) const {
    03973                 return *(*this + n);
    03974             }
    03975
    03976 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03977             BOOST_UBLAS_INLINE
    03978 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03979             typename self_type::
    03980 #endif
    03981             iterator1 begin () const {
    03982                 return iterator1 ((*this) (), it1_ ().begin (), it2_);
    03983             }
    03984             BOOST_UBLAS_INLINE
    03985 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03986             typename self_type::
    03987 #endif
    03988             iterator1 end () const {
    03989                 return iterator1 ((*this) (), it1_ ().end (), it2_);
    03990             }
    03991             BOOST_UBLAS_INLINE
    03992 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03993             typename self_type::
    03994 #endif
    03995             reverse_iterator1 rbegin () const {
    03996                 return reverse_iterator1 (end ());
    03997             }
    03998             BOOST_UBLAS_INLINE
    03999 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04000             typename self_type::
    04001 #endif
    04002             reverse_iterator1 rend () const {
    04003                 return reverse_iterator1 (begin ());
    04004             }
    04005 #endif
    04006
    04007             // Indices
    04008             BOOST_UBLAS_INLINE
    04009             size_type index1 () const {
    04010                 return it1_.index ();
    04011             }
    04012             BOOST_UBLAS_INLINE
    04013             size_type index2 () const {
    04014                 return it2_.index ();
    04015             }
    04016
    04017             // Assignment
    04018             BOOST_UBLAS_INLINE
    04019             iterator2 &operator = (const iterator2 &it) {
    04020                 container_reference<self_type>::assign (&it ());
    04021                 it1_ = it.it1_;
    04022                 it2_ = it.it2_;
    04023                 return *this;
    04024             }
    04025
    04026             // Comparison
    04027             BOOST_UBLAS_INLINE
    04028             bool operator == (const iterator2 &it) const {
    04029                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04030                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    04031                 return it2_ == it.it2_;
    04032             }
    04033             BOOST_UBLAS_INLINE
    04034             bool operator < (const iterator2 &it) const {
    04035                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04036                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    04037                 return it2_ < it.it2_;
    04038             }
    04039
    04040         private:
    04041             subiterator1_type it1_;
    04042             subiterator2_type it2_;
    04043
    04044             friend class const_iterator2;
    04045         };
    04046 #endif
    04047
    04048         BOOST_UBLAS_INLINE
    04049         iterator2 begin2 () {
    04050             return find2 (0, 0, 0);
    04051         }
    04052         BOOST_UBLAS_INLINE
    04053         iterator2 end2 () {
    04054             return find2 (0, 0, size2 ());
    04055         }
    04056
    04057         // Reverse iterators
    04058
    04059         BOOST_UBLAS_INLINE
    04060         const_reverse_iterator1 rbegin1 () const {
    04061             return const_reverse_iterator1 (end1 ());
    04062         }
    04063         BOOST_UBLAS_INLINE
    04064         const_reverse_iterator1 rend1 () const {
    04065             return const_reverse_iterator1 (begin1 ());
    04066         }
    04067
    04068         BOOST_UBLAS_INLINE
    04069         reverse_iterator1 rbegin1 () {
    04070             return reverse_iterator1 (end1 ());
    04071         }
    04072         BOOST_UBLAS_INLINE
    04073         reverse_iterator1 rend1 () {
    04074             return reverse_iterator1 (begin1 ());
    04075         }
    04076
    04077         BOOST_UBLAS_INLINE
    04078         const_reverse_iterator2 rbegin2 () const {
    04079             return const_reverse_iterator2 (end2 ());
    04080         }
    04081         BOOST_UBLAS_INLINE
    04082         const_reverse_iterator2 rend2 () const {
    04083             return const_reverse_iterator2 (begin2 ());
    04084         }
    04085
    04086         BOOST_UBLAS_INLINE
    04087         reverse_iterator2 rbegin2 () {
    04088             return reverse_iterator2 (end2 ());
    04089         }
    04090         BOOST_UBLAS_INLINE
    04091         reverse_iterator2 rend2 () {
    04092             return reverse_iterator2 (begin2 ());
    04093         }
    04094
    04095     private:
    04096         matrix_closure_type data_;
    04097         slice_type s1_;
    04098         slice_type s2_;
    04099     };
    04100
    04101     // Simple Projections
    04102     template<class M>
    04103     BOOST_UBLAS_INLINE
    04104     matrix_slice<M> subslice (M &data, typename M::size_type start1, typename M::difference_type stride1, typename M::size_type size1, typename M::size_type start2, typename M::difference_type stride2, typename M::size_type size2) {
    04105         typedef basic_slice<typename M::size_type, typename M::difference_type> slice_type;
    04106         return matrix_slice<M> (data, slice_type (start1, stride1, size1), slice_type (start2, stride2, size2));
    04107     }
    04108     template<class M>
    04109     BOOST_UBLAS_INLINE
    04110     matrix_slice<const M> subslice (const M &data, typename M::size_type start1, typename M::difference_type stride1, typename M::size_type size1, typename M::size_type start2, typename M::difference_type stride2, typename M::size_type size2) {
    04111         typedef basic_slice<typename M::size_type, typename M::difference_type> slice_type;
    04112         return matrix_slice<const M> (data, slice_type (start1, stride1, size1), slice_type (start2, stride2, size2));
    04113     }
    04114
    04115     // Generic Projections
    04116     template<class M>
    04117     BOOST_UBLAS_INLINE
    04118     matrix_slice<M> project (M &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
    04119         return matrix_slice<M> (data, s1, s2);
    04120     }
    04121     template<class M>
    04122     BOOST_UBLAS_INLINE
    04123     const matrix_slice<const M> project (const M &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
    04124         // ISSUE was: return matrix_slice<M> (const_cast<M &> (data), s1, s2);
    04125         return matrix_slice<const M> (data, s1, s2);
    04126     }
    04127     // ISSUE in the following two functions it would be logical to use matrix_slice<V>::range_type but this confuses VC7.1 and 8.0
    04128     template<class M>
    04129     BOOST_UBLAS_INLINE
    04130     matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
    04131         return data.project (r1, r2);
    04132     }
    04133     template<class M>
    04134     BOOST_UBLAS_INLINE
    04135     const matrix_slice<M> project (const matrix_slice<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
    04136         return data.project (r1, r2);
    04137     }
    04138     template<class M>
    04139     BOOST_UBLAS_INLINE
    04140     matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
    04141         return data.project (s1, s2);
    04142     }
    04143     template<class M>
    04144     BOOST_UBLAS_INLINE
    04145     const matrix_slice<M> project (const matrix_slice<M> &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
    04146         return data.project (s1, s2);
    04147     }
    04148
    04149     // Specialization of temporary_traits
    04150     template <class M>
    04151     struct matrix_temporary_traits< matrix_slice<M> >
    04152     : matrix_temporary_traits< M > {};
    04153     template <class M>
    04154     struct matrix_temporary_traits< const matrix_slice<M> >
    04155     : matrix_temporary_traits< M > {};
    04156
    04157     template <class M>
    04158     struct vector_temporary_traits< matrix_slice<M> >
    04159     : vector_temporary_traits< M > {};
    04160     template <class M>
    04161     struct vector_temporary_traits< const matrix_slice<M> >
    04162     : vector_temporary_traits< M > {};
    04163
    04164     // Matrix based indirection class
    04165     // Contributed by Toon Knapen.
    04166     // Extended and optimized by Kresimir Fresl.
    04185     template<class M, class IA>
    04186     class matrix_indirect:
    04187         public matrix_expression<matrix_indirect<M, IA> > {
    04188
    04189         typedef matrix_indirect<M, IA> self_type;
    04190     public:
    04191 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    04192         using matrix_expression<self_type>::operator ();
    04193 #endif
    04194         typedef M matrix_type;
    04195         typedef IA indirect_array_type;
    04196         typedef typename M::size_type size_type;
    04197         typedef typename M::difference_type difference_type;
    04198         typedef typename M::value_type value_type;
    04199         typedef typename M::const_reference const_reference;
    04200         typedef typename boost::mpl::if_<boost::is_const<M>,
    04201                                           typename M::const_reference,
    04202                                           typename M::reference>::type reference;
    04203         typedef typename boost::mpl::if_<boost::is_const<M>,
    04204                                           typename M::const_closure_type,
    04205                                           typename M::closure_type>::type matrix_closure_type;
    04206         typedef basic_range<size_type, difference_type> range_type;
    04207         typedef basic_slice<size_type, difference_type> slice_type;
    04208         typedef const self_type const_closure_type;
    04209         typedef self_type closure_type;
    04210         typedef typename storage_restrict_traits<typename M::storage_category,
    04211                                                  dense_proxy_tag>::storage_category storage_category;
    04212         typedef typename M::orientation_category orientation_category;
    04213
    04214         // Construction and destruction
    04215         BOOST_UBLAS_INLINE
    04216         matrix_indirect (matrix_type &data, size_type size1, size_type size2):
    04217             data_ (data), ia1_ (size1), ia2_ (size2) {}
    04218         BOOST_UBLAS_INLINE
    04219         matrix_indirect (matrix_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2):
    04220             data_ (data), ia1_ (ia1.preprocess (data.size1 ())), ia2_ (ia2.preprocess (data.size2 ())) {}
    04221         BOOST_UBLAS_INLINE
    04222         matrix_indirect (const matrix_closure_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2, int):
    04223             data_ (data), ia1_ (ia1.preprocess (data.size1 ())), ia2_ (ia2.preprocess (data.size2 ())) {}
    04224
    04225         // Accessors
    04226         BOOST_UBLAS_INLINE
    04227         size_type size1 () const {
    04228             return ia1_.size ();
    04229         }
    04230         BOOST_UBLAS_INLINE
    04231         size_type size2 () const {
    04232             return ia2_.size ();
    04233         }
    04234         BOOST_UBLAS_INLINE
    04235         const indirect_array_type &indirect1 () const {
    04236             return ia1_;
    04237         }
    04238         BOOST_UBLAS_INLINE
    04239         indirect_array_type &indirect1 () {
    04240             return ia1_;
    04241         }
    04242         BOOST_UBLAS_INLINE
    04243         const indirect_array_type &indirect2 () const {
    04244             return ia2_;
    04245         }
    04246         BOOST_UBLAS_INLINE
    04247         indirect_array_type &indirect2 () {
    04248             return ia2_;
    04249         }
    04250
    04251         // Storage accessors
    04252         BOOST_UBLAS_INLINE
    04253         const matrix_closure_type &data () const {
    04254             return data_;
    04255         }
    04256         BOOST_UBLAS_INLINE
    04257         matrix_closure_type &data () {
    04258             return data_;
    04259         }
    04260
    04261         // Element access
    04262 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
    04263         BOOST_UBLAS_INLINE
    04264         const_reference operator () (size_type i, size_type j) const {
    04265             return data_ (ia1_ (i), ia2_ (j));
    04266         }
    04267         BOOST_UBLAS_INLINE
    04268         reference operator () (size_type i, size_type j) {
    04269             return data_ (ia1_ (i), ia2_ (j));
    04270         }
    04271 #else
    04272         BOOST_UBLAS_INLINE
    04273         reference operator () (size_type i, size_type j) const {
    04274             return data_ (ia1_ (i), ia2_ (j));
    04275         }
    04276 #endif
    04277
    04278         // ISSUE can this be done in free project function?
    04279         // Although a const function can create a non-const proxy to a non-const object
    04280         // Critical is that matrix_type and data_ (vector_closure_type) are const correct
    04281         BOOST_UBLAS_INLINE
    04282         matrix_indirect<matrix_type, indirect_array_type> project (const range_type &r1, const range_type &r2) const {
    04283             return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (r1.preprocess (data_.size1 ())), ia2_.compose (r2.preprocess (data_.size2 ())), 0);
    04284         }
    04285         BOOST_UBLAS_INLINE
    04286         matrix_indirect<matrix_type, indirect_array_type> project (const slice_type &s1, const slice_type &s2) const {
    04287             return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (s1.preprocess (data_.size1 ())), ia2_.compose (s2.preprocess (data_.size2 ())), 0);
    04288         }
    04289         BOOST_UBLAS_INLINE
    04290         matrix_indirect<matrix_type, indirect_array_type> project (const indirect_array_type &ia1, const indirect_array_type &ia2) const {
    04291             return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (ia1.preprocess (data_.size1 ())), ia2_.compose (ia2.preprocess (data_.size2 ())), 0);
    04292         }
    04293
    04294         // Assignment
    04295         BOOST_UBLAS_INLINE
    04296         matrix_indirect &operator = (const matrix_indirect &mi) {
    04297             matrix_assign<scalar_assign> (*this, mi);
    04298             return *this;
    04299         }
    04300         BOOST_UBLAS_INLINE
    04301         matrix_indirect &assign_temporary (matrix_indirect &mi) {
    04302             return *this = mi;
    04303         }
    04304         template<class AE>
    04305         BOOST_UBLAS_INLINE
    04306         matrix_indirect &operator = (const matrix_expression<AE> &ae) {
    04307             matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae));
    04308             return *this;
    04309         }
    04310         template<class AE>
    04311         BOOST_UBLAS_INLINE
    04312         matrix_indirect &assign (const matrix_expression<AE> &ae) {
    04313             matrix_assign<scalar_assign> (*this, ae);
    04314             return *this;
    04315         }
    04316         template<class AE>
    04317         BOOST_UBLAS_INLINE
    04318         matrix_indirect& operator += (const matrix_expression<AE> &ae) {
    04319             matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae));
    04320             return *this;
    04321         }
    04322         template<class AE>
    04323         BOOST_UBLAS_INLINE
    04324         matrix_indirect &plus_assign (const matrix_expression<AE> &ae) {
    04325             matrix_assign<scalar_plus_assign> (*this, ae);
    04326             return *this;
    04327         }
    04328         template<class AE>
    04329         BOOST_UBLAS_INLINE
    04330         matrix_indirect& operator -= (const matrix_expression<AE> &ae) {
    04331             matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae));
    04332             return *this;
    04333         }
    04334         template<class AE>
    04335         BOOST_UBLAS_INLINE
    04336         matrix_indirect &minus_assign (const matrix_expression<AE> &ae) {
    04337             matrix_assign<scalar_minus_assign> (*this, ae);
    04338             return *this;
    04339         }
    04340         template<class AT>
    04341         BOOST_UBLAS_INLINE
    04342         matrix_indirect& operator *= (const AT &at) {
    04343             matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
    04344             return *this;
    04345         }
    04346         template<class AT>
    04347         BOOST_UBLAS_INLINE
    04348         matrix_indirect& operator /= (const AT &at) {
    04349             matrix_assign_scalar<scalar_divides_assign> (*this, at);
    04350             return *this;
    04351         }
    04352
    04353         // Closure comparison
    04354         BOOST_UBLAS_INLINE
    04355         bool same_closure (const matrix_indirect &mi) const {
    04356             return (*this).data_.same_closure (mi.data_);
    04357         }
    04358
    04359         // Comparison
    04360         BOOST_UBLAS_INLINE
    04361         bool operator == (const matrix_indirect &mi) const {
    04362             return (*this).data_ == mi.data_ && ia1_ == mi.ia1_ && ia2_ == mi.ia2_;
    04363         }
    04364
    04365         // Swapping
    04366         BOOST_UBLAS_INLINE
    04367         void swap (matrix_indirect mi) {
    04368             if (this != &mi) {
    04369                 BOOST_UBLAS_CHECK (size1 () == mi.size1 (), bad_size ());
    04370                 BOOST_UBLAS_CHECK (size2 () == mi.size2 (), bad_size ());
    04371                 matrix_swap<scalar_swap> (*this, mi);
    04372             }
    04373         }
    04374         BOOST_UBLAS_INLINE
    04375         friend void swap (matrix_indirect mi1, matrix_indirect mi2) {
    04376             mi1.swap (mi2);
    04377         }
    04378
    04379         // Iterator types
    04380     private:
    04381         typedef typename IA::const_iterator const_subiterator1_type;
    04382         typedef typename IA::const_iterator subiterator1_type;
    04383         typedef typename IA::const_iterator const_subiterator2_type;
    04384         typedef typename IA::const_iterator subiterator2_type;
    04385
    04386     public:
    04387 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04388         typedef indexed_iterator1<matrix_indirect<matrix_type, indirect_array_type>,
    04389                                   typename matrix_type::iterator1::iterator_category> iterator1;
    04390         typedef indexed_iterator2<matrix_indirect<matrix_type, indirect_array_type>,
    04391                                   typename matrix_type::iterator2::iterator_category> iterator2;
    04392         typedef indexed_const_iterator1<matrix_indirect<matrix_type, indirect_array_type>,
    04393                                         typename matrix_type::const_iterator1::iterator_category> const_iterator1;
    04394         typedef indexed_const_iterator2<matrix_indirect<matrix_type, indirect_array_type>,
    04395                                         typename matrix_type::const_iterator2::iterator_category> const_iterator2;
    04396 #else
    04397         class const_iterator1;
    04398         class iterator1;
    04399         class const_iterator2;
    04400         class iterator2;
    04401 #endif
    04402         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    04403         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
    04404         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    04405         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
    04406
    04407         // Element lookup
    04408         BOOST_UBLAS_INLINE
    04409         const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
    04410 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04411             return const_iterator1 (*this, i, j);
    04412 #else
    04413             return const_iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j);
    04414 #endif
    04415         }
    04416         BOOST_UBLAS_INLINE
    04417         iterator1 find1 (int /* rank */, size_type i, size_type j) {
    04418 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04419             return iterator1 (*this, i, j);
    04420 #else
    04421             return iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j);
    04422 #endif
    04423         }
    04424         BOOST_UBLAS_INLINE
    04425         const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
    04426 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04427             return const_iterator2 (*this, i, j);
    04428 #else
    04429             return const_iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j);
    04430 #endif
    04431         }
    04432         BOOST_UBLAS_INLINE
    04433         iterator2 find2 (int /* rank */, size_type i, size_type j) {
    04434 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04435             return iterator2 (*this, i, j);
    04436 #else
    04437             return iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j);
    04438 #endif
    04439         }
    04440
    04441         // Iterators simply are indices.
    04442
    04443 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04444         class const_iterator1:
    04445             public container_const_reference<matrix_indirect>,
    04446             public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
    04447                         iterator_base<const_iterator1, value_type>::type {
    04448         public:
    04449             typedef typename M::const_iterator1::value_type value_type;
    04450             typedef typename M::const_iterator1::difference_type difference_type;
    04451             typedef typename M::const_reference reference;    //FIXME due to indexing access
    04452             typedef typename M::const_iterator1::pointer pointer;
    04453             typedef const_iterator2 dual_iterator_type;
    04454             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    04455
    04456             // Construction and destruction
    04457             BOOST_UBLAS_INLINE
    04458             const_iterator1 ():
    04459                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    04460             BOOST_UBLAS_INLINE
    04461             const_iterator1 (const self_type &mi, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
    04462                 container_const_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
    04463             BOOST_UBLAS_INLINE
    04464             const_iterator1 (const iterator1 &it):
    04465                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
    04466
    04467             // Arithmetic
    04468             BOOST_UBLAS_INLINE
    04469             const_iterator1 &operator ++ () {
    04470                 ++ it1_;
    04471                 return *this;
    04472             }
    04473             BOOST_UBLAS_INLINE
    04474             const_iterator1 &operator -- () {
    04475                 -- it1_;
    04476                 return *this;
    04477             }
    04478             BOOST_UBLAS_INLINE
    04479             const_iterator1 &operator += (difference_type n) {
    04480                 it1_ += n;
    04481                 return *this;
    04482             }
    04483             BOOST_UBLAS_INLINE
    04484             const_iterator1 &operator -= (difference_type n) {
    04485                 it1_ -= n;
    04486                 return *this;
    04487             }
    04488             BOOST_UBLAS_INLINE
    04489             difference_type operator - (const const_iterator1 &it) const {
    04490                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04491                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    04492                 return it1_ - it.it1_;
    04493             }
    04494
    04495             // Dereference
    04496             BOOST_UBLAS_INLINE
    04497             const_reference operator * () const {
    04498                 // FIXME replace find with at_element
    04499                 return (*this) ().data_ (*it1_, *it2_);
    04500             }
    04501             BOOST_UBLAS_INLINE
    04502             const_reference operator [] (difference_type n) const {
    04503                 return *(*this + n);
    04504             }
    04505
    04506 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    04507             BOOST_UBLAS_INLINE
    04508 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04509             typename self_type::
    04510 #endif
    04511             const_iterator2 begin () const {
    04512                 return const_iterator2 ((*this) (), it1_, it2_ ().begin ());
    04513             }
    04514             BOOST_UBLAS_INLINE
    04515 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04516             typename self_type::
    04517 #endif
    04518             const_iterator2 end () const {
    04519                 return const_iterator2 ((*this) (), it1_, it2_ ().end ());
    04520             }
    04521             BOOST_UBLAS_INLINE
    04522 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04523             typename self_type::
    04524 #endif
    04525             const_reverse_iterator2 rbegin () const {
    04526                 return const_reverse_iterator2 (end ());
    04527             }
    04528             BOOST_UBLAS_INLINE
    04529 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04530             typename self_type::
    04531 #endif
    04532             const_reverse_iterator2 rend () const {
    04533                 return const_reverse_iterator2 (begin ());
    04534             }
    04535 #endif
    04536
    04537             // Indices
    04538             BOOST_UBLAS_INLINE
    04539             size_type index1 () const {
    04540                 return it1_.index ();
    04541             }
    04542             BOOST_UBLAS_INLINE
    04543             size_type index2 () const {
    04544                 return it2_.index ();
    04545             }
    04546
    04547             // Assignment
    04548             BOOST_UBLAS_INLINE
    04549             const_iterator1 &operator = (const const_iterator1 &it) {
    04550                 container_const_reference<self_type>::assign (&it ());
    04551                 it1_ = it.it1_;
    04552                 it2_ = it.it2_;
    04553                 return *this;
    04554             }
    04555
    04556             // Comparison
    04557             BOOST_UBLAS_INLINE
    04558             bool operator == (const const_iterator1 &it) const {
    04559                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04560                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    04561                 return it1_ == it.it1_;
    04562             }
    04563             BOOST_UBLAS_INLINE
    04564             bool operator < (const const_iterator1 &it) const {
    04565                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04566                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    04567                 return it1_ < it.it1_;
    04568             }
    04569
    04570         private:
    04571             const_subiterator1_type it1_;
    04572             const_subiterator2_type it2_;
    04573         };
    04574 #endif
    04575
    04576         BOOST_UBLAS_INLINE
    04577         const_iterator1 begin1 () const {
    04578             return find1 (0, 0, 0);
    04579         }
    04580         BOOST_UBLAS_INLINE
    04581         const_iterator1 end1 () const {
    04582             return find1 (0, size1 (), 0);
    04583         }
    04584
    04585 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04586         class iterator1:
    04587             public container_reference<matrix_indirect>,
    04588             public iterator_base_traits<typename M::iterator1::iterator_category>::template
    04589                         iterator_base<iterator1, value_type>::type {
    04590         public:
    04591             typedef typename M::iterator1::value_type value_type;
    04592             typedef typename M::iterator1::difference_type difference_type;
    04593             typedef typename M::reference reference;    //FIXME due to indexing access
    04594             typedef typename M::iterator1::pointer pointer;
    04595             typedef iterator2 dual_iterator_type;
    04596             typedef reverse_iterator2 dual_reverse_iterator_type;
    04597
    04598             // Construction and destruction
    04599             BOOST_UBLAS_INLINE
    04600             iterator1 ():
    04601                 container_reference<self_type> (), it1_ (), it2_ () {}
    04602             BOOST_UBLAS_INLINE
    04603             iterator1 (self_type &mi, const subiterator1_type &it1, const subiterator2_type &it2):
    04604                 container_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
    04605
    04606             // Arithmetic
    04607             BOOST_UBLAS_INLINE
    04608             iterator1 &operator ++ () {
    04609                 ++ it1_;
    04610                 return *this;
    04611             }
    04612             BOOST_UBLAS_INLINE
    04613             iterator1 &operator -- () {
    04614                 -- it1_;
    04615                 return *this;
    04616             }
    04617             BOOST_UBLAS_INLINE
    04618             iterator1 &operator += (difference_type n) {
    04619                 it1_ += n;
    04620                 return *this;
    04621             }
    04622             BOOST_UBLAS_INLINE
    04623             iterator1 &operator -= (difference_type n) {
    04624                 it1_ -= n;
    04625                 return *this;
    04626             }
    04627             BOOST_UBLAS_INLINE
    04628             difference_type operator - (const iterator1 &it) const {
    04629                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04630                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    04631                 return it1_ - it.it1_;
    04632             }
    04633
    04634             // Dereference
    04635             BOOST_UBLAS_INLINE
    04636             reference operator * () const {
    04637                 // FIXME replace find with at_element
    04638                 return (*this) ().data_ (*it1_, *it2_);
    04639             }
    04640             BOOST_UBLAS_INLINE
    04641             reference operator [] (difference_type n) const {
    04642                 return *(*this + n);
    04643             }
    04644
    04645 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    04646             BOOST_UBLAS_INLINE
    04647 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04648             typename self_type::
    04649 #endif
    04650             iterator2 begin () const {
    04651                 return iterator2 ((*this) (), it1_, it2_ ().begin ());
    04652             }
    04653             BOOST_UBLAS_INLINE
    04654 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04655             typename self_type::
    04656 #endif
    04657             iterator2 end () const {
    04658                 return iterator2 ((*this) (), it1_, it2_ ().end ());
    04659             }
    04660             BOOST_UBLAS_INLINE
    04661 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04662             typename self_type::
    04663 #endif
    04664             reverse_iterator2 rbegin () const {
    04665                 return reverse_iterator2 (end ());
    04666             }
    04667             BOOST_UBLAS_INLINE
    04668 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04669             typename self_type::
    04670 #endif
    04671             reverse_iterator2 rend () const {
    04672                 return reverse_iterator2 (begin ());
    04673             }
    04674 #endif
    04675
    04676             // Indices
    04677             BOOST_UBLAS_INLINE
    04678             size_type index1 () const {
    04679                 return it1_.index ();
    04680             }
    04681             BOOST_UBLAS_INLINE
    04682             size_type index2 () const {
    04683                 return it2_.index ();
    04684             }
    04685
    04686             // Assignment
    04687             BOOST_UBLAS_INLINE
    04688             iterator1 &operator = (const iterator1 &it) {
    04689                 container_reference<self_type>::assign (&it ());
    04690                 it1_ = it.it1_;
    04691                 it2_ = it.it2_;
    04692                 return *this;
    04693             }
    04694
    04695             // Comparison
    04696             BOOST_UBLAS_INLINE
    04697             bool operator == (const iterator1 &it) const {
    04698                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04699                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    04700                 return it1_ == it.it1_;
    04701             }
    04702             BOOST_UBLAS_INLINE
    04703             bool operator < (const iterator1 &it) const {
    04704                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04705                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    04706                 return it1_ < it.it1_;
    04707             }
    04708
    04709         private:
    04710             subiterator1_type it1_;
    04711             subiterator2_type it2_;
    04712
    04713             friend class const_iterator1;
    04714         };
    04715 #endif
    04716
    04717         BOOST_UBLAS_INLINE
    04718         iterator1 begin1 () {
    04719             return find1 (0, 0, 0);
    04720         }
    04721         BOOST_UBLAS_INLINE
    04722         iterator1 end1 () {
    04723             return find1 (0, size1 (), 0);
    04724         }
    04725
    04726 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04727         class const_iterator2:
    04728             public container_const_reference<matrix_indirect>,
    04729             public iterator_base_traits<typename M::const_iterator2::iterator_category>::template
    04730                         iterator_base<const_iterator2, value_type>::type {
    04731         public:
    04732             typedef typename M::const_iterator2::value_type value_type;
    04733             typedef typename M::const_iterator2::difference_type difference_type;
    04734             typedef typename M::const_reference reference;    //FIXME due to indexing access
    04735             typedef typename M::const_iterator2::pointer pointer;
    04736             typedef const_iterator1 dual_iterator_type;
    04737             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    04738
    04739             // Construction and destruction
    04740             BOOST_UBLAS_INLINE
    04741             const_iterator2 ():
    04742                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    04743             BOOST_UBLAS_INLINE
    04744             const_iterator2 (const self_type &mi, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
    04745                 container_const_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
    04746             BOOST_UBLAS_INLINE
    04747             const_iterator2 (const iterator2 &it):
    04748                 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
    04749
    04750             // Arithmetic
    04751             BOOST_UBLAS_INLINE
    04752             const_iterator2 &operator ++ () {
    04753                 ++ it2_;
    04754                 return *this;
    04755             }
    04756             BOOST_UBLAS_INLINE
    04757             const_iterator2 &operator -- () {
    04758                 -- it2_;
    04759                 return *this;
    04760             }
    04761             BOOST_UBLAS_INLINE
    04762             const_iterator2 &operator += (difference_type n) {
    04763                 it2_ += n;
    04764                 return *this;
    04765             }
    04766             BOOST_UBLAS_INLINE
    04767             const_iterator2 &operator -= (difference_type n) {
    04768                 it2_ -= n;
    04769                 return *this;
    04770             }
    04771             BOOST_UBLAS_INLINE
    04772             difference_type operator - (const const_iterator2 &it) const {
    04773                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04774                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    04775                 return it2_ - it.it2_;
    04776             }
    04777
    04778             // Dereference
    04779             BOOST_UBLAS_INLINE
    04780             const_reference operator * () const {
    04781                 // FIXME replace find with at_element
    04782                 return (*this) ().data_ (*it1_, *it2_);
    04783             }
    04784             BOOST_UBLAS_INLINE
    04785             const_reference operator [] (difference_type n) const {
    04786                 return *(*this + n);
    04787             }
    04788
    04789 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    04790             BOOST_UBLAS_INLINE
    04791 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04792             typename self_type::
    04793 #endif
    04794             const_iterator1 begin () const {
    04795                 return const_iterator1 ((*this) (), it1_ ().begin (), it2_);
    04796             }
    04797             BOOST_UBLAS_INLINE
    04798 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04799             typename self_type::
    04800 #endif
    04801             const_iterator1 end () const {
    04802                 return const_iterator1 ((*this) (), it1_ ().end (), it2_);
    04803             }
    04804             BOOST_UBLAS_INLINE
    04805 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04806             typename self_type::
    04807 #endif
    04808             const_reverse_iterator1 rbegin () const {
    04809                 return const_reverse_iterator1 (end ());
    04810             }
    04811             BOOST_UBLAS_INLINE
    04812 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04813             typename self_type::
    04814 #endif
    04815             const_reverse_iterator1 rend () const {
    04816                 return const_reverse_iterator1 (begin ());
    04817             }
    04818 #endif
    04819
    04820             // Indices
    04821             BOOST_UBLAS_INLINE
    04822             size_type index1 () const {
    04823                 return it1_.index ();
    04824             }
    04825             BOOST_UBLAS_INLINE
    04826             size_type index2 () const {
    04827                 return it2_.index ();
    04828             }
    04829
    04830             // Assignment
    04831             BOOST_UBLAS_INLINE
    04832             const_iterator2 &operator = (const const_iterator2 &it) {
    04833                 container_const_reference<self_type>::assign (&it ());
    04834                 it1_ = it.it1_;
    04835                 it2_ = it.it2_;
    04836                 return *this;
    04837             }
    04838
    04839             // Comparison
    04840             BOOST_UBLAS_INLINE
    04841             bool operator == (const const_iterator2 &it) const {
    04842                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04843                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    04844                 return it2_ == it.it2_;
    04845             }
    04846             BOOST_UBLAS_INLINE
    04847             bool operator < (const const_iterator2 &it) const {
    04848                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04849                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    04850                 return it2_ < it.it2_;
    04851             }
    04852
    04853         private:
    04854             const_subiterator1_type it1_;
    04855             const_subiterator2_type it2_;
    04856         };
    04857 #endif
    04858
    04859         BOOST_UBLAS_INLINE
    04860         const_iterator2 begin2 () const {
    04861             return find2 (0, 0, 0);
    04862         }
    04863         BOOST_UBLAS_INLINE
    04864         const_iterator2 end2 () const {
    04865             return find2 (0, 0, size2 ());
    04866         }
    04867
    04868 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04869         class iterator2:
    04870             public container_reference<matrix_indirect>,
    04871             public iterator_base_traits<typename M::iterator2::iterator_category>::template
    04872                         iterator_base<iterator2, value_type>::type {
    04873         public:
    04874             typedef typename M::iterator2::value_type value_type;
    04875             typedef typename M::iterator2::difference_type difference_type;
    04876             typedef typename M::reference reference;    //FIXME due to indexing access
    04877             typedef typename M::iterator2::pointer pointer;
    04878             typedef iterator1 dual_iterator_type;
    04879             typedef reverse_iterator1 dual_reverse_iterator_type;
    04880
    04881             // Construction and destruction
    04882             BOOST_UBLAS_INLINE
    04883             iterator2 ():
    04884                 container_reference<self_type> (), it1_ (), it2_ () {}
    04885             BOOST_UBLAS_INLINE
    04886             iterator2 (self_type &mi, const subiterator1_type &it1, const subiterator2_type &it2):
    04887                 container_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
    04888
    04889             // Arithmetic
    04890             BOOST_UBLAS_INLINE
    04891             iterator2 &operator ++ () {
    04892                 ++ it2_;
    04893                 return *this;
    04894             }
    04895             BOOST_UBLAS_INLINE
    04896             iterator2 &operator -- () {
    04897                 -- it2_;
    04898                 return *this;
    04899             }
    04900             BOOST_UBLAS_INLINE
    04901             iterator2 &operator += (difference_type n) {
    04902                 it2_ += n;
    04903                 return *this;
    04904             }
    04905             BOOST_UBLAS_INLINE
    04906             iterator2 &operator -= (difference_type n) {
    04907                 it2_ -= n;
    04908                 return *this;
    04909             }
    04910             BOOST_UBLAS_INLINE
    04911             difference_type operator - (const iterator2 &it) const {
    04912                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04913                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    04914                 return it2_ - it.it2_;
    04915             }
    04916
    04917             // Dereference
    04918             BOOST_UBLAS_INLINE
    04919             reference operator * () const {
    04920                 // FIXME replace find with at_element
    04921                 return (*this) ().data_ (*it1_, *it2_);
    04922             }
    04923             BOOST_UBLAS_INLINE
    04924             reference operator [] (difference_type n) const {
    04925                 return *(*this + n);
    04926             }
    04927
    04928 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    04929             BOOST_UBLAS_INLINE
    04930 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04931             typename self_type::
    04932 #endif
    04933             iterator1 begin () const {
    04934                 return iterator1 ((*this) (), it1_ ().begin (), it2_);
    04935             }
    04936             BOOST_UBLAS_INLINE
    04937 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04938             typename self_type::
    04939 #endif
    04940             iterator1 end () const {
    04941                 return iterator1 ((*this) (), it1_ ().end (), it2_);
    04942             }
    04943             BOOST_UBLAS_INLINE
    04944 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04945             typename self_type::
    04946 #endif
    04947             reverse_iterator1 rbegin () const {
    04948                 return reverse_iterator1 (end ());
    04949             }
    04950             BOOST_UBLAS_INLINE
    04951 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04952             typename self_type::
    04953 #endif
    04954             reverse_iterator1 rend () const {
    04955                 return reverse_iterator1 (begin ());
    04956             }
    04957 #endif
    04958
    04959             // Indices
    04960             BOOST_UBLAS_INLINE
    04961             size_type index1 () const {
    04962                 return it1_.index ();
    04963             }
    04964             BOOST_UBLAS_INLINE
    04965             size_type index2 () const {
    04966                 return it2_.index ();
    04967             }
    04968
    04969             // Assignment
    04970             BOOST_UBLAS_INLINE
    04971             iterator2 &operator = (const iterator2 &it) {
    04972                 container_reference<self_type>::assign (&it ());
    04973                 it1_ = it.it1_;
    04974                 it2_ = it.it2_;
    04975                 return *this;
    04976             }
    04977
    04978             // Comparison
    04979             BOOST_UBLAS_INLINE
    04980             bool operator == (const iterator2 &it) const {
    04981                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04982                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    04983                 return it2_ == it.it2_;
    04984             }
    04985             BOOST_UBLAS_INLINE
    04986             bool operator < (const iterator2 &it) const {
    04987                 BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
    04988                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    04989                 return it2_ < it.it2_;
    04990             }
    04991
    04992         private:
    04993             subiterator1_type it1_;
    04994             subiterator2_type it2_;
    04995
    04996             friend class const_iterator2;
    04997         };
    04998 #endif
    04999
    05000         BOOST_UBLAS_INLINE
    05001         iterator2 begin2 () {
    05002             return find2 (0, 0, 0);
    05003         }
    05004         BOOST_UBLAS_INLINE
    05005         iterator2 end2 () {
    05006             return find2 (0, 0, size2 ());
    05007         }
    05008
    05009         // Reverse iterators
    05010
    05011         BOOST_UBLAS_INLINE
    05012         const_reverse_iterator1 rbegin1 () const {
    05013             return const_reverse_iterator1 (end1 ());
    05014         }
    05015         BOOST_UBLAS_INLINE
    05016         const_reverse_iterator1 rend1 () const {
    05017             return const_reverse_iterator1 (begin1 ());
    05018         }
    05019
    05020         BOOST_UBLAS_INLINE
    05021         reverse_iterator1 rbegin1 () {
    05022             return reverse_iterator1 (end1 ());
    05023         }
    05024         BOOST_UBLAS_INLINE
    05025         reverse_iterator1 rend1 () {
    05026             return reverse_iterator1 (begin1 ());
    05027         }
    05028
    05029         BOOST_UBLAS_INLINE
    05030         const_reverse_iterator2 rbegin2 () const {
    05031             return const_reverse_iterator2 (end2 ());
    05032         }
    05033         BOOST_UBLAS_INLINE
    05034         const_reverse_iterator2 rend2 () const {
    05035             return const_reverse_iterator2 (begin2 ());
    05036         }
    05037
    05038         BOOST_UBLAS_INLINE
    05039         reverse_iterator2 rbegin2 () {
    05040             return reverse_iterator2 (end2 ());
    05041         }
    05042         BOOST_UBLAS_INLINE
    05043         reverse_iterator2 rend2 () {
    05044             return reverse_iterator2 (begin2 ());
    05045         }
    05046
    05047     private:
    05048         matrix_closure_type data_;
    05049         indirect_array_type ia1_;
    05050         indirect_array_type ia2_;
    05051     };
    05052
    05053     // Projections
    05054     template<class M, class A>
    05055     BOOST_UBLAS_INLINE
    05056     matrix_indirect<M, indirect_array<A> > project (M &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
    05057         return matrix_indirect<M, indirect_array<A> > (data, ia1, ia2);
    05058     }
    05059     template<class M, class A>
    05060     BOOST_UBLAS_INLINE
    05061     const matrix_indirect<const M, indirect_array<A> > project (const M &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
    05062         // ISSUE was: return matrix_indirect<M, indirect_array<A> > (const_cast<M &> (data), ia1, ia2);
    05063         return matrix_indirect<const M, indirect_array<A> > (data, ia1, ia2);
    05064     }
    05065     template<class M, class IA>
    05066     BOOST_UBLAS_INLINE
    05067     matrix_indirect<M, IA> project (matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::range_type &r1, const typename matrix_indirect<M, IA>::range_type &r2) {
    05068         return data.project (r1, r2);
    05069     }
    05070     template<class M, class IA>
    05071     BOOST_UBLAS_INLINE
    05072     const matrix_indirect<M, IA> project (const matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::range_type &r1, const typename matrix_indirect<M, IA>::range_type &r2) {
    05073         return data.project (r1, r2);
    05074     }
    05075     template<class M, class IA>
    05076     BOOST_UBLAS_INLINE
    05077     matrix_indirect<M, IA> project (matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::slice_type &s1, const typename matrix_indirect<M, IA>::slice_type &s2) {
    05078         return data.project (s1, s2);
    05079     }
    05080     template<class M, class IA>
    05081     BOOST_UBLAS_INLINE
    05082     const matrix_indirect<M, IA> project (const matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::slice_type &s1, const typename matrix_indirect<M, IA>::slice_type &s2) {
    05083         return data.project (s1, s2);
    05084     }
    05085     template<class M, class A>
    05086     BOOST_UBLAS_INLINE
    05087     matrix_indirect<M, indirect_array<A> > project (matrix_indirect<M, indirect_array<A> > &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
    05088         return data.project (ia1, ia2);
    05089     }
    05090     template<class M, class A>
    05091     BOOST_UBLAS_INLINE
    05092     const matrix_indirect<M, indirect_array<A> > project (const matrix_indirect<M, indirect_array<A> > &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
    05093         return data.project (ia1, ia2);
    05094     }
    05095
    05097     template <class M>
    05098     struct matrix_temporary_traits< matrix_indirect<M> >
    05099     : matrix_temporary_traits< M > {};
    05100     template <class M>
    05101     struct matrix_temporary_traits< const matrix_indirect<M> >
    05102     : matrix_temporary_traits< M > {};
    05103
    05104     template <class M>
    05105     struct vector_temporary_traits< matrix_indirect<M> >
    05106     : vector_temporary_traits< M > {};
    05107     template <class M>
    05108     struct vector_temporary_traits< const matrix_indirect<M> >
    05109     : vector_temporary_traits< M > {};
    05110
    05111 }}}
    05112
    05113 #endif