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

vector_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_VECTOR_PROXY_
00014 #define _BOOST_UBLAS_VECTOR_PROXY_
00015 
00016 #include <boost/numeric/ublas/vector_expression.hpp>
00017 #include <boost/numeric/ublas/detail/vector_assign.hpp>
00018 #include <boost/numeric/ublas/detail/temporary.hpp>
00019 
00020 // Iterators based on ideas of Jeremy Siek
00021 
00022 namespace boost { namespace numeric { namespace ublas {
00023 
00033     template<class V>
00034     class vector_range:
00035         public vector_expression<vector_range<V> > {
00036 
00037         typedef vector_range<V> self_type;
00038     public:
00039 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
00040         using vector_expression<self_type>::operator ();
00041 #endif
00042         typedef const V const_vector_type;
00043         typedef V vector_type;
00044         typedef typename V::size_type size_type;
00045         typedef typename V::difference_type difference_type;
00046         typedef typename V::value_type value_type;
00047         typedef typename V::const_reference const_reference;
00048         typedef typename boost::mpl::if_<boost::is_const<V>,
00049                                           typename V::const_reference,
00050                                           typename V::reference>::type reference;
00051         typedef typename boost::mpl::if_<boost::is_const<V>,
00052                                           typename V::const_closure_type,
00053                                           typename V::closure_type>::type vector_closure_type;
00054         typedef basic_range<size_type, difference_type> range_type;
00055         typedef const self_type const_closure_type;
00056         typedef self_type closure_type;
00057         typedef typename storage_restrict_traits<typename V::storage_category,
00058                                                  dense_proxy_tag>::storage_category storage_category;
00059 
00060         // Construction and destruction
00061         BOOST_UBLAS_INLINE
00062         vector_range (vector_type &data, const range_type &r):
00063             data_ (data), r_ (r.preprocess (data.size ())) {
00064             // Early checking of preconditions here.
00065             // BOOST_UBLAS_CHECK (r_.start () <= data_.size () &&
00066             //                   r_.start () + r_.size () <= data_.size (), bad_index ());
00067         }
00068         BOOST_UBLAS_INLINE
00069         vector_range (const vector_closure_type &data, const range_type &r, bool):
00070             data_ (data), r_ (r.preprocess (data.size ())) {
00071             // Early checking of preconditions here.
00072             // BOOST_UBLAS_CHECK (r_.start () <= data_.size () &&
00073             //                    r_.start () + r_.size () <= data_.size (), bad_index ());
00074         }
00075 
00076         // Accessors
00077         BOOST_UBLAS_INLINE
00078         size_type start () const {
00079             return r_.start ();
00080         }
00081         BOOST_UBLAS_INLINE
00082         size_type size () const {
00083             return r_.size ();
00084         }
00085 
00086         // Storage accessors
00087         BOOST_UBLAS_INLINE
00088         const vector_closure_type &data () const {
00089             return data_;
00090         }
00091         BOOST_UBLAS_INLINE
00092         vector_closure_type &data () {
00093             return data_;
00094         }
00095 
00096         // Element access
00097 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
00098         BOOST_UBLAS_INLINE
00099         const_reference operator () (size_type i) const {
00100             return data_ (r_ (i));
00101         }
00102         BOOST_UBLAS_INLINE
00103         reference operator () (size_type i) {
00104             return data_ (r_ (i));
00105         }
00106 
00107         BOOST_UBLAS_INLINE
00108         const_reference operator [] (size_type i) const {
00109             return (*this) (i);
00110         }
00111         BOOST_UBLAS_INLINE
00112         reference operator [] (size_type i) {
00113             return (*this) (i);
00114         }
00115 #else
00116         BOOST_UBLAS_INLINE
00117         reference operator () (size_type i) const {
00118             return data_ (r_ (i));
00119         }
00120 
00121         BOOST_UBLAS_INLINE
00122         reference operator [] (size_type i) const {
00123             return (*this) (i);
00124         }
00125 #endif
00126 
00127         // ISSUE can this be done in free project function?
00128         // Although a const function can create a non-const proxy to a non-const object
00129         // Critical is that vector_type and data_ (vector_closure_type) are const correct
00130         BOOST_UBLAS_INLINE
00131         vector_range<vector_type> project (const range_type &r) const {
00132             return vector_range<vector_type> (data_, r_.compose (r.preprocess (data_.size ())), false);
00133         }
00134 
00135         // Assignment
00136         BOOST_UBLAS_INLINE
00137         vector_range &operator = (const vector_range &vr) {
00138             // ISSUE need a temporary, proxy can be overlaping alias
00139             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vr));
00140             return *this;
00141         }
00142         BOOST_UBLAS_INLINE
00143         vector_range &assign_temporary (vector_range &vr) {
00144             // assign elements, proxied container remains the same
00145             vector_assign<scalar_assign> (*this, vr);
00146             return *this;
00147         }
00148         template<class AE>
00149         BOOST_UBLAS_INLINE
00150         vector_range &operator = (const vector_expression<AE> &ae) {
00151             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
00152             return *this;
00153         }
00154         template<class AE>
00155         BOOST_UBLAS_INLINE
00156         vector_range &assign (const vector_expression<AE> &ae) {
00157             vector_assign<scalar_assign> (*this, ae);
00158             return *this;
00159         }
00160         template<class AE>
00161         BOOST_UBLAS_INLINE
00162         vector_range &operator += (const vector_expression<AE> &ae) {
00163             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
00164             return *this;
00165         }
00166         template<class AE>
00167         BOOST_UBLAS_INLINE
00168         vector_range &plus_assign (const vector_expression<AE> &ae) {
00169             vector_assign<scalar_plus_assign> (*this, ae);
00170             return *this;
00171         }
00172         template<class AE>
00173         BOOST_UBLAS_INLINE
00174         vector_range &operator -= (const vector_expression<AE> &ae) {
00175             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
00176             return *this;
00177         }
00178         template<class AE>
00179         BOOST_UBLAS_INLINE
00180         vector_range &minus_assign (const vector_expression<AE> &ae) {
00181             vector_assign<scalar_minus_assign> (*this, ae);
00182             return *this;
00183         }
00184         template<class AT>
00185         BOOST_UBLAS_INLINE
00186         vector_range &operator *= (const AT &at) {
00187             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
00188             return *this;
00189         }
00190         template<class AT>
00191         BOOST_UBLAS_INLINE
00192         vector_range &operator /= (const AT &at) {
00193             vector_assign_scalar<scalar_divides_assign> (*this, at);
00194             return *this;
00195         }
00196 
00197         // Closure comparison
00198         BOOST_UBLAS_INLINE
00199         bool same_closure (const vector_range &vr) const {
00200             return (*this).data_.same_closure (vr.data_);
00201         }
00202 
00203         // Comparison
00204         BOOST_UBLAS_INLINE
00205         bool operator == (const vector_range &vr) const {
00206             return (*this).data_ == vr.data_ && r_ == vr.r_;
00207         }
00208 
00209         // Swapping
00210         BOOST_UBLAS_INLINE
00211         void swap (vector_range vr) {
00212             if (this != &vr) {
00213                 BOOST_UBLAS_CHECK (size () == vr.size (), bad_size ());
00214                 // Sparse ranges may be nonconformant now.
00215                 // std::swap_ranges (begin (), end (), vr.begin ());
00216                 vector_swap<scalar_swap> (*this, vr);
00217             }
00218         }
00219         BOOST_UBLAS_INLINE
00220         friend void swap (vector_range vr1, vector_range vr2) {
00221             vr1.swap (vr2);
00222         }
00223 
00224         // Iterator types
00225     private:
00226         typedef typename V::const_iterator const_subiterator_type;
00227         typedef typename boost::mpl::if_<boost::is_const<V>,
00228                                           typename V::const_iterator,
00229                                           typename V::iterator>::type subiterator_type;
00230 
00231     public:
00232 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00233         typedef indexed_iterator<vector_range<vector_type>,
00234                                  typename subiterator_type::iterator_category> iterator;
00235         typedef indexed_const_iterator<vector_range<vector_type>,
00236                                        typename const_subiterator_type::iterator_category> const_iterator;
00237 #else
00238         class const_iterator;
00239         class iterator;
00240 #endif
00241 
00242         // Element lookup
00243         BOOST_UBLAS_INLINE
00244         const_iterator find (size_type i) const {
00245             const_subiterator_type it (data_.find (start () + i));
00246 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00247             return const_iterator (*this, it.index ());
00248 #else
00249             return const_iterator (*this, it);
00250 #endif
00251         }
00252         BOOST_UBLAS_INLINE
00253         iterator find (size_type i) {
00254             subiterator_type it (data_.find (start () + i));
00255 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00256             return iterator (*this, it.index ());
00257 #else
00258             return iterator (*this, it);
00259 #endif
00260         }
00261 
00262 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
00263         class const_iterator:
00264             public container_const_reference<vector_range>,
00265             public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
00266                         iterator_base<const_iterator, value_type>::type {
00267         public:
00268             typedef typename const_subiterator_type::difference_type difference_type;
00269             typedef typename const_subiterator_type::value_type value_type;
00270             typedef typename const_subiterator_type::reference reference;
00271             typedef typename const_subiterator_type::pointer pointer;
00272 
00273             // Construction and destruction
00274             BOOST_UBLAS_INLINE
00275             const_iterator ():
00276                 container_const_reference<self_type> (), it_ () {}
00277             BOOST_UBLAS_INLINE
00278             const_iterator (const self_type &vr, const const_subiterator_type &it):
00279                 container_const_reference<self_type> (vr), it_ (it) {}
00280             BOOST_UBLAS_INLINE
00281             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
00282                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
00283 
00284             // Arithmetic
00285             BOOST_UBLAS_INLINE
00286             const_iterator &operator ++ () {
00287                 ++ it_;
00288                 return *this;
00289             }
00290             BOOST_UBLAS_INLINE
00291             const_iterator &operator -- () {
00292                 -- it_;
00293                 return *this;
00294             }
00295             BOOST_UBLAS_INLINE
00296             const_iterator &operator += (difference_type n) {
00297                 it_ += n;
00298                 return *this;
00299             }
00300             BOOST_UBLAS_INLINE
00301             const_iterator &operator -= (difference_type n) {
00302                 it_ -= n;
00303                 return *this;
00304             }
00305             BOOST_UBLAS_INLINE
00306             difference_type operator - (const const_iterator &it) const {
00307                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00308                 return it_ - it.it_;
00309             }
00310 
00311             // Dereference
00312             BOOST_UBLAS_INLINE
00313             const_reference operator * () const {
00314                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
00315                 return *it_;
00316             }
00317             BOOST_UBLAS_INLINE
00318             const_reference operator [] (difference_type n) const {
00319                 return *(*this + n);
00320             }
00321 
00322             // Index
00323             BOOST_UBLAS_INLINE
00324             size_type index () const {
00325                 return it_.index () - (*this) ().start ();
00326             }
00327 
00328             // Assignment
00329             BOOST_UBLAS_INLINE
00330             const_iterator &operator = (const const_iterator &it) {
00331                 container_const_reference<self_type>::assign (&it ());
00332                 it_ = it.it_;
00333                 return *this;
00334             }
00335 
00336             // Comparison
00337             BOOST_UBLAS_INLINE
00338             bool operator == (const const_iterator &it) const {
00339                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00340                 return it_ == it.it_;
00341             }
00342             BOOST_UBLAS_INLINE
00343             bool operator < (const const_iterator &it) const {
00344                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00345                 return it_ < it.it_;
00346             }
00347 
00348         private:
00349             const_subiterator_type it_;
00350         };
00351 #endif
00352 
00353         BOOST_UBLAS_INLINE
00354         const_iterator begin () const {
00355             return find (0);
00356         }
00357         BOOST_UBLAS_INLINE
00358         const_iterator end () const {
00359             return find (size ());
00360         }
00361 
00362 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
00363         class iterator:
00364             public container_reference<vector_range>,
00365             public iterator_base_traits<typename subiterator_type::iterator_category>::template
00366                         iterator_base<iterator, value_type>::type {
00367         public:
00368             typedef typename subiterator_type::difference_type difference_type;
00369             typedef typename subiterator_type::value_type value_type;
00370             typedef typename subiterator_type::reference reference;
00371             typedef typename subiterator_type::pointer pointer;
00372 
00373             // Construction and destruction
00374             BOOST_UBLAS_INLINE
00375             iterator ():
00376                 container_reference<self_type> (), it_ () {}
00377             BOOST_UBLAS_INLINE
00378             iterator (self_type &vr, const subiterator_type &it):
00379                 container_reference<self_type> (vr), it_ (it) {}
00380 
00381             // Arithmetic
00382             BOOST_UBLAS_INLINE
00383             iterator &operator ++ () {
00384                 ++ it_;
00385                 return *this;
00386             }
00387             BOOST_UBLAS_INLINE
00388             iterator &operator -- () {
00389                 -- it_;
00390                 return *this;
00391             }
00392             BOOST_UBLAS_INLINE
00393             iterator &operator += (difference_type n) {
00394                 it_ += n;
00395                 return *this;
00396             }
00397             BOOST_UBLAS_INLINE
00398             iterator &operator -= (difference_type n) {
00399                 it_ -= n;
00400                 return *this;
00401             }
00402             BOOST_UBLAS_INLINE
00403             difference_type operator - (const iterator &it) const {
00404                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00405                 return it_ - it.it_;
00406             }
00407 
00408             // Dereference
00409             BOOST_UBLAS_INLINE
00410             reference operator * () const {
00411                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
00412                 return *it_;
00413             }
00414             BOOST_UBLAS_INLINE
00415             reference operator [] (difference_type n) const {
00416                 return *(*this + n);
00417             }
00418 
00419             // Index
00420             BOOST_UBLAS_INLINE
00421             size_type index () const {
00422                 return it_.index () - (*this) ().start ();
00423             }
00424 
00425             // Assignment
00426             BOOST_UBLAS_INLINE
00427             iterator &operator = (const iterator &it) {
00428                 container_reference<self_type>::assign (&it ());
00429                 it_ = it.it_;
00430                 return *this;
00431             }
00432 
00433             // Comparison
00434             BOOST_UBLAS_INLINE
00435             bool operator == (const iterator &it) const {
00436                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00437                 return it_ == it.it_;
00438             }
00439             BOOST_UBLAS_INLINE
00440             bool operator < (const iterator &it) const {
00441                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00442                 return it_ < it.it_;
00443             }
00444 
00445         private:
00446             subiterator_type it_;
00447 
00448             friend class const_iterator;
00449         };
00450 #endif
00451 
00452         BOOST_UBLAS_INLINE
00453         iterator begin () {
00454             return find (0);
00455         }
00456         BOOST_UBLAS_INLINE
00457         iterator end () {
00458             return find (size ());
00459         }
00460 
00461         // Reverse iterator
00462         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
00463         typedef reverse_iterator_base<iterator> reverse_iterator;
00464 
00465         BOOST_UBLAS_INLINE
00466         const_reverse_iterator rbegin () const {
00467             return const_reverse_iterator (end ());
00468         }
00469         BOOST_UBLAS_INLINE
00470         const_reverse_iterator rend () const {
00471             return const_reverse_iterator (begin ());
00472         }
00473         BOOST_UBLAS_INLINE
00474         reverse_iterator rbegin () {
00475             return reverse_iterator (end ());
00476         }
00477         BOOST_UBLAS_INLINE
00478         reverse_iterator rend () {
00479             return reverse_iterator (begin ());
00480         }
00481 
00482     private:
00483         vector_closure_type data_;
00484         range_type r_;
00485     };
00486 
00487     // ------------------
00488     // Simple Projections
00489     // ------------------
00490 
00496     template<class V>
00497     BOOST_UBLAS_INLINE
00498     vector_range<V> subrange (V &data, typename V::size_type start, typename V::size_type stop) {
00499         typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
00500         return vector_range<V> (data, range_type (start, stop));
00501     }
00502 
00508     template<class V>
00509     BOOST_UBLAS_INLINE
00510     vector_range<const V> subrange (const V &data, typename V::size_type start, typename V::size_type stop) {
00511         typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
00512         return vector_range<const V> (data, range_type (start, stop));
00513     }
00514 
00515     // -------------------
00516     // Generic Projections
00517     // -------------------
00518     
00524     template<class V>
00525     BOOST_UBLAS_INLINE
00526     vector_range<V> project (V &data, typename vector_range<V>::range_type const &r) {
00527         return vector_range<V> (data, r);
00528     }
00529 
00535     template<class V>
00536     BOOST_UBLAS_INLINE
00537     const vector_range<const V> project (const V &data, typename vector_range<V>::range_type const &r) {
00538         // ISSUE was: return vector_range<V> (const_cast<V &> (data), r);
00539         return vector_range<const V> (data, r);
00540    }
00541 
00547     template<class V>
00548     BOOST_UBLAS_INLINE
00549     vector_range<V> project (vector_range<V> &data, const typename vector_range<V>::range_type &r) {
00550         return data.project (r);
00551     }
00552 
00558     template<class V>
00559     BOOST_UBLAS_INLINE
00560     const vector_range<V> project (const vector_range<V> &data, const typename vector_range<V>::range_type &r) {
00561         return data.project (r);
00562     }
00563 
00564     // Specialization of temporary_traits
00565     template <class V>
00566     struct vector_temporary_traits< vector_range<V> >
00567     : vector_temporary_traits< V > {} ;
00568     template <class V>
00569     struct vector_temporary_traits< const vector_range<V> >
00570     : vector_temporary_traits< V > {} ;
00571 
00572 
00587     template<class V>
00588     class vector_slice:
00589         public vector_expression<vector_slice<V> > {
00590 
00591         typedef vector_slice<V> self_type;
00592     public:
00593 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
00594         using vector_expression<self_type>::operator ();
00595 #endif
00596         typedef const V const_vector_type;
00597         typedef V vector_type;
00598         typedef typename V::size_type size_type;
00599         typedef typename V::difference_type difference_type;
00600         typedef typename V::value_type value_type;
00601         typedef typename V::const_reference const_reference;
00602         typedef typename boost::mpl::if_<boost::is_const<V>,
00603                                           typename V::const_reference,
00604                                           typename V::reference>::type reference;
00605         typedef typename boost::mpl::if_<boost::is_const<V>,
00606                                           typename V::const_closure_type,
00607                                           typename V::closure_type>::type vector_closure_type;
00608         typedef basic_range<size_type, difference_type> range_type;
00609         typedef basic_slice<size_type, difference_type> slice_type;
00610         typedef const self_type const_closure_type;
00611         typedef self_type closure_type;
00612         typedef typename storage_restrict_traits<typename V::storage_category,
00613                                                  dense_proxy_tag>::storage_category storage_category;
00614 
00615         // Construction and destruction
00616         BOOST_UBLAS_INLINE
00617         vector_slice (vector_type &data, const slice_type &s):
00618             data_ (data), s_ (s.preprocess (data.size ())) {
00619             // Early checking of preconditions here.
00620             // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
00621             //                    s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
00622         }
00623         BOOST_UBLAS_INLINE
00624         vector_slice (const vector_closure_type &data, const slice_type &s, int):
00625             data_ (data), s_ (s.preprocess (data.size ())) {
00626             // Early checking of preconditions here.
00627             // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
00628             //                    s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
00629         }
00630 
00631         // Accessors
00632         BOOST_UBLAS_INLINE
00633         size_type start () const {
00634             return s_.start ();
00635         }
00636         BOOST_UBLAS_INLINE
00637         difference_type stride () const {
00638             return s_.stride ();
00639         }
00640         BOOST_UBLAS_INLINE
00641         size_type size () const {
00642             return s_.size ();
00643         }
00644 
00645         // Storage accessors
00646         BOOST_UBLAS_INLINE
00647         const vector_closure_type &data () const {
00648             return data_;
00649         }
00650         BOOST_UBLAS_INLINE
00651         vector_closure_type &data () {
00652             return data_;
00653         }
00654 
00655         // Element access
00656 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
00657         BOOST_UBLAS_INLINE
00658         const_reference operator () (size_type i) const {
00659             return data_ (s_ (i));
00660         }
00661         BOOST_UBLAS_INLINE
00662         reference operator () (size_type i) {
00663             return data_ (s_ (i));
00664         }
00665 
00666         BOOST_UBLAS_INLINE
00667         const_reference operator [] (size_type i) const {
00668             return (*this) (i);
00669         }
00670         BOOST_UBLAS_INLINE
00671         reference operator [] (size_type i) {
00672             return (*this) (i);
00673         }
00674 #else
00675         BOOST_UBLAS_INLINE
00676         reference operator () (size_type i) const {
00677             return data_ (s_ (i));
00678         }
00679 
00680         BOOST_UBLAS_INLINE
00681         reference operator [] (size_type i) const {
00682             return (*this) (i);
00683         }
00684 #endif
00685 
00686         // ISSUE can this be done in free project function?
00687         // Although a const function can create a non-const proxy to a non-const object
00688         // Critical is that vector_type and data_ (vector_closure_type) are const correct
00689         BOOST_UBLAS_INLINE
00690         vector_slice<vector_type> project (const range_type &r) const {
00691             return vector_slice<vector_type>  (data_, s_.compose (r.preprocess (data_.size ())), false);
00692         }
00693         BOOST_UBLAS_INLINE
00694         vector_slice<vector_type> project (const slice_type &s) const {
00695             return vector_slice<vector_type>  (data_, s_.compose (s.preprocess (data_.size ())), false);
00696         }
00697 
00698         // Assignment
00699         BOOST_UBLAS_INLINE
00700         vector_slice &operator = (const vector_slice &vs) {
00701             // ISSUE need a temporary, proxy can be overlaping alias
00702             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vs));
00703             return *this;
00704         }
00705         BOOST_UBLAS_INLINE
00706         vector_slice &assign_temporary (vector_slice &vs) {
00707             // assign elements, proxied container remains the same
00708             vector_assign<scalar_assign> (*this, vs);
00709             return *this;
00710         }
00711         template<class AE>
00712         BOOST_UBLAS_INLINE
00713         vector_slice &operator = (const vector_expression<AE> &ae) {
00714             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
00715             return *this;
00716         }
00717         template<class AE>
00718         BOOST_UBLAS_INLINE
00719         vector_slice &assign (const vector_expression<AE> &ae) {
00720             vector_assign<scalar_assign> (*this, ae);
00721             return *this;
00722         }
00723         template<class AE>
00724         BOOST_UBLAS_INLINE
00725         vector_slice &operator += (const vector_expression<AE> &ae) {
00726             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
00727             return *this;
00728         }
00729         template<class AE>
00730         BOOST_UBLAS_INLINE
00731         vector_slice &plus_assign (const vector_expression<AE> &ae) {
00732             vector_assign<scalar_plus_assign> (*this, ae);
00733             return *this;
00734         }
00735         template<class AE>
00736         BOOST_UBLAS_INLINE
00737         vector_slice &operator -= (const vector_expression<AE> &ae) {
00738             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
00739             return *this;
00740         }
00741         template<class AE>
00742         BOOST_UBLAS_INLINE
00743         vector_slice &minus_assign (const vector_expression<AE> &ae) {
00744             vector_assign<scalar_minus_assign> (*this, ae);
00745             return *this;
00746         }
00747         template<class AT>
00748         BOOST_UBLAS_INLINE
00749         vector_slice &operator *= (const AT &at) {
00750             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
00751             return *this;
00752         }
00753         template<class AT>
00754         BOOST_UBLAS_INLINE
00755         vector_slice &operator /= (const AT &at) {
00756             vector_assign_scalar<scalar_divides_assign> (*this, at);
00757             return *this;
00758         }
00759 
00760         // Closure comparison
00761         BOOST_UBLAS_INLINE
00762         bool same_closure (const vector_slice &vr) const {
00763             return (*this).data_.same_closure (vr.data_);
00764         }
00765 
00766         // Comparison
00767         BOOST_UBLAS_INLINE
00768         bool operator == (const vector_slice &vs) const {
00769             return (*this).data_ == vs.data_ && s_ == vs.s_;
00770         }
00771 
00772         // Swapping
00773         BOOST_UBLAS_INLINE
00774         void swap (vector_slice vs) {
00775             if (this != &vs) {
00776                 BOOST_UBLAS_CHECK (size () == vs.size (), bad_size ());
00777                 // Sparse ranges may be nonconformant now.
00778                 // std::swap_ranges (begin (), end (), vs.begin ());
00779                 vector_swap<scalar_swap> (*this, vs);
00780             }
00781         }
00782         BOOST_UBLAS_INLINE
00783         friend void swap (vector_slice vs1, vector_slice vs2) {
00784             vs1.swap (vs2);
00785         }
00786 
00787         // Iterator types
00788     private:
00789         // Use slice as an index - FIXME this fails for packed assignment
00790         typedef typename slice_type::const_iterator const_subiterator_type;
00791         typedef typename slice_type::const_iterator subiterator_type;
00792 
00793     public:
00794 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00795         typedef indexed_iterator<vector_slice<vector_type>,
00796                                  typename vector_type::iterator::iterator_category> iterator;
00797         typedef indexed_const_iterator<vector_slice<vector_type>,
00798                                        typename vector_type::const_iterator::iterator_category> const_iterator;
00799 #else
00800         class const_iterator;
00801         class iterator;
00802 #endif
00803 
00804         // Element lookup
00805         BOOST_UBLAS_INLINE
00806         const_iterator find (size_type i) const {
00807 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00808             return const_iterator (*this, i);
00809 #else
00810             return const_iterator (*this, s_.begin () + i);
00811 #endif
00812         }
00813         BOOST_UBLAS_INLINE
00814         iterator find (size_type i) {
00815 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
00816             return iterator (*this, i);
00817 #else
00818             return iterator (*this, s_.begin () + i);
00819 #endif
00820         }
00821 
00822 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
00823         class const_iterator:
00824             public container_const_reference<vector_slice>,
00825             public iterator_base_traits<typename V::const_iterator::iterator_category>::template
00826                         iterator_base<const_iterator, value_type>::type {
00827         public:
00828             typedef typename V::const_iterator::difference_type difference_type;
00829             typedef typename V::const_iterator::value_type value_type;
00830             typedef typename V::const_reference reference;    //FIXME due to indexing access
00831             typedef typename V::const_iterator::pointer pointer;
00832 
00833             // Construction and destruction
00834             BOOST_UBLAS_INLINE
00835             const_iterator ():
00836                 container_const_reference<self_type> (), it_ () {}
00837             BOOST_UBLAS_INLINE
00838             const_iterator (const self_type &vs, const const_subiterator_type &it):
00839                 container_const_reference<self_type> (vs), it_ (it) {}
00840             BOOST_UBLAS_INLINE
00841             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
00842                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
00843 
00844             // Arithmetic
00845             BOOST_UBLAS_INLINE
00846             const_iterator &operator ++ () {
00847                 ++ it_;
00848                 return *this;
00849             }
00850             BOOST_UBLAS_INLINE
00851             const_iterator &operator -- () {
00852                 -- it_;
00853                 return *this;
00854             }
00855             BOOST_UBLAS_INLINE
00856             const_iterator &operator += (difference_type n) {
00857                 it_ += n;
00858                 return *this;
00859             }
00860             BOOST_UBLAS_INLINE
00861             const_iterator &operator -= (difference_type n) {
00862                 it_ -= n;
00863                 return *this;
00864             }
00865             BOOST_UBLAS_INLINE
00866             difference_type operator - (const const_iterator &it) const {
00867                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00868                 return it_ - it.it_;
00869             }
00870 
00871             // Dereference
00872             BOOST_UBLAS_INLINE
00873             const_reference operator * () const {
00874                 // FIXME replace find with at_element
00875                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
00876                 return (*this) ().data_ (*it_);
00877             }
00878             BOOST_UBLAS_INLINE
00879             const_reference operator [] (difference_type n) const {
00880                 return *(*this + n);
00881             }
00882 
00883             // Index
00884             BOOST_UBLAS_INLINE
00885             size_type index () const {
00886                 return it_.index ();
00887             }
00888 
00889             // Assignment
00890             BOOST_UBLAS_INLINE
00891             const_iterator &operator = (const const_iterator &it) {
00892                 container_const_reference<self_type>::assign (&it ());
00893                 it_ = it.it_;
00894                 return *this;
00895             }
00896 
00897             // Comparison
00898             BOOST_UBLAS_INLINE
00899             bool operator == (const const_iterator &it) const {
00900                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00901                 return it_ == it.it_;
00902             }
00903             BOOST_UBLAS_INLINE
00904             bool operator < (const const_iterator &it) const {
00905                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00906                 return it_ < it.it_;
00907             }
00908 
00909         private:
00910             const_subiterator_type it_;
00911         };
00912 #endif
00913 
00914         BOOST_UBLAS_INLINE
00915         const_iterator begin () const {
00916             return find (0);
00917         }
00918         BOOST_UBLAS_INLINE
00919         const_iterator end () const {
00920             return find (size ());
00921         }
00922 
00923 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
00924         class iterator:
00925             public container_reference<vector_slice>,
00926             public iterator_base_traits<typename V::iterator::iterator_category>::template
00927                         iterator_base<iterator, value_type>::type {
00928         public:
00929             typedef typename V::iterator::difference_type difference_type;
00930             typedef typename V::iterator::value_type value_type;
00931             typedef typename V::reference reference;    //FIXME due to indexing access
00932             typedef typename V::iterator::pointer pointer;
00933 
00934             // Construction and destruction
00935             BOOST_UBLAS_INLINE
00936             iterator ():
00937                 container_reference<self_type> (), it_ () {}
00938             BOOST_UBLAS_INLINE
00939             iterator (self_type &vs, const subiterator_type &it):
00940                 container_reference<self_type> (vs), it_ (it) {}
00941 
00942             // Arithmetic
00943             BOOST_UBLAS_INLINE
00944             iterator &operator ++ () {
00945                 ++ it_;
00946                 return *this;
00947             }
00948             BOOST_UBLAS_INLINE
00949             iterator &operator -- () {
00950                 -- it_;
00951                 return *this;
00952             }
00953             BOOST_UBLAS_INLINE
00954             iterator &operator += (difference_type n) {
00955                 it_ += n;
00956                 return *this;
00957             }
00958             BOOST_UBLAS_INLINE
00959             iterator &operator -= (difference_type n) {
00960                 it_ -= n;
00961                 return *this;
00962             }
00963             BOOST_UBLAS_INLINE
00964             difference_type operator - (const iterator &it) const {
00965                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
00966                 return it_ - it.it_;
00967             }
00968 
00969             // Dereference
00970             BOOST_UBLAS_INLINE
00971             reference operator * () const {
00972                 // FIXME replace find with at_element
00973                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
00974                 return (*this) ().data_ (*it_);
00975             }
00976             BOOST_UBLAS_INLINE
00977             reference operator [] (difference_type n) const {
00978                 return *(*this + n);
00979             }
00980 
00981 
00982             // Index
00983             BOOST_UBLAS_INLINE
00984             size_type index () const {
00985                 return it_.index ();
00986             }
00987 
00988             // Assignment
00989             BOOST_UBLAS_INLINE
00990             iterator &operator = (const iterator &it) {
00991                 container_reference<self_type>::assign (&it ());
00992                 it_ = it.it_;
00993                 return *this;
00994             }
00995 
00996             // Comparison
00997             BOOST_UBLAS_INLINE
00998             bool operator == (const iterator &it) const {
00999                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01000                 return it_ == it.it_;
01001             }
01002             BOOST_UBLAS_INLINE
01003             bool operator < (const iterator &it) const {
01004                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01005                 return it_ < it.it_;
01006             }
01007 
01008         private:
01009             subiterator_type it_;
01010 
01011             friend class const_iterator;
01012         };
01013 #endif
01014 
01015         BOOST_UBLAS_INLINE
01016         iterator begin () {
01017             return find (0);
01018         }
01019         BOOST_UBLAS_INLINE
01020         iterator end () {
01021             return find (size ());
01022         }
01023 
01024         // Reverse iterator
01025         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
01026         typedef reverse_iterator_base<iterator> reverse_iterator;
01027 
01028         BOOST_UBLAS_INLINE
01029         const_reverse_iterator rbegin () const {
01030             return const_reverse_iterator (end ());
01031         }
01032         BOOST_UBLAS_INLINE
01033         const_reverse_iterator rend () const {
01034             return const_reverse_iterator (begin ());
01035         }
01036         BOOST_UBLAS_INLINE
01037         reverse_iterator rbegin () {
01038             return reverse_iterator (end ());
01039         }
01040         BOOST_UBLAS_INLINE
01041         reverse_iterator rend () {
01042             return reverse_iterator (begin ());
01043         }
01044 
01045     private:
01046         vector_closure_type data_;
01047         slice_type s_;
01048     };
01049 
01050     // Simple Projections
01051     template<class V>
01052     BOOST_UBLAS_INLINE
01053     vector_slice<V> subslice (V &data, typename V::size_type start, typename V::difference_type stride, typename V::size_type size) {
01054         typedef basic_slice<typename V::size_type, typename V::difference_type> slice_type;
01055         return vector_slice<V> (data, slice_type (start, stride, size));
01056     }
01057     template<class V>
01058     BOOST_UBLAS_INLINE
01059     vector_slice<const V> subslice (const V &data, typename V::size_type start, typename V::difference_type stride, typename V::size_type size)  {
01060         typedef basic_slice<typename V::size_type, typename V::difference_type> slice_type;
01061         return vector_slice<const V> (data, slice_type (start, stride, size));
01062     }
01063 
01064     // Generic Projections
01065     template<class V>
01066     BOOST_UBLAS_INLINE
01067     vector_slice<V> project (V &data, const typename vector_slice<V>::slice_type &s) {
01068         return vector_slice<V> (data, s);
01069     }
01070     template<class V>
01071     BOOST_UBLAS_INLINE
01072     const vector_slice<const V> project (const V &data, const typename vector_slice<V>::slice_type &s) {
01073         // ISSUE was: return vector_slice<V> (const_cast<V &> (data), s);
01074         return vector_slice<const V> (data, s);
01075     }
01076     template<class V>
01077     BOOST_UBLAS_INLINE
01078     vector_slice<V> project (vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
01079         return data.project (s);
01080     }
01081     template<class V>
01082     BOOST_UBLAS_INLINE
01083     const vector_slice<V> project (const vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
01084         return data.project (s);
01085     }
01086     // ISSUE in the following two functions it would be logical to use vector_slice<V>::range_type but this confuses VC7.1 and 8.0
01087     template<class V>
01088     BOOST_UBLAS_INLINE
01089     vector_slice<V> project (vector_slice<V> &data, const typename vector_range<V>::range_type &r) {
01090         return data.project (r);
01091     }
01092     template<class V>
01093     BOOST_UBLAS_INLINE
01094     const vector_slice<V> project (const vector_slice<V> &data, const typename vector_range<V>::range_type &r) {
01095         return data.project (r);
01096     }
01097 
01098     // Specialization of temporary_traits
01099     template <class V>
01100     struct vector_temporary_traits< vector_slice<V> >
01101     : vector_temporary_traits< V > {} ;
01102     template <class V>
01103     struct vector_temporary_traits< const vector_slice<V> >
01104     : vector_temporary_traits< V > {} ;
01105 
01106 
01107     // Vector based indirection class
01108     // Contributed by Toon Knapen.
01109     // Extended and optimized by Kresimir Fresl.
01110 
01130     template<class V, class IA>
01131     class vector_indirect:
01132         public vector_expression<vector_indirect<V, IA> > {
01133 
01134         typedef vector_indirect<V, IA> self_type;
01135     public:
01136 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
01137         using vector_expression<self_type>::operator ();
01138 #endif
01139         typedef const V const_vector_type;
01140         typedef V vector_type;
01141         typedef const IA const_indirect_array_type;
01142         typedef IA indirect_array_type;
01143         typedef typename V::size_type size_type;
01144         typedef typename V::difference_type difference_type;
01145         typedef typename V::value_type value_type;
01146         typedef typename V::const_reference const_reference;
01147         typedef typename boost::mpl::if_<boost::is_const<V>,
01148                                           typename V::const_reference,
01149                                           typename V::reference>::type reference;
01150         typedef typename boost::mpl::if_<boost::is_const<V>,
01151                                           typename V::const_closure_type,
01152                                           typename V::closure_type>::type vector_closure_type;
01153         typedef basic_range<size_type, difference_type> range_type;
01154         typedef basic_slice<size_type, difference_type> slice_type;
01155         typedef const self_type const_closure_type;
01156         typedef self_type closure_type;
01157         typedef typename storage_restrict_traits<typename V::storage_category,
01158                                                  dense_proxy_tag>::storage_category storage_category;
01159 
01160         // Construction and destruction
01161         BOOST_UBLAS_INLINE
01162         vector_indirect (vector_type &data, size_type size):
01163             data_ (data), ia_ (size) {}
01164         BOOST_UBLAS_INLINE
01165         vector_indirect (vector_type &data, const indirect_array_type &ia):
01166             data_ (data), ia_ (ia.preprocess (data.size ())) {}
01167         BOOST_UBLAS_INLINE
01168         vector_indirect (const vector_closure_type &data, const indirect_array_type &ia, int):
01169             data_ (data), ia_ (ia.preprocess (data.size ())) {}
01170 
01171         // Accessors
01172         BOOST_UBLAS_INLINE
01173         size_type size () const {
01174             return ia_.size ();
01175         }
01176         BOOST_UBLAS_INLINE
01177         const_indirect_array_type &indirect () const {
01178             return ia_;
01179         }
01180         BOOST_UBLAS_INLINE
01181         indirect_array_type &indirect () {
01182             return ia_;
01183         }
01184 
01185         // Storage accessors
01186         BOOST_UBLAS_INLINE
01187         const vector_closure_type &data () const {
01188             return data_;
01189         }
01190         BOOST_UBLAS_INLINE
01191         vector_closure_type &data () {
01192             return data_;
01193         }
01194 
01195         // Element access
01196 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
01197         BOOST_UBLAS_INLINE
01198         const_reference operator () (size_type i) const {
01199             return data_ (ia_ (i));
01200         }
01201         BOOST_UBLAS_INLINE
01202         reference operator () (size_type i) {
01203             return data_ (ia_ (i));
01204         }
01205 
01206         BOOST_UBLAS_INLINE
01207         const_reference operator [] (size_type i) const {
01208             return (*this) (i);
01209         }
01210         BOOST_UBLAS_INLINE
01211         reference operator [] (size_type i) {
01212             return (*this) (i);
01213         }
01214 #else
01215         BOOST_UBLAS_INLINE
01216         reference operator () (size_type i) const {
01217             return data_ (ia_ (i));
01218         }
01219 
01220         BOOST_UBLAS_INLINE
01221         reference operator [] (size_type i) const {
01222             return (*this) (i);
01223         }
01224 #endif
01225 
01226         // ISSUE can this be done in free project function?
01227         // Although a const function can create a non-const proxy to a non-const object
01228         // Critical is that vector_type and data_ (vector_closure_type) are const correct
01229         BOOST_UBLAS_INLINE
01230         vector_indirect<vector_type, indirect_array_type> project (const range_type &r) const {
01231             return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (r.preprocess (data_.size ())), 0);
01232         }
01233         BOOST_UBLAS_INLINE
01234         vector_indirect<vector_type, indirect_array_type> project (const slice_type &s) const {
01235             return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (s.preprocess (data_.size ())), 0);
01236         }
01237         BOOST_UBLAS_INLINE
01238         vector_indirect<vector_type, indirect_array_type> project (const indirect_array_type &ia) const {
01239             return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (ia.preprocess (data_.size ())), 0);
01240         }
01241 
01242         // Assignment
01243         BOOST_UBLAS_INLINE
01244         vector_indirect &operator = (const vector_indirect &vi) {
01245             // ISSUE need a temporary, proxy can be overlaping alias
01246             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vi));
01247             return *this;
01248         }
01249         BOOST_UBLAS_INLINE
01250         vector_indirect &assign_temporary (vector_indirect &vi) {
01251             // assign elements, proxied container remains the same
01252             vector_assign<scalar_assign> (*this, vi);
01253             return *this;
01254         }
01255         template<class AE>
01256         BOOST_UBLAS_INLINE
01257         vector_indirect &operator = (const vector_expression<AE> &ae) {
01258             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
01259             return *this;
01260         }
01261         template<class AE>
01262         BOOST_UBLAS_INLINE
01263         vector_indirect &assign (const vector_expression<AE> &ae) {
01264             vector_assign<scalar_assign> (*this, ae);
01265             return *this;
01266         }
01267         template<class AE>
01268         BOOST_UBLAS_INLINE
01269         vector_indirect &operator += (const vector_expression<AE> &ae) {
01270             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
01271             return *this;
01272         }
01273         template<class AE>
01274         BOOST_UBLAS_INLINE
01275         vector_indirect &plus_assign (const vector_expression<AE> &ae) {
01276             vector_assign<scalar_plus_assign> (*this, ae);
01277             return *this;
01278         }
01279         template<class AE>
01280         BOOST_UBLAS_INLINE
01281         vector_indirect &operator -= (const vector_expression<AE> &ae) {
01282             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
01283             return *this;
01284         }
01285         template<class AE>
01286         BOOST_UBLAS_INLINE
01287         vector_indirect &minus_assign (const vector_expression<AE> &ae) {
01288             vector_assign<scalar_minus_assign> (*this, ae);
01289             return *this;
01290         }
01291         template<class AT>
01292         BOOST_UBLAS_INLINE
01293         vector_indirect &operator *= (const AT &at) {
01294             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
01295             return *this;
01296         }
01297         template<class AT>
01298         BOOST_UBLAS_INLINE
01299         vector_indirect &operator /= (const AT &at) {
01300             vector_assign_scalar<scalar_divides_assign> (*this, at);
01301             return *this;
01302         }
01303 
01304         // Closure comparison
01305         BOOST_UBLAS_INLINE
01306         bool same_closure (const vector_indirect &vr) const {
01307 return true;
01308         }
01309 
01310         // Comparison
01311         BOOST_UBLAS_INLINE
01312         bool operator == (const vector_indirect &vi) const {
01313             return (*this).data_ == vi.data_ && ia_ == vi.ia_;
01314         }
01315 
01316         // Swapping
01317         BOOST_UBLAS_INLINE
01318         void swap (vector_indirect vi) {
01319             if (this != &vi) {
01320                 BOOST_UBLAS_CHECK (size () == vi.size (), bad_size ());
01321                 // Sparse ranges may be nonconformant now.
01322                 // std::swap_ranges (begin (), end (), vi.begin ());
01323                 vector_swap<scalar_swap> (*this, vi);
01324             }
01325         }
01326         BOOST_UBLAS_INLINE
01327         friend void swap (vector_indirect vi1, vector_indirect vi2) {
01328             vi1.swap (vi2);
01329         }
01330 
01331         // Iterator types
01332     private:
01333         // Use indirect array as an index - FIXME this fails for packed assignment
01334         typedef typename IA::const_iterator const_subiterator_type;
01335         typedef typename IA::const_iterator subiterator_type;
01336 
01337     public:
01338 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
01339         typedef indexed_iterator<vector_indirect<vector_type, indirect_array_type>,
01340                                  typename vector_type::iterator::iterator_category> iterator;
01341         typedef indexed_const_iterator<vector_indirect<vector_type, indirect_array_type>,
01342                                        typename vector_type::const_iterator::iterator_category> const_iterator;
01343 #else
01344         class const_iterator;
01345         class iterator;
01346 #endif
01347         // Element lookup
01348         BOOST_UBLAS_INLINE
01349         const_iterator find (size_type i) const {
01350 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
01351             return const_iterator (*this, i);
01352 #else
01353             return const_iterator (*this, ia_.begin () + i);
01354 #endif
01355         }
01356         BOOST_UBLAS_INLINE
01357         iterator find (size_type i) {
01358 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
01359             return iterator (*this, i);
01360 #else
01361             return iterator (*this, ia_.begin () + i);
01362 #endif
01363         }
01364 
01365         // Iterators simply are indices.
01366 
01367 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
01368         class const_iterator:
01369             public container_const_reference<vector_indirect>,
01370             public iterator_base_traits<typename V::const_iterator::iterator_category>::template
01371                         iterator_base<const_iterator, value_type>::type {
01372         public:
01373             typedef typename V::const_iterator::difference_type difference_type;
01374             typedef typename V::const_iterator::value_type value_type;
01375             typedef typename V::const_reference reference;    //FIXME due to indexing access
01376             typedef typename V::const_iterator::pointer pointer;
01377 
01378             // Construction and destruction
01379             BOOST_UBLAS_INLINE
01380             const_iterator ():
01381                 container_const_reference<self_type> (), it_ () {}
01382             BOOST_UBLAS_INLINE
01383             const_iterator (const self_type &vi, const const_subiterator_type &it):
01384                 container_const_reference<self_type> (vi), it_ (it) {}
01385             BOOST_UBLAS_INLINE
01386             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
01387                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
01388 
01389             // Arithmetic
01390             BOOST_UBLAS_INLINE
01391             const_iterator &operator ++ () {
01392                 ++ it_;
01393                 return *this;
01394             }
01395             BOOST_UBLAS_INLINE
01396             const_iterator &operator -- () {
01397                 -- it_;
01398                 return *this;
01399             }
01400             BOOST_UBLAS_INLINE
01401             const_iterator &operator += (difference_type n) {
01402                 it_ += n;
01403                 return *this;
01404             }
01405             BOOST_UBLAS_INLINE
01406             const_iterator &operator -= (difference_type n) {
01407                 it_ -= n;
01408                 return *this;
01409             }
01410             BOOST_UBLAS_INLINE
01411             difference_type operator - (const const_iterator &it) const {
01412                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01413                 return it_ - it.it_;
01414             }
01415 
01416             // Dereference
01417             BOOST_UBLAS_INLINE
01418             const_reference operator * () const {
01419                 // FIXME replace find with at_element
01420                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
01421                 return (*this) ().data_ (*it_);
01422             }
01423             BOOST_UBLAS_INLINE
01424             const_reference operator [] (difference_type n) const {
01425                 return *(*this + n);
01426             }
01427 
01428             // Index
01429             BOOST_UBLAS_INLINE
01430             size_type index () const {
01431                 return it_.index ();
01432             }
01433 
01434             // Assignment
01435             BOOST_UBLAS_INLINE
01436             const_iterator &operator = (const const_iterator &it) {
01437                 container_const_reference<self_type>::assign (&it ());
01438                 it_ = it.it_;
01439                 return *this;
01440             }
01441 
01442             // Comparison
01443             BOOST_UBLAS_INLINE
01444             bool operator == (const const_iterator &it) const {
01445                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01446                 return it_ == it.it_;
01447             }
01448             BOOST_UBLAS_INLINE
01449             bool operator < (const const_iterator &it) const {
01450                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01451                 return it_ < it.it_;
01452             }
01453 
01454         private:
01455             const_subiterator_type it_;
01456         };
01457 #endif
01458 
01459         BOOST_UBLAS_INLINE
01460         const_iterator begin () const {
01461             return find (0);
01462         }
01463         BOOST_UBLAS_INLINE
01464         const_iterator end () const {
01465             return find (size ());
01466         }
01467 
01468 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
01469         class iterator:
01470             public container_reference<vector_indirect>,
01471             public iterator_base_traits<typename V::iterator::iterator_category>::template
01472                         iterator_base<iterator, value_type>::type {
01473         public:
01474             typedef typename V::iterator::difference_type difference_type;
01475             typedef typename V::iterator::value_type value_type;
01476             typedef typename V::reference reference;    //FIXME due to indexing access
01477             typedef typename V::iterator::pointer pointer;
01478 
01479             // Construction and destruction
01480             BOOST_UBLAS_INLINE
01481             iterator ():
01482                 container_reference<self_type> (), it_ () {}
01483             BOOST_UBLAS_INLINE
01484             iterator (self_type &vi, const subiterator_type &it):
01485                 container_reference<self_type> (vi), it_ (it) {}
01486 
01487             // Arithmetic
01488             BOOST_UBLAS_INLINE
01489             iterator &operator ++ () {
01490                 ++ it_;
01491                 return *this;
01492             }
01493             BOOST_UBLAS_INLINE
01494             iterator &operator -- () {
01495                 -- it_;
01496                 return *this;
01497             }
01498             BOOST_UBLAS_INLINE
01499             iterator &operator += (difference_type n) {
01500                 it_ += n;
01501                 return *this;
01502             }
01503             BOOST_UBLAS_INLINE
01504             iterator &operator -= (difference_type n) {
01505                 it_ -= n;
01506                 return *this;
01507             }
01508             BOOST_UBLAS_INLINE
01509             difference_type operator - (const iterator &it) const {
01510                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01511                 return it_ - it.it_;
01512             }
01513 
01514             // Dereference
01515             BOOST_UBLAS_INLINE
01516             reference operator * () const {
01517                 // FIXME replace find with at_element
01518                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
01519                 return (*this) ().data_ (*it_);
01520             }
01521             BOOST_UBLAS_INLINE
01522             reference operator [] (difference_type n) const {
01523                 return *(*this + n);
01524             }
01525 
01526             // Index
01527             BOOST_UBLAS_INLINE
01528             size_type index () const {
01529                 return it_.index ();
01530             }
01531 
01532             // Assignment
01533             BOOST_UBLAS_INLINE
01534             iterator &operator = (const iterator &it) {
01535                 container_reference<self_type>::assign (&it ());
01536                 it_ = it.it_;
01537                 return *this;
01538             }
01539 
01540             // Comparison
01541             BOOST_UBLAS_INLINE
01542             bool operator == (const iterator &it) const {
01543                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01544                 return it_ == it.it_;
01545             }
01546             BOOST_UBLAS_INLINE
01547             bool operator < (const iterator &it) const {
01548                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
01549                 return it_ < it.it_;
01550             }
01551 
01552         private:
01553             subiterator_type it_;
01554 
01555             friend class const_iterator;
01556         };
01557 #endif
01558 
01559         BOOST_UBLAS_INLINE
01560         iterator begin () {
01561             return find (0);
01562         }
01563         BOOST_UBLAS_INLINE
01564         iterator end () {
01565             return find (size ());
01566         }
01567 
01568         // Reverse iterator
01569         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
01570         typedef reverse_iterator_base<iterator> reverse_iterator;
01571 
01572         BOOST_UBLAS_INLINE
01573         const_reverse_iterator rbegin () const {
01574             return const_reverse_iterator (end ());
01575         }
01576         BOOST_UBLAS_INLINE
01577         const_reverse_iterator rend () const {
01578             return const_reverse_iterator (begin ());
01579         }
01580         BOOST_UBLAS_INLINE
01581         reverse_iterator rbegin () {
01582             return reverse_iterator (end ());
01583         }
01584         BOOST_UBLAS_INLINE
01585         reverse_iterator rend () {
01586             return reverse_iterator (begin ());
01587         }
01588 
01589     private:
01590         vector_closure_type data_;
01591         indirect_array_type ia_;
01592     };
01593 
01594     // Projections
01595     template<class V, class A>
01596     BOOST_UBLAS_INLINE
01597     vector_indirect<V, indirect_array<A> > project (V &data, const indirect_array<A> &ia) {
01598         return vector_indirect<V, indirect_array<A> > (data, ia);
01599     }
01600     template<class V, class A>
01601     BOOST_UBLAS_INLINE
01602     const vector_indirect<const V, indirect_array<A> > project (const V &data, const indirect_array<A> &ia) {
01603         // ISSUE was: return vector_indirect<V, indirect_array<A> > (const_cast<V &> (data), ia)
01604         return vector_indirect<const V, indirect_array<A> > (data, ia);
01605     }
01606     template<class V, class IA>
01607     BOOST_UBLAS_INLINE
01608     vector_indirect<V, IA> project (vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::range_type &r) {
01609         return data.project (r);
01610     }
01611     template<class V, class IA>
01612     BOOST_UBLAS_INLINE
01613     const vector_indirect<V, IA> project (const vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::range_type &r) {
01614         return data.project (r);
01615     }
01616     template<class V, class IA>
01617     BOOST_UBLAS_INLINE
01618     vector_indirect<V, IA> project (vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::slice_type &s) {
01619         return data.project (s);
01620     }
01621     template<class V, class IA>
01622     BOOST_UBLAS_INLINE
01623     const vector_indirect<V, IA> project (const vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::slice_type &s) {
01624         return data.project (s);
01625     }
01626     template<class V, class A>
01627     BOOST_UBLAS_INLINE
01628     vector_indirect<V, indirect_array<A> > project (vector_indirect<V, indirect_array<A> > &data, const indirect_array<A> &ia) {
01629         return data.project (ia);
01630     }
01631     template<class V, class A>
01632     BOOST_UBLAS_INLINE
01633     const vector_indirect<V, indirect_array<A> > project (const vector_indirect<V, indirect_array<A> > &data, const indirect_array<A> &ia) {
01634         return data.project (ia);
01635     }
01636 
01637     // Specialization of temporary_traits
01638     template <class V>
01639     struct vector_temporary_traits< vector_indirect<V> >
01640     : vector_temporary_traits< V > {} ;
01641     template <class V>
01642     struct vector_temporary_traits< const vector_indirect<V> >
01643     : vector_temporary_traits< V > {} ;
01644 
01645 }}}
01646 
01647 #endif