source: NonGTP/Boost/boost/numeric/ublas/vector_proxy.hpp @ 857

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