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_MATRIX_PROXY_ 14 #define _BOOST_UBLAS_MATRIX_PROXY_ 15 16 #include <boost/numeric/ublas/matrix_expression.hpp> 17 #include <boost/numeric/ublas/detail/vector_assign.hpp> 18 #include <boost/numeric/ublas/detail/matrix_assign.hpp> 19 #include <boost/numeric/ublas/detail/temporary.hpp> 20 21 // Iterators based on ideas of Jeremy Siek 22 23 namespace boost { namespace numeric { namespace ublas { 24 25 /** \brief 26 */ 27 template<class M> 28 class matrix_row: 29 public vector_expression<matrix_row<M> > { 30 31 typedef matrix_row<M> self_type; 32 public: 33 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 34 using vector_expression<self_type>::operator (); 35 #endif 36 typedef M matrix_type; 37 typedef typename M::size_type size_type; 38 typedef typename M::difference_type difference_type; 39 typedef typename M::value_type value_type; 40 typedef typename M::const_reference const_reference; 41 typedef typename boost::mpl::if_<boost::is_const<M>, 42 typename M::const_reference, 43 typename M::reference>::type reference; 44 typedef typename boost::mpl::if_<boost::is_const<M>, 45 typename M::const_closure_type, 46 typename M::closure_type>::type matrix_closure_type; 47 typedef const self_type const_closure_type; 48 typedef self_type closure_type; 49 typedef typename storage_restrict_traits<typename M::storage_category, 50 dense_proxy_tag>::storage_category storage_category; 51 52 // Construction and destruction 53 BOOST_UBLAS_INLINE matrix_row(matrix_type & data,size_type i)54 matrix_row (matrix_type &data, size_type i): 55 data_ (data), i_ (i) { 56 // Early checking of preconditions here. 57 // BOOST_UBLAS_CHECK (i_ < data_.size1 (), bad_index ()); 58 } 59 60 // Accessors 61 BOOST_UBLAS_INLINE size() const62 size_type size () const { 63 return data_.size2 (); 64 } 65 BOOST_UBLAS_INLINE index() const66 size_type index () const { 67 return i_; 68 } 69 70 // Storage accessors 71 BOOST_UBLAS_INLINE data() const72 const matrix_closure_type &data () const { 73 return data_; 74 } 75 BOOST_UBLAS_INLINE data()76 matrix_closure_type &data () { 77 return data_; 78 } 79 80 // Element access 81 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 82 BOOST_UBLAS_INLINE operator ()(size_type j) const83 const_reference operator () (size_type j) const { 84 return data_ (i_, j); 85 } 86 BOOST_UBLAS_INLINE operator ()(size_type j)87 reference operator () (size_type j) { 88 return data_ (i_, j); 89 } 90 91 BOOST_UBLAS_INLINE operator [](size_type j) const92 const_reference operator [] (size_type j) const { 93 return (*this) (j); 94 } 95 BOOST_UBLAS_INLINE operator [](size_type j)96 reference operator [] (size_type j) { 97 return (*this) (j); 98 } 99 #else 100 BOOST_UBLAS_INLINE operator ()(size_type j) const101 reference operator () (size_type j) const { 102 return data_ (i_, j); 103 } 104 105 BOOST_UBLAS_INLINE operator [](size_type j) const106 reference operator [] (size_type j) const { 107 return (*this) (j); 108 } 109 #endif 110 111 // Assignment 112 BOOST_UBLAS_INLINE operator =(const matrix_row & mr)113 matrix_row &operator = (const matrix_row &mr) { 114 // ISSUE need a temporary, proxy can be overlaping alias 115 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mr)); 116 return *this; 117 } 118 BOOST_UBLAS_INLINE assign_temporary(matrix_row & mr)119 matrix_row &assign_temporary (matrix_row &mr) { 120 // assign elements, proxied container remains the same 121 vector_assign<scalar_assign> (*this, mr); 122 return *this; 123 } 124 template<class AE> 125 BOOST_UBLAS_INLINE operator =(const vector_expression<AE> & ae)126 matrix_row &operator = (const vector_expression<AE> &ae) { 127 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae)); 128 return *this; 129 } 130 template<class AE> 131 BOOST_UBLAS_INLINE assign(const vector_expression<AE> & ae)132 matrix_row &assign (const vector_expression<AE> &ae) { 133 vector_assign<scalar_assign> (*this, ae); 134 return *this; 135 } 136 template<class AE> 137 BOOST_UBLAS_INLINE operator +=(const vector_expression<AE> & ae)138 matrix_row &operator += (const vector_expression<AE> &ae) { 139 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae)); 140 return *this; 141 } 142 template<class AE> 143 BOOST_UBLAS_INLINE plus_assign(const vector_expression<AE> & ae)144 matrix_row &plus_assign (const vector_expression<AE> &ae) { 145 vector_assign<scalar_plus_assign> (*this, ae); 146 return *this; 147 } 148 template<class AE> 149 BOOST_UBLAS_INLINE operator -=(const vector_expression<AE> & ae)150 matrix_row &operator -= (const vector_expression<AE> &ae) { 151 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae)); 152 return *this; 153 } 154 template<class AE> 155 BOOST_UBLAS_INLINE minus_assign(const vector_expression<AE> & ae)156 matrix_row &minus_assign (const vector_expression<AE> &ae) { 157 vector_assign<scalar_minus_assign> (*this, ae); 158 return *this; 159 } 160 template<class AT> 161 BOOST_UBLAS_INLINE operator *=(const AT & at)162 matrix_row &operator *= (const AT &at) { 163 vector_assign_scalar<scalar_multiplies_assign> (*this, at); 164 return *this; 165 } 166 template<class AT> 167 BOOST_UBLAS_INLINE operator /=(const AT & at)168 matrix_row &operator /= (const AT &at) { 169 vector_assign_scalar<scalar_divides_assign> (*this, at); 170 return *this; 171 } 172 173 // Closure comparison 174 BOOST_UBLAS_INLINE same_closure(const matrix_row & mr) const175 bool same_closure (const matrix_row &mr) const { 176 return (*this).data_.same_closure (mr.data_); 177 } 178 179 // Comparison 180 BOOST_UBLAS_INLINE operator ==(const matrix_row & mr) const181 bool operator == (const matrix_row &mr) const { 182 return (*this).data_ == mr.data_ && index () == mr.index (); 183 } 184 185 // Swapping 186 BOOST_UBLAS_INLINE swap(matrix_row mr)187 void swap (matrix_row mr) { 188 if (this != &mr) { 189 BOOST_UBLAS_CHECK (size () == mr.size (), bad_size ()); 190 // Sparse ranges may be nonconformant now. 191 // std::swap_ranges (begin (), end (), mr.begin ()); 192 vector_swap<scalar_swap> (*this, mr); 193 } 194 } 195 BOOST_UBLAS_INLINE swap(matrix_row mr1,matrix_row mr2)196 friend void swap (matrix_row mr1, matrix_row mr2) { 197 mr1.swap (mr2); 198 } 199 200 // Iterator types 201 private: 202 typedef typename M::const_iterator2 const_subiterator_type; 203 typedef typename boost::mpl::if_<boost::is_const<M>, 204 typename M::const_iterator2, 205 typename M::iterator2>::type subiterator_type; 206 207 public: 208 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 209 typedef indexed_iterator<matrix_row<matrix_type>, 210 typename subiterator_type::iterator_category> iterator; 211 typedef indexed_const_iterator<matrix_row<matrix_type>, 212 typename const_subiterator_type::iterator_category> const_iterator; 213 #else 214 class const_iterator; 215 class iterator; 216 #endif 217 218 // Element lookup 219 BOOST_UBLAS_INLINE find(size_type j) const220 const_iterator find (size_type j) const { 221 const_subiterator_type it2 (data_.find2 (1, i_, j)); 222 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 223 return const_iterator (*this, it2.index2 ()); 224 #else 225 return const_iterator (*this, it2); 226 #endif 227 } 228 BOOST_UBLAS_INLINE find(size_type j)229 iterator find (size_type j) { 230 subiterator_type it2 (data_.find2 (1, i_, j)); 231 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 232 return iterator (*this, it2.index2 ()); 233 #else 234 return iterator (*this, it2); 235 #endif 236 } 237 238 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 239 class const_iterator: 240 public container_const_reference<matrix_row>, 241 public iterator_base_traits<typename const_subiterator_type::iterator_category>::template 242 iterator_base<const_iterator, value_type>::type { 243 public: 244 typedef typename const_subiterator_type::value_type value_type; 245 typedef typename const_subiterator_type::difference_type difference_type; 246 typedef typename const_subiterator_type::reference reference; 247 typedef typename const_subiterator_type::pointer pointer; 248 249 // Construction and destruction 250 BOOST_UBLAS_INLINE const_iterator()251 const_iterator (): 252 container_const_reference<self_type> (), it_ () {} 253 BOOST_UBLAS_INLINE const_iterator(const self_type & mr,const const_subiterator_type & it)254 const_iterator (const self_type &mr, const const_subiterator_type &it): 255 container_const_reference<self_type> (mr), it_ (it) {} 256 BOOST_UBLAS_INLINE const_iterator(const typename self_type::iterator & it)257 const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here 258 container_const_reference<self_type> (it ()), it_ (it.it_) {} 259 260 // Arithmetic 261 BOOST_UBLAS_INLINE operator ++()262 const_iterator &operator ++ () { 263 ++ it_; 264 return *this; 265 } 266 BOOST_UBLAS_INLINE operator --()267 const_iterator &operator -- () { 268 -- it_; 269 return *this; 270 } 271 BOOST_UBLAS_INLINE operator +=(difference_type n)272 const_iterator &operator += (difference_type n) { 273 it_ += n; 274 return *this; 275 } 276 BOOST_UBLAS_INLINE operator -=(difference_type n)277 const_iterator &operator -= (difference_type n) { 278 it_ -= n; 279 return *this; 280 } 281 BOOST_UBLAS_INLINE operator -(const const_iterator & it) const282 difference_type operator - (const const_iterator &it) const { 283 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 284 return it_ - it.it_; 285 } 286 287 // Dereference 288 BOOST_UBLAS_INLINE operator *() const289 const_reference operator * () const { 290 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); 291 return *it_; 292 } 293 BOOST_UBLAS_INLINE operator [](difference_type n) const294 const_reference operator [] (difference_type n) const { 295 return *(*this + n); 296 } 297 298 // Index 299 BOOST_UBLAS_INLINE index() const300 size_type index () const { 301 return it_.index2 (); 302 } 303 304 // Assignment 305 BOOST_UBLAS_INLINE operator =(const const_iterator & it)306 const_iterator &operator = (const const_iterator &it) { 307 container_const_reference<self_type>::assign (&it ()); 308 it_ = it.it_; 309 return *this; 310 } 311 312 // Comparison 313 BOOST_UBLAS_INLINE operator ==(const const_iterator & it) const314 bool operator == (const const_iterator &it) const { 315 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 316 return it_ == it.it_; 317 } 318 BOOST_UBLAS_INLINE operator <(const const_iterator & it) const319 bool operator < (const const_iterator &it) const { 320 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 321 return it_ < it.it_; 322 } 323 324 private: 325 const_subiterator_type it_; 326 }; 327 #endif 328 329 BOOST_UBLAS_INLINE begin() const330 const_iterator begin () const { 331 return find (0); 332 } 333 BOOST_UBLAS_INLINE cbegin() const334 const_iterator cbegin () const { 335 return begin (); 336 } 337 BOOST_UBLAS_INLINE end() const338 const_iterator end () const { 339 return find (size ()); 340 } 341 BOOST_UBLAS_INLINE cend() const342 const_iterator cend () const { 343 return end (); 344 } 345 346 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 347 class iterator: 348 public container_reference<matrix_row>, 349 public iterator_base_traits<typename subiterator_type::iterator_category>::template 350 iterator_base<iterator, value_type>::type { 351 public: 352 typedef typename subiterator_type::value_type value_type; 353 typedef typename subiterator_type::difference_type difference_type; 354 typedef typename subiterator_type::reference reference; 355 typedef typename subiterator_type::pointer pointer; 356 357 // Construction and destruction 358 BOOST_UBLAS_INLINE iterator()359 iterator (): 360 container_reference<self_type> (), it_ () {} 361 BOOST_UBLAS_INLINE iterator(self_type & mr,const subiterator_type & it)362 iterator (self_type &mr, const subiterator_type &it): 363 container_reference<self_type> (mr), it_ (it) {} 364 365 // Arithmetic 366 BOOST_UBLAS_INLINE operator ++()367 iterator &operator ++ () { 368 ++ it_; 369 return *this; 370 } 371 BOOST_UBLAS_INLINE operator --()372 iterator &operator -- () { 373 -- it_; 374 return *this; 375 } 376 BOOST_UBLAS_INLINE operator +=(difference_type n)377 iterator &operator += (difference_type n) { 378 it_ += n; 379 return *this; 380 } 381 BOOST_UBLAS_INLINE operator -=(difference_type n)382 iterator &operator -= (difference_type n) { 383 it_ -= n; 384 return *this; 385 } 386 BOOST_UBLAS_INLINE operator -(const iterator & it) const387 difference_type operator - (const iterator &it) const { 388 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 389 return it_ - it.it_; 390 } 391 392 // Dereference 393 BOOST_UBLAS_INLINE operator *() const394 reference operator * () const { 395 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); 396 return *it_; 397 } 398 BOOST_UBLAS_INLINE operator [](difference_type n) const399 reference operator [] (difference_type n) const { 400 return *(*this + n); 401 } 402 403 // Index 404 BOOST_UBLAS_INLINE index() const405 size_type index () const { 406 return it_.index2 (); 407 } 408 409 // Assignment 410 BOOST_UBLAS_INLINE operator =(const iterator & it)411 iterator &operator = (const iterator &it) { 412 container_reference<self_type>::assign (&it ()); 413 it_ = it.it_; 414 return *this; 415 } 416 417 // Comparison 418 BOOST_UBLAS_INLINE operator ==(const iterator & it) const419 bool operator == (const iterator &it) const { 420 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 421 return it_ == it.it_; 422 } 423 BOOST_UBLAS_INLINE operator <(const iterator & it) const424 bool operator < (const iterator &it) const { 425 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 426 return it_ < it.it_; 427 } 428 429 private: 430 subiterator_type it_; 431 432 friend class const_iterator; 433 }; 434 #endif 435 436 BOOST_UBLAS_INLINE begin()437 iterator begin () { 438 return find (0); 439 } 440 BOOST_UBLAS_INLINE end()441 iterator end () { 442 return find (size ()); 443 } 444 445 // Reverse iterator 446 typedef reverse_iterator_base<const_iterator> const_reverse_iterator; 447 typedef reverse_iterator_base<iterator> reverse_iterator; 448 449 BOOST_UBLAS_INLINE rbegin() const450 const_reverse_iterator rbegin () const { 451 return const_reverse_iterator (end ()); 452 } 453 BOOST_UBLAS_INLINE crbegin() const454 const_reverse_iterator crbegin () const { 455 return rbegin (); 456 } 457 BOOST_UBLAS_INLINE rend() const458 const_reverse_iterator rend () const { 459 return const_reverse_iterator (begin ()); 460 } 461 BOOST_UBLAS_INLINE crend() const462 const_reverse_iterator crend () const { 463 return rend (); 464 } 465 BOOST_UBLAS_INLINE rbegin()466 reverse_iterator rbegin () { 467 return reverse_iterator (end ()); 468 } 469 BOOST_UBLAS_INLINE rend()470 reverse_iterator rend () { 471 return reverse_iterator (begin ()); 472 } 473 474 private: 475 matrix_closure_type data_; 476 size_type i_; 477 }; 478 479 // Projections 480 template<class M> 481 BOOST_UBLAS_INLINE row(M & data,typename M::size_type i)482 matrix_row<M> row (M &data, typename M::size_type i) { 483 return matrix_row<M> (data, i); 484 } 485 template<class M> 486 BOOST_UBLAS_INLINE row(const M & data,typename M::size_type i)487 const matrix_row<const M> row (const M &data, typename M::size_type i) { 488 return matrix_row<const M> (data, i); 489 } 490 491 // Specialize temporary 492 template <class M> 493 struct vector_temporary_traits< matrix_row<M> > 494 : vector_temporary_traits< M > {} ; 495 template <class M> 496 struct vector_temporary_traits< const matrix_row<M> > 497 : vector_temporary_traits< M > {} ; 498 499 // Matrix based column vector class 500 template<class M> 501 class matrix_column: 502 public vector_expression<matrix_column<M> > { 503 504 typedef matrix_column<M> self_type; 505 public: 506 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 507 using vector_expression<self_type>::operator (); 508 #endif 509 typedef M matrix_type; 510 typedef typename M::size_type size_type; 511 typedef typename M::difference_type difference_type; 512 typedef typename M::value_type value_type; 513 typedef typename M::const_reference const_reference; 514 typedef typename boost::mpl::if_<boost::is_const<M>, 515 typename M::const_reference, 516 typename M::reference>::type reference; 517 typedef typename boost::mpl::if_<boost::is_const<M>, 518 typename M::const_closure_type, 519 typename M::closure_type>::type matrix_closure_type; 520 typedef const self_type const_closure_type; 521 typedef self_type closure_type; 522 typedef typename storage_restrict_traits<typename M::storage_category, 523 dense_proxy_tag>::storage_category storage_category; 524 525 // Construction and destruction 526 BOOST_UBLAS_INLINE matrix_column(matrix_type & data,size_type j)527 matrix_column (matrix_type &data, size_type j): 528 data_ (data), j_ (j) { 529 // Early checking of preconditions here. 530 // BOOST_UBLAS_CHECK (j_ < data_.size2 (), bad_index ()); 531 } 532 533 // Accessors 534 BOOST_UBLAS_INLINE size() const535 size_type size () const { 536 return data_.size1 (); 537 } 538 BOOST_UBLAS_INLINE index() const539 size_type index () const { 540 return j_; 541 } 542 543 // Storage accessors 544 BOOST_UBLAS_INLINE data() const545 const matrix_closure_type &data () const { 546 return data_; 547 } 548 BOOST_UBLAS_INLINE data()549 matrix_closure_type &data () { 550 return data_; 551 } 552 553 // Element access 554 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 555 BOOST_UBLAS_INLINE operator ()(size_type i) const556 const_reference operator () (size_type i) const { 557 return data_ (i, j_); 558 } 559 BOOST_UBLAS_INLINE operator ()(size_type i)560 reference operator () (size_type i) { 561 return data_ (i, j_); 562 } 563 564 BOOST_UBLAS_INLINE operator [](size_type i) const565 const_reference operator [] (size_type i) const { 566 return (*this) (i); 567 } 568 BOOST_UBLAS_INLINE operator [](size_type i)569 reference operator [] (size_type i) { 570 return (*this) (i); 571 } 572 #else 573 BOOST_UBLAS_INLINE operator ()(size_type i) const574 reference operator () (size_type i) const { 575 return data_ (i, j_); 576 } 577 578 BOOST_UBLAS_INLINE operator [](size_type i) const579 reference operator [] (size_type i) const { 580 return (*this) (i); 581 } 582 #endif 583 584 // Assignment 585 BOOST_UBLAS_INLINE operator =(const matrix_column & mc)586 matrix_column &operator = (const matrix_column &mc) { 587 // ISSUE need a temporary, proxy can be overlaping alias 588 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mc)); 589 return *this; 590 } 591 BOOST_UBLAS_INLINE assign_temporary(matrix_column & mc)592 matrix_column &assign_temporary (matrix_column &mc) { 593 // assign elements, proxied container remains the same 594 vector_assign<scalar_assign> (*this, mc); 595 return *this; 596 } 597 template<class AE> 598 BOOST_UBLAS_INLINE operator =(const vector_expression<AE> & ae)599 matrix_column &operator = (const vector_expression<AE> &ae) { 600 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae)); 601 return *this; 602 } 603 template<class AE> 604 BOOST_UBLAS_INLINE assign(const vector_expression<AE> & ae)605 matrix_column &assign (const vector_expression<AE> &ae) { 606 vector_assign<scalar_assign> (*this, ae); 607 return *this; 608 } 609 template<class AE> 610 BOOST_UBLAS_INLINE operator +=(const vector_expression<AE> & ae)611 matrix_column &operator += (const vector_expression<AE> &ae) { 612 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae)); 613 return *this; 614 } 615 template<class AE> 616 BOOST_UBLAS_INLINE plus_assign(const vector_expression<AE> & ae)617 matrix_column &plus_assign (const vector_expression<AE> &ae) { 618 vector_assign<scalar_plus_assign> (*this, ae); 619 return *this; 620 } 621 template<class AE> 622 BOOST_UBLAS_INLINE operator -=(const vector_expression<AE> & ae)623 matrix_column &operator -= (const vector_expression<AE> &ae) { 624 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae)); 625 return *this; 626 } 627 template<class AE> 628 BOOST_UBLAS_INLINE minus_assign(const vector_expression<AE> & ae)629 matrix_column &minus_assign (const vector_expression<AE> &ae) { 630 vector_assign<scalar_minus_assign> (*this, ae); 631 return *this; 632 } 633 template<class AT> 634 BOOST_UBLAS_INLINE operator *=(const AT & at)635 matrix_column &operator *= (const AT &at) { 636 vector_assign_scalar<scalar_multiplies_assign> (*this, at); 637 return *this; 638 } 639 template<class AT> 640 BOOST_UBLAS_INLINE operator /=(const AT & at)641 matrix_column &operator /= (const AT &at) { 642 vector_assign_scalar<scalar_divides_assign> (*this, at); 643 return *this; 644 } 645 646 // Closure comparison 647 BOOST_UBLAS_INLINE same_closure(const matrix_column & mc) const648 bool same_closure (const matrix_column &mc) const { 649 return (*this).data_.same_closure (mc.data_); 650 } 651 652 // Comparison 653 BOOST_UBLAS_INLINE operator ==(const matrix_column & mc) const654 bool operator == (const matrix_column &mc) const { 655 return (*this).data_ == mc.data_ && index () == mc.index (); 656 } 657 658 // Swapping 659 BOOST_UBLAS_INLINE swap(matrix_column mc)660 void swap (matrix_column mc) { 661 if (this != &mc) { 662 BOOST_UBLAS_CHECK (size () == mc.size (), bad_size ()); 663 // Sparse ranges may be nonconformant now. 664 // std::swap_ranges (begin (), end (), mc.begin ()); 665 vector_swap<scalar_swap> (*this, mc); 666 } 667 } 668 BOOST_UBLAS_INLINE swap(matrix_column mc1,matrix_column mc2)669 friend void swap (matrix_column mc1, matrix_column mc2) { 670 mc1.swap (mc2); 671 } 672 673 // Iterator types 674 private: 675 typedef typename M::const_iterator1 const_subiterator_type; 676 typedef typename boost::mpl::if_<boost::is_const<M>, 677 typename M::const_iterator1, 678 typename M::iterator1>::type subiterator_type; 679 680 public: 681 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 682 typedef indexed_iterator<matrix_column<matrix_type>, 683 typename subiterator_type::iterator_category> iterator; 684 typedef indexed_const_iterator<matrix_column<matrix_type>, 685 typename const_subiterator_type::iterator_category> const_iterator; 686 #else 687 class const_iterator; 688 class iterator; 689 #endif 690 691 // Element lookup 692 BOOST_UBLAS_INLINE find(size_type i) const693 const_iterator find (size_type i) const { 694 const_subiterator_type it1 (data_.find1 (1, i, j_)); 695 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 696 return const_iterator (*this, it1.index1 ()); 697 #else 698 return const_iterator (*this, it1); 699 #endif 700 } 701 BOOST_UBLAS_INLINE find(size_type i)702 iterator find (size_type i) { 703 subiterator_type it1 (data_.find1 (1, i, j_)); 704 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 705 return iterator (*this, it1.index1 ()); 706 #else 707 return iterator (*this, it1); 708 #endif 709 } 710 711 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 712 class const_iterator: 713 public container_const_reference<matrix_column>, 714 public iterator_base_traits<typename const_subiterator_type::iterator_category>::template 715 iterator_base<const_iterator, value_type>::type { 716 public: 717 typedef typename const_subiterator_type::value_type value_type; 718 typedef typename const_subiterator_type::difference_type difference_type; 719 typedef typename const_subiterator_type::reference reference; 720 typedef typename const_subiterator_type::pointer pointer; 721 722 // Construction and destruction 723 BOOST_UBLAS_INLINE const_iterator()724 const_iterator (): 725 container_const_reference<self_type> (), it_ () {} 726 BOOST_UBLAS_INLINE const_iterator(const self_type & mc,const const_subiterator_type & it)727 const_iterator (const self_type &mc, const const_subiterator_type &it): 728 container_const_reference<self_type> (mc), it_ (it) {} 729 BOOST_UBLAS_INLINE const_iterator(const typename self_type::iterator & it)730 const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here 731 container_const_reference<self_type> (it ()), it_ (it.it_) {} 732 733 // Arithmetic 734 BOOST_UBLAS_INLINE operator ++()735 const_iterator &operator ++ () { 736 ++ it_; 737 return *this; 738 } 739 BOOST_UBLAS_INLINE operator --()740 const_iterator &operator -- () { 741 -- it_; 742 return *this; 743 } 744 BOOST_UBLAS_INLINE operator +=(difference_type n)745 const_iterator &operator += (difference_type n) { 746 it_ += n; 747 return *this; 748 } 749 BOOST_UBLAS_INLINE operator -=(difference_type n)750 const_iterator &operator -= (difference_type n) { 751 it_ -= n; 752 return *this; 753 } 754 BOOST_UBLAS_INLINE operator -(const const_iterator & it) const755 difference_type operator - (const const_iterator &it) const { 756 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 757 return it_ - it.it_; 758 } 759 760 // Dereference 761 BOOST_UBLAS_INLINE operator *() const762 const_reference operator * () const { 763 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); 764 return *it_; 765 } 766 BOOST_UBLAS_INLINE operator [](difference_type n) const767 const_reference operator [] (difference_type n) const { 768 return *(*this + n); 769 } 770 771 // Index 772 BOOST_UBLAS_INLINE index() const773 size_type index () const { 774 return it_.index1 (); 775 } 776 777 // Assignment 778 BOOST_UBLAS_INLINE operator =(const const_iterator & it)779 const_iterator &operator = (const const_iterator &it) { 780 container_const_reference<self_type>::assign (&it ()); 781 it_ = it.it_; 782 return *this; 783 } 784 785 // Comparison 786 BOOST_UBLAS_INLINE operator ==(const const_iterator & it) const787 bool operator == (const const_iterator &it) const { 788 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 789 return it_ == it.it_; 790 } 791 BOOST_UBLAS_INLINE operator <(const const_iterator & it) const792 bool operator < (const const_iterator &it) const { 793 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 794 return it_ < it.it_; 795 } 796 797 private: 798 const_subiterator_type it_; 799 }; 800 #endif 801 802 BOOST_UBLAS_INLINE begin() const803 const_iterator begin () const { 804 return find (0); 805 } 806 BOOST_UBLAS_INLINE cbegin() const807 const_iterator cbegin () const { 808 return begin (); 809 } 810 BOOST_UBLAS_INLINE end() const811 const_iterator end () const { 812 return find (size ()); 813 } 814 BOOST_UBLAS_INLINE cend() const815 const_iterator cend () const { 816 return end (); 817 } 818 819 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 820 class iterator: 821 public container_reference<matrix_column>, 822 public iterator_base_traits<typename subiterator_type::iterator_category>::template 823 iterator_base<iterator, value_type>::type { 824 public: 825 typedef typename subiterator_type::value_type value_type; 826 typedef typename subiterator_type::difference_type difference_type; 827 typedef typename subiterator_type::reference reference; 828 typedef typename subiterator_type::pointer pointer; 829 830 // Construction and destruction 831 BOOST_UBLAS_INLINE iterator()832 iterator (): 833 container_reference<self_type> (), it_ () {} 834 BOOST_UBLAS_INLINE iterator(self_type & mc,const subiterator_type & it)835 iterator (self_type &mc, const subiterator_type &it): 836 container_reference<self_type> (mc), it_ (it) {} 837 838 // Arithmetic 839 BOOST_UBLAS_INLINE operator ++()840 iterator &operator ++ () { 841 ++ it_; 842 return *this; 843 } 844 BOOST_UBLAS_INLINE operator --()845 iterator &operator -- () { 846 -- it_; 847 return *this; 848 } 849 BOOST_UBLAS_INLINE operator +=(difference_type n)850 iterator &operator += (difference_type n) { 851 it_ += n; 852 return *this; 853 } 854 BOOST_UBLAS_INLINE operator -=(difference_type n)855 iterator &operator -= (difference_type n) { 856 it_ -= n; 857 return *this; 858 } 859 BOOST_UBLAS_INLINE operator -(const iterator & it) const860 difference_type operator - (const iterator &it) const { 861 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 862 return it_ - it.it_; 863 } 864 865 // Dereference 866 BOOST_UBLAS_INLINE operator *() const867 reference operator * () const { 868 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ()); 869 return *it_; 870 } 871 BOOST_UBLAS_INLINE operator [](difference_type n) const872 reference operator [] (difference_type n) const { 873 return *(*this + n); 874 } 875 876 // Index 877 BOOST_UBLAS_INLINE index() const878 size_type index () const { 879 return it_.index1 (); 880 } 881 882 // Assignment 883 BOOST_UBLAS_INLINE operator =(const iterator & it)884 iterator &operator = (const iterator &it) { 885 container_reference<self_type>::assign (&it ()); 886 it_ = it.it_; 887 return *this; 888 } 889 890 // Comparison 891 BOOST_UBLAS_INLINE operator ==(const iterator & it) const892 bool operator == (const iterator &it) const { 893 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 894 return it_ == it.it_; 895 } 896 BOOST_UBLAS_INLINE operator <(const iterator & it) const897 bool operator < (const iterator &it) const { 898 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 899 return it_ < it.it_; 900 } 901 902 private: 903 subiterator_type it_; 904 905 friend class const_iterator; 906 }; 907 #endif 908 909 BOOST_UBLAS_INLINE begin()910 iterator begin () { 911 return find (0); 912 } 913 BOOST_UBLAS_INLINE end()914 iterator end () { 915 return find (size ()); 916 } 917 918 // Reverse iterator 919 typedef reverse_iterator_base<const_iterator> const_reverse_iterator; 920 typedef reverse_iterator_base<iterator> reverse_iterator; 921 922 BOOST_UBLAS_INLINE rbegin() const923 const_reverse_iterator rbegin () const { 924 return const_reverse_iterator (end ()); 925 } 926 BOOST_UBLAS_INLINE crbegin() const927 const_reverse_iterator crbegin () const { 928 return rbegin (); 929 } 930 BOOST_UBLAS_INLINE rend() const931 const_reverse_iterator rend () const { 932 return const_reverse_iterator (begin ()); 933 } 934 BOOST_UBLAS_INLINE crend() const935 const_reverse_iterator crend () const { 936 return rend (); 937 } rbegin()938 reverse_iterator rbegin () { 939 return reverse_iterator (end ()); 940 } 941 BOOST_UBLAS_INLINE rend()942 reverse_iterator rend () { 943 return reverse_iterator (begin ()); 944 } 945 946 private: 947 matrix_closure_type data_; 948 size_type j_; 949 }; 950 951 // Projections 952 template<class M> 953 BOOST_UBLAS_INLINE column(M & data,typename M::size_type j)954 matrix_column<M> column (M &data, typename M::size_type j) { 955 return matrix_column<M> (data, j); 956 } 957 template<class M> 958 BOOST_UBLAS_INLINE column(const M & data,typename M::size_type j)959 const matrix_column<const M> column (const M &data, typename M::size_type j) { 960 return matrix_column<const M> (data, j); 961 } 962 963 // Specialize temporary 964 template <class M> 965 struct vector_temporary_traits< matrix_column<M> > 966 : vector_temporary_traits< M > {} ; 967 template <class M> 968 struct vector_temporary_traits< const matrix_column<M> > 969 : vector_temporary_traits< M > {} ; 970 971 // Matrix based vector range class 972 template<class M> 973 class matrix_vector_range: 974 public vector_expression<matrix_vector_range<M> > { 975 976 typedef matrix_vector_range<M> self_type; 977 public: 978 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 979 using vector_expression<self_type>::operator (); 980 #endif 981 typedef M matrix_type; 982 typedef typename M::size_type size_type; 983 typedef typename M::difference_type difference_type; 984 typedef typename M::value_type value_type; 985 typedef typename M::const_reference const_reference; 986 typedef typename boost::mpl::if_<boost::is_const<M>, 987 typename M::const_reference, 988 typename M::reference>::type reference; 989 typedef typename boost::mpl::if_<boost::is_const<M>, 990 typename M::const_closure_type, 991 typename M::closure_type>::type matrix_closure_type; 992 typedef basic_range<size_type, difference_type> range_type; 993 typedef const self_type const_closure_type; 994 typedef self_type closure_type; 995 typedef typename storage_restrict_traits<typename M::storage_category, 996 dense_proxy_tag>::storage_category storage_category; 997 998 // Construction and destruction 999 BOOST_UBLAS_INLINE matrix_vector_range(matrix_type & data,const range_type & r1,const range_type & r2)1000 matrix_vector_range (matrix_type &data, const range_type &r1, const range_type &r2): 1001 data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) { 1002 // Early checking of preconditions here. 1003 // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () && 1004 // r1_.start () + r1_.size () <= data_.size1 (), bad_index ()); 1005 // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () && 1006 // r2_.start () + r2_.size () <= data_.size2 (), bad_index ()); 1007 // BOOST_UBLAS_CHECK (r1_.size () == r2_.size (), bad_size ()); 1008 } 1009 1010 // Accessors 1011 BOOST_UBLAS_INLINE start1() const1012 size_type start1 () const { 1013 return r1_.start (); 1014 } 1015 BOOST_UBLAS_INLINE start2() const1016 size_type start2 () const { 1017 return r2_.start (); 1018 } 1019 BOOST_UBLAS_INLINE size() const1020 size_type size () const { 1021 return BOOST_UBLAS_SAME (r1_.size (), r2_.size ()); 1022 } 1023 1024 // Storage accessors 1025 BOOST_UBLAS_INLINE data() const1026 const matrix_closure_type &data () const { 1027 return data_; 1028 } 1029 BOOST_UBLAS_INLINE data()1030 matrix_closure_type &data () { 1031 return data_; 1032 } 1033 1034 // Element access 1035 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 1036 BOOST_UBLAS_INLINE operator ()(size_type i) const1037 const_reference operator () (size_type i) const { 1038 return data_ (r1_ (i), r2_ (i)); 1039 } 1040 BOOST_UBLAS_INLINE operator ()(size_type i)1041 reference operator () (size_type i) { 1042 return data_ (r1_ (i), r2_ (i)); 1043 } 1044 1045 BOOST_UBLAS_INLINE operator [](size_type i) const1046 const_reference operator [] (size_type i) const { 1047 return (*this) (i); 1048 } 1049 BOOST_UBLAS_INLINE operator [](size_type i)1050 reference operator [] (size_type i) { 1051 return (*this) (i); 1052 } 1053 #else 1054 BOOST_UBLAS_INLINE operator ()(size_type i) const1055 reference operator () (size_type i) const { 1056 return data_ (r1_ (i), r2_ (i)); 1057 } 1058 1059 BOOST_UBLAS_INLINE operator [](size_type i) const1060 reference operator [] (size_type i) const { 1061 return (*this) (i); 1062 } 1063 #endif 1064 1065 // Assignment 1066 BOOST_UBLAS_INLINE operator =(const matrix_vector_range & mvr)1067 matrix_vector_range &operator = (const matrix_vector_range &mvr) { 1068 // ISSUE need a temporary, proxy can be overlaping alias 1069 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvr)); 1070 return *this; 1071 } 1072 BOOST_UBLAS_INLINE assign_temporary(matrix_vector_range & mvr)1073 matrix_vector_range &assign_temporary (matrix_vector_range &mvr) { 1074 // assign elements, proxied container remains the same 1075 vector_assign<scalar_assign> (*this, mvr); 1076 return *this; 1077 } 1078 template<class AE> 1079 BOOST_UBLAS_INLINE operator =(const vector_expression<AE> & ae)1080 matrix_vector_range &operator = (const vector_expression<AE> &ae) { 1081 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae)); 1082 return *this; 1083 } 1084 template<class AE> 1085 BOOST_UBLAS_INLINE assign(const vector_expression<AE> & ae)1086 matrix_vector_range &assign (const vector_expression<AE> &ae) { 1087 vector_assign<scalar_assign> (*this, ae); 1088 return *this; 1089 } 1090 template<class AE> 1091 BOOST_UBLAS_INLINE operator +=(const vector_expression<AE> & ae)1092 matrix_vector_range &operator += (const vector_expression<AE> &ae) { 1093 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae)); 1094 return *this; 1095 } 1096 template<class AE> 1097 BOOST_UBLAS_INLINE plus_assign(const vector_expression<AE> & ae)1098 matrix_vector_range &plus_assign (const vector_expression<AE> &ae) { 1099 vector_assign<scalar_plus_assign> (*this, ae); 1100 return *this; 1101 } 1102 template<class AE> 1103 BOOST_UBLAS_INLINE operator -=(const vector_expression<AE> & ae)1104 matrix_vector_range &operator -= (const vector_expression<AE> &ae) { 1105 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae)); 1106 return *this; 1107 } 1108 template<class AE> 1109 BOOST_UBLAS_INLINE minus_assign(const vector_expression<AE> & ae)1110 matrix_vector_range &minus_assign (const vector_expression<AE> &ae) { 1111 vector_assign<scalar_minus_assign> (*this, ae); 1112 return *this; 1113 } 1114 template<class AT> 1115 BOOST_UBLAS_INLINE operator *=(const AT & at)1116 matrix_vector_range &operator *= (const AT &at) { 1117 vector_assign_scalar<scalar_multiplies_assign> (*this, at); 1118 return *this; 1119 } 1120 template<class AT> 1121 BOOST_UBLAS_INLINE operator /=(const AT & at)1122 matrix_vector_range &operator /= (const AT &at) { 1123 vector_assign_scalar<scalar_divides_assign> (*this, at); 1124 return *this; 1125 } 1126 1127 // Closure comparison 1128 BOOST_UBLAS_INLINE same_closure(const matrix_vector_range & mvr) const1129 bool same_closure (const matrix_vector_range &mvr) const { 1130 return (*this).data_.same_closure (mvr.data_); 1131 } 1132 1133 // Comparison 1134 BOOST_UBLAS_INLINE operator ==(const matrix_vector_range & mvr) const1135 bool operator == (const matrix_vector_range &mvr) const { 1136 return (*this).data_ == mvr.data_ && r1_ == mvr.r1_ && r2_ == mvr.r2_; 1137 } 1138 1139 // Swapping 1140 BOOST_UBLAS_INLINE swap(matrix_vector_range mvr)1141 void swap (matrix_vector_range mvr) { 1142 if (this != &mvr) { 1143 BOOST_UBLAS_CHECK (size () == mvr.size (), bad_size ()); 1144 // Sparse ranges may be nonconformant now. 1145 // std::swap_ranges (begin (), end (), mvr.begin ()); 1146 vector_swap<scalar_swap> (*this, mvr); 1147 } 1148 } 1149 BOOST_UBLAS_INLINE swap(matrix_vector_range mvr1,matrix_vector_range mvr2)1150 friend void swap (matrix_vector_range mvr1, matrix_vector_range mvr2) { 1151 mvr1.swap (mvr2); 1152 } 1153 1154 // Iterator types 1155 private: 1156 // Use range as an index - FIXME this fails for packed assignment 1157 typedef typename range_type::const_iterator const_subiterator1_type; 1158 typedef typename range_type::const_iterator subiterator1_type; 1159 typedef typename range_type::const_iterator const_subiterator2_type; 1160 typedef typename range_type::const_iterator subiterator2_type; 1161 1162 public: 1163 class const_iterator; 1164 class iterator; 1165 1166 // Element lookup 1167 BOOST_UBLAS_INLINE find(size_type i) const1168 const_iterator find (size_type i) const { 1169 return const_iterator (*this, r1_.begin () + i, r2_.begin () + i); 1170 } 1171 BOOST_UBLAS_INLINE find(size_type i)1172 iterator find (size_type i) { 1173 return iterator (*this, r1_.begin () + i, r2_.begin () + i); 1174 } 1175 1176 class const_iterator: 1177 public container_const_reference<matrix_vector_range>, 1178 public iterator_base_traits<typename M::const_iterator1::iterator_category>::template 1179 iterator_base<const_iterator, value_type>::type { 1180 public: 1181 // FIXME Iterator can never be different code was: 1182 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category> 1183 BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value )); 1184 1185 typedef typename matrix_vector_range::value_type value_type; 1186 typedef typename matrix_vector_range::difference_type difference_type; 1187 typedef typename matrix_vector_range::const_reference reference; 1188 typedef const typename matrix_vector_range::value_type *pointer; 1189 1190 // Construction and destruction 1191 BOOST_UBLAS_INLINE const_iterator()1192 const_iterator (): 1193 container_const_reference<self_type> (), it1_ (), it2_ () {} 1194 BOOST_UBLAS_INLINE const_iterator(const self_type & mvr,const const_subiterator1_type & it1,const const_subiterator2_type & it2)1195 const_iterator (const self_type &mvr, const const_subiterator1_type &it1, const const_subiterator2_type &it2): 1196 container_const_reference<self_type> (mvr), it1_ (it1), it2_ (it2) {} 1197 BOOST_UBLAS_INLINE const_iterator(const typename self_type::iterator & it)1198 const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here 1199 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {} 1200 1201 // Arithmetic 1202 BOOST_UBLAS_INLINE operator ++()1203 const_iterator &operator ++ () { 1204 ++ it1_; 1205 ++ it2_; 1206 return *this; 1207 } 1208 BOOST_UBLAS_INLINE operator --()1209 const_iterator &operator -- () { 1210 -- it1_; 1211 -- it2_; 1212 return *this; 1213 } 1214 BOOST_UBLAS_INLINE operator +=(difference_type n)1215 const_iterator &operator += (difference_type n) { 1216 it1_ += n; 1217 it2_ += n; 1218 return *this; 1219 } 1220 BOOST_UBLAS_INLINE operator -=(difference_type n)1221 const_iterator &operator -= (difference_type n) { 1222 it1_ -= n; 1223 it2_ -= n; 1224 return *this; 1225 } 1226 BOOST_UBLAS_INLINE operator -(const const_iterator & it) const1227 difference_type operator - (const const_iterator &it) const { 1228 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1229 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_); 1230 } 1231 1232 // Dereference 1233 BOOST_UBLAS_INLINE operator *() const1234 const_reference operator * () const { 1235 // FIXME replace find with at_element 1236 return (*this) ().data_ (*it1_, *it2_); 1237 } 1238 BOOST_UBLAS_INLINE operator [](difference_type n) const1239 const_reference operator [] (difference_type n) const { 1240 return *(*this + n); 1241 } 1242 1243 // Index 1244 BOOST_UBLAS_INLINE index() const1245 size_type index () const { 1246 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ()); 1247 } 1248 1249 // Assignment 1250 BOOST_UBLAS_INLINE operator =(const const_iterator & it)1251 const_iterator &operator = (const const_iterator &it) { 1252 container_const_reference<self_type>::assign (&it ()); 1253 it1_ = it.it1_; 1254 it2_ = it.it2_; 1255 return *this; 1256 } 1257 1258 // Comparison 1259 BOOST_UBLAS_INLINE operator ==(const const_iterator & it) const1260 bool operator == (const const_iterator &it) const { 1261 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1262 return it1_ == it.it1_ && it2_ == it.it2_; 1263 } 1264 BOOST_UBLAS_INLINE operator <(const const_iterator & it) const1265 bool operator < (const const_iterator &it) const { 1266 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1267 return it1_ < it.it1_ && it2_ < it.it2_; 1268 } 1269 1270 private: 1271 const_subiterator1_type it1_; 1272 const_subiterator2_type it2_; 1273 }; 1274 1275 BOOST_UBLAS_INLINE begin() const1276 const_iterator begin () const { 1277 return find (0); 1278 } 1279 BOOST_UBLAS_INLINE cbegin() const1280 const_iterator cbegin () const { 1281 return begin (); 1282 } 1283 BOOST_UBLAS_INLINE end() const1284 const_iterator end () const { 1285 return find (size ()); 1286 } 1287 BOOST_UBLAS_INLINE cend() const1288 const_iterator cend () const { 1289 return end (); 1290 } 1291 1292 class iterator: 1293 public container_reference<matrix_vector_range>, 1294 public iterator_base_traits<typename M::iterator1::iterator_category>::template 1295 iterator_base<iterator, value_type>::type { 1296 public: 1297 // FIXME Iterator can never be different code was: 1298 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category> 1299 BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value )); 1300 1301 typedef typename matrix_vector_range::value_type value_type; 1302 typedef typename matrix_vector_range::difference_type difference_type; 1303 typedef typename matrix_vector_range::reference reference; 1304 typedef typename matrix_vector_range::value_type *pointer; 1305 1306 // Construction and destruction 1307 BOOST_UBLAS_INLINE iterator()1308 iterator (): 1309 container_reference<self_type> (), it1_ (), it2_ () {} 1310 BOOST_UBLAS_INLINE iterator(self_type & mvr,const subiterator1_type & it1,const subiterator2_type & it2)1311 iterator (self_type &mvr, const subiterator1_type &it1, const subiterator2_type &it2): 1312 container_reference<self_type> (mvr), it1_ (it1), it2_ (it2) {} 1313 1314 // Arithmetic 1315 BOOST_UBLAS_INLINE operator ++()1316 iterator &operator ++ () { 1317 ++ it1_; 1318 ++ it2_; 1319 return *this; 1320 } 1321 BOOST_UBLAS_INLINE operator --()1322 iterator &operator -- () { 1323 -- it1_; 1324 -- it2_; 1325 return *this; 1326 } 1327 BOOST_UBLAS_INLINE operator +=(difference_type n)1328 iterator &operator += (difference_type n) { 1329 it1_ += n; 1330 it2_ += n; 1331 return *this; 1332 } 1333 BOOST_UBLAS_INLINE operator -=(difference_type n)1334 iterator &operator -= (difference_type n) { 1335 it1_ -= n; 1336 it2_ -= n; 1337 return *this; 1338 } 1339 BOOST_UBLAS_INLINE operator -(const iterator & it) const1340 difference_type operator - (const iterator &it) const { 1341 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1342 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_); 1343 } 1344 1345 // Dereference 1346 BOOST_UBLAS_INLINE operator *() const1347 reference operator * () const { 1348 // FIXME replace find with at_element 1349 return (*this) ().data_ (*it1_, *it2_); 1350 } 1351 BOOST_UBLAS_INLINE operator [](difference_type n) const1352 reference operator [] (difference_type n) const { 1353 return *(*this + n); 1354 } 1355 1356 // Index 1357 BOOST_UBLAS_INLINE index() const1358 size_type index () const { 1359 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ()); 1360 } 1361 1362 // Assignment 1363 BOOST_UBLAS_INLINE operator =(const iterator & it)1364 iterator &operator = (const iterator &it) { 1365 container_reference<self_type>::assign (&it ()); 1366 it1_ = it.it1_; 1367 it2_ = it.it2_; 1368 return *this; 1369 } 1370 1371 // Comparison 1372 BOOST_UBLAS_INLINE operator ==(const iterator & it) const1373 bool operator == (const iterator &it) const { 1374 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1375 return it1_ == it.it1_ && it2_ == it.it2_; 1376 } 1377 BOOST_UBLAS_INLINE operator <(const iterator & it) const1378 bool operator < (const iterator &it) const { 1379 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1380 return it1_ < it.it1_ && it2_ < it.it2_; 1381 } 1382 1383 private: 1384 subiterator1_type it1_; 1385 subiterator2_type it2_; 1386 1387 friend class const_iterator; 1388 }; 1389 1390 BOOST_UBLAS_INLINE begin()1391 iterator begin () { 1392 return find (0); 1393 } 1394 BOOST_UBLAS_INLINE end()1395 iterator end () { 1396 return find (size ()); 1397 } 1398 1399 // Reverse iterator 1400 typedef reverse_iterator_base<const_iterator> const_reverse_iterator; 1401 typedef reverse_iterator_base<iterator> reverse_iterator; 1402 1403 BOOST_UBLAS_INLINE rbegin() const1404 const_reverse_iterator rbegin () const { 1405 return const_reverse_iterator (end ()); 1406 } 1407 BOOST_UBLAS_INLINE crbegin() const1408 const_reverse_iterator crbegin () const { 1409 return rbegin (); 1410 } 1411 BOOST_UBLAS_INLINE rend() const1412 const_reverse_iterator rend () const { 1413 return const_reverse_iterator (begin ()); 1414 } 1415 BOOST_UBLAS_INLINE crend() const1416 const_reverse_iterator crend () const { 1417 return rend (); 1418 } 1419 BOOST_UBLAS_INLINE rbegin()1420 reverse_iterator rbegin () { 1421 return reverse_iterator (end ()); 1422 } 1423 BOOST_UBLAS_INLINE rend()1424 reverse_iterator rend () { 1425 return reverse_iterator (begin ()); 1426 } 1427 1428 private: 1429 matrix_closure_type data_; 1430 range_type r1_; 1431 range_type r2_; 1432 }; 1433 1434 // Specialize temporary 1435 template <class M> 1436 struct vector_temporary_traits< matrix_vector_range<M> > 1437 : vector_temporary_traits< M > {} ; 1438 template <class M> 1439 struct vector_temporary_traits< const matrix_vector_range<M> > 1440 : vector_temporary_traits< M > {} ; 1441 1442 // Matrix based vector slice class 1443 template<class M> 1444 class matrix_vector_slice: 1445 public vector_expression<matrix_vector_slice<M> > { 1446 1447 typedef matrix_vector_slice<M> self_type; 1448 public: 1449 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 1450 using vector_expression<self_type>::operator (); 1451 #endif 1452 typedef M matrix_type; 1453 typedef typename M::size_type size_type; 1454 typedef typename M::difference_type difference_type; 1455 typedef typename M::value_type value_type; 1456 typedef typename M::const_reference const_reference; 1457 typedef typename boost::mpl::if_<boost::is_const<M>, 1458 typename M::const_reference, 1459 typename M::reference>::type reference; 1460 typedef typename boost::mpl::if_<boost::is_const<M>, 1461 typename M::const_closure_type, 1462 typename M::closure_type>::type matrix_closure_type; 1463 typedef basic_range<size_type, difference_type> range_type; 1464 typedef basic_slice<size_type, difference_type> slice_type; 1465 typedef const self_type const_closure_type; 1466 typedef self_type closure_type; 1467 typedef typename storage_restrict_traits<typename M::storage_category, 1468 dense_proxy_tag>::storage_category storage_category; 1469 1470 // Construction and destruction 1471 BOOST_UBLAS_INLINE matrix_vector_slice(matrix_type & data,const slice_type & s1,const slice_type & s2)1472 matrix_vector_slice (matrix_type &data, const slice_type &s1, const slice_type &s2): 1473 data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) { 1474 // Early checking of preconditions here. 1475 // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () && 1476 // s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ()); 1477 // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () && 1478 // s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ()); 1479 } 1480 1481 // Accessors 1482 BOOST_UBLAS_INLINE start1() const1483 size_type start1 () const { 1484 return s1_.start (); 1485 } 1486 BOOST_UBLAS_INLINE start2() const1487 size_type start2 () const { 1488 return s2_.start (); 1489 } 1490 BOOST_UBLAS_INLINE stride1() const1491 difference_type stride1 () const { 1492 return s1_.stride (); 1493 } 1494 BOOST_UBLAS_INLINE stride2() const1495 difference_type stride2 () const { 1496 return s2_.stride (); 1497 } 1498 BOOST_UBLAS_INLINE size() const1499 size_type size () const { 1500 return BOOST_UBLAS_SAME (s1_.size (), s2_.size ()); 1501 } 1502 1503 // Storage accessors 1504 BOOST_UBLAS_INLINE data() const1505 const matrix_closure_type &data () const { 1506 return data_; 1507 } 1508 BOOST_UBLAS_INLINE data()1509 matrix_closure_type &data () { 1510 return data_; 1511 } 1512 1513 // Element access 1514 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 1515 BOOST_UBLAS_INLINE operator ()(size_type i) const1516 const_reference operator () (size_type i) const { 1517 return data_ (s1_ (i), s2_ (i)); 1518 } 1519 BOOST_UBLAS_INLINE operator ()(size_type i)1520 reference operator () (size_type i) { 1521 return data_ (s1_ (i), s2_ (i)); 1522 } 1523 1524 BOOST_UBLAS_INLINE operator [](size_type i) const1525 const_reference operator [] (size_type i) const { 1526 return (*this) (i); 1527 } 1528 BOOST_UBLAS_INLINE operator [](size_type i)1529 reference operator [] (size_type i) { 1530 return (*this) (i); 1531 } 1532 #else 1533 BOOST_UBLAS_INLINE operator ()(size_type i) const1534 reference operator () (size_type i) const { 1535 return data_ (s1_ (i), s2_ (i)); 1536 } 1537 1538 BOOST_UBLAS_INLINE operator [](size_type i) const1539 reference operator [] (size_type i) const { 1540 return (*this) (i); 1541 } 1542 #endif 1543 1544 // Assignment 1545 BOOST_UBLAS_INLINE operator =(const matrix_vector_slice & mvs)1546 matrix_vector_slice &operator = (const matrix_vector_slice &mvs) { 1547 // ISSUE need a temporary, proxy can be overlaping alias 1548 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvs)); 1549 return *this; 1550 } 1551 BOOST_UBLAS_INLINE assign_temporary(matrix_vector_slice & mvs)1552 matrix_vector_slice &assign_temporary (matrix_vector_slice &mvs) { 1553 // assign elements, proxied container remains the same 1554 vector_assign<scalar_assign> (*this, mvs); 1555 return *this; 1556 } 1557 template<class AE> 1558 BOOST_UBLAS_INLINE operator =(const vector_expression<AE> & ae)1559 matrix_vector_slice &operator = (const vector_expression<AE> &ae) { 1560 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae)); 1561 return *this; 1562 } 1563 template<class AE> 1564 BOOST_UBLAS_INLINE assign(const vector_expression<AE> & ae)1565 matrix_vector_slice &assign (const vector_expression<AE> &ae) { 1566 vector_assign<scalar_assign> (*this, ae); 1567 return *this; 1568 } 1569 template<class AE> 1570 BOOST_UBLAS_INLINE operator +=(const vector_expression<AE> & ae)1571 matrix_vector_slice &operator += (const vector_expression<AE> &ae) { 1572 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae)); 1573 return *this; 1574 } 1575 template<class AE> 1576 BOOST_UBLAS_INLINE plus_assign(const vector_expression<AE> & ae)1577 matrix_vector_slice &plus_assign (const vector_expression<AE> &ae) { 1578 vector_assign<scalar_plus_assign> (*this, ae); 1579 return *this; 1580 } 1581 template<class AE> 1582 BOOST_UBLAS_INLINE operator -=(const vector_expression<AE> & ae)1583 matrix_vector_slice &operator -= (const vector_expression<AE> &ae) { 1584 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae)); 1585 return *this; 1586 } 1587 template<class AE> 1588 BOOST_UBLAS_INLINE minus_assign(const vector_expression<AE> & ae)1589 matrix_vector_slice &minus_assign (const vector_expression<AE> &ae) { 1590 vector_assign<scalar_minus_assign> (*this, ae); 1591 return *this; 1592 } 1593 template<class AT> 1594 BOOST_UBLAS_INLINE operator *=(const AT & at)1595 matrix_vector_slice &operator *= (const AT &at) { 1596 vector_assign_scalar<scalar_multiplies_assign> (*this, at); 1597 return *this; 1598 } 1599 template<class AT> 1600 BOOST_UBLAS_INLINE operator /=(const AT & at)1601 matrix_vector_slice &operator /= (const AT &at) { 1602 vector_assign_scalar<scalar_divides_assign> (*this, at); 1603 return *this; 1604 } 1605 1606 // Closure comparison 1607 BOOST_UBLAS_INLINE same_closure(const matrix_vector_slice & mvs) const1608 bool same_closure (const matrix_vector_slice &mvs) const { 1609 return (*this).data_.same_closure (mvs.data_); 1610 } 1611 1612 // Comparison 1613 BOOST_UBLAS_INLINE operator ==(const matrix_vector_slice & mvs) const1614 bool operator == (const matrix_vector_slice &mvs) const { 1615 return (*this).data_ == mvs.data_ && s1_ == mvs.s1_ && s2_ == mvs.s2_; 1616 } 1617 1618 // Swapping 1619 BOOST_UBLAS_INLINE swap(matrix_vector_slice mvs)1620 void swap (matrix_vector_slice mvs) { 1621 if (this != &mvs) { 1622 BOOST_UBLAS_CHECK (size () == mvs.size (), bad_size ()); 1623 // Sparse ranges may be nonconformant now. 1624 // std::swap_ranges (begin (), end (), mvs.begin ()); 1625 vector_swap<scalar_swap> (*this, mvs); 1626 } 1627 } 1628 BOOST_UBLAS_INLINE swap(matrix_vector_slice mvs1,matrix_vector_slice mvs2)1629 friend void swap (matrix_vector_slice mvs1, matrix_vector_slice mvs2) { 1630 mvs1.swap (mvs2); 1631 } 1632 1633 // Iterator types 1634 private: 1635 // Use slice as an index - FIXME this fails for packed assignment 1636 typedef typename slice_type::const_iterator const_subiterator1_type; 1637 typedef typename slice_type::const_iterator subiterator1_type; 1638 typedef typename slice_type::const_iterator const_subiterator2_type; 1639 typedef typename slice_type::const_iterator subiterator2_type; 1640 1641 public: 1642 class const_iterator; 1643 class iterator; 1644 1645 // Element lookup 1646 BOOST_UBLAS_INLINE find(size_type i) const1647 const_iterator find (size_type i) const { 1648 return const_iterator (*this, s1_.begin () + i, s2_.begin () + i); 1649 } 1650 BOOST_UBLAS_INLINE find(size_type i)1651 iterator find (size_type i) { 1652 return iterator (*this, s1_.begin () + i, s2_.begin () + i); 1653 } 1654 1655 // Iterators simply are indices. 1656 1657 class const_iterator: 1658 public container_const_reference<matrix_vector_slice>, 1659 public iterator_base_traits<typename M::const_iterator1::iterator_category>::template 1660 iterator_base<const_iterator, value_type>::type { 1661 public: 1662 // FIXME Iterator can never be different code was: 1663 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category> 1664 BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value )); 1665 1666 typedef typename matrix_vector_slice::value_type value_type; 1667 typedef typename matrix_vector_slice::difference_type difference_type; 1668 typedef typename matrix_vector_slice::const_reference reference; 1669 typedef const typename matrix_vector_slice::value_type *pointer; 1670 1671 // Construction and destruction 1672 BOOST_UBLAS_INLINE const_iterator()1673 const_iterator (): 1674 container_const_reference<self_type> (), it1_ (), it2_ () {} 1675 BOOST_UBLAS_INLINE const_iterator(const self_type & mvs,const const_subiterator1_type & it1,const const_subiterator2_type & it2)1676 const_iterator (const self_type &mvs, const const_subiterator1_type &it1, const const_subiterator2_type &it2): 1677 container_const_reference<self_type> (mvs), it1_ (it1), it2_ (it2) {} 1678 BOOST_UBLAS_INLINE const_iterator(const typename self_type::iterator & it)1679 const_iterator (const typename self_type::iterator &it): // ISSUE vector:: stops VC8 using std::iterator here 1680 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {} 1681 1682 // Arithmetic 1683 BOOST_UBLAS_INLINE operator ++()1684 const_iterator &operator ++ () { 1685 ++ it1_; 1686 ++ it2_; 1687 return *this; 1688 } 1689 BOOST_UBLAS_INLINE operator --()1690 const_iterator &operator -- () { 1691 -- it1_; 1692 -- it2_; 1693 return *this; 1694 } 1695 BOOST_UBLAS_INLINE operator +=(difference_type n)1696 const_iterator &operator += (difference_type n) { 1697 it1_ += n; 1698 it2_ += n; 1699 return *this; 1700 } 1701 BOOST_UBLAS_INLINE operator -=(difference_type n)1702 const_iterator &operator -= (difference_type n) { 1703 it1_ -= n; 1704 it2_ -= n; 1705 return *this; 1706 } 1707 BOOST_UBLAS_INLINE operator -(const const_iterator & it) const1708 difference_type operator - (const const_iterator &it) const { 1709 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1710 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_); 1711 } 1712 1713 // Dereference 1714 BOOST_UBLAS_INLINE operator *() const1715 const_reference operator * () const { 1716 // FIXME replace find with at_element 1717 return (*this) ().data_ (*it1_, *it2_); 1718 } 1719 BOOST_UBLAS_INLINE operator [](difference_type n) const1720 const_reference operator [] (difference_type n) const { 1721 return *(*this + n); 1722 } 1723 1724 // Index 1725 BOOST_UBLAS_INLINE index() const1726 size_type index () const { 1727 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ()); 1728 } 1729 1730 // Assignment 1731 BOOST_UBLAS_INLINE operator =(const const_iterator & it)1732 const_iterator &operator = (const const_iterator &it) { 1733 container_const_reference<self_type>::assign (&it ()); 1734 it1_ = it.it1_; 1735 it2_ = it.it2_; 1736 return *this; 1737 } 1738 1739 // Comparison 1740 BOOST_UBLAS_INLINE operator ==(const const_iterator & it) const1741 bool operator == (const const_iterator &it) const { 1742 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1743 return it1_ == it.it1_ && it2_ == it.it2_; 1744 } 1745 BOOST_UBLAS_INLINE operator <(const const_iterator & it) const1746 bool operator < (const const_iterator &it) const { 1747 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1748 return it1_ < it.it1_ && it2_ < it.it2_; 1749 } 1750 1751 private: 1752 const_subiterator1_type it1_; 1753 const_subiterator2_type it2_; 1754 }; 1755 1756 BOOST_UBLAS_INLINE begin() const1757 const_iterator begin () const { 1758 return find (0); 1759 } 1760 BOOST_UBLAS_INLINE cbegin() const1761 const_iterator cbegin () const { 1762 return begin (); 1763 } 1764 BOOST_UBLAS_INLINE end() const1765 const_iterator end () const { 1766 return find (size ()); 1767 } 1768 BOOST_UBLAS_INLINE cend() const1769 const_iterator cend () const { 1770 return end (); 1771 } 1772 1773 class iterator: 1774 public container_reference<matrix_vector_slice>, 1775 public iterator_base_traits<typename M::iterator1::iterator_category>::template 1776 iterator_base<iterator, value_type>::type { 1777 public: 1778 // FIXME Iterator can never be different code was: 1779 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category> 1780 BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value )); 1781 1782 typedef typename matrix_vector_slice::value_type value_type; 1783 typedef typename matrix_vector_slice::difference_type difference_type; 1784 typedef typename matrix_vector_slice::reference reference; 1785 typedef typename matrix_vector_slice::value_type *pointer; 1786 1787 // Construction and destruction 1788 BOOST_UBLAS_INLINE iterator()1789 iterator (): 1790 container_reference<self_type> (), it1_ (), it2_ () {} 1791 BOOST_UBLAS_INLINE iterator(self_type & mvs,const subiterator1_type & it1,const subiterator2_type & it2)1792 iterator (self_type &mvs, const subiterator1_type &it1, const subiterator2_type &it2): 1793 container_reference<self_type> (mvs), it1_ (it1), it2_ (it2) {} 1794 1795 // Arithmetic 1796 BOOST_UBLAS_INLINE operator ++()1797 iterator &operator ++ () { 1798 ++ it1_; 1799 ++ it2_; 1800 return *this; 1801 } 1802 BOOST_UBLAS_INLINE operator --()1803 iterator &operator -- () { 1804 -- it1_; 1805 -- it2_; 1806 return *this; 1807 } 1808 BOOST_UBLAS_INLINE operator +=(difference_type n)1809 iterator &operator += (difference_type n) { 1810 it1_ += n; 1811 it2_ += n; 1812 return *this; 1813 } 1814 BOOST_UBLAS_INLINE operator -=(difference_type n)1815 iterator &operator -= (difference_type n) { 1816 it1_ -= n; 1817 it2_ -= n; 1818 return *this; 1819 } 1820 BOOST_UBLAS_INLINE operator -(const iterator & it) const1821 difference_type operator - (const iterator &it) const { 1822 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1823 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_); 1824 } 1825 1826 // Dereference 1827 BOOST_UBLAS_INLINE operator *() const1828 reference operator * () const { 1829 // FIXME replace find with at_element 1830 return (*this) ().data_ (*it1_, *it2_); 1831 } 1832 BOOST_UBLAS_INLINE operator [](difference_type n) const1833 reference operator [] (difference_type n) const { 1834 return *(*this + n); 1835 } 1836 1837 // Index 1838 BOOST_UBLAS_INLINE index() const1839 size_type index () const { 1840 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ()); 1841 } 1842 1843 // Assignment 1844 BOOST_UBLAS_INLINE operator =(const iterator & it)1845 iterator &operator = (const iterator &it) { 1846 container_reference<self_type>::assign (&it ()); 1847 it1_ = it.it1_; 1848 it2_ = it.it2_; 1849 return *this; 1850 } 1851 1852 // Comparison 1853 BOOST_UBLAS_INLINE operator ==(const iterator & it) const1854 bool operator == (const iterator &it) const { 1855 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1856 return it1_ == it.it1_ && it2_ == it.it2_; 1857 } 1858 BOOST_UBLAS_INLINE operator <(const iterator & it) const1859 bool operator < (const iterator &it) const { 1860 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 1861 return it1_ < it.it1_ && it2_ < it.it2_; 1862 } 1863 1864 private: 1865 subiterator1_type it1_; 1866 subiterator2_type it2_; 1867 1868 friend class const_iterator; 1869 }; 1870 1871 BOOST_UBLAS_INLINE begin()1872 iterator begin () { 1873 return find (0); 1874 } 1875 BOOST_UBLAS_INLINE end()1876 iterator end () { 1877 return find (size ()); 1878 } 1879 1880 // Reverse iterator 1881 typedef reverse_iterator_base<const_iterator> const_reverse_iterator; 1882 typedef reverse_iterator_base<iterator> reverse_iterator; 1883 1884 BOOST_UBLAS_INLINE rbegin() const1885 const_reverse_iterator rbegin () const { 1886 return const_reverse_iterator (end ()); 1887 } 1888 BOOST_UBLAS_INLINE crbegin() const1889 const_reverse_iterator crbegin () const { 1890 return rbegin (); 1891 } 1892 BOOST_UBLAS_INLINE rend() const1893 const_reverse_iterator rend () const { 1894 return const_reverse_iterator (begin ()); 1895 } 1896 BOOST_UBLAS_INLINE crend() const1897 const_reverse_iterator crend () const { 1898 return rend (); 1899 } 1900 BOOST_UBLAS_INLINE rbegin()1901 reverse_iterator rbegin () { 1902 return reverse_iterator (end ()); 1903 } 1904 BOOST_UBLAS_INLINE rend()1905 reverse_iterator rend () { 1906 return reverse_iterator (begin ()); 1907 } 1908 1909 private: 1910 matrix_closure_type data_; 1911 slice_type s1_; 1912 slice_type s2_; 1913 }; 1914 1915 // Specialize temporary 1916 template <class M> 1917 struct vector_temporary_traits< matrix_vector_slice<M> > 1918 : vector_temporary_traits< M > {} ; 1919 template <class M> 1920 struct vector_temporary_traits< const matrix_vector_slice<M> > 1921 : vector_temporary_traits< M > {} ; 1922 1923 // Matrix based vector indirection class 1924 1925 template<class M, class IA> 1926 class matrix_vector_indirect: 1927 public vector_expression<matrix_vector_indirect<M, IA> > { 1928 1929 typedef matrix_vector_indirect<M, IA> self_type; 1930 public: 1931 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 1932 using vector_expression<self_type>::operator (); 1933 #endif 1934 typedef M matrix_type; 1935 typedef IA indirect_array_type; 1936 typedef typename M::size_type size_type; 1937 typedef typename M::difference_type difference_type; 1938 typedef typename M::value_type value_type; 1939 typedef typename M::const_reference const_reference; 1940 typedef typename boost::mpl::if_<boost::is_const<M>, 1941 typename M::const_reference, 1942 typename M::reference>::type reference; 1943 typedef typename boost::mpl::if_<boost::is_const<M>, 1944 typename M::const_closure_type, 1945 typename M::closure_type>::type matrix_closure_type; 1946 typedef const self_type const_closure_type; 1947 typedef self_type closure_type; 1948 typedef typename storage_restrict_traits<typename M::storage_category, 1949 dense_proxy_tag>::storage_category storage_category; 1950 1951 // Construction and destruction 1952 BOOST_UBLAS_INLINE matrix_vector_indirect(matrix_type & data,size_type size)1953 matrix_vector_indirect (matrix_type &data, size_type size): 1954 data_ (data), ia1_ (size), ia2_ (size) {} 1955 BOOST_UBLAS_INLINE matrix_vector_indirect(matrix_type & data,const indirect_array_type & ia1,const indirect_array_type & ia2)1956 matrix_vector_indirect (matrix_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2): 1957 data_ (data), ia1_ (ia1), ia2_ (ia2) { 1958 // Early checking of preconditions here. 1959 // BOOST_UBLAS_CHECK (ia1_.size () == ia2_.size (), bad_size ()); 1960 } 1961 1962 // Accessors 1963 BOOST_UBLAS_INLINE size() const1964 size_type size () const { 1965 return BOOST_UBLAS_SAME (ia1_.size (), ia2_.size ()); 1966 } 1967 BOOST_UBLAS_INLINE indirect1() const1968 const indirect_array_type &indirect1 () const { 1969 return ia1_; 1970 } 1971 BOOST_UBLAS_INLINE indirect1()1972 indirect_array_type &indirect1 () { 1973 return ia1_; 1974 } 1975 BOOST_UBLAS_INLINE indirect2() const1976 const indirect_array_type &indirect2 () const { 1977 return ia2_; 1978 } 1979 BOOST_UBLAS_INLINE indirect2()1980 indirect_array_type &indirect2 () { 1981 return ia2_; 1982 } 1983 1984 // Storage accessors 1985 BOOST_UBLAS_INLINE data() const1986 const matrix_closure_type &data () const { 1987 return data_; 1988 } 1989 BOOST_UBLAS_INLINE data()1990 matrix_closure_type &data () { 1991 return data_; 1992 } 1993 1994 // Element access 1995 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 1996 BOOST_UBLAS_INLINE operator ()(size_type i) const1997 const_reference operator () (size_type i) const { 1998 return data_ (ia1_ (i), ia2_ (i)); 1999 } 2000 BOOST_UBLAS_INLINE operator ()(size_type i)2001 reference operator () (size_type i) { 2002 return data_ (ia1_ (i), ia2_ (i)); 2003 } 2004 2005 BOOST_UBLAS_INLINE operator [](size_type i) const2006 const_reference operator [] (size_type i) const { 2007 return (*this) (i); 2008 } 2009 BOOST_UBLAS_INLINE operator [](size_type i)2010 reference operator [] (size_type i) { 2011 return (*this) (i); 2012 } 2013 #else 2014 BOOST_UBLAS_INLINE operator ()(size_type i) const2015 reference operator () (size_type i) const { 2016 return data_ (ia1_ (i), ia2_ (i)); 2017 } 2018 2019 BOOST_UBLAS_INLINE operator [](size_type i) const2020 reference operator [] (size_type i) const { 2021 return (*this) (i); 2022 } 2023 #endif 2024 2025 // Assignment 2026 BOOST_UBLAS_INLINE operator =(const matrix_vector_indirect & mvi)2027 matrix_vector_indirect &operator = (const matrix_vector_indirect &mvi) { 2028 // ISSUE need a temporary, proxy can be overlaping alias 2029 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvi)); 2030 return *this; 2031 } 2032 BOOST_UBLAS_INLINE assign_temporary(matrix_vector_indirect & mvi)2033 matrix_vector_indirect &assign_temporary (matrix_vector_indirect &mvi) { 2034 // assign elements, proxied container remains the same 2035 vector_assign<scalar_assign> (*this, mvi); 2036 return *this; 2037 } 2038 template<class AE> 2039 BOOST_UBLAS_INLINE operator =(const vector_expression<AE> & ae)2040 matrix_vector_indirect &operator = (const vector_expression<AE> &ae) { 2041 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae)); 2042 return *this; 2043 } 2044 template<class AE> 2045 BOOST_UBLAS_INLINE assign(const vector_expression<AE> & ae)2046 matrix_vector_indirect &assign (const vector_expression<AE> &ae) { 2047 vector_assign<scalar_assign> (*this, ae); 2048 return *this; 2049 } 2050 template<class AE> 2051 BOOST_UBLAS_INLINE operator +=(const vector_expression<AE> & ae)2052 matrix_vector_indirect &operator += (const vector_expression<AE> &ae) { 2053 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae)); 2054 return *this; 2055 } 2056 template<class AE> 2057 BOOST_UBLAS_INLINE plus_assign(const vector_expression<AE> & ae)2058 matrix_vector_indirect &plus_assign (const vector_expression<AE> &ae) { 2059 vector_assign<scalar_plus_assign> (*this, ae); 2060 return *this; 2061 } 2062 template<class AE> 2063 BOOST_UBLAS_INLINE operator -=(const vector_expression<AE> & ae)2064 matrix_vector_indirect &operator -= (const vector_expression<AE> &ae) { 2065 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae)); 2066 return *this; 2067 } 2068 template<class AE> 2069 BOOST_UBLAS_INLINE minus_assign(const vector_expression<AE> & ae)2070 matrix_vector_indirect &minus_assign (const vector_expression<AE> &ae) { 2071 vector_assign<scalar_minus_assign> (*this, ae); 2072 return *this; 2073 } 2074 template<class AT> 2075 BOOST_UBLAS_INLINE operator *=(const AT & at)2076 matrix_vector_indirect &operator *= (const AT &at) { 2077 vector_assign_scalar<scalar_multiplies_assign> (*this, at); 2078 return *this; 2079 } 2080 template<class AT> 2081 BOOST_UBLAS_INLINE operator /=(const AT & at)2082 matrix_vector_indirect &operator /= (const AT &at) { 2083 vector_assign_scalar<scalar_divides_assign> (*this, at); 2084 return *this; 2085 } 2086 2087 // Closure comparison 2088 BOOST_UBLAS_INLINE same_closure(const matrix_vector_indirect & mvi) const2089 bool same_closure (const matrix_vector_indirect &mvi) const { 2090 return (*this).data_.same_closure (mvi.data_); 2091 } 2092 2093 // Comparison 2094 BOOST_UBLAS_INLINE operator ==(const matrix_vector_indirect & mvi) const2095 bool operator == (const matrix_vector_indirect &mvi) const { 2096 return (*this).data_ == mvi.data_ && ia1_ == mvi.ia1_ && ia2_ == mvi.ia2_; 2097 } 2098 2099 // Swapping 2100 BOOST_UBLAS_INLINE swap(matrix_vector_indirect mvi)2101 void swap (matrix_vector_indirect mvi) { 2102 if (this != &mvi) { 2103 BOOST_UBLAS_CHECK (size () == mvi.size (), bad_size ()); 2104 // Sparse ranges may be nonconformant now. 2105 // std::swap_ranges (begin (), end (), mvi.begin ()); 2106 vector_swap<scalar_swap> (*this, mvi); 2107 } 2108 } 2109 BOOST_UBLAS_INLINE swap(matrix_vector_indirect mvi1,matrix_vector_indirect mvi2)2110 friend void swap (matrix_vector_indirect mvi1, matrix_vector_indirect mvi2) { 2111 mvi1.swap (mvi2); 2112 } 2113 2114 // Iterator types 2115 private: 2116 // Use indirect array as an index - FIXME this fails for packed assignment 2117 typedef typename IA::const_iterator const_subiterator1_type; 2118 typedef typename IA::const_iterator subiterator1_type; 2119 typedef typename IA::const_iterator const_subiterator2_type; 2120 typedef typename IA::const_iterator subiterator2_type; 2121 2122 public: 2123 class const_iterator; 2124 class iterator; 2125 2126 // Element lookup 2127 BOOST_UBLAS_INLINE find(size_type i) const2128 const_iterator find (size_type i) const { 2129 return const_iterator (*this, ia1_.begin () + i, ia2_.begin () + i); 2130 } 2131 BOOST_UBLAS_INLINE find(size_type i)2132 iterator find (size_type i) { 2133 return iterator (*this, ia1_.begin () + i, ia2_.begin () + i); 2134 } 2135 2136 // Iterators simply are indices. 2137 2138 class const_iterator: 2139 public container_const_reference<matrix_vector_indirect>, 2140 public iterator_base_traits<typename M::const_iterator1::iterator_category>::template 2141 iterator_base<const_iterator, value_type>::type { 2142 public: 2143 // FIXME Iterator can never be different code was: 2144 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category> 2145 BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value )); 2146 2147 typedef typename matrix_vector_indirect::value_type value_type; 2148 typedef typename matrix_vector_indirect::difference_type difference_type; 2149 typedef typename matrix_vector_indirect::const_reference reference; 2150 typedef const typename matrix_vector_indirect::value_type *pointer; 2151 2152 // Construction and destruction 2153 BOOST_UBLAS_INLINE const_iterator()2154 const_iterator (): 2155 container_const_reference<self_type> (), it1_ (), it2_ () {} 2156 BOOST_UBLAS_INLINE const_iterator(const self_type & mvi,const const_subiterator1_type & it1,const const_subiterator2_type & it2)2157 const_iterator (const self_type &mvi, const const_subiterator1_type &it1, const const_subiterator2_type &it2): 2158 container_const_reference<self_type> (mvi), it1_ (it1), it2_ (it2) {} 2159 BOOST_UBLAS_INLINE const_iterator(const typename self_type::iterator & it)2160 const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here 2161 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {} 2162 2163 // Arithmetic 2164 BOOST_UBLAS_INLINE operator ++()2165 const_iterator &operator ++ () { 2166 ++ it1_; 2167 ++ it2_; 2168 return *this; 2169 } 2170 BOOST_UBLAS_INLINE operator --()2171 const_iterator &operator -- () { 2172 -- it1_; 2173 -- it2_; 2174 return *this; 2175 } 2176 BOOST_UBLAS_INLINE operator +=(difference_type n)2177 const_iterator &operator += (difference_type n) { 2178 it1_ += n; 2179 it2_ += n; 2180 return *this; 2181 } 2182 BOOST_UBLAS_INLINE operator -=(difference_type n)2183 const_iterator &operator -= (difference_type n) { 2184 it1_ -= n; 2185 it2_ -= n; 2186 return *this; 2187 } 2188 BOOST_UBLAS_INLINE operator -(const const_iterator & it) const2189 difference_type operator - (const const_iterator &it) const { 2190 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 2191 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_); 2192 } 2193 2194 // Dereference 2195 BOOST_UBLAS_INLINE operator *() const2196 const_reference operator * () const { 2197 // FIXME replace find with at_element 2198 return (*this) ().data_ (*it1_, *it2_); 2199 } 2200 BOOST_UBLAS_INLINE operator [](difference_type n) const2201 const_reference operator [] (difference_type n) const { 2202 return *(*this + n); 2203 } 2204 2205 // Index 2206 BOOST_UBLAS_INLINE index() const2207 size_type index () const { 2208 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ()); 2209 } 2210 2211 // Assignment 2212 BOOST_UBLAS_INLINE operator =(const const_iterator & it)2213 const_iterator &operator = (const const_iterator &it) { 2214 container_const_reference<self_type>::assign (&it ()); 2215 it1_ = it.it1_; 2216 it2_ = it.it2_; 2217 return *this; 2218 } 2219 2220 // Comparison 2221 BOOST_UBLAS_INLINE operator ==(const const_iterator & it) const2222 bool operator == (const const_iterator &it) const { 2223 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 2224 return it1_ == it.it1_ && it2_ == it.it2_; 2225 } 2226 BOOST_UBLAS_INLINE operator <(const const_iterator & it) const2227 bool operator < (const const_iterator &it) const { 2228 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 2229 return it1_ < it.it1_ && it2_ < it.it2_; 2230 } 2231 2232 private: 2233 const_subiterator1_type it1_; 2234 const_subiterator2_type it2_; 2235 }; 2236 2237 BOOST_UBLAS_INLINE begin() const2238 const_iterator begin () const { 2239 return find (0); 2240 } 2241 BOOST_UBLAS_INLINE cbegin() const2242 const_iterator cbegin () const { 2243 return begin (); 2244 } 2245 BOOST_UBLAS_INLINE end() const2246 const_iterator end () const { 2247 return find (size ()); 2248 } 2249 BOOST_UBLAS_INLINE cend() const2250 const_iterator cend () const { 2251 return end (); 2252 } 2253 2254 class iterator: 2255 public container_reference<matrix_vector_indirect>, 2256 public iterator_base_traits<typename M::iterator1::iterator_category>::template 2257 iterator_base<iterator, value_type>::type { 2258 public: 2259 // FIXME Iterator can never be different code was: 2260 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category> 2261 BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value )); 2262 2263 typedef typename matrix_vector_indirect::value_type value_type; 2264 typedef typename matrix_vector_indirect::difference_type difference_type; 2265 typedef typename matrix_vector_indirect::reference reference; 2266 typedef typename matrix_vector_indirect::value_type *pointer; 2267 2268 // Construction and destruction 2269 BOOST_UBLAS_INLINE iterator()2270 iterator (): 2271 container_reference<self_type> (), it1_ (), it2_ () {} 2272 BOOST_UBLAS_INLINE iterator(self_type & mvi,const subiterator1_type & it1,const subiterator2_type & it2)2273 iterator (self_type &mvi, const subiterator1_type &it1, const subiterator2_type &it2): 2274 container_reference<self_type> (mvi), it1_ (it1), it2_ (it2) {} 2275 2276 // Arithmetic 2277 BOOST_UBLAS_INLINE operator ++()2278 iterator &operator ++ () { 2279 ++ it1_; 2280 ++ it2_; 2281 return *this; 2282 } 2283 BOOST_UBLAS_INLINE operator --()2284 iterator &operator -- () { 2285 -- it1_; 2286 -- it2_; 2287 return *this; 2288 } 2289 BOOST_UBLAS_INLINE operator +=(difference_type n)2290 iterator &operator += (difference_type n) { 2291 it1_ += n; 2292 it2_ += n; 2293 return *this; 2294 } 2295 BOOST_UBLAS_INLINE operator -=(difference_type n)2296 iterator &operator -= (difference_type n) { 2297 it1_ -= n; 2298 it2_ -= n; 2299 return *this; 2300 } 2301 BOOST_UBLAS_INLINE operator -(const iterator & it) const2302 difference_type operator - (const iterator &it) const { 2303 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 2304 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_); 2305 } 2306 2307 // Dereference 2308 BOOST_UBLAS_INLINE operator *() const2309 reference operator * () const { 2310 // FIXME replace find with at_element 2311 return (*this) ().data_ (*it1_, *it2_); 2312 } 2313 BOOST_UBLAS_INLINE operator [](difference_type n) const2314 reference operator [] (difference_type n) const { 2315 return *(*this + n); 2316 } 2317 2318 // Index 2319 BOOST_UBLAS_INLINE index() const2320 size_type index () const { 2321 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ()); 2322 } 2323 2324 // Assignment 2325 BOOST_UBLAS_INLINE operator =(const iterator & it)2326 iterator &operator = (const iterator &it) { 2327 container_reference<self_type>::assign (&it ()); 2328 it1_ = it.it1_; 2329 it2_ = it.it2_; 2330 return *this; 2331 } 2332 2333 // Comparison 2334 BOOST_UBLAS_INLINE operator ==(const iterator & it) const2335 bool operator == (const iterator &it) const { 2336 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 2337 return it1_ == it.it1_ && it2_ == it.it2_; 2338 } 2339 BOOST_UBLAS_INLINE operator <(const iterator & it) const2340 bool operator < (const iterator &it) const { 2341 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 2342 return it1_ < it.it1_ && it2_ < it.it2_; 2343 } 2344 2345 private: 2346 subiterator1_type it1_; 2347 subiterator2_type it2_; 2348 2349 friend class const_iterator; 2350 }; 2351 2352 BOOST_UBLAS_INLINE begin()2353 iterator begin () { 2354 return find (0); 2355 } 2356 BOOST_UBLAS_INLINE end()2357 iterator end () { 2358 return find (size ()); 2359 } 2360 2361 // Reverse iterator 2362 typedef reverse_iterator_base<const_iterator> const_reverse_iterator; 2363 typedef reverse_iterator_base<iterator> reverse_iterator; 2364 2365 BOOST_UBLAS_INLINE rbegin() const2366 const_reverse_iterator rbegin () const { 2367 return const_reverse_iterator (end ()); 2368 } 2369 BOOST_UBLAS_INLINE crbegin() const2370 const_reverse_iterator crbegin () const { 2371 return rbegin (); 2372 } 2373 BOOST_UBLAS_INLINE rend() const2374 const_reverse_iterator rend () const { 2375 return const_reverse_iterator (begin ()); 2376 } 2377 BOOST_UBLAS_INLINE crend() const2378 const_reverse_iterator crend () const { 2379 return rend (); 2380 } 2381 BOOST_UBLAS_INLINE rbegin()2382 reverse_iterator rbegin () { 2383 return reverse_iterator (end ()); 2384 } 2385 BOOST_UBLAS_INLINE rend()2386 reverse_iterator rend () { 2387 return reverse_iterator (begin ()); 2388 } 2389 2390 private: 2391 matrix_closure_type data_; 2392 indirect_array_type ia1_; 2393 indirect_array_type ia2_; 2394 }; 2395 2396 // Specialize temporary 2397 template <class M, class IA> 2398 struct vector_temporary_traits< matrix_vector_indirect<M,IA> > 2399 : vector_temporary_traits< M > {} ; 2400 template <class M, class IA> 2401 struct vector_temporary_traits< const matrix_vector_indirect<M,IA> > 2402 : vector_temporary_traits< M > {} ; 2403 2404 // Matrix based range class 2405 template<class M> 2406 class matrix_range: 2407 public matrix_expression<matrix_range<M> > { 2408 2409 typedef matrix_range<M> self_type; 2410 public: 2411 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 2412 using matrix_expression<self_type>::operator (); 2413 #endif 2414 typedef M matrix_type; 2415 typedef typename M::size_type size_type; 2416 typedef typename M::difference_type difference_type; 2417 typedef typename M::value_type value_type; 2418 typedef typename M::const_reference const_reference; 2419 typedef typename boost::mpl::if_<boost::is_const<M>, 2420 typename M::const_reference, 2421 typename M::reference>::type reference; 2422 typedef typename boost::mpl::if_<boost::is_const<M>, 2423 typename M::const_closure_type, 2424 typename M::closure_type>::type matrix_closure_type; 2425 typedef basic_range<size_type, difference_type> range_type; 2426 typedef const self_type const_closure_type; 2427 typedef self_type closure_type; 2428 typedef typename storage_restrict_traits<typename M::storage_category, 2429 dense_proxy_tag>::storage_category storage_category; 2430 typedef typename M::orientation_category orientation_category; 2431 2432 // Construction and destruction 2433 BOOST_UBLAS_INLINE matrix_range(matrix_type & data,const range_type & r1,const range_type & r2)2434 matrix_range (matrix_type &data, const range_type &r1, const range_type &r2): 2435 data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) { 2436 // Early checking of preconditions here. 2437 // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () && 2438 // r1_.start () + r1_.size () <= data_.size1 (), bad_index ()); 2439 // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () && 2440 // r2_.start () + r2_.size () <= data_.size2 (), bad_index ()); 2441 } 2442 BOOST_UBLAS_INLINE matrix_range(const matrix_closure_type & data,const range_type & r1,const range_type & r2,int)2443 matrix_range (const matrix_closure_type &data, const range_type &r1, const range_type &r2, int): 2444 data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) { 2445 // Early checking of preconditions here. 2446 // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () && 2447 // r1_.start () + r1_.size () <= data_.size1 (), bad_index ()); 2448 // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () && 2449 // r2_.start () + r2_.size () <= data_.size2 (), bad_index ()); 2450 } 2451 2452 // Accessors 2453 BOOST_UBLAS_INLINE start1() const2454 size_type start1 () const { 2455 return r1_.start (); 2456 } 2457 BOOST_UBLAS_INLINE size1() const2458 size_type size1 () const { 2459 return r1_.size (); 2460 } 2461 BOOST_UBLAS_INLINE start2() const2462 size_type start2() const { 2463 return r2_.start (); 2464 } 2465 BOOST_UBLAS_INLINE size2() const2466 size_type size2 () const { 2467 return r2_.size (); 2468 } 2469 2470 // Storage accessors 2471 BOOST_UBLAS_INLINE data() const2472 const matrix_closure_type &data () const { 2473 return data_; 2474 } 2475 BOOST_UBLAS_INLINE data()2476 matrix_closure_type &data () { 2477 return data_; 2478 } 2479 2480 // Element access 2481 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 2482 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const2483 const_reference operator () (size_type i, size_type j) const { 2484 return data_ (r1_ (i), r2_ (j)); 2485 } 2486 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j)2487 reference operator () (size_type i, size_type j) { 2488 return data_ (r1_ (i), r2_ (j)); 2489 } 2490 #else 2491 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const2492 reference operator () (size_type i, size_type j) const { 2493 return data_ (r1_ (i), r2_ (j)); 2494 } 2495 #endif 2496 2497 // ISSUE can this be done in free project function? 2498 // Although a const function can create a non-const proxy to a non-const object 2499 // Critical is that matrix_type and data_ (vector_closure_type) are const correct 2500 BOOST_UBLAS_INLINE project(const range_type & r1,const range_type & r2) const2501 matrix_range<matrix_type> project (const range_type &r1, const range_type &r2) const { 2502 return matrix_range<matrix_type> (data_, r1_.compose (r1.preprocess (data_.size1 ())), r2_.compose (r2.preprocess (data_.size2 ())), 0); 2503 } 2504 2505 // Assignment 2506 BOOST_UBLAS_INLINE operator =(const matrix_range & mr)2507 matrix_range &operator = (const matrix_range &mr) { 2508 matrix_assign<scalar_assign> (*this, mr); 2509 return *this; 2510 } 2511 BOOST_UBLAS_INLINE assign_temporary(matrix_range & mr)2512 matrix_range &assign_temporary (matrix_range &mr) { 2513 return *this = mr; 2514 } 2515 template<class AE> 2516 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)2517 matrix_range &operator = (const matrix_expression<AE> &ae) { 2518 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae)); 2519 return *this; 2520 } 2521 template<class AE> 2522 BOOST_UBLAS_INLINE assign(const matrix_expression<AE> & ae)2523 matrix_range &assign (const matrix_expression<AE> &ae) { 2524 matrix_assign<scalar_assign> (*this, ae); 2525 return *this; 2526 } 2527 template<class AE> 2528 BOOST_UBLAS_INLINE operator +=(const matrix_expression<AE> & ae)2529 matrix_range& operator += (const matrix_expression<AE> &ae) { 2530 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae)); 2531 return *this; 2532 } 2533 template<class AE> 2534 BOOST_UBLAS_INLINE plus_assign(const matrix_expression<AE> & ae)2535 matrix_range &plus_assign (const matrix_expression<AE> &ae) { 2536 matrix_assign<scalar_plus_assign> (*this, ae); 2537 return *this; 2538 } 2539 template<class AE> 2540 BOOST_UBLAS_INLINE operator -=(const matrix_expression<AE> & ae)2541 matrix_range& operator -= (const matrix_expression<AE> &ae) { 2542 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae)); 2543 return *this; 2544 } 2545 template<class AE> 2546 BOOST_UBLAS_INLINE minus_assign(const matrix_expression<AE> & ae)2547 matrix_range &minus_assign (const matrix_expression<AE> &ae) { 2548 matrix_assign<scalar_minus_assign> (*this, ae); 2549 return *this; 2550 } 2551 template<class AT> 2552 BOOST_UBLAS_INLINE operator *=(const AT & at)2553 matrix_range& operator *= (const AT &at) { 2554 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 2555 return *this; 2556 } 2557 template<class AT> 2558 BOOST_UBLAS_INLINE operator /=(const AT & at)2559 matrix_range& operator /= (const AT &at) { 2560 matrix_assign_scalar<scalar_divides_assign> (*this, at); 2561 return *this; 2562 } 2563 2564 // Closure comparison 2565 BOOST_UBLAS_INLINE same_closure(const matrix_range & mr) const2566 bool same_closure (const matrix_range &mr) const { 2567 return (*this).data_.same_closure (mr.data_); 2568 } 2569 2570 // Comparison 2571 BOOST_UBLAS_INLINE operator ==(const matrix_range & mr) const2572 bool operator == (const matrix_range &mr) const { 2573 return (*this).data_ == (mr.data_) && r1_ == mr.r1_ && r2_ == mr.r2_; 2574 } 2575 2576 // Swapping 2577 BOOST_UBLAS_INLINE swap(matrix_range mr)2578 void swap (matrix_range mr) { 2579 if (this != &mr) { 2580 BOOST_UBLAS_CHECK (size1 () == mr.size1 (), bad_size ()); 2581 BOOST_UBLAS_CHECK (size2 () == mr.size2 (), bad_size ()); 2582 matrix_swap<scalar_swap> (*this, mr); 2583 } 2584 } 2585 BOOST_UBLAS_INLINE swap(matrix_range mr1,matrix_range mr2)2586 friend void swap (matrix_range mr1, matrix_range mr2) { 2587 mr1.swap (mr2); 2588 } 2589 2590 // Iterator types 2591 private: 2592 typedef typename M::const_iterator1 const_subiterator1_type; 2593 typedef typename boost::mpl::if_<boost::is_const<M>, 2594 typename M::const_iterator1, 2595 typename M::iterator1>::type subiterator1_type; 2596 typedef typename M::const_iterator2 const_subiterator2_type; 2597 typedef typename boost::mpl::if_<boost::is_const<M>, 2598 typename M::const_iterator2, 2599 typename M::iterator2>::type subiterator2_type; 2600 2601 public: 2602 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 2603 typedef indexed_iterator1<matrix_range<matrix_type>, 2604 typename subiterator1_type::iterator_category> iterator1; 2605 typedef indexed_iterator2<matrix_range<matrix_type>, 2606 typename subiterator2_type::iterator_category> iterator2; 2607 typedef indexed_const_iterator1<matrix_range<matrix_type>, 2608 typename const_subiterator1_type::iterator_category> const_iterator1; 2609 typedef indexed_const_iterator2<matrix_range<matrix_type>, 2610 typename const_subiterator2_type::iterator_category> const_iterator2; 2611 #else 2612 class const_iterator1; 2613 class iterator1; 2614 class const_iterator2; 2615 class iterator2; 2616 #endif 2617 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 2618 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 2619 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 2620 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 2621 2622 // Element lookup 2623 BOOST_UBLAS_INLINE find1(int rank,size_type i,size_type j) const2624 const_iterator1 find1 (int rank, size_type i, size_type j) const { 2625 const_subiterator1_type it1 (data_.find1 (rank, start1 () + i, start2 () + j)); 2626 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 2627 return const_iterator1 (*this, it1.index1 (), it1.index2 ()); 2628 #else 2629 return const_iterator1 (*this, it1); 2630 #endif 2631 } 2632 BOOST_UBLAS_INLINE find1(int rank,size_type i,size_type j)2633 iterator1 find1 (int rank, size_type i, size_type j) { 2634 subiterator1_type it1 (data_.find1 (rank, start1 () + i, start2 () + j)); 2635 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 2636 return iterator1 (*this, it1.index1 (), it1.index2 ()); 2637 #else 2638 return iterator1 (*this, it1); 2639 #endif 2640 } 2641 BOOST_UBLAS_INLINE find2(int rank,size_type i,size_type j) const2642 const_iterator2 find2 (int rank, size_type i, size_type j) const { 2643 const_subiterator2_type it2 (data_.find2 (rank, start1 () + i, start2 () + j)); 2644 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 2645 return const_iterator2 (*this, it2.index1 (), it2.index2 ()); 2646 #else 2647 return const_iterator2 (*this, it2); 2648 #endif 2649 } 2650 BOOST_UBLAS_INLINE find2(int rank,size_type i,size_type j)2651 iterator2 find2 (int rank, size_type i, size_type j) { 2652 subiterator2_type it2 (data_.find2 (rank, start1 () + i, start2 () + j)); 2653 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 2654 return iterator2 (*this, it2.index1 (), it2.index2 ()); 2655 #else 2656 return iterator2 (*this, it2); 2657 #endif 2658 } 2659 2660 2661 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 2662 class const_iterator1: 2663 public container_const_reference<matrix_range>, 2664 public iterator_base_traits<typename const_subiterator1_type::iterator_category>::template 2665 iterator_base<const_iterator1, value_type>::type { 2666 public: 2667 typedef typename const_subiterator1_type::value_type value_type; 2668 typedef typename const_subiterator1_type::difference_type difference_type; 2669 typedef typename const_subiterator1_type::reference reference; 2670 typedef typename const_subiterator1_type::pointer pointer; 2671 typedef const_iterator2 dual_iterator_type; 2672 typedef const_reverse_iterator2 dual_reverse_iterator_type; 2673 2674 // Construction and destruction 2675 BOOST_UBLAS_INLINE const_iterator1()2676 const_iterator1 (): 2677 container_const_reference<self_type> (), it_ () {} 2678 BOOST_UBLAS_INLINE const_iterator1(const self_type & mr,const const_subiterator1_type & it)2679 const_iterator1 (const self_type &mr, const const_subiterator1_type &it): 2680 container_const_reference<self_type> (mr), it_ (it) {} 2681 BOOST_UBLAS_INLINE const_iterator1(const iterator1 & it)2682 const_iterator1 (const iterator1 &it): 2683 container_const_reference<self_type> (it ()), it_ (it.it_) {} 2684 2685 // Arithmetic 2686 BOOST_UBLAS_INLINE operator ++()2687 const_iterator1 &operator ++ () { 2688 ++ it_; 2689 return *this; 2690 } 2691 BOOST_UBLAS_INLINE operator --()2692 const_iterator1 &operator -- () { 2693 -- it_; 2694 return *this; 2695 } 2696 BOOST_UBLAS_INLINE operator +=(difference_type n)2697 const_iterator1 &operator += (difference_type n) { 2698 it_ += n; 2699 return *this; 2700 } 2701 BOOST_UBLAS_INLINE operator -=(difference_type n)2702 const_iterator1 &operator -= (difference_type n) { 2703 it_ -= n; 2704 return *this; 2705 } 2706 BOOST_UBLAS_INLINE operator -(const const_iterator1 & it) const2707 difference_type operator - (const const_iterator1 &it) const { 2708 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 2709 return it_ - it.it_; 2710 } 2711 2712 // Dereference 2713 BOOST_UBLAS_INLINE operator *() const2714 const_reference operator * () const { 2715 return *it_; 2716 } 2717 BOOST_UBLAS_INLINE operator [](difference_type n) const2718 const_reference operator [] (difference_type n) const { 2719 return *(*this + n); 2720 } 2721 2722 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 2723 BOOST_UBLAS_INLINE 2724 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2725 typename self_type:: 2726 #endif begin() const2727 const_iterator2 begin () const { 2728 const self_type &mr = (*this) (); 2729 return mr.find2 (1, index1 (), 0); 2730 } 2731 BOOST_UBLAS_INLINE 2732 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2733 typename self_type:: 2734 #endif cbegin() const2735 const_iterator2 cbegin () const { 2736 return begin (); 2737 } 2738 BOOST_UBLAS_INLINE 2739 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2740 typename self_type:: 2741 #endif end() const2742 const_iterator2 end () const { 2743 const self_type &mr = (*this) (); 2744 return mr.find2 (1, index1 (), mr.size2 ()); 2745 } 2746 BOOST_UBLAS_INLINE 2747 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2748 typename self_type:: 2749 #endif cend() const2750 const_iterator2 cend () const { 2751 return end (); 2752 } 2753 BOOST_UBLAS_INLINE 2754 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2755 typename self_type:: 2756 #endif rbegin() const2757 const_reverse_iterator2 rbegin () const { 2758 return const_reverse_iterator2 (end ()); 2759 } 2760 BOOST_UBLAS_INLINE 2761 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2762 typename self_type:: 2763 #endif crbegin() const2764 const_reverse_iterator2 crbegin () const { 2765 return rbegin (); 2766 } 2767 BOOST_UBLAS_INLINE 2768 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2769 typename self_type:: 2770 #endif rend() const2771 const_reverse_iterator2 rend () const { 2772 return const_reverse_iterator2 (begin ()); 2773 } 2774 BOOST_UBLAS_INLINE 2775 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2776 typename self_type:: 2777 #endif crend() const2778 const_reverse_iterator2 crend () const { 2779 return rend (); 2780 } 2781 #endif 2782 2783 // Indices 2784 BOOST_UBLAS_INLINE index1() const2785 size_type index1 () const { 2786 return it_.index1 () - (*this) ().start1 (); 2787 } 2788 BOOST_UBLAS_INLINE index2() const2789 size_type index2 () const { 2790 return it_.index2 () - (*this) ().start2 (); 2791 } 2792 2793 // Assignment 2794 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)2795 const_iterator1 &operator = (const const_iterator1 &it) { 2796 container_const_reference<self_type>::assign (&it ()); 2797 it_ = it.it_; 2798 return *this; 2799 } 2800 2801 // Comparison 2802 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const2803 bool operator == (const const_iterator1 &it) const { 2804 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 2805 return it_ == it.it_; 2806 } 2807 BOOST_UBLAS_INLINE operator <(const const_iterator1 & it) const2808 bool operator < (const const_iterator1 &it) const { 2809 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 2810 return it_ < it.it_; 2811 } 2812 2813 private: 2814 const_subiterator1_type it_; 2815 }; 2816 #endif 2817 2818 BOOST_UBLAS_INLINE begin1() const2819 const_iterator1 begin1 () const { 2820 return find1 (0, 0, 0); 2821 } 2822 BOOST_UBLAS_INLINE cbegin1() const2823 const_iterator1 cbegin1 () const { 2824 return begin1 (); 2825 } 2826 BOOST_UBLAS_INLINE end1() const2827 const_iterator1 end1 () const { 2828 return find1 (0, size1 (), 0); 2829 } 2830 BOOST_UBLAS_INLINE cend1() const2831 const_iterator1 cend1 () const { 2832 return end1 (); 2833 } 2834 2835 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 2836 class iterator1: 2837 public container_reference<matrix_range>, 2838 public iterator_base_traits<typename subiterator1_type::iterator_category>::template 2839 iterator_base<iterator1, value_type>::type { 2840 public: 2841 typedef typename subiterator1_type::value_type value_type; 2842 typedef typename subiterator1_type::difference_type difference_type; 2843 typedef typename subiterator1_type::reference reference; 2844 typedef typename subiterator1_type::pointer pointer; 2845 typedef iterator2 dual_iterator_type; 2846 typedef reverse_iterator2 dual_reverse_iterator_type; 2847 2848 // Construction and destruction 2849 BOOST_UBLAS_INLINE iterator1()2850 iterator1 (): 2851 container_reference<self_type> (), it_ () {} 2852 BOOST_UBLAS_INLINE iterator1(self_type & mr,const subiterator1_type & it)2853 iterator1 (self_type &mr, const subiterator1_type &it): 2854 container_reference<self_type> (mr), it_ (it) {} 2855 2856 // Arithmetic 2857 BOOST_UBLAS_INLINE operator ++()2858 iterator1 &operator ++ () { 2859 ++ it_; 2860 return *this; 2861 } 2862 BOOST_UBLAS_INLINE operator --()2863 iterator1 &operator -- () { 2864 -- it_; 2865 return *this; 2866 } 2867 BOOST_UBLAS_INLINE operator +=(difference_type n)2868 iterator1 &operator += (difference_type n) { 2869 it_ += n; 2870 return *this; 2871 } 2872 BOOST_UBLAS_INLINE operator -=(difference_type n)2873 iterator1 &operator -= (difference_type n) { 2874 it_ -= n; 2875 return *this; 2876 } 2877 BOOST_UBLAS_INLINE operator -(const iterator1 & it) const2878 difference_type operator - (const iterator1 &it) const { 2879 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 2880 return it_ - it.it_; 2881 } 2882 2883 // Dereference 2884 BOOST_UBLAS_INLINE operator *() const2885 reference operator * () const { 2886 return *it_; 2887 } 2888 BOOST_UBLAS_INLINE operator [](difference_type n) const2889 reference operator [] (difference_type n) const { 2890 return *(*this + n); 2891 } 2892 2893 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 2894 BOOST_UBLAS_INLINE 2895 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2896 typename self_type:: 2897 #endif begin() const2898 iterator2 begin () const { 2899 self_type &mr = (*this) (); 2900 return mr.find2 (1, index1 (), 0); 2901 } 2902 BOOST_UBLAS_INLINE 2903 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2904 typename self_type:: 2905 #endif end() const2906 iterator2 end () const { 2907 self_type &mr = (*this) (); 2908 return mr.find2 (1, index1 (), mr.size2 ()); 2909 } 2910 BOOST_UBLAS_INLINE 2911 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2912 typename self_type:: 2913 #endif rbegin() const2914 reverse_iterator2 rbegin () const { 2915 return reverse_iterator2 (end ()); 2916 } 2917 BOOST_UBLAS_INLINE 2918 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2919 typename self_type:: 2920 #endif rend() const2921 reverse_iterator2 rend () const { 2922 return reverse_iterator2 (begin ()); 2923 } 2924 #endif 2925 2926 // Indices 2927 BOOST_UBLAS_INLINE index1() const2928 size_type index1 () const { 2929 return it_.index1 () - (*this) ().start1 (); 2930 } 2931 BOOST_UBLAS_INLINE index2() const2932 size_type index2 () const { 2933 return it_.index2 () - (*this) ().start2 (); 2934 } 2935 2936 // Assignment 2937 BOOST_UBLAS_INLINE operator =(const iterator1 & it)2938 iterator1 &operator = (const iterator1 &it) { 2939 container_reference<self_type>::assign (&it ()); 2940 it_ = it.it_; 2941 return *this; 2942 } 2943 2944 // Comparison 2945 BOOST_UBLAS_INLINE operator ==(const iterator1 & it) const2946 bool operator == (const iterator1 &it) const { 2947 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 2948 return it_ == it.it_; 2949 } 2950 BOOST_UBLAS_INLINE operator <(const iterator1 & it) const2951 bool operator < (const iterator1 &it) const { 2952 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 2953 return it_ < it.it_; 2954 } 2955 2956 private: 2957 subiterator1_type it_; 2958 2959 friend class const_iterator1; 2960 }; 2961 #endif 2962 2963 BOOST_UBLAS_INLINE begin1()2964 iterator1 begin1 () { 2965 return find1 (0, 0, 0); 2966 } 2967 BOOST_UBLAS_INLINE end1()2968 iterator1 end1 () { 2969 return find1 (0, size1 (), 0); 2970 } 2971 2972 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 2973 class const_iterator2: 2974 public container_const_reference<matrix_range>, 2975 public iterator_base_traits<typename const_subiterator2_type::iterator_category>::template 2976 iterator_base<const_iterator2, value_type>::type { 2977 public: 2978 typedef typename const_subiterator2_type::value_type value_type; 2979 typedef typename const_subiterator2_type::difference_type difference_type; 2980 typedef typename const_subiterator2_type::reference reference; 2981 typedef typename const_subiterator2_type::pointer pointer; 2982 typedef const_iterator1 dual_iterator_type; 2983 typedef const_reverse_iterator1 dual_reverse_iterator_type; 2984 2985 // Construction and destruction 2986 BOOST_UBLAS_INLINE const_iterator2()2987 const_iterator2 (): 2988 container_const_reference<self_type> (), it_ () {} 2989 BOOST_UBLAS_INLINE const_iterator2(const self_type & mr,const const_subiterator2_type & it)2990 const_iterator2 (const self_type &mr, const const_subiterator2_type &it): 2991 container_const_reference<self_type> (mr), it_ (it) {} 2992 BOOST_UBLAS_INLINE const_iterator2(const iterator2 & it)2993 const_iterator2 (const iterator2 &it): 2994 container_const_reference<self_type> (it ()), it_ (it.it_) {} 2995 2996 // Arithmetic 2997 BOOST_UBLAS_INLINE operator ++()2998 const_iterator2 &operator ++ () { 2999 ++ it_; 3000 return *this; 3001 } 3002 BOOST_UBLAS_INLINE operator --()3003 const_iterator2 &operator -- () { 3004 -- it_; 3005 return *this; 3006 } 3007 BOOST_UBLAS_INLINE operator +=(difference_type n)3008 const_iterator2 &operator += (difference_type n) { 3009 it_ += n; 3010 return *this; 3011 } 3012 BOOST_UBLAS_INLINE operator -=(difference_type n)3013 const_iterator2 &operator -= (difference_type n) { 3014 it_ -= n; 3015 return *this; 3016 } 3017 BOOST_UBLAS_INLINE operator -(const const_iterator2 & it) const3018 difference_type operator - (const const_iterator2 &it) const { 3019 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 3020 return it_ - it.it_; 3021 } 3022 3023 // Dereference 3024 BOOST_UBLAS_INLINE operator *() const3025 const_reference operator * () const { 3026 return *it_; 3027 } 3028 BOOST_UBLAS_INLINE operator [](difference_type n) const3029 const_reference operator [] (difference_type n) const { 3030 return *(*this + n); 3031 } 3032 3033 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 3034 BOOST_UBLAS_INLINE 3035 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3036 typename self_type:: 3037 #endif begin() const3038 const_iterator1 begin () const { 3039 const self_type &mr = (*this) (); 3040 return mr.find1 (1, 0, index2 ()); 3041 } 3042 BOOST_UBLAS_INLINE 3043 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3044 typename self_type:: 3045 #endif cbegin() const3046 const_iterator1 cbegin () const { 3047 return begin (); 3048 } 3049 BOOST_UBLAS_INLINE 3050 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3051 typename self_type:: 3052 #endif end() const3053 const_iterator1 end () const { 3054 const self_type &mr = (*this) (); 3055 return mr.find1 (1, mr.size1 (), index2 ()); 3056 } 3057 BOOST_UBLAS_INLINE 3058 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3059 typename self_type:: 3060 #endif cend() const3061 const_iterator1 cend () const { 3062 return end (); 3063 } 3064 BOOST_UBLAS_INLINE 3065 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3066 typename self_type:: 3067 #endif rbegin() const3068 const_reverse_iterator1 rbegin () const { 3069 return const_reverse_iterator1 (end ()); 3070 } 3071 BOOST_UBLAS_INLINE 3072 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3073 typename self_type:: 3074 #endif crbegin() const3075 const_reverse_iterator1 crbegin () const { 3076 return rbegin (); 3077 } 3078 BOOST_UBLAS_INLINE 3079 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3080 typename self_type:: 3081 #endif rend() const3082 const_reverse_iterator1 rend () const { 3083 return const_reverse_iterator1 (begin ()); 3084 } 3085 BOOST_UBLAS_INLINE 3086 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3087 typename self_type:: 3088 #endif crend() const3089 const_reverse_iterator1 crend () const { 3090 return rend (); 3091 } 3092 #endif 3093 3094 // Indices 3095 BOOST_UBLAS_INLINE index1() const3096 size_type index1 () const { 3097 return it_.index1 () - (*this) ().start1 (); 3098 } 3099 BOOST_UBLAS_INLINE index2() const3100 size_type index2 () const { 3101 return it_.index2 () - (*this) ().start2 (); 3102 } 3103 3104 // Assignment 3105 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)3106 const_iterator2 &operator = (const const_iterator2 &it) { 3107 container_const_reference<self_type>::assign (&it ()); 3108 it_ = it.it_; 3109 return *this; 3110 } 3111 3112 // Comparison 3113 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const3114 bool operator == (const const_iterator2 &it) const { 3115 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 3116 return it_ == it.it_; 3117 } 3118 BOOST_UBLAS_INLINE operator <(const const_iterator2 & it) const3119 bool operator < (const const_iterator2 &it) const { 3120 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 3121 return it_ < it.it_; 3122 } 3123 3124 private: 3125 const_subiterator2_type it_; 3126 }; 3127 #endif 3128 3129 BOOST_UBLAS_INLINE begin2() const3130 const_iterator2 begin2 () const { 3131 return find2 (0, 0, 0); 3132 } 3133 BOOST_UBLAS_INLINE cbegin2() const3134 const_iterator2 cbegin2 () const { 3135 return begin2 (); 3136 } 3137 BOOST_UBLAS_INLINE end2() const3138 const_iterator2 end2 () const { 3139 return find2 (0, 0, size2 ()); 3140 } 3141 BOOST_UBLAS_INLINE cend2() const3142 const_iterator2 cend2 () const { 3143 return end2 (); 3144 } 3145 3146 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 3147 class iterator2: 3148 public container_reference<matrix_range>, 3149 public iterator_base_traits<typename subiterator2_type::iterator_category>::template 3150 iterator_base<iterator2, value_type>::type { 3151 public: 3152 typedef typename subiterator2_type::value_type value_type; 3153 typedef typename subiterator2_type::difference_type difference_type; 3154 typedef typename subiterator2_type::reference reference; 3155 typedef typename subiterator2_type::pointer pointer; 3156 typedef iterator1 dual_iterator_type; 3157 typedef reverse_iterator1 dual_reverse_iterator_type; 3158 3159 // Construction and destruction 3160 BOOST_UBLAS_INLINE iterator2()3161 iterator2 (): 3162 container_reference<self_type> (), it_ () {} 3163 BOOST_UBLAS_INLINE iterator2(self_type & mr,const subiterator2_type & it)3164 iterator2 (self_type &mr, const subiterator2_type &it): 3165 container_reference<self_type> (mr), it_ (it) {} 3166 3167 // Arithmetic 3168 BOOST_UBLAS_INLINE operator ++()3169 iterator2 &operator ++ () { 3170 ++ it_; 3171 return *this; 3172 } 3173 BOOST_UBLAS_INLINE operator --()3174 iterator2 &operator -- () { 3175 -- it_; 3176 return *this; 3177 } 3178 BOOST_UBLAS_INLINE operator +=(difference_type n)3179 iterator2 &operator += (difference_type n) { 3180 it_ += n; 3181 return *this; 3182 } 3183 BOOST_UBLAS_INLINE operator -=(difference_type n)3184 iterator2 &operator -= (difference_type n) { 3185 it_ -= n; 3186 return *this; 3187 } 3188 BOOST_UBLAS_INLINE operator -(const iterator2 & it) const3189 difference_type operator - (const iterator2 &it) const { 3190 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 3191 return it_ - it.it_; 3192 } 3193 3194 // Dereference 3195 BOOST_UBLAS_INLINE operator *() const3196 reference operator * () const { 3197 return *it_; 3198 } 3199 BOOST_UBLAS_INLINE operator [](difference_type n) const3200 reference operator [] (difference_type n) const { 3201 return *(*this + n); 3202 } 3203 3204 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 3205 BOOST_UBLAS_INLINE 3206 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3207 typename self_type:: 3208 #endif begin() const3209 iterator1 begin () const { 3210 self_type &mr = (*this) (); 3211 return mr.find1 (1, 0, index2 ()); 3212 } 3213 BOOST_UBLAS_INLINE 3214 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3215 typename self_type:: 3216 #endif end() const3217 iterator1 end () const { 3218 self_type &mr = (*this) (); 3219 return mr.find1 (1, mr.size1 (), index2 ()); 3220 } 3221 BOOST_UBLAS_INLINE 3222 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3223 typename self_type:: 3224 #endif rbegin() const3225 reverse_iterator1 rbegin () const { 3226 return reverse_iterator1 (end ()); 3227 } 3228 BOOST_UBLAS_INLINE 3229 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3230 typename self_type:: 3231 #endif rend() const3232 reverse_iterator1 rend () const { 3233 return reverse_iterator1 (begin ()); 3234 } 3235 #endif 3236 3237 // Indices 3238 BOOST_UBLAS_INLINE index1() const3239 size_type index1 () const { 3240 return it_.index1 () - (*this) ().start1 (); 3241 } 3242 BOOST_UBLAS_INLINE index2() const3243 size_type index2 () const { 3244 return it_.index2 () - (*this) ().start2 (); 3245 } 3246 3247 // Assignment 3248 BOOST_UBLAS_INLINE operator =(const iterator2 & it)3249 iterator2 &operator = (const iterator2 &it) { 3250 container_reference<self_type>::assign (&it ()); 3251 it_ = it.it_; 3252 return *this; 3253 } 3254 3255 // Comparison 3256 BOOST_UBLAS_INLINE operator ==(const iterator2 & it) const3257 bool operator == (const iterator2 &it) const { 3258 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 3259 return it_ == it.it_; 3260 } 3261 BOOST_UBLAS_INLINE operator <(const iterator2 & it) const3262 bool operator < (const iterator2 &it) const { 3263 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 3264 return it_ < it.it_; 3265 } 3266 3267 private: 3268 subiterator2_type it_; 3269 3270 friend class const_iterator2; 3271 }; 3272 #endif 3273 3274 BOOST_UBLAS_INLINE begin2()3275 iterator2 begin2 () { 3276 return find2 (0, 0, 0); 3277 } 3278 BOOST_UBLAS_INLINE end2()3279 iterator2 end2 () { 3280 return find2 (0, 0, size2 ()); 3281 } 3282 3283 // Reverse iterators 3284 3285 BOOST_UBLAS_INLINE rbegin1() const3286 const_reverse_iterator1 rbegin1 () const { 3287 return const_reverse_iterator1 (end1 ()); 3288 } 3289 BOOST_UBLAS_INLINE crbegin1() const3290 const_reverse_iterator1 crbegin1 () const { 3291 return rbegin1 (); 3292 } 3293 BOOST_UBLAS_INLINE rend1() const3294 const_reverse_iterator1 rend1 () const { 3295 return const_reverse_iterator1 (begin1 ()); 3296 } 3297 BOOST_UBLAS_INLINE crend1() const3298 const_reverse_iterator1 crend1 () const { 3299 return rend1 (); 3300 } 3301 3302 BOOST_UBLAS_INLINE rbegin1()3303 reverse_iterator1 rbegin1 () { 3304 return reverse_iterator1 (end1 ()); 3305 } 3306 BOOST_UBLAS_INLINE rend1()3307 reverse_iterator1 rend1 () { 3308 return reverse_iterator1 (begin1 ()); 3309 } 3310 3311 BOOST_UBLAS_INLINE rbegin2() const3312 const_reverse_iterator2 rbegin2 () const { 3313 return const_reverse_iterator2 (end2 ()); 3314 } 3315 BOOST_UBLAS_INLINE crbegin2() const3316 const_reverse_iterator2 crbegin2 () const { 3317 return rbegin2 (); 3318 } 3319 BOOST_UBLAS_INLINE rend2() const3320 const_reverse_iterator2 rend2 () const { 3321 return const_reverse_iterator2 (begin2 ()); 3322 } 3323 BOOST_UBLAS_INLINE crend2() const3324 const_reverse_iterator2 crend2 () const { 3325 return rend2 (); 3326 } 3327 3328 BOOST_UBLAS_INLINE rbegin2()3329 reverse_iterator2 rbegin2 () { 3330 return reverse_iterator2 (end2 ()); 3331 } 3332 BOOST_UBLAS_INLINE rend2()3333 reverse_iterator2 rend2 () { 3334 return reverse_iterator2 (begin2 ()); 3335 } 3336 3337 private: 3338 matrix_closure_type data_; 3339 range_type r1_; 3340 range_type r2_; 3341 }; 3342 3343 // Simple Projections 3344 template<class M> 3345 BOOST_UBLAS_INLINE subrange(M & data,typename M::size_type start1,typename M::size_type stop1,typename M::size_type start2,typename M::size_type stop2)3346 matrix_range<M> subrange (M &data, typename M::size_type start1, typename M::size_type stop1, typename M::size_type start2, typename M::size_type stop2) { 3347 typedef basic_range<typename M::size_type, typename M::difference_type> range_type; 3348 return matrix_range<M> (data, range_type (start1, stop1), range_type (start2, stop2)); 3349 } 3350 template<class M> 3351 BOOST_UBLAS_INLINE subrange(const M & data,typename M::size_type start1,typename M::size_type stop1,typename M::size_type start2,typename M::size_type stop2)3352 matrix_range<const M> subrange (const M &data, typename M::size_type start1, typename M::size_type stop1, typename M::size_type start2, typename M::size_type stop2) { 3353 typedef basic_range<typename M::size_type, typename M::difference_type> range_type; 3354 return matrix_range<const M> (data, range_type (start1, stop1), range_type (start2, stop2)); 3355 } 3356 3357 // Generic Projections 3358 template<class M> 3359 BOOST_UBLAS_INLINE project(M & data,const typename matrix_range<M>::range_type & r1,const typename matrix_range<M>::range_type & r2)3360 matrix_range<M> project (M &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) { 3361 return matrix_range<M> (data, r1, r2); 3362 } 3363 template<class M> 3364 BOOST_UBLAS_INLINE project(const M & data,const typename matrix_range<M>::range_type & r1,const typename matrix_range<M>::range_type & r2)3365 const matrix_range<const M> project (const M &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) { 3366 // ISSUE was: return matrix_range<M> (const_cast<M &> (data), r1, r2); 3367 return matrix_range<const M> (data, r1, r2); 3368 } 3369 template<class M> 3370 BOOST_UBLAS_INLINE project(matrix_range<M> & data,const typename matrix_range<M>::range_type & r1,const typename matrix_range<M>::range_type & r2)3371 matrix_range<M> project (matrix_range<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) { 3372 return data.project (r1, r2); 3373 } 3374 template<class M> 3375 BOOST_UBLAS_INLINE project(const matrix_range<M> & data,const typename matrix_range<M>::range_type & r1,const typename matrix_range<M>::range_type & r2)3376 const matrix_range<M> project (const matrix_range<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) { 3377 return data.project (r1, r2); 3378 } 3379 3380 // Specialization of temporary_traits 3381 template <class M> 3382 struct matrix_temporary_traits< matrix_range<M> > 3383 : matrix_temporary_traits< M > {} ; 3384 template <class M> 3385 struct matrix_temporary_traits< const matrix_range<M> > 3386 : matrix_temporary_traits< M > {} ; 3387 3388 template <class M> 3389 struct vector_temporary_traits< matrix_range<M> > 3390 : vector_temporary_traits< M > {} ; 3391 template <class M> 3392 struct vector_temporary_traits< const matrix_range<M> > 3393 : vector_temporary_traits< M > {} ; 3394 3395 // Matrix based slice class 3396 template<class M> 3397 class matrix_slice: 3398 public matrix_expression<matrix_slice<M> > { 3399 3400 typedef matrix_slice<M> self_type; 3401 public: 3402 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 3403 using matrix_expression<self_type>::operator (); 3404 #endif 3405 typedef M matrix_type; 3406 typedef typename M::size_type size_type; 3407 typedef typename M::difference_type difference_type; 3408 typedef typename M::value_type value_type; 3409 typedef typename M::const_reference const_reference; 3410 typedef typename boost::mpl::if_<boost::is_const<M>, 3411 typename M::const_reference, 3412 typename M::reference>::type reference; 3413 typedef typename boost::mpl::if_<boost::is_const<M>, 3414 typename M::const_closure_type, 3415 typename M::closure_type>::type matrix_closure_type; 3416 typedef basic_range<size_type, difference_type> range_type; 3417 typedef basic_slice<size_type, difference_type> slice_type; 3418 typedef const self_type const_closure_type; 3419 typedef self_type closure_type; 3420 typedef typename storage_restrict_traits<typename M::storage_category, 3421 dense_proxy_tag>::storage_category storage_category; 3422 typedef typename M::orientation_category orientation_category; 3423 3424 // Construction and destruction 3425 BOOST_UBLAS_INLINE matrix_slice(matrix_type & data,const slice_type & s1,const slice_type & s2)3426 matrix_slice (matrix_type &data, const slice_type &s1, const slice_type &s2): 3427 data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) { 3428 // Early checking of preconditions here. 3429 // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () && 3430 // s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ()); 3431 // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () && 3432 // s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ()); 3433 } 3434 BOOST_UBLAS_INLINE matrix_slice(const matrix_closure_type & data,const slice_type & s1,const slice_type & s2,int)3435 matrix_slice (const matrix_closure_type &data, const slice_type &s1, const slice_type &s2, int): 3436 data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) { 3437 // Early checking of preconditions. 3438 // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () && 3439 // s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ()); 3440 // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () && 3441 // s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ()); 3442 } 3443 3444 // Accessors 3445 BOOST_UBLAS_INLINE start1() const3446 size_type start1 () const { 3447 return s1_.start (); 3448 } 3449 BOOST_UBLAS_INLINE start2() const3450 size_type start2 () const { 3451 return s2_.start (); 3452 } 3453 BOOST_UBLAS_INLINE stride1() const3454 difference_type stride1 () const { 3455 return s1_.stride (); 3456 } 3457 BOOST_UBLAS_INLINE stride2() const3458 difference_type stride2 () const { 3459 return s2_.stride (); 3460 } 3461 BOOST_UBLAS_INLINE size1() const3462 size_type size1 () const { 3463 return s1_.size (); 3464 } 3465 BOOST_UBLAS_INLINE size2() const3466 size_type size2 () const { 3467 return s2_.size (); 3468 } 3469 3470 // Storage accessors 3471 BOOST_UBLAS_INLINE data() const3472 const matrix_closure_type &data () const { 3473 return data_; 3474 } 3475 BOOST_UBLAS_INLINE data()3476 matrix_closure_type &data () { 3477 return data_; 3478 } 3479 3480 // Element access 3481 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 3482 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const3483 const_reference operator () (size_type i, size_type j) const { 3484 return data_ (s1_ (i), s2_ (j)); 3485 } 3486 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j)3487 reference operator () (size_type i, size_type j) { 3488 return data_ (s1_ (i), s2_ (j)); 3489 } 3490 #else 3491 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const3492 reference operator () (size_type i, size_type j) const { 3493 return data_ (s1_ (i), s2_ (j)); 3494 } 3495 #endif 3496 3497 // ISSUE can this be done in free project function? 3498 // Although a const function can create a non-const proxy to a non-const object 3499 // Critical is that matrix_type and data_ (vector_closure_type) are const correct 3500 BOOST_UBLAS_INLINE project(const range_type & r1,const range_type & r2) const3501 matrix_slice<matrix_type> project (const range_type &r1, const range_type &r2) const { 3502 return matrix_slice<matrix_type> (data_, s1_.compose (r1.preprocess (data_.size1 ())), s2_.compose (r2.preprocess (data_.size2 ())), 0); 3503 } 3504 BOOST_UBLAS_INLINE project(const slice_type & s1,const slice_type & s2) const3505 matrix_slice<matrix_type> project (const slice_type &s1, const slice_type &s2) const { 3506 return matrix_slice<matrix_type> (data_, s1_.compose (s1.preprocess (data_.size1 ())), s2_.compose (s2.preprocess (data_.size2 ())), 0); 3507 } 3508 3509 // Assignment 3510 BOOST_UBLAS_INLINE operator =(const matrix_slice & ms)3511 matrix_slice &operator = (const matrix_slice &ms) { 3512 matrix_assign<scalar_assign> (*this, ms); 3513 return *this; 3514 } 3515 BOOST_UBLAS_INLINE assign_temporary(matrix_slice & ms)3516 matrix_slice &assign_temporary (matrix_slice &ms) { 3517 return *this = ms; 3518 } 3519 template<class AE> 3520 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)3521 matrix_slice &operator = (const matrix_expression<AE> &ae) { 3522 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae)); 3523 return *this; 3524 } 3525 template<class AE> 3526 BOOST_UBLAS_INLINE assign(const matrix_expression<AE> & ae)3527 matrix_slice &assign (const matrix_expression<AE> &ae) { 3528 matrix_assign<scalar_assign> (*this, ae); 3529 return *this; 3530 } 3531 template<class AE> 3532 BOOST_UBLAS_INLINE operator +=(const matrix_expression<AE> & ae)3533 matrix_slice& operator += (const matrix_expression<AE> &ae) { 3534 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae)); 3535 return *this; 3536 } 3537 template<class AE> 3538 BOOST_UBLAS_INLINE plus_assign(const matrix_expression<AE> & ae)3539 matrix_slice &plus_assign (const matrix_expression<AE> &ae) { 3540 matrix_assign<scalar_plus_assign> (*this, ae); 3541 return *this; 3542 } 3543 template<class AE> 3544 BOOST_UBLAS_INLINE operator -=(const matrix_expression<AE> & ae)3545 matrix_slice& operator -= (const matrix_expression<AE> &ae) { 3546 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae)); 3547 return *this; 3548 } 3549 template<class AE> 3550 BOOST_UBLAS_INLINE minus_assign(const matrix_expression<AE> & ae)3551 matrix_slice &minus_assign (const matrix_expression<AE> &ae) { 3552 matrix_assign<scalar_minus_assign> (*this, ae); 3553 return *this; 3554 } 3555 template<class AT> 3556 BOOST_UBLAS_INLINE operator *=(const AT & at)3557 matrix_slice& operator *= (const AT &at) { 3558 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 3559 return *this; 3560 } 3561 template<class AT> 3562 BOOST_UBLAS_INLINE operator /=(const AT & at)3563 matrix_slice& operator /= (const AT &at) { 3564 matrix_assign_scalar<scalar_divides_assign> (*this, at); 3565 return *this; 3566 } 3567 3568 // Closure comparison 3569 BOOST_UBLAS_INLINE same_closure(const matrix_slice & ms) const3570 bool same_closure (const matrix_slice &ms) const { 3571 return (*this).data_.same_closure (ms.data_); 3572 } 3573 3574 // Comparison 3575 BOOST_UBLAS_INLINE operator ==(const matrix_slice & ms) const3576 bool operator == (const matrix_slice &ms) const { 3577 return (*this).data_ == ms.data_ && s1_ == ms.s1_ && s2_ == ms.s2_; 3578 } 3579 3580 // Swapping 3581 BOOST_UBLAS_INLINE swap(matrix_slice ms)3582 void swap (matrix_slice ms) { 3583 if (this != &ms) { 3584 BOOST_UBLAS_CHECK (size1 () == ms.size1 (), bad_size ()); 3585 BOOST_UBLAS_CHECK (size2 () == ms.size2 (), bad_size ()); 3586 matrix_swap<scalar_swap> (*this, ms); 3587 } 3588 } 3589 BOOST_UBLAS_INLINE swap(matrix_slice ms1,matrix_slice ms2)3590 friend void swap (matrix_slice ms1, matrix_slice ms2) { 3591 ms1.swap (ms2); 3592 } 3593 3594 // Iterator types 3595 private: 3596 // Use slice as an index - FIXME this fails for packed assignment 3597 typedef typename slice_type::const_iterator const_subiterator1_type; 3598 typedef typename slice_type::const_iterator subiterator1_type; 3599 typedef typename slice_type::const_iterator const_subiterator2_type; 3600 typedef typename slice_type::const_iterator subiterator2_type; 3601 3602 public: 3603 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 3604 typedef indexed_iterator1<matrix_slice<matrix_type>, 3605 typename matrix_type::iterator1::iterator_category> iterator1; 3606 typedef indexed_iterator2<matrix_slice<matrix_type>, 3607 typename matrix_type::iterator2::iterator_category> iterator2; 3608 typedef indexed_const_iterator1<matrix_slice<matrix_type>, 3609 typename matrix_type::const_iterator1::iterator_category> const_iterator1; 3610 typedef indexed_const_iterator2<matrix_slice<matrix_type>, 3611 typename matrix_type::const_iterator2::iterator_category> const_iterator2; 3612 #else 3613 class const_iterator1; 3614 class iterator1; 3615 class const_iterator2; 3616 class iterator2; 3617 #endif 3618 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 3619 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 3620 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 3621 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 3622 3623 // Element lookup 3624 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j) const3625 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const { 3626 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 3627 return const_iterator1 (*this, i, j); 3628 #else 3629 return const_iterator1 (*this, s1_.begin () + i, s2_.begin () + j); 3630 #endif 3631 } 3632 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j)3633 iterator1 find1 (int /* rank */, size_type i, size_type j) { 3634 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 3635 return iterator1 (*this, i, j); 3636 #else 3637 return iterator1 (*this, s1_.begin () + i, s2_.begin () + j); 3638 #endif 3639 } 3640 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j) const3641 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const { 3642 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 3643 return const_iterator2 (*this, i, j); 3644 #else 3645 return const_iterator2 (*this, s1_.begin () + i, s2_.begin () + j); 3646 #endif 3647 } 3648 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j)3649 iterator2 find2 (int /* rank */, size_type i, size_type j) { 3650 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 3651 return iterator2 (*this, i, j); 3652 #else 3653 return iterator2 (*this, s1_.begin () + i, s2_.begin () + j); 3654 #endif 3655 } 3656 3657 // Iterators simply are indices. 3658 3659 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 3660 class const_iterator1: 3661 public container_const_reference<matrix_slice>, 3662 public iterator_base_traits<typename M::const_iterator1::iterator_category>::template 3663 iterator_base<const_iterator1, value_type>::type { 3664 public: 3665 typedef typename M::const_iterator1::value_type value_type; 3666 typedef typename M::const_iterator1::difference_type difference_type; 3667 typedef typename M::const_reference reference; //FIXME due to indexing access 3668 typedef typename M::const_iterator1::pointer pointer; 3669 typedef const_iterator2 dual_iterator_type; 3670 typedef const_reverse_iterator2 dual_reverse_iterator_type; 3671 3672 // Construction and destruction 3673 BOOST_UBLAS_INLINE const_iterator1()3674 const_iterator1 (): 3675 container_const_reference<self_type> (), it1_ (), it2_ () {} 3676 BOOST_UBLAS_INLINE const_iterator1(const self_type & ms,const const_subiterator1_type & it1,const const_subiterator2_type & it2)3677 const_iterator1 (const self_type &ms, const const_subiterator1_type &it1, const const_subiterator2_type &it2): 3678 container_const_reference<self_type> (ms), it1_ (it1), it2_ (it2) {} 3679 BOOST_UBLAS_INLINE const_iterator1(const iterator1 & it)3680 const_iterator1 (const iterator1 &it): 3681 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {} 3682 3683 // Arithmetic 3684 BOOST_UBLAS_INLINE operator ++()3685 const_iterator1 &operator ++ () { 3686 ++ it1_; 3687 return *this; 3688 } 3689 BOOST_UBLAS_INLINE operator --()3690 const_iterator1 &operator -- () { 3691 -- it1_; 3692 return *this; 3693 } 3694 BOOST_UBLAS_INLINE operator +=(difference_type n)3695 const_iterator1 &operator += (difference_type n) { 3696 it1_ += n; 3697 return *this; 3698 } 3699 BOOST_UBLAS_INLINE operator -=(difference_type n)3700 const_iterator1 &operator -= (difference_type n) { 3701 it1_ -= n; 3702 return *this; 3703 } 3704 BOOST_UBLAS_INLINE operator -(const const_iterator1 & it) const3705 difference_type operator - (const const_iterator1 &it) const { 3706 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 3707 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 3708 return it1_ - it.it1_; 3709 } 3710 3711 // Dereference 3712 BOOST_UBLAS_INLINE operator *() const3713 const_reference operator * () const { 3714 // FIXME replace find with at_element 3715 return (*this) ().data_ (*it1_, *it2_); 3716 } 3717 BOOST_UBLAS_INLINE operator [](difference_type n) const3718 const_reference operator [] (difference_type n) const { 3719 return *(*this + n); 3720 } 3721 3722 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 3723 BOOST_UBLAS_INLINE 3724 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3725 typename self_type:: 3726 #endif begin() const3727 const_iterator2 begin () const { 3728 return const_iterator2 ((*this) (), it1_, it2_ ().begin ()); 3729 } 3730 BOOST_UBLAS_INLINE 3731 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3732 typename self_type:: 3733 #endif cbegin() const3734 const_iterator2 cbegin () const { 3735 return begin (); 3736 } 3737 BOOST_UBLAS_INLINE 3738 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3739 typename self_type:: 3740 #endif end() const3741 const_iterator2 end () const { 3742 return const_iterator2 ((*this) (), it1_, it2_ ().end ()); 3743 } 3744 BOOST_UBLAS_INLINE 3745 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3746 typename self_type:: 3747 #endif cend() const3748 const_iterator2 cend () const { 3749 return end (); 3750 } 3751 BOOST_UBLAS_INLINE 3752 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3753 typename self_type:: 3754 #endif rbegin() const3755 const_reverse_iterator2 rbegin () const { 3756 return const_reverse_iterator2 (end ()); 3757 } 3758 BOOST_UBLAS_INLINE 3759 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3760 typename self_type:: 3761 #endif crbegin() const3762 const_reverse_iterator2 crbegin () const { 3763 return rbegin (); 3764 } 3765 BOOST_UBLAS_INLINE 3766 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3767 typename self_type:: 3768 #endif rend() const3769 const_reverse_iterator2 rend () const { 3770 return const_reverse_iterator2 (begin ()); 3771 } 3772 BOOST_UBLAS_INLINE 3773 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3774 typename self_type:: 3775 #endif crend() const3776 const_reverse_iterator2 crend () const { 3777 return rend (); 3778 } 3779 #endif 3780 3781 // Indices 3782 BOOST_UBLAS_INLINE index1() const3783 size_type index1 () const { 3784 return it1_.index (); 3785 } 3786 BOOST_UBLAS_INLINE index2() const3787 size_type index2 () const { 3788 return it2_.index (); 3789 } 3790 3791 // Assignment 3792 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)3793 const_iterator1 &operator = (const const_iterator1 &it) { 3794 container_const_reference<self_type>::assign (&it ()); 3795 it1_ = it.it1_; 3796 it2_ = it.it2_; 3797 return *this; 3798 } 3799 3800 // Comparison 3801 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const3802 bool operator == (const const_iterator1 &it) const { 3803 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 3804 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 3805 return it1_ == it.it1_; 3806 } 3807 BOOST_UBLAS_INLINE operator <(const const_iterator1 & it) const3808 bool operator < (const const_iterator1 &it) const { 3809 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 3810 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 3811 return it1_ < it.it1_; 3812 } 3813 3814 private: 3815 const_subiterator1_type it1_; 3816 const_subiterator2_type it2_; 3817 }; 3818 #endif 3819 3820 BOOST_UBLAS_INLINE begin1() const3821 const_iterator1 begin1 () const { 3822 return find1 (0, 0, 0); 3823 } 3824 BOOST_UBLAS_INLINE cbegin1() const3825 const_iterator1 cbegin1 () const { 3826 return begin1 (); 3827 } 3828 BOOST_UBLAS_INLINE end1() const3829 const_iterator1 end1 () const { 3830 return find1 (0, size1 (), 0); 3831 } 3832 BOOST_UBLAS_INLINE cend1() const3833 const_iterator1 cend1 () const { 3834 return end1 (); 3835 } 3836 3837 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 3838 class iterator1: 3839 public container_reference<matrix_slice>, 3840 public iterator_base_traits<typename M::iterator1::iterator_category>::template 3841 iterator_base<iterator1, value_type>::type { 3842 public: 3843 typedef typename M::iterator1::value_type value_type; 3844 typedef typename M::iterator1::difference_type difference_type; 3845 typedef typename M::reference reference; //FIXME due to indexing access 3846 typedef typename M::iterator1::pointer pointer; 3847 typedef iterator2 dual_iterator_type; 3848 typedef reverse_iterator2 dual_reverse_iterator_type; 3849 3850 // Construction and destruction 3851 BOOST_UBLAS_INLINE iterator1()3852 iterator1 (): 3853 container_reference<self_type> (), it1_ (), it2_ () {} 3854 BOOST_UBLAS_INLINE iterator1(self_type & ms,const subiterator1_type & it1,const subiterator2_type & it2)3855 iterator1 (self_type &ms, const subiterator1_type &it1, const subiterator2_type &it2): 3856 container_reference<self_type> (ms), it1_ (it1), it2_ (it2) {} 3857 3858 // Arithmetic 3859 BOOST_UBLAS_INLINE operator ++()3860 iterator1 &operator ++ () { 3861 ++ it1_; 3862 return *this; 3863 } 3864 BOOST_UBLAS_INLINE operator --()3865 iterator1 &operator -- () { 3866 -- it1_; 3867 return *this; 3868 } 3869 BOOST_UBLAS_INLINE operator +=(difference_type n)3870 iterator1 &operator += (difference_type n) { 3871 it1_ += n; 3872 return *this; 3873 } 3874 BOOST_UBLAS_INLINE operator -=(difference_type n)3875 iterator1 &operator -= (difference_type n) { 3876 it1_ -= n; 3877 return *this; 3878 } 3879 BOOST_UBLAS_INLINE operator -(const iterator1 & it) const3880 difference_type operator - (const iterator1 &it) const { 3881 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 3882 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 3883 return it1_ - it.it1_; 3884 } 3885 3886 // Dereference 3887 BOOST_UBLAS_INLINE operator *() const3888 reference operator * () const { 3889 // FIXME replace find with at_element 3890 return (*this) ().data_ (*it1_, *it2_); 3891 } 3892 BOOST_UBLAS_INLINE operator [](difference_type n) const3893 reference operator [] (difference_type n) const { 3894 return *(*this + n); 3895 } 3896 3897 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 3898 BOOST_UBLAS_INLINE 3899 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3900 typename self_type:: 3901 #endif begin() const3902 iterator2 begin () const { 3903 return iterator2 ((*this) (), it1_, it2_ ().begin ()); 3904 } 3905 BOOST_UBLAS_INLINE 3906 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3907 typename self_type:: 3908 #endif end() const3909 iterator2 end () const { 3910 return iterator2 ((*this) (), it1_, it2_ ().end ()); 3911 } 3912 BOOST_UBLAS_INLINE 3913 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3914 typename self_type:: 3915 #endif rbegin() const3916 reverse_iterator2 rbegin () const { 3917 return reverse_iterator2 (end ()); 3918 } 3919 BOOST_UBLAS_INLINE 3920 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 3921 typename self_type:: 3922 #endif rend() const3923 reverse_iterator2 rend () const { 3924 return reverse_iterator2 (begin ()); 3925 } 3926 #endif 3927 3928 // Indices 3929 BOOST_UBLAS_INLINE index1() const3930 size_type index1 () const { 3931 return it1_.index (); 3932 } 3933 BOOST_UBLAS_INLINE index2() const3934 size_type index2 () const { 3935 return it2_.index (); 3936 } 3937 3938 // Assignment 3939 BOOST_UBLAS_INLINE operator =(const iterator1 & it)3940 iterator1 &operator = (const iterator1 &it) { 3941 container_reference<self_type>::assign (&it ()); 3942 it1_ = it.it1_; 3943 it2_ = it.it2_; 3944 return *this; 3945 } 3946 3947 // Comparison 3948 BOOST_UBLAS_INLINE operator ==(const iterator1 & it) const3949 bool operator == (const iterator1 &it) const { 3950 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 3951 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 3952 return it1_ == it.it1_; 3953 } 3954 BOOST_UBLAS_INLINE operator <(const iterator1 & it) const3955 bool operator < (const iterator1 &it) const { 3956 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 3957 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 3958 return it1_ < it.it1_; 3959 } 3960 3961 private: 3962 subiterator1_type it1_; 3963 subiterator2_type it2_; 3964 3965 friend class const_iterator1; 3966 }; 3967 #endif 3968 3969 BOOST_UBLAS_INLINE begin1()3970 iterator1 begin1 () { 3971 return find1 (0, 0, 0); 3972 } 3973 BOOST_UBLAS_INLINE end1()3974 iterator1 end1 () { 3975 return find1 (0, size1 (), 0); 3976 } 3977 3978 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 3979 class const_iterator2: 3980 public container_const_reference<matrix_slice>, 3981 public iterator_base_traits<typename M::const_iterator2::iterator_category>::template 3982 iterator_base<const_iterator2, value_type>::type { 3983 public: 3984 typedef typename M::const_iterator2::value_type value_type; 3985 typedef typename M::const_iterator2::difference_type difference_type; 3986 typedef typename M::const_reference reference; //FIXME due to indexing access 3987 typedef typename M::const_iterator2::pointer pointer; 3988 typedef const_iterator1 dual_iterator_type; 3989 typedef const_reverse_iterator1 dual_reverse_iterator_type; 3990 3991 // Construction and destruction 3992 BOOST_UBLAS_INLINE const_iterator2()3993 const_iterator2 (): 3994 container_const_reference<self_type> (), it1_ (), it2_ () {} 3995 BOOST_UBLAS_INLINE const_iterator2(const self_type & ms,const const_subiterator1_type & it1,const const_subiterator2_type & it2)3996 const_iterator2 (const self_type &ms, const const_subiterator1_type &it1, const const_subiterator2_type &it2): 3997 container_const_reference<self_type> (ms), it1_ (it1), it2_ (it2) {} 3998 BOOST_UBLAS_INLINE const_iterator2(const iterator2 & it)3999 const_iterator2 (const iterator2 &it): 4000 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {} 4001 4002 // Arithmetic 4003 BOOST_UBLAS_INLINE operator ++()4004 const_iterator2 &operator ++ () { 4005 ++ it2_; 4006 return *this; 4007 } 4008 BOOST_UBLAS_INLINE operator --()4009 const_iterator2 &operator -- () { 4010 -- it2_; 4011 return *this; 4012 } 4013 BOOST_UBLAS_INLINE operator +=(difference_type n)4014 const_iterator2 &operator += (difference_type n) { 4015 it2_ += n; 4016 return *this; 4017 } 4018 BOOST_UBLAS_INLINE operator -=(difference_type n)4019 const_iterator2 &operator -= (difference_type n) { 4020 it2_ -= n; 4021 return *this; 4022 } 4023 BOOST_UBLAS_INLINE operator -(const const_iterator2 & it) const4024 difference_type operator - (const const_iterator2 &it) const { 4025 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 4026 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 4027 return it2_ - it.it2_; 4028 } 4029 4030 // Dereference 4031 BOOST_UBLAS_INLINE operator *() const4032 const_reference operator * () const { 4033 // FIXME replace find with at_element 4034 return (*this) ().data_ (*it1_, *it2_); 4035 } 4036 BOOST_UBLAS_INLINE operator [](difference_type n) const4037 const_reference operator [] (difference_type n) const { 4038 return *(*this + n); 4039 } 4040 4041 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 4042 BOOST_UBLAS_INLINE 4043 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4044 typename self_type:: 4045 #endif begin() const4046 const_iterator1 begin () const { 4047 return const_iterator1 ((*this) (), it1_ ().begin (), it2_); 4048 } 4049 BOOST_UBLAS_INLINE 4050 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4051 typename self_type:: 4052 #endif cbegin() const4053 const_iterator1 cbegin () const { 4054 return begin (); 4055 } 4056 BOOST_UBLAS_INLINE 4057 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4058 typename self_type:: 4059 #endif end() const4060 const_iterator1 end () const { 4061 return const_iterator1 ((*this) (), it1_ ().end (), it2_); 4062 } 4063 BOOST_UBLAS_INLINE 4064 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4065 typename self_type:: 4066 #endif cend() const4067 const_iterator1 cend () const { 4068 return end (); 4069 } 4070 BOOST_UBLAS_INLINE 4071 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4072 typename self_type:: 4073 #endif rbegin() const4074 const_reverse_iterator1 rbegin () const { 4075 return const_reverse_iterator1 (end ()); 4076 } 4077 BOOST_UBLAS_INLINE 4078 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4079 typename self_type:: 4080 #endif crbegin() const4081 const_reverse_iterator1 crbegin () const { 4082 return rbegin (); 4083 } 4084 BOOST_UBLAS_INLINE 4085 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4086 typename self_type:: 4087 #endif rend() const4088 const_reverse_iterator1 rend () const { 4089 return const_reverse_iterator1 (begin ()); 4090 } 4091 BOOST_UBLAS_INLINE 4092 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4093 typename self_type:: 4094 #endif crend() const4095 const_reverse_iterator1 crend () const { 4096 return rend (); 4097 } 4098 #endif 4099 4100 // Indices 4101 BOOST_UBLAS_INLINE index1() const4102 size_type index1 () const { 4103 return it1_.index (); 4104 } 4105 BOOST_UBLAS_INLINE index2() const4106 size_type index2 () const { 4107 return it2_.index (); 4108 } 4109 4110 // Assignment 4111 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)4112 const_iterator2 &operator = (const const_iterator2 &it) { 4113 container_const_reference<self_type>::assign (&it ()); 4114 it1_ = it.it1_; 4115 it2_ = it.it2_; 4116 return *this; 4117 } 4118 4119 // Comparison 4120 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const4121 bool operator == (const const_iterator2 &it) const { 4122 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 4123 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 4124 return it2_ == it.it2_; 4125 } 4126 BOOST_UBLAS_INLINE operator <(const const_iterator2 & it) const4127 bool operator < (const const_iterator2 &it) const { 4128 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 4129 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 4130 return it2_ < it.it2_; 4131 } 4132 4133 private: 4134 const_subiterator1_type it1_; 4135 const_subiterator2_type it2_; 4136 }; 4137 #endif 4138 4139 BOOST_UBLAS_INLINE begin2() const4140 const_iterator2 begin2 () const { 4141 return find2 (0, 0, 0); 4142 } 4143 BOOST_UBLAS_INLINE cbegin2() const4144 const_iterator2 cbegin2 () const { 4145 return begin2 (); 4146 } 4147 BOOST_UBLAS_INLINE end2() const4148 const_iterator2 end2 () const { 4149 return find2 (0, 0, size2 ()); 4150 } 4151 BOOST_UBLAS_INLINE cend2() const4152 const_iterator2 cend2 () const { 4153 return end2 (); 4154 } 4155 4156 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 4157 class iterator2: 4158 public container_reference<matrix_slice>, 4159 public iterator_base_traits<typename M::iterator2::iterator_category>::template 4160 iterator_base<iterator2, value_type>::type { 4161 public: 4162 typedef typename M::iterator2::value_type value_type; 4163 typedef typename M::iterator2::difference_type difference_type; 4164 typedef typename M::reference reference; //FIXME due to indexing access 4165 typedef typename M::iterator2::pointer pointer; 4166 typedef iterator1 dual_iterator_type; 4167 typedef reverse_iterator1 dual_reverse_iterator_type; 4168 4169 // Construction and destruction 4170 BOOST_UBLAS_INLINE iterator2()4171 iterator2 (): 4172 container_reference<self_type> (), it1_ (), it2_ () {} 4173 BOOST_UBLAS_INLINE iterator2(self_type & ms,const subiterator1_type & it1,const subiterator2_type & it2)4174 iterator2 (self_type &ms, const subiterator1_type &it1, const subiterator2_type &it2): 4175 container_reference<self_type> (ms), it1_ (it1), it2_ (it2) {} 4176 4177 // Arithmetic 4178 BOOST_UBLAS_INLINE operator ++()4179 iterator2 &operator ++ () { 4180 ++ it2_; 4181 return *this; 4182 } 4183 BOOST_UBLAS_INLINE operator --()4184 iterator2 &operator -- () { 4185 -- it2_; 4186 return *this; 4187 } 4188 BOOST_UBLAS_INLINE operator +=(difference_type n)4189 iterator2 &operator += (difference_type n) { 4190 it2_ += n; 4191 return *this; 4192 } 4193 BOOST_UBLAS_INLINE operator -=(difference_type n)4194 iterator2 &operator -= (difference_type n) { 4195 it2_ -= n; 4196 return *this; 4197 } 4198 BOOST_UBLAS_INLINE operator -(const iterator2 & it) const4199 difference_type operator - (const iterator2 &it) const { 4200 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 4201 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 4202 return it2_ - it.it2_; 4203 } 4204 4205 // Dereference 4206 BOOST_UBLAS_INLINE operator *() const4207 reference operator * () const { 4208 // FIXME replace find with at_element 4209 return (*this) ().data_ (*it1_, *it2_); 4210 } 4211 BOOST_UBLAS_INLINE operator [](difference_type n) const4212 reference operator [] (difference_type n) const { 4213 return *(*this + n); 4214 } 4215 4216 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 4217 BOOST_UBLAS_INLINE 4218 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4219 typename self_type:: 4220 #endif begin() const4221 iterator1 begin () const { 4222 return iterator1 ((*this) (), it1_ ().begin (), it2_); 4223 } 4224 BOOST_UBLAS_INLINE 4225 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4226 typename self_type:: 4227 #endif end() const4228 iterator1 end () const { 4229 return iterator1 ((*this) (), it1_ ().end (), it2_); 4230 } 4231 BOOST_UBLAS_INLINE 4232 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4233 typename self_type:: 4234 #endif rbegin() const4235 reverse_iterator1 rbegin () const { 4236 return reverse_iterator1 (end ()); 4237 } 4238 BOOST_UBLAS_INLINE 4239 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4240 typename self_type:: 4241 #endif rend() const4242 reverse_iterator1 rend () const { 4243 return reverse_iterator1 (begin ()); 4244 } 4245 #endif 4246 4247 // Indices 4248 BOOST_UBLAS_INLINE index1() const4249 size_type index1 () const { 4250 return it1_.index (); 4251 } 4252 BOOST_UBLAS_INLINE index2() const4253 size_type index2 () const { 4254 return it2_.index (); 4255 } 4256 4257 // Assignment 4258 BOOST_UBLAS_INLINE operator =(const iterator2 & it)4259 iterator2 &operator = (const iterator2 &it) { 4260 container_reference<self_type>::assign (&it ()); 4261 it1_ = it.it1_; 4262 it2_ = it.it2_; 4263 return *this; 4264 } 4265 4266 // Comparison 4267 BOOST_UBLAS_INLINE operator ==(const iterator2 & it) const4268 bool operator == (const iterator2 &it) const { 4269 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 4270 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 4271 return it2_ == it.it2_; 4272 } 4273 BOOST_UBLAS_INLINE operator <(const iterator2 & it) const4274 bool operator < (const iterator2 &it) const { 4275 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 4276 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 4277 return it2_ < it.it2_; 4278 } 4279 4280 private: 4281 subiterator1_type it1_; 4282 subiterator2_type it2_; 4283 4284 friend class const_iterator2; 4285 }; 4286 #endif 4287 4288 BOOST_UBLAS_INLINE begin2()4289 iterator2 begin2 () { 4290 return find2 (0, 0, 0); 4291 } 4292 BOOST_UBLAS_INLINE end2()4293 iterator2 end2 () { 4294 return find2 (0, 0, size2 ()); 4295 } 4296 4297 // Reverse iterators 4298 4299 BOOST_UBLAS_INLINE rbegin1() const4300 const_reverse_iterator1 rbegin1 () const { 4301 return const_reverse_iterator1 (end1 ()); 4302 } 4303 BOOST_UBLAS_INLINE crbegin1() const4304 const_reverse_iterator1 crbegin1 () const { 4305 return rbegin1 (); 4306 } 4307 BOOST_UBLAS_INLINE rend1() const4308 const_reverse_iterator1 rend1 () const { 4309 return const_reverse_iterator1 (begin1 ()); 4310 } 4311 BOOST_UBLAS_INLINE crend1() const4312 const_reverse_iterator1 crend1 () const { 4313 return rend1 (); 4314 } 4315 4316 BOOST_UBLAS_INLINE rbegin1()4317 reverse_iterator1 rbegin1 () { 4318 return reverse_iterator1 (end1 ()); 4319 } 4320 BOOST_UBLAS_INLINE rend1()4321 reverse_iterator1 rend1 () { 4322 return reverse_iterator1 (begin1 ()); 4323 } 4324 4325 BOOST_UBLAS_INLINE rbegin2() const4326 const_reverse_iterator2 rbegin2 () const { 4327 return const_reverse_iterator2 (end2 ()); 4328 } 4329 BOOST_UBLAS_INLINE crbegin2() const4330 const_reverse_iterator2 crbegin2 () const { 4331 return rbegin2 (); 4332 } 4333 BOOST_UBLAS_INLINE rend2() const4334 const_reverse_iterator2 rend2 () const { 4335 return const_reverse_iterator2 (begin2 ()); 4336 } 4337 BOOST_UBLAS_INLINE crend2() const4338 const_reverse_iterator2 crend2 () const { 4339 return rend2 (); 4340 } 4341 4342 BOOST_UBLAS_INLINE rbegin2()4343 reverse_iterator2 rbegin2 () { 4344 return reverse_iterator2 (end2 ()); 4345 } 4346 BOOST_UBLAS_INLINE rend2()4347 reverse_iterator2 rend2 () { 4348 return reverse_iterator2 (begin2 ()); 4349 } 4350 4351 private: 4352 matrix_closure_type data_; 4353 slice_type s1_; 4354 slice_type s2_; 4355 }; 4356 4357 // Simple Projections 4358 template<class M> 4359 BOOST_UBLAS_INLINE subslice(M & data,typename M::size_type start1,typename M::difference_type stride1,typename M::size_type size1,typename M::size_type start2,typename M::difference_type stride2,typename M::size_type size2)4360 matrix_slice<M> subslice (M &data, typename M::size_type start1, typename M::difference_type stride1, typename M::size_type size1, typename M::size_type start2, typename M::difference_type stride2, typename M::size_type size2) { 4361 typedef basic_slice<typename M::size_type, typename M::difference_type> slice_type; 4362 return matrix_slice<M> (data, slice_type (start1, stride1, size1), slice_type (start2, stride2, size2)); 4363 } 4364 template<class M> 4365 BOOST_UBLAS_INLINE subslice(const M & data,typename M::size_type start1,typename M::difference_type stride1,typename M::size_type size1,typename M::size_type start2,typename M::difference_type stride2,typename M::size_type size2)4366 matrix_slice<const M> subslice (const M &data, typename M::size_type start1, typename M::difference_type stride1, typename M::size_type size1, typename M::size_type start2, typename M::difference_type stride2, typename M::size_type size2) { 4367 typedef basic_slice<typename M::size_type, typename M::difference_type> slice_type; 4368 return matrix_slice<const M> (data, slice_type (start1, stride1, size1), slice_type (start2, stride2, size2)); 4369 } 4370 4371 // Generic Projections 4372 template<class M> 4373 BOOST_UBLAS_INLINE project(M & data,const typename matrix_slice<M>::slice_type & s1,const typename matrix_slice<M>::slice_type & s2)4374 matrix_slice<M> project (M &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) { 4375 return matrix_slice<M> (data, s1, s2); 4376 } 4377 template<class M> 4378 BOOST_UBLAS_INLINE project(const M & data,const typename matrix_slice<M>::slice_type & s1,const typename matrix_slice<M>::slice_type & s2)4379 const matrix_slice<const M> project (const M &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) { 4380 // ISSUE was: return matrix_slice<M> (const_cast<M &> (data), s1, s2); 4381 return matrix_slice<const M> (data, s1, s2); 4382 } 4383 // ISSUE in the following two functions it would be logical to use matrix_slice<V>::range_type but this confuses VC7.1 and 8.0 4384 template<class M> 4385 BOOST_UBLAS_INLINE project(matrix_slice<M> & data,const typename matrix_range<M>::range_type & r1,const typename matrix_range<M>::range_type & r2)4386 matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) { 4387 return data.project (r1, r2); 4388 } 4389 template<class M> 4390 BOOST_UBLAS_INLINE project(const matrix_slice<M> & data,const typename matrix_range<M>::range_type & r1,const typename matrix_range<M>::range_type & r2)4391 const matrix_slice<M> project (const matrix_slice<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) { 4392 return data.project (r1, r2); 4393 } 4394 template<class M> 4395 BOOST_UBLAS_INLINE project(matrix_slice<M> & data,const typename matrix_slice<M>::slice_type & s1,const typename matrix_slice<M>::slice_type & s2)4396 matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) { 4397 return data.project (s1, s2); 4398 } 4399 template<class M> 4400 BOOST_UBLAS_INLINE project(const matrix_slice<M> & data,const typename matrix_slice<M>::slice_type & s1,const typename matrix_slice<M>::slice_type & s2)4401 const matrix_slice<M> project (const matrix_slice<M> &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) { 4402 return data.project (s1, s2); 4403 } 4404 4405 // Specialization of temporary_traits 4406 template <class M> 4407 struct matrix_temporary_traits< matrix_slice<M> > 4408 : matrix_temporary_traits< M > {}; 4409 template <class M> 4410 struct matrix_temporary_traits< const matrix_slice<M> > 4411 : matrix_temporary_traits< M > {}; 4412 4413 template <class M> 4414 struct vector_temporary_traits< matrix_slice<M> > 4415 : vector_temporary_traits< M > {}; 4416 template <class M> 4417 struct vector_temporary_traits< const matrix_slice<M> > 4418 : vector_temporary_traits< M > {}; 4419 4420 // Matrix based indirection class 4421 // Contributed by Toon Knapen. 4422 // Extended and optimized by Kresimir Fresl. 4423 /** \brief A matrix referencing a non continuous submatrix of elements given another matrix of indices. 4424 * 4425 * It is the most general version of any submatrices because it uses another matrix of indices to reference 4426 * the submatrix. 4427 * 4428 * The matrix of indices can be of any type with the restriction that its elements must be 4429 * type-compatible with the size_type \c of the container. In practice, the following are good candidates: 4430 * - \c boost::numeric::ublas::indirect_array<A> where \c A can be \c int, \c size_t, \c long, etc... 4431 * - \c boost::numeric::ublas::matrix<int> can work too (\c int can be replaced by another integer type) 4432 * - etc... 4433 * 4434 * An indirect matrix can be used as a normal matrix in any expression. If the specified indirect matrix 4435 * falls outside that of the indices of the matrix, then the \c matrix_indirect is not a well formed 4436 * \i Matrix \i Expression and access to an element outside of indices of the matrix is \b undefined. 4437 * 4438 * \tparam V the type of the referenced matrix, for example \c matrix<double>) 4439 * \tparam IA the type of index matrix. Default is \c ublas::indirect_array<> 4440 */ 4441 template<class M, class IA> 4442 class matrix_indirect: 4443 public matrix_expression<matrix_indirect<M, IA> > { 4444 4445 typedef matrix_indirect<M, IA> self_type; 4446 public: 4447 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 4448 using matrix_expression<self_type>::operator (); 4449 #endif 4450 typedef M matrix_type; 4451 typedef IA indirect_array_type; 4452 typedef typename M::size_type size_type; 4453 typedef typename M::difference_type difference_type; 4454 typedef typename M::value_type value_type; 4455 typedef typename M::const_reference const_reference; 4456 typedef typename boost::mpl::if_<boost::is_const<M>, 4457 typename M::const_reference, 4458 typename M::reference>::type reference; 4459 typedef typename boost::mpl::if_<boost::is_const<M>, 4460 typename M::const_closure_type, 4461 typename M::closure_type>::type matrix_closure_type; 4462 typedef basic_range<size_type, difference_type> range_type; 4463 typedef basic_slice<size_type, difference_type> slice_type; 4464 typedef const self_type const_closure_type; 4465 typedef self_type closure_type; 4466 typedef typename storage_restrict_traits<typename M::storage_category, 4467 dense_proxy_tag>::storage_category storage_category; 4468 typedef typename M::orientation_category orientation_category; 4469 4470 // Construction and destruction 4471 BOOST_UBLAS_INLINE matrix_indirect(matrix_type & data,size_type size1,size_type size2)4472 matrix_indirect (matrix_type &data, size_type size1, size_type size2): 4473 data_ (data), ia1_ (size1), ia2_ (size2) {} 4474 BOOST_UBLAS_INLINE matrix_indirect(matrix_type & data,const indirect_array_type & ia1,const indirect_array_type & ia2)4475 matrix_indirect (matrix_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2): 4476 data_ (data), ia1_ (ia1.preprocess (data.size1 ())), ia2_ (ia2.preprocess (data.size2 ())) {} 4477 BOOST_UBLAS_INLINE matrix_indirect(const matrix_closure_type & data,const indirect_array_type & ia1,const indirect_array_type & ia2,int)4478 matrix_indirect (const matrix_closure_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2, int): 4479 data_ (data), ia1_ (ia1.preprocess (data.size1 ())), ia2_ (ia2.preprocess (data.size2 ())) {} 4480 4481 // Accessors 4482 BOOST_UBLAS_INLINE size1() const4483 size_type size1 () const { 4484 return ia1_.size (); 4485 } 4486 BOOST_UBLAS_INLINE size2() const4487 size_type size2 () const { 4488 return ia2_.size (); 4489 } 4490 BOOST_UBLAS_INLINE indirect1() const4491 const indirect_array_type &indirect1 () const { 4492 return ia1_; 4493 } 4494 BOOST_UBLAS_INLINE indirect1()4495 indirect_array_type &indirect1 () { 4496 return ia1_; 4497 } 4498 BOOST_UBLAS_INLINE indirect2() const4499 const indirect_array_type &indirect2 () const { 4500 return ia2_; 4501 } 4502 BOOST_UBLAS_INLINE indirect2()4503 indirect_array_type &indirect2 () { 4504 return ia2_; 4505 } 4506 4507 // Storage accessors 4508 BOOST_UBLAS_INLINE data() const4509 const matrix_closure_type &data () const { 4510 return data_; 4511 } 4512 BOOST_UBLAS_INLINE data()4513 matrix_closure_type &data () { 4514 return data_; 4515 } 4516 4517 // Element access 4518 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 4519 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const4520 const_reference operator () (size_type i, size_type j) const { 4521 return data_ (ia1_ (i), ia2_ (j)); 4522 } 4523 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j)4524 reference operator () (size_type i, size_type j) { 4525 return data_ (ia1_ (i), ia2_ (j)); 4526 } 4527 #else 4528 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const4529 reference operator () (size_type i, size_type j) const { 4530 return data_ (ia1_ (i), ia2_ (j)); 4531 } 4532 #endif 4533 4534 // ISSUE can this be done in free project function? 4535 // Although a const function can create a non-const proxy to a non-const object 4536 // Critical is that matrix_type and data_ (vector_closure_type) are const correct 4537 BOOST_UBLAS_INLINE project(const range_type & r1,const range_type & r2) const4538 matrix_indirect<matrix_type, indirect_array_type> project (const range_type &r1, const range_type &r2) const { 4539 return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (r1.preprocess (data_.size1 ())), ia2_.compose (r2.preprocess (data_.size2 ())), 0); 4540 } 4541 BOOST_UBLAS_INLINE project(const slice_type & s1,const slice_type & s2) const4542 matrix_indirect<matrix_type, indirect_array_type> project (const slice_type &s1, const slice_type &s2) const { 4543 return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (s1.preprocess (data_.size1 ())), ia2_.compose (s2.preprocess (data_.size2 ())), 0); 4544 } 4545 BOOST_UBLAS_INLINE project(const indirect_array_type & ia1,const indirect_array_type & ia2) const4546 matrix_indirect<matrix_type, indirect_array_type> project (const indirect_array_type &ia1, const indirect_array_type &ia2) const { 4547 return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (ia1.preprocess (data_.size1 ())), ia2_.compose (ia2.preprocess (data_.size2 ())), 0); 4548 } 4549 4550 // Assignment 4551 BOOST_UBLAS_INLINE operator =(const matrix_indirect & mi)4552 matrix_indirect &operator = (const matrix_indirect &mi) { 4553 matrix_assign<scalar_assign> (*this, mi); 4554 return *this; 4555 } 4556 BOOST_UBLAS_INLINE assign_temporary(matrix_indirect & mi)4557 matrix_indirect &assign_temporary (matrix_indirect &mi) { 4558 return *this = mi; 4559 } 4560 template<class AE> 4561 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)4562 matrix_indirect &operator = (const matrix_expression<AE> &ae) { 4563 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae)); 4564 return *this; 4565 } 4566 template<class AE> 4567 BOOST_UBLAS_INLINE assign(const matrix_expression<AE> & ae)4568 matrix_indirect &assign (const matrix_expression<AE> &ae) { 4569 matrix_assign<scalar_assign> (*this, ae); 4570 return *this; 4571 } 4572 template<class AE> 4573 BOOST_UBLAS_INLINE operator +=(const matrix_expression<AE> & ae)4574 matrix_indirect& operator += (const matrix_expression<AE> &ae) { 4575 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae)); 4576 return *this; 4577 } 4578 template<class AE> 4579 BOOST_UBLAS_INLINE plus_assign(const matrix_expression<AE> & ae)4580 matrix_indirect &plus_assign (const matrix_expression<AE> &ae) { 4581 matrix_assign<scalar_plus_assign> (*this, ae); 4582 return *this; 4583 } 4584 template<class AE> 4585 BOOST_UBLAS_INLINE operator -=(const matrix_expression<AE> & ae)4586 matrix_indirect& operator -= (const matrix_expression<AE> &ae) { 4587 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae)); 4588 return *this; 4589 } 4590 template<class AE> 4591 BOOST_UBLAS_INLINE minus_assign(const matrix_expression<AE> & ae)4592 matrix_indirect &minus_assign (const matrix_expression<AE> &ae) { 4593 matrix_assign<scalar_minus_assign> (*this, ae); 4594 return *this; 4595 } 4596 template<class AT> 4597 BOOST_UBLAS_INLINE operator *=(const AT & at)4598 matrix_indirect& operator *= (const AT &at) { 4599 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 4600 return *this; 4601 } 4602 template<class AT> 4603 BOOST_UBLAS_INLINE operator /=(const AT & at)4604 matrix_indirect& operator /= (const AT &at) { 4605 matrix_assign_scalar<scalar_divides_assign> (*this, at); 4606 return *this; 4607 } 4608 4609 // Closure comparison 4610 BOOST_UBLAS_INLINE same_closure(const matrix_indirect & mi) const4611 bool same_closure (const matrix_indirect &mi) const { 4612 return (*this).data_.same_closure (mi.data_); 4613 } 4614 4615 // Comparison 4616 BOOST_UBLAS_INLINE operator ==(const matrix_indirect & mi) const4617 bool operator == (const matrix_indirect &mi) const { 4618 return (*this).data_ == mi.data_ && ia1_ == mi.ia1_ && ia2_ == mi.ia2_; 4619 } 4620 4621 // Swapping 4622 BOOST_UBLAS_INLINE swap(matrix_indirect mi)4623 void swap (matrix_indirect mi) { 4624 if (this != &mi) { 4625 BOOST_UBLAS_CHECK (size1 () == mi.size1 (), bad_size ()); 4626 BOOST_UBLAS_CHECK (size2 () == mi.size2 (), bad_size ()); 4627 matrix_swap<scalar_swap> (*this, mi); 4628 } 4629 } 4630 BOOST_UBLAS_INLINE swap(matrix_indirect mi1,matrix_indirect mi2)4631 friend void swap (matrix_indirect mi1, matrix_indirect mi2) { 4632 mi1.swap (mi2); 4633 } 4634 4635 // Iterator types 4636 private: 4637 typedef typename IA::const_iterator const_subiterator1_type; 4638 typedef typename IA::const_iterator subiterator1_type; 4639 typedef typename IA::const_iterator const_subiterator2_type; 4640 typedef typename IA::const_iterator subiterator2_type; 4641 4642 public: 4643 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 4644 typedef indexed_iterator1<matrix_indirect<matrix_type, indirect_array_type>, 4645 typename matrix_type::iterator1::iterator_category> iterator1; 4646 typedef indexed_iterator2<matrix_indirect<matrix_type, indirect_array_type>, 4647 typename matrix_type::iterator2::iterator_category> iterator2; 4648 typedef indexed_const_iterator1<matrix_indirect<matrix_type, indirect_array_type>, 4649 typename matrix_type::const_iterator1::iterator_category> const_iterator1; 4650 typedef indexed_const_iterator2<matrix_indirect<matrix_type, indirect_array_type>, 4651 typename matrix_type::const_iterator2::iterator_category> const_iterator2; 4652 #else 4653 class const_iterator1; 4654 class iterator1; 4655 class const_iterator2; 4656 class iterator2; 4657 #endif 4658 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 4659 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 4660 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 4661 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 4662 4663 // Element lookup 4664 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j) const4665 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const { 4666 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 4667 return const_iterator1 (*this, i, j); 4668 #else 4669 return const_iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j); 4670 #endif 4671 } 4672 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j)4673 iterator1 find1 (int /* rank */, size_type i, size_type j) { 4674 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 4675 return iterator1 (*this, i, j); 4676 #else 4677 return iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j); 4678 #endif 4679 } 4680 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j) const4681 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const { 4682 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 4683 return const_iterator2 (*this, i, j); 4684 #else 4685 return const_iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j); 4686 #endif 4687 } 4688 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j)4689 iterator2 find2 (int /* rank */, size_type i, size_type j) { 4690 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 4691 return iterator2 (*this, i, j); 4692 #else 4693 return iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j); 4694 #endif 4695 } 4696 4697 // Iterators simply are indices. 4698 4699 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 4700 class const_iterator1: 4701 public container_const_reference<matrix_indirect>, 4702 public iterator_base_traits<typename M::const_iterator1::iterator_category>::template 4703 iterator_base<const_iterator1, value_type>::type { 4704 public: 4705 typedef typename M::const_iterator1::value_type value_type; 4706 typedef typename M::const_iterator1::difference_type difference_type; 4707 typedef typename M::const_reference reference; //FIXME due to indexing access 4708 typedef typename M::const_iterator1::pointer pointer; 4709 typedef const_iterator2 dual_iterator_type; 4710 typedef const_reverse_iterator2 dual_reverse_iterator_type; 4711 4712 // Construction and destruction 4713 BOOST_UBLAS_INLINE const_iterator1()4714 const_iterator1 (): 4715 container_const_reference<self_type> (), it1_ (), it2_ () {} 4716 BOOST_UBLAS_INLINE const_iterator1(const self_type & mi,const const_subiterator1_type & it1,const const_subiterator2_type & it2)4717 const_iterator1 (const self_type &mi, const const_subiterator1_type &it1, const const_subiterator2_type &it2): 4718 container_const_reference<self_type> (mi), it1_ (it1), it2_ (it2) {} 4719 BOOST_UBLAS_INLINE const_iterator1(const iterator1 & it)4720 const_iterator1 (const iterator1 &it): 4721 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {} 4722 4723 // Arithmetic 4724 BOOST_UBLAS_INLINE operator ++()4725 const_iterator1 &operator ++ () { 4726 ++ it1_; 4727 return *this; 4728 } 4729 BOOST_UBLAS_INLINE operator --()4730 const_iterator1 &operator -- () { 4731 -- it1_; 4732 return *this; 4733 } 4734 BOOST_UBLAS_INLINE operator +=(difference_type n)4735 const_iterator1 &operator += (difference_type n) { 4736 it1_ += n; 4737 return *this; 4738 } 4739 BOOST_UBLAS_INLINE operator -=(difference_type n)4740 const_iterator1 &operator -= (difference_type n) { 4741 it1_ -= n; 4742 return *this; 4743 } 4744 BOOST_UBLAS_INLINE operator -(const const_iterator1 & it) const4745 difference_type operator - (const const_iterator1 &it) const { 4746 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 4747 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 4748 return it1_ - it.it1_; 4749 } 4750 4751 // Dereference 4752 BOOST_UBLAS_INLINE operator *() const4753 const_reference operator * () const { 4754 // FIXME replace find with at_element 4755 return (*this) ().data_ (*it1_, *it2_); 4756 } 4757 BOOST_UBLAS_INLINE operator [](difference_type n) const4758 const_reference operator [] (difference_type n) const { 4759 return *(*this + n); 4760 } 4761 4762 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 4763 BOOST_UBLAS_INLINE 4764 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4765 typename self_type:: 4766 #endif begin() const4767 const_iterator2 begin () const { 4768 return const_iterator2 ((*this) (), it1_, it2_ ().begin ()); 4769 } 4770 BOOST_UBLAS_INLINE 4771 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4772 typename self_type:: 4773 #endif cbegin() const4774 const_iterator2 cbegin () const { 4775 return begin (); 4776 } 4777 BOOST_UBLAS_INLINE 4778 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4779 typename self_type:: 4780 #endif end() const4781 const_iterator2 end () const { 4782 return const_iterator2 ((*this) (), it1_, it2_ ().end ()); 4783 } 4784 BOOST_UBLAS_INLINE 4785 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4786 typename self_type:: 4787 #endif cend() const4788 const_iterator2 cend () const { 4789 return end (); 4790 } 4791 BOOST_UBLAS_INLINE 4792 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4793 typename self_type:: 4794 #endif rbegin() const4795 const_reverse_iterator2 rbegin () const { 4796 return const_reverse_iterator2 (end ()); 4797 } 4798 BOOST_UBLAS_INLINE 4799 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4800 typename self_type:: 4801 #endif crbegin() const4802 const_reverse_iterator2 crbegin () const { 4803 return rbegin (); 4804 } 4805 BOOST_UBLAS_INLINE 4806 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4807 typename self_type:: 4808 #endif rend() const4809 const_reverse_iterator2 rend () const { 4810 return const_reverse_iterator2 (begin ()); 4811 } 4812 BOOST_UBLAS_INLINE 4813 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4814 typename self_type:: 4815 #endif crend() const4816 const_reverse_iterator2 crend () const { 4817 return rend (); 4818 } 4819 #endif 4820 4821 // Indices 4822 BOOST_UBLAS_INLINE index1() const4823 size_type index1 () const { 4824 return it1_.index (); 4825 } 4826 BOOST_UBLAS_INLINE index2() const4827 size_type index2 () const { 4828 return it2_.index (); 4829 } 4830 4831 // Assignment 4832 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)4833 const_iterator1 &operator = (const const_iterator1 &it) { 4834 container_const_reference<self_type>::assign (&it ()); 4835 it1_ = it.it1_; 4836 it2_ = it.it2_; 4837 return *this; 4838 } 4839 4840 // Comparison 4841 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const4842 bool operator == (const const_iterator1 &it) const { 4843 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 4844 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 4845 return it1_ == it.it1_; 4846 } 4847 BOOST_UBLAS_INLINE operator <(const const_iterator1 & it) const4848 bool operator < (const const_iterator1 &it) const { 4849 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 4850 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 4851 return it1_ < it.it1_; 4852 } 4853 4854 private: 4855 const_subiterator1_type it1_; 4856 const_subiterator2_type it2_; 4857 }; 4858 #endif 4859 4860 BOOST_UBLAS_INLINE begin1() const4861 const_iterator1 begin1 () const { 4862 return find1 (0, 0, 0); 4863 } 4864 BOOST_UBLAS_INLINE cbegin1() const4865 const_iterator1 cbegin1 () const { 4866 return begin1 (); 4867 } 4868 BOOST_UBLAS_INLINE end1() const4869 const_iterator1 end1 () const { 4870 return find1 (0, size1 (), 0); 4871 } 4872 BOOST_UBLAS_INLINE cend1() const4873 const_iterator1 cend1 () const { 4874 return end1 (); 4875 } 4876 4877 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 4878 class iterator1: 4879 public container_reference<matrix_indirect>, 4880 public iterator_base_traits<typename M::iterator1::iterator_category>::template 4881 iterator_base<iterator1, value_type>::type { 4882 public: 4883 typedef typename M::iterator1::value_type value_type; 4884 typedef typename M::iterator1::difference_type difference_type; 4885 typedef typename M::reference reference; //FIXME due to indexing access 4886 typedef typename M::iterator1::pointer pointer; 4887 typedef iterator2 dual_iterator_type; 4888 typedef reverse_iterator2 dual_reverse_iterator_type; 4889 4890 // Construction and destruction 4891 BOOST_UBLAS_INLINE iterator1()4892 iterator1 (): 4893 container_reference<self_type> (), it1_ (), it2_ () {} 4894 BOOST_UBLAS_INLINE iterator1(self_type & mi,const subiterator1_type & it1,const subiterator2_type & it2)4895 iterator1 (self_type &mi, const subiterator1_type &it1, const subiterator2_type &it2): 4896 container_reference<self_type> (mi), it1_ (it1), it2_ (it2) {} 4897 4898 // Arithmetic 4899 BOOST_UBLAS_INLINE operator ++()4900 iterator1 &operator ++ () { 4901 ++ it1_; 4902 return *this; 4903 } 4904 BOOST_UBLAS_INLINE operator --()4905 iterator1 &operator -- () { 4906 -- it1_; 4907 return *this; 4908 } 4909 BOOST_UBLAS_INLINE operator +=(difference_type n)4910 iterator1 &operator += (difference_type n) { 4911 it1_ += n; 4912 return *this; 4913 } 4914 BOOST_UBLAS_INLINE operator -=(difference_type n)4915 iterator1 &operator -= (difference_type n) { 4916 it1_ -= n; 4917 return *this; 4918 } 4919 BOOST_UBLAS_INLINE operator -(const iterator1 & it) const4920 difference_type operator - (const iterator1 &it) const { 4921 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 4922 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 4923 return it1_ - it.it1_; 4924 } 4925 4926 // Dereference 4927 BOOST_UBLAS_INLINE operator *() const4928 reference operator * () const { 4929 // FIXME replace find with at_element 4930 return (*this) ().data_ (*it1_, *it2_); 4931 } 4932 BOOST_UBLAS_INLINE operator [](difference_type n) const4933 reference operator [] (difference_type n) const { 4934 return *(*this + n); 4935 } 4936 4937 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 4938 BOOST_UBLAS_INLINE 4939 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4940 typename self_type:: 4941 #endif begin() const4942 iterator2 begin () const { 4943 return iterator2 ((*this) (), it1_, it2_ ().begin ()); 4944 } 4945 BOOST_UBLAS_INLINE 4946 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4947 typename self_type:: 4948 #endif end() const4949 iterator2 end () const { 4950 return iterator2 ((*this) (), it1_, it2_ ().end ()); 4951 } 4952 BOOST_UBLAS_INLINE 4953 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4954 typename self_type:: 4955 #endif rbegin() const4956 reverse_iterator2 rbegin () const { 4957 return reverse_iterator2 (end ()); 4958 } 4959 BOOST_UBLAS_INLINE 4960 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 4961 typename self_type:: 4962 #endif rend() const4963 reverse_iterator2 rend () const { 4964 return reverse_iterator2 (begin ()); 4965 } 4966 #endif 4967 4968 // Indices 4969 BOOST_UBLAS_INLINE index1() const4970 size_type index1 () const { 4971 return it1_.index (); 4972 } 4973 BOOST_UBLAS_INLINE index2() const4974 size_type index2 () const { 4975 return it2_.index (); 4976 } 4977 4978 // Assignment 4979 BOOST_UBLAS_INLINE operator =(const iterator1 & it)4980 iterator1 &operator = (const iterator1 &it) { 4981 container_reference<self_type>::assign (&it ()); 4982 it1_ = it.it1_; 4983 it2_ = it.it2_; 4984 return *this; 4985 } 4986 4987 // Comparison 4988 BOOST_UBLAS_INLINE operator ==(const iterator1 & it) const4989 bool operator == (const iterator1 &it) const { 4990 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 4991 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 4992 return it1_ == it.it1_; 4993 } 4994 BOOST_UBLAS_INLINE operator <(const iterator1 & it) const4995 bool operator < (const iterator1 &it) const { 4996 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 4997 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 4998 return it1_ < it.it1_; 4999 } 5000 5001 private: 5002 subiterator1_type it1_; 5003 subiterator2_type it2_; 5004 5005 friend class const_iterator1; 5006 }; 5007 #endif 5008 5009 BOOST_UBLAS_INLINE begin1()5010 iterator1 begin1 () { 5011 return find1 (0, 0, 0); 5012 } 5013 BOOST_UBLAS_INLINE end1()5014 iterator1 end1 () { 5015 return find1 (0, size1 (), 0); 5016 } 5017 5018 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 5019 class const_iterator2: 5020 public container_const_reference<matrix_indirect>, 5021 public iterator_base_traits<typename M::const_iterator2::iterator_category>::template 5022 iterator_base<const_iterator2, value_type>::type { 5023 public: 5024 typedef typename M::const_iterator2::value_type value_type; 5025 typedef typename M::const_iterator2::difference_type difference_type; 5026 typedef typename M::const_reference reference; //FIXME due to indexing access 5027 typedef typename M::const_iterator2::pointer pointer; 5028 typedef const_iterator1 dual_iterator_type; 5029 typedef const_reverse_iterator1 dual_reverse_iterator_type; 5030 5031 // Construction and destruction 5032 BOOST_UBLAS_INLINE const_iterator2()5033 const_iterator2 (): 5034 container_const_reference<self_type> (), it1_ (), it2_ () {} 5035 BOOST_UBLAS_INLINE const_iterator2(const self_type & mi,const const_subiterator1_type & it1,const const_subiterator2_type & it2)5036 const_iterator2 (const self_type &mi, const const_subiterator1_type &it1, const const_subiterator2_type &it2): 5037 container_const_reference<self_type> (mi), it1_ (it1), it2_ (it2) {} 5038 BOOST_UBLAS_INLINE const_iterator2(const iterator2 & it)5039 const_iterator2 (const iterator2 &it): 5040 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {} 5041 5042 // Arithmetic 5043 BOOST_UBLAS_INLINE operator ++()5044 const_iterator2 &operator ++ () { 5045 ++ it2_; 5046 return *this; 5047 } 5048 BOOST_UBLAS_INLINE operator --()5049 const_iterator2 &operator -- () { 5050 -- it2_; 5051 return *this; 5052 } 5053 BOOST_UBLAS_INLINE operator +=(difference_type n)5054 const_iterator2 &operator += (difference_type n) { 5055 it2_ += n; 5056 return *this; 5057 } 5058 BOOST_UBLAS_INLINE operator -=(difference_type n)5059 const_iterator2 &operator -= (difference_type n) { 5060 it2_ -= n; 5061 return *this; 5062 } 5063 BOOST_UBLAS_INLINE operator -(const const_iterator2 & it) const5064 difference_type operator - (const const_iterator2 &it) const { 5065 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 5066 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 5067 return it2_ - it.it2_; 5068 } 5069 5070 // Dereference 5071 BOOST_UBLAS_INLINE operator *() const5072 const_reference operator * () const { 5073 // FIXME replace find with at_element 5074 return (*this) ().data_ (*it1_, *it2_); 5075 } 5076 BOOST_UBLAS_INLINE operator [](difference_type n) const5077 const_reference operator [] (difference_type n) const { 5078 return *(*this + n); 5079 } 5080 5081 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 5082 BOOST_UBLAS_INLINE 5083 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5084 typename self_type:: 5085 #endif begin() const5086 const_iterator1 begin () const { 5087 return const_iterator1 ((*this) (), it1_ ().begin (), it2_); 5088 } 5089 BOOST_UBLAS_INLINE 5090 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5091 typename self_type:: 5092 #endif cbegin() const5093 const_iterator1 cbegin () const { 5094 return begin (); 5095 } 5096 BOOST_UBLAS_INLINE 5097 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5098 typename self_type:: 5099 #endif end() const5100 const_iterator1 end () const { 5101 return const_iterator1 ((*this) (), it1_ ().end (), it2_); 5102 } 5103 BOOST_UBLAS_INLINE 5104 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5105 typename self_type:: 5106 #endif cend() const5107 const_iterator1 cend () const { 5108 return end (); 5109 } 5110 BOOST_UBLAS_INLINE 5111 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5112 typename self_type:: 5113 #endif rbegin() const5114 const_reverse_iterator1 rbegin () const { 5115 return const_reverse_iterator1 (end ()); 5116 } 5117 BOOST_UBLAS_INLINE 5118 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5119 typename self_type:: 5120 #endif crbegin() const5121 const_reverse_iterator1 crbegin () const { 5122 return rbegin (); 5123 } 5124 BOOST_UBLAS_INLINE 5125 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5126 typename self_type:: 5127 #endif rend() const5128 const_reverse_iterator1 rend () const { 5129 return const_reverse_iterator1 (begin ()); 5130 } 5131 BOOST_UBLAS_INLINE 5132 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5133 typename self_type:: 5134 #endif crend() const5135 const_reverse_iterator1 crend () const { 5136 return rend (); 5137 } 5138 #endif 5139 5140 // Indices 5141 BOOST_UBLAS_INLINE index1() const5142 size_type index1 () const { 5143 return it1_.index (); 5144 } 5145 BOOST_UBLAS_INLINE index2() const5146 size_type index2 () const { 5147 return it2_.index (); 5148 } 5149 5150 // Assignment 5151 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)5152 const_iterator2 &operator = (const const_iterator2 &it) { 5153 container_const_reference<self_type>::assign (&it ()); 5154 it1_ = it.it1_; 5155 it2_ = it.it2_; 5156 return *this; 5157 } 5158 5159 // Comparison 5160 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const5161 bool operator == (const const_iterator2 &it) const { 5162 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 5163 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 5164 return it2_ == it.it2_; 5165 } 5166 BOOST_UBLAS_INLINE operator <(const const_iterator2 & it) const5167 bool operator < (const const_iterator2 &it) const { 5168 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 5169 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 5170 return it2_ < it.it2_; 5171 } 5172 5173 private: 5174 const_subiterator1_type it1_; 5175 const_subiterator2_type it2_; 5176 }; 5177 #endif 5178 5179 BOOST_UBLAS_INLINE begin2() const5180 const_iterator2 begin2 () const { 5181 return find2 (0, 0, 0); 5182 } 5183 BOOST_UBLAS_INLINE cbegin2() const5184 const_iterator2 cbegin2 () const { 5185 return begin2 (); 5186 } 5187 BOOST_UBLAS_INLINE end2() const5188 const_iterator2 end2 () const { 5189 return find2 (0, 0, size2 ()); 5190 } 5191 BOOST_UBLAS_INLINE cend2() const5192 const_iterator2 cend2 () const { 5193 return end2 (); 5194 } 5195 5196 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 5197 class iterator2: 5198 public container_reference<matrix_indirect>, 5199 public iterator_base_traits<typename M::iterator2::iterator_category>::template 5200 iterator_base<iterator2, value_type>::type { 5201 public: 5202 typedef typename M::iterator2::value_type value_type; 5203 typedef typename M::iterator2::difference_type difference_type; 5204 typedef typename M::reference reference; //FIXME due to indexing access 5205 typedef typename M::iterator2::pointer pointer; 5206 typedef iterator1 dual_iterator_type; 5207 typedef reverse_iterator1 dual_reverse_iterator_type; 5208 5209 // Construction and destruction 5210 BOOST_UBLAS_INLINE iterator2()5211 iterator2 (): 5212 container_reference<self_type> (), it1_ (), it2_ () {} 5213 BOOST_UBLAS_INLINE iterator2(self_type & mi,const subiterator1_type & it1,const subiterator2_type & it2)5214 iterator2 (self_type &mi, const subiterator1_type &it1, const subiterator2_type &it2): 5215 container_reference<self_type> (mi), it1_ (it1), it2_ (it2) {} 5216 5217 // Arithmetic 5218 BOOST_UBLAS_INLINE operator ++()5219 iterator2 &operator ++ () { 5220 ++ it2_; 5221 return *this; 5222 } 5223 BOOST_UBLAS_INLINE operator --()5224 iterator2 &operator -- () { 5225 -- it2_; 5226 return *this; 5227 } 5228 BOOST_UBLAS_INLINE operator +=(difference_type n)5229 iterator2 &operator += (difference_type n) { 5230 it2_ += n; 5231 return *this; 5232 } 5233 BOOST_UBLAS_INLINE operator -=(difference_type n)5234 iterator2 &operator -= (difference_type n) { 5235 it2_ -= n; 5236 return *this; 5237 } 5238 BOOST_UBLAS_INLINE operator -(const iterator2 & it) const5239 difference_type operator - (const iterator2 &it) const { 5240 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 5241 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 5242 return it2_ - it.it2_; 5243 } 5244 5245 // Dereference 5246 BOOST_UBLAS_INLINE operator *() const5247 reference operator * () const { 5248 // FIXME replace find with at_element 5249 return (*this) ().data_ (*it1_, *it2_); 5250 } 5251 BOOST_UBLAS_INLINE operator [](difference_type n) const5252 reference operator [] (difference_type n) const { 5253 return *(*this + n); 5254 } 5255 5256 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 5257 BOOST_UBLAS_INLINE 5258 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5259 typename self_type:: 5260 #endif begin() const5261 iterator1 begin () const { 5262 return iterator1 ((*this) (), it1_ ().begin (), it2_); 5263 } 5264 BOOST_UBLAS_INLINE 5265 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5266 typename self_type:: 5267 #endif end() const5268 iterator1 end () const { 5269 return iterator1 ((*this) (), it1_ ().end (), it2_); 5270 } 5271 BOOST_UBLAS_INLINE 5272 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5273 typename self_type:: 5274 #endif rbegin() const5275 reverse_iterator1 rbegin () const { 5276 return reverse_iterator1 (end ()); 5277 } 5278 BOOST_UBLAS_INLINE 5279 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 5280 typename self_type:: 5281 #endif rend() const5282 reverse_iterator1 rend () const { 5283 return reverse_iterator1 (begin ()); 5284 } 5285 #endif 5286 5287 // Indices 5288 BOOST_UBLAS_INLINE index1() const5289 size_type index1 () const { 5290 return it1_.index (); 5291 } 5292 BOOST_UBLAS_INLINE index2() const5293 size_type index2 () const { 5294 return it2_.index (); 5295 } 5296 5297 // Assignment 5298 BOOST_UBLAS_INLINE operator =(const iterator2 & it)5299 iterator2 &operator = (const iterator2 &it) { 5300 container_reference<self_type>::assign (&it ()); 5301 it1_ = it.it1_; 5302 it2_ = it.it2_; 5303 return *this; 5304 } 5305 5306 // Comparison 5307 BOOST_UBLAS_INLINE operator ==(const iterator2 & it) const5308 bool operator == (const iterator2 &it) const { 5309 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 5310 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 5311 return it2_ == it.it2_; 5312 } 5313 BOOST_UBLAS_INLINE operator <(const iterator2 & it) const5314 bool operator < (const iterator2 &it) const { 5315 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ()); 5316 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 5317 return it2_ < it.it2_; 5318 } 5319 5320 private: 5321 subiterator1_type it1_; 5322 subiterator2_type it2_; 5323 5324 friend class const_iterator2; 5325 }; 5326 #endif 5327 5328 BOOST_UBLAS_INLINE begin2()5329 iterator2 begin2 () { 5330 return find2 (0, 0, 0); 5331 } 5332 BOOST_UBLAS_INLINE end2()5333 iterator2 end2 () { 5334 return find2 (0, 0, size2 ()); 5335 } 5336 5337 // Reverse iterators 5338 5339 BOOST_UBLAS_INLINE rbegin1() const5340 const_reverse_iterator1 rbegin1 () const { 5341 return const_reverse_iterator1 (end1 ()); 5342 } 5343 BOOST_UBLAS_INLINE crbegin1() const5344 const_reverse_iterator1 crbegin1 () const { 5345 return rbegin1 (); 5346 } 5347 BOOST_UBLAS_INLINE rend1() const5348 const_reverse_iterator1 rend1 () const { 5349 return const_reverse_iterator1 (begin1 ()); 5350 } 5351 BOOST_UBLAS_INLINE crend1() const5352 const_reverse_iterator1 crend1 () const { 5353 return rend1 (); 5354 } 5355 5356 BOOST_UBLAS_INLINE rbegin1()5357 reverse_iterator1 rbegin1 () { 5358 return reverse_iterator1 (end1 ()); 5359 } 5360 BOOST_UBLAS_INLINE rend1()5361 reverse_iterator1 rend1 () { 5362 return reverse_iterator1 (begin1 ()); 5363 } 5364 5365 BOOST_UBLAS_INLINE rbegin2() const5366 const_reverse_iterator2 rbegin2 () const { 5367 return const_reverse_iterator2 (end2 ()); 5368 } 5369 BOOST_UBLAS_INLINE crbegin2() const5370 const_reverse_iterator2 crbegin2 () const { 5371 return rbegin2 (); 5372 } 5373 BOOST_UBLAS_INLINE rend2() const5374 const_reverse_iterator2 rend2 () const { 5375 return const_reverse_iterator2 (begin2 ()); 5376 } 5377 BOOST_UBLAS_INLINE crend2() const5378 const_reverse_iterator2 crend2 () const { 5379 return rend2 (); 5380 } 5381 5382 BOOST_UBLAS_INLINE rbegin2()5383 reverse_iterator2 rbegin2 () { 5384 return reverse_iterator2 (end2 ()); 5385 } 5386 BOOST_UBLAS_INLINE rend2()5387 reverse_iterator2 rend2 () { 5388 return reverse_iterator2 (begin2 ()); 5389 } 5390 5391 private: 5392 matrix_closure_type data_; 5393 indirect_array_type ia1_; 5394 indirect_array_type ia2_; 5395 }; 5396 5397 // Projections 5398 template<class M, class A> 5399 BOOST_UBLAS_INLINE project(M & data,const indirect_array<A> & ia1,const indirect_array<A> & ia2)5400 matrix_indirect<M, indirect_array<A> > project (M &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) { 5401 return matrix_indirect<M, indirect_array<A> > (data, ia1, ia2); 5402 } 5403 template<class M, class A> 5404 BOOST_UBLAS_INLINE project(const M & data,const indirect_array<A> & ia1,const indirect_array<A> & ia2)5405 const matrix_indirect<const M, indirect_array<A> > project (const M &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) { 5406 // ISSUE was: return matrix_indirect<M, indirect_array<A> > (const_cast<M &> (data), ia1, ia2); 5407 return matrix_indirect<const M, indirect_array<A> > (data, ia1, ia2); 5408 } 5409 template<class M, class IA> 5410 BOOST_UBLAS_INLINE project(matrix_indirect<M,IA> & data,const typename matrix_indirect<M,IA>::range_type & r1,const typename matrix_indirect<M,IA>::range_type & r2)5411 matrix_indirect<M, IA> project (matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::range_type &r1, const typename matrix_indirect<M, IA>::range_type &r2) { 5412 return data.project (r1, r2); 5413 } 5414 template<class M, class IA> 5415 BOOST_UBLAS_INLINE project(const matrix_indirect<M,IA> & data,const typename matrix_indirect<M,IA>::range_type & r1,const typename matrix_indirect<M,IA>::range_type & r2)5416 const matrix_indirect<M, IA> project (const matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::range_type &r1, const typename matrix_indirect<M, IA>::range_type &r2) { 5417 return data.project (r1, r2); 5418 } 5419 template<class M, class IA> 5420 BOOST_UBLAS_INLINE project(matrix_indirect<M,IA> & data,const typename matrix_indirect<M,IA>::slice_type & s1,const typename matrix_indirect<M,IA>::slice_type & s2)5421 matrix_indirect<M, IA> project (matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::slice_type &s1, const typename matrix_indirect<M, IA>::slice_type &s2) { 5422 return data.project (s1, s2); 5423 } 5424 template<class M, class IA> 5425 BOOST_UBLAS_INLINE project(const matrix_indirect<M,IA> & data,const typename matrix_indirect<M,IA>::slice_type & s1,const typename matrix_indirect<M,IA>::slice_type & s2)5426 const matrix_indirect<M, IA> project (const matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::slice_type &s1, const typename matrix_indirect<M, IA>::slice_type &s2) { 5427 return data.project (s1, s2); 5428 } 5429 template<class M, class A> 5430 BOOST_UBLAS_INLINE project(matrix_indirect<M,indirect_array<A>> & data,const indirect_array<A> & ia1,const indirect_array<A> & ia2)5431 matrix_indirect<M, indirect_array<A> > project (matrix_indirect<M, indirect_array<A> > &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) { 5432 return data.project (ia1, ia2); 5433 } 5434 template<class M, class A> 5435 BOOST_UBLAS_INLINE project(const matrix_indirect<M,indirect_array<A>> & data,const indirect_array<A> & ia1,const indirect_array<A> & ia2)5436 const matrix_indirect<M, indirect_array<A> > project (const matrix_indirect<M, indirect_array<A> > &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) { 5437 return data.project (ia1, ia2); 5438 } 5439 5440 /// Specialization of temporary_traits 5441 template <class M> 5442 struct matrix_temporary_traits< matrix_indirect<M> > 5443 : matrix_temporary_traits< M > {}; 5444 template <class M> 5445 struct matrix_temporary_traits< const matrix_indirect<M> > 5446 : matrix_temporary_traits< M > {}; 5447 5448 template <class M> 5449 struct vector_temporary_traits< matrix_indirect<M> > 5450 : vector_temporary_traits< M > {}; 5451 template <class M> 5452 struct vector_temporary_traits< const matrix_indirect<M> > 5453 : vector_temporary_traits< M > {}; 5454 5455 }}} 5456 5457 #endif 5458