]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/boost/boost/numeric/ublas/vector_proxy.hpp
Add subset of boost library headers needed for compilation on PowerPC
[eurobot/public.git] / src / boost / 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 end () const {
359             return find (size ());
360         }
361
362 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
363         class iterator:
364             public container_reference<vector_range>,
365             public iterator_base_traits<typename subiterator_type::iterator_category>::template
366                         iterator_base<iterator, value_type>::type {
367         public:
368             typedef typename subiterator_type::difference_type difference_type;
369             typedef typename subiterator_type::value_type value_type;
370             typedef typename subiterator_type::reference reference;
371             typedef typename subiterator_type::pointer pointer;
372
373             // Construction and destruction
374             BOOST_UBLAS_INLINE
375             iterator ():
376                 container_reference<self_type> (), it_ () {}
377             BOOST_UBLAS_INLINE
378             iterator (self_type &vr, const subiterator_type &it):
379                 container_reference<self_type> (vr), it_ (it) {}
380
381             // Arithmetic
382             BOOST_UBLAS_INLINE
383             iterator &operator ++ () {
384                 ++ it_;
385                 return *this;
386             }
387             BOOST_UBLAS_INLINE
388             iterator &operator -- () {
389                 -- it_;
390                 return *this;
391             }
392             BOOST_UBLAS_INLINE
393             iterator &operator += (difference_type n) {
394                 it_ += n;
395                 return *this;
396             }
397             BOOST_UBLAS_INLINE
398             iterator &operator -= (difference_type n) {
399                 it_ -= n;
400                 return *this;
401             }
402             BOOST_UBLAS_INLINE
403             difference_type operator - (const iterator &it) const {
404                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
405                 return it_ - it.it_;
406             }
407
408             // Dereference
409             BOOST_UBLAS_INLINE
410             reference operator * () const {
411                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
412                 return *it_;
413             }
414             BOOST_UBLAS_INLINE
415             reference operator [] (difference_type n) const {
416                 return *(*this + n);
417             }
418
419             // Index
420             BOOST_UBLAS_INLINE
421             size_type index () const {
422                 return it_.index () - (*this) ().start ();
423             }
424
425             // Assignment
426             BOOST_UBLAS_INLINE
427             iterator &operator = (const iterator &it) {
428                 container_reference<self_type>::assign (&it ());
429                 it_ = it.it_;
430                 return *this;
431             }
432
433             // Comparison
434             BOOST_UBLAS_INLINE
435             bool operator == (const iterator &it) const {
436                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
437                 return it_ == it.it_;
438             }
439             BOOST_UBLAS_INLINE
440             bool operator < (const iterator &it) const {
441                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
442                 return it_ < it.it_;
443             }
444
445         private:
446             subiterator_type it_;
447
448             friend class const_iterator;
449         };
450 #endif
451
452         BOOST_UBLAS_INLINE
453         iterator begin () {
454             return find (0);
455         }
456         BOOST_UBLAS_INLINE
457         iterator end () {
458             return find (size ());
459         }
460
461         // Reverse iterator
462         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
463         typedef reverse_iterator_base<iterator> reverse_iterator;
464
465         BOOST_UBLAS_INLINE
466         const_reverse_iterator rbegin () const {
467             return const_reverse_iterator (end ());
468         }
469         BOOST_UBLAS_INLINE
470         const_reverse_iterator rend () const {
471             return const_reverse_iterator (begin ());
472         }
473         BOOST_UBLAS_INLINE
474         reverse_iterator rbegin () {
475             return reverse_iterator (end ());
476         }
477         BOOST_UBLAS_INLINE
478         reverse_iterator rend () {
479             return reverse_iterator (begin ());
480         }
481
482     private:
483         vector_closure_type data_;
484         range_type r_;
485     };
486
487     // ------------------
488     // Simple Projections
489     // ------------------
490
491     /** \brief Return a \c vector_range on a specified vector, a start and stop index.
492      * 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.
493      * 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
494      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
495      */
496     template<class V>
497     BOOST_UBLAS_INLINE
498     vector_range<V> subrange (V &data, typename V::size_type start, typename V::size_type stop) {
499         typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
500         return vector_range<V> (data, range_type (start, stop));
501     }
502
503     /** \brief Return a \c const \c vector_range on a specified vector, a start and stop index.
504      * 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.
505      *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
506      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
507      */
508     template<class V>
509     BOOST_UBLAS_INLINE
510     vector_range<const V> subrange (const V &data, typename V::size_type start, typename V::size_type stop) {
511         typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
512         return vector_range<const V> (data, range_type (start, stop));
513     }
514
515     // -------------------
516     // Generic Projections
517     // -------------------
518     
519     /** \brief Return a \c const \c vector_range on a specified vector and \c range
520      * 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.
521      * 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
522      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
523      */
524     template<class V>
525     BOOST_UBLAS_INLINE
526     vector_range<V> project (V &data, typename vector_range<V>::range_type const &r) {
527         return vector_range<V> (data, r);
528     }
529
530     /** \brief Return a \c vector_range on a specified vector and \c range
531      * Return a \c vector_range on a specified vector and \c range. The resulting \c vector_range can be manipulated like a normal vector.
532      * 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
533      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
534      */
535     template<class V>
536     BOOST_UBLAS_INLINE
537     const vector_range<const V> project (const V &data, typename vector_range<V>::range_type const &r) {
538         // ISSUE was: return vector_range<V> (const_cast<V &> (data), r);
539         return vector_range<const V> (data, r);
540    }
541
542     /** \brief Return a \c const \c vector_range on a specified vector and const \c range
543      * 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.
544      * 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
545      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
546      */
547     template<class V>
548     BOOST_UBLAS_INLINE
549     vector_range<V> project (vector_range<V> &data, const typename vector_range<V>::range_type &r) {
550         return data.project (r);
551     }
552
553     /** \brief Return a \c vector_range on a specified vector and const \c range
554      * 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.
555      * 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
556      * Vector Expression and access to an element outside of index range of the vector is \b undefined.
557      */
558     template<class V>
559     BOOST_UBLAS_INLINE
560     const vector_range<V> project (const vector_range<V> &data, const typename vector_range<V>::range_type &r) {
561         return data.project (r);
562     }
563
564     // Specialization of temporary_traits
565     template <class V>
566     struct vector_temporary_traits< vector_range<V> >
567     : vector_temporary_traits< V > {} ;
568     template <class V>
569     struct vector_temporary_traits< const vector_range<V> >
570     : vector_temporary_traits< V > {} ;
571
572
573     /** \brief A vector referencing a non continuous subvector of elements of vector v containing all elements specified by \c slice.
574      *
575      * A vector slice can be used as a normal vector in any expression.
576      * If the specified slice falls outside that of the index slice of the vector, then
577      * the \c vector_slice is not a well formed \i Vector \i Expression and access to an 
578      * element outside of index slice of the vector is \b undefined.
579      *
580      * A slice is a generalization of a range. In a range going from \f$a\f$ to \f$b\f$, 
581      * all elements belong to the range. In a slice, a \i \f$step\f$ can be specified meaning to
582      * take one element over \f$step\f$ in the range specified from \f$a\f$ to \f$b\f$.
583      * Obviously, a slice with a \f$step\f$ of 1 is equivalent to a range.
584      *
585      * \tparam V the type of vector referenced (for example \c vector<double>)
586      */
587     template<class V>
588     class vector_slice:
589         public vector_expression<vector_slice<V> > {
590
591         typedef vector_slice<V> self_type;
592     public:
593 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
594         using vector_expression<self_type>::operator ();
595 #endif
596         typedef const V const_vector_type;
597         typedef V vector_type;
598         typedef typename V::size_type size_type;
599         typedef typename V::difference_type difference_type;
600         typedef typename V::value_type value_type;
601         typedef typename V::const_reference const_reference;
602         typedef typename boost::mpl::if_<boost::is_const<V>,
603                                           typename V::const_reference,
604                                           typename V::reference>::type reference;
605         typedef typename boost::mpl::if_<boost::is_const<V>,
606                                           typename V::const_closure_type,
607                                           typename V::closure_type>::type vector_closure_type;
608         typedef basic_range<size_type, difference_type> range_type;
609         typedef basic_slice<size_type, difference_type> slice_type;
610         typedef const self_type const_closure_type;
611         typedef self_type closure_type;
612         typedef typename storage_restrict_traits<typename V::storage_category,
613                                                  dense_proxy_tag>::storage_category storage_category;
614
615         // Construction and destruction
616         BOOST_UBLAS_INLINE
617         vector_slice (vector_type &data, const slice_type &s):
618             data_ (data), s_ (s.preprocess (data.size ())) {
619             // Early checking of preconditions here.
620             // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
621             //                    s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
622         }
623         BOOST_UBLAS_INLINE
624         vector_slice (const vector_closure_type &data, const slice_type &s, int):
625             data_ (data), s_ (s.preprocess (data.size ())) {
626             // Early checking of preconditions here.
627             // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
628             //                    s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
629         }
630
631         // Accessors
632         BOOST_UBLAS_INLINE
633         size_type start () const {
634             return s_.start ();
635         }
636         BOOST_UBLAS_INLINE
637         difference_type stride () const {
638             return s_.stride ();
639         }
640         BOOST_UBLAS_INLINE
641         size_type size () const {
642             return s_.size ();
643         }
644
645         // Storage accessors
646         BOOST_UBLAS_INLINE
647         const vector_closure_type &data () const {
648             return data_;
649         }
650         BOOST_UBLAS_INLINE
651         vector_closure_type &data () {
652             return data_;
653         }
654
655         // Element access
656 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
657         BOOST_UBLAS_INLINE
658         const_reference operator () (size_type i) const {
659             return data_ (s_ (i));
660         }
661         BOOST_UBLAS_INLINE
662         reference operator () (size_type i) {
663             return data_ (s_ (i));
664         }
665
666         BOOST_UBLAS_INLINE
667         const_reference operator [] (size_type i) const {
668             return (*this) (i);
669         }
670         BOOST_UBLAS_INLINE
671         reference operator [] (size_type i) {
672             return (*this) (i);
673         }
674 #else
675         BOOST_UBLAS_INLINE
676         reference operator () (size_type i) const {
677             return data_ (s_ (i));
678         }
679
680         BOOST_UBLAS_INLINE
681         reference operator [] (size_type i) const {
682             return (*this) (i);
683         }
684 #endif
685
686         // ISSUE can this be done in free project function?
687         // Although a const function can create a non-const proxy to a non-const object
688         // Critical is that vector_type and data_ (vector_closure_type) are const correct
689         BOOST_UBLAS_INLINE
690         vector_slice<vector_type> project (const range_type &r) const {
691             return vector_slice<vector_type>  (data_, s_.compose (r.preprocess (data_.size ())), false);
692         }
693         BOOST_UBLAS_INLINE
694         vector_slice<vector_type> project (const slice_type &s) const {
695             return vector_slice<vector_type>  (data_, s_.compose (s.preprocess (data_.size ())), false);
696         }
697
698         // Assignment
699         BOOST_UBLAS_INLINE
700         vector_slice &operator = (const vector_slice &vs) {
701             // ISSUE need a temporary, proxy can be overlaping alias
702             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vs));
703             return *this;
704         }
705         BOOST_UBLAS_INLINE
706         vector_slice &assign_temporary (vector_slice &vs) {
707             // assign elements, proxied container remains the same
708             vector_assign<scalar_assign> (*this, vs);
709             return *this;
710         }
711         template<class AE>
712         BOOST_UBLAS_INLINE
713         vector_slice &operator = (const vector_expression<AE> &ae) {
714             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
715             return *this;
716         }
717         template<class AE>
718         BOOST_UBLAS_INLINE
719         vector_slice &assign (const vector_expression<AE> &ae) {
720             vector_assign<scalar_assign> (*this, ae);
721             return *this;
722         }
723         template<class AE>
724         BOOST_UBLAS_INLINE
725         vector_slice &operator += (const vector_expression<AE> &ae) {
726             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
727             return *this;
728         }
729         template<class AE>
730         BOOST_UBLAS_INLINE
731         vector_slice &plus_assign (const vector_expression<AE> &ae) {
732             vector_assign<scalar_plus_assign> (*this, ae);
733             return *this;
734         }
735         template<class AE>
736         BOOST_UBLAS_INLINE
737         vector_slice &operator -= (const vector_expression<AE> &ae) {
738             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
739             return *this;
740         }
741         template<class AE>
742         BOOST_UBLAS_INLINE
743         vector_slice &minus_assign (const vector_expression<AE> &ae) {
744             vector_assign<scalar_minus_assign> (*this, ae);
745             return *this;
746         }
747         template<class AT>
748         BOOST_UBLAS_INLINE
749         vector_slice &operator *= (const AT &at) {
750             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
751             return *this;
752         }
753         template<class AT>
754         BOOST_UBLAS_INLINE
755         vector_slice &operator /= (const AT &at) {
756             vector_assign_scalar<scalar_divides_assign> (*this, at);
757             return *this;
758         }
759
760         // Closure comparison
761         BOOST_UBLAS_INLINE
762         bool same_closure (const vector_slice &vr) const {
763             return (*this).data_.same_closure (vr.data_);
764         }
765
766         // Comparison
767         BOOST_UBLAS_INLINE
768         bool operator == (const vector_slice &vs) const {
769             return (*this).data_ == vs.data_ && s_ == vs.s_;
770         }
771
772         // Swapping
773         BOOST_UBLAS_INLINE
774         void swap (vector_slice vs) {
775             if (this != &vs) {
776                 BOOST_UBLAS_CHECK (size () == vs.size (), bad_size ());
777                 // Sparse ranges may be nonconformant now.
778                 // std::swap_ranges (begin (), end (), vs.begin ());
779                 vector_swap<scalar_swap> (*this, vs);
780             }
781         }
782         BOOST_UBLAS_INLINE
783         friend void swap (vector_slice vs1, vector_slice vs2) {
784             vs1.swap (vs2);
785         }
786
787         // Iterator types
788     private:
789         // Use slice as an index - FIXME this fails for packed assignment
790         typedef typename slice_type::const_iterator const_subiterator_type;
791         typedef typename slice_type::const_iterator subiterator_type;
792
793     public:
794 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
795         typedef indexed_iterator<vector_slice<vector_type>,
796                                  typename vector_type::iterator::iterator_category> iterator;
797         typedef indexed_const_iterator<vector_slice<vector_type>,
798                                        typename vector_type::const_iterator::iterator_category> const_iterator;
799 #else
800         class const_iterator;
801         class iterator;
802 #endif
803
804         // Element lookup
805         BOOST_UBLAS_INLINE
806         const_iterator find (size_type i) const {
807 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
808             return const_iterator (*this, i);
809 #else
810             return const_iterator (*this, s_.begin () + i);
811 #endif
812         }
813         BOOST_UBLAS_INLINE
814         iterator find (size_type i) {
815 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
816             return iterator (*this, i);
817 #else
818             return iterator (*this, s_.begin () + i);
819 #endif
820         }
821
822 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
823         class const_iterator:
824             public container_const_reference<vector_slice>,
825             public iterator_base_traits<typename V::const_iterator::iterator_category>::template
826                         iterator_base<const_iterator, value_type>::type {
827         public:
828             typedef typename V::const_iterator::difference_type difference_type;
829             typedef typename V::const_iterator::value_type value_type;
830             typedef typename V::const_reference reference;    //FIXME due to indexing access
831             typedef typename V::const_iterator::pointer pointer;
832
833             // Construction and destruction
834             BOOST_UBLAS_INLINE
835             const_iterator ():
836                 container_const_reference<self_type> (), it_ () {}
837             BOOST_UBLAS_INLINE
838             const_iterator (const self_type &vs, const const_subiterator_type &it):
839                 container_const_reference<self_type> (vs), it_ (it) {}
840             BOOST_UBLAS_INLINE
841             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
842                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
843
844             // Arithmetic
845             BOOST_UBLAS_INLINE
846             const_iterator &operator ++ () {
847                 ++ it_;
848                 return *this;
849             }
850             BOOST_UBLAS_INLINE
851             const_iterator &operator -- () {
852                 -- it_;
853                 return *this;
854             }
855             BOOST_UBLAS_INLINE
856             const_iterator &operator += (difference_type n) {
857                 it_ += n;
858                 return *this;
859             }
860             BOOST_UBLAS_INLINE
861             const_iterator &operator -= (difference_type n) {
862                 it_ -= n;
863                 return *this;
864             }
865             BOOST_UBLAS_INLINE
866             difference_type operator - (const const_iterator &it) const {
867                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
868                 return it_ - it.it_;
869             }
870
871             // Dereference
872             BOOST_UBLAS_INLINE
873             const_reference operator * () const {
874                 // FIXME replace find with at_element
875                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
876                 return (*this) ().data_ (*it_);
877             }
878             BOOST_UBLAS_INLINE
879             const_reference operator [] (difference_type n) const {
880                 return *(*this + n);
881             }
882
883             // Index
884             BOOST_UBLAS_INLINE
885             size_type index () const {
886                 return it_.index ();
887             }
888
889             // Assignment
890             BOOST_UBLAS_INLINE
891             const_iterator &operator = (const const_iterator &it) {
892                 container_const_reference<self_type>::assign (&it ());
893                 it_ = it.it_;
894                 return *this;
895             }
896
897             // Comparison
898             BOOST_UBLAS_INLINE
899             bool operator == (const const_iterator &it) const {
900                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
901                 return it_ == it.it_;
902             }
903             BOOST_UBLAS_INLINE
904             bool operator < (const const_iterator &it) const {
905                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
906                 return it_ < it.it_;
907             }
908
909         private:
910             const_subiterator_type it_;
911         };
912 #endif
913
914         BOOST_UBLAS_INLINE
915         const_iterator begin () const {
916             return find (0);
917         }
918         BOOST_UBLAS_INLINE
919         const_iterator end () const {
920             return find (size ());
921         }
922
923 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
924         class iterator:
925             public container_reference<vector_slice>,
926             public iterator_base_traits<typename V::iterator::iterator_category>::template
927                         iterator_base<iterator, value_type>::type {
928         public:
929             typedef typename V::iterator::difference_type difference_type;
930             typedef typename V::iterator::value_type value_type;
931             typedef typename V::reference reference;    //FIXME due to indexing access
932             typedef typename V::iterator::pointer pointer;
933
934             // Construction and destruction
935             BOOST_UBLAS_INLINE
936             iterator ():
937                 container_reference<self_type> (), it_ () {}
938             BOOST_UBLAS_INLINE
939             iterator (self_type &vs, const subiterator_type &it):
940                 container_reference<self_type> (vs), it_ (it) {}
941
942             // Arithmetic
943             BOOST_UBLAS_INLINE
944             iterator &operator ++ () {
945                 ++ it_;
946                 return *this;
947             }
948             BOOST_UBLAS_INLINE
949             iterator &operator -- () {
950                 -- it_;
951                 return *this;
952             }
953             BOOST_UBLAS_INLINE
954             iterator &operator += (difference_type n) {
955                 it_ += n;
956                 return *this;
957             }
958             BOOST_UBLAS_INLINE
959             iterator &operator -= (difference_type n) {
960                 it_ -= n;
961                 return *this;
962             }
963             BOOST_UBLAS_INLINE
964             difference_type operator - (const iterator &it) const {
965                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
966                 return it_ - it.it_;
967             }
968
969             // Dereference
970             BOOST_UBLAS_INLINE
971             reference operator * () const {
972                 // FIXME replace find with at_element
973                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
974                 return (*this) ().data_ (*it_);
975             }
976             BOOST_UBLAS_INLINE
977             reference operator [] (difference_type n) const {
978                 return *(*this + n);
979             }
980
981
982             // Index
983             BOOST_UBLAS_INLINE
984             size_type index () const {
985                 return it_.index ();
986             }
987
988             // Assignment
989             BOOST_UBLAS_INLINE
990             iterator &operator = (const iterator &it) {
991                 container_reference<self_type>::assign (&it ());
992                 it_ = it.it_;
993                 return *this;
994             }
995
996             // Comparison
997             BOOST_UBLAS_INLINE
998             bool operator == (const iterator &it) const {
999                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1000                 return it_ == it.it_;
1001             }
1002             BOOST_UBLAS_INLINE
1003             bool operator < (const iterator &it) const {
1004                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1005                 return it_ < it.it_;
1006             }
1007
1008         private:
1009             subiterator_type it_;
1010
1011             friend class const_iterator;
1012         };
1013 #endif
1014
1015         BOOST_UBLAS_INLINE
1016         iterator begin () {
1017             return find (0);
1018         }
1019         BOOST_UBLAS_INLINE
1020         iterator end () {
1021             return find (size ());
1022         }
1023
1024         // Reverse iterator
1025         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1026         typedef reverse_iterator_base<iterator> reverse_iterator;
1027
1028         BOOST_UBLAS_INLINE
1029         const_reverse_iterator rbegin () const {
1030             return const_reverse_iterator (end ());
1031         }
1032         BOOST_UBLAS_INLINE
1033         const_reverse_iterator rend () const {
1034             return const_reverse_iterator (begin ());
1035         }
1036         BOOST_UBLAS_INLINE
1037         reverse_iterator rbegin () {
1038             return reverse_iterator (end ());
1039         }
1040         BOOST_UBLAS_INLINE
1041         reverse_iterator rend () {
1042             return reverse_iterator (begin ());
1043         }
1044
1045     private:
1046         vector_closure_type data_;
1047         slice_type s_;
1048     };
1049
1050     // Simple Projections
1051     template<class V>
1052     BOOST_UBLAS_INLINE
1053     vector_slice<V> subslice (V &data, typename V::size_type start, typename V::difference_type stride, typename V::size_type size) {
1054         typedef basic_slice<typename V::size_type, typename V::difference_type> slice_type;
1055         return vector_slice<V> (data, slice_type (start, stride, size));
1056     }
1057     template<class V>
1058     BOOST_UBLAS_INLINE
1059     vector_slice<const V> subslice (const V &data, typename V::size_type start, typename V::difference_type stride, typename V::size_type size)  {
1060         typedef basic_slice<typename V::size_type, typename V::difference_type> slice_type;
1061         return vector_slice<const V> (data, slice_type (start, stride, size));
1062     }
1063
1064     // Generic Projections
1065     template<class V>
1066     BOOST_UBLAS_INLINE
1067     vector_slice<V> project (V &data, const typename vector_slice<V>::slice_type &s) {
1068         return vector_slice<V> (data, s);
1069     }
1070     template<class V>
1071     BOOST_UBLAS_INLINE
1072     const vector_slice<const V> project (const V &data, const typename vector_slice<V>::slice_type &s) {
1073         // ISSUE was: return vector_slice<V> (const_cast<V &> (data), s);
1074         return vector_slice<const V> (data, s);
1075     }
1076     template<class V>
1077     BOOST_UBLAS_INLINE
1078     vector_slice<V> project (vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
1079         return data.project (s);
1080     }
1081     template<class V>
1082     BOOST_UBLAS_INLINE
1083     const vector_slice<V> project (const vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
1084         return data.project (s);
1085     }
1086     // 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
1087     template<class V>
1088     BOOST_UBLAS_INLINE
1089     vector_slice<V> project (vector_slice<V> &data, const typename vector_range<V>::range_type &r) {
1090         return data.project (r);
1091     }
1092     template<class V>
1093     BOOST_UBLAS_INLINE
1094     const vector_slice<V> project (const vector_slice<V> &data, const typename vector_range<V>::range_type &r) {
1095         return data.project (r);
1096     }
1097
1098     // Specialization of temporary_traits
1099     template <class V>
1100     struct vector_temporary_traits< vector_slice<V> >
1101     : vector_temporary_traits< V > {} ;
1102     template <class V>
1103     struct vector_temporary_traits< const vector_slice<V> >
1104     : vector_temporary_traits< V > {} ;
1105
1106
1107     // Vector based indirection class
1108     // Contributed by Toon Knapen.
1109     // Extended and optimized by Kresimir Fresl.
1110
1111     /** \brief A vector referencing a non continuous subvector of elements given another vector of indices.
1112      *
1113      * It is the most general version of any subvectors because it uses another vector of indices to reference
1114      * the subvector. 
1115      *
1116      * The vector of indices can be of any type with the restriction that its elements must be
1117      * type-compatible with the size_type \c of the container. In practice, the following are good candidates:
1118      * - \c boost::numeric::ublas::indirect_array<A> where \c A can be \c int, \c size_t, \c long, etc...
1119      * - \c std::vector<A> where \c A can \c int, \c size_t, \c long, etc...
1120      * - \c boost::numeric::ublas::vector<int> can work too (\c int can be replaced by another integer type)
1121      * - etc...
1122      *
1123      * An indirect vector can be used as a normal vector in any expression. If the specified indirect vector 
1124      * falls outside that of the indices of the vector, then the \c vector_indirect is not a well formed 
1125      * \i Vector \i Expression and access to an element outside of indices of the vector is \b undefined.
1126      *
1127      * \tparam V the type of vector referenced (for example \c vector<double>)
1128      * \tparam IA the type of index vector. Default is \c ublas::indirect_array<>
1129      */
1130     template<class V, class IA>
1131     class vector_indirect:
1132         public vector_expression<vector_indirect<V, IA> > {
1133
1134         typedef vector_indirect<V, IA> self_type;
1135     public:
1136 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1137         using vector_expression<self_type>::operator ();
1138 #endif
1139         typedef const V const_vector_type;
1140         typedef V vector_type;
1141         typedef const IA const_indirect_array_type;
1142         typedef IA indirect_array_type;
1143         typedef typename V::size_type size_type;
1144         typedef typename V::difference_type difference_type;
1145         typedef typename V::value_type value_type;
1146         typedef typename V::const_reference const_reference;
1147         typedef typename boost::mpl::if_<boost::is_const<V>,
1148                                           typename V::const_reference,
1149                                           typename V::reference>::type reference;
1150         typedef typename boost::mpl::if_<boost::is_const<V>,
1151                                           typename V::const_closure_type,
1152                                           typename V::closure_type>::type vector_closure_type;
1153         typedef basic_range<size_type, difference_type> range_type;
1154         typedef basic_slice<size_type, difference_type> slice_type;
1155         typedef const self_type const_closure_type;
1156         typedef self_type closure_type;
1157         typedef typename storage_restrict_traits<typename V::storage_category,
1158                                                  dense_proxy_tag>::storage_category storage_category;
1159
1160         // Construction and destruction
1161         BOOST_UBLAS_INLINE
1162         vector_indirect (vector_type &data, size_type size):
1163             data_ (data), ia_ (size) {}
1164         BOOST_UBLAS_INLINE
1165         vector_indirect (vector_type &data, const indirect_array_type &ia):
1166             data_ (data), ia_ (ia.preprocess (data.size ())) {}
1167         BOOST_UBLAS_INLINE
1168         vector_indirect (const vector_closure_type &data, const indirect_array_type &ia, int):
1169             data_ (data), ia_ (ia.preprocess (data.size ())) {}
1170
1171         // Accessors
1172         BOOST_UBLAS_INLINE
1173         size_type size () const {
1174             return ia_.size ();
1175         }
1176         BOOST_UBLAS_INLINE
1177         const_indirect_array_type &indirect () const {
1178             return ia_;
1179         }
1180         BOOST_UBLAS_INLINE
1181         indirect_array_type &indirect () {
1182             return ia_;
1183         }
1184
1185         // Storage accessors
1186         BOOST_UBLAS_INLINE
1187         const vector_closure_type &data () const {
1188             return data_;
1189         }
1190         BOOST_UBLAS_INLINE
1191         vector_closure_type &data () {
1192             return data_;
1193         }
1194
1195         // Element access
1196 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1197         BOOST_UBLAS_INLINE
1198         const_reference operator () (size_type i) const {
1199             return data_ (ia_ (i));
1200         }
1201         BOOST_UBLAS_INLINE
1202         reference operator () (size_type i) {
1203             return data_ (ia_ (i));
1204         }
1205
1206         BOOST_UBLAS_INLINE
1207         const_reference operator [] (size_type i) const {
1208             return (*this) (i);
1209         }
1210         BOOST_UBLAS_INLINE
1211         reference operator [] (size_type i) {
1212             return (*this) (i);
1213         }
1214 #else
1215         BOOST_UBLAS_INLINE
1216         reference operator () (size_type i) const {
1217             return data_ (ia_ (i));
1218         }
1219
1220         BOOST_UBLAS_INLINE
1221         reference operator [] (size_type i) const {
1222             return (*this) (i);
1223         }
1224 #endif
1225
1226         // ISSUE can this be done in free project function?
1227         // Although a const function can create a non-const proxy to a non-const object
1228         // Critical is that vector_type and data_ (vector_closure_type) are const correct
1229         BOOST_UBLAS_INLINE
1230         vector_indirect<vector_type, indirect_array_type> project (const range_type &r) const {
1231             return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (r.preprocess (data_.size ())), 0);
1232         }
1233         BOOST_UBLAS_INLINE
1234         vector_indirect<vector_type, indirect_array_type> project (const slice_type &s) const {
1235             return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (s.preprocess (data_.size ())), 0);
1236         }
1237         BOOST_UBLAS_INLINE
1238         vector_indirect<vector_type, indirect_array_type> project (const indirect_array_type &ia) const {
1239             return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (ia.preprocess (data_.size ())), 0);
1240         }
1241
1242         // Assignment
1243         BOOST_UBLAS_INLINE
1244         vector_indirect &operator = (const vector_indirect &vi) {
1245             // ISSUE need a temporary, proxy can be overlaping alias
1246             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vi));
1247             return *this;
1248         }
1249         BOOST_UBLAS_INLINE
1250         vector_indirect &assign_temporary (vector_indirect &vi) {
1251             // assign elements, proxied container remains the same
1252             vector_assign<scalar_assign> (*this, vi);
1253             return *this;
1254         }
1255         template<class AE>
1256         BOOST_UBLAS_INLINE
1257         vector_indirect &operator = (const vector_expression<AE> &ae) {
1258             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
1259             return *this;
1260         }
1261         template<class AE>
1262         BOOST_UBLAS_INLINE
1263         vector_indirect &assign (const vector_expression<AE> &ae) {
1264             vector_assign<scalar_assign> (*this, ae);
1265             return *this;
1266         }
1267         template<class AE>
1268         BOOST_UBLAS_INLINE
1269         vector_indirect &operator += (const vector_expression<AE> &ae) {
1270             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
1271             return *this;
1272         }
1273         template<class AE>
1274         BOOST_UBLAS_INLINE
1275         vector_indirect &plus_assign (const vector_expression<AE> &ae) {
1276             vector_assign<scalar_plus_assign> (*this, ae);
1277             return *this;
1278         }
1279         template<class AE>
1280         BOOST_UBLAS_INLINE
1281         vector_indirect &operator -= (const vector_expression<AE> &ae) {
1282             vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
1283             return *this;
1284         }
1285         template<class AE>
1286         BOOST_UBLAS_INLINE
1287         vector_indirect &minus_assign (const vector_expression<AE> &ae) {
1288             vector_assign<scalar_minus_assign> (*this, ae);
1289             return *this;
1290         }
1291         template<class AT>
1292         BOOST_UBLAS_INLINE
1293         vector_indirect &operator *= (const AT &at) {
1294             vector_assign_scalar<scalar_multiplies_assign> (*this, at);
1295             return *this;
1296         }
1297         template<class AT>
1298         BOOST_UBLAS_INLINE
1299         vector_indirect &operator /= (const AT &at) {
1300             vector_assign_scalar<scalar_divides_assign> (*this, at);
1301             return *this;
1302         }
1303
1304         // Closure comparison
1305         BOOST_UBLAS_INLINE
1306         bool same_closure (const vector_indirect &vr) const {
1307 return true;
1308         }
1309
1310         // Comparison
1311         BOOST_UBLAS_INLINE
1312         bool operator == (const vector_indirect &vi) const {
1313             return (*this).data_ == vi.data_ && ia_ == vi.ia_;
1314         }
1315
1316         // Swapping
1317         BOOST_UBLAS_INLINE
1318         void swap (vector_indirect vi) {
1319             if (this != &vi) {
1320                 BOOST_UBLAS_CHECK (size () == vi.size (), bad_size ());
1321                 // Sparse ranges may be nonconformant now.
1322                 // std::swap_ranges (begin (), end (), vi.begin ());
1323                 vector_swap<scalar_swap> (*this, vi);
1324             }
1325         }
1326         BOOST_UBLAS_INLINE
1327         friend void swap (vector_indirect vi1, vector_indirect vi2) {
1328             vi1.swap (vi2);
1329         }
1330
1331         // Iterator types
1332     private:
1333         // Use indirect array as an index - FIXME this fails for packed assignment
1334         typedef typename IA::const_iterator const_subiterator_type;
1335         typedef typename IA::const_iterator subiterator_type;
1336
1337     public:
1338 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1339         typedef indexed_iterator<vector_indirect<vector_type, indirect_array_type>,
1340                                  typename vector_type::iterator::iterator_category> iterator;
1341         typedef indexed_const_iterator<vector_indirect<vector_type, indirect_array_type>,
1342                                        typename vector_type::const_iterator::iterator_category> const_iterator;
1343 #else
1344         class const_iterator;
1345         class iterator;
1346 #endif
1347         // Element lookup
1348         BOOST_UBLAS_INLINE
1349         const_iterator find (size_type i) const {
1350 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1351             return const_iterator (*this, i);
1352 #else
1353             return const_iterator (*this, ia_.begin () + i);
1354 #endif
1355         }
1356         BOOST_UBLAS_INLINE
1357         iterator find (size_type i) {
1358 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1359             return iterator (*this, i);
1360 #else
1361             return iterator (*this, ia_.begin () + i);
1362 #endif
1363         }
1364
1365         // Iterators simply are indices.
1366
1367 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1368         class const_iterator:
1369             public container_const_reference<vector_indirect>,
1370             public iterator_base_traits<typename V::const_iterator::iterator_category>::template
1371                         iterator_base<const_iterator, value_type>::type {
1372         public:
1373             typedef typename V::const_iterator::difference_type difference_type;
1374             typedef typename V::const_iterator::value_type value_type;
1375             typedef typename V::const_reference reference;    //FIXME due to indexing access
1376             typedef typename V::const_iterator::pointer pointer;
1377
1378             // Construction and destruction
1379             BOOST_UBLAS_INLINE
1380             const_iterator ():
1381                 container_const_reference<self_type> (), it_ () {}
1382             BOOST_UBLAS_INLINE
1383             const_iterator (const self_type &vi, const const_subiterator_type &it):
1384                 container_const_reference<self_type> (vi), it_ (it) {}
1385             BOOST_UBLAS_INLINE
1386             const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
1387                 container_const_reference<self_type> (it ()), it_ (it.it_) {}
1388
1389             // Arithmetic
1390             BOOST_UBLAS_INLINE
1391             const_iterator &operator ++ () {
1392                 ++ it_;
1393                 return *this;
1394             }
1395             BOOST_UBLAS_INLINE
1396             const_iterator &operator -- () {
1397                 -- it_;
1398                 return *this;
1399             }
1400             BOOST_UBLAS_INLINE
1401             const_iterator &operator += (difference_type n) {
1402                 it_ += n;
1403                 return *this;
1404             }
1405             BOOST_UBLAS_INLINE
1406             const_iterator &operator -= (difference_type n) {
1407                 it_ -= n;
1408                 return *this;
1409             }
1410             BOOST_UBLAS_INLINE
1411             difference_type operator - (const const_iterator &it) const {
1412                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1413                 return it_ - it.it_;
1414             }
1415
1416             // Dereference
1417             BOOST_UBLAS_INLINE
1418             const_reference operator * () const {
1419                 // FIXME replace find with at_element
1420                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1421                 return (*this) ().data_ (*it_);
1422             }
1423             BOOST_UBLAS_INLINE
1424             const_reference operator [] (difference_type n) const {
1425                 return *(*this + n);
1426             }
1427
1428             // Index
1429             BOOST_UBLAS_INLINE
1430             size_type index () const {
1431                 return it_.index ();
1432             }
1433
1434             // Assignment
1435             BOOST_UBLAS_INLINE
1436             const_iterator &operator = (const const_iterator &it) {
1437                 container_const_reference<self_type>::assign (&it ());
1438                 it_ = it.it_;
1439                 return *this;
1440             }
1441
1442             // Comparison
1443             BOOST_UBLAS_INLINE
1444             bool operator == (const const_iterator &it) const {
1445                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1446                 return it_ == it.it_;
1447             }
1448             BOOST_UBLAS_INLINE
1449             bool operator < (const const_iterator &it) const {
1450                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1451                 return it_ < it.it_;
1452             }
1453
1454         private:
1455             const_subiterator_type it_;
1456         };
1457 #endif
1458
1459         BOOST_UBLAS_INLINE
1460         const_iterator begin () const {
1461             return find (0);
1462         }
1463         BOOST_UBLAS_INLINE
1464         const_iterator end () const {
1465             return find (size ());
1466         }
1467
1468 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1469         class iterator:
1470             public container_reference<vector_indirect>,
1471             public iterator_base_traits<typename V::iterator::iterator_category>::template
1472                         iterator_base<iterator, value_type>::type {
1473         public:
1474             typedef typename V::iterator::difference_type difference_type;
1475             typedef typename V::iterator::value_type value_type;
1476             typedef typename V::reference reference;    //FIXME due to indexing access
1477             typedef typename V::iterator::pointer pointer;
1478
1479             // Construction and destruction
1480             BOOST_UBLAS_INLINE
1481             iterator ():
1482                 container_reference<self_type> (), it_ () {}
1483             BOOST_UBLAS_INLINE
1484             iterator (self_type &vi, const subiterator_type &it):
1485                 container_reference<self_type> (vi), it_ (it) {}
1486
1487             // Arithmetic
1488             BOOST_UBLAS_INLINE
1489             iterator &operator ++ () {
1490                 ++ it_;
1491                 return *this;
1492             }
1493             BOOST_UBLAS_INLINE
1494             iterator &operator -- () {
1495                 -- it_;
1496                 return *this;
1497             }
1498             BOOST_UBLAS_INLINE
1499             iterator &operator += (difference_type n) {
1500                 it_ += n;
1501                 return *this;
1502             }
1503             BOOST_UBLAS_INLINE
1504             iterator &operator -= (difference_type n) {
1505                 it_ -= n;
1506                 return *this;
1507             }
1508             BOOST_UBLAS_INLINE
1509             difference_type operator - (const iterator &it) const {
1510                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1511                 return it_ - it.it_;
1512             }
1513
1514             // Dereference
1515             BOOST_UBLAS_INLINE
1516             reference operator * () const {
1517                 // FIXME replace find with at_element
1518                 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1519                 return (*this) ().data_ (*it_);
1520             }
1521             BOOST_UBLAS_INLINE
1522             reference operator [] (difference_type n) const {
1523                 return *(*this + n);
1524             }
1525
1526             // Index
1527             BOOST_UBLAS_INLINE
1528             size_type index () const {
1529                 return it_.index ();
1530             }
1531
1532             // Assignment
1533             BOOST_UBLAS_INLINE
1534             iterator &operator = (const iterator &it) {
1535                 container_reference<self_type>::assign (&it ());
1536                 it_ = it.it_;
1537                 return *this;
1538             }
1539
1540             // Comparison
1541             BOOST_UBLAS_INLINE
1542             bool operator == (const iterator &it) const {
1543                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1544                 return it_ == it.it_;
1545             }
1546             BOOST_UBLAS_INLINE
1547             bool operator < (const iterator &it) const {
1548                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1549                 return it_ < it.it_;
1550             }
1551
1552         private:
1553             subiterator_type it_;
1554
1555             friend class const_iterator;
1556         };
1557 #endif
1558
1559         BOOST_UBLAS_INLINE
1560         iterator begin () {
1561             return find (0);
1562         }
1563         BOOST_UBLAS_INLINE
1564         iterator end () {
1565             return find (size ());
1566         }
1567
1568         // Reverse iterator
1569         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1570         typedef reverse_iterator_base<iterator> reverse_iterator;
1571
1572         BOOST_UBLAS_INLINE
1573         const_reverse_iterator rbegin () const {
1574             return const_reverse_iterator (end ());
1575         }
1576         BOOST_UBLAS_INLINE
1577         const_reverse_iterator rend () const {
1578             return const_reverse_iterator (begin ());
1579         }
1580         BOOST_UBLAS_INLINE
1581         reverse_iterator rbegin () {
1582             return reverse_iterator (end ());
1583         }
1584         BOOST_UBLAS_INLINE
1585         reverse_iterator rend () {
1586             return reverse_iterator (begin ());
1587         }
1588
1589     private:
1590         vector_closure_type data_;
1591         indirect_array_type ia_;
1592     };
1593
1594     // Projections
1595     template<class V, class A>
1596     BOOST_UBLAS_INLINE
1597     vector_indirect<V, indirect_array<A> > project (V &data, const indirect_array<A> &ia) {
1598         return vector_indirect<V, indirect_array<A> > (data, ia);
1599     }
1600     template<class V, class A>
1601     BOOST_UBLAS_INLINE
1602     const vector_indirect<const V, indirect_array<A> > project (const V &data, const indirect_array<A> &ia) {
1603         // ISSUE was: return vector_indirect<V, indirect_array<A> > (const_cast<V &> (data), ia)
1604         return vector_indirect<const V, indirect_array<A> > (data, ia);
1605     }
1606     template<class V, class IA>
1607     BOOST_UBLAS_INLINE
1608     vector_indirect<V, IA> project (vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::range_type &r) {
1609         return data.project (r);
1610     }
1611     template<class V, class IA>
1612     BOOST_UBLAS_INLINE
1613     const vector_indirect<V, IA> project (const vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::range_type &r) {
1614         return data.project (r);
1615     }
1616     template<class V, class IA>
1617     BOOST_UBLAS_INLINE
1618     vector_indirect<V, IA> project (vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::slice_type &s) {
1619         return data.project (s);
1620     }
1621     template<class V, class IA>
1622     BOOST_UBLAS_INLINE
1623     const vector_indirect<V, IA> project (const vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::slice_type &s) {
1624         return data.project (s);
1625     }
1626     template<class V, class A>
1627     BOOST_UBLAS_INLINE
1628     vector_indirect<V, indirect_array<A> > project (vector_indirect<V, indirect_array<A> > &data, const indirect_array<A> &ia) {
1629         return data.project (ia);
1630     }
1631     template<class V, class A>
1632     BOOST_UBLAS_INLINE
1633     const vector_indirect<V, indirect_array<A> > project (const vector_indirect<V, indirect_array<A> > &data, const indirect_array<A> &ia) {
1634         return data.project (ia);
1635     }
1636
1637     // Specialization of temporary_traits
1638     template <class V>
1639     struct vector_temporary_traits< vector_indirect<V> >
1640     : vector_temporary_traits< V > {} ;
1641     template <class V>
1642     struct vector_temporary_traits< const vector_indirect<V> >
1643     : vector_temporary_traits< V > {} ;
1644
1645 }}}
1646
1647 #endif