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 vector_range(vector_type & data,const range_type & r)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 vector_range(const vector_closure_type & data,const range_type & r,bool)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 start() const78 size_type start () const { 79 return r_.start (); 80 } 81 BOOST_UBLAS_INLINE size() const82 size_type size () const { 83 return r_.size (); 84 } 85 86 // Storage accessors 87 BOOST_UBLAS_INLINE data() const88 const vector_closure_type &data () const { 89 return data_; 90 } 91 BOOST_UBLAS_INLINE data()92 vector_closure_type &data () { 93 return data_; 94 } 95 96 // Element access 97 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 98 BOOST_UBLAS_INLINE operator ()(size_type i) const99 const_reference operator () (size_type i) const { 100 return data_ (r_ (i)); 101 } 102 BOOST_UBLAS_INLINE operator ()(size_type i)103 reference operator () (size_type i) { 104 return data_ (r_ (i)); 105 } 106 107 BOOST_UBLAS_INLINE operator [](size_type i) const108 const_reference operator [] (size_type i) const { 109 return (*this) (i); 110 } 111 BOOST_UBLAS_INLINE operator [](size_type i)112 reference operator [] (size_type i) { 113 return (*this) (i); 114 } 115 #else 116 BOOST_UBLAS_INLINE operator ()(size_type i) const117 reference operator () (size_type i) const { 118 return data_ (r_ (i)); 119 } 120 121 BOOST_UBLAS_INLINE operator [](size_type i) const122 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 project(const range_type & r) const131 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 operator =(const vector_range & vr)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 assign_temporary(vector_range & vr)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 operator =(const vector_expression<AE> & ae)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 assign(const vector_expression<AE> & ae)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 operator +=(const vector_expression<AE> & ae)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 plus_assign(const vector_expression<AE> & ae)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 operator -=(const vector_expression<AE> & ae)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 minus_assign(const vector_expression<AE> & ae)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 operator *=(const AT & at)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 operator /=(const AT & at)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 same_closure(const vector_range & vr) const199 bool same_closure (const vector_range &vr) const { 200 return (*this).data_.same_closure (vr.data_); 201 } 202 203 // Comparison 204 BOOST_UBLAS_INLINE operator ==(const vector_range & vr) const205 bool operator == (const vector_range &vr) const { 206 return (*this).data_ == vr.data_ && r_ == vr.r_; 207 } 208 209 // Swapping 210 BOOST_UBLAS_INLINE swap(vector_range vr)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 swap(vector_range vr1,vector_range vr2)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 find(size_type i) const244 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 find(size_type i)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 const_iterator()275 const_iterator (): 276 container_const_reference<self_type> (), it_ () {} 277 BOOST_UBLAS_INLINE const_iterator(const self_type & vr,const const_subiterator_type & it)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 const_iterator(const typename self_type::iterator & it)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 operator ++()286 const_iterator &operator ++ () { 287 ++ it_; 288 return *this; 289 } 290 BOOST_UBLAS_INLINE operator --()291 const_iterator &operator -- () { 292 -- it_; 293 return *this; 294 } 295 BOOST_UBLAS_INLINE operator +=(difference_type n)296 const_iterator &operator += (difference_type n) { 297 it_ += n; 298 return *this; 299 } 300 BOOST_UBLAS_INLINE operator -=(difference_type n)301 const_iterator &operator -= (difference_type n) { 302 it_ -= n; 303 return *this; 304 } 305 BOOST_UBLAS_INLINE operator -(const const_iterator & it) const306 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 operator *() const313 const_reference operator * () const { 314 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); 315 return *it_; 316 } 317 BOOST_UBLAS_INLINE operator [](difference_type n) const318 const_reference operator [] (difference_type n) const { 319 return *(*this + n); 320 } 321 322 // Index 323 BOOST_UBLAS_INLINE index() const324 size_type index () const { 325 return it_.index () - (*this) ().start (); 326 } 327 328 // Assignment 329 BOOST_UBLAS_INLINE operator =(const const_iterator & it)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 operator ==(const const_iterator & it) const338 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 operator <(const const_iterator & it) const343 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 begin() const354 const_iterator begin () const { 355 return find (0); 356 } 357 BOOST_UBLAS_INLINE cbegin() const358 const_iterator cbegin () const { 359 return begin (); 360 } 361 BOOST_UBLAS_INLINE end() const362 const_iterator end () const { 363 return find (size ()); 364 } 365 BOOST_UBLAS_INLINE cend() const366 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 iterator()383 iterator (): 384 container_reference<self_type> (), it_ () {} 385 BOOST_UBLAS_INLINE iterator(self_type & vr,const subiterator_type & it)386 iterator (self_type &vr, const subiterator_type &it): 387 container_reference<self_type> (vr), it_ (it) {} 388 389 // Arithmetic 390 BOOST_UBLAS_INLINE operator ++()391 iterator &operator ++ () { 392 ++ it_; 393 return *this; 394 } 395 BOOST_UBLAS_INLINE operator --()396 iterator &operator -- () { 397 -- it_; 398 return *this; 399 } 400 BOOST_UBLAS_INLINE operator +=(difference_type n)401 iterator &operator += (difference_type n) { 402 it_ += n; 403 return *this; 404 } 405 BOOST_UBLAS_INLINE operator -=(difference_type n)406 iterator &operator -= (difference_type n) { 407 it_ -= n; 408 return *this; 409 } 410 BOOST_UBLAS_INLINE operator -(const iterator & it) const411 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 operator *() const418 reference operator * () const { 419 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); 420 return *it_; 421 } 422 BOOST_UBLAS_INLINE operator [](difference_type n) const423 reference operator [] (difference_type n) const { 424 return *(*this + n); 425 } 426 427 // Index 428 BOOST_UBLAS_INLINE index() const429 size_type index () const { 430 return it_.index () - (*this) ().start (); 431 } 432 433 // Assignment 434 BOOST_UBLAS_INLINE operator =(const iterator & it)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 operator ==(const iterator & it) const443 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 operator <(const iterator & it) const448 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 begin()461 iterator begin () { 462 return find (0); 463 } 464 BOOST_UBLAS_INLINE end()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 rbegin() const474 const_reverse_iterator rbegin () const { 475 return const_reverse_iterator (end ()); 476 } 477 BOOST_UBLAS_INLINE crbegin() const478 const_reverse_iterator crbegin () const { 479 return rbegin (); 480 } 481 BOOST_UBLAS_INLINE rend() const482 const_reverse_iterator rend () const { 483 return const_reverse_iterator (begin ()); 484 } 485 BOOST_UBLAS_INLINE crend() const486 const_reverse_iterator crend () const { 487 return rend (); 488 } 489 490 BOOST_UBLAS_INLINE rbegin()491 reverse_iterator rbegin () { 492 return reverse_iterator (end ()); 493 } 494 BOOST_UBLAS_INLINE rend()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 subrange(V & data,typename V::size_type start,typename V::size_type stop)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 subrange(const V & data,typename V::size_type start,typename V::size_type stop)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 project(V & data,typename vector_range<V>::range_type const & r)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 project(const V & data,typename vector_range<V>::range_type const & r)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 project(vector_range<V> & data,const typename vector_range<V>::range_type & r)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 project(const vector_range<V> & data,const typename vector_range<V>::range_type & r)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 vector_slice(vector_type & data,const slice_type & s)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 vector_slice(const vector_closure_type & data,const slice_type & s,int)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 start() const650 size_type start () const { 651 return s_.start (); 652 } 653 BOOST_UBLAS_INLINE stride() const654 difference_type stride () const { 655 return s_.stride (); 656 } 657 BOOST_UBLAS_INLINE size() const658 size_type size () const { 659 return s_.size (); 660 } 661 662 // Storage accessors 663 BOOST_UBLAS_INLINE data() const664 const vector_closure_type &data () const { 665 return data_; 666 } 667 BOOST_UBLAS_INLINE data()668 vector_closure_type &data () { 669 return data_; 670 } 671 672 // Element access 673 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 674 BOOST_UBLAS_INLINE operator ()(size_type i) const675 const_reference operator () (size_type i) const { 676 return data_ (s_ (i)); 677 } 678 BOOST_UBLAS_INLINE operator ()(size_type i)679 reference operator () (size_type i) { 680 return data_ (s_ (i)); 681 } 682 683 BOOST_UBLAS_INLINE operator [](size_type i) const684 const_reference operator [] (size_type i) const { 685 return (*this) (i); 686 } 687 BOOST_UBLAS_INLINE operator [](size_type i)688 reference operator [] (size_type i) { 689 return (*this) (i); 690 } 691 #else 692 BOOST_UBLAS_INLINE operator ()(size_type i) const693 reference operator () (size_type i) const { 694 return data_ (s_ (i)); 695 } 696 697 BOOST_UBLAS_INLINE operator [](size_type i) const698 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 project(const range_type & r) const707 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 project(const slice_type & s) const711 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 operator =(const vector_slice & vs)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 assign_temporary(vector_slice & vs)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 operator =(const vector_expression<AE> & ae)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 assign(const vector_expression<AE> & ae)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 operator +=(const vector_expression<AE> & ae)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 plus_assign(const vector_expression<AE> & ae)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 operator -=(const vector_expression<AE> & ae)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 minus_assign(const vector_expression<AE> & ae)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 operator *=(const AT & at)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 operator /=(const AT & at)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 same_closure(const vector_slice & vr) const779 bool same_closure (const vector_slice &vr) const { 780 return (*this).data_.same_closure (vr.data_); 781 } 782 783 // Comparison 784 BOOST_UBLAS_INLINE operator ==(const vector_slice & vs) const785 bool operator == (const vector_slice &vs) const { 786 return (*this).data_ == vs.data_ && s_ == vs.s_; 787 } 788 789 // Swapping 790 BOOST_UBLAS_INLINE swap(vector_slice vs)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 swap(vector_slice vs1,vector_slice vs2)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 find(size_type i) const823 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 find(size_type i)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 const_iterator()852 const_iterator (): 853 container_const_reference<self_type> (), it_ () {} 854 BOOST_UBLAS_INLINE const_iterator(const self_type & vs,const const_subiterator_type & it)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 const_iterator(const typename self_type::iterator & it)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 operator ++()863 const_iterator &operator ++ () { 864 ++ it_; 865 return *this; 866 } 867 BOOST_UBLAS_INLINE operator --()868 const_iterator &operator -- () { 869 -- it_; 870 return *this; 871 } 872 BOOST_UBLAS_INLINE operator +=(difference_type n)873 const_iterator &operator += (difference_type n) { 874 it_ += n; 875 return *this; 876 } 877 BOOST_UBLAS_INLINE operator -=(difference_type n)878 const_iterator &operator -= (difference_type n) { 879 it_ -= n; 880 return *this; 881 } 882 BOOST_UBLAS_INLINE operator -(const const_iterator & it) const883 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 operator *() const890 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 operator [](difference_type n) const896 const_reference operator [] (difference_type n) const { 897 return *(*this + n); 898 } 899 900 // Index 901 BOOST_UBLAS_INLINE index() const902 size_type index () const { 903 return it_.index (); 904 } 905 906 // Assignment 907 BOOST_UBLAS_INLINE operator =(const const_iterator & it)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 operator ==(const const_iterator & it) const916 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 operator <(const const_iterator & it) const921 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 begin() const932 const_iterator begin () const { 933 return find (0); 934 } 935 BOOST_UBLAS_INLINE cbegin() const936 const_iterator cbegin () const { 937 return begin (); 938 } 939 BOOST_UBLAS_INLINE end() const940 const_iterator end () const { 941 return find (size ()); 942 } 943 BOOST_UBLAS_INLINE cend() const944 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 iterator()961 iterator (): 962 container_reference<self_type> (), it_ () {} 963 BOOST_UBLAS_INLINE iterator(self_type & vs,const subiterator_type & it)964 iterator (self_type &vs, const subiterator_type &it): 965 container_reference<self_type> (vs), it_ (it) {} 966 967 // Arithmetic 968 BOOST_UBLAS_INLINE operator ++()969 iterator &operator ++ () { 970 ++ it_; 971 return *this; 972 } 973 BOOST_UBLAS_INLINE operator --()974 iterator &operator -- () { 975 -- it_; 976 return *this; 977 } 978 BOOST_UBLAS_INLINE operator +=(difference_type n)979 iterator &operator += (difference_type n) { 980 it_ += n; 981 return *this; 982 } 983 BOOST_UBLAS_INLINE operator -=(difference_type n)984 iterator &operator -= (difference_type n) { 985 it_ -= n; 986 return *this; 987 } 988 BOOST_UBLAS_INLINE operator -(const iterator & it) const989 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 operator *() const996 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 operator [](difference_type n) const1002 reference operator [] (difference_type n) const { 1003 return *(*this + n); 1004 } 1005 1006 1007 // Index 1008 BOOST_UBLAS_INLINE index() const1009 size_type index () const { 1010 return it_.index (); 1011 } 1012 1013 // Assignment 1014 BOOST_UBLAS_INLINE operator =(const iterator & it)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 operator ==(const iterator & it) const1023 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 operator <(const iterator & it) const1028 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 begin()1041 iterator begin () { 1042 return find (0); 1043 } 1044 BOOST_UBLAS_INLINE end()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 rbegin() const1054 const_reverse_iterator rbegin () const { 1055 return const_reverse_iterator (end ()); 1056 } 1057 BOOST_UBLAS_INLINE crbegin() const1058 const_reverse_iterator crbegin () const { 1059 return rbegin (); 1060 } 1061 BOOST_UBLAS_INLINE rend() const1062 const_reverse_iterator rend () const { 1063 return const_reverse_iterator (begin ()); 1064 } 1065 BOOST_UBLAS_INLINE crend() const1066 const_reverse_iterator crend () const { 1067 return rend (); 1068 } 1069 BOOST_UBLAS_INLINE rbegin()1070 reverse_iterator rbegin () { 1071 return reverse_iterator (end ()); 1072 } 1073 BOOST_UBLAS_INLINE rend()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 subslice(V & data,typename V::size_type start,typename V::difference_type stride,typename V::size_type size)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 subslice(const V & data,typename V::size_type start,typename V::difference_type stride,typename V::size_type size)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 project(V & data,const typename vector_slice<V>::slice_type & s)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 project(const V & data,const typename vector_slice<V>::slice_type & s)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 project(vector_slice<V> & data,const typename vector_slice<V>::slice_type & s)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 project(const vector_slice<V> & data,const typename vector_slice<V>::slice_type & s)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 project(vector_slice<V> & data,const typename vector_range<V>::range_type & r)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 project(const vector_slice<V> & data,const typename vector_range<V>::range_type & r)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 vector_indirect(vector_type & data,size_type size)1195 vector_indirect (vector_type &data, size_type size): 1196 data_ (data), ia_ (size) {} 1197 BOOST_UBLAS_INLINE vector_indirect(vector_type & data,const indirect_array_type & ia)1198 vector_indirect (vector_type &data, const indirect_array_type &ia): 1199 data_ (data), ia_ (ia.preprocess (data.size ())) {} 1200 BOOST_UBLAS_INLINE vector_indirect(const vector_closure_type & data,const indirect_array_type & ia,int)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 size() const1206 size_type size () const { 1207 return ia_.size (); 1208 } 1209 BOOST_UBLAS_INLINE indirect() const1210 const_indirect_array_type &indirect () const { 1211 return ia_; 1212 } 1213 BOOST_UBLAS_INLINE indirect()1214 indirect_array_type &indirect () { 1215 return ia_; 1216 } 1217 1218 // Storage accessors 1219 BOOST_UBLAS_INLINE data() const1220 const vector_closure_type &data () const { 1221 return data_; 1222 } 1223 BOOST_UBLAS_INLINE data()1224 vector_closure_type &data () { 1225 return data_; 1226 } 1227 1228 // Element access 1229 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 1230 BOOST_UBLAS_INLINE operator ()(size_type i) const1231 const_reference operator () (size_type i) const { 1232 return data_ (ia_ (i)); 1233 } 1234 BOOST_UBLAS_INLINE operator ()(size_type i)1235 reference operator () (size_type i) { 1236 return data_ (ia_ (i)); 1237 } 1238 1239 BOOST_UBLAS_INLINE operator [](size_type i) const1240 const_reference operator [] (size_type i) const { 1241 return (*this) (i); 1242 } 1243 BOOST_UBLAS_INLINE operator [](size_type i)1244 reference operator [] (size_type i) { 1245 return (*this) (i); 1246 } 1247 #else 1248 BOOST_UBLAS_INLINE operator ()(size_type i) const1249 reference operator () (size_type i) const { 1250 return data_ (ia_ (i)); 1251 } 1252 1253 BOOST_UBLAS_INLINE operator [](size_type i) const1254 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 project(const range_type & r) const1263 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 project(const slice_type & s) const1267 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 project(const indirect_array_type & ia) const1271 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 operator =(const vector_indirect & vi)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 assign_temporary(vector_indirect & vi)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 operator =(const vector_expression<AE> & ae)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 assign(const vector_expression<AE> & ae)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 operator +=(const vector_expression<AE> & ae)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 plus_assign(const vector_expression<AE> & ae)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 operator -=(const vector_expression<AE> & ae)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 minus_assign(const vector_expression<AE> & ae)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 operator *=(const AT & at)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 operator /=(const AT & at)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 same_closure(const vector_indirect &) const1339 bool same_closure (const vector_indirect &/*vr*/) const { 1340 return true; 1341 } 1342 1343 // Comparison 1344 BOOST_UBLAS_INLINE operator ==(const vector_indirect & vi) const1345 bool operator == (const vector_indirect &vi) const { 1346 return (*this).data_ == vi.data_ && ia_ == vi.ia_; 1347 } 1348 1349 // Swapping 1350 BOOST_UBLAS_INLINE swap(vector_indirect vi)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 swap(vector_indirect vi1,vector_indirect vi2)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 find(size_type i) const1382 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 find(size_type i)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 const_iterator()1413 const_iterator (): 1414 container_const_reference<self_type> (), it_ () {} 1415 BOOST_UBLAS_INLINE const_iterator(const self_type & vi,const const_subiterator_type & it)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 const_iterator(const typename self_type::iterator & it)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 operator ++()1424 const_iterator &operator ++ () { 1425 ++ it_; 1426 return *this; 1427 } 1428 BOOST_UBLAS_INLINE operator --()1429 const_iterator &operator -- () { 1430 -- it_; 1431 return *this; 1432 } 1433 BOOST_UBLAS_INLINE operator +=(difference_type n)1434 const_iterator &operator += (difference_type n) { 1435 it_ += n; 1436 return *this; 1437 } 1438 BOOST_UBLAS_INLINE operator -=(difference_type n)1439 const_iterator &operator -= (difference_type n) { 1440 it_ -= n; 1441 return *this; 1442 } 1443 BOOST_UBLAS_INLINE operator -(const const_iterator & it) const1444 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 operator *() const1451 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 operator [](difference_type n) const1457 const_reference operator [] (difference_type n) const { 1458 return *(*this + n); 1459 } 1460 1461 // Index 1462 BOOST_UBLAS_INLINE index() const1463 size_type index () const { 1464 return it_.index (); 1465 } 1466 1467 // Assignment 1468 BOOST_UBLAS_INLINE operator =(const const_iterator & it)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 operator ==(const const_iterator & it) const1477 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 operator <(const const_iterator & it) const1482 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 begin() const1493 const_iterator begin () const { 1494 return find (0); 1495 } 1496 BOOST_UBLAS_INLINE cbegin() const1497 const_iterator cbegin () const { 1498 return begin (); 1499 } 1500 BOOST_UBLAS_INLINE end() const1501 const_iterator end () const { 1502 return find (size ()); 1503 } 1504 BOOST_UBLAS_INLINE cend() const1505 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 iterator()1522 iterator (): 1523 container_reference<self_type> (), it_ () {} 1524 BOOST_UBLAS_INLINE iterator(self_type & vi,const subiterator_type & it)1525 iterator (self_type &vi, const subiterator_type &it): 1526 container_reference<self_type> (vi), it_ (it) {} 1527 1528 // Arithmetic 1529 BOOST_UBLAS_INLINE operator ++()1530 iterator &operator ++ () { 1531 ++ it_; 1532 return *this; 1533 } 1534 BOOST_UBLAS_INLINE operator --()1535 iterator &operator -- () { 1536 -- it_; 1537 return *this; 1538 } 1539 BOOST_UBLAS_INLINE operator +=(difference_type n)1540 iterator &operator += (difference_type n) { 1541 it_ += n; 1542 return *this; 1543 } 1544 BOOST_UBLAS_INLINE operator -=(difference_type n)1545 iterator &operator -= (difference_type n) { 1546 it_ -= n; 1547 return *this; 1548 } 1549 BOOST_UBLAS_INLINE operator -(const iterator & it) const1550 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 operator *() const1557 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 operator [](difference_type n) const1563 reference operator [] (difference_type n) const { 1564 return *(*this + n); 1565 } 1566 1567 // Index 1568 BOOST_UBLAS_INLINE index() const1569 size_type index () const { 1570 return it_.index (); 1571 } 1572 1573 // Assignment 1574 BOOST_UBLAS_INLINE operator =(const iterator & it)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 operator ==(const iterator & it) const1583 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 operator <(const iterator & it) const1588 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 begin()1601 iterator begin () { 1602 return find (0); 1603 } 1604 BOOST_UBLAS_INLINE end()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 rbegin() const1614 const_reverse_iterator rbegin () const { 1615 return const_reverse_iterator (end ()); 1616 } 1617 BOOST_UBLAS_INLINE crbegin() const1618 const_reverse_iterator crbegin () const { 1619 return rbegin (); 1620 } 1621 BOOST_UBLAS_INLINE rend() const1622 const_reverse_iterator rend () const { 1623 return const_reverse_iterator (begin ()); 1624 } 1625 BOOST_UBLAS_INLINE crend() const1626 const_reverse_iterator crend () const { 1627 return rend (); 1628 } 1629 1630 BOOST_UBLAS_INLINE rbegin()1631 reverse_iterator rbegin () { 1632 return reverse_iterator (end ()); 1633 } 1634 BOOST_UBLAS_INLINE rend()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 project(V & data,const indirect_array<A> & ia)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 project(const V & data,const indirect_array<A> & ia)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 project(vector_indirect<V,IA> & data,const typename vector_indirect<V,IA>::range_type & r)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 project(const vector_indirect<V,IA> & data,const typename vector_indirect<V,IA>::range_type & r)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 project(vector_indirect<V,IA> & data,const typename vector_indirect<V,IA>::slice_type & s)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 project(const vector_indirect<V,IA> & data,const typename vector_indirect<V,IA>::slice_type & s)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 project(vector_indirect<V,indirect_array<A>> & data,const indirect_array<A> & ia)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 project(const vector_indirect<V,indirect_array<A>> & data,const indirect_array<A> & ia)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