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

source code of include/boost/numeric/ublas/vector_proxy.hpp