Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / numeric / ublas / vector_proxy.hpp
1 //
2 //  Copyright (c) 2000-2002
3 //  Joerg Walter, Mathias Koch
4 //
5 //  Distributed under the Boost Software License, Version 1.0. (See
6 //  accompanying file LICENSE_1_0.txt or copy at
7 //  http://www.boost.org/LICENSE_1_0.txt)
8 //
9 //  The authors gratefully acknowledge the support of
10 //  GeNeSys mbH & Co. KG in producing this work.
11 //
12
13 #ifndef _BOOST_UBLAS_VECTOR_PROXY_
14 #define _BOOST_UBLAS_VECTOR_PROXY_
15
16 #include <boost/numeric/ublas/vector_expression.hpp>
17 #include <boost/numeric/ublas/detail/vector_assign.hpp>
18 #include <boost/numeric/ublas/detail/temporary.hpp>
19
20 // Iterators based on ideas of Jeremy Siek
21
22 namespace boost { namespace numeric { namespace ublas {
23
24     /** \brief A vector referencing a continuous subvector of elements of vector \c v containing all elements specified by \c range.
25      *
26      * A vector range can be used as a normal vector in any expression. 
27      * If the specified range falls outside that of the index range of the vector, then
28      * the \c vector_range is not a well formed \i Vector \i Expression and access to an 
29      * element outside of index range of the vector is \b undefined.
30      *
31      * \tparam V the type of vector referenced (for example \c vector<double>)
32      */
33     template<class V>
34     class vector_range:
35         public vector_expression<vector_range<V> > {
36
37         typedef vector_range<V> self_type;
38     public:
39 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
40         using vector_expression<self_type>::operator ();
41 #endif
42         typedef const V const_vector_type;
43         typedef V vector_type;
44         typedef typename V::size_type size_type;
45         typedef typename V::difference_type difference_type;
46         typedef typename V::value_type value_type;
47         typedef typename V::const_reference const_reference;
48         typedef typename boost::mpl::if_<boost::is_const<V>,
49                                           typename V::const_reference,
50                                           typename V::reference>::type reference;
51         typedef typename boost::mpl::if_<boost::is_const<V>,
52                                           typename V::const_closure_type,
53                                           typename V::closure_type>::type vector_closure_type;
54         typedef basic_range<size_type, difference_type> range_type;
55         typedef const self_type const_closure_type;
56         typedef self_type closure_type;
57         typedef typename storage_restrict_traits<typename V::storage_category,
58                                                  dense_proxy_tag>::storage_category storage_category;
59
60         // Construction and destruction
61         BOOST_UBLAS_INLINE
62         vector_range (vector_type &data, const range_type &r):
63             data_ (data), r_ (r.preprocess (data.size ())) {
64             // Early checking of preconditions here.
65             // BOOST_UBLAS_CHECK (r_.start () <= data_.size () &&
66             //                   r_.start () + r_.size () <= data_.size (), bad_index ());
67         }
68         BOOST_UBLAS_INLINE
69         vector_range (const vector_closure_type &data, const range_type &r, bool):
70             data_ (data), r_ (r.preprocess (data.size ())) {
71             // Early checking of preconditions here.
72             // BOOST_UBLAS_CHECK (r_.start () <= data_.size () &&
73             //                    r_.start () + r_.size () <= data_.size (), bad_index ());
74         }
75
76         // Accessors
77         BOOST_UBLAS_INLINE
78         size_type start () const {
79             return r_.start ();
80         }
81         BOOST_UBLAS_INLINE
82         size_type size () const {
83             return r_.size ();
84         }
85
86         // Storage accessors
87         BOOST_UBLAS_INLINE
88         const vector_closure_type &data () const {
89             return data_;
90         }
91         BOOST_UBLAS_INLINE
92         vector_closure_type &data () {
93             return data_;
94         }
95
96         // Element access
97 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
98         BOOST_UBLAS_INLINE
99         const_reference operator () (size_type i) const {
100             return data_ (r_ (i));
101         }
102         BOOST_UBLAS_INLINE
103         reference operator () (size_type i) {
104             return data_ (r_ (i));
105         }
106
107         BOOST_UBLAS_INLINE
108         const_reference operator [] (size_type i) const {
109             return (*this) (i);
110         }
111         BOOST_UBLAS_INLINE
112         reference operator [] (size_type i) {
113             return (*this) (i);
114         }
115 #else
116         BOOST_UBLAS_INLINE
117         reference operator () (size_type i) const {
118             return data_ (r_ (i));
119         }
120
121         BOOST_UBLAS_INLINE
122         reference operator [] (size_type i) const {
123             return (*this) (i);
124         }
125 #endif
126
127         // ISSUE can this be done in free project function?
128         // Although a const function can create a non-const proxy to a non-const object
129         // Critical is that vector_type and data_ (vector_closure_type) are const correct
130         BOOST_UBLAS_INLINE
131         vector_range<vector_type> project (const range_type &r) const {
132             return vector_range<vector_type> (data_, r_.compose (r.preprocess (data_.size ())), false);
133         }
134
135         // Assignment
136         BOOST_UBLAS_INLINE
137         vector_range &operator = (const vector_range &vr) {
138             // ISSUE need a temporary, proxy can be overlaping alias
139             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vr));
140             return *this;
141         }
142         BOOST_UBLAS_INLINE
143         vector_range &assign_temporary (vector_range &vr) {
144             // assign elements, proxied container remains the same
145             vector_assign<scalar_assign> (*this, vr);
146             return *this;
147         }
148         template<class AE>
149         BOOST_UBLAS_INLINE
150         vector_range &operator = (const vector_expression<AE> &ae) {
151             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
152             return *this;
153         }
154         template<class AE>
155         BOOST_UBLAS_INLINE
156         vector_range &assign (const vector_expression<AE> &ae) {
157             vector_assign<scalar_assign> (*this, ae);
158             return *this;
159         }
160         template<class AE>
161         BOOST_UBLAS_INLINE
162         vector_range &operator += (const vector_expression<AE> &ae) {
163             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
164             return *this;
165         }
166         template<class AE>
167         BOOST_UBLAS_INLINE
168         vector_range &plus_assign (const vector_expression<AE> &ae) {
169             vector_assign<scalar_plus_assign> (*this, ae);
170             return *this;
171         }
172         template<class AE>
173         BOOST_UBLAS_INLINE
174         vector_range &operator -= (const vector_expression<AE> &ae) {
175             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
176             return *this;
177         }
178         template<class AE>
179         BOOST_UBLAS_INLINE
180         vector_range &minus_assign (const vector_expression<AE> &ae) {
181             vector_assign<scalar_minus_assign> (*this, ae);
182             return *this;
183         }
184         template<class AT>
185         BOOST_UBLAS_INLINE
186         vector_range &operator *= (const AT &at) {
187             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
188             return *this;
189         }
190         template<class AT>
191         BOOST_UBLAS_INLINE
192         vector_range &operator /= (const AT &at) {
193             vector_assign_scalar<scalar_divides_assign> (*this, at);
194             return *this;
195         }
196
197         // Closure comparison
198         BOOST_UBLAS_INLINE
199         bool same_closure (const vector_range &vr) const {
200             return (*this).data_.same_closure (vr.data_);
201         }
202
203         // Comparison
204         BOOST_UBLAS_INLINE
205         bool operator == (const vector_range &vr) const {
206             return (*this).data_ == vr.data_ && r_ == vr.r_;
207         }
208
209         // Swapping
210         BOOST_UBLAS_INLINE
211         void swap (vector_range vr) {
212             if (this != &vr) {
213                 BOOST_UBLAS_CHECK (size () == vr.size (), bad_size ());
214                 // Sparse ranges may be nonconformant now.
215                 // std::swap_ranges (begin (), end (), vr.begin ());
216                 vector_swap<scalar_swap> (*this, vr);
217             }
218         }
219         BOOST_UBLAS_INLINE
220         friend void swap (vector_range vr1, vector_range vr2) {
221             vr1.swap (vr2);
222         }
223
224         // Iterator types
225     private:
226         typedef typename V::const_iterator const_subiterator_type;
227         typedef typename boost::mpl::if_<boost::is_const<V>,
228                                           typename V::const_iterator,
229                                           typename V::iterator>::type subiterator_type;
230
231     public:
232 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
233         typedef indexed_iterator<vector_range<vector_type>,
234                                  typename subiterator_type::iterator_category> iterator;
235         typedef indexed_const_iterator<vector_range<vector_type>,
236                                        typename const_subiterator_type::iterator_category> const_iterator;
237 #else
238         class const_iterator;
239         class iterator;
240 #endif
241
242         // Element lookup
243         BOOST_UBLAS_INLINE
244         const_iterator find (size_type i) const {
245             const_subiterator_type it (data_.find (start () + i));
246 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
247             return const_iterator (*this, it.index ());
248 #else
249             return const_iterator (*this, it);
250 #endif
251         }
252         BOOST_UBLAS_INLINE
253         iterator find (size_type i) {
254             subiterator_type it (data_.find (start () + i));
255 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
256             return iterator (*this, it.index ());
257 #else
258             return iterator (*this, it);
259 #endif
260         }
261
262 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
263         class const_iterator:
264             public container_const_reference<vector_range>,
265             public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
266                         iterator_base<const_iterator, value_type>::type {
267         public:
268             typedef typename const_subiterator_type::difference_type difference_type;
269             typedef typename const_subiterator_type::value_type value_type;
270             typedef typename const_subiterator_type::reference reference;
271             typedef typename const_subiterator_type::pointer pointer;
272
273             // Construction and destruction
274             BOOST_UBLAS_INLINE
275             const_iterator ():
276                 container_const_reference<self_type> (), it_ () {}
277             BOOST_UBLAS_INLINE
278             const_iterator (const self_type &vr, const const_subiterator_type &it):
279                 container_const_reference<self_type> (vr), it_ (it) {}
280             BOOST_UBLAS_INLINE
281             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
282                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
283
284             // Arithmetic
285             BOOST_UBLAS_INLINE
286             const_iterator &operator ++ () {
287                 ++ it_;
288                 return *this;
289             }
290             BOOST_UBLAS_INLINE
291             const_iterator &operator -- () {
292                 -- it_;
293                 return *this;
294             }
295             BOOST_UBLAS_INLINE
296             const_iterator &operator += (difference_type n) {
297                 it_ += n;
298                 return *this;
299             }
300             BOOST_UBLAS_INLINE
301             const_iterator &operator -= (difference_type n) {
302                 it_ -= n;
303                 return *this;
304             }
305             BOOST_UBLAS_INLINE
306             difference_type operator - (const const_iterator &it) const {
307                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
308                 return it_ - it.it_;
309             }
310
311             // Dereference
312             BOOST_UBLAS_INLINE
313             const_reference operator * () const {
314                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
315                 return *it_;
316             }
317             BOOST_UBLAS_INLINE
318             const_reference operator [] (difference_type n) const {
319                 return *(*this + n);
320             }
321
322             // Index
323             BOOST_UBLAS_INLINE
324             size_type index () const {
325                 return it_.index () - (*this) ().start ();
326             }
327
328             // Assignment
329             BOOST_UBLAS_INLINE
330             const_iterator &operator = (const const_iterator &it) {
331                 container_const_reference<self_type>::assign (&it ());
332                 it_ = it.it_;
333                 return *this;
334             }
335
336             // Comparison
337             BOOST_UBLAS_INLINE
338             bool operator == (const const_iterator &it) const {
339                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
340                 return it_ == it.it_;
341             }
342             BOOST_UBLAS_INLINE
343             bool operator < (const const_iterator &it) const {
344                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
345                 return it_ < it.it_;
346             }
347
348         private:
349             const_subiterator_type it_;
350         };
351 #endif
352
353         BOOST_UBLAS_INLINE
354         const_iterator begin () const {
355             return find (0);
356         }
357         BOOST_UBLAS_INLINE
358         const_iterator cbegin () const {
359             return begin ();
360         }
361         BOOST_UBLAS_INLINE
362         const_iterator end () const {
363             return find (size ());
364         }
365         BOOST_UBLAS_INLINE
366         const_iterator cend () const {
367             return end ();
368         }
369
370 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
371         class iterator:
372             public container_reference<vector_range>,
373             public iterator_base_traits<typename subiterator_type::iterator_category>::template
374                         iterator_base<iterator, value_type>::type {
375         public:
376             typedef typename subiterator_type::difference_type difference_type;
377             typedef typename subiterator_type::value_type value_type;
378             typedef typename subiterator_type::reference reference;
379             typedef typename subiterator_type::pointer pointer;
380
381             // Construction and destruction
382             BOOST_UBLAS_INLINE
383             iterator ():
384                 container_reference<self_type> (), it_ () {}
385             BOOST_UBLAS_INLINE
386             iterator (self_type &vr, const subiterator_type &it):
387                 container_reference<self_type> (vr), it_ (it) {}
388
389             // Arithmetic
390             BOOST_UBLAS_INLINE
391             iterator &operator ++ () {
392                 ++ it_;
393                 return *this;
394             }
395             BOOST_UBLAS_INLINE
396             iterator &operator -- () {
397                 -- it_;
398                 return *this;
399             }
400             BOOST_UBLAS_INLINE
401             iterator &operator += (difference_type n) {
402                 it_ += n;
403                 return *this;
404             }
405             BOOST_UBLAS_INLINE
406             iterator &operator -= (difference_type n) {
407                 it_ -= n;
408                 return *this;
409             }
410             BOOST_UBLAS_INLINE
411             difference_type operator - (const iterator &it) const {
412                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
413                 return it_ - it.it_;
414             }
415
416             // Dereference
417             BOOST_UBLAS_INLINE
418             reference operator * () const {
419                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
420                 return *it_;
421             }
422             BOOST_UBLAS_INLINE
423             reference operator [] (difference_type n) const {
424                 return *(*this + n);
425             }
426
427             // Index
428             BOOST_UBLAS_INLINE
429             size_type index () const {
430                 return it_.index () - (*this) ().start ();
431             }
432
433             // Assignment
434             BOOST_UBLAS_INLINE
435             iterator &operator = (const iterator &it) {
436                 container_reference<self_type>::assign (&it ());
437                 it_ = it.it_;
438                 return *this;
439             }
440
441             // Comparison
442             BOOST_UBLAS_INLINE
443             bool operator == (const iterator &it) const {
444                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
445                 return it_ == it.it_;
446             }
447             BOOST_UBLAS_INLINE
448             bool operator < (const iterator &it) const {
449                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
450                 return it_ < it.it_;
451             }
452
453         private:
454             subiterator_type it_;
455
456             friend class const_iterator;
457         };
458 #endif
459
460         BOOST_UBLAS_INLINE
461         iterator begin () {
462             return find (0);
463         }
464         BOOST_UBLAS_INLINE
465         iterator end () {
466             return find (size ());
467         }
468
469         // Reverse iterator
470         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
471         typedef reverse_iterator_base<iterator> reverse_iterator;
472
473         BOOST_UBLAS_INLINE
474         const_reverse_iterator rbegin () const {
475             return const_reverse_iterator (end ());
476         }
477         BOOST_UBLAS_INLINE
478         const_reverse_iterator crbegin () const {
479             return rbegin ();
480         }
481         BOOST_UBLAS_INLINE
482         const_reverse_iterator rend () const {
483             return const_reverse_iterator (begin ());
484         }
485         BOOST_UBLAS_INLINE
486         const_reverse_iterator crend () const {
487             return rend ();
488         }
489
490         BOOST_UBLAS_INLINE
491         reverse_iterator rbegin () {
492             return reverse_iterator (end ());
493         }
494         BOOST_UBLAS_INLINE
495         reverse_iterator rend () {
496             return reverse_iterator (begin ());
497         }
498
499     private:
500         vector_closure_type data_;
501         range_type r_;
502     };
503
504     // ------------------
505     // Simple Projections
506     // ------------------
507
508     /** \brief Return a \c vector_range on a specified vector, a start and stop index.
509      * 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.
510      * 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
511      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
512      */
513     template<class V>
514     BOOST_UBLAS_INLINE
515     vector_range<V> subrange (V &data, typename V::size_type start, typename V::size_type stop) {
516         typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
517         return vector_range<V> (data, range_type (start, stop));
518     }
519
520     /** \brief Return a \c const \c vector_range on a specified vector, a start and stop index.
521      * 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.
522      *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
523      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
524      */
525     template<class V>
526     BOOST_UBLAS_INLINE
527     vector_range<const V> subrange (const V &data, typename V::size_type start, typename V::size_type stop) {
528         typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
529         return vector_range<const V> (data, range_type (start, stop));
530     }
531
532     // -------------------
533     // Generic Projections
534     // -------------------
535     
536     /** \brief Return a \c const \c vector_range on a specified vector and \c range
537      * 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.
538      * 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
539      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
540      */
541     template<class V>
542     BOOST_UBLAS_INLINE
543     vector_range<V> project (V &data, typename vector_range<V>::range_type const &r) {
544         return vector_range<V> (data, r);
545     }
546
547     /** \brief Return a \c vector_range on a specified vector and \c range
548      * Return a \c vector_range on a specified vector and \c range. The resulting \c vector_range can be manipulated like a normal vector.
549      * 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
550      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
551      */
552     template<class V>
553     BOOST_UBLAS_INLINE
554     const vector_range<const V> project (const V &data, typename vector_range<V>::range_type const &r) {
555         // ISSUE was: return vector_range<V> (const_cast<V &> (data), r);
556         return vector_range<const V> (data, r);
557    }
558
559     /** \brief Return a \c const \c vector_range on a specified vector and const \c range
560      * 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.
561      * 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
562      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
563      */
564     template<class V>
565     BOOST_UBLAS_INLINE
566     vector_range<V> project (vector_range<V> &data, const typename vector_range<V>::range_type &r) {
567         return data.project (r);
568     }
569
570     /** \brief Return a \c vector_range on a specified vector and const \c range
571      * 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.
572      * 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
573      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
574      */
575     template<class V>
576     BOOST_UBLAS_INLINE
577     const vector_range<V> project (const vector_range<V> &data, const typename vector_range<V>::range_type &r) {
578         return data.project (r);
579     }
580
581     // Specialization of temporary_traits
582     template <class V>
583     struct vector_temporary_traits< vector_range<V> >
584     : vector_temporary_traits< V > {} ;
585     template <class V>
586     struct vector_temporary_traits< const vector_range<V> >
587     : vector_temporary_traits< V > {} ;
588
589
590     /** \brief A vector referencing a non continuous subvector of elements of vector v containing all elements specified by \c slice.
591      *
592      * A vector slice can be used as a normal vector in any expression.
593      * If the specified slice falls outside that of the index slice of the vector, then
594      * the \c vector_slice is not a well formed \i Vector \i Expression and access to an 
595      * element outside of index slice of the vector is \b undefined.
596      *
597      * A slice is a generalization of a range. In a range going from \f$a\f$ to \f$b\f$, 
598      * all elements belong to the range. In a slice, a \i \f$step\f$ can be specified meaning to
599      * take one element over \f$step\f$ in the range specified from \f$a\f$ to \f$b\f$.
600      * Obviously, a slice with a \f$step\f$ of 1 is equivalent to a range.
601      *
602      * \tparam V the type of vector referenced (for example \c vector<double>)
603      */
604     template<class V>
605     class vector_slice:
606         public vector_expression<vector_slice<V> > {
607
608         typedef vector_slice<V> self_type;
609     public:
610 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
611         using vector_expression<self_type>::operator ();
612 #endif
613         typedef const V const_vector_type;
614         typedef V vector_type;
615         typedef typename V::size_type size_type;
616         typedef typename V::difference_type difference_type;
617         typedef typename V::value_type value_type;
618         typedef typename V::const_reference const_reference;
619         typedef typename boost::mpl::if_<boost::is_const<V>,
620                                           typename V::const_reference,
621                                           typename V::reference>::type reference;
622         typedef typename boost::mpl::if_<boost::is_const<V>,
623                                           typename V::const_closure_type,
624                                           typename V::closure_type>::type vector_closure_type;
625         typedef basic_range<size_type, difference_type> range_type;
626         typedef basic_slice<size_type, difference_type> slice_type;
627         typedef const self_type const_closure_type;
628         typedef self_type closure_type;
629         typedef typename storage_restrict_traits<typename V::storage_category,
630                                                  dense_proxy_tag>::storage_category storage_category;
631
632         // Construction and destruction
633         BOOST_UBLAS_INLINE
634         vector_slice (vector_type &data, const slice_type &s):
635             data_ (data), s_ (s.preprocess (data.size ())) {
636             // Early checking of preconditions here.
637             // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
638             //                    s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
639         }
640         BOOST_UBLAS_INLINE
641         vector_slice (const vector_closure_type &data, const slice_type &s, int):
642             data_ (data), s_ (s.preprocess (data.size ())) {
643             // Early checking of preconditions here.
644             // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
645             //                    s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
646         }
647
648         // Accessors
649         BOOST_UBLAS_INLINE
650         size_type start () const {
651             return s_.start ();
652         }
653         BOOST_UBLAS_INLINE
654         difference_type stride () const {
655             return s_.stride ();
656         }
657         BOOST_UBLAS_INLINE
658         size_type size () const {
659             return s_.size ();
660         }
661
662         // Storage accessors
663         BOOST_UBLAS_INLINE
664         const vector_closure_type &data () const {
665             return data_;
666         }
667         BOOST_UBLAS_INLINE
668         vector_closure_type &data () {
669             return data_;
670         }
671
672         // Element access
673 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
674         BOOST_UBLAS_INLINE
675         const_reference operator () (size_type i) const {
676             return data_ (s_ (i));
677         }
678         BOOST_UBLAS_INLINE
679         reference operator () (size_type i) {
680             return data_ (s_ (i));
681         }
682
683         BOOST_UBLAS_INLINE
684         const_reference operator [] (size_type i) const {
685             return (*this) (i);
686         }
687         BOOST_UBLAS_INLINE
688         reference operator [] (size_type i) {
689             return (*this) (i);
690         }
691 #else
692         BOOST_UBLAS_INLINE
693         reference operator () (size_type i) const {
694             return data_ (s_ (i));
695         }
696
697         BOOST_UBLAS_INLINE
698         reference operator [] (size_type i) const {
699             return (*this) (i);
700         }
701 #endif
702
703         // ISSUE can this be done in free project function?
704         // Although a const function can create a non-const proxy to a non-const object
705         // Critical is that vector_type and data_ (vector_closure_type) are const correct
706         BOOST_UBLAS_INLINE
707         vector_slice<vector_type> project (const range_type &r) const {
708             return vector_slice<vector_type>  (data_, s_.compose (r.preprocess (data_.size ())), false);
709         }
710         BOOST_UBLAS_INLINE
711         vector_slice<vector_type> project (const slice_type &s) const {
712             return vector_slice<vector_type>  (data_, s_.compose (s.preprocess (data_.size ())), false);
713         }
714
715         // Assignment
716         BOOST_UBLAS_INLINE
717         vector_slice &operator = (const vector_slice &vs) {
718             // ISSUE need a temporary, proxy can be overlaping alias
719             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vs));
720             return *this;
721         }
722         BOOST_UBLAS_INLINE
723         vector_slice &assign_temporary (vector_slice &vs) {
724             // assign elements, proxied container remains the same
725             vector_assign<scalar_assign> (*this, vs);
726             return *this;
727         }
728         template<class AE>
729         BOOST_UBLAS_INLINE
730         vector_slice &operator = (const vector_expression<AE> &ae) {
731             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
732             return *this;
733         }
734         template<class AE>
735         BOOST_UBLAS_INLINE
736         vector_slice &assign (const vector_expression<AE> &ae) {
737             vector_assign<scalar_assign> (*this, ae);
738             return *this;
739         }
740         template<class AE>
741         BOOST_UBLAS_INLINE
742         vector_slice &operator += (const vector_expression<AE> &ae) {
743             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
744             return *this;
745         }
746         template<class AE>
747         BOOST_UBLAS_INLINE
748         vector_slice &plus_assign (const vector_expression<AE> &ae) {
749             vector_assign<scalar_plus_assign> (*this, ae);
750             return *this;
751         }
752         template<class AE>
753         BOOST_UBLAS_INLINE
754         vector_slice &operator -= (const vector_expression<AE> &ae) {
755             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
756             return *this;
757         }
758         template<class AE>
759         BOOST_UBLAS_INLINE
760         vector_slice &minus_assign (const vector_expression<AE> &ae) {
761             vector_assign<scalar_minus_assign> (*this, ae);
762             return *this;
763         }
764         template<class AT>
765         BOOST_UBLAS_INLINE
766         vector_slice &operator *= (const AT &at) {
767             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
768             return *this;
769         }
770         template<class AT>
771         BOOST_UBLAS_INLINE
772         vector_slice &operator /= (const AT &at) {
773             vector_assign_scalar<scalar_divides_assign> (*this, at);
774             return *this;
775         }
776
777         // Closure comparison
778         BOOST_UBLAS_INLINE
779         bool same_closure (const vector_slice &vr) const {
780             return (*this).data_.same_closure (vr.data_);
781         }
782
783         // Comparison
784         BOOST_UBLAS_INLINE
785         bool operator == (const vector_slice &vs) const {
786             return (*this).data_ == vs.data_ && s_ == vs.s_;
787         }
788
789         // Swapping
790         BOOST_UBLAS_INLINE
791         void swap (vector_slice vs) {
792             if (this != &vs) {
793                 BOOST_UBLAS_CHECK (size () == vs.size (), bad_size ());
794                 // Sparse ranges may be nonconformant now.
795                 // std::swap_ranges (begin (), end (), vs.begin ());
796                 vector_swap<scalar_swap> (*this, vs);
797             }
798         }
799         BOOST_UBLAS_INLINE
800         friend void swap (vector_slice vs1, vector_slice vs2) {
801             vs1.swap (vs2);
802         }
803
804         // Iterator types
805     private:
806         // Use slice as an index - FIXME this fails for packed assignment
807         typedef typename slice_type::const_iterator const_subiterator_type;
808         typedef typename slice_type::const_iterator subiterator_type;
809
810     public:
811 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
812         typedef indexed_iterator<vector_slice<vector_type>,
813                                  typename vector_type::iterator::iterator_category> iterator;
814         typedef indexed_const_iterator<vector_slice<vector_type>,
815                                        typename vector_type::const_iterator::iterator_category> const_iterator;
816 #else
817         class const_iterator;
818         class iterator;
819 #endif
820
821         // Element lookup
822         BOOST_UBLAS_INLINE
823         const_iterator find (size_type i) const {
824 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
825             return const_iterator (*this, i);
826 #else
827             return const_iterator (*this, s_.begin () + i);
828 #endif
829         }
830         BOOST_UBLAS_INLINE
831         iterator find (size_type i) {
832 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
833             return iterator (*this, i);
834 #else
835             return iterator (*this, s_.begin () + i);
836 #endif
837         }
838
839 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
840         class const_iterator:
841             public container_const_reference<vector_slice>,
842             public iterator_base_traits<typename V::const_iterator::iterator_category>::template
843                         iterator_base<const_iterator, value_type>::type {
844         public:
845             typedef typename V::const_iterator::difference_type difference_type;
846             typedef typename V::const_iterator::value_type value_type;
847             typedef typename V::const_reference reference;    //FIXME due to indexing access
848             typedef typename V::const_iterator::pointer pointer;
849
850             // Construction and destruction
851             BOOST_UBLAS_INLINE
852             const_iterator ():
853                 container_const_reference<self_type> (), it_ () {}
854             BOOST_UBLAS_INLINE
855             const_iterator (const self_type &vs, const const_subiterator_type &it):
856                 container_const_reference<self_type> (vs), it_ (it) {}
857             BOOST_UBLAS_INLINE
858             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
859                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
860
861             // Arithmetic
862             BOOST_UBLAS_INLINE
863             const_iterator &operator ++ () {
864                 ++ it_;
865                 return *this;
866             }
867             BOOST_UBLAS_INLINE
868             const_iterator &operator -- () {
869                 -- it_;
870                 return *this;
871             }
872             BOOST_UBLAS_INLINE
873             const_iterator &operator += (difference_type n) {
874                 it_ += n;
875                 return *this;
876             }
877             BOOST_UBLAS_INLINE
878             const_iterator &operator -= (difference_type n) {
879                 it_ -= n;
880                 return *this;
881             }
882             BOOST_UBLAS_INLINE
883             difference_type operator - (const const_iterator &it) const {
884                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
885                 return it_ - it.it_;
886             }
887
888             // Dereference
889             BOOST_UBLAS_INLINE
890             const_reference operator * () const {
891                 // FIXME replace find with at_element
892                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
893                 return (*this) ().data_ (*it_);
894             }
895             BOOST_UBLAS_INLINE
896             const_reference operator [] (difference_type n) const {
897                 return *(*this + n);
898             }
899
900             // Index
901             BOOST_UBLAS_INLINE
902             size_type index () const {
903                 return it_.index ();
904             }
905
906             // Assignment
907             BOOST_UBLAS_INLINE
908             const_iterator &operator = (const const_iterator &it) {
909                 container_const_reference<self_type>::assign (&it ());
910                 it_ = it.it_;
911                 return *this;
912             }
913
914             // Comparison
915             BOOST_UBLAS_INLINE
916             bool operator == (const const_iterator &it) const {
917                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
918                 return it_ == it.it_;
919             }
920             BOOST_UBLAS_INLINE
921             bool operator < (const const_iterator &it) const {
922                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
923                 return it_ < it.it_;
924             }
925
926         private:
927             const_subiterator_type it_;
928         };
929 #endif
930
931         BOOST_UBLAS_INLINE
932         const_iterator begin () const {
933             return find (0);
934         }
935         BOOST_UBLAS_INLINE
936         const_iterator cbegin () const {
937             return begin ();
938         }
939         BOOST_UBLAS_INLINE
940         const_iterator end () const {
941             return find (size ());
942         }
943         BOOST_UBLAS_INLINE
944         const_iterator cend () const {
945             return end ();
946         }
947
948 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
949         class iterator:
950             public container_reference<vector_slice>,
951             public iterator_base_traits<typename V::iterator::iterator_category>::template
952                         iterator_base<iterator, value_type>::type {
953         public:
954             typedef typename V::iterator::difference_type difference_type;
955             typedef typename V::iterator::value_type value_type;
956             typedef typename V::reference reference;    //FIXME due to indexing access
957             typedef typename V::iterator::pointer pointer;
958
959             // Construction and destruction
960             BOOST_UBLAS_INLINE
961             iterator ():
962                 container_reference<self_type> (), it_ () {}
963             BOOST_UBLAS_INLINE
964             iterator (self_type &vs, const subiterator_type &it):
965                 container_reference<self_type> (vs), it_ (it) {}
966
967             // Arithmetic
968             BOOST_UBLAS_INLINE
969             iterator &operator ++ () {
970                 ++ it_;
971                 return *this;
972             }
973             BOOST_UBLAS_INLINE
974             iterator &operator -- () {
975                 -- it_;
976                 return *this;
977             }
978             BOOST_UBLAS_INLINE
979             iterator &operator += (difference_type n) {
980                 it_ += n;
981                 return *this;
982             }
983             BOOST_UBLAS_INLINE
984             iterator &operator -= (difference_type n) {
985                 it_ -= n;
986                 return *this;
987             }
988             BOOST_UBLAS_INLINE
989             difference_type operator - (const iterator &it) const {
990                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
991                 return it_ - it.it_;
992             }
993
994             // Dereference
995             BOOST_UBLAS_INLINE
996             reference operator * () const {
997                 // FIXME replace find with at_element
998                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
999                 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