New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
vector_proxy.hpp in vendors/XIOS/current/extern/boost/include/boost/numeric/ublas – NEMO

source: vendors/XIOS/current/extern/boost/include/boost/numeric/ublas/vector_proxy.hpp @ 3428

Last change on this file since 3428 was 3428, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

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