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

matrix_proxy.hpp

Go to the documentation of this file.
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