Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:18

0001 //
0002 //  Copyright (c) 2000-2002
0003 //  Joerg Walter, Mathias Koch
0004 //
0005 //  Distributed under the Boost Software License, Version 1.0. (See
0006 //  accompanying file LICENSE_1_0.txt or copy at
0007 //  http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 //  The authors gratefully acknowledge the support of
0010 //  GeNeSys mbH & Co. KG in producing this work.
0011 //
0012 
0013 #ifndef _BOOST_UBLAS_VECTOR_PROXY_
0014 #define _BOOST_UBLAS_VECTOR_PROXY_
0015 
0016 #include <boost/numeric/ublas/vector_expression.hpp>
0017 #include <boost/numeric/ublas/detail/vector_assign.hpp>
0018 #include <boost/numeric/ublas/detail/temporary.hpp>
0019 
0020 // Iterators based on ideas of Jeremy Siek
0021 
0022 namespace boost { namespace numeric { namespace ublas {
0023 
0024     /** \brief A vector referencing a continuous subvector of elements of vector \c v containing all elements specified by \c range.
0025      *
0026      * A vector range can be used as a normal vector in any expression. 
0027      * If the specified range falls outside that of the index range of the vector, then
0028      * the \c vector_range is not a well formed \i Vector \i Expression and access to an 
0029      * element outside of index range of the vector is \b undefined.
0030      *
0031      * \tparam V the type of vector referenced (for example \c vector<double>)
0032      */
0033     template<class V>
0034     class vector_range:
0035         public vector_expression<vector_range<V> > {
0036 
0037         typedef vector_range<V> self_type;
0038     public:
0039 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
0040         using vector_expression<self_type>::operator ();
0041 #endif
0042         typedef const V const_vector_type;
0043         typedef V vector_type;
0044         typedef typename V::size_type size_type;
0045         typedef typename V::difference_type difference_type;
0046         typedef typename V::value_type value_type;
0047         typedef typename V::const_reference const_reference;
0048         typedef typename boost::mpl::if_<boost::is_const<V>,
0049                                           typename V::const_reference,
0050                                           typename V::reference>::type reference;
0051         typedef typename boost::mpl::if_<boost::is_const<V>,
0052                                           typename V::const_closure_type,
0053                                           typename V::closure_type>::type vector_closure_type;
0054         typedef basic_range<size_type, difference_type> range_type;
0055         typedef const self_type const_closure_type;
0056         typedef self_type closure_type;
0057         typedef typename storage_restrict_traits<typename V::storage_category,
0058                                                  dense_proxy_tag>::storage_category storage_category;
0059 
0060         // Construction and destruction
0061         BOOST_UBLAS_INLINE
0062         vector_range (vector_type &data, const range_type &r):
0063             data_ (data), r_ (r.preprocess (data.size ())) {
0064             // Early checking of preconditions here.
0065             // BOOST_UBLAS_CHECK (r_.start () <= data_.size () &&
0066             //                   r_.start () + r_.size () <= data_.size (), bad_index ());
0067         }
0068         BOOST_UBLAS_INLINE
0069         vector_range (const vector_closure_type &data, const range_type &r, bool):
0070             data_ (data), r_ (r.preprocess (data.size ())) {
0071             // Early checking of preconditions here.
0072             // BOOST_UBLAS_CHECK (r_.start () <= data_.size () &&
0073             //                    r_.start () + r_.size () <= data_.size (), bad_index ());
0074         }
0075 
0076         // Accessors
0077         BOOST_UBLAS_INLINE
0078         size_type start () const {
0079             return r_.start ();
0080         }
0081         BOOST_UBLAS_INLINE
0082         size_type size () const {
0083             return r_.size ();
0084         }
0085 
0086         // Storage accessors
0087         BOOST_UBLAS_INLINE
0088         const vector_closure_type &data () const {
0089             return data_;
0090         }
0091         BOOST_UBLAS_INLINE
0092         vector_closure_type &data () {
0093             return data_;
0094         }
0095 
0096         // Element access
0097 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
0098         BOOST_UBLAS_INLINE
0099         const_reference operator () (size_type i) const {
0100             return data_ (r_ (i));
0101         }
0102         BOOST_UBLAS_INLINE
0103         reference operator () (size_type i) {
0104             return data_ (r_ (i));
0105         }
0106 
0107         BOOST_UBLAS_INLINE
0108         const_reference operator [] (size_type i) const {
0109             return (*this) (i);
0110         }
0111         BOOST_UBLAS_INLINE
0112         reference operator [] (size_type i) {
0113             return (*this) (i);
0114         }
0115 #else
0116         BOOST_UBLAS_INLINE
0117         reference operator () (size_type i) const {
0118             return data_ (r_ (i));
0119         }
0120 
0121         BOOST_UBLAS_INLINE
0122         reference operator [] (size_type i) const {
0123             return (*this) (i);
0124         }
0125 #endif
0126 
0127         // ISSUE can this be done in free project function?
0128         // Although a const function can create a non-const proxy to a non-const object
0129         // Critical is that vector_type and data_ (vector_closure_type) are const correct
0130         BOOST_UBLAS_INLINE
0131         vector_range<vector_type> project (const range_type &r) const {
0132             return vector_range<vector_type> (data_, r_.compose (r.preprocess (data_.size ())), false);
0133         }
0134 
0135         // Assignment
0136         BOOST_UBLAS_INLINE
0137         vector_range &operator = (const vector_range &vr) {
0138             // ISSUE need a temporary, proxy can be overlaping alias
0139             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vr));
0140             return *this;
0141         }
0142         BOOST_UBLAS_INLINE
0143         vector_range &assign_temporary (vector_range &vr) {
0144             // assign elements, proxied container remains the same
0145             vector_assign<scalar_assign> (*this, vr);
0146             return *this;
0147         }
0148         template<class AE>
0149         BOOST_UBLAS_INLINE
0150         vector_range &operator = (const vector_expression<AE> &ae) {
0151             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
0152             return *this;
0153         }
0154         template<class AE>
0155         BOOST_UBLAS_INLINE
0156         vector_range &assign (const vector_expression<AE> &ae) {
0157             vector_assign<scalar_assign> (*this, ae);
0158             return *this;
0159         }
0160         template<class AE>
0161         BOOST_UBLAS_INLINE
0162         vector_range &operator += (const vector_expression<AE> &ae) {
0163             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
0164             return *this;
0165         }
0166         template<class AE>
0167         BOOST_UBLAS_INLINE
0168         vector_range &plus_assign (const vector_expression<AE> &ae) {
0169             vector_assign<scalar_plus_assign> (*this, ae);
0170             return *this;
0171         }
0172         template<class AE>
0173         BOOST_UBLAS_INLINE
0174         vector_range &operator -= (const vector_expression<AE> &ae) {
0175             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
0176             return *this;
0177         }
0178         template<class AE>
0179         BOOST_UBLAS_INLINE
0180         vector_range &minus_assign (const vector_expression<AE> &ae) {
0181             vector_assign<scalar_minus_assign> (*this, ae);
0182             return *this;
0183         }
0184         template<class AT>
0185         BOOST_UBLAS_INLINE
0186         vector_range &operator *= (const AT &at) {
0187             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
0188             return *this;
0189         }
0190         template<class AT>
0191         BOOST_UBLAS_INLINE
0192         vector_range &operator /= (const AT &at) {
0193             vector_assign_scalar<scalar_divides_assign> (*this, at);
0194             return *this;
0195         }
0196 
0197         // Closure comparison
0198         BOOST_UBLAS_INLINE
0199         bool same_closure (const vector_range &vr) const {
0200             return (*this).data_.same_closure (vr.data_);
0201         }
0202 
0203         // Comparison
0204         BOOST_UBLAS_INLINE
0205         bool operator == (const vector_range &vr) const {
0206             return (*this).data_ == vr.data_ && r_ == vr.r_;
0207         }
0208 
0209         // Swapping
0210         BOOST_UBLAS_INLINE
0211         void swap (vector_range vr) {
0212             if (this != &vr) {
0213                 BOOST_UBLAS_CHECK (size () == vr.size (), bad_size ());
0214                 // Sparse ranges may be nonconformant now.
0215                 // std::swap_ranges (begin (), end (), vr.begin ());
0216                 vector_swap<scalar_swap> (*this, vr);
0217             }
0218         }
0219         BOOST_UBLAS_INLINE
0220         friend void swap (vector_range vr1, vector_range vr2) {
0221             vr1.swap (vr2);
0222         }
0223 
0224         // Iterator types
0225     private:
0226         typedef typename V::const_iterator const_subiterator_type;
0227         typedef typename boost::mpl::if_<boost::is_const<V>,
0228                                           typename V::const_iterator,
0229                                           typename V::iterator>::type subiterator_type;
0230 
0231     public:
0232 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
0233         typedef indexed_iterator<vector_range<vector_type>,
0234                                  typename subiterator_type::iterator_category> iterator;
0235         typedef indexed_const_iterator<vector_range<vector_type>,
0236                                        typename const_subiterator_type::iterator_category> const_iterator;
0237 #else
0238         class const_iterator;
0239         class iterator;
0240 #endif
0241 
0242         // Element lookup
0243         BOOST_UBLAS_INLINE
0244         const_iterator find (size_type i) const {
0245             const_subiterator_type it (data_.find (start () + i));
0246 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
0247             return const_iterator (*this, it.index ());
0248 #else
0249             return const_iterator (*this, it);
0250 #endif
0251         }
0252         BOOST_UBLAS_INLINE
0253         iterator find (size_type i) {
0254             subiterator_type it (data_.find (start () + i));
0255 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
0256             return iterator (*this, it.index ());
0257 #else
0258             return iterator (*this, it);
0259 #endif
0260         }
0261 
0262 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
0263         class const_iterator:
0264             public container_const_reference<vector_range>,
0265             public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
0266                         iterator_base<const_iterator, value_type>::type {
0267         public:
0268             typedef typename const_subiterator_type::difference_type difference_type;
0269             typedef typename const_subiterator_type::value_type value_type;
0270             typedef typename const_subiterator_type::reference reference;
0271             typedef typename const_subiterator_type::pointer pointer;
0272 
0273             // Construction and destruction
0274             BOOST_UBLAS_INLINE
0275             const_iterator ():
0276                 container_const_reference<self_type> (), it_ () {}
0277             BOOST_UBLAS_INLINE
0278             const_iterator (const self_type &vr, const const_subiterator_type &it):
0279                 container_const_reference<self_type> (vr), it_ (it) {}
0280             BOOST_UBLAS_INLINE
0281             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
0282                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
0283 
0284             // Arithmetic
0285             BOOST_UBLAS_INLINE
0286             const_iterator &operator ++ () {
0287                 ++ it_;
0288                 return *this;
0289             }
0290             BOOST_UBLAS_INLINE
0291             const_iterator &operator -- () {
0292                 -- it_;
0293                 return *this;
0294             }
0295             BOOST_UBLAS_INLINE
0296             const_iterator &operator += (difference_type n) {
0297                 it_ += n;
0298                 return *this;
0299             }
0300             BOOST_UBLAS_INLINE
0301             const_iterator &operator -= (difference_type n) {
0302                 it_ -= n;
0303                 return *this;
0304             }
0305             BOOST_UBLAS_INLINE
0306             difference_type operator - (const const_iterator &it) const {
0307                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0308                 return it_ - it.it_;
0309             }
0310 
0311             // Dereference
0312             BOOST_UBLAS_INLINE
0313             const_reference operator * () const {
0314                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
0315                 return *it_;
0316             }
0317             BOOST_UBLAS_INLINE
0318             const_reference operator [] (difference_type n) const {
0319                 return *(*this + n);
0320             }
0321 
0322             // Index
0323             BOOST_UBLAS_INLINE
0324             size_type index () const {
0325                 return it_.index () - (*this) ().start ();
0326             }
0327 
0328             // Assignment
0329             BOOST_UBLAS_INLINE
0330             const_iterator &operator = (const const_iterator &it) {
0331                 container_const_reference<self_type>::assign (&it ());
0332                 it_ = it.it_;
0333                 return *this;
0334             }
0335 
0336             // Comparison
0337             BOOST_UBLAS_INLINE
0338             bool operator == (const const_iterator &it) const {
0339                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0340                 return it_ == it.it_;
0341             }
0342             BOOST_UBLAS_INLINE
0343             bool operator < (const const_iterator &it) const {
0344                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0345                 return it_ < it.it_;
0346             }
0347 
0348         private:
0349             const_subiterator_type it_;
0350         };
0351 #endif
0352 
0353         BOOST_UBLAS_INLINE
0354         const_iterator begin () const {
0355             return find (0);
0356         }
0357         BOOST_UBLAS_INLINE
0358         const_iterator cbegin () const {
0359             return begin ();
0360         }
0361         BOOST_UBLAS_INLINE
0362         const_iterator end () const {
0363             return find (size ());
0364         }
0365         BOOST_UBLAS_INLINE
0366         const_iterator cend () const {
0367             return end ();
0368         }
0369 
0370 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
0371         class iterator:
0372             public container_reference<vector_range>,
0373             public iterator_base_traits<typename subiterator_type::iterator_category>::template
0374                         iterator_base<iterator, value_type>::type {
0375         public:
0376             typedef typename subiterator_type::difference_type difference_type;
0377             typedef typename subiterator_type::value_type value_type;
0378             typedef typename subiterator_type::reference reference;
0379             typedef typename subiterator_type::pointer pointer;
0380 
0381             // Construction and destruction
0382             BOOST_UBLAS_INLINE
0383             iterator ():
0384                 container_reference<self_type> (), it_ () {}
0385             BOOST_UBLAS_INLINE
0386             iterator (self_type &vr, const subiterator_type &it):
0387                 container_reference<self_type> (vr), it_ (it) {}
0388 
0389             // Arithmetic
0390             BOOST_UBLAS_INLINE
0391             iterator &operator ++ () {
0392                 ++ it_;
0393                 return *this;
0394             }
0395             BOOST_UBLAS_INLINE
0396             iterator &operator -- () {
0397                 -- it_;
0398                 return *this;
0399             }
0400             BOOST_UBLAS_INLINE
0401             iterator &operator += (difference_type n) {
0402                 it_ += n;
0403                 return *this;
0404             }
0405             BOOST_UBLAS_INLINE
0406             iterator &operator -= (difference_type n) {
0407                 it_ -= n;
0408                 return *this;
0409             }
0410             BOOST_UBLAS_INLINE
0411             difference_type operator - (const iterator &it) const {
0412                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0413                 return it_ - it.it_;
0414             }
0415 
0416             // Dereference
0417             BOOST_UBLAS_INLINE
0418             reference operator * () const {
0419                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
0420                 return *it_;
0421             }
0422             BOOST_UBLAS_INLINE
0423             reference operator [] (difference_type n) const {
0424                 return *(*this + n);
0425             }
0426 
0427             // Index
0428             BOOST_UBLAS_INLINE
0429             size_type index () const {
0430                 return it_.index () - (*this) ().start ();
0431             }
0432 
0433             // Assignment
0434             BOOST_UBLAS_INLINE
0435             iterator &operator = (const iterator &it) {
0436                 container_reference<self_type>::assign (&it ());
0437                 it_ = it.it_;
0438                 return *this;
0439             }
0440 
0441             // Comparison
0442             BOOST_UBLAS_INLINE
0443             bool operator == (const iterator &it) const {
0444                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0445                 return it_ == it.it_;
0446             }
0447             BOOST_UBLAS_INLINE
0448             bool operator < (const iterator &it) const {
0449                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0450                 return it_ < it.it_;
0451             }
0452 
0453         private:
0454             subiterator_type it_;
0455 
0456             friend class const_iterator;
0457         };
0458 #endif
0459 
0460         BOOST_UBLAS_INLINE
0461         iterator begin () {
0462             return find (0);
0463         }
0464         BOOST_UBLAS_INLINE
0465         iterator end () {
0466             return find (size ());
0467         }
0468 
0469         // Reverse iterator
0470         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
0471         typedef reverse_iterator_base<iterator> reverse_iterator;
0472 
0473         BOOST_UBLAS_INLINE
0474         const_reverse_iterator rbegin () const {
0475             return const_reverse_iterator (end ());
0476         }
0477         BOOST_UBLAS_INLINE
0478         const_reverse_iterator crbegin () const {
0479             return rbegin ();
0480         }
0481         BOOST_UBLAS_INLINE
0482         const_reverse_iterator rend () const {
0483             return const_reverse_iterator (begin ());
0484         }
0485         BOOST_UBLAS_INLINE
0486         const_reverse_iterator crend () const {
0487             return rend ();
0488         }
0489 
0490         BOOST_UBLAS_INLINE
0491         reverse_iterator rbegin () {
0492             return reverse_iterator (end ());
0493         }
0494         BOOST_UBLAS_INLINE
0495         reverse_iterator rend () {
0496             return reverse_iterator (begin ());
0497         }
0498 
0499     private:
0500         vector_closure_type data_;
0501         range_type r_;
0502     };
0503 
0504     // ------------------
0505     // Simple Projections
0506     // ------------------
0507 
0508     /** \brief Return a \c vector_range on a specified vector, a start and stop index.
0509      * Return a \c vector_range on a specified vector, a start and stop index. The resulting \c vector_range can be manipulated like a normal vector.
0510      * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
0511      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
0512      */
0513     template<class V>
0514     BOOST_UBLAS_INLINE
0515     vector_range<V> subrange (V &data, typename V::size_type start, typename V::size_type stop) {
0516         typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
0517         return vector_range<V> (data, range_type (start, stop));
0518     }
0519 
0520     /** \brief Return a \c const \c vector_range on a specified vector, a start and stop index.
0521      * Return a \c const \c vector_range on a specified vector, a start and stop index. The resulting \c const \c vector_range can be manipulated like a normal vector.
0522      *If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
0523      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
0524      */
0525     template<class V>
0526     BOOST_UBLAS_INLINE
0527     vector_range<const V> subrange (const V &data, typename V::size_type start, typename V::size_type stop) {
0528         typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
0529         return vector_range<const V> (data, range_type (start, stop));
0530     }
0531 
0532     // -------------------
0533     // Generic Projections
0534     // -------------------
0535     
0536     /** \brief Return a \c const \c vector_range on a specified vector and \c range
0537      * Return a \c const \c vector_range on a specified vector and \c range. The resulting \c vector_range can be manipulated like a normal vector.
0538      * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
0539      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
0540      */
0541     template<class V>
0542     BOOST_UBLAS_INLINE
0543     vector_range<V> project (V &data, typename vector_range<V>::range_type const &r) {
0544         return vector_range<V> (data, r);
0545     }
0546 
0547     /** \brief Return a \c vector_range on a specified vector and \c range
0548      * Return a \c vector_range on a specified vector and \c range. The resulting \c vector_range can be manipulated like a normal vector.
0549      * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
0550      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
0551      */
0552     template<class V>
0553     BOOST_UBLAS_INLINE
0554     const vector_range<const V> project (const V &data, typename vector_range<V>::range_type const &r) {
0555         // ISSUE was: return vector_range<V> (const_cast<V &> (data), r);
0556         return vector_range<const V> (data, r);
0557    }
0558 
0559     /** \brief Return a \c const \c vector_range on a specified vector and const \c range
0560      * Return a \c const \c vector_range on a specified vector and const \c range. The resulting \c vector_range can be manipulated like a normal vector.
0561      * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
0562      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
0563      */
0564     template<class V>
0565     BOOST_UBLAS_INLINE
0566     vector_range<V> project (vector_range<V> &data, const typename vector_range<V>::range_type &r) {
0567         return data.project (r);
0568     }
0569 
0570     /** \brief Return a \c vector_range on a specified vector and const \c range
0571      * Return a \c vector_range on a specified vector and const \c range. The resulting \c vector_range can be manipulated like a normal vector.
0572      * If the specified range falls outside that of of the index range of the vector, then the resulting \c vector_range is not a well formed
0573      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
0574      */
0575     template<class V>
0576     BOOST_UBLAS_INLINE
0577     const vector_range<V> project (const vector_range<V> &data, const typename vector_range<V>::range_type &r) {
0578         return data.project (r);
0579     }
0580 
0581     // Specialization of temporary_traits
0582     template <class V>
0583     struct vector_temporary_traits< vector_range<V> >
0584     : vector_temporary_traits< V > {} ;
0585     template <class V>
0586     struct vector_temporary_traits< const vector_range<V> >
0587     : vector_temporary_traits< V > {} ;
0588 
0589 
0590     /** \brief A vector referencing a non continuous subvector of elements of vector v containing all elements specified by \c slice.
0591      *
0592      * A vector slice can be used as a normal vector in any expression.
0593      * If the specified slice falls outside that of the index slice of the vector, then
0594      * the \c vector_slice is not a well formed \i Vector \i Expression and access to an 
0595      * element outside of index slice of the vector is \b undefined.
0596      *
0597      * A slice is a generalization of a range. In a range going from \f$a\f$ to \f$b\f$, 
0598      * all elements belong to the range. In a slice, a \i \f$step\f$ can be specified meaning to
0599      * take one element over \f$step\f$ in the range specified from \f$a\f$ to \f$b\f$.
0600      * Obviously, a slice with a \f$step\f$ of 1 is equivalent to a range.
0601      *
0602      * \tparam V the type of vector referenced (for example \c vector<double>)
0603      */
0604     template<class V>
0605     class vector_slice:
0606         public vector_expression<vector_slice<V> > {
0607 
0608         typedef vector_slice<V> self_type;
0609     public:
0610 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
0611         using vector_expression<self_type>::operator ();
0612 #endif
0613         typedef const V const_vector_type;
0614         typedef V vector_type;
0615         typedef typename V::size_type size_type;
0616         typedef typename V::difference_type difference_type;
0617         typedef typename V::value_type value_type;
0618         typedef typename V::const_reference const_reference;
0619         typedef typename boost::mpl::if_<boost::is_const<V>,
0620                                           typename V::const_reference,
0621                                           typename V::reference>::type reference;
0622         typedef typename boost::mpl::if_<boost::is_const<V>,
0623                                           typename V::const_closure_type,
0624                                           typename V::closure_type>::type vector_closure_type;
0625         typedef basic_range<size_type, difference_type> range_type;
0626         typedef basic_slice<size_type, difference_type> slice_type;
0627         typedef const self_type const_closure_type;
0628         typedef self_type closure_type;
0629         typedef typename storage_restrict_traits<typename V::storage_category,
0630                                                  dense_proxy_tag>::storage_category storage_category;
0631 
0632         // Construction and destruction
0633         BOOST_UBLAS_INLINE
0634         vector_slice (vector_type &data, const slice_type &s):
0635             data_ (data), s_ (s.preprocess (data.size ())) {
0636             // Early checking of preconditions here.
0637             // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
0638             //                    s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
0639         }
0640         BOOST_UBLAS_INLINE
0641         vector_slice (const vector_closure_type &data, const slice_type &s, int):
0642             data_ (data), s_ (s.preprocess (data.size ())) {
0643             // Early checking of preconditions here.
0644             // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
0645             //                    s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
0646         }
0647 
0648         // Accessors
0649         BOOST_UBLAS_INLINE
0650         size_type start () const {
0651             return s_.start ();
0652         }
0653         BOOST_UBLAS_INLINE
0654         difference_type stride () const {
0655             return s_.stride ();
0656         }
0657         BOOST_UBLAS_INLINE
0658         size_type size () const {
0659             return s_.size ();
0660         }
0661 
0662         // Storage accessors
0663         BOOST_UBLAS_INLINE
0664         const vector_closure_type &data () const {
0665             return data_;
0666         }
0667         BOOST_UBLAS_INLINE
0668         vector_closure_type &data () {
0669             return data_;
0670         }
0671 
0672         // Element access
0673 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
0674         BOOST_UBLAS_INLINE
0675         const_reference operator () (size_type i) const {
0676             return data_ (s_ (i));
0677         }
0678         BOOST_UBLAS_INLINE
0679         reference operator () (size_type i) {
0680             return data_ (s_ (i));
0681         }
0682 
0683         BOOST_UBLAS_INLINE
0684         const_reference operator [] (size_type i) const {
0685             return (*this) (i);
0686         }
0687         BOOST_UBLAS_INLINE
0688         reference operator [] (size_type i) {
0689             return (*this) (i);
0690         }
0691 #else
0692         BOOST_UBLAS_INLINE
0693         reference operator () (size_type i) const {
0694             return data_ (s_ (i));
0695         }
0696 
0697         BOOST_UBLAS_INLINE
0698         reference operator [] (size_type i) const {
0699             return (*this) (i);
0700         }
0701 #endif
0702 
0703         // ISSUE can this be done in free project function?
0704         // Although a const function can create a non-const proxy to a non-const object
0705         // Critical is that vector_type and data_ (vector_closure_type) are const correct
0706         BOOST_UBLAS_INLINE
0707         vector_slice<vector_type> project (const range_type &r) const {
0708             return vector_slice<vector_type>  (data_, s_.compose (r.preprocess (data_.size ())), false);
0709         }
0710         BOOST_UBLAS_INLINE
0711         vector_slice<vector_type> project (const slice_type &s) const {
0712             return vector_slice<vector_type>  (data_, s_.compose (s.preprocess (data_.size ())), false);
0713         }
0714 
0715         // Assignment
0716         BOOST_UBLAS_INLINE
0717         vector_slice &operator = (const vector_slice &vs) {
0718             // ISSUE need a temporary, proxy can be overlaping alias
0719             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vs));
0720             return *this;
0721         }
0722         BOOST_UBLAS_INLINE
0723         vector_slice &assign_temporary (vector_slice &vs) {
0724             // assign elements, proxied container remains the same
0725             vector_assign<scalar_assign> (*this, vs);
0726             return *this;
0727         }
0728         template<class AE>
0729         BOOST_UBLAS_INLINE
0730         vector_slice &operator = (const vector_expression<AE> &ae) {
0731             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
0732             return *this;
0733         }
0734         template<class AE>
0735         BOOST_UBLAS_INLINE
0736         vector_slice &assign (const vector_expression<AE> &ae) {
0737             vector_assign<scalar_assign> (*this, ae);
0738             return *this;
0739         }
0740         template<class AE>
0741         BOOST_UBLAS_INLINE
0742         vector_slice &operator += (const vector_expression<AE> &ae) {
0743             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
0744             return *this;
0745         }
0746         template<class AE>
0747         BOOST_UBLAS_INLINE
0748         vector_slice &plus_assign (const vector_expression<AE> &ae) {
0749             vector_assign<scalar_plus_assign> (*this, ae);
0750             return *this;
0751         }
0752         template<class AE>
0753         BOOST_UBLAS_INLINE
0754         vector_slice &operator -= (const vector_expression<AE> &ae) {
0755             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
0756             return *this;
0757         }
0758         template<class AE>
0759         BOOST_UBLAS_INLINE
0760         vector_slice &minus_assign (const vector_expression<AE> &ae) {
0761             vector_assign<scalar_minus_assign> (*this, ae);
0762             return *this;
0763         }
0764         template<class AT>
0765         BOOST_UBLAS_INLINE
0766         vector_slice &operator *= (const AT &at) {
0767             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
0768             return *this;
0769         }
0770         template<class AT>
0771         BOOST_UBLAS_INLINE
0772         vector_slice &operator /= (const AT &at) {
0773             vector_assign_scalar<scalar_divides_assign> (*this, at);
0774             return *this;
0775         }
0776 
0777         // Closure comparison
0778         BOOST_UBLAS_INLINE
0779         bool same_closure (const vector_slice &vr) const {
0780             return (*this).data_.same_closure (vr.data_);
0781         }
0782 
0783         // Comparison
0784         BOOST_UBLAS_INLINE
0785         bool operator == (const vector_slice &vs) const {
0786             return (*this).data_ == vs.data_ && s_ == vs.s_;
0787         }
0788 
0789         // Swapping
0790         BOOST_UBLAS_INLINE
0791         void swap (vector_slice vs) {
0792             if (this != &vs) {
0793                 BOOST_UBLAS_CHECK (size () == vs.size (), bad_size ());
0794                 // Sparse ranges may be nonconformant now.
0795                 // std::swap_ranges (begin (), end (), vs.begin ());
0796                 vector_swap<scalar_swap> (*this, vs);
0797             }
0798         }
0799         BOOST_UBLAS_INLINE
0800         friend void swap (vector_slice vs1, vector_slice vs2) {
0801             vs1.swap (vs2);
0802         }
0803 
0804         // Iterator types
0805     private:
0806         // Use slice as an index - FIXME this fails for packed assignment
0807         typedef typename slice_type::const_iterator const_subiterator_type;
0808         typedef typename slice_type::const_iterator subiterator_type;
0809 
0810     public:
0811 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
0812         typedef indexed_iterator<vector_slice<vector_type>,
0813                                  typename vector_type::iterator::iterator_category> iterator;
0814         typedef indexed_const_iterator<vector_slice<vector_type>,
0815                                        typename vector_type::const_iterator::iterator_category> const_iterator;
0816 #else
0817         class const_iterator;
0818         class iterator;
0819 #endif
0820 
0821         // Element lookup
0822         BOOST_UBLAS_INLINE
0823         const_iterator find (size_type i) const {
0824 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
0825             return const_iterator (*this, i);
0826 #else
0827             return const_iterator (*this, s_.begin () + i);
0828 #endif
0829         }
0830         BOOST_UBLAS_INLINE
0831         iterator find (size_type i) {
0832 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
0833             return iterator (*this, i);
0834 #else
0835             return iterator (*this, s_.begin () + i);
0836 #endif
0837         }
0838 
0839 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
0840         class const_iterator:
0841             public container_const_reference<vector_slice>,
0842             public iterator_base_traits<typename V::const_iterator::iterator_category>::template
0843                         iterator_base<const_iterator, value_type>::type {
0844         public:
0845             typedef typename V::const_iterator::difference_type difference_type;
0846             typedef typename V::const_iterator::value_type value_type;
0847             typedef typename V::const_reference reference;    //FIXME due to indexing access
0848             typedef typename V::const_iterator::pointer pointer;
0849 
0850             // Construction and destruction
0851             BOOST_UBLAS_INLINE
0852             const_iterator ():
0853                 container_const_reference<self_type> (), it_ () {}
0854             BOOST_UBLAS_INLINE
0855             const_iterator (const self_type &vs, const const_subiterator_type &it):
0856                 container_const_reference<self_type> (vs), it_ (it) {}
0857             BOOST_UBLAS_INLINE
0858             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
0859                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
0860 
0861             // Arithmetic
0862             BOOST_UBLAS_INLINE
0863             const_iterator &operator ++ () {
0864                 ++ it_;
0865                 return *this;
0866             }
0867             BOOST_UBLAS_INLINE
0868             const_iterator &operator -- () {
0869                 -- it_;
0870                 return *this;
0871             }
0872             BOOST_UBLAS_INLINE
0873             const_iterator &operator += (difference_type n) {
0874                 it_ += n;
0875                 return *this;
0876             }
0877             BOOST_UBLAS_INLINE
0878             const_iterator &operator -= (difference_type n) {
0879                 it_ -= n;
0880                 return *this;
0881             }
0882             BOOST_UBLAS_INLINE
0883             difference_type operator - (const const_iterator &it) const {
0884                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0885                 return it_ - it.it_;
0886             }
0887 
0888             // Dereference
0889             BOOST_UBLAS_INLINE
0890             const_reference operator * () const {
0891                 // FIXME replace find with at_element
0892                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
0893                 return (*this) ().data_ (*it_);
0894             }
0895             BOOST_UBLAS_INLINE
0896             const_reference operator [] (difference_type n) const {
0897                 return *(*this + n);
0898             }
0899 
0900             // Index
0901             BOOST_UBLAS_INLINE
0902             size_type index () const {
0903                 return it_.index ();
0904             }
0905 
0906             // Assignment
0907             BOOST_UBLAS_INLINE
0908             const_iterator &operator = (const const_iterator &it) {
0909                 container_const_reference<self_type>::assign (&it ());
0910                 it_ = it.it_;
0911                 return *this;
0912             }
0913 
0914             // Comparison
0915             BOOST_UBLAS_INLINE
0916             bool operator == (const const_iterator &it) const {
0917                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0918                 return it_ == it.it_;
0919             }
0920             BOOST_UBLAS_INLINE
0921             bool operator < (const const_iterator &it) const {
0922                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0923                 return it_ < it.it_;
0924             }
0925 
0926         private:
0927             const_subiterator_type it_;
0928         };
0929 #endif
0930 
0931         BOOST_UBLAS_INLINE
0932         const_iterator begin () const {
0933             return find (0);
0934         }
0935         BOOST_UBLAS_INLINE
0936         const_iterator cbegin () const {
0937             return begin ();
0938         }
0939         BOOST_UBLAS_INLINE
0940         const_iterator end () const {
0941             return find (size ());
0942         }
0943         BOOST_UBLAS_INLINE
0944         const_iterator cend () const {
0945             return end ();
0946         }
0947 
0948 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
0949         class iterator:
0950             public container_reference<vector_slice>,
0951             public iterator_base_traits<typename V::iterator::iterator_category>::template
0952                         iterator_base<iterator, value_type>::type {
0953         public:
0954             typedef typename V::iterator::difference_type difference_type;
0955             typedef typename V::iterator::value_type value_type;
0956             typedef typename V::reference reference;    //FIXME due to indexing access
0957             typedef typename V::iterator::pointer pointer;
0958 
0959             // Construction and destruction
0960             BOOST_UBLAS_INLINE
0961             iterator ():
0962                 container_reference<self_type> (), it_ () {}
0963             BOOST_UBLAS_INLINE
0964             iterator (self_type &vs, const subiterator_type &it):
0965                 container_reference<self_type> (vs), it_ (it) {}
0966 
0967             // Arithmetic
0968             BOOST_UBLAS_INLINE
0969             iterator &operator ++ () {
0970                 ++ it_;
0971                 return *this;
0972             }
0973             BOOST_UBLAS_INLINE
0974             iterator &operator -- () {
0975                 -- it_;
0976                 return *this;
0977             }
0978             BOOST_UBLAS_INLINE
0979             iterator &operator += (difference_type n) {
0980                 it_ += n;
0981                 return *this;
0982             }
0983             BOOST_UBLAS_INLINE
0984             iterator &operator -= (difference_type n) {
0985                 it_ -= n;
0986                 return *this;
0987             }
0988             BOOST_UBLAS_INLINE
0989             difference_type operator - (const iterator &it) const {
0990                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0991                 return it_ - it.it_;
0992             }
0993 
0994             // Dereference
0995             BOOST_UBLAS_INLINE
0996             reference operator * () const {
0997                 // FIXME replace find with at_element
0998                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
0999                 return (*this) ().data_ (*it_);
1000             }
1001             BOOST_UBLAS_INLINE
1002             reference operator [] (difference_type n) const {
1003                 return *(*this + n);
1004             }
1005 
1006 
1007             // Index
1008             BOOST_UBLAS_INLINE
1009             size_type index () const {
1010                 return it_.index ();
1011             }
1012 
1013             // Assignment
1014             BOOST_UBLAS_INLINE
1015             iterator &operator = (const iterator &it) {
1016                 container_reference<self_type>::assign (&it ());
1017                 it_ = it.it_;
1018                 return *this;
1019             }
1020 
1021             // Comparison
1022             BOOST_UBLAS_INLINE
1023             bool operator == (const iterator &it) const {
1024                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1025                 return it_ == it.it_;
1026             }
1027             BOOST_UBLAS_INLINE
1028             bool operator < (const iterator &it) const {
1029                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1030                 return it_ < it.it_;
1031             }
1032 
1033         private:
1034             subiterator_type it_;
1035 
1036             friend class const_iterator;
1037         };
1038 #endif
1039 
1040         BOOST_UBLAS_INLINE
1041         iterator begin () {
1042             return find (0);
1043         }
1044         BOOST_UBLAS_INLINE
1045         iterator end () {
1046             return find (size ());
1047         }
1048 
1049         // Reverse iterator
1050         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1051         typedef reverse_iterator_base<iterator> reverse_iterator;
1052 
1053         BOOST_UBLAS_INLINE
1054         const_reverse_iterator rbegin () const {
1055             return const_reverse_iterator (end ());
1056         }
1057         BOOST_UBLAS_INLINE
1058         const_reverse_iterator crbegin () const {
1059             return rbegin ();
1060         }
1061         BOOST_UBLAS_INLINE
1062         const_reverse_iterator rend () const {
1063             return const_reverse_iterator (begin ());
1064         }
1065         BOOST_UBLAS_INLINE
1066         const_reverse_iterator crend () const {
1067             return rend ();
1068         }
1069         BOOST_UBLAS_INLINE
1070         reverse_iterator rbegin () {
1071             return reverse_iterator (end ());
1072         }
1073         BOOST_UBLAS_INLINE
1074         reverse_iterator rend () {
1075             return reverse_iterator (begin ());
1076         }
1077 
1078     private:
1079         vector_closure_type data_;
1080         slice_type s_;
1081     };
1082 
1083     // Simple Projections
1084     template<class V>
1085     BOOST_UBLAS_INLINE
1086     vector_slice<V> subslice (V &data, typename V::size_type start, typename V::difference_type stride, typename V::size_type size) {
1087         typedef basic_slice<typename V::size_type, typename V::difference_type> slice_type;
1088         return vector_slice<V> (data, slice_type (start, stride, size));
1089     }
1090     template<class V>
1091     BOOST_UBLAS_INLINE
1092     vector_slice<const V> subslice (const V &data, typename V::size_type start, typename V::difference_type stride, typename V::size_type size)  {
1093         typedef basic_slice<typename V::size_type, typename V::difference_type> slice_type;
1094         return vector_slice<const V> (data, slice_type (start, stride, size));
1095     }
1096 
1097     // Generic Projections
1098     template<class V>
1099     BOOST_UBLAS_INLINE
1100     vector_slice<V> project (V &data, const typename vector_slice<V>::slice_type &s) {
1101         return vector_slice<V> (data, s);
1102     }
1103     template<class V>
1104     BOOST_UBLAS_INLINE
1105     const vector_slice<const V> project (const V &data, const typename vector_slice<V>::slice_type &s) {
1106         // ISSUE was: return vector_slice<V> (const_cast<V &> (data), s);
1107         return vector_slice<const V> (data, s);
1108     }
1109     template<class V>
1110     BOOST_UBLAS_INLINE
1111     vector_slice<V> project (vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
1112         return data.project (s);
1113     }
1114     template<class V>
1115     BOOST_UBLAS_INLINE
1116     const vector_slice<V> project (const vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
1117         return data.project (s);
1118     }
1119     // 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
1120     template<class V>
1121     BOOST_UBLAS_INLINE
1122     vector_slice<V> project (vector_slice<V> &data, const typename vector_range<V>::range_type &r) {
1123         return data.project (r);
1124     }
1125     template<class V>
1126     BOOST_UBLAS_INLINE
1127     const vector_slice<V> project (const vector_slice<V> &data, const typename vector_range<V>::range_type &r) {
1128         return data.project (r);
1129     }
1130 
1131     // Specialization of temporary_traits
1132     template <class V>
1133     struct vector_temporary_traits< vector_slice<V> >
1134     : vector_temporary_traits< V > {} ;
1135     template <class V>
1136     struct vector_temporary_traits< const vector_slice<V> >
1137     : vector_temporary_traits< V > {} ;
1138 
1139 
1140     // Vector based indirection class
1141     // Contributed by Toon Knapen.
1142     // Extended and optimized by Kresimir Fresl.
1143 
1144     /** \brief A vector referencing a non continuous subvector of elements given another vector of indices.
1145      *
1146      * It is the most general version of any subvectors because it uses another vector of indices to reference
1147      * the subvector. 
1148      *
1149      * The vector of indices can be of any type with the restriction that its elements must be
1150      * type-compatible with the size_type \c of the container. In practice, the following are good candidates:
1151      * - \c boost::numeric::ublas::indirect_array<A> where \c A can be \c int, \c size_t, \c long, etc...
1152      * - \c std::vector<A> where \c A can \c int, \c size_t, \c long, etc...
1153      * - \c boost::numeric::ublas::vector<int> can work too (\c int can be replaced by another integer type)
1154      * - etc...
1155      *
1156      * An indirect vector can be used as a normal vector in any expression. If the specified indirect vector 
1157      * falls outside that of the indices of the vector, then the \c vector_indirect is not a well formed 
1158      * \i Vector \i Expression and access to an element outside of indices of the vector is \b undefined.
1159      *
1160      * \tparam V the type of vector referenced (for example \c vector<double>)
1161      * \tparam IA the type of index vector. Default is \c ublas::indirect_array<>
1162      */
1163     template<class V, class IA>
1164     class vector_indirect:
1165         public vector_expression<vector_indirect<V, IA> > {
1166 
1167         typedef vector_indirect<V, IA> self_type;
1168     public:
1169 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1170         using vector_expression<self_type>::operator ();
1171 #endif
1172         typedef const V const_vector_type;
1173         typedef V vector_type;
1174         typedef const IA const_indirect_array_type;
1175         typedef IA indirect_array_type;
1176         typedef typename V::size_type size_type;
1177         typedef typename V::difference_type difference_type;
1178         typedef typename V::value_type value_type;
1179         typedef typename V::const_reference const_reference;
1180         typedef typename boost::mpl::if_<boost::is_const<V>,
1181                                           typename V::const_reference,
1182                                           typename V::reference>::type reference;
1183         typedef typename boost::mpl::if_<boost::is_const<V>,
1184                                           typename V::const_closure_type,
1185                                           typename V::closure_type>::type vector_closure_type;
1186         typedef basic_range<size_type, difference_type> range_type;
1187         typedef basic_slice<size_type, difference_type> slice_type;
1188         typedef const self_type const_closure_type;
1189         typedef self_type closure_type;
1190         typedef typename storage_restrict_traits<typename V::storage_category,
1191                                                  dense_proxy_tag>::storage_category storage_category;
1192 
1193         // Construction and destruction
1194         BOOST_UBLAS_INLINE
1195         vector_indirect (vector_type &data, size_type size):
1196             data_ (data), ia_ (size) {}
1197         BOOST_UBLAS_INLINE
1198         vector_indirect (vector_type &data, const indirect_array_type &ia):
1199             data_ (data), ia_ (ia.preprocess (data.size ())) {}
1200         BOOST_UBLAS_INLINE
1201         vector_indirect (const vector_closure_type &data, const indirect_array_type &ia, int):
1202             data_ (data), ia_ (ia.preprocess (data.size ())) {}
1203 
1204         // Accessors
1205         BOOST_UBLAS_INLINE
1206         size_type size () const {
1207             return ia_.size ();
1208         }
1209         BOOST_UBLAS_INLINE
1210         const_indirect_array_type &indirect () const {
1211             return ia_;
1212         }
1213         BOOST_UBLAS_INLINE
1214         indirect_array_type &indirect () {
1215             return ia_;
1216         }
1217 
1218         // Storage accessors
1219         BOOST_UBLAS_INLINE
1220         const vector_closure_type &data () const {
1221             return data_;
1222         }
1223         BOOST_UBLAS_INLINE
1224         vector_closure_type &data () {
1225             return data_;
1226         }
1227 
1228         // Element access
1229 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1230         BOOST_UBLAS_INLINE
1231         const_reference operator () (size_type i) const {
1232             return data_ (ia_ (i));
1233         }
1234         BOOST_UBLAS_INLINE
1235         reference operator () (size_type i) {
1236             return data_ (ia_ (i));
1237         }
1238 
1239         BOOST_UBLAS_INLINE
1240         const_reference operator [] (size_type i) const {
1241             return (*this) (i);
1242         }
1243         BOOST_UBLAS_INLINE
1244         reference operator [] (size_type i) {
1245             return (*this) (i);
1246         }
1247 #else
1248         BOOST_UBLAS_INLINE
1249         reference operator () (size_type i) const {
1250             return data_ (ia_ (i));
1251         }
1252 
1253         BOOST_UBLAS_INLINE
1254         reference operator [] (size_type i) const {
1255             return (*this) (i);
1256         }
1257 #endif
1258 
1259         // ISSUE can this be done in free project function?
1260         // Although a const function can create a non-const proxy to a non-const object
1261         // Critical is that vector_type and data_ (vector_closure_type) are const correct
1262         BOOST_UBLAS_INLINE
1263         vector_indirect<vector_type, indirect_array_type> project (const range_type &r) const {
1264             return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (r.preprocess (data_.size ())), 0);
1265         }
1266         BOOST_UBLAS_INLINE
1267         vector_indirect<vector_type, indirect_array_type> project (const slice_type &s) const {
1268             return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (s.preprocess (data_.size ())), 0);
1269         }
1270         BOOST_UBLAS_INLINE
1271         vector_indirect<vector_type, indirect_array_type> project (const indirect_array_type &ia) const {
1272             return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (ia.preprocess (data_.size ())), 0);
1273         }
1274 
1275         // Assignment
1276         BOOST_UBLAS_INLINE
1277         vector_indirect &operator = (const vector_indirect &vi) {
1278             // ISSUE need a temporary, proxy can be overlaping alias
1279             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vi));
1280             return *this;
1281         }
1282         BOOST_UBLAS_INLINE
1283         vector_indirect &assign_temporary (vector_indirect &vi) {
1284             // assign elements, proxied container remains the same
1285             vector_assign<scalar_assign> (*this, vi);
1286             return *this;
1287         }
1288         template<class AE>
1289         BOOST_UBLAS_INLINE
1290         vector_indirect &operator = (const vector_expression<AE> &ae) {
1291             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
1292             return *this;
1293         }
1294         template<class AE>
1295         BOOST_UBLAS_INLINE
1296         vector_indirect &assign (const vector_expression<AE> &ae) {
1297             vector_assign<scalar_assign> (*this, ae);
1298             return *this;
1299         }
1300         template<class AE>
1301         BOOST_UBLAS_INLINE
1302         vector_indirect &operator += (const vector_expression<AE> &ae) {
1303             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
1304             return *this;
1305         }
1306         template<class AE>
1307         BOOST_UBLAS_INLINE
1308         vector_indirect &plus_assign (const vector_expression<AE> &ae) {
1309             vector_assign<scalar_plus_assign> (*this, ae);
1310             return *this;
1311         }
1312         template<class AE>
1313         BOOST_UBLAS_INLINE
1314         vector_indirect &operator -= (const vector_expression<AE> &ae) {
1315             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
1316             return *this;
1317         }
1318         template<class AE>
1319         BOOST_UBLAS_INLINE
1320         vector_indirect &minus_assign (const vector_expression<AE> &ae) {
1321             vector_assign<scalar_minus_assign> (*this, ae);
1322             return *this;
1323         }
1324         template<class AT>
1325         BOOST_UBLAS_INLINE
1326         vector_indirect &operator *= (const AT &at) {
1327             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
1328             return *this;
1329         }
1330         template<class AT>
1331         BOOST_UBLAS_INLINE
1332         vector_indirect &operator /= (const AT &at) {
1333             vector_assign_scalar<scalar_divides_assign> (*this, at);
1334             return *this;
1335         }
1336 
1337         // Closure comparison
1338         BOOST_UBLAS_INLINE
1339         bool same_closure (const vector_indirect &/*vr*/) const {
1340             return true;
1341         }
1342 
1343         // Comparison
1344         BOOST_UBLAS_INLINE
1345         bool operator == (const vector_indirect &vi) const {
1346             return (*this).data_ == vi.data_ && ia_ == vi.ia_;
1347         }
1348 
1349         // Swapping
1350         BOOST_UBLAS_INLINE
1351         void swap (vector_indirect vi) {
1352             if (this != &vi) {
1353                 BOOST_UBLAS_CHECK (size () == vi.size (), bad_size ());
1354                 // Sparse ranges may be nonconformant now.
1355                 // std::swap_ranges (begin (), end (), vi.begin ());
1356                 vector_swap<scalar_swap> (*this, vi);
1357             }
1358         }
1359         BOOST_UBLAS_INLINE
1360         friend void swap (vector_indirect vi1, vector_indirect vi2) {
1361             vi1.swap (vi2);
1362         }
1363 
1364         // Iterator types
1365     private:
1366         // Use indirect array as an index - FIXME this fails for packed assignment
1367         typedef typename IA::const_iterator const_subiterator_type;
1368         typedef typename IA::const_iterator subiterator_type;
1369 
1370     public:
1371 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1372         typedef indexed_iterator<vector_indirect<vector_type, indirect_array_type>,
1373                                  typename vector_type::iterator::iterator_category> iterator;
1374         typedef indexed_const_iterator<vector_indirect<vector_type, indirect_array_type>,
1375                                        typename vector_type::const_iterator::iterator_category> const_iterator;
1376 #else
1377         class const_iterator;
1378         class iterator;
1379 #endif
1380         // Element lookup
1381         BOOST_UBLAS_INLINE
1382         const_iterator find (size_type i) const {
1383 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1384             return const_iterator (*this, i);
1385 #else
1386             return const_iterator (*this, ia_.begin () + i);
1387 #endif
1388         }
1389         BOOST_UBLAS_INLINE
1390         iterator find (size_type i) {
1391 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1392             return iterator (*this, i);
1393 #else
1394             return iterator (*this, ia_.begin () + i);
1395 #endif
1396         }
1397 
1398         // Iterators simply are indices.
1399 
1400 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1401         class const_iterator:
1402             public container_const_reference<vector_indirect>,
1403             public iterator_base_traits<typename V::const_iterator::iterator_category>::template
1404                         iterator_base<const_iterator, value_type>::type {
1405         public:
1406             typedef typename V::const_iterator::difference_type difference_type;
1407             typedef typename V::const_iterator::value_type value_type;
1408             typedef typename V::const_reference reference;    //FIXME due to indexing access
1409             typedef typename V::const_iterator::pointer pointer;
1410 
1411             // Construction and destruction
1412             BOOST_UBLAS_INLINE
1413             const_iterator ():
1414                 container_const_reference<self_type> (), it_ () {}
1415             BOOST_UBLAS_INLINE
1416             const_iterator (const self_type &vi, const const_subiterator_type &it):
1417                 container_const_reference<self_type> (vi), it_ (it) {}
1418             BOOST_UBLAS_INLINE
1419             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
1420                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
1421 
1422             // Arithmetic
1423             BOOST_UBLAS_INLINE
1424             const_iterator &operator ++ () {
1425                 ++ it_;
1426                 return *this;
1427             }
1428             BOOST_UBLAS_INLINE
1429             const_iterator &operator -- () {
1430                 -- it_;
1431                 return *this;
1432             }
1433             BOOST_UBLAS_INLINE
1434             const_iterator &operator += (difference_type n) {
1435                 it_ += n;
1436                 return *this;
1437             }
1438             BOOST_UBLAS_INLINE
1439             const_iterator &operator -= (difference_type n) {
1440                 it_ -= n;
1441                 return *this;
1442             }
1443             BOOST_UBLAS_INLINE
1444             difference_type operator - (const const_iterator &it) const {
1445                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1446                 return it_ - it.it_;
1447             }
1448 
1449             // Dereference
1450             BOOST_UBLAS_INLINE
1451             const_reference operator * () const {
1452                 // FIXME replace find with at_element
1453                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1454                 return (*this) ().data_ (*it_);
1455             }
1456             BOOST_UBLAS_INLINE
1457             const_reference operator [] (difference_type n) const {
1458                 return *(*this + n);
1459             }
1460 
1461             // Index
1462             BOOST_UBLAS_INLINE
1463             size_type index () const {
1464                 return it_.index ();
1465             }
1466 
1467             // Assignment
1468             BOOST_UBLAS_INLINE
1469             const_iterator &operator = (const const_iterator &it) {
1470                 container_const_reference<self_type>::assign (&it ());
1471                 it_ = it.it_;
1472                 return *this;
1473             }
1474 
1475             // Comparison
1476             BOOST_UBLAS_INLINE
1477             bool operator == (const const_iterator &it) const {
1478                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1479                 return it_ == it.it_;
1480             }
1481             BOOST_UBLAS_INLINE
1482             bool operator < (const const_iterator &it) const {
1483                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1484                 return it_ < it.it_;
1485             }
1486 
1487         private:
1488             const_subiterator_type it_;
1489         };
1490 #endif
1491 
1492         BOOST_UBLAS_INLINE
1493         const_iterator begin () const {
1494             return find (0);
1495         }
1496         BOOST_UBLAS_INLINE
1497         const_iterator cbegin () const {
1498             return begin ();
1499         }
1500         BOOST_UBLAS_INLINE
1501         const_iterator end () const {
1502             return find (size ());
1503         }
1504         BOOST_UBLAS_INLINE
1505         const_iterator cend () const {
1506             return end ();
1507         }
1508 
1509 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1510         class iterator:
1511             public container_reference<vector_indirect>,
1512             public iterator_base_traits<typename V::iterator::iterator_category>::template
1513                         iterator_base<iterator, value_type>::type {
1514         public:
1515             typedef typename V::iterator::difference_type difference_type;
1516             typedef typename V::iterator::value_type value_type;
1517             typedef typename V::reference reference;    //FIXME due to indexing access
1518             typedef typename V::iterator::pointer pointer;
1519 
1520             // Construction and destruction
1521             BOOST_UBLAS_INLINE
1522             iterator ():
1523                 container_reference<self_type> (), it_ () {}
1524             BOOST_UBLAS_INLINE
1525             iterator (self_type &vi, const subiterator_type &it):
1526                 container_reference<self_type> (vi), it_ (it) {}
1527 
1528             // Arithmetic
1529             BOOST_UBLAS_INLINE
1530             iterator &operator ++ () {
1531                 ++ it_;
1532                 return *this;
1533             }
1534             BOOST_UBLAS_INLINE
1535             iterator &operator -- () {
1536                 -- it_;
1537                 return *this;
1538             }
1539             BOOST_UBLAS_INLINE
1540             iterator &operator += (difference_type n) {
1541                 it_ += n;
1542                 return *this;
1543             }
1544             BOOST_UBLAS_INLINE
1545             iterator &operator -= (difference_type n) {
1546                 it_ -= n;
1547                 return *this;
1548             }
1549             BOOST_UBLAS_INLINE
1550             difference_type operator - (const iterator &it) const {
1551                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1552                 return it_ - it.it_;
1553             }
1554 
1555             // Dereference
1556             BOOST_UBLAS_INLINE
1557             reference operator * () const {
1558                 // FIXME replace find with at_element
1559                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1560                 return (*this) ().data_ (*it_);
1561             }
1562             BOOST_UBLAS_INLINE
1563             reference operator [] (difference_type n) const {
1564                 return *(*this + n);
1565             }
1566 
1567             // Index
1568             BOOST_UBLAS_INLINE
1569             size_type index () const {
1570                 return it_.index ();
1571             }
1572 
1573             // Assignment
1574             BOOST_UBLAS_INLINE
1575             iterator &operator = (const iterator &it) {
1576                 container_reference<self_type>::assign (&it ());
1577                 it_ = it.it_;
1578                 return *this;
1579             }
1580 
1581             // Comparison
1582             BOOST_UBLAS_INLINE
1583             bool operator == (const iterator &it) const {
1584                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1585                 return it_ == it.it_;
1586             }
1587             BOOST_UBLAS_INLINE
1588             bool operator < (const iterator &it) const {
1589                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1590                 return it_ < it.it_;
1591             }
1592 
1593         private:
1594             subiterator_type it_;
1595 
1596             friend class const_iterator;
1597         };
1598 #endif
1599 
1600         BOOST_UBLAS_INLINE
1601         iterator begin () {
1602             return find (0);
1603         }
1604         BOOST_UBLAS_INLINE
1605         iterator end () {
1606             return find (size ());
1607         }
1608 
1609         // Reverse iterator
1610         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1611         typedef reverse_iterator_base<iterator> reverse_iterator;
1612 
1613         BOOST_UBLAS_INLINE
1614         const_reverse_iterator rbegin () const {
1615             return const_reverse_iterator (end ());
1616         }
1617         BOOST_UBLAS_INLINE
1618         const_reverse_iterator crbegin () const {
1619             return rbegin ();
1620         }
1621         BOOST_UBLAS_INLINE
1622         const_reverse_iterator rend () const {
1623             return const_reverse_iterator (begin ());
1624         }
1625         BOOST_UBLAS_INLINE
1626         const_reverse_iterator crend () const {
1627             return rend ();
1628         }
1629 
1630         BOOST_UBLAS_INLINE
1631         reverse_iterator rbegin () {
1632             return reverse_iterator (end ());
1633         }
1634         BOOST_UBLAS_INLINE
1635         reverse_iterator rend () {
1636             return reverse_iterator (begin ());
1637         }
1638 
1639     private:
1640         vector_closure_type data_;
1641         indirect_array_type ia_;
1642     };
1643 
1644     // Projections
1645     template<class V, class A>
1646     BOOST_UBLAS_INLINE
1647     vector_indirect<V, indirect_array<A> > project (V &data, const indirect_array<A> &ia) {
1648         return vector_indirect<V, indirect_array<A> > (data, ia);
1649     }
1650     template<class V, class A>
1651     BOOST_UBLAS_INLINE
1652     const vector_indirect<const V, indirect_array<A> > project (const V &data, const indirect_array<A> &ia) {
1653         // ISSUE was: return vector_indirect<V, indirect_array<A> > (const_cast<V &> (data), ia)
1654         return vector_indirect<const V, indirect_array<A> > (data, ia);
1655     }
1656     template<class V, class IA>
1657     BOOST_UBLAS_INLINE
1658     vector_indirect<V, IA> project (vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::range_type &r) {
1659         return data.project (r);
1660     }
1661     template<class V, class IA>
1662     BOOST_UBLAS_INLINE
1663     const vector_indirect<V, IA> project (const vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::range_type &r) {
1664         return data.project (r);
1665     }
1666     template<class V, class IA>
1667     BOOST_UBLAS_INLINE
1668     vector_indirect<V, IA> project (vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::slice_type &s) {
1669         return data.project (s);
1670     }
1671     template<class V, class IA>
1672     BOOST_UBLAS_INLINE
1673     const vector_indirect<V, IA> project (const vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::slice_type &s) {
1674         return data.project (s);
1675     }
1676     template<class V, class A>
1677     BOOST_UBLAS_INLINE
1678     vector_indirect<V, indirect_array<A> > project (vector_indirect<V, indirect_array<A> > &data, const indirect_array<A> &ia) {
1679         return data.project (ia);
1680     }
1681     template<class V, class A>
1682     BOOST_UBLAS_INLINE
1683     const vector_indirect<V, indirect_array<A> > project (const vector_indirect<V, indirect_array<A> > &data, const indirect_array<A> &ia) {
1684         return data.project (ia);
1685     }
1686 
1687     // Specialization of temporary_traits
1688     template <class V>
1689     struct vector_temporary_traits< vector_indirect<V> >
1690     : vector_temporary_traits< V > {} ;
1691     template <class V>
1692     struct vector_temporary_traits< const vector_indirect<V> >
1693     : vector_temporary_traits< V > {} ;
1694 
1695 }}}
1696 
1697 #endif