Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/numeric/ublas/vector_proxy.hpp @ 47

Last change on this file since 47 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 56.5 KB
Line 
1//
2//  Copyright (c) 2000-2002
3//  Joerg Walter, Mathias Koch
4//
5//  Permission to use, copy, modify, distribute and sell this software
6//  and its documentation for any purpose is hereby granted without fee,
7//  provided that the above copyright notice appear in all copies and
8//  that both that copyright notice and this permission notice appear
9//  in supporting documentation.  The authors make no representations
10//  about the suitability of this software for any purpose.
11//  It is provided "as is" without express or implied warranty.
12//
13//  The authors gratefully acknowledge the support of
14//  GeNeSys mbH & Co. KG in producing this work.
15//
16
17#ifndef _BOOST_UBLAS_VECTOR_PROXY_
18#define _BOOST_UBLAS_VECTOR_PROXY_
19
20#include <boost/numeric/ublas/vector_expression.hpp>
21#include <boost/numeric/ublas/detail/vector_assign.hpp>
22#include <boost/numeric/ublas/detail/temporary.hpp>
23
24// Iterators based on ideas of Jeremy Siek
25
26namespace boost { namespace numeric { namespace ublas {
27
28    // Vector based range class
29    template<class V>
30    class vector_range:
31        public vector_expression<vector_range<V> > {
32
33        typedef vector_range<V> self_type;
34    public:
35#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
36        using vector_expression<self_type>::operator ();
37#endif
38        typedef const V const_vector_type;
39        typedef V vector_type;
40        typedef typename V::size_type size_type;
41        typedef typename V::difference_type difference_type;
42        typedef typename V::value_type value_type;
43        typedef typename V::const_reference const_reference;
44        typedef typename boost::mpl::if_<boost::is_const<V>,
45                                          typename V::const_reference,
46                                          typename V::reference>::type reference;
47        typedef typename boost::mpl::if_<boost::is_const<V>,
48                                          typename V::const_closure_type,
49                                          typename V::closure_type>::type vector_closure_type;
50        typedef basic_range<size_type, difference_type> range_type;
51        typedef const self_type const_closure_type;
52        typedef self_type closure_type;
53        typedef typename storage_restrict_traits<typename V::storage_category,
54                                                 dense_proxy_tag>::storage_category storage_category;
55
56        // Construction and destruction
57        BOOST_UBLAS_INLINE
58        vector_range (vector_type &data, const range_type &r):
59            data_ (data), r_ (r.preprocess (data.size ())) {
60            // Early checking of preconditions here.
61            // BOOST_UBLAS_CHECK (r_.start () <= data_.size () &&
62            //                   r_.start () + r_.size () <= data_.size (), bad_index ());
63        }
64        BOOST_UBLAS_INLINE
65        vector_range (const vector_closure_type &data, const range_type &r, bool):
66            data_ (data), r_ (r.preprocess (data.size ())) {
67            // Early checking of preconditions here.
68            // BOOST_UBLAS_CHECK (r_.start () <= data_.size () &&
69            //                    r_.start () + r_.size () <= data_.size (), bad_index ());
70        }
71
72        // Accessors
73        BOOST_UBLAS_INLINE
74        size_type start () const {
75            return r_.start ();
76        }
77        BOOST_UBLAS_INLINE
78        size_type size () const {
79            return r_.size ();
80        }
81
82        // Storage accessors
83        BOOST_UBLAS_INLINE
84        const vector_closure_type &data () const {
85            return data_;
86        }
87        BOOST_UBLAS_INLINE
88        vector_closure_type &data () {
89            return data_;
90        }
91
92        // Element access
93#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
94        BOOST_UBLAS_INLINE
95        const_reference operator () (size_type i) const {
96            return data_ (r_ (i));
97        }
98        BOOST_UBLAS_INLINE
99        reference operator () (size_type i) {
100            return data_ (r_ (i));
101        }
102
103        BOOST_UBLAS_INLINE
104        const_reference operator [] (size_type i) const {
105            return (*this) (i);
106        }
107        BOOST_UBLAS_INLINE
108        reference operator [] (size_type i) {
109            return (*this) (i);
110        }
111#else
112        BOOST_UBLAS_INLINE
113        reference operator () (size_type i) const {
114            return data_ (r_ (i));
115        }
116
117        BOOST_UBLAS_INLINE
118        reference operator [] (size_type i) const {
119            return (*this) (i);
120        }
121#endif
122
123        // ISSUE can this be done in free project function?
124        // Although a const function can create a non-const proxy to a non-const object
125        // Critical is that vector_type and data_ (vector_closure_type) are const correct
126        BOOST_UBLAS_INLINE
127        vector_range<vector_type> project (const range_type &r) const {
128            return vector_range<vector_type> (data_, r_.compose (r.preprocess (data_.size ())), false);
129        }
130
131        // Assignment
132        BOOST_UBLAS_INLINE
133        vector_range &operator = (const vector_range &vr) {
134            // ISSUE need a temporary, proxy can be overlaping alias
135            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vr));
136            return *this;
137        }
138        BOOST_UBLAS_INLINE
139        vector_range &assign_temporary (vector_range &vr) {
140            // assign elements, proxied container remains the same
141            vector_assign<scalar_assign> (*this, vr);
142            return *this;
143        }
144        template<class AE>
145        BOOST_UBLAS_INLINE
146        vector_range &operator = (const vector_expression<AE> &ae) {
147            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
148            return *this;
149        }
150        template<class AE>
151        BOOST_UBLAS_INLINE
152        vector_range &assign (const vector_expression<AE> &ae) {
153            vector_assign<scalar_assign> (*this, ae);
154            return *this;
155        }
156        template<class AE>
157        BOOST_UBLAS_INLINE
158        vector_range &operator += (const vector_expression<AE> &ae) {
159            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
160            return *this;
161        }
162        template<class AE>
163        BOOST_UBLAS_INLINE
164        vector_range &plus_assign (const vector_expression<AE> &ae) {
165            vector_assign<scalar_plus_assign> (*this, ae);
166            return *this;
167        }
168        template<class AE>
169        BOOST_UBLAS_INLINE
170        vector_range &operator -= (const vector_expression<AE> &ae) {
171            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
172            return *this;
173        }
174        template<class AE>
175        BOOST_UBLAS_INLINE
176        vector_range &minus_assign (const vector_expression<AE> &ae) {
177            vector_assign<scalar_minus_assign> (*this, ae);
178            return *this;
179        }
180        template<class AT>
181        BOOST_UBLAS_INLINE
182        vector_range &operator *= (const AT &at) {
183            vector_assign_scalar<scalar_multiplies_assign> (*this, at);
184            return *this;
185        }
186        template<class AT>
187        BOOST_UBLAS_INLINE
188        vector_range &operator /= (const AT &at) {
189            vector_assign_scalar<scalar_divides_assign> (*this, at);
190            return *this;
191        }
192
193        // Closure comparison
194        BOOST_UBLAS_INLINE
195        bool same_closure (const vector_range &vr) const {
196            return (*this).data_.same_closure (vr.data_);
197        }
198
199        // Comparison
200        BOOST_UBLAS_INLINE
201        bool operator == (const vector_range &vr) const {
202            return (*this).data_ == vr.data_ && r_ == vr.r_;
203        }
204
205        // Swapping
206        BOOST_UBLAS_INLINE
207        void swap (vector_range vr) {
208            if (this != &vr) {
209                BOOST_UBLAS_CHECK (size () == vr.size (), bad_size ());
210                // Sparse ranges may be nonconformant now.
211                // std::swap_ranges (begin (), end (), vr.begin ());
212                vector_swap<scalar_swap> (*this, vr);
213            }
214        }
215        BOOST_UBLAS_INLINE
216        friend void swap (vector_range vr1, vector_range vr2) {
217            vr1.swap (vr2);
218        }
219
220        // Iterator types
221    private:
222        typedef typename V::const_iterator const_subiterator_type;
223        typedef typename boost::mpl::if_<boost::is_const<V>,
224                                          typename V::const_iterator,
225                                          typename V::iterator>::type subiterator_type;
226
227    public:
228#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
229        typedef indexed_iterator<vector_range<vector_type>,
230                                 typename subiterator_type::iterator_category> iterator;
231        typedef indexed_const_iterator<vector_range<vector_type>,
232                                       typename const_subiterator_type::iterator_category> const_iterator;
233#else
234        class const_iterator;
235        class iterator;
236#endif
237
238        // Element lookup
239        BOOST_UBLAS_INLINE
240        const_iterator find (size_type i) const {
241            const_subiterator_type it (data_.find (start () + i));
242#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
243            return const_iterator (*this, it.index ());
244#else
245            return const_iterator (*this, it);
246#endif
247        }
248        BOOST_UBLAS_INLINE
249        iterator find (size_type i) {
250            subiterator_type it (data_.find (start () + i));
251#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
252            return iterator (*this, it.index ());
253#else
254            return iterator (*this, it);
255#endif
256        }
257
258#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
259        class const_iterator:
260            public container_const_reference<vector_range>,
261            public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
262                        iterator_base<const_iterator, value_type>::type {
263        public:
264            typedef typename const_subiterator_type::difference_type difference_type;
265            typedef typename const_subiterator_type::value_type value_type;
266            typedef typename const_subiterator_type::reference reference;
267            typedef typename const_subiterator_type::pointer pointer;
268
269            // Construction and destruction
270            BOOST_UBLAS_INLINE
271            const_iterator ():
272                container_const_reference<self_type> (), it_ () {}
273            BOOST_UBLAS_INLINE
274            const_iterator (const self_type &vr, const const_subiterator_type &it):
275                container_const_reference<self_type> (vr), it_ (it) {}
276            BOOST_UBLAS_INLINE
277            const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
278                container_const_reference<self_type> (it ()), it_ (it.it_) {}
279
280            // Arithmetic
281            BOOST_UBLAS_INLINE
282            const_iterator &operator ++ () {
283                ++ it_;
284                return *this;
285            }
286            BOOST_UBLAS_INLINE
287            const_iterator &operator -- () {
288                -- it_;
289                return *this;
290            }
291            BOOST_UBLAS_INLINE
292            const_iterator &operator += (difference_type n) {
293                it_ += n;
294                return *this;
295            }
296            BOOST_UBLAS_INLINE
297            const_iterator &operator -= (difference_type n) {
298                it_ -= n;
299                return *this;
300            }
301            BOOST_UBLAS_INLINE
302            difference_type operator - (const const_iterator &it) const {
303                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
304                return it_ - it.it_;
305            }
306
307            // Dereference
308            BOOST_UBLAS_INLINE
309            const_reference operator * () const {
310                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
311                return *it_;
312            }
313            BOOST_UBLAS_INLINE
314            const_reference operator [] (difference_type n) const {
315                return *(*this + n);
316            }
317
318            // Index
319            BOOST_UBLAS_INLINE
320            size_type index () const {
321                return it_.index () - (*this) ().start ();
322            }
323
324            // Assignment
325            BOOST_UBLAS_INLINE
326            const_iterator &operator = (const const_iterator &it) {
327                container_const_reference<self_type>::assign (&it ());
328                it_ = it.it_;
329                return *this;
330            }
331
332            // Comparison
333            BOOST_UBLAS_INLINE
334            bool operator == (const const_iterator &it) const {
335                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
336                return it_ == it.it_;
337            }
338            BOOST_UBLAS_INLINE
339            bool operator < (const const_iterator &it) const {
340                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
341                return it_ < it.it_;
342            }
343
344        private:
345            const_subiterator_type it_;
346        };
347#endif
348
349        BOOST_UBLAS_INLINE
350        const_iterator begin () const {
351            return find (0);
352        }
353        BOOST_UBLAS_INLINE
354        const_iterator end () const {
355            return find (size ());
356        }
357
358#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
359        class iterator:
360            public container_reference<vector_range>,
361            public iterator_base_traits<typename subiterator_type::iterator_category>::template
362                        iterator_base<iterator, value_type>::type {
363        public:
364            typedef typename subiterator_type::difference_type difference_type;
365            typedef typename subiterator_type::value_type value_type;
366            typedef typename subiterator_type::reference reference;
367            typedef typename subiterator_type::pointer pointer;
368
369            // Construction and destruction
370            BOOST_UBLAS_INLINE
371            iterator ():
372                container_reference<self_type> (), it_ () {}
373            BOOST_UBLAS_INLINE
374            iterator (self_type &vr, const subiterator_type &it):
375                container_reference<self_type> (vr), it_ (it) {}
376
377            // Arithmetic
378            BOOST_UBLAS_INLINE
379            iterator &operator ++ () {
380                ++ it_;
381                return *this;
382            }
383            BOOST_UBLAS_INLINE
384            iterator &operator -- () {
385                -- it_;
386                return *this;
387            }
388            BOOST_UBLAS_INLINE
389            iterator &operator += (difference_type n) {
390                it_ += n;
391                return *this;
392            }
393            BOOST_UBLAS_INLINE
394            iterator &operator -= (difference_type n) {
395                it_ -= n;
396                return *this;
397            }
398            BOOST_UBLAS_INLINE
399            difference_type operator - (const iterator &it) const {
400                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
401                return it_ - it.it_;
402            }
403
404            // Dereference
405            BOOST_UBLAS_INLINE
406            reference operator * () const {
407                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
408                return *it_;
409            }
410            BOOST_UBLAS_INLINE
411            reference operator [] (difference_type n) const {
412                return *(*this + n);
413            }
414
415            // Index
416            BOOST_UBLAS_INLINE
417            size_type index () const {
418                return it_.index () - (*this) ().start ();
419            }
420
421            // Assignment
422            BOOST_UBLAS_INLINE
423            iterator &operator = (const iterator &it) {
424                container_reference<self_type>::assign (&it ());
425                it_ = it.it_;
426                return *this;
427            }
428
429            // Comparison
430            BOOST_UBLAS_INLINE
431            bool operator == (const iterator &it) const {
432                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
433                return it_ == it.it_;
434            }
435            BOOST_UBLAS_INLINE
436            bool operator < (const iterator &it) const {
437                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
438                return it_ < it.it_;
439            }
440
441        private:
442            subiterator_type it_;
443
444            friend class const_iterator;
445        };
446#endif
447
448        BOOST_UBLAS_INLINE
449        iterator begin () {
450            return find (0);
451        }
452        BOOST_UBLAS_INLINE
453        iterator end () {
454            return find (size ());
455        }
456
457        // Reverse iterator
458        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
459        typedef reverse_iterator_base<iterator> reverse_iterator;
460
461        BOOST_UBLAS_INLINE
462        const_reverse_iterator rbegin () const {
463            return const_reverse_iterator (end ());
464        }
465        BOOST_UBLAS_INLINE
466        const_reverse_iterator rend () const {
467            return const_reverse_iterator (begin ());
468        }
469        BOOST_UBLAS_INLINE
470        reverse_iterator rbegin () {
471            return reverse_iterator (end ());
472        }
473        BOOST_UBLAS_INLINE
474        reverse_iterator rend () {
475            return reverse_iterator (begin ());
476        }
477
478    private:
479        vector_closure_type data_;
480        range_type r_;
481    };
482
483    // Simple Projections
484    template<class V>
485    BOOST_UBLAS_INLINE
486    vector_range<V> subrange (V &data, typename V::size_type start, typename V::size_type stop) {
487        typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
488        return vector_range<V> (data, range_type (start, stop));
489    }
490    template<class V>
491    BOOST_UBLAS_INLINE
492    vector_range<const V> subrange (const V &data, typename V::size_type start, typename V::size_type stop) {
493        typedef basic_range<typename V::size_type, typename V::difference_type> range_type;
494        return vector_range<const V> (data, range_type (start, stop));
495    }
496
497    // Generic Projections
498    template<class V>
499    BOOST_UBLAS_INLINE
500    vector_range<V> project (V &data, typename vector_range<V>::range_type const &r) {
501        return vector_range<V> (data, r);
502    }
503    template<class V>
504    BOOST_UBLAS_INLINE
505    const vector_range<const V> project (const V &data, typename vector_range<V>::range_type const &r) {
506        // ISSUE was: return vector_range<V> (const_cast<V &> (data), r);
507        return vector_range<const V> (data, r);
508    }
509    template<class V>
510    BOOST_UBLAS_INLINE
511    vector_range<V> project (vector_range<V> &data, const typename vector_range<V>::range_type &r) {
512        return data.project (r);
513    }
514    template<class V>
515    BOOST_UBLAS_INLINE
516    const vector_range<V> project (const vector_range<V> &data, const typename vector_range<V>::range_type &r) {
517        return data.project (r);
518    }
519
520    // Specialization of temporary_traits
521    template <class V>
522    struct vector_temporary_traits< vector_range<V> >
523    : vector_temporary_traits< V > {} ;
524    template <class V>
525    struct vector_temporary_traits< const vector_range<V> >
526    : vector_temporary_traits< V > {} ;
527
528
529    // Vector based slice class
530    template<class V>
531    class vector_slice:
532        public vector_expression<vector_slice<V> > {
533
534        typedef vector_slice<V> self_type;
535    public:
536#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
537        using vector_expression<self_type>::operator ();
538#endif
539        typedef const V const_vector_type;
540        typedef V vector_type;
541        typedef typename V::size_type size_type;
542        typedef typename V::difference_type difference_type;
543        typedef typename V::value_type value_type;
544        typedef typename V::const_reference const_reference;
545        typedef typename boost::mpl::if_<boost::is_const<V>,
546                                          typename V::const_reference,
547                                          typename V::reference>::type reference;
548        typedef typename boost::mpl::if_<boost::is_const<V>,
549                                          typename V::const_closure_type,
550                                          typename V::closure_type>::type vector_closure_type;
551        typedef basic_range<size_type, difference_type> range_type;
552        typedef basic_slice<size_type, difference_type> slice_type;
553        typedef const self_type const_closure_type;
554        typedef self_type closure_type;
555        typedef typename storage_restrict_traits<typename V::storage_category,
556                                                 dense_proxy_tag>::storage_category storage_category;
557
558        // Construction and destruction
559        BOOST_UBLAS_INLINE
560        vector_slice (vector_type &data, const slice_type &s):
561            data_ (data), s_ (s.preprocess (data.size ())) {
562            // Early checking of preconditions here.
563            // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
564            //                    s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
565        }
566        BOOST_UBLAS_INLINE
567        vector_slice (const vector_closure_type &data, const slice_type &s, int):
568            data_ (data), s_ (s.preprocess (data.size ())) {
569            // Early checking of preconditions here.
570            // BOOST_UBLAS_CHECK (s_.start () <= data_.size () &&
571            //                    s_.start () + s_.stride () * (s_.size () - (s_.size () > 0)) <= data_.size (), bad_index ());
572        }
573
574        // Accessors
575        BOOST_UBLAS_INLINE
576        size_type start () const {
577            return s_.start ();
578        }
579        BOOST_UBLAS_INLINE
580        difference_type stride () const {
581            return s_.stride ();
582        }
583        BOOST_UBLAS_INLINE
584        size_type size () const {
585            return s_.size ();
586        }
587
588        // Storage accessors
589        BOOST_UBLAS_INLINE
590        const vector_closure_type &data () const {
591            return data_;
592        }
593        BOOST_UBLAS_INLINE
594        vector_closure_type &data () {
595            return data_;
596        }
597
598        // Element access
599#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
600        BOOST_UBLAS_INLINE
601        const_reference operator () (size_type i) const {
602            return data_ (s_ (i));
603        }
604        BOOST_UBLAS_INLINE
605        reference operator () (size_type i) {
606            return data_ (s_ (i));
607        }
608
609        BOOST_UBLAS_INLINE
610        const_reference operator [] (size_type i) const {
611            return (*this) (i);
612        }
613        BOOST_UBLAS_INLINE
614        reference operator [] (size_type i) {
615            return (*this) (i);
616        }
617#else
618        BOOST_UBLAS_INLINE
619        reference operator () (size_type i) const {
620            return data_ (s_ (i));
621        }
622
623        BOOST_UBLAS_INLINE
624        reference operator [] (size_type i) const {
625            return (*this) (i);
626        }
627#endif
628
629        // ISSUE can this be done in free project function?
630        // Although a const function can create a non-const proxy to a non-const object
631        // Critical is that vector_type and data_ (vector_closure_type) are const correct
632        BOOST_UBLAS_INLINE
633        vector_slice<vector_type> project (const range_type &r) const {
634            return vector_slice<vector_type>  (data_, s_.compose (r.preprocess (data_.size ())), false);
635        }
636        BOOST_UBLAS_INLINE
637        vector_slice<vector_type> project (const slice_type &s) const {
638            return vector_slice<vector_type>  (data_, s_.compose (s.preprocess (data_.size ())), false);
639        }
640
641        // Assignment
642        BOOST_UBLAS_INLINE
643        vector_slice &operator = (const vector_slice &vs) {
644            // ISSUE need a temporary, proxy can be overlaping alias
645            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vs));
646            return *this;
647        }
648        BOOST_UBLAS_INLINE
649        vector_slice &assign_temporary (vector_slice &vs) {
650            // assign elements, proxied container remains the same
651            vector_assign<scalar_assign> (*this, vs);
652            return *this;
653        }
654        template<class AE>
655        BOOST_UBLAS_INLINE
656        vector_slice &operator = (const vector_expression<AE> &ae) {
657            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
658            return *this;
659        }
660        template<class AE>
661        BOOST_UBLAS_INLINE
662        vector_slice &assign (const vector_expression<AE> &ae) {
663            vector_assign<scalar_assign> (*this, ae);
664            return *this;
665        }
666        template<class AE>
667        BOOST_UBLAS_INLINE
668        vector_slice &operator += (const vector_expression<AE> &ae) {
669            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
670            return *this;
671        }
672        template<class AE>
673        BOOST_UBLAS_INLINE
674        vector_slice &plus_assign (const vector_expression<AE> &ae) {
675            vector_assign<scalar_plus_assign> (*this, ae);
676            return *this;
677        }
678        template<class AE>
679        BOOST_UBLAS_INLINE
680        vector_slice &operator -= (const vector_expression<AE> &ae) {
681            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
682            return *this;
683        }
684        template<class AE>
685        BOOST_UBLAS_INLINE
686        vector_slice &minus_assign (const vector_expression<AE> &ae) {
687            vector_assign<scalar_minus_assign> (*this, ae);
688            return *this;
689        }
690        template<class AT>
691        BOOST_UBLAS_INLINE
692        vector_slice &operator *= (const AT &at) {
693            vector_assign_scalar<scalar_multiplies_assign> (*this, at);
694            return *this;
695        }
696        template<class AT>
697        BOOST_UBLAS_INLINE
698        vector_slice &operator /= (const AT &at) {
699            vector_assign_scalar<scalar_divides_assign> (*this, at);
700            return *this;
701        }
702
703        // Closure comparison
704        BOOST_UBLAS_INLINE
705        bool same_closure (const vector_slice &vr) const {
706            return (*this).data_.same_closure (vr.data_);
707        }
708
709        // Comparison
710        BOOST_UBLAS_INLINE
711        bool operator == (const vector_slice &vs) const {
712            return (*this).data_ == vs.data_ && s_ == vs.s_;
713        }
714
715        // Swapping
716        BOOST_UBLAS_INLINE
717        void swap (vector_slice vs) {
718            if (this != &vs) {
719                BOOST_UBLAS_CHECK (size () == vs.size (), bad_size ());
720                // Sparse ranges may be nonconformant now.
721                // std::swap_ranges (begin (), end (), vs.begin ());
722                vector_swap<scalar_swap> (*this, vs);
723            }
724        }
725        BOOST_UBLAS_INLINE
726        friend void swap (vector_slice vs1, vector_slice vs2) {
727            vs1.swap (vs2);
728        }
729
730        // Iterator types
731    private:
732        // Use slice as an index - FIXME this fails for packed assignment
733        typedef typename slice_type::const_iterator const_subiterator_type;
734        typedef typename slice_type::const_iterator subiterator_type;
735
736    public:
737#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
738        typedef indexed_iterator<vector_slice<vector_type>,
739                                 typename vector_type::iterator::iterator_category> iterator;
740        typedef indexed_const_iterator<vector_slice<vector_type>,
741                                       typename vector_type::const_iterator::iterator_category> const_iterator;
742#else
743        class const_iterator;
744        class iterator;
745#endif
746
747        // Element lookup
748        BOOST_UBLAS_INLINE
749        const_iterator find (size_type i) const {
750#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
751            return const_iterator (*this, i);
752#else
753            return const_iterator (*this, s_.begin () + i);
754#endif
755        }
756        BOOST_UBLAS_INLINE
757        iterator find (size_type i) {
758#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
759            return iterator (*this, i);
760#else
761            return iterator (*this, s_.begin () + i);
762#endif
763        }
764
765#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
766        class const_iterator:
767            public container_const_reference<vector_slice>,
768            public iterator_base_traits<typename V::const_iterator::iterator_category>::template
769                        iterator_base<const_iterator, value_type>::type {
770        public:
771            typedef typename V::const_iterator::difference_type difference_type;
772            typedef typename V::const_iterator::value_type value_type;
773            typedef typename V::const_reference reference;    //FIXME due to indexing access
774            typedef typename V::const_iterator::pointer pointer;
775
776            // Construction and destruction
777            BOOST_UBLAS_INLINE
778            const_iterator ():
779                container_const_reference<self_type> (), it_ () {}
780            BOOST_UBLAS_INLINE
781            const_iterator (const self_type &vs, const const_subiterator_type &it):
782                container_const_reference<self_type> (vs), it_ (it) {}
783            BOOST_UBLAS_INLINE
784            const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
785                container_const_reference<self_type> (it ()), it_ (it.it_) {}
786
787            // Arithmetic
788            BOOST_UBLAS_INLINE
789            const_iterator &operator ++ () {
790                ++ it_;
791                return *this;
792            }
793            BOOST_UBLAS_INLINE
794            const_iterator &operator -- () {
795                -- it_;
796                return *this;
797            }
798            BOOST_UBLAS_INLINE
799            const_iterator &operator += (difference_type n) {
800                it_ += n;
801                return *this;
802            }
803            BOOST_UBLAS_INLINE
804            const_iterator &operator -= (difference_type n) {
805                it_ -= n;
806                return *this;
807            }
808            BOOST_UBLAS_INLINE
809            difference_type operator - (const const_iterator &it) const {
810                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
811                return it_ - it.it_;
812            }
813
814            // Dereference
815            BOOST_UBLAS_INLINE
816            const_reference operator * () const {
817                // FIXME replace find with at_element
818                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
819                return (*this) ().data_ (*it_);
820            }
821            BOOST_UBLAS_INLINE
822            const_reference operator [] (difference_type n) const {
823                return *(*this + n);
824            }
825
826            // Index
827            BOOST_UBLAS_INLINE
828            size_type index () const {
829                return it_.index ();
830            }
831
832            // Assignment
833            BOOST_UBLAS_INLINE
834            const_iterator &operator = (const const_iterator &it) {
835                container_const_reference<self_type>::assign (&it ());
836                it_ = it.it_;
837                return *this;
838            }
839
840            // Comparison
841            BOOST_UBLAS_INLINE
842            bool operator == (const const_iterator &it) const {
843                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
844                return it_ == it.it_;
845            }
846            BOOST_UBLAS_INLINE
847            bool operator < (const const_iterator &it) const {
848                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
849                return it_ < it.it_;
850            }
851
852        private:
853            const_subiterator_type it_;
854        };
855#endif
856
857        BOOST_UBLAS_INLINE
858        const_iterator begin () const {
859            return find (0);
860        }
861        BOOST_UBLAS_INLINE
862        const_iterator end () const {
863            return find (size ());
864        }
865
866#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
867        class iterator:
868            public container_reference<vector_slice>,
869            public iterator_base_traits<typename V::iterator::iterator_category>::template
870                        iterator_base<iterator, value_type>::type {
871        public:
872            typedef typename V::iterator::difference_type difference_type;
873            typedef typename V::iterator::value_type value_type;
874            typedef typename V::reference reference;    //FIXME due to indexing access
875            typedef typename V::iterator::pointer pointer;
876
877            // Construction and destruction
878            BOOST_UBLAS_INLINE
879            iterator ():
880                container_reference<self_type> (), it_ () {}
881            BOOST_UBLAS_INLINE
882            iterator (self_type &vs, const subiterator_type &it):
883                container_reference<self_type> (vs), it_ (it) {}
884
885            // Arithmetic
886            BOOST_UBLAS_INLINE
887            iterator &operator ++ () {
888                ++ it_;
889                return *this;
890            }
891            BOOST_UBLAS_INLINE
892            iterator &operator -- () {
893                -- it_;
894                return *this;
895            }
896            BOOST_UBLAS_INLINE
897            iterator &operator += (difference_type n) {
898                it_ += n;
899                return *this;
900            }
901            BOOST_UBLAS_INLINE
902            iterator &operator -= (difference_type n) {
903                it_ -= n;
904                return *this;
905            }
906            BOOST_UBLAS_INLINE
907            difference_type operator - (const iterator &it) const {
908                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
909                return it_ - it.it_;
910            }
911
912            // Dereference
913            BOOST_UBLAS_INLINE
914            reference operator * () const {
915                // FIXME replace find with at_element
916                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
917                return (*this) ().data_ (*it_);
918            }
919            BOOST_UBLAS_INLINE
920            reference operator [] (difference_type n) const {
921                return *(*this + n);
922            }
923
924
925            // Index
926            BOOST_UBLAS_INLINE
927            size_type index () const {
928                return it_.index ();
929            }
930
931            // Assignment
932            BOOST_UBLAS_INLINE
933            iterator &operator = (const iterator &it) {
934                container_reference<self_type>::assign (&it ());
935                it_ = it.it_;
936                return *this;
937            }
938
939            // Comparison
940            BOOST_UBLAS_INLINE
941            bool operator == (const iterator &it) const {
942                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
943                return it_ == it.it_;
944            }
945            BOOST_UBLAS_INLINE
946            bool operator < (const iterator &it) const {
947                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
948                return it_ < it.it_;
949            }
950
951        private:
952            subiterator_type it_;
953
954            friend class const_iterator;
955        };
956#endif
957
958        BOOST_UBLAS_INLINE
959        iterator begin () {
960            return find (0);
961        }
962        BOOST_UBLAS_INLINE
963        iterator end () {
964            return find (size ());
965        }
966
967        // Reverse iterator
968        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
969        typedef reverse_iterator_base<iterator> reverse_iterator;
970
971        BOOST_UBLAS_INLINE
972        const_reverse_iterator rbegin () const {
973            return const_reverse_iterator (end ());
974        }
975        BOOST_UBLAS_INLINE
976        const_reverse_iterator rend () const {
977            return const_reverse_iterator (begin ());
978        }
979        BOOST_UBLAS_INLINE
980        reverse_iterator rbegin () {
981            return reverse_iterator (end ());
982        }
983        BOOST_UBLAS_INLINE
984        reverse_iterator rend () {
985            return reverse_iterator (begin ());
986        }
987
988    private:
989        vector_closure_type data_;
990        slice_type s_;
991    };
992
993    // Simple Projections
994    template<class V>
995    BOOST_UBLAS_INLINE
996    vector_slice<V> subslice (V &data, typename V::size_type start, typename V::difference_type stride, typename V::size_type size) {
997        typedef basic_slice<typename V::size_type, typename V::difference_type> slice_type;
998        return vector_slice<V> (data, slice_type (start, stride, size));
999    }
1000    template<class V>
1001    BOOST_UBLAS_INLINE
1002    vector_slice<const V> subslice (const V &data, typename V::size_type start, typename V::difference_type stride, typename V::size_type size)  {
1003        typedef basic_slice<typename V::size_type, typename V::difference_type> slice_type;
1004        return vector_slice<const V> (data, slice_type (start, stride, size));
1005    }
1006
1007    // Generic Projections
1008    template<class V>
1009    BOOST_UBLAS_INLINE
1010    vector_slice<V> project (V &data, const typename vector_slice<V>::slice_type &s) {
1011        return vector_slice<V> (data, s);
1012    }
1013    template<class V>
1014    BOOST_UBLAS_INLINE
1015    const vector_slice<const V> project (const V &data, const typename vector_slice<V>::slice_type &s) {
1016        // ISSUE was: return vector_slice<V> (const_cast<V &> (data), s);
1017        return vector_slice<const V> (data, s);
1018    }
1019    template<class V>
1020    BOOST_UBLAS_INLINE
1021    vector_slice<V> project (vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
1022        return data.project (s);
1023    }
1024    template<class V>
1025    BOOST_UBLAS_INLINE
1026    const vector_slice<V> project (const vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
1027        return data.project (s);
1028    }
1029    // 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
1030    template<class V>
1031    BOOST_UBLAS_INLINE
1032    vector_slice<V> project (vector_slice<V> &data, const typename vector_range<V>::range_type &r) {
1033        return data.project (r);
1034    }
1035    template<class V>
1036    BOOST_UBLAS_INLINE
1037    const vector_slice<V> project (const vector_slice<V> &data, const typename vector_range<V>::range_type &r) {
1038        return data.project (r);
1039    }
1040
1041    // Specialization of temporary_traits
1042    template <class V>
1043    struct vector_temporary_traits< vector_slice<V> >
1044    : vector_temporary_traits< V > {} ;
1045    template <class V>
1046    struct vector_temporary_traits< const vector_slice<V> >
1047    : vector_temporary_traits< V > {} ;
1048
1049
1050    // Vector based indirection class
1051    // Contributed by Toon Knapen.
1052    // Extended and optimized by Kresimir Fresl.
1053    template<class V, class IA>
1054    class vector_indirect:
1055        public vector_expression<vector_indirect<V, IA> > {
1056
1057        typedef vector_indirect<V, IA> self_type;
1058    public:
1059#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1060        using vector_expression<self_type>::operator ();
1061#endif
1062        typedef const V const_vector_type;
1063        typedef V vector_type;
1064        typedef const IA const_indirect_array_type;
1065        typedef IA indirect_array_type;
1066        typedef typename V::size_type size_type;
1067        typedef typename V::difference_type difference_type;
1068        typedef typename V::value_type value_type;
1069        typedef typename V::const_reference const_reference;
1070        typedef typename boost::mpl::if_<boost::is_const<V>,
1071                                          typename V::const_reference,
1072                                          typename V::reference>::type reference;
1073        typedef typename boost::mpl::if_<boost::is_const<V>,
1074                                          typename V::const_closure_type,
1075                                          typename V::closure_type>::type vector_closure_type;
1076        typedef basic_range<size_type, difference_type> range_type;
1077        typedef basic_slice<size_type, difference_type> slice_type;
1078        typedef const self_type const_closure_type;
1079        typedef self_type closure_type;
1080        typedef typename storage_restrict_traits<typename V::storage_category,
1081                                                 dense_proxy_tag>::storage_category storage_category;
1082
1083        // Construction and destruction
1084        BOOST_UBLAS_INLINE
1085        vector_indirect (vector_type &data, size_type size):
1086            data_ (data), ia_ (size) {}
1087        BOOST_UBLAS_INLINE
1088        vector_indirect (vector_type &data, const indirect_array_type &ia):
1089            data_ (data), ia_ (ia.preprocess (data.size ())) {}
1090        BOOST_UBLAS_INLINE
1091        vector_indirect (const vector_closure_type &data, const indirect_array_type &ia, int):
1092            data_ (data), ia_ (ia.preprocess (data.size ())) {}
1093
1094        // Accessors
1095        BOOST_UBLAS_INLINE
1096        size_type size () const {
1097            return ia_.size ();
1098        }
1099        BOOST_UBLAS_INLINE
1100        const_indirect_array_type &indirect () const {
1101            return ia_;
1102        }
1103        BOOST_UBLAS_INLINE
1104        indirect_array_type &indirect () {
1105            return ia_;
1106        }
1107
1108        // Storage accessors
1109        BOOST_UBLAS_INLINE
1110        const vector_closure_type &data () const {
1111            return data_;
1112        }
1113        BOOST_UBLAS_INLINE
1114        vector_closure_type &data () {
1115            return data_;
1116        }
1117
1118        // Element access
1119#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1120        BOOST_UBLAS_INLINE
1121        const_reference operator () (size_type i) const {
1122            return data_ (ia_ (i));
1123        }
1124        BOOST_UBLAS_INLINE
1125        reference operator () (size_type i) {
1126            return data_ (ia_ (i));
1127        }
1128
1129        BOOST_UBLAS_INLINE
1130        const_reference operator [] (size_type i) const {
1131            return (*this) (i);
1132        }
1133        BOOST_UBLAS_INLINE
1134        reference operator [] (size_type i) {
1135            return (*this) (i);
1136        }
1137#else
1138        BOOST_UBLAS_INLINE
1139        reference operator () (size_type i) const {
1140            return data_ (ia_ (i));
1141        }
1142
1143        BOOST_UBLAS_INLINE
1144        reference operator [] (size_type i) const {
1145            return (*this) (i);
1146        }
1147#endif
1148
1149        // ISSUE can this be done in free project function?
1150        // Although a const function can create a non-const proxy to a non-const object
1151        // Critical is that vector_type and data_ (vector_closure_type) are const correct
1152        BOOST_UBLAS_INLINE
1153        vector_indirect<vector_type, indirect_array_type> project (const range_type &r) const {
1154            return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (r.preprocess (data_.size ())), 0);
1155        }
1156        BOOST_UBLAS_INLINE
1157        vector_indirect<vector_type, indirect_array_type> project (const slice_type &s) const {
1158            return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (s.preprocess (data_.size ())), 0);
1159        }
1160        BOOST_UBLAS_INLINE
1161        vector_indirect<vector_type, indirect_array_type> project (const indirect_array_type &ia) const {
1162            return vector_indirect<vector_type, indirect_array_type> (data_, ia_.compose (ia.preprocess (data_.size ())), 0);
1163        }
1164
1165        // Assignment
1166        BOOST_UBLAS_INLINE
1167        vector_indirect &operator = (const vector_indirect &vi) {
1168            // ISSUE need a temporary, proxy can be overlaping alias
1169            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vi));
1170            return *this;
1171        }
1172        BOOST_UBLAS_INLINE
1173        vector_indirect &assign_temporary (vector_indirect &vi) {
1174            // assign elements, proxied container remains the same
1175            vector_assign<scalar_assign> (*this, vi);
1176            return *this;
1177        }
1178        template<class AE>
1179        BOOST_UBLAS_INLINE
1180        vector_indirect &operator = (const vector_expression<AE> &ae) {
1181            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae));
1182            return *this;
1183        }
1184        template<class AE>
1185        BOOST_UBLAS_INLINE
1186        vector_indirect &assign (const vector_expression<AE> &ae) {
1187            vector_assign<scalar_assign> (*this, ae);
1188            return *this;
1189        }
1190        template<class AE>
1191        BOOST_UBLAS_INLINE
1192        vector_indirect &operator += (const vector_expression<AE> &ae) {
1193            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae));
1194            return *this;
1195        }
1196        template<class AE>
1197        BOOST_UBLAS_INLINE
1198        vector_indirect &plus_assign (const vector_expression<AE> &ae) {
1199            vector_assign<scalar_plus_assign> (*this, ae);
1200            return *this;
1201        }
1202        template<class AE>
1203        BOOST_UBLAS_INLINE
1204        vector_indirect &operator -= (const vector_expression<AE> &ae) {
1205            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae));
1206            return *this;
1207        }
1208        template<class AE>
1209        BOOST_UBLAS_INLINE
1210        vector_indirect &minus_assign (const vector_expression<AE> &ae) {
1211            vector_assign<scalar_minus_assign> (*this, ae);
1212            return *this;
1213        }
1214        template<class AT>
1215        BOOST_UBLAS_INLINE
1216        vector_indirect &operator *= (const AT &at) {
1217            vector_assign_scalar<scalar_multiplies_assign> (*this, at);
1218            return *this;
1219        }
1220        template<class AT>
1221        BOOST_UBLAS_INLINE
1222        vector_indirect &operator /= (const AT &at) {
1223            vector_assign_scalar<scalar_divides_assign> (*this, at);
1224            return *this;
1225        }
1226
1227        // Closure comparison
1228        BOOST_UBLAS_INLINE
1229        bool same_closure (const vector_indirect &vr) const {
1230return true;
1231        }
1232
1233        // Comparison
1234        BOOST_UBLAS_INLINE
1235        bool operator == (const vector_indirect &vi) const {
1236            return (*this).data_ == vi.data_ && ia_ == vi.ia_;
1237        }
1238
1239        // Swapping
1240        BOOST_UBLAS_INLINE
1241        void swap (vector_indirect vi) {
1242            if (this != &vi) {
1243                BOOST_UBLAS_CHECK (size () == vi.size (), bad_size ());
1244                // Sparse ranges may be nonconformant now.
1245                // std::swap_ranges (begin (), end (), vi.begin ());
1246                vector_swap<scalar_swap> (*this, vi);
1247            }
1248        }
1249        BOOST_UBLAS_INLINE
1250        friend void swap (vector_indirect vi1, vector_indirect vi2) {
1251            vi1.swap (vi2);
1252        }
1253
1254        // Iterator types
1255    private:
1256        // Use indirect array as an index - FIXME this fails for packed assignment
1257        typedef typename IA::const_iterator const_subiterator_type;
1258        typedef typename IA::const_iterator subiterator_type;
1259
1260    public:
1261#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1262        typedef indexed_iterator<vector_indirect<vector_type, indirect_array_type>,
1263                                 typename vector_type::iterator::iterator_category> iterator;
1264        typedef indexed_const_iterator<vector_indirect<vector_type, indirect_array_type>,
1265                                       typename vector_type::const_iterator::iterator_category> const_iterator;
1266#else
1267        class const_iterator;
1268        class iterator;
1269#endif
1270        // Element lookup
1271        BOOST_UBLAS_INLINE
1272        const_iterator find (size_type i) const {
1273#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1274            return const_iterator (*this, i);
1275#else
1276            return const_iterator (*this, ia_.begin () + i);
1277#endif
1278        }
1279        BOOST_UBLAS_INLINE
1280        iterator find (size_type i) {
1281#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1282            return iterator (*this, i);
1283#else
1284            return iterator (*this, ia_.begin () + i);
1285#endif
1286        }
1287
1288        // Iterators simply are indices.
1289
1290#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1291        class const_iterator:
1292            public container_const_reference<vector_indirect>,
1293            public iterator_base_traits<typename V::const_iterator::iterator_category>::template
1294                        iterator_base<const_iterator, value_type>::type {
1295        public:
1296            typedef typename V::const_iterator::difference_type difference_type;
1297            typedef typename V::const_iterator::value_type value_type;
1298            typedef typename V::const_reference reference;    //FIXME due to indexing access
1299            typedef typename V::const_iterator::pointer pointer;
1300
1301            // Construction and destruction
1302            BOOST_UBLAS_INLINE
1303            const_iterator ():
1304                container_const_reference<self_type> (), it_ () {}
1305            BOOST_UBLAS_INLINE
1306            const_iterator (const self_type &vi, const const_subiterator_type &it):
1307                container_const_reference<self_type> (vi), it_ (it) {}
1308            BOOST_UBLAS_INLINE
1309            const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
1310                container_const_reference<self_type> (it ()), it_ (it.it_) {}
1311
1312            // Arithmetic
1313            BOOST_UBLAS_INLINE
1314            const_iterator &operator ++ () {
1315                ++ it_;
1316                return *this;
1317            }
1318            BOOST_UBLAS_INLINE
1319            const_iterator &operator -- () {
1320                -- it_;
1321                return *this;
1322            }
1323            BOOST_UBLAS_INLINE
1324            const_iterator &operator += (difference_type n) {
1325                it_ += n;
1326                return *this;
1327            }
1328            BOOST_UBLAS_INLINE
1329            const_iterator &operator -= (difference_type n) {
1330                it_ -= n;
1331                return *this;
1332            }
1333            BOOST_UBLAS_INLINE
1334            difference_type operator - (const const_iterator &it) const {
1335                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1336                return it_ - it.it_;
1337            }
1338
1339            // Dereference
1340            BOOST_UBLAS_INLINE
1341            const_reference operator * () const {
1342                // FIXME replace find with at_element
1343                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1344                return (*this) ().data_ (*it_);
1345            }
1346            BOOST_UBLAS_INLINE
1347            const_reference operator [] (difference_type n) const {
1348                return *(*this + n);
1349            }
1350
1351            // Index
1352            BOOST_UBLAS_INLINE
1353            size_type index () const {
1354                return it_.index ();
1355            }
1356
1357            // Assignment
1358            BOOST_UBLAS_INLINE
1359            const_iterator &operator = (const const_iterator &it) {
1360                container_const_reference<self_type>::assign (&it ());
1361                it_ = it.it_;
1362                return *this;
1363            }
1364
1365            // Comparison
1366            BOOST_UBLAS_INLINE
1367            bool operator == (const const_iterator &it) const {
1368                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1369                return it_ == it.it_;
1370            }
1371            BOOST_UBLAS_INLINE
1372            bool operator < (const const_iterator &it) const {
1373                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1374                return it_ < it.it_;
1375            }
1376
1377        private:
1378            const_subiterator_type it_;
1379        };
1380#endif
1381
1382        BOOST_UBLAS_INLINE
1383        const_iterator begin () const {
1384            return find (0);
1385        }
1386        BOOST_UBLAS_INLINE
1387        const_iterator end () const {
1388            return find (size ());
1389        }
1390
1391#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1392        class iterator:
1393            public container_reference<vector_indirect>,
1394            public iterator_base_traits<typename V::iterator::iterator_category>::template
1395                        iterator_base<iterator, value_type>::type {
1396        public:
1397            typedef typename V::iterator::difference_type difference_type;
1398            typedef typename V::iterator::value_type value_type;
1399            typedef typename V::reference reference;    //FIXME due to indexing access
1400            typedef typename V::iterator::pointer pointer;
1401
1402            // Construction and destruction
1403            BOOST_UBLAS_INLINE
1404            iterator ():
1405                container_reference<self_type> (), it_ () {}
1406            BOOST_UBLAS_INLINE
1407            iterator (self_type &vi, const subiterator_type &it):
1408                container_reference<self_type> (vi), it_ (it) {}
1409
1410            // Arithmetic
1411            BOOST_UBLAS_INLINE
1412            iterator &operator ++ () {
1413                ++ it_;
1414                return *this;
1415            }
1416            BOOST_UBLAS_INLINE
1417            iterator &operator -- () {
1418                -- it_;
1419                return *this;
1420            }
1421            BOOST_UBLAS_INLINE
1422            iterator &operator += (difference_type n) {
1423                it_ += n;
1424                return *this;
1425            }
1426            BOOST_UBLAS_INLINE
1427            iterator &operator -= (difference_type n) {
1428                it_ -= n;
1429                return *this;
1430            }
1431            BOOST_UBLAS_INLINE
1432            difference_type operator - (const iterator &it) const {
1433                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1434                return it_ - it.it_;
1435            }
1436
1437            // Dereference
1438            BOOST_UBLAS_INLINE
1439            reference operator * () const {
1440                // FIXME replace find with at_element
1441                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
1442                return (*this) ().data_ (*it_);
1443            }
1444            BOOST_UBLAS_INLINE
1445            reference operator [] (difference_type n) const {
1446                return *(*this + n);
1447            }
1448
1449            // Index
1450            BOOST_UBLAS_INLINE
1451            size_type index () const {
1452                return it_.index ();
1453            }
1454
1455            // Assignment
1456            BOOST_UBLAS_INLINE
1457            iterator &operator = (const iterator &it) {
1458                container_reference<self_type>::assign (&it ());
1459                it_ = it.it_;
1460                return *this;
1461            }
1462
1463            // Comparison
1464            BOOST_UBLAS_INLINE
1465            bool operator == (const iterator &it) const {
1466                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1467                return it_ == it.it_;
1468            }
1469            BOOST_UBLAS_INLINE
1470            bool operator < (const iterator &it) const {
1471                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1472                return it_ < it.it_;
1473            }
1474
1475        private:
1476            subiterator_type it_;
1477
1478            friend class const_iterator;
1479        };
1480#endif
1481
1482        BOOST_UBLAS_INLINE
1483        iterator begin () {
1484            return find (0);
1485        }
1486        BOOST_UBLAS_INLINE
1487        iterator end () {
1488            return find (size ());
1489        }
1490
1491        // Reverse iterator
1492        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1493        typedef reverse_iterator_base<iterator> reverse_iterator;
1494
1495        BOOST_UBLAS_INLINE
1496        const_reverse_iterator rbegin () const {
1497            return const_reverse_iterator (end ());
1498        }
1499        BOOST_UBLAS_INLINE
1500        const_reverse_iterator rend () const {
1501            return const_reverse_iterator (begin ());
1502        }
1503        BOOST_UBLAS_INLINE
1504        reverse_iterator rbegin () {
1505            return reverse_iterator (end ());
1506        }
1507        BOOST_UBLAS_INLINE
1508        reverse_iterator rend () {
1509            return reverse_iterator (begin ());
1510        }
1511
1512    private:
1513        vector_closure_type data_;
1514        indirect_array_type ia_;
1515    };
1516
1517    // Projections
1518    template<class V, class A>
1519    BOOST_UBLAS_INLINE
1520    vector_indirect<V, indirect_array<A> > project (V &data, const indirect_array<A> &ia) {
1521        return vector_indirect<V, indirect_array<A> > (data, ia);
1522    }
1523    template<class V, class A>
1524    BOOST_UBLAS_INLINE
1525    const vector_indirect<const V, indirect_array<A> > project (const V &data, const indirect_array<A> &ia) {
1526        // ISSUE was: return vector_indirect<V, indirect_array<A> > (const_cast<V &> (data), ia)
1527        return vector_indirect<const V, indirect_array<A> > (data, ia);
1528    }
1529    template<class V, class IA>
1530    BOOST_UBLAS_INLINE
1531    vector_indirect<V, IA> project (vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::range_type &r) {
1532        return data.project (r);
1533    }
1534    template<class V, class IA>
1535    BOOST_UBLAS_INLINE
1536    const vector_indirect<V, IA> project (const vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::range_type &r) {
1537        return data.project (r);
1538    }
1539    template<class V, class IA>
1540    BOOST_UBLAS_INLINE
1541    vector_indirect<V, IA> project (vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::slice_type &s) {
1542        return data.project (s);
1543    }
1544    template<class V, class IA>
1545    BOOST_UBLAS_INLINE
1546    const vector_indirect<V, IA> project (const vector_indirect<V, IA> &data, const typename vector_indirect<V, IA>::slice_type &s) {
1547        return data.project (s);
1548    }
1549    template<class V, class A>
1550    BOOST_UBLAS_INLINE
1551    vector_indirect<V, indirect_array<A> > project (vector_indirect<V, indirect_array<A> > &data, const indirect_array<A> &ia) {
1552        return data.project (ia);
1553    }
1554    template<class V, class A>
1555    BOOST_UBLAS_INLINE
1556    const vector_indirect<V, indirect_array<A> > project (const vector_indirect<V, indirect_array<A> > &data, const indirect_array<A> &ia) {
1557        return data.project (ia);
1558    }
1559
1560    // Specialization of temporary_traits
1561    template <class V>
1562    struct vector_temporary_traits< vector_indirect<V> >
1563    : vector_temporary_traits< V > {} ;
1564    template <class V>
1565    struct vector_temporary_traits< const vector_indirect<V> >
1566    : vector_temporary_traits< V > {} ;
1567
1568}}}
1569
1570#endif
Note: See TracBrowser for help on using the repository browser.