1 | // |
2 | // Copyright (c) 2000-2002 |
3 | // Joerg Walter, Mathias Koch |
4 | // |
5 | // Distributed under the Boost Software License, Version 1.0. (See |
6 | // accompanying file LICENSE_1_0.txt or copy at |
7 | // http://www.boost.org/LICENSE_1_0.txt) |
8 | // |
9 | // The authors gratefully acknowledge the support of |
10 | // GeNeSys mbH & Co. KG in producing this work. |
11 | // |
12 | |
13 | #ifndef _BOOST_UBLAS_VECTOR_PROXY_ |
14 | #define _BOOST_UBLAS_VECTOR_PROXY_ |
15 | |
16 | #include <boost/numeric/ublas/vector_expression.hpp> |
17 | #include <boost/numeric/ublas/detail/vector_assign.hpp> |
18 | #include <boost/numeric/ublas/detail/temporary.hpp> |
19 | |
20 | // Iterators based on ideas of Jeremy Siek |
21 | |
22 | namespace boost { namespace numeric { namespace ublas { |
23 | |
24 | /** \brief A vector referencing a continuous subvector of elements of vector \c v containing all elements specified by \c range. |
25 | * |
26 | * A vector range can be used as a normal vector in any expression. |
27 | * If the specified range falls outside that of the index range of the vector, then |
28 | * the \c vector_range is not a well formed \i Vector \i Expression and access to an |
29 | * element outside of index range of the vector is \b undefined. |
30 | * |
31 | * \tparam V the type of vector referenced (for example \c vector<double>) |
32 | */ |
33 | template<class V> |
34 | class vector_range: |
35 | public vector_expression<vector_range<V> > { |
36 | |
37 | typedef vector_range<V> self_type; |
38 | public: |
39 | #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS |
40 | using vector_expression<self_type>::operator (); |
41 | #endif |
42 | typedef const V const_vector_type; |
43 | typedef V vector_type; |
44 | typedef typename V::size_type size_type; |
45 | typedef typename V::difference_type difference_type; |
46 | typedef typename V::value_type value_type; |
47 | typedef typename V::const_reference const_reference; |
48 | typedef typename boost::mpl::if_<boost::is_const<V>, |
49 | typename V::const_reference, |
50 | typename V::reference>::type reference; |
51 | typedef typename boost::mpl::if_<boost::is_const<V>, |
52 | typename V::const_closure_type, |
53 | typename V::closure_type>::type vector_closure_type; |
54 | typedef basic_range<size_type, difference_type> range_type; |
55 | typedef const self_type const_closure_type; |
56 | typedef self_type closure_type; |
57 | typedef typename storage_restrict_traits<typename V::storage_category, |
58 | dense_proxy_tag>::storage_category storage_category; |
59 | |
60 | // Construction and destruction |
61 | BOOST_UBLAS_INLINE |
62 | vector_range (vector_type &data, const range_type &r): |
63 | data_ (data), r_ (r.preprocess (data.size ())) { |
64 | // Early checking of preconditions here. |
65 | // BOOST_UBLAS_CHECK (r_.start () <= data_.size () && |
66 | // r_.start () + r_.size () <= data_.size (), bad_index ()); |
67 | } |
68 | BOOST_UBLAS_INLINE |
69 | vector_range (const vector_closure_type &data, const range_type &r, bool): |
70 | data_ (data), r_ (r.preprocess (data.size ())) { |
71 | // Early checking of preconditions here. |
72 | // BOOST_UBLAS_CHECK (r_.start () <= data_.size () && |
73 | // r_.start () + r_.size () <= data_.size (), bad_index ()); |
74 | } |
75 | |
76 | // Accessors |
77 | BOOST_UBLAS_INLINE |
78 | size_type start () const { |
79 | return r_.start (); |
80 | } |
81 | BOOST_UBLAS_INLINE |
82 | size_type size () const { |
83 | return r_.size (); |
84 | } |
85 | |
86 | // Storage accessors |
87 | BOOST_UBLAS_INLINE |
88 | const vector_closure_type &data () const { |
89 | return data_; |
90 | } |
91 | BOOST_UBLAS_INLINE |
92 | vector_closure_type &data () { |
93 | return data_; |
94 | } |
95 | |
96 | // Element access |
97 | #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER |
98 | BOOST_UBLAS_INLINE |
99 | const_reference operator () (size_type i) const { |
100 | return data_ (r_ (i)); |
101 | } |
102 | BOOST_UBLAS_INLINE |
103 | reference operator () (size_type i) { |
104 | return data_ (r_ (i)); |
105 | } |
106 | |
107 | BOOST_UBLAS_INLINE |
108 | const_reference operator [] (size_type i) const { |
109 | return (*this) (i); |
110 | } |
111 | BOOST_UBLAS_INLINE |
112 | reference operator [] (size_type i) { |
113 | return (*this) (i); |
114 | } |
115 | #else |
116 | BOOST_UBLAS_INLINE |
117 | reference operator () (size_type i) const { |
118 | return data_ (r_ (i)); |
119 | } |
120 | |
121 | BOOST_UBLAS_INLINE |
122 | reference operator [] (size_type i) const { |
123 | return (*this) (i); |
124 | } |
125 | #endif |
126 | |
127 | // ISSUE can this be done in free project function? |
128 | // Although a const function can create a non-const proxy to a non-const object |
129 | // Critical is that vector_type and data_ (vector_closure_type) are const correct |
130 | BOOST_UBLAS_INLINE |
131 | vector_range<vector_type> project (const range_type &r) const { |
132 | return vector_range<vector_type> (data_, r_.compose (r.preprocess (data_.size ())), false); |
133 | } |
134 | |
135 | // Assignment |
136 | BOOST_UBLAS_INLINE |
137 | vector_range &operator = (const vector_range &vr) { |
138 | // ISSUE need a temporary, proxy can be overlaping alias |
139 | vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (vr)); |
140 | return *this; |
141 | } |
142 | BOOST_UBLAS_INLINE |
143 | vector_range &assign_temporary (vector_range &vr) { |
144 | // assign elements, proxied container remains the same |
145 | vector_assign<scalar_assign> (*this, vr); |
146 | return *this; |
147 | } |
148 | template<class AE> |
149 | BOOST_UBLAS_INLINE |
150 | vector_range &operator = (const vector_expression<AE> &ae) { |
151 | vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (ae)); |
152 | return *this; |
153 | } |
154 | template<class AE> |
155 | BOOST_UBLAS_INLINE |
156 | vector_range &assign (const vector_expression<AE> &ae) { |
157 | vector_assign<scalar_assign> (*this, ae); |
158 | return *this; |
159 | } |
160 | template<class AE> |
161 | BOOST_UBLAS_INLINE |
162 | vector_range &operator += (const vector_expression<AE> &ae) { |
163 | vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this + ae)); |
164 | return *this; |
165 | } |
166 | template<class AE> |
167 | BOOST_UBLAS_INLINE |
168 | vector_range &plus_assign (const vector_expression<AE> &ae) { |
169 | vector_assign<scalar_plus_assign> (*this, ae); |
170 | return *this; |
171 | } |
172 | template<class AE> |
173 | BOOST_UBLAS_INLINE |
174 | vector_range &operator -= (const vector_expression<AE> &ae) { |
175 | vector_assign<scalar_assign> (*this, typename vector_temporary_traits<V>::type (*this - ae)); |
176 | return *this; |
177 | } |
178 | template<class AE> |
179 | BOOST_UBLAS_INLINE |
180 | vector_range &minus_assign (const vector_expression<AE> &ae) { |
181 | vector_assign<scalar_minus_assign> (*this, ae); |
182 | return *this; |
183 | } |
184 | template<class AT> |
185 | BOOST_UBLAS_INLINE |
186 | vector_range &operator *= (const AT &at) { |
187 | vector_assign_scalar<scalar_multiplies_assign> (*this, at); |
188 | return *this; |
189 | } |
190 | template<class AT> |
191 | BOOST_UBLAS_INLINE |
192 | vector_range &operator /= (const AT &at) { |
193 | vector_assign_scalar<scalar_divides_assign> (*this, at); |
194 | return *this; |
195 | } |
196 | |
197 | // Closure comparison |
198 | BOOST_UBLAS_INLINE |
199 | bool same_closure (const vector_range &vr) const { |
200 | return (*this).data_.same_closure (vr.data_); |
201 | } |
202 | |
203 | // Comparison |
204 | BOOST_UBLAS_INLINE |
205 | bool operator == (const vector_range &vr) const { |
206 | return (*this).data_ == vr.data_ && r_ == vr.r_; |
207 | } |
208 | |
209 | // Swapping |
210 | BOOST_UBLAS_INLINE |
211 | void swap (vector_range vr) { |
212 | if (this != &vr) { |
213 | BOOST_UBLAS_CHECK (size () == vr.size (), bad_size ()); |
214 | // Sparse ranges may be nonconformant now. |
215 | // std::swap_ranges (begin (), end (), vr.begin ()); |
216 | vector_swap<scalar_swap> (*this, vr); |
217 | } |
218 | } |
219 | BOOST_UBLAS_INLINE |
220 | friend void swap (vector_range vr1, vector_range vr2) { |
221 | vr1.swap (vr2); |
222 | } |
223 | |
224 | // Iterator types |
225 | private: |
226 | typedef typename V::const_iterator const_subiterator_type; |
227 | typedef typename boost::mpl::if_<boost::is_const<V>, |
228 | typename V::const_iterator, |
229 | typename V::iterator>::type subiterator_type; |
230 | |
231 | public: |
232 | #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR |
233 | typedef indexed_iterator<vector_range<vector_type>, |
234 | typename subiterator_type::iterator_category> iterator; |
235 | typedef indexed_const_iterator<vector_range<vector_type>, |
236 | typename const_subiterator_type::iterator_category> const_iterator; |
237 | #else |
238 | class const_iterator; |
239 | class iterator; |
240 | #endif |
241 | |
242 | // Element lookup |
243 | BOOST_UBLAS_INLINE |
244 | const_iterator find (size_type i) const { |
245 | const_subiterator_type it (data_.find (start () + i)); |
246 | #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR |
247 | return const_iterator (*this, it.index ()); |
248 | #else |
249 | return const_iterator (*this, it); |
250 | #endif |
251 | } |
252 | BOOST_UBLAS_INLINE |
253 | iterator find (size_type i) { |
254 | subiterator_type it (data_.find (start () + i)); |
255 | #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR |
256 | return iterator (*this, it.index ()); |
257 | #else |
258 | return iterator (*this, it); |
259 | #endif |
260 | } |
261 | |
262 | #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR |
263 | class const_iterator: |
264 | public container_const_reference<vector_range>, |
265 | public iterator_base_traits<typename const_subiterator_type::iterator_category>::template |
266 | iterator_base<const_iterator, value_type>::type { |
267 | public: |
268 | typedef typename const_subiterator_type::difference_type difference_type; |
269 | typedef typename const_subiterator_type::value_type value_type; |
270 | typedef typename const_subiterator_type::reference reference; |
271 | typedef typename const_subiterator_type::pointer pointer; |
272 | |
273 | // Construction and destruction |
274 | BOOST_UBLAS_INLINE |
275 | const_iterator (): |
276 | container_const_reference<self_type> (), it_ () {} |
277 | BOOST_UBLAS_INLINE |
278 | const_iterator (const self_type &vr, const const_subiterator_type &it): |
279 | container_const_reference<self_type> (vr), it_ (it) {} |
280 | BOOST_UBLAS_INLINE |
281 | const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here |
282 | container_const_reference<self_type> (it ()), it_ (it.it_) {} |
283 | |
284 | // Arithmetic |
285 | BOOST_UBLAS_INLINE |
286 | const_iterator &operator ++ () { |
287 | ++ it_; |
288 | return *this; |
289 | } |
290 | BOOST_UBLAS_INLINE |
291 | const_iterator &operator -- () { |
292 | -- it_; |
293 | return *this; |
294 | } |
295 | BOOST_UBLAS_INLINE |
296 | const_iterator &operator += (difference_type n) { |
297 | it_ += n; |
298 | return *this; |
299 | } |
300 | BOOST_UBLAS_INLINE |
301 | const_iterator &operator -= (difference_type n) { |
302 | it_ -= n; |
303 | return *this; |
304 | } |
305 | BOOST_UBLAS_INLINE |
306 | difference_type operator - (const const_iterator &it) const { |
307 | BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); |
308 | return it_ - it.it_; |
309 | } |
310 | |
311 | // Dereference |
312 | BOOST_UBLAS_INLINE |
313 | const_reference operator * () const { |
314 | BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); |
315 | return *it_; |
316 | } |
317 | BOOST_UBLAS_INLINE |
318 | const_reference operator [] (difference_type n) const { |
319 | return *(*this + n); |
320 | } |
321 | |
322 | // Index |
323 | BOOST_UBLAS_INLINE |
324 | size_type index () const { |
325 | return it_.index () - (*this) ().start (); |
326 | } |
327 | |
328 | // Assignment |
329 | BOOST_UBLAS_INLINE |
330 | const_iterator &operator = (const const_iterator &it) { |
331 | container_const_reference<self_type>::assign (&it ()); |
332 | it_ = it.it_; |
333 | return *this; |
334 | } |
335 | |
336 | // Comparison |
337 | BOOST_UBLAS_INLINE |
338 | bool operator == (const const_iterator &it) const { |
339 | BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); |
340 | return it_ == it.it_; |
341 | } |
342 | BOOST_UBLAS_INLINE |
343 | bool operator < (const const_iterator &it) const { |
344 | BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); |
345 | return it_ < it.it_; |
346 | } |
347 | |
348 | private: |
349 | const_subiterator_type it_; |
350 | }; |
351 | #endif |
352 | |
353 | BOOST_UBLAS_INLINE |
354 | const_iterator begin () const { |
355 | return find (0); |
356 | } |
357 | BOOST_UBLAS_INLINE |
358 | const_iterator 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 | |