- Main Page
- Related Pages
- Classes
- Files

- File List

# vector_proxy.hpp

    00001 //
    00002 //  Copyright (c) 2000-2002
    00003 //  Joerg Walter, Mathias Koch
    00004 //
    00005 //  Distributed under the Boost Software License, Version 1.0. (See
    00006 //  accompanying file LICENSE_1_0.txt or copy at
    00007 //  http://www.boost.org/LICENSE_1_0.txt)
    00008 //
    00009 //  The authors gratefully acknowledge the support of
    00010 //  GeNeSys mbH & Co. KG in producing this work.
    00011 //
    00012
    00013 #ifndef _BOOST_UBLAS_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