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_SYMMETRIC_ 14 #define _BOOST_UBLAS_SYMMETRIC_ 15 16 #include <boost/numeric/ublas/matrix.hpp> 17 #include <boost/numeric/ublas/triangular.hpp> 18 #include <boost/numeric/ublas/detail/temporary.hpp> 19 20 // Iterators based on ideas of Jeremy Siek 21 // Symmetric matrices are square. Thanks to Peter Schmitteckert for spotting this. 22 23 namespace boost { namespace numeric { namespace ublas { 24 25 template<class M> is_symmetric(const M & m)26 bool is_symmetric (const M &m) { 27 typedef typename M::size_type size_type; 28 29 if (m.size1 () != m.size2 ()) 30 return false; 31 size_type size = BOOST_UBLAS_SAME (m.size1 (), m.size2 ()); 32 for (size_type i = 0; i < size; ++ i) { 33 for (size_type j = i; j < size; ++ j) { 34 if (m (i, j) != m (j, i)) 35 return false; 36 } 37 } 38 return true; 39 } 40 41 // Array based symmetric matrix class 42 template<class T, class TRI, class L, class A> 43 class symmetric_matrix: 44 public matrix_container<symmetric_matrix<T, TRI, L, A> > { 45 46 typedef T *pointer; 47 typedef TRI triangular_type; 48 typedef L layout_type; 49 typedef symmetric_matrix<T, TRI, L, A> self_type; 50 public: 51 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 52 using matrix_container<self_type>::operator (); 53 #endif 54 typedef typename A::size_type size_type; 55 typedef typename A::difference_type difference_type; 56 typedef T value_type; 57 typedef const T &const_reference; 58 typedef T &reference; 59 typedef A array_type; 60 61 typedef const matrix_reference<const self_type> const_closure_type; 62 typedef matrix_reference<self_type> closure_type; 63 typedef vector<T, A> vector_temporary_type; 64 typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix 65 typedef packed_tag storage_category; 66 typedef typename L::orientation_category orientation_category; 67 68 // Construction and destruction 69 BOOST_UBLAS_INLINE symmetric_matrix()70 symmetric_matrix (): 71 matrix_container<self_type> (), 72 size_ (0), data_ (0) {} 73 BOOST_UBLAS_INLINE symmetric_matrix(size_type size)74 symmetric_matrix (size_type size): 75 matrix_container<self_type> (), 76 size_ (BOOST_UBLAS_SAME (size, size)), data_ (triangular_type::packed_size (layout_type (), size, size)) { 77 } 78 BOOST_UBLAS_INLINE symmetric_matrix(size_type size1,size_type size2)79 symmetric_matrix (size_type size1, size_type size2): 80 matrix_container<self_type> (), 81 size_ (BOOST_UBLAS_SAME (size1, size2)), data_ (triangular_type::packed_size (layout_type (), size1, size2)) { 82 } 83 BOOST_UBLAS_INLINE symmetric_matrix(size_type size,const array_type & data)84 symmetric_matrix (size_type size, const array_type &data): 85 matrix_container<self_type> (), 86 size_ (size), data_ (data) {} 87 BOOST_UBLAS_INLINE symmetric_matrix(const symmetric_matrix & m)88 symmetric_matrix (const symmetric_matrix &m): 89 matrix_container<self_type> (), 90 size_ (m.size_), data_ (m.data_) {} 91 template<class AE> 92 BOOST_UBLAS_INLINE symmetric_matrix(const matrix_expression<AE> & ae)93 symmetric_matrix (const matrix_expression<AE> &ae): 94 matrix_container<self_type> (), 95 size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())), 96 data_ (triangular_type::packed_size (layout_type (), size_, size_)) { 97 matrix_assign<scalar_assign> (*this, ae); 98 } 99 100 // Accessors 101 BOOST_UBLAS_INLINE size1() const102 size_type size1 () const { 103 return size_; 104 } 105 BOOST_UBLAS_INLINE size2() const106 size_type size2 () const { 107 return size_; 108 } 109 110 // Storage accessors 111 BOOST_UBLAS_INLINE data() const112 const array_type &data () const { 113 return data_; 114 } 115 BOOST_UBLAS_INLINE data()116 array_type &data () { 117 return data_; 118 } 119 120 // Resizing 121 BOOST_UBLAS_INLINE resize(size_type size,bool preserve=true)122 void resize (size_type size, bool preserve = true) { 123 if (preserve) { 124 self_type temporary (size, size); 125 detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary); 126 } 127 else { 128 data ().resize (triangular_type::packed_size (layout_type (), size, size)); 129 size_ = size; 130 } 131 } 132 BOOST_UBLAS_INLINE resize(size_type size1,size_type size2,bool preserve=true)133 void resize (size_type size1, size_type size2, bool preserve = true) { 134 resize (BOOST_UBLAS_SAME (size1, size2), preserve); 135 } 136 BOOST_UBLAS_INLINE resize_packed_preserve(size_type size)137 void resize_packed_preserve (size_type size) { 138 size_ = BOOST_UBLAS_SAME (size, size); 139 data ().resize (triangular_type::packed_size (layout_type (), size_, size_), value_type ()); 140 } 141 142 // Element access 143 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const144 const_reference operator () (size_type i, size_type j) const { 145 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 146 BOOST_UBLAS_CHECK (j < size_, bad_index ()); 147 if (triangular_type::other (i, j)) 148 return data () [triangular_type::element (layout_type (), i, size_, j, size_)]; 149 else 150 return data () [triangular_type::element (layout_type (), j, size_, i, size_)]; 151 } 152 BOOST_UBLAS_INLINE at_element(size_type i,size_type j)153 reference at_element (size_type i, size_type j) { 154 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 155 BOOST_UBLAS_CHECK (j < size_, bad_index ()); 156 return data () [triangular_type::element (layout_type (), i, size_, j, size_)]; 157 } 158 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j)159 reference operator () (size_type i, size_type j) { 160 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 161 BOOST_UBLAS_CHECK (j < size_, bad_index ()); 162 if (triangular_type::other (i, j)) 163 return data () [triangular_type::element (layout_type (), i, size_, j, size_)]; 164 else 165 return data () [triangular_type::element (layout_type (), j, size_, i, size_)]; 166 } 167 168 // Element assignment 169 BOOST_UBLAS_INLINE insert_element(size_type i,size_type j,const_reference t)170 reference insert_element (size_type i, size_type j, const_reference t) { 171 return (operator () (i, j) = t); 172 } 173 BOOST_UBLAS_INLINE erase_element(size_type i,size_type j)174 void erase_element (size_type i, size_type j) { 175 operator () (i, j) = value_type/*zero*/(); 176 } 177 178 // Zeroing 179 BOOST_UBLAS_INLINE clear()180 void clear () { 181 // data ().clear (); 182 std::fill (data ().begin (), data ().end (), value_type/*zero*/()); 183 } 184 185 // Assignment 186 BOOST_UBLAS_INLINE operator =(const symmetric_matrix & m)187 symmetric_matrix &operator = (const symmetric_matrix &m) { 188 size_ = m.size_; 189 data () = m.data (); 190 return *this; 191 } 192 BOOST_UBLAS_INLINE assign_temporary(symmetric_matrix & m)193 symmetric_matrix &assign_temporary (symmetric_matrix &m) { 194 swap (m); 195 return *this; 196 } 197 template<class AE> 198 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)199 symmetric_matrix &operator = (const matrix_expression<AE> &ae) { 200 self_type temporary (ae); 201 return assign_temporary (temporary); 202 } 203 template<class AE> 204 BOOST_UBLAS_INLINE assign(const matrix_expression<AE> & ae)205 symmetric_matrix &assign (const matrix_expression<AE> &ae) { 206 matrix_assign<scalar_assign> (*this, ae); 207 return *this; 208 } 209 template<class AE> 210 BOOST_UBLAS_INLINE operator +=(const matrix_expression<AE> & ae)211 symmetric_matrix& operator += (const matrix_expression<AE> &ae) { 212 self_type temporary (*this + ae); 213 return assign_temporary (temporary); 214 } 215 template<class AE> 216 BOOST_UBLAS_INLINE plus_assign(const matrix_expression<AE> & ae)217 symmetric_matrix &plus_assign (const matrix_expression<AE> &ae) { 218 matrix_assign<scalar_plus_assign> (*this, ae); 219 return *this; 220 } 221 template<class AE> 222 BOOST_UBLAS_INLINE operator -=(const matrix_expression<AE> & ae)223 symmetric_matrix& operator -= (const matrix_expression<AE> &ae) { 224 self_type temporary (*this - ae); 225 return assign_temporary (temporary); 226 } 227 template<class AE> 228 BOOST_UBLAS_INLINE minus_assign(const matrix_expression<AE> & ae)229 symmetric_matrix &minus_assign (const matrix_expression<AE> &ae) { 230 matrix_assign<scalar_minus_assign> (*this, ae); 231 return *this; 232 } 233 template<class AT> 234 BOOST_UBLAS_INLINE operator *=(const AT & at)235 symmetric_matrix& operator *= (const AT &at) { 236 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 237 return *this; 238 } 239 template<class AT> 240 BOOST_UBLAS_INLINE operator /=(const AT & at)241 symmetric_matrix& operator /= (const AT &at) { 242 matrix_assign_scalar<scalar_divides_assign> (*this, at); 243 return *this; 244 } 245 246 // Swapping 247 BOOST_UBLAS_INLINE swap(symmetric_matrix & m)248 void swap (symmetric_matrix &m) { 249 if (this != &m) { 250 std::swap (size_, m.size_); 251 data ().swap (m.data ()); 252 } 253 } 254 BOOST_UBLAS_INLINE swap(symmetric_matrix & m1,symmetric_matrix & m2)255 friend void swap (symmetric_matrix &m1, symmetric_matrix &m2) { 256 m1.swap (m2); 257 } 258 259 // Iterator types 260 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 261 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1; 262 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2; 263 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1; 264 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2; 265 #else 266 class const_iterator1; 267 class iterator1; 268 class const_iterator2; 269 class iterator2; 270 #endif 271 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 272 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 273 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 274 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 275 276 // Element lookup 277 BOOST_UBLAS_INLINE find1(int,size_type i,size_type j) const278 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const { 279 return const_iterator1 (*this, i, j); 280 } 281 BOOST_UBLAS_INLINE find1(int rank,size_type i,size_type j)282 iterator1 find1 (int rank, size_type i, size_type j) { 283 if (rank == 1) 284 i = triangular_type::mutable_restrict1 (i, j, size1(), size2()); 285 if (rank == 0) 286 i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2()); 287 return iterator1 (*this, i, j); 288 } 289 BOOST_UBLAS_INLINE find2(int,size_type i,size_type j) const290 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const { 291 return const_iterator2 (*this, i, j); 292 } 293 BOOST_UBLAS_INLINE find2(int rank,size_type i,size_type j)294 iterator2 find2 (int rank, size_type i, size_type j) { 295 if (rank == 1) 296 j = triangular_type::mutable_restrict2 (i, j, size1(), size2()); 297 if (rank == 0) 298 j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2()); 299 return iterator2 (*this, i, j); 300 } 301 302 // Iterators simply are indices. 303 304 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 305 class const_iterator1: 306 public container_const_reference<symmetric_matrix>, 307 public random_access_iterator_base<dense_random_access_iterator_tag, 308 const_iterator1, value_type> { 309 public: 310 typedef typename symmetric_matrix::value_type value_type; 311 typedef typename symmetric_matrix::difference_type difference_type; 312 typedef typename symmetric_matrix::const_reference reference; 313 typedef const typename symmetric_matrix::pointer pointer; 314 315 typedef const_iterator2 dual_iterator_type; 316 typedef const_reverse_iterator2 dual_reverse_iterator_type; 317 318 // Construction and destruction 319 BOOST_UBLAS_INLINE const_iterator1()320 const_iterator1 (): 321 container_const_reference<self_type> (), it1_ (), it2_ () {} 322 BOOST_UBLAS_INLINE const_iterator1(const self_type & m,size_type it1,size_type it2)323 const_iterator1 (const self_type &m, size_type it1, size_type it2): 324 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {} 325 BOOST_UBLAS_INLINE const_iterator1(const iterator1 & it)326 const_iterator1 (const iterator1 &it): 327 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {} 328 329 // Arithmetic 330 BOOST_UBLAS_INLINE operator ++()331 const_iterator1 &operator ++ () { 332 ++ it1_; 333 return *this; 334 } 335 BOOST_UBLAS_INLINE operator --()336 const_iterator1 &operator -- () { 337 -- it1_; 338 return *this; 339 } 340 BOOST_UBLAS_INLINE operator +=(difference_type n)341 const_iterator1 &operator += (difference_type n) { 342 it1_ += n; 343 return *this; 344 } 345 BOOST_UBLAS_INLINE operator -=(difference_type n)346 const_iterator1 &operator -= (difference_type n) { 347 it1_ -= n; 348 return *this; 349 } 350 BOOST_UBLAS_INLINE operator -(const const_iterator1 & it) const351 difference_type operator - (const const_iterator1 &it) const { 352 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 353 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 354 return it1_ - it.it1_; 355 } 356 357 // Dereference 358 BOOST_UBLAS_INLINE operator *() const359 const_reference operator * () const { 360 return (*this) () (it1_, it2_); 361 } 362 BOOST_UBLAS_INLINE operator [](difference_type n) const363 const_reference operator [] (difference_type n) const { 364 return *(*this + n); 365 } 366 367 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 368 BOOST_UBLAS_INLINE 369 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 370 typename self_type:: 371 #endif begin() const372 const_iterator2 begin () const { 373 return (*this) ().find2 (1, it1_, 0); 374 } 375 BOOST_UBLAS_INLINE 376 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 377 typename self_type:: 378 #endif cbegin() const379 const_iterator2 cbegin () const { 380 return begin (); 381 } 382 BOOST_UBLAS_INLINE 383 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 384 typename self_type:: 385 #endif end() const386 const_iterator2 end () const { 387 return (*this) ().find2 (1, it1_, (*this) ().size2 ()); 388 } 389 BOOST_UBLAS_INLINE 390 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 391 typename self_type:: 392 #endif cend() const393 const_iterator2 cend () const { 394 return end (); 395 } 396 BOOST_UBLAS_INLINE 397 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 398 typename self_type:: 399 #endif rbegin() const400 const_reverse_iterator2 rbegin () const { 401 return const_reverse_iterator2 (end ()); 402 } 403 BOOST_UBLAS_INLINE 404 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 405 typename self_type:: 406 #endif crbegin() const407 const_reverse_iterator2 crbegin () const { 408 return rbegin (); 409 } 410 BOOST_UBLAS_INLINE 411 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 412 typename self_type:: 413 #endif rend() const414 const_reverse_iterator2 rend () const { 415 return const_reverse_iterator2 (begin ()); 416 } 417 BOOST_UBLAS_INLINE 418 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 419 typename self_type:: 420 #endif crend() const421 const_reverse_iterator2 crend () const { 422 return rend (); 423 } 424 #endif 425 426 // Indices 427 BOOST_UBLAS_INLINE index1() const428 size_type index1 () const { 429 return it1_; 430 } 431 BOOST_UBLAS_INLINE index2() const432 size_type index2 () const { 433 return it2_; 434 } 435 436 // Assignment 437 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)438 const_iterator1 &operator = (const const_iterator1 &it) { 439 container_const_reference<self_type>::assign (&it ()); 440 it1_ = it.it1_; 441 it2_ = it.it2_; 442 return *this; 443 } 444 445 // Comparison 446 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const447 bool operator == (const const_iterator1 &it) const { 448 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 449 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 450 return it1_ == it.it1_; 451 } 452 BOOST_UBLAS_INLINE operator <(const const_iterator1 & it) const453 bool operator < (const const_iterator1 &it) const { 454 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 455 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 456 return it1_ < it.it1_; 457 } 458 459 private: 460 size_type it1_; 461 size_type it2_; 462 }; 463 #endif 464 465 BOOST_UBLAS_INLINE begin1() const466 const_iterator1 begin1 () const { 467 return find1 (0, 0, 0); 468 } 469 BOOST_UBLAS_INLINE cbegin1() const470 const_iterator1 cbegin1 () const { 471 return begin1 (); 472 } 473 BOOST_UBLAS_INLINE end1() const474 const_iterator1 end1 () const { 475 return find1 (0, size_, 0); 476 } 477 BOOST_UBLAS_INLINE cend1() const478 const_iterator1 cend1 () const { 479 return end1 (); 480 } 481 482 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 483 class iterator1: 484 public container_reference<symmetric_matrix>, 485 public random_access_iterator_base<packed_random_access_iterator_tag, 486 iterator1, value_type> { 487 public: 488 typedef typename symmetric_matrix::value_type value_type; 489 typedef typename symmetric_matrix::difference_type difference_type; 490 typedef typename symmetric_matrix::reference reference; 491 typedef typename symmetric_matrix::pointer pointer; 492 typedef iterator2 dual_iterator_type; 493 typedef reverse_iterator2 dual_reverse_iterator_type; 494 495 // Construction and destruction 496 BOOST_UBLAS_INLINE iterator1()497 iterator1 (): 498 container_reference<self_type> (), it1_ (), it2_ () {} 499 BOOST_UBLAS_INLINE iterator1(self_type & m,size_type it1,size_type it2)500 iterator1 (self_type &m, size_type it1, size_type it2): 501 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {} 502 503 // Arithmetic 504 BOOST_UBLAS_INLINE operator ++()505 iterator1 &operator ++ () { 506 ++ it1_; 507 return *this; 508 } 509 BOOST_UBLAS_INLINE operator --()510 iterator1 &operator -- () { 511 -- it1_; 512 return *this; 513 } 514 BOOST_UBLAS_INLINE operator +=(difference_type n)515 iterator1 &operator += (difference_type n) { 516 it1_ += n; 517 return *this; 518 } 519 BOOST_UBLAS_INLINE operator -=(difference_type n)520 iterator1 &operator -= (difference_type n) { 521 it1_ -= n; 522 return *this; 523 } 524 BOOST_UBLAS_INLINE operator -(const iterator1 & it) const525 difference_type operator - (const iterator1 &it) const { 526 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 527 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 528 return it1_ - it.it1_; 529 } 530 531 // Dereference 532 BOOST_UBLAS_INLINE operator *() const533 reference operator * () const { 534 return (*this) () (it1_, it2_); 535 } 536 BOOST_UBLAS_INLINE operator [](difference_type n) const537 reference operator [] (difference_type n) const { 538 return *(*this + n); 539 } 540 541 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 542 BOOST_UBLAS_INLINE 543 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 544 typename self_type:: 545 #endif begin() const546 iterator2 begin () const { 547 return (*this) ().find2 (1, it1_, 0); 548 } 549 BOOST_UBLAS_INLINE 550 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 551 typename self_type:: 552 #endif end() const553 iterator2 end () const { 554 return (*this) ().find2 (1, it1_, (*this) ().size2 ()); 555 } 556 BOOST_UBLAS_INLINE 557 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 558 typename self_type:: 559 #endif rbegin() const560 reverse_iterator2 rbegin () const { 561 return reverse_iterator2 (end ()); 562 } 563 BOOST_UBLAS_INLINE 564 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 565 typename self_type:: 566 #endif rend() const567 reverse_iterator2 rend () const { 568 return reverse_iterator2 (begin ()); 569 } 570 #endif 571 572 // Indices 573 BOOST_UBLAS_INLINE index1() const574 size_type index1 () const { 575 return it1_; 576 } 577 BOOST_UBLAS_INLINE index2() const578 size_type index2 () const { 579 return it2_; 580 } 581 582 // Assignment 583 BOOST_UBLAS_INLINE operator =(const iterator1 & it)584 iterator1 &operator = (const iterator1 &it) { 585 container_reference<self_type>::assign (&it ()); 586 it1_ = it.it1_; 587 it2_ = it.it2_; 588 return *this; 589 } 590 591 // Comparison 592 BOOST_UBLAS_INLINE operator ==(const iterator1 & it) const593 bool operator == (const iterator1 &it) const { 594 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 595 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 596 return it1_ == it.it1_; 597 } 598 BOOST_UBLAS_INLINE operator <(const iterator1 & it) const599 bool operator < (const iterator1 &it) const { 600 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 601 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 602 return it1_ < it.it1_; 603 } 604 605 private: 606 size_type it1_; 607 size_type it2_; 608 609 friend class const_iterator1; 610 }; 611 #endif 612 613 BOOST_UBLAS_INLINE begin1()614 iterator1 begin1 () { 615 return find1 (0, 0, 0); 616 } 617 BOOST_UBLAS_INLINE end1()618 iterator1 end1 () { 619 return find1 (0, size_, 0); 620 } 621 622 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 623 class const_iterator2: 624 public container_const_reference<symmetric_matrix>, 625 public random_access_iterator_base<dense_random_access_iterator_tag, 626 const_iterator2, value_type> { 627 public: 628 typedef typename symmetric_matrix::value_type value_type; 629 typedef typename symmetric_matrix::difference_type difference_type; 630 typedef typename symmetric_matrix::const_reference reference; 631 typedef const typename symmetric_matrix::pointer pointer; 632 633 typedef const_iterator1 dual_iterator_type; 634 typedef const_reverse_iterator1 dual_reverse_iterator_type; 635 636 // Construction and destruction 637 BOOST_UBLAS_INLINE const_iterator2()638 const_iterator2 (): 639 container_const_reference<self_type> (), it1_ (), it2_ () {} 640 BOOST_UBLAS_INLINE const_iterator2(const self_type & m,size_type it1,size_type it2)641 const_iterator2 (const self_type &m, size_type it1, size_type it2): 642 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {} 643 BOOST_UBLAS_INLINE const_iterator2(const iterator2 & it)644 const_iterator2 (const iterator2 &it): 645 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {} 646 647 // Arithmetic 648 BOOST_UBLAS_INLINE operator ++()649 const_iterator2 &operator ++ () { 650 ++ it2_; 651 return *this; 652 } 653 BOOST_UBLAS_INLINE operator --()654 const_iterator2 &operator -- () { 655 -- it2_; 656 return *this; 657 } 658 BOOST_UBLAS_INLINE operator +=(difference_type n)659 const_iterator2 &operator += (difference_type n) { 660 it2_ += n; 661 return *this; 662 } 663 BOOST_UBLAS_INLINE operator -=(difference_type n)664 const_iterator2 &operator -= (difference_type n) { 665 it2_ -= n; 666 return *this; 667 } 668 BOOST_UBLAS_INLINE operator -(const const_iterator2 & it) const669 difference_type operator - (const const_iterator2 &it) const { 670 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 671 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 672 return it2_ - it.it2_; 673 } 674 675 // Dereference 676 BOOST_UBLAS_INLINE operator *() const677 const_reference operator * () const { 678 return (*this) () (it1_, it2_); 679 } 680 BOOST_UBLAS_INLINE operator [](difference_type n) const681 const_reference operator [] (difference_type n) const { 682 return *(*this + n); 683 } 684 685 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 686 BOOST_UBLAS_INLINE 687 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 688 typename self_type:: 689 #endif begin() const690 const_iterator1 begin () const { 691 return (*this) ().find1 (1, 0, it2_); 692 } 693 BOOST_UBLAS_INLINE 694 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 695 typename self_type:: 696 #endif cbegin() const697 const_iterator1 cbegin () const { 698 return begin (); 699 } 700 BOOST_UBLAS_INLINE 701 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 702 typename self_type:: 703 #endif end() const704 const_iterator1 end () const { 705 return (*this) ().find1 (1, (*this) ().size1 (), it2_); 706 } 707 BOOST_UBLAS_INLINE 708 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 709 typename self_type:: 710 #endif cend() const711 const_iterator1 cend () const { 712 return end (); 713 } 714 BOOST_UBLAS_INLINE 715 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 716 typename self_type:: 717 #endif rbegin() const718 const_reverse_iterator1 rbegin () const { 719 return const_reverse_iterator1 (end ()); 720 } 721 BOOST_UBLAS_INLINE 722 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 723 typename self_type:: 724 #endif crbegin() const725 const_reverse_iterator1 crbegin () const { 726 return rbegin (); 727 } 728 BOOST_UBLAS_INLINE 729 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 730 typename self_type:: 731 #endif rend() const732 const_reverse_iterator1 rend () const { 733 return const_reverse_iterator1 (begin ()); 734 } 735 BOOST_UBLAS_INLINE 736 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 737 typename self_type:: 738 #endif crend() const739 const_reverse_iterator1 crend () const { 740 return rend (); 741 } 742 #endif 743 744 // Indices 745 BOOST_UBLAS_INLINE index1() const746 size_type index1 () const { 747 return it1_; 748 } 749 BOOST_UBLAS_INLINE index2() const750 size_type index2 () const { 751 return it2_; 752 } 753 754 // Assignment 755 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)756 const_iterator2 &operator = (const const_iterator2 &it) { 757 container_const_reference<self_type>::assign (&it ()); 758 it1_ = it.it1_; 759 it2_ = it.it2_; 760 return *this; 761 } 762 763 // Comparison 764 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const765 bool operator == (const const_iterator2 &it) const { 766 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 767 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 768 return it2_ == it.it2_; 769 } 770 BOOST_UBLAS_INLINE operator <(const const_iterator2 & it) const771 bool operator < (const const_iterator2 &it) const { 772 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 773 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 774 return it2_ < it.it2_; 775 } 776 777 private: 778 size_type it1_; 779 size_type it2_; 780 }; 781 #endif 782 783 BOOST_UBLAS_INLINE begin2() const784 const_iterator2 begin2 () const { 785 return find2 (0, 0, 0); 786 } 787 BOOST_UBLAS_INLINE cbegin2() const788 const_iterator2 cbegin2 () const { 789 return begin2 (); 790 } 791 BOOST_UBLAS_INLINE end2() const792 const_iterator2 end2 () const { 793 return find2 (0, 0, size_); 794 } 795 BOOST_UBLAS_INLINE cend2() const796 const_iterator2 cend2 () const { 797 return end2 (); 798 } 799 800 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 801 class iterator2: 802 public container_reference<symmetric_matrix>, 803 public random_access_iterator_base<packed_random_access_iterator_tag, 804 iterator2, value_type> { 805 public: 806 typedef typename symmetric_matrix::value_type value_type; 807 typedef typename symmetric_matrix::difference_type difference_type; 808 typedef typename symmetric_matrix::reference reference; 809 typedef typename symmetric_matrix::pointer pointer; 810 811 typedef iterator1 dual_iterator_type; 812 typedef reverse_iterator1 dual_reverse_iterator_type; 813 814 // Construction and destruction 815 BOOST_UBLAS_INLINE iterator2()816 iterator2 (): 817 container_reference<self_type> (), it1_ (), it2_ () {} 818 BOOST_UBLAS_INLINE iterator2(self_type & m,size_type it1,size_type it2)819 iterator2 (self_type &m, size_type it1, size_type it2): 820 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {} 821 822 // Arithmetic 823 BOOST_UBLAS_INLINE operator ++()824 iterator2 &operator ++ () { 825 ++ it2_; 826 return *this; 827 } 828 BOOST_UBLAS_INLINE operator --()829 iterator2 &operator -- () { 830 -- it2_; 831 return *this; 832 } 833 BOOST_UBLAS_INLINE operator +=(difference_type n)834 iterator2 &operator += (difference_type n) { 835 it2_ += n; 836 return *this; 837 } 838 BOOST_UBLAS_INLINE operator -=(difference_type n)839 iterator2 &operator -= (difference_type n) { 840 it2_ -= n; 841 return *this; 842 } 843 BOOST_UBLAS_INLINE operator -(const iterator2 & it) const844 difference_type operator - (const iterator2 &it) const { 845 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 846 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 847 return it2_ - it.it2_; 848 } 849 850 // Dereference 851 BOOST_UBLAS_INLINE operator *() const852 reference operator * () const { 853 return (*this) () (it1_, it2_); 854 } 855 BOOST_UBLAS_INLINE operator [](difference_type n) const856 reference operator [] (difference_type n) const { 857 return *(*this + n); 858 } 859 860 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 861 BOOST_UBLAS_INLINE 862 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 863 typename self_type:: 864 #endif begin() const865 iterator1 begin () const { 866 return (*this) ().find1 (1, 0, it2_); 867 } 868 BOOST_UBLAS_INLINE 869 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 870 typename self_type:: 871 #endif end() const872 iterator1 end () const { 873 return (*this) ().find1 (1, (*this) ().size1 (), it2_); 874 } 875 BOOST_UBLAS_INLINE 876 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 877 typename self_type:: 878 #endif rbegin() const879 reverse_iterator1 rbegin () const { 880 return reverse_iterator1 (end ()); 881 } 882 BOOST_UBLAS_INLINE 883 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 884 typename self_type:: 885 #endif rend() const886 reverse_iterator1 rend () const { 887 return reverse_iterator1 (begin ()); 888 } 889 #endif 890 891 // Indices 892 BOOST_UBLAS_INLINE index1() const893 size_type index1 () const { 894 return it1_; 895 } 896 BOOST_UBLAS_INLINE index2() const897 size_type index2 () const { 898 return it2_; 899 } 900 901 // Assignment 902 BOOST_UBLAS_INLINE operator =(const iterator2 & it)903 iterator2 &operator = (const iterator2 &it) { 904 container_reference<self_type>::assign (&it ()); 905 it1_ = it.it1_; 906 it2_ = it.it2_; 907 return *this; 908 } 909 910 // Comparison 911 BOOST_UBLAS_INLINE operator ==(const iterator2 & it) const912 bool operator == (const iterator2 &it) const { 913 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 914 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 915 return it2_ == it.it2_; 916 } 917 BOOST_UBLAS_INLINE operator <(const iterator2 & it) const918 bool operator < (const iterator2 &it) const { 919 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 920 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 921 return it2_ < it.it2_; 922 } 923 924 private: 925 size_type it1_; 926 size_type it2_; 927 928 friend class const_iterator2; 929 }; 930 #endif 931 932 BOOST_UBLAS_INLINE begin2()933 iterator2 begin2 () { 934 return find2 (0, 0, 0); 935 } 936 BOOST_UBLAS_INLINE end2()937 iterator2 end2 () { 938 return find2 (0, 0, size_); 939 } 940 941 // Reverse iterators 942 943 BOOST_UBLAS_INLINE rbegin1() const944 const_reverse_iterator1 rbegin1 () const { 945 return const_reverse_iterator1 (end1 ()); 946 } 947 BOOST_UBLAS_INLINE crbegin1() const948 const_reverse_iterator1 crbegin1 () const { 949 return rbegin1 (); 950 } 951 BOOST_UBLAS_INLINE rend1() const952 const_reverse_iterator1 rend1 () const { 953 return const_reverse_iterator1 (begin1 ()); 954 } 955 BOOST_UBLAS_INLINE crend1() const956 const_reverse_iterator1 crend1 () const { 957 return rend1 (); 958 } 959 960 BOOST_UBLAS_INLINE rbegin1()961 reverse_iterator1 rbegin1 () { 962 return reverse_iterator1 (end1 ()); 963 } 964 BOOST_UBLAS_INLINE rend1()965 reverse_iterator1 rend1 () { 966 return reverse_iterator1 (begin1 ()); 967 } 968 969 BOOST_UBLAS_INLINE rbegin2() const970 const_reverse_iterator2 rbegin2 () const { 971 return const_reverse_iterator2 (end2 ()); 972 } 973 BOOST_UBLAS_INLINE crbegin2() const974 const_reverse_iterator2 crbegin2 () const { 975 return rbegin2 (); 976 } 977 BOOST_UBLAS_INLINE rend2() const978 const_reverse_iterator2 rend2 () const { 979 return const_reverse_iterator2 (begin2 ()); 980 } 981 BOOST_UBLAS_INLINE crend2() const982 const_reverse_iterator2 crend2 () const { 983 return rend2 (); 984 } 985 BOOST_UBLAS_INLINE rbegin2()986 reverse_iterator2 rbegin2 () { 987 return reverse_iterator2 (end2 ()); 988 } 989 BOOST_UBLAS_INLINE rend2()990 reverse_iterator2 rend2 () { 991 return reverse_iterator2 (begin2 ()); 992 } 993 994 private: 995 size_type size_; 996 array_type data_; 997 }; 998 999 1000 // Symmetric matrix adaptor class 1001 template<class M, class TRI> 1002 class symmetric_adaptor: 1003 public matrix_expression<symmetric_adaptor<M, TRI> > { 1004 1005 typedef symmetric_adaptor<M, TRI> self_type; 1006 public: 1007 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 1008 using matrix_expression<self_type>::operator (); 1009 #endif 1010 typedef const M const_matrix_type; 1011 typedef M matrix_type; 1012 typedef TRI triangular_type; 1013 typedef typename M::size_type size_type; 1014 typedef typename M::difference_type difference_type; 1015 typedef typename M::value_type value_type; 1016 typedef typename M::const_reference const_reference; 1017 typedef typename boost::mpl::if_<boost::is_const<M>, 1018 typename M::const_reference, 1019 typename M::reference>::type reference; 1020 typedef typename boost::mpl::if_<boost::is_const<M>, 1021 typename M::const_closure_type, 1022 typename M::closure_type>::type matrix_closure_type; 1023 typedef const self_type const_closure_type; 1024 typedef self_type closure_type; 1025 // Replaced by _temporary_traits to avoid type requirements on M 1026 //typedef typename M::vector_temporary_type vector_temporary_type; 1027 //typedef typename M::matrix_temporary_type matrix_temporary_type; 1028 typedef typename storage_restrict_traits<typename M::storage_category, 1029 packed_proxy_tag>::storage_category storage_category; 1030 typedef typename M::orientation_category orientation_category; 1031 1032 // Construction and destruction 1033 BOOST_UBLAS_INLINE symmetric_adaptor(matrix_type & data)1034 symmetric_adaptor (matrix_type &data): 1035 matrix_expression<self_type> (), 1036 data_ (data) { 1037 BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ()); 1038 } 1039 BOOST_UBLAS_INLINE symmetric_adaptor(const symmetric_adaptor & m)1040 symmetric_adaptor (const symmetric_adaptor &m): 1041 matrix_expression<self_type> (), 1042 data_ (m.data_) { 1043 BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ()); 1044 } 1045 1046 // Accessors 1047 BOOST_UBLAS_INLINE size1() const1048 size_type size1 () const { 1049 return data_.size1 (); 1050 } 1051 BOOST_UBLAS_INLINE size2() const1052 size_type size2 () const { 1053 return data_.size2 (); 1054 } 1055 1056 // Storage accessors 1057 BOOST_UBLAS_INLINE data() const1058 const matrix_closure_type &data () const { 1059 return data_; 1060 } 1061 BOOST_UBLAS_INLINE data()1062 matrix_closure_type &data () { 1063 return data_; 1064 } 1065 1066 // Element access 1067 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 1068 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const1069 const_reference operator () (size_type i, size_type j) const { 1070 BOOST_UBLAS_CHECK (i < size1 (), bad_index ()); 1071 BOOST_UBLAS_CHECK (j < size2 (), bad_index ()); 1072 if (triangular_type::other (i, j)) 1073 return data () (i, j); 1074 else 1075 return data () (j, i); 1076 } 1077 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j)1078 reference operator () (size_type i, size_type j) { 1079 BOOST_UBLAS_CHECK (i < size1 (), bad_index ()); 1080 BOOST_UBLAS_CHECK (j < size2 (), bad_index ()); 1081 if (triangular_type::other (i, j)) 1082 return data () (i, j); 1083 else 1084 return data () (j, i); 1085 } 1086 #else 1087 BOOST_UBLAS_INLINE operator ()(size_type i,size_type j) const1088 reference operator () (size_type i, size_type j) const { 1089 BOOST_UBLAS_CHECK (i < size1 (), bad_index ()); 1090 BOOST_UBLAS_CHECK (j < size2 (), bad_index ()); 1091 if (triangular_type::other (i, j)) 1092 return data () (i, j); 1093 else 1094 return data () (j, i); 1095 } 1096 #endif 1097 1098 // Assignment 1099 BOOST_UBLAS_INLINE operator =(const symmetric_adaptor & m)1100 symmetric_adaptor &operator = (const symmetric_adaptor &m) { 1101 matrix_assign<scalar_assign, triangular_type> (*this, m); 1102 return *this; 1103 } 1104 BOOST_UBLAS_INLINE assign_temporary(symmetric_adaptor & m)1105 symmetric_adaptor &assign_temporary (symmetric_adaptor &m) { 1106 *this = m; 1107 return *this; 1108 } 1109 template<class AE> 1110 BOOST_UBLAS_INLINE operator =(const matrix_expression<AE> & ae)1111 symmetric_adaptor &operator = (const matrix_expression<AE> &ae) { 1112 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae)); 1113 return *this; 1114 } 1115 template<class AE> 1116 BOOST_UBLAS_INLINE assign(const matrix_expression<AE> & ae)1117 symmetric_adaptor &assign (const matrix_expression<AE> &ae) { 1118 matrix_assign<scalar_assign, triangular_type> (*this, ae); 1119 return *this; 1120 } 1121 template<class AE> 1122 BOOST_UBLAS_INLINE operator +=(const matrix_expression<AE> & ae)1123 symmetric_adaptor& operator += (const matrix_expression<AE> &ae) { 1124 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae)); 1125 return *this; 1126 } 1127 template<class AE> 1128 BOOST_UBLAS_INLINE plus_assign(const matrix_expression<AE> & ae)1129 symmetric_adaptor &plus_assign (const matrix_expression<AE> &ae) { 1130 matrix_assign<scalar_plus_assign, triangular_type> (*this, ae); 1131 return *this; 1132 } 1133 template<class AE> 1134 BOOST_UBLAS_INLINE operator -=(const matrix_expression<AE> & ae)1135 symmetric_adaptor& operator -= (const matrix_expression<AE> &ae) { 1136 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae)); 1137 return *this; 1138 } 1139 template<class AE> 1140 BOOST_UBLAS_INLINE minus_assign(const matrix_expression<AE> & ae)1141 symmetric_adaptor &minus_assign (const matrix_expression<AE> &ae) { 1142 matrix_assign<scalar_minus_assign, triangular_type> (*this, ae); 1143 return *this; 1144 } 1145 template<class AT> 1146 BOOST_UBLAS_INLINE operator *=(const AT & at)1147 symmetric_adaptor& operator *= (const AT &at) { 1148 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 1149 return *this; 1150 } 1151 template<class AT> 1152 BOOST_UBLAS_INLINE operator /=(const AT & at)1153 symmetric_adaptor& operator /= (const AT &at) { 1154 matrix_assign_scalar<scalar_divides_assign> (*this, at); 1155 return *this; 1156 } 1157 1158 // Closure comparison 1159 BOOST_UBLAS_INLINE same_closure(const symmetric_adaptor & sa) const1160 bool same_closure (const symmetric_adaptor &sa) const { 1161 return (*this).data ().same_closure (sa.data ()); 1162 } 1163 1164 // Swapping 1165 BOOST_UBLAS_INLINE swap(symmetric_adaptor & m)1166 void swap (symmetric_adaptor &m) { 1167 if (this != &m) 1168 matrix_swap<scalar_swap, triangular_type> (*this, m); 1169 } 1170 BOOST_UBLAS_INLINE swap(symmetric_adaptor & m1,symmetric_adaptor & m2)1171 friend void swap (symmetric_adaptor &m1, symmetric_adaptor &m2) { 1172 m1.swap (m2); 1173 } 1174 1175 // Iterator types 1176 private: 1177 // Use matrix iterator 1178 typedef typename M::const_iterator1 const_subiterator1_type; 1179 typedef typename boost::mpl::if_<boost::is_const<M>, 1180 typename M::const_iterator1, 1181 typename M::iterator1>::type subiterator1_type; 1182 typedef typename M::const_iterator2 const_subiterator2_type; 1183 typedef typename boost::mpl::if_<boost::is_const<M>, 1184 typename M::const_iterator2, 1185 typename M::iterator2>::type subiterator2_type; 1186 1187 public: 1188 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 1189 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1; 1190 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2; 1191 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1; 1192 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2; 1193 #else 1194 class const_iterator1; 1195 class iterator1; 1196 class const_iterator2; 1197 class iterator2; 1198 #endif 1199 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 1200 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 1201 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 1202 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 1203 1204 // Element lookup 1205 BOOST_UBLAS_INLINE find1(int rank,size_type i,size_type j) const1206 const_iterator1 find1 (int rank, size_type i, size_type j) const { 1207 if (triangular_type::other (i, j)) { 1208 if (triangular_type::other (size1 (), j)) { 1209 return const_iterator1 (*this, 0, 0, 1210 data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j), 1211 data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ())); 1212 } else { 1213 return const_iterator1 (*this, 0, 1, 1214 data ().find1 (rank, i, j), data ().find1 (rank, j, j), 1215 data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ())); 1216 } 1217 } else { 1218 if (triangular_type::other (size1 (), j)) { 1219 return const_iterator1 (*this, 1, 0, 1220 data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j), 1221 data ().find2 (rank, j, i), data ().find2 (rank, j, j)); 1222 } else { 1223 return const_iterator1 (*this, 1, 1, 1224 data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()), 1225 data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ())); 1226 } 1227 } 1228 } 1229 BOOST_UBLAS_INLINE find1(int rank,size_type i,size_type j)1230 iterator1 find1 (int rank, size_type i, size_type j) { 1231 if (rank == 1) 1232 i = triangular_type::mutable_restrict1 (i, j, size1(), size2()); 1233 return iterator1 (*this, data ().find1 (rank, i, j)); 1234 } 1235 BOOST_UBLAS_INLINE find2(int rank,size_type i,size_type j) const1236 const_iterator2 find2 (int rank, size_type i, size_type j) const { 1237 if (triangular_type::other (i, j)) { 1238 if (triangular_type::other (i, size2 ())) { 1239 return const_iterator2 (*this, 1, 1, 1240 data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()), 1241 data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ())); 1242 } else { 1243 return const_iterator2 (*this, 1, 0, 1244 data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i), 1245 data ().find2 (rank, i, j), data ().find2 (rank, i, i)); 1246 } 1247 } else { 1248 if (triangular_type::other (i, size2 ())) { 1249 return const_iterator2 (*this, 0, 1, 1250 data ().find1 (rank, j, i), data ().find1 (rank, i, i), 1251 data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ())); 1252 } else { 1253 return const_iterator2 (*this, 0, 0, 1254 data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i), 1255 data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ())); 1256 } 1257 } 1258 } 1259 BOOST_UBLAS_INLINE find2(int rank,size_type i,size_type j)1260 iterator2 find2 (int rank, size_type i, size_type j) { 1261 if (rank == 1) 1262 j = triangular_type::mutable_restrict2 (i, j, size1(), size2()); 1263 return iterator2 (*this, data ().find2 (rank, i, j)); 1264 } 1265 1266 // Iterators simply are indices. 1267 1268 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 1269 class const_iterator1: 1270 public container_const_reference<symmetric_adaptor>, 1271 public random_access_iterator_base<typename iterator_restrict_traits< 1272 typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category, 1273 const_iterator1, value_type> { 1274 public: 1275 typedef typename const_subiterator1_type::value_type value_type; 1276 typedef typename const_subiterator1_type::difference_type difference_type; 1277 typedef typename const_subiterator1_type::reference reference; 1278 typedef typename const_subiterator1_type::pointer pointer; 1279 1280 typedef const_iterator2 dual_iterator_type; 1281 typedef const_reverse_iterator2 dual_reverse_iterator_type; 1282 1283 // Construction and destruction 1284 BOOST_UBLAS_INLINE const_iterator1()1285 const_iterator1 (): 1286 container_const_reference<self_type> (), 1287 begin_ (-1), end_ (-1), current_ (-1), 1288 it1_begin_ (), it1_end_ (), it1_ (), 1289 it2_begin_ (), it2_end_ (), it2_ () {} 1290 BOOST_UBLAS_INLINE const_iterator1(const self_type & m,int begin,int end,const const_subiterator1_type & it1_begin,const const_subiterator1_type & it1_end,const const_subiterator2_type & it2_begin,const const_subiterator2_type & it2_end)1291 const_iterator1 (const self_type &m, int begin, int end, 1292 const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end, 1293 const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end): 1294 container_const_reference<self_type> (m), 1295 begin_ (begin), end_ (end), current_ (begin), 1296 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_), 1297 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) { 1298 if (current_ == 0 && it1_ == it1_end_) 1299 current_ = 1; 1300 if (current_ == 1 && it2_ == it2_end_) 1301 current_ = 0; 1302 if ((current_ == 0 && it1_ == it1_end_) || 1303 (current_ == 1 && it2_ == it2_end_)) 1304 current_ = end_; 1305 BOOST_UBLAS_CHECK (current_ == end_ || 1306 (current_ == 0 && it1_ != it1_end_) || 1307 (current_ == 1 && it2_ != it2_end_), internal_logic ()); 1308 } 1309 // FIXME cannot compile 1310 // iterator1 does not have these members! 1311 BOOST_UBLAS_INLINE const_iterator1(const iterator1 & it)1312 const_iterator1 (const iterator1 &it): 1313 container_const_reference<self_type> (it ()), 1314 begin_ (it.begin_), end_ (it.end_), current_ (it.current_), 1315 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_), 1316 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) { 1317 BOOST_UBLAS_CHECK (current_ == end_ || 1318 (current_ == 0 && it1_ != it1_end_) || 1319 (current_ == 1 && it2_ != it2_end_), internal_logic ()); 1320 } 1321 1322 // Arithmetic 1323 BOOST_UBLAS_INLINE operator ++()1324 const_iterator1 &operator ++ () { 1325 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1326 if (current_ == 0) { 1327 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 1328 ++ it1_; 1329 if (it1_ == it1_end_ && end_ == 1) { 1330 it2_ = it2_begin_; 1331 current_ = 1; 1332 } 1333 } else /* if (current_ == 1) */ { 1334 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 1335 ++ it2_; 1336 if (it2_ == it2_end_ && end_ == 0) { 1337 it1_ = it1_begin_; 1338 current_ = 0; 1339 } 1340 } 1341 return *this; 1342 } 1343 BOOST_UBLAS_INLINE operator --()1344 const_iterator1 &operator -- () { 1345 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1346 if (current_ == 0) { 1347 if (it1_ == it1_begin_ && begin_ == 1) { 1348 it2_ = it2_end_; 1349 BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ()); 1350 -- it2_; 1351 current_ = 1; 1352 } else { 1353 -- it1_; 1354 } 1355 } else /* if (current_ == 1) */ { 1356 if (it2_ == it2_begin_ && begin_ == 0) { 1357 it1_ = it1_end_; 1358 BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ()); 1359 -- it1_; 1360 current_ = 0; 1361 } else { 1362 -- it2_; 1363 } 1364 } 1365 return *this; 1366 } 1367 BOOST_UBLAS_INLINE operator +=(difference_type n)1368 const_iterator1 &operator += (difference_type n) { 1369 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1370 if (current_ == 0) { 1371 size_type d = (std::min) (n, it1_end_ - it1_); 1372 it1_ += d; 1373 n -= d; 1374 if (n > 0 || (end_ == 1 && it1_ == it1_end_)) { 1375 BOOST_UBLAS_CHECK (end_ == 1, external_logic ()); 1376 d = (std::min) (n, it2_end_ - it2_begin_); 1377 it2_ = it2_begin_ + d; 1378 n -= d; 1379 current_ = 1; 1380 } 1381 } else /* if (current_ == 1) */ { 1382 size_type d = (std::min) (n, it2_end_ - it2_); 1383 it2_ += d; 1384 n -= d; 1385 if (n > 0 || (end_ == 0 && it2_ == it2_end_)) { 1386 BOOST_UBLAS_CHECK (end_ == 0, external_logic ()); 1387 d = (std::min) (n, it1_end_ - it1_begin_); 1388 it1_ = it1_begin_ + d; 1389 n -= d; 1390 current_ = 0; 1391 } 1392 } 1393 BOOST_UBLAS_CHECK (n == 0, external_logic ()); 1394 return *this; 1395 } 1396 BOOST_UBLAS_INLINE operator -=(difference_type n)1397 const_iterator1 &operator -= (difference_type n) { 1398 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1399 if (current_ == 0) { 1400 size_type d = (std::min) (n, it1_ - it1_begin_); 1401 it1_ -= d; 1402 n -= d; 1403 if (n > 0) { 1404 BOOST_UBLAS_CHECK (end_ == 1, external_logic ()); 1405 d = (std::min) (n, it2_end_ - it2_begin_); 1406 it2_ = it2_end_ - d; 1407 n -= d; 1408 current_ = 1; 1409 } 1410 } else /* if (current_ == 1) */ { 1411 size_type d = (std::min) (n, it2_ - it2_begin_); 1412 it2_ -= d; 1413 n -= d; 1414 if (n > 0) { 1415 BOOST_UBLAS_CHECK (end_ == 0, external_logic ()); 1416 d = (std::min) (n, it1_end_ - it1_begin_); 1417 it1_ = it1_end_ - d; 1418 n -= d; 1419 current_ = 0; 1420 } 1421 } 1422 BOOST_UBLAS_CHECK (n == 0, external_logic ()); 1423 return *this; 1424 } 1425 BOOST_UBLAS_INLINE operator -(const const_iterator1 & it) const1426 difference_type operator - (const const_iterator1 &it) const { 1427 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1428 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1429 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ()); 1430 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ()); 1431 if (current_ == 0 && it.current_ == 0) { 1432 return it1_ - it.it1_; 1433 } else if (current_ == 0 && it.current_ == 1) { 1434 if (end_ == 1 && it.end_ == 1) { 1435 return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_); 1436 } else /* if (end_ == 0 && it.end_ == 0) */ { 1437 return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_); 1438 } 1439 1440 } else if (current_ == 1 && it.current_ == 0) { 1441 if (end_ == 1 && it.end_ == 1) { 1442 return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_); 1443 } else /* if (end_ == 0 && it.end_ == 0) */ { 1444 return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_); 1445 } 1446 } 1447 /* current_ == 1 && it.current_ == 1 */ { 1448 return it2_ - it.it2_; 1449 } 1450 } 1451 1452 // Dereference 1453 BOOST_UBLAS_INLINE operator *() const1454 const_reference operator * () const { 1455 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1456 if (current_ == 0) { 1457 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 1458 return *it1_; 1459 } else /* if (current_ == 1) */ { 1460 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 1461 return *it2_; 1462 } 1463 } 1464 BOOST_UBLAS_INLINE operator [](difference_type n) const1465 const_reference operator [] (difference_type n) const { 1466 return *(*this + n); 1467 } 1468 1469 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 1470 BOOST_UBLAS_INLINE 1471 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1472 typename self_type:: 1473 #endif begin() const1474 const_iterator2 begin () const { 1475 return (*this) ().find2 (1, index1 (), 0); 1476 } 1477 BOOST_UBLAS_INLINE 1478 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1479 typename self_type:: 1480 #endif cbegin() const1481 const_iterator2 cbegin () const { 1482 return begin (); 1483 } 1484 BOOST_UBLAS_INLINE 1485 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1486 typename self_type:: 1487 #endif end() const1488 const_iterator2 end () const { 1489 return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); 1490 } 1491 BOOST_UBLAS_INLINE 1492 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1493 typename self_type:: 1494 #endif cend() const1495 const_iterator2 cend () const { 1496 return end (); 1497 } 1498 BOOST_UBLAS_INLINE 1499 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1500 typename self_type:: 1501 #endif rbegin() const1502 const_reverse_iterator2 rbegin () const { 1503 return const_reverse_iterator2 (end ()); 1504 } 1505 BOOST_UBLAS_INLINE 1506 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1507 typename self_type:: 1508 #endif crbegin() const1509 const_reverse_iterator2 crbegin () const { 1510 return rbegin (); 1511 } 1512 BOOST_UBLAS_INLINE 1513 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1514 typename self_type:: 1515 #endif rend() const1516 const_reverse_iterator2 rend () const { 1517 return const_reverse_iterator2 (begin ()); 1518 } 1519 BOOST_UBLAS_INLINE 1520 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1521 typename self_type:: 1522 #endif crend() const1523 const_reverse_iterator2 crend () const { 1524 return rend (); 1525 } 1526 #endif 1527 1528 // Indices 1529 BOOST_UBLAS_INLINE index1() const1530 size_type index1 () const { 1531 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1532 if (current_ == 0) { 1533 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 1534 return it1_.index1 (); 1535 } else /* if (current_ == 1) */ { 1536 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 1537 return it2_.index2 (); 1538 } 1539 } 1540 BOOST_UBLAS_INLINE index2() const1541 size_type index2 () const { 1542 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1543 if (current_ == 0) { 1544 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 1545 return it1_.index2 (); 1546 } else /* if (current_ == 1) */ { 1547 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 1548 return it2_.index1 (); 1549 } 1550 } 1551 1552 // Assignment 1553 BOOST_UBLAS_INLINE operator =(const const_iterator1 & it)1554 const_iterator1 &operator = (const const_iterator1 &it) { 1555 container_const_reference<self_type>::assign (&it ()); 1556 begin_ = it.begin_; 1557 end_ = it.end_; 1558 current_ = it.current_; 1559 it1_begin_ = it.it1_begin_; 1560 it1_end_ = it.it1_end_; 1561 it1_ = it.it1_; 1562 it2_begin_ = it.it2_begin_; 1563 it2_end_ = it.it2_end_; 1564 it2_ = it.it2_; 1565 return *this; 1566 } 1567 1568 // Comparison 1569 BOOST_UBLAS_INLINE operator ==(const const_iterator1 & it) const1570 bool operator == (const const_iterator1 &it) const { 1571 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1572 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1573 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ()); 1574 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ()); 1575 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) || 1576 (current_ == 1 && it.current_ == 1 && it2_ == it.it2_); 1577 } 1578 BOOST_UBLAS_INLINE operator <(const const_iterator1 & it) const1579 bool operator < (const const_iterator1 &it) const { 1580 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1581 return it - *this > 0; 1582 } 1583 1584 private: 1585 int begin_; 1586 int end_; 1587 int current_; 1588 const_subiterator1_type it1_begin_; 1589 const_subiterator1_type it1_end_; 1590 const_subiterator1_type it1_; 1591 const_subiterator2_type it2_begin_; 1592 const_subiterator2_type it2_end_; 1593 const_subiterator2_type it2_; 1594 }; 1595 #endif 1596 1597 BOOST_UBLAS_INLINE begin1() const1598 const_iterator1 begin1 () const { 1599 return find1 (0, 0, 0); 1600 } 1601 BOOST_UBLAS_INLINE cbegin1() const1602 const_iterator1 cbegin1 () const { 1603 return begin1 (); 1604 } 1605 BOOST_UBLAS_INLINE end1() const1606 const_iterator1 end1 () const { 1607 return find1 (0, size1 (), 0); 1608 } 1609 BOOST_UBLAS_INLINE cend1() const1610 const_iterator1 cend1 () const { 1611 return end1 (); 1612 } 1613 1614 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 1615 class iterator1: 1616 public container_reference<symmetric_adaptor>, 1617 public random_access_iterator_base<typename iterator_restrict_traits< 1618 typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category, 1619 iterator1, value_type> { 1620 public: 1621 typedef typename subiterator1_type::value_type value_type; 1622 typedef typename subiterator1_type::difference_type difference_type; 1623 typedef typename subiterator1_type::reference reference; 1624 typedef typename subiterator1_type::pointer pointer; 1625 1626 typedef iterator2 dual_iterator_type; 1627 typedef reverse_iterator2 dual_reverse_iterator_type; 1628 1629 // Construction and destruction 1630 BOOST_UBLAS_INLINE iterator1()1631 iterator1 (): 1632 container_reference<self_type> (), it1_ () {} 1633 BOOST_UBLAS_INLINE iterator1(self_type & m,const subiterator1_type & it1)1634 iterator1 (self_type &m, const subiterator1_type &it1): 1635 container_reference<self_type> (m), it1_ (it1) {} 1636 1637 // Arithmetic 1638 BOOST_UBLAS_INLINE operator ++()1639 iterator1 &operator ++ () { 1640 ++ it1_; 1641 return *this; 1642 } 1643 BOOST_UBLAS_INLINE operator --()1644 iterator1 &operator -- () { 1645 -- it1_; 1646 return *this; 1647 } 1648 BOOST_UBLAS_INLINE operator +=(difference_type n)1649 iterator1 &operator += (difference_type n) { 1650 it1_ += n; 1651 return *this; 1652 } 1653 BOOST_UBLAS_INLINE operator -=(difference_type n)1654 iterator1 &operator -= (difference_type n) { 1655 it1_ -= n; 1656 return *this; 1657 } 1658 BOOST_UBLAS_INLINE operator -(const iterator1 & it) const1659 difference_type operator - (const iterator1 &it) const { 1660 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1661 return it1_ - it.it1_; 1662 } 1663 1664 // Dereference 1665 BOOST_UBLAS_INLINE operator *() const1666 reference operator * () const { 1667 return *it1_; 1668 } 1669 BOOST_UBLAS_INLINE operator [](difference_type n) const1670 reference operator [] (difference_type n) const { 1671 return *(*this + n); 1672 } 1673 1674 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 1675 BOOST_UBLAS_INLINE 1676 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1677 typename self_type:: 1678 #endif begin() const1679 iterator2 begin () const { 1680 return (*this) ().find2 (1, index1 (), 0); 1681 } 1682 BOOST_UBLAS_INLINE 1683 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1684 typename self_type:: 1685 #endif end() const1686 iterator2 end () const { 1687 return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); 1688 } 1689 BOOST_UBLAS_INLINE 1690 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1691 typename self_type:: 1692 #endif rbegin() const1693 reverse_iterator2 rbegin () const { 1694 return reverse_iterator2 (end ()); 1695 } 1696 BOOST_UBLAS_INLINE 1697 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1698 typename self_type:: 1699 #endif rend() const1700 reverse_iterator2 rend () const { 1701 return reverse_iterator2 (begin ()); 1702 } 1703 #endif 1704 1705 // Indices 1706 BOOST_UBLAS_INLINE index1() const1707 size_type index1 () const { 1708 return it1_.index1 (); 1709 } 1710 BOOST_UBLAS_INLINE index2() const1711 size_type index2 () const { 1712 return it1_.index2 (); 1713 } 1714 1715 // Assignment 1716 BOOST_UBLAS_INLINE operator =(const iterator1 & it)1717 iterator1 &operator = (const iterator1 &it) { 1718 container_reference<self_type>::assign (&it ()); 1719 it1_ = it.it1_; 1720 return *this; 1721 } 1722 1723 // Comparison 1724 BOOST_UBLAS_INLINE operator ==(const iterator1 & it) const1725 bool operator == (const iterator1 &it) const { 1726 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1727 return it1_ == it.it1_; 1728 } 1729 BOOST_UBLAS_INLINE operator <(const iterator1 & it) const1730 bool operator < (const iterator1 &it) const { 1731 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1732 return it1_ < it.it1_; 1733 } 1734 1735 private: 1736 subiterator1_type it1_; 1737 1738 friend class const_iterator1; 1739 }; 1740 #endif 1741 1742 BOOST_UBLAS_INLINE begin1()1743 iterator1 begin1 () { 1744 return find1 (0, 0, 0); 1745 } 1746 BOOST_UBLAS_INLINE end1()1747 iterator1 end1 () { 1748 return find1 (0, size1 (), 0); 1749 } 1750 1751 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 1752 class const_iterator2: 1753 public container_const_reference<symmetric_adaptor>, 1754 public random_access_iterator_base<typename iterator_restrict_traits< 1755 typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category, 1756 const_iterator2, value_type> { 1757 public: 1758 typedef typename const_subiterator2_type::value_type value_type; 1759 typedef typename const_subiterator2_type::difference_type difference_type; 1760 typedef typename const_subiterator2_type::reference reference; 1761 typedef typename const_subiterator2_type::pointer pointer; 1762 1763 typedef const_iterator1 dual_iterator_type; 1764 typedef const_reverse_iterator1 dual_reverse_iterator_type; 1765 1766 // Construction and destruction 1767 BOOST_UBLAS_INLINE const_iterator2()1768 const_iterator2 (): 1769 container_const_reference<self_type> (), 1770 begin_ (-1), end_ (-1), current_ (-1), 1771 it1_begin_ (), it1_end_ (), it1_ (), 1772 it2_begin_ (), it2_end_ (), it2_ () {} 1773 BOOST_UBLAS_INLINE const_iterator2(const self_type & m,int begin,int end,const const_subiterator1_type & it1_begin,const const_subiterator1_type & it1_end,const const_subiterator2_type & it2_begin,const const_subiterator2_type & it2_end)1774 const_iterator2 (const self_type &m, int begin, int end, 1775 const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end, 1776 const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end): 1777 container_const_reference<self_type> (m), 1778 begin_ (begin), end_ (end), current_ (begin), 1779 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_), 1780 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) { 1781 if (current_ == 0 && it1_ == it1_end_) 1782 current_ = 1; 1783 if (current_ == 1 && it2_ == it2_end_) 1784 current_ = 0; 1785 if ((current_ == 0 && it1_ == it1_end_) || 1786 (current_ == 1 && it2_ == it2_end_)) 1787 current_ = end_; 1788 BOOST_UBLAS_CHECK (current_ == end_ || 1789 (current_ == 0 && it1_ != it1_end_) || 1790 (current_ == 1 && it2_ != it2_end_), internal_logic ()); 1791 } 1792 // FIXME cannot compiler 1793 // iterator2 does not have these members! 1794 BOOST_UBLAS_INLINE const_iterator2(const iterator2 & it)1795 const_iterator2 (const iterator2 &it): 1796 container_const_reference<self_type> (it ()), 1797 begin_ (it.begin_), end_ (it.end_), current_ (it.current_), 1798 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_), 1799 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) { 1800 BOOST_UBLAS_CHECK (current_ == end_ || 1801 (current_ == 0 && it1_ != it1_end_) || 1802 (current_ == 1 && it2_ != it2_end_), internal_logic ()); 1803 } 1804 1805 // Arithmetic 1806 BOOST_UBLAS_INLINE operator ++()1807 const_iterator2 &operator ++ () { 1808 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1809 if (current_ == 0) { 1810 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 1811 ++ it1_; 1812 if (it1_ == it1_end_ && end_ == 1) { 1813 it2_ = it2_begin_; 1814 current_ = 1; 1815 } 1816 } else /* if (current_ == 1) */ { 1817 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 1818 ++ it2_; 1819 if (it2_ == it2_end_ && end_ == 0) { 1820 it1_ = it1_begin_; 1821 current_ = 0; 1822 } 1823 } 1824 return *this; 1825 } 1826 BOOST_UBLAS_INLINE operator --()1827 const_iterator2 &operator -- () { 1828 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1829 if (current_ == 0) { 1830 if (it1_ == it1_begin_ && begin_ == 1) { 1831 it2_ = it2_end_; 1832 BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ()); 1833 -- it2_; 1834 current_ = 1; 1835 } else { 1836 -- it1_; 1837 } 1838 } else /* if (current_ == 1) */ { 1839 if (it2_ == it2_begin_ && begin_ == 0) { 1840 it1_ = it1_end_; 1841 BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ()); 1842 -- it1_; 1843 current_ = 0; 1844 } else { 1845 -- it2_; 1846 } 1847 } 1848 return *this; 1849 } 1850 BOOST_UBLAS_INLINE operator +=(difference_type n)1851 const_iterator2 &operator += (difference_type n) { 1852 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1853 if (current_ == 0) { 1854 size_type d = (std::min) (n, it1_end_ - it1_); 1855 it1_ += d; 1856 n -= d; 1857 if (n > 0 || (end_ == 1 && it1_ == it1_end_)) { 1858 BOOST_UBLAS_CHECK (end_ == 1, external_logic ()); 1859 d = (std::min) (n, it2_end_ - it2_begin_); 1860 it2_ = it2_begin_ + d; 1861 n -= d; 1862 current_ = 1; 1863 } 1864 } else /* if (current_ == 1) */ { 1865 size_type d = (std::min) (n, it2_end_ - it2_); 1866 it2_ += d; 1867 n -= d; 1868 if (n > 0 || (end_ == 0 && it2_ == it2_end_)) { 1869 BOOST_UBLAS_CHECK (end_ == 0, external_logic ()); 1870 d = (std::min) (n, it1_end_ - it1_begin_); 1871 it1_ = it1_begin_ + d; 1872 n -= d; 1873 current_ = 0; 1874 } 1875 } 1876 BOOST_UBLAS_CHECK (n == 0, external_logic ()); 1877 return *this; 1878 } 1879 BOOST_UBLAS_INLINE operator -=(difference_type n)1880 const_iterator2 &operator -= (difference_type n) { 1881 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1882 if (current_ == 0) { 1883 size_type d = (std::min) (n, it1_ - it1_begin_); 1884 it1_ -= d; 1885 n -= d; 1886 if (n > 0) { 1887 BOOST_UBLAS_CHECK (end_ == 1, external_logic ()); 1888 d = (std::min) (n, it2_end_ - it2_begin_); 1889 it2_ = it2_end_ - d; 1890 n -= d; 1891 current_ = 1; 1892 } 1893 } else /* if (current_ == 1) */ { 1894 size_type d = (std::min) (n, it2_ - it2_begin_); 1895 it2_ -= d; 1896 n -= d; 1897 if (n > 0) { 1898 BOOST_UBLAS_CHECK (end_ == 0, external_logic ()); 1899 d = (std::min) (n, it1_end_ - it1_begin_); 1900 it1_ = it1_end_ - d; 1901 n -= d; 1902 current_ = 0; 1903 } 1904 } 1905 BOOST_UBLAS_CHECK (n == 0, external_logic ()); 1906 return *this; 1907 } 1908 BOOST_UBLAS_INLINE operator -(const const_iterator2 & it) const1909 difference_type operator - (const const_iterator2 &it) const { 1910 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 1911 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1912 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ()); 1913 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ()); 1914 if (current_ == 0 && it.current_ == 0) { 1915 return it1_ - it.it1_; 1916 } else if (current_ == 0 && it.current_ == 1) { 1917 if (end_ == 1 && it.end_ == 1) { 1918 return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_); 1919 } else /* if (end_ == 0 && it.end_ == 0) */ { 1920 return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_); 1921 } 1922 1923 } else if (current_ == 1 && it.current_ == 0) { 1924 if (end_ == 1 && it.end_ == 1) { 1925 return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_); 1926 } else /* if (end_ == 0 && it.end_ == 0) */ { 1927 return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_); 1928 } 1929 } 1930 /* current_ == 1 && it.current_ == 1 */ { 1931 return it2_ - it.it2_; 1932 } 1933 } 1934 1935 // Dereference 1936 BOOST_UBLAS_INLINE operator *() const1937 const_reference operator * () const { 1938 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 1939 if (current_ == 0) { 1940 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 1941 return *it1_; 1942 } else /* if (current_ == 1) */ { 1943 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 1944 return *it2_; 1945 } 1946 } 1947 BOOST_UBLAS_INLINE operator [](difference_type n) const1948 const_reference operator [] (difference_type n) const { 1949 return *(*this + n); 1950 } 1951 1952 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 1953 BOOST_UBLAS_INLINE 1954 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1955 typename self_type:: 1956 #endif begin() const1957 const_iterator1 begin () const { 1958 return (*this) ().find1 (1, 0, index2 ()); 1959 } 1960 BOOST_UBLAS_INLINE 1961 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1962 typename self_type:: 1963 #endif cbegin() const1964 const_iterator1 cbegin () const { 1965 return begin (); 1966 } 1967 BOOST_UBLAS_INLINE 1968 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1969 typename self_type:: 1970 #endif end() const1971 const_iterator1 end () const { 1972 return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); 1973 } 1974 BOOST_UBLAS_INLINE 1975 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1976 typename self_type:: 1977 #endif cend() const1978 const_iterator1 cend () const { 1979 return end (); 1980 } 1981 BOOST_UBLAS_INLINE 1982 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1983 typename self_type:: 1984 #endif rbegin() const1985 const_reverse_iterator1 rbegin () const { 1986 return const_reverse_iterator1 (end ()); 1987 } 1988 BOOST_UBLAS_INLINE 1989 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1990 typename self_type:: 1991 #endif crbegin() const1992 const_reverse_iterator1 crbegin () const { 1993 return rbegin (); 1994 } 1995 BOOST_UBLAS_INLINE 1996 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 1997 typename self_type:: 1998 #endif rend() const1999 const_reverse_iterator1 rend () const { 2000 return const_reverse_iterator1 (begin ()); 2001 } 2002 BOOST_UBLAS_INLINE 2003 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2004 typename self_type:: 2005 #endif crend() const2006 const_reverse_iterator1 crend () const { 2007 return rend (); 2008 } 2009 #endif 2010 2011 // Indices 2012 BOOST_UBLAS_INLINE index1() const2013 size_type index1 () const { 2014 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 2015 if (current_ == 0) { 2016 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 2017 return it1_.index2 (); 2018 } else /* if (current_ == 1) */ { 2019 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 2020 return it2_.index1 (); 2021 } 2022 } 2023 BOOST_UBLAS_INLINE index2() const2024 size_type index2 () const { 2025 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 2026 if (current_ == 0) { 2027 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 2028 return it1_.index1 (); 2029 } else /* if (current_ == 1) */ { 2030 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 2031 return it2_.index2 (); 2032 } 2033 } 2034 2035 // Assignment 2036 BOOST_UBLAS_INLINE operator =(const const_iterator2 & it)2037 const_iterator2 &operator = (const const_iterator2 &it) { 2038 container_const_reference<self_type>::assign (&it ()); 2039 begin_ = it.begin_; 2040 end_ = it.end_; 2041 current_ = it.current_; 2042 it1_begin_ = it.it1_begin_; 2043 it1_end_ = it.it1_end_; 2044 it1_ = it.it1_; 2045 it2_begin_ = it.it2_begin_; 2046 it2_end_ = it.it2_end_; 2047 it2_ = it.it2_; 2048 return *this; 2049 } 2050 2051 // Comparison 2052 BOOST_UBLAS_INLINE operator ==(const const_iterator2 & it) const2053 bool operator == (const const_iterator2 &it) const { 2054 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2055 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 2056 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ()); 2057 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ()); 2058 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) || 2059 (current_ == 1 && it.current_ == 1 && it2_ == it.it2_); 2060 } 2061 BOOST_UBLAS_INLINE operator <(const const_iterator2 & it) const2062 bool operator < (const const_iterator2 &it) const { 2063 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2064 return it - *this > 0; 2065 } 2066 2067 private: 2068 int begin_; 2069 int end_; 2070 int current_; 2071 const_subiterator1_type it1_begin_; 2072 const_subiterator1_type it1_end_; 2073 const_subiterator1_type it1_; 2074 const_subiterator2_type it2_begin_; 2075 const_subiterator2_type it2_end_; 2076 const_subiterator2_type it2_; 2077 }; 2078 #endif 2079 2080 BOOST_UBLAS_INLINE begin2() const2081 const_iterator2 begin2 () const { 2082 return find2 (0, 0, 0); 2083 } 2084 BOOST_UBLAS_INLINE cbegin2() const2085 const_iterator2 cbegin2 () const { 2086 return begin2 (); 2087 } 2088 BOOST_UBLAS_INLINE end2() const2089 const_iterator2 end2 () const { 2090 return find2 (0, 0, size2 ()); 2091 } 2092 BOOST_UBLAS_INLINE cend2() const2093 const_iterator2 cend2 () const { 2094 return end2 (); 2095 } 2096 2097 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 2098 class iterator2: 2099 public container_reference<symmetric_adaptor>, 2100 public random_access_iterator_base<typename iterator_restrict_traits< 2101 typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category, 2102 iterator2, value_type> { 2103 public: 2104 typedef typename subiterator2_type::value_type value_type; 2105 typedef typename subiterator2_type::difference_type difference_type; 2106 typedef typename subiterator2_type::reference reference; 2107 typedef typename subiterator2_type::pointer pointer; 2108 2109 typedef iterator1 dual_iterator_type; 2110 typedef reverse_iterator1 dual_reverse_iterator_type; 2111 2112 // Construction and destruction 2113 BOOST_UBLAS_INLINE iterator2()2114 iterator2 (): 2115 container_reference<self_type> (), it2_ () {} 2116 BOOST_UBLAS_INLINE iterator2(self_type & m,const subiterator2_type & it2)2117 iterator2 (self_type &m, const subiterator2_type &it2): 2118 container_reference<self_type> (m), it2_ (it2) {} 2119 2120 // Arithmetic 2121 BOOST_UBLAS_INLINE operator ++()2122 iterator2 &operator ++ () { 2123 ++ it2_; 2124 return *this; 2125 } 2126 BOOST_UBLAS_INLINE operator --()2127 iterator2 &operator -- () { 2128 -- it2_; 2129 return *this; 2130 } 2131 BOOST_UBLAS_INLINE operator +=(difference_type n)2132 iterator2 &operator += (difference_type n) { 2133 it2_ += n; 2134 return *this; 2135 } 2136 BOOST_UBLAS_INLINE operator -=(difference_type n)2137 iterator2 &operator -= (difference_type n) { 2138 it2_ -= n; 2139 return *this; 2140 } 2141 BOOST_UBLAS_INLINE operator -(const iterator2 & it) const2142 difference_type operator - (const iterator2 &it) const { 2143 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2144 return it2_ - it.it2_; 2145 } 2146 2147 // Dereference 2148 BOOST_UBLAS_INLINE operator *() const2149 reference operator * () const { 2150 return *it2_; 2151 } 2152 BOOST_UBLAS_INLINE operator [](difference_type n) const2153 reference operator [] (difference_type n) const { 2154 return *(*this + n); 2155 } 2156 2157 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 2158 BOOST_UBLAS_INLINE 2159 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2160 typename self_type:: 2161 #endif begin() const2162 iterator1 begin () const { 2163 return (*this) ().find1 (1, 0, index2 ()); 2164 } 2165 BOOST_UBLAS_INLINE 2166 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2167 typename self_type:: 2168 #endif end() const2169 iterator1 end () const { 2170 return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); 2171 } 2172 BOOST_UBLAS_INLINE 2173 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2174 typename self_type:: 2175 #endif rbegin() const2176 reverse_iterator1 rbegin () const { 2177 return reverse_iterator1 (end ()); 2178 } 2179 BOOST_UBLAS_INLINE 2180 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 2181 typename self_type:: 2182 #endif rend() const2183 reverse_iterator1 rend () const { 2184 return reverse_iterator1 (begin ()); 2185 } 2186 #endif 2187 2188 // Indices 2189 BOOST_UBLAS_INLINE index1() const2190 size_type index1 () const { 2191 return it2_.index1 (); 2192 } 2193 BOOST_UBLAS_INLINE index2() const2194 size_type index2 () const { 2195 return it2_.index2 (); 2196 } 2197 2198 // Assignment 2199 BOOST_UBLAS_INLINE operator =(const iterator2 & it)2200 iterator2 &operator = (const iterator2 &it) { 2201 container_reference<self_type>::assign (&it ()); 2202 it2_ = it.it2_; 2203 return *this; 2204 } 2205 2206 // Comparison 2207 BOOST_UBLAS_INLINE operator ==(const iterator2 & it) const2208 bool operator == (const iterator2 &it) const { 2209 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2210 return it2_ == it.it2_; 2211 } 2212 BOOST_UBLAS_INLINE operator <(const iterator2 & it) const2213 bool operator < (const iterator2 &it) const { 2214 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 2215 return it2_ < it.it2_; 2216 } 2217 2218 private: 2219 subiterator2_type it2_; 2220 2221 friend class const_iterator2; 2222 }; 2223 #endif 2224 2225 BOOST_UBLAS_INLINE begin2()2226 iterator2 begin2 () { 2227 return find2 (0, 0, 0); 2228 } 2229 BOOST_UBLAS_INLINE end2()2230 iterator2 end2 () { 2231 return find2 (0, 0, size2 ()); 2232 } 2233 2234 // Reverse iterators 2235 2236 BOOST_UBLAS_INLINE rbegin1() const2237 const_reverse_iterator1 rbegin1 () const { 2238 return const_reverse_iterator1 (end1 ()); 2239 } 2240 BOOST_UBLAS_INLINE crbegin1() const2241 const_reverse_iterator1 crbegin1 () const { 2242 return rbegin1 (); 2243 } 2244 BOOST_UBLAS_INLINE rend1() const2245 const_reverse_iterator1 rend1 () const { 2246 return const_reverse_iterator1 (begin1 ()); 2247 } 2248 BOOST_UBLAS_INLINE crend1() const2249 const_reverse_iterator1 crend1 () const { 2250 return rend1 (); 2251 } 2252 2253 BOOST_UBLAS_INLINE rbegin1()2254 reverse_iterator1 rbegin1 () { 2255 return reverse_iterator1 (end1 ()); 2256 } 2257 BOOST_UBLAS_INLINE rend1()2258 reverse_iterator1 rend1 () { 2259 return reverse_iterator1 (begin1 ()); 2260 } 2261 2262 BOOST_UBLAS_INLINE rbegin2() const2263 const_reverse_iterator2 rbegin2 () const { 2264 return const_reverse_iterator2 (end2 ()); 2265 } 2266 BOOST_UBLAS_INLINE crbegin2() const2267 const_reverse_iterator2 crbegin2 () const { 2268 return rbegin2 (); 2269 } 2270 BOOST_UBLAS_INLINE rend2() const2271 const_reverse_iterator2 rend2 () const { 2272 return const_reverse_iterator2 (begin2 ()); 2273 } 2274 BOOST_UBLAS_INLINE crend2() const2275 const_reverse_iterator2 crend2 () const { 2276 return rend2 (); 2277 } 2278 2279 BOOST_UBLAS_INLINE rbegin2()2280 reverse_iterator2 rbegin2 () { 2281 return reverse_iterator2 (end2 ()); 2282 } 2283 BOOST_UBLAS_INLINE rend2()2284 reverse_iterator2 rend2 () { 2285 return reverse_iterator2 (begin2 ()); 2286 } 2287 2288 private: 2289 matrix_closure_type data_; 2290 }; 2291 2292 // Specialization for temporary_traits 2293 template <class M, class TRI> 2294 struct vector_temporary_traits< symmetric_adaptor<M, TRI> > 2295 : vector_temporary_traits< M > {} ; 2296 template <class M, class TRI> 2297 struct vector_temporary_traits< const symmetric_adaptor<M, TRI> > 2298 : vector_temporary_traits< M > {} ; 2299 2300 template <class M, class TRI> 2301 struct matrix_temporary_traits< symmetric_adaptor<M, TRI> > 2302 : matrix_temporary_traits< M > {} ; 2303 template <class M, class TRI> 2304 struct matrix_temporary_traits< const symmetric_adaptor<M, TRI> > 2305 : matrix_temporary_traits< M > {} ; 2306 2307 }}} 2308 2309 #endif 2310