...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
00001 // 00002 // Copyright (c) 2000-2002 00003 // Joerg Walter, Mathias Koch 00004 // 00005 // Distributed under the Boost Software License, Version 1.0. (See 00006 // accompanying file LICENSE_1_0.txt or copy at 00007 // http://www.boost.org/LICENSE_1_0.txt) 00008 // 00009 // The authors gratefully acknowledge the support of 00010 // GeNeSys mbH & Co. KG in producing this work. 00011 // 00012 00013 #ifndef _BOOST_UBLAS_SYMMETRIC_ 00014 #define _BOOST_UBLAS_SYMMETRIC_ 00015 00016 #include <boost/numeric/ublas/matrix.hpp> 00017 #include <boost/numeric/ublas/triangular.hpp> 00018 #include <boost/numeric/ublas/detail/temporary.hpp> 00019 00020 // Iterators based on ideas of Jeremy Siek 00021 // Symmetric matrices are square. Thanks to Peter Schmitteckert for spotting this. 00022 00023 namespace boost { namespace numeric { namespace ublas { 00024 00025 template<class M> 00026 bool is_symmetric (const M &m) { 00027 typedef typename M::size_type size_type; 00028 00029 if (m.size1 () != m.size2 ()) 00030 return false; 00031 size_type size = BOOST_UBLAS_SAME (m.size1 (), m.size2 ()); 00032 for (size_type i = 0; i < size; ++ i) { 00033 for (size_type j = i; j < size; ++ j) { 00034 if (m (i, j) != m (j, i)) 00035 return false; 00036 } 00037 } 00038 return true; 00039 } 00040 00041 // Array based symmetric matrix class 00042 template<class T, class TRI, class L, class A> 00043 class symmetric_matrix: 00044 public matrix_container<symmetric_matrix<T, TRI, L, A> > { 00045 00046 typedef T *pointer; 00047 typedef TRI triangular_type; 00048 typedef L layout_type; 00049 typedef symmetric_matrix<T, TRI, L, A> self_type; 00050 public: 00051 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 00052 using matrix_container<self_type>::operator (); 00053 #endif 00054 typedef typename A::size_type size_type; 00055 typedef typename A::difference_type difference_type; 00056 typedef T value_type; 00057 typedef const T &const_reference; 00058 typedef T &reference; 00059 typedef A array_type; 00060 00061 typedef const matrix_reference<const self_type> const_closure_type; 00062 typedef matrix_reference<self_type> closure_type; 00063 typedef vector<T, A> vector_temporary_type; 00064 typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix 00065 typedef packed_tag storage_category; 00066 typedef typename L::orientation_category orientation_category; 00067 00068 // Construction and destruction 00069 BOOST_UBLAS_INLINE 00070 symmetric_matrix (): 00071 matrix_container<self_type> (), 00072 size_ (0), data_ (0) {} 00073 BOOST_UBLAS_INLINE 00074 symmetric_matrix (size_type size): 00075 matrix_container<self_type> (), 00076 size_ (BOOST_UBLAS_SAME (size, size)), data_ (triangular_type::packed_size (layout_type (), size, size)) { 00077 } 00078 BOOST_UBLAS_INLINE 00079 symmetric_matrix (size_type size1, size_type size2): 00080 matrix_container<self_type> (), 00081 size_ (BOOST_UBLAS_SAME (size1, size2)), data_ (triangular_type::packed_size (layout_type (), size1, size2)) { 00082 } 00083 BOOST_UBLAS_INLINE 00084 symmetric_matrix (size_type size, const array_type &data): 00085 matrix_container<self_type> (), 00086 size_ (size), data_ (data) {} 00087 BOOST_UBLAS_INLINE 00088 symmetric_matrix (const symmetric_matrix &m): 00089 matrix_container<self_type> (), 00090 size_ (m.size_), data_ (m.data_) {} 00091 template<class AE> 00092 BOOST_UBLAS_INLINE 00093 symmetric_matrix (const matrix_expression<AE> &ae): 00094 matrix_container<self_type> (), 00095 size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())), 00096 data_ (triangular_type::packed_size (layout_type (), size_, size_)) { 00097 matrix_assign<scalar_assign> (*this, ae); 00098 } 00099 00100 // Accessors 00101 BOOST_UBLAS_INLINE 00102 size_type size1 () const { 00103 return size_; 00104 } 00105 BOOST_UBLAS_INLINE 00106 size_type size2 () const { 00107 return size_; 00108 } 00109 00110 // Storage accessors 00111 BOOST_UBLAS_INLINE 00112 const array_type &data () const { 00113 return data_; 00114 } 00115 BOOST_UBLAS_INLINE 00116 array_type &data () { 00117 return data_; 00118 } 00119 00120 // Resizing 00121 BOOST_UBLAS_INLINE 00122 void resize (size_type size, bool preserve = true) { 00123 if (preserve) { 00124 self_type temporary (size, size); 00125 detail::matrix_resize_preserve<layout_type, triangular_type> (*this, temporary); 00126 } 00127 else { 00128 data ().resize (triangular_type::packed_size (layout_type (), size, size)); 00129 size_ = size; 00130 } 00131 } 00132 BOOST_UBLAS_INLINE 00133 void resize (size_type size1, size_type size2, bool preserve = true) { 00134 resize (BOOST_UBLAS_SAME (size1, size2), preserve); 00135 } 00136 BOOST_UBLAS_INLINE 00137 void resize_packed_preserve (size_type size) { 00138 size_ = BOOST_UBLAS_SAME (size, size); 00139 data ().resize (triangular_type::packed_size (layout_type (), size_, size_), value_type ()); 00140 } 00141 00142 // Element access 00143 BOOST_UBLAS_INLINE 00144 const_reference operator () (size_type i, size_type j) const { 00145 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 00146 BOOST_UBLAS_CHECK (j < size_, bad_index ()); 00147 if (triangular_type::other (i, j)) 00148 return data () [triangular_type::element (layout_type (), i, size_, j, size_)]; 00149 else 00150 return data () [triangular_type::element (layout_type (), j, size_, i, size_)]; 00151 } 00152 BOOST_UBLAS_INLINE 00153 reference at_element (size_type i, size_type j) { 00154 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 00155 BOOST_UBLAS_CHECK (j < size_, bad_index ()); 00156 return data () [triangular_type::element (layout_type (), i, size_, j, size_)]; 00157 } 00158 BOOST_UBLAS_INLINE 00159 reference operator () (size_type i, size_type j) { 00160 BOOST_UBLAS_CHECK (i < size_, bad_index ()); 00161 BOOST_UBLAS_CHECK (j < size_, bad_index ()); 00162 if (triangular_type::other (i, j)) 00163 return data () [triangular_type::element (layout_type (), i, size_, j, size_)]; 00164 else 00165 return data () [triangular_type::element (layout_type (), j, size_, i, size_)]; 00166 } 00167 00168 // Element assignment 00169 BOOST_UBLAS_INLINE 00170 reference insert_element (size_type i, size_type j, const_reference t) { 00171 return (operator () (i, j) = t); 00172 } 00173 BOOST_UBLAS_INLINE 00174 void erase_element (size_type i, size_type j) { 00175 operator () (i, j) = value_type/*zero*/(); 00176 } 00177 00178 // Zeroing 00179 BOOST_UBLAS_INLINE 00180 void clear () { 00181 // data ().clear (); 00182 std::fill (data ().begin (), data ().end (), value_type/*zero*/()); 00183 } 00184 00185 // Assignment 00186 BOOST_UBLAS_INLINE 00187 symmetric_matrix &operator = (const symmetric_matrix &m) { 00188 size_ = m.size_; 00189 data () = m.data (); 00190 return *this; 00191 } 00192 BOOST_UBLAS_INLINE 00193 symmetric_matrix &assign_temporary (symmetric_matrix &m) { 00194 swap (m); 00195 return *this; 00196 } 00197 template<class AE> 00198 BOOST_UBLAS_INLINE 00199 symmetric_matrix &operator = (const matrix_expression<AE> &ae) { 00200 self_type temporary (ae); 00201 return assign_temporary (temporary); 00202 } 00203 template<class AE> 00204 BOOST_UBLAS_INLINE 00205 symmetric_matrix &assign (const matrix_expression<AE> &ae) { 00206 matrix_assign<scalar_assign> (*this, ae); 00207 return *this; 00208 } 00209 template<class AE> 00210 BOOST_UBLAS_INLINE 00211 symmetric_matrix& operator += (const matrix_expression<AE> &ae) { 00212 self_type temporary (*this + ae); 00213 return assign_temporary (temporary); 00214 } 00215 template<class AE> 00216 BOOST_UBLAS_INLINE 00217 symmetric_matrix &plus_assign (const matrix_expression<AE> &ae) { 00218 matrix_assign<scalar_plus_assign> (*this, ae); 00219 return *this; 00220 } 00221 template<class AE> 00222 BOOST_UBLAS_INLINE 00223 symmetric_matrix& operator -= (const matrix_expression<AE> &ae) { 00224 self_type temporary (*this - ae); 00225 return assign_temporary (temporary); 00226 } 00227 template<class AE> 00228 BOOST_UBLAS_INLINE 00229 symmetric_matrix &minus_assign (const matrix_expression<AE> &ae) { 00230 matrix_assign<scalar_minus_assign> (*this, ae); 00231 return *this; 00232 } 00233 template<class AT> 00234 BOOST_UBLAS_INLINE 00235 symmetric_matrix& operator *= (const AT &at) { 00236 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 00237 return *this; 00238 } 00239 template<class AT> 00240 BOOST_UBLAS_INLINE 00241 symmetric_matrix& operator /= (const AT &at) { 00242 matrix_assign_scalar<scalar_divides_assign> (*this, at); 00243 return *this; 00244 } 00245 00246 // Swapping 00247 BOOST_UBLAS_INLINE 00248 void swap (symmetric_matrix &m) { 00249 if (this != &m) { 00250 std::swap (size_, m.size_); 00251 data ().swap (m.data ()); 00252 } 00253 } 00254 BOOST_UBLAS_INLINE 00255 friend void swap (symmetric_matrix &m1, symmetric_matrix &m2) { 00256 m1.swap (m2); 00257 } 00258 00259 // Iterator types 00260 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 00261 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1; 00262 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2; 00263 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1; 00264 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2; 00265 #else 00266 class const_iterator1; 00267 class iterator1; 00268 class const_iterator2; 00269 class iterator2; 00270 #endif 00271 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 00272 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 00273 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 00274 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 00275 00276 // Element lookup 00277 BOOST_UBLAS_INLINE 00278 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const { 00279 return const_iterator1 (*this, i, j); 00280 } 00281 BOOST_UBLAS_INLINE 00282 iterator1 find1 (int rank, size_type i, size_type j) { 00283 if (rank == 1) 00284 i = triangular_type::mutable_restrict1 (i, j, size1(), size2()); 00285 if (rank == 0) 00286 i = triangular_type::global_mutable_restrict1 (i, size1(), j, size2()); 00287 return iterator1 (*this, i, j); 00288 } 00289 BOOST_UBLAS_INLINE 00290 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const { 00291 return const_iterator2 (*this, i, j); 00292 } 00293 BOOST_UBLAS_INLINE 00294 iterator2 find2 (int rank, size_type i, size_type j) { 00295 if (rank == 1) 00296 j = triangular_type::mutable_restrict2 (i, j, size1(), size2()); 00297 if (rank == 0) 00298 j = triangular_type::global_mutable_restrict2 (i, size1(), j, size2()); 00299 return iterator2 (*this, i, j); 00300 } 00301 00302 // Iterators simply are indices. 00303 00304 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 00305 class const_iterator1: 00306 public container_const_reference<symmetric_matrix>, 00307 public random_access_iterator_base<dense_random_access_iterator_tag, 00308 const_iterator1, value_type> { 00309 public: 00310 typedef typename symmetric_matrix::value_type value_type; 00311 typedef typename symmetric_matrix::difference_type difference_type; 00312 typedef typename symmetric_matrix::const_reference reference; 00313 typedef const typename symmetric_matrix::pointer pointer; 00314 00315 typedef const_iterator2 dual_iterator_type; 00316 typedef const_reverse_iterator2 dual_reverse_iterator_type; 00317 00318 // Construction and destruction 00319 BOOST_UBLAS_INLINE 00320 const_iterator1 (): 00321 container_const_reference<self_type> (), it1_ (), it2_ () {} 00322 BOOST_UBLAS_INLINE 00323 const_iterator1 (const self_type &m, size_type it1, size_type it2): 00324 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {} 00325 BOOST_UBLAS_INLINE 00326 const_iterator1 (const iterator1 &it): 00327 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {} 00328 00329 // Arithmetic 00330 BOOST_UBLAS_INLINE 00331 const_iterator1 &operator ++ () { 00332 ++ it1_; 00333 return *this; 00334 } 00335 BOOST_UBLAS_INLINE 00336 const_iterator1 &operator -- () { 00337 -- it1_; 00338 return *this; 00339 } 00340 BOOST_UBLAS_INLINE 00341 const_iterator1 &operator += (difference_type n) { 00342 it1_ += n; 00343 return *this; 00344 } 00345 BOOST_UBLAS_INLINE 00346 const_iterator1 &operator -= (difference_type n) { 00347 it1_ -= n; 00348 return *this; 00349 } 00350 BOOST_UBLAS_INLINE 00351 difference_type operator - (const const_iterator1 &it) const { 00352 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00353 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 00354 return it1_ - it.it1_; 00355 } 00356 00357 // Dereference 00358 BOOST_UBLAS_INLINE 00359 const_reference operator * () const { 00360 return (*this) () (it1_, it2_); 00361 } 00362 BOOST_UBLAS_INLINE 00363 const_reference operator [] (difference_type n) const { 00364 return *(*this + n); 00365 } 00366 00367 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 00368 BOOST_UBLAS_INLINE 00369 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00370 typename self_type:: 00371 #endif 00372 const_iterator2 begin () const { 00373 return (*this) ().find2 (1, it1_, 0); 00374 } 00375 BOOST_UBLAS_INLINE 00376 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00377 typename self_type:: 00378 #endif 00379 const_iterator2 end () const { 00380 return (*this) ().find2 (1, it1_, (*this) ().size2 ()); 00381 } 00382 BOOST_UBLAS_INLINE 00383 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00384 typename self_type:: 00385 #endif 00386 const_reverse_iterator2 rbegin () const { 00387 return const_reverse_iterator2 (end ()); 00388 } 00389 BOOST_UBLAS_INLINE 00390 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00391 typename self_type:: 00392 #endif 00393 const_reverse_iterator2 rend () const { 00394 return const_reverse_iterator2 (begin ()); 00395 } 00396 #endif 00397 00398 // Indices 00399 BOOST_UBLAS_INLINE 00400 size_type index1 () const { 00401 return it1_; 00402 } 00403 BOOST_UBLAS_INLINE 00404 size_type index2 () const { 00405 return it2_; 00406 } 00407 00408 // Assignment 00409 BOOST_UBLAS_INLINE 00410 const_iterator1 &operator = (const const_iterator1 &it) { 00411 container_const_reference<self_type>::assign (&it ()); 00412 it1_ = it.it1_; 00413 it2_ = it.it2_; 00414 return *this; 00415 } 00416 00417 // Comparison 00418 BOOST_UBLAS_INLINE 00419 bool operator == (const const_iterator1 &it) const { 00420 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00421 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 00422 return it1_ == it.it1_; 00423 } 00424 BOOST_UBLAS_INLINE 00425 bool operator < (const const_iterator1 &it) const { 00426 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00427 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 00428 return it1_ < it.it1_; 00429 } 00430 00431 private: 00432 size_type it1_; 00433 size_type it2_; 00434 }; 00435 #endif 00436 00437 BOOST_UBLAS_INLINE 00438 const_iterator1 begin1 () const { 00439 return find1 (0, 0, 0); 00440 } 00441 BOOST_UBLAS_INLINE 00442 const_iterator1 end1 () const { 00443 return find1 (0, size_, 0); 00444 } 00445 00446 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 00447 class iterator1: 00448 public container_reference<symmetric_matrix>, 00449 public random_access_iterator_base<packed_random_access_iterator_tag, 00450 iterator1, value_type> { 00451 public: 00452 typedef typename symmetric_matrix::value_type value_type; 00453 typedef typename symmetric_matrix::difference_type difference_type; 00454 typedef typename symmetric_matrix::reference reference; 00455 typedef typename symmetric_matrix::pointer pointer; 00456 typedef iterator2 dual_iterator_type; 00457 typedef reverse_iterator2 dual_reverse_iterator_type; 00458 00459 // Construction and destruction 00460 BOOST_UBLAS_INLINE 00461 iterator1 (): 00462 container_reference<self_type> (), it1_ (), it2_ () {} 00463 BOOST_UBLAS_INLINE 00464 iterator1 (self_type &m, size_type it1, size_type it2): 00465 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {} 00466 00467 // Arithmetic 00468 BOOST_UBLAS_INLINE 00469 iterator1 &operator ++ () { 00470 ++ it1_; 00471 return *this; 00472 } 00473 BOOST_UBLAS_INLINE 00474 iterator1 &operator -- () { 00475 -- it1_; 00476 return *this; 00477 } 00478 BOOST_UBLAS_INLINE 00479 iterator1 &operator += (difference_type n) { 00480 it1_ += n; 00481 return *this; 00482 } 00483 BOOST_UBLAS_INLINE 00484 iterator1 &operator -= (difference_type n) { 00485 it1_ -= n; 00486 return *this; 00487 } 00488 BOOST_UBLAS_INLINE 00489 difference_type operator - (const iterator1 &it) const { 00490 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00491 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 00492 return it1_ - it.it1_; 00493 } 00494 00495 // Dereference 00496 BOOST_UBLAS_INLINE 00497 reference operator * () const { 00498 return (*this) () (it1_, it2_); 00499 } 00500 BOOST_UBLAS_INLINE 00501 reference operator [] (difference_type n) const { 00502 return *(*this + n); 00503 } 00504 00505 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 00506 BOOST_UBLAS_INLINE 00507 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00508 typename self_type:: 00509 #endif 00510 iterator2 begin () const { 00511 return (*this) ().find2 (1, it1_, 0); 00512 } 00513 BOOST_UBLAS_INLINE 00514 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00515 typename self_type:: 00516 #endif 00517 iterator2 end () const { 00518 return (*this) ().find2 (1, it1_, (*this) ().size2 ()); 00519 } 00520 BOOST_UBLAS_INLINE 00521 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00522 typename self_type:: 00523 #endif 00524 reverse_iterator2 rbegin () const { 00525 return reverse_iterator2 (end ()); 00526 } 00527 BOOST_UBLAS_INLINE 00528 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00529 typename self_type:: 00530 #endif 00531 reverse_iterator2 rend () const { 00532 return reverse_iterator2 (begin ()); 00533 } 00534 #endif 00535 00536 // Indices 00537 BOOST_UBLAS_INLINE 00538 size_type index1 () const { 00539 return it1_; 00540 } 00541 BOOST_UBLAS_INLINE 00542 size_type index2 () const { 00543 return it2_; 00544 } 00545 00546 // Assignment 00547 BOOST_UBLAS_INLINE 00548 iterator1 &operator = (const iterator1 &it) { 00549 container_reference<self_type>::assign (&it ()); 00550 it1_ = it.it1_; 00551 it2_ = it.it2_; 00552 return *this; 00553 } 00554 00555 // Comparison 00556 BOOST_UBLAS_INLINE 00557 bool operator == (const iterator1 &it) const { 00558 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00559 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 00560 return it1_ == it.it1_; 00561 } 00562 BOOST_UBLAS_INLINE 00563 bool operator < (const iterator1 &it) const { 00564 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00565 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ()); 00566 return it1_ < it.it1_; 00567 } 00568 00569 private: 00570 size_type it1_; 00571 size_type it2_; 00572 00573 friend class const_iterator1; 00574 }; 00575 #endif 00576 00577 BOOST_UBLAS_INLINE 00578 iterator1 begin1 () { 00579 return find1 (0, 0, 0); 00580 } 00581 BOOST_UBLAS_INLINE 00582 iterator1 end1 () { 00583 return find1 (0, size_, 0); 00584 } 00585 00586 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 00587 class const_iterator2: 00588 public container_const_reference<symmetric_matrix>, 00589 public random_access_iterator_base<dense_random_access_iterator_tag, 00590 const_iterator2, value_type> { 00591 public: 00592 typedef typename symmetric_matrix::value_type value_type; 00593 typedef typename symmetric_matrix::difference_type difference_type; 00594 typedef typename symmetric_matrix::const_reference reference; 00595 typedef const typename symmetric_matrix::pointer pointer; 00596 00597 typedef const_iterator1 dual_iterator_type; 00598 typedef const_reverse_iterator1 dual_reverse_iterator_type; 00599 00600 // Construction and destruction 00601 BOOST_UBLAS_INLINE 00602 const_iterator2 (): 00603 container_const_reference<self_type> (), it1_ (), it2_ () {} 00604 BOOST_UBLAS_INLINE 00605 const_iterator2 (const self_type &m, size_type it1, size_type it2): 00606 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {} 00607 BOOST_UBLAS_INLINE 00608 const_iterator2 (const iterator2 &it): 00609 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {} 00610 00611 // Arithmetic 00612 BOOST_UBLAS_INLINE 00613 const_iterator2 &operator ++ () { 00614 ++ it2_; 00615 return *this; 00616 } 00617 BOOST_UBLAS_INLINE 00618 const_iterator2 &operator -- () { 00619 -- it2_; 00620 return *this; 00621 } 00622 BOOST_UBLAS_INLINE 00623 const_iterator2 &operator += (difference_type n) { 00624 it2_ += n; 00625 return *this; 00626 } 00627 BOOST_UBLAS_INLINE 00628 const_iterator2 &operator -= (difference_type n) { 00629 it2_ -= n; 00630 return *this; 00631 } 00632 BOOST_UBLAS_INLINE 00633 difference_type operator - (const const_iterator2 &it) const { 00634 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00635 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 00636 return it2_ - it.it2_; 00637 } 00638 00639 // Dereference 00640 BOOST_UBLAS_INLINE 00641 const_reference operator * () const { 00642 return (*this) () (it1_, it2_); 00643 } 00644 BOOST_UBLAS_INLINE 00645 const_reference operator [] (difference_type n) const { 00646 return *(*this + n); 00647 } 00648 00649 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 00650 BOOST_UBLAS_INLINE 00651 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00652 typename self_type:: 00653 #endif 00654 const_iterator1 begin () const { 00655 return (*this) ().find1 (1, 0, it2_); 00656 } 00657 BOOST_UBLAS_INLINE 00658 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00659 typename self_type:: 00660 #endif 00661 const_iterator1 end () const { 00662 return (*this) ().find1 (1, (*this) ().size1 (), it2_); 00663 } 00664 BOOST_UBLAS_INLINE 00665 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00666 typename self_type:: 00667 #endif 00668 const_reverse_iterator1 rbegin () const { 00669 return const_reverse_iterator1 (end ()); 00670 } 00671 BOOST_UBLAS_INLINE 00672 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00673 typename self_type:: 00674 #endif 00675 const_reverse_iterator1 rend () const { 00676 return const_reverse_iterator1 (begin ()); 00677 } 00678 #endif 00679 00680 // Indices 00681 BOOST_UBLAS_INLINE 00682 size_type index1 () const { 00683 return it1_; 00684 } 00685 BOOST_UBLAS_INLINE 00686 size_type index2 () const { 00687 return it2_; 00688 } 00689 00690 // Assignment 00691 BOOST_UBLAS_INLINE 00692 const_iterator2 &operator = (const const_iterator2 &it) { 00693 container_const_reference<self_type>::assign (&it ()); 00694 it1_ = it.it1_; 00695 it2_ = it.it2_; 00696 return *this; 00697 } 00698 00699 // Comparison 00700 BOOST_UBLAS_INLINE 00701 bool operator == (const const_iterator2 &it) const { 00702 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00703 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 00704 return it2_ == it.it2_; 00705 } 00706 BOOST_UBLAS_INLINE 00707 bool operator < (const const_iterator2 &it) const { 00708 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00709 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 00710 return it2_ < it.it2_; 00711 } 00712 00713 private: 00714 size_type it1_; 00715 size_type it2_; 00716 }; 00717 #endif 00718 00719 BOOST_UBLAS_INLINE 00720 const_iterator2 begin2 () const { 00721 return find2 (0, 0, 0); 00722 } 00723 BOOST_UBLAS_INLINE 00724 const_iterator2 end2 () const { 00725 return find2 (0, 0, size_); 00726 } 00727 00728 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 00729 class iterator2: 00730 public container_reference<symmetric_matrix>, 00731 public random_access_iterator_base<packed_random_access_iterator_tag, 00732 iterator2, value_type> { 00733 public: 00734 typedef typename symmetric_matrix::value_type value_type; 00735 typedef typename symmetric_matrix::difference_type difference_type; 00736 typedef typename symmetric_matrix::reference reference; 00737 typedef typename symmetric_matrix::pointer pointer; 00738 00739 typedef iterator1 dual_iterator_type; 00740 typedef reverse_iterator1 dual_reverse_iterator_type; 00741 00742 // Construction and destruction 00743 BOOST_UBLAS_INLINE 00744 iterator2 (): 00745 container_reference<self_type> (), it1_ (), it2_ () {} 00746 BOOST_UBLAS_INLINE 00747 iterator2 (self_type &m, size_type it1, size_type it2): 00748 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {} 00749 00750 // Arithmetic 00751 BOOST_UBLAS_INLINE 00752 iterator2 &operator ++ () { 00753 ++ it2_; 00754 return *this; 00755 } 00756 BOOST_UBLAS_INLINE 00757 iterator2 &operator -- () { 00758 -- it2_; 00759 return *this; 00760 } 00761 BOOST_UBLAS_INLINE 00762 iterator2 &operator += (difference_type n) { 00763 it2_ += n; 00764 return *this; 00765 } 00766 BOOST_UBLAS_INLINE 00767 iterator2 &operator -= (difference_type n) { 00768 it2_ -= n; 00769 return *this; 00770 } 00771 BOOST_UBLAS_INLINE 00772 difference_type operator - (const iterator2 &it) const { 00773 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00774 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 00775 return it2_ - it.it2_; 00776 } 00777 00778 // Dereference 00779 BOOST_UBLAS_INLINE 00780 reference operator * () const { 00781 return (*this) () (it1_, it2_); 00782 } 00783 BOOST_UBLAS_INLINE 00784 reference operator [] (difference_type n) const { 00785 return *(*this + n); 00786 } 00787 00788 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 00789 BOOST_UBLAS_INLINE 00790 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00791 typename self_type:: 00792 #endif 00793 iterator1 begin () const { 00794 return (*this) ().find1 (1, 0, it2_); 00795 } 00796 BOOST_UBLAS_INLINE 00797 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00798 typename self_type:: 00799 #endif 00800 iterator1 end () const { 00801 return (*this) ().find1 (1, (*this) ().size1 (), it2_); 00802 } 00803 BOOST_UBLAS_INLINE 00804 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00805 typename self_type:: 00806 #endif 00807 reverse_iterator1 rbegin () const { 00808 return reverse_iterator1 (end ()); 00809 } 00810 BOOST_UBLAS_INLINE 00811 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 00812 typename self_type:: 00813 #endif 00814 reverse_iterator1 rend () const { 00815 return reverse_iterator1 (begin ()); 00816 } 00817 #endif 00818 00819 // Indices 00820 BOOST_UBLAS_INLINE 00821 size_type index1 () const { 00822 return it1_; 00823 } 00824 BOOST_UBLAS_INLINE 00825 size_type index2 () const { 00826 return it2_; 00827 } 00828 00829 // Assignment 00830 BOOST_UBLAS_INLINE 00831 iterator2 &operator = (const iterator2 &it) { 00832 container_reference<self_type>::assign (&it ()); 00833 it1_ = it.it1_; 00834 it2_ = it.it2_; 00835 return *this; 00836 } 00837 00838 // Comparison 00839 BOOST_UBLAS_INLINE 00840 bool operator == (const iterator2 &it) const { 00841 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00842 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 00843 return it2_ == it.it2_; 00844 } 00845 BOOST_UBLAS_INLINE 00846 bool operator < (const iterator2 &it) const { 00847 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 00848 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ()); 00849 return it2_ < it.it2_; 00850 } 00851 00852 private: 00853 size_type it1_; 00854 size_type it2_; 00855 00856 friend class const_iterator2; 00857 }; 00858 #endif 00859 00860 BOOST_UBLAS_INLINE 00861 iterator2 begin2 () { 00862 return find2 (0, 0, 0); 00863 } 00864 BOOST_UBLAS_INLINE 00865 iterator2 end2 () { 00866 return find2 (0, 0, size_); 00867 } 00868 00869 // Reverse iterators 00870 00871 BOOST_UBLAS_INLINE 00872 const_reverse_iterator1 rbegin1 () const { 00873 return const_reverse_iterator1 (end1 ()); 00874 } 00875 BOOST_UBLAS_INLINE 00876 const_reverse_iterator1 rend1 () const { 00877 return const_reverse_iterator1 (begin1 ()); 00878 } 00879 00880 BOOST_UBLAS_INLINE 00881 reverse_iterator1 rbegin1 () { 00882 return reverse_iterator1 (end1 ()); 00883 } 00884 BOOST_UBLAS_INLINE 00885 reverse_iterator1 rend1 () { 00886 return reverse_iterator1 (begin1 ()); 00887 } 00888 00889 BOOST_UBLAS_INLINE 00890 const_reverse_iterator2 rbegin2 () const { 00891 return const_reverse_iterator2 (end2 ()); 00892 } 00893 BOOST_UBLAS_INLINE 00894 const_reverse_iterator2 rend2 () const { 00895 return const_reverse_iterator2 (begin2 ()); 00896 } 00897 00898 BOOST_UBLAS_INLINE 00899 reverse_iterator2 rbegin2 () { 00900 return reverse_iterator2 (end2 ()); 00901 } 00902 BOOST_UBLAS_INLINE 00903 reverse_iterator2 rend2 () { 00904 return reverse_iterator2 (begin2 ()); 00905 } 00906 00907 private: 00908 size_type size_; 00909 array_type data_; 00910 }; 00911 00912 00913 // Symmetric matrix adaptor class 00914 template<class M, class TRI> 00915 class symmetric_adaptor: 00916 public matrix_expression<symmetric_adaptor<M, TRI> > { 00917 00918 typedef symmetric_adaptor<M, TRI> self_type; 00919 public: 00920 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS 00921 using matrix_expression<self_type>::operator (); 00922 #endif 00923 typedef const M const_matrix_type; 00924 typedef M matrix_type; 00925 typedef TRI triangular_type; 00926 typedef typename M::size_type size_type; 00927 typedef typename M::difference_type difference_type; 00928 typedef typename M::value_type value_type; 00929 typedef typename M::const_reference const_reference; 00930 typedef typename boost::mpl::if_<boost::is_const<M>, 00931 typename M::const_reference, 00932 typename M::reference>::type reference; 00933 typedef typename boost::mpl::if_<boost::is_const<M>, 00934 typename M::const_closure_type, 00935 typename M::closure_type>::type matrix_closure_type; 00936 typedef const self_type const_closure_type; 00937 typedef self_type closure_type; 00938 // Replaced by _temporary_traits to avoid type requirements on M 00939 //typedef typename M::vector_temporary_type vector_temporary_type; 00940 //typedef typename M::matrix_temporary_type matrix_temporary_type; 00941 typedef typename storage_restrict_traits<typename M::storage_category, 00942 packed_proxy_tag>::storage_category storage_category; 00943 typedef typename M::orientation_category orientation_category; 00944 00945 // Construction and destruction 00946 BOOST_UBLAS_INLINE 00947 symmetric_adaptor (matrix_type &data): 00948 matrix_expression<self_type> (), 00949 data_ (data) { 00950 BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ()); 00951 } 00952 BOOST_UBLAS_INLINE 00953 symmetric_adaptor (const symmetric_adaptor &m): 00954 matrix_expression<self_type> (), 00955 data_ (m.data_) { 00956 BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ()); 00957 } 00958 00959 // Accessors 00960 BOOST_UBLAS_INLINE 00961 size_type size1 () const { 00962 return data_.size1 (); 00963 } 00964 BOOST_UBLAS_INLINE 00965 size_type size2 () const { 00966 return data_.size2 (); 00967 } 00968 00969 // Storage accessors 00970 BOOST_UBLAS_INLINE 00971 const matrix_closure_type &data () const { 00972 return data_; 00973 } 00974 BOOST_UBLAS_INLINE 00975 matrix_closure_type &data () { 00976 return data_; 00977 } 00978 00979 // Element access 00980 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER 00981 BOOST_UBLAS_INLINE 00982 const_reference operator () (size_type i, size_type j) const { 00983 BOOST_UBLAS_CHECK (i < size1 (), bad_index ()); 00984 BOOST_UBLAS_CHECK (j < size2 (), bad_index ()); 00985 if (triangular_type::other (i, j)) 00986 return data () (i, j); 00987 else 00988 return data () (j, i); 00989 } 00990 BOOST_UBLAS_INLINE 00991 reference operator () (size_type i, size_type j) { 00992 BOOST_UBLAS_CHECK (i < size1 (), bad_index ()); 00993 BOOST_UBLAS_CHECK (j < size2 (), bad_index ()); 00994 if (triangular_type::other (i, j)) 00995 return data () (i, j); 00996 else 00997 return data () (j, i); 00998 } 00999 #else 01000 BOOST_UBLAS_INLINE 01001 reference operator () (size_type i, size_type j) const { 01002 BOOST_UBLAS_CHECK (i < size1 (), bad_index ()); 01003 BOOST_UBLAS_CHECK (j < size2 (), bad_index ()); 01004 if (triangular_type::other (i, j)) 01005 return data () (i, j); 01006 else 01007 return data () (j, i); 01008 } 01009 #endif 01010 01011 // Assignment 01012 BOOST_UBLAS_INLINE 01013 symmetric_adaptor &operator = (const symmetric_adaptor &m) { 01014 matrix_assign<scalar_assign, triangular_type> (*this, m); 01015 return *this; 01016 } 01017 BOOST_UBLAS_INLINE 01018 symmetric_adaptor &assign_temporary (symmetric_adaptor &m) { 01019 *this = m; 01020 return *this; 01021 } 01022 template<class AE> 01023 BOOST_UBLAS_INLINE 01024 symmetric_adaptor &operator = (const matrix_expression<AE> &ae) { 01025 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae)); 01026 return *this; 01027 } 01028 template<class AE> 01029 BOOST_UBLAS_INLINE 01030 symmetric_adaptor &assign (const matrix_expression<AE> &ae) { 01031 matrix_assign<scalar_assign, triangular_type> (*this, ae); 01032 return *this; 01033 } 01034 template<class AE> 01035 BOOST_UBLAS_INLINE 01036 symmetric_adaptor& operator += (const matrix_expression<AE> &ae) { 01037 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae)); 01038 return *this; 01039 } 01040 template<class AE> 01041 BOOST_UBLAS_INLINE 01042 symmetric_adaptor &plus_assign (const matrix_expression<AE> &ae) { 01043 matrix_assign<scalar_plus_assign, triangular_type> (*this, ae); 01044 return *this; 01045 } 01046 template<class AE> 01047 BOOST_UBLAS_INLINE 01048 symmetric_adaptor& operator -= (const matrix_expression<AE> &ae) { 01049 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae)); 01050 return *this; 01051 } 01052 template<class AE> 01053 BOOST_UBLAS_INLINE 01054 symmetric_adaptor &minus_assign (const matrix_expression<AE> &ae) { 01055 matrix_assign<scalar_minus_assign, triangular_type> (*this, ae); 01056 return *this; 01057 } 01058 template<class AT> 01059 BOOST_UBLAS_INLINE 01060 symmetric_adaptor& operator *= (const AT &at) { 01061 matrix_assign_scalar<scalar_multiplies_assign> (*this, at); 01062 return *this; 01063 } 01064 template<class AT> 01065 BOOST_UBLAS_INLINE 01066 symmetric_adaptor& operator /= (const AT &at) { 01067 matrix_assign_scalar<scalar_divides_assign> (*this, at); 01068 return *this; 01069 } 01070 01071 // Closure comparison 01072 BOOST_UBLAS_INLINE 01073 bool same_closure (const symmetric_adaptor &sa) const { 01074 return (*this).data ().same_closure (sa.data ()); 01075 } 01076 01077 // Swapping 01078 BOOST_UBLAS_INLINE 01079 void swap (symmetric_adaptor &m) { 01080 if (this != &m) 01081 matrix_swap<scalar_swap, triangular_type> (*this, m); 01082 } 01083 BOOST_UBLAS_INLINE 01084 friend void swap (symmetric_adaptor &m1, symmetric_adaptor &m2) { 01085 m1.swap (m2); 01086 } 01087 01088 // Iterator types 01089 private: 01090 // Use matrix iterator 01091 typedef typename M::const_iterator1 const_subiterator1_type; 01092 typedef typename boost::mpl::if_<boost::is_const<M>, 01093 typename M::const_iterator1, 01094 typename M::iterator1>::type subiterator1_type; 01095 typedef typename M::const_iterator2 const_subiterator2_type; 01096 typedef typename boost::mpl::if_<boost::is_const<M>, 01097 typename M::const_iterator2, 01098 typename M::iterator2>::type subiterator2_type; 01099 01100 public: 01101 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR 01102 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1; 01103 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2; 01104 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1; 01105 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2; 01106 #else 01107 class const_iterator1; 01108 class iterator1; 01109 class const_iterator2; 01110 class iterator2; 01111 #endif 01112 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1; 01113 typedef reverse_iterator_base1<iterator1> reverse_iterator1; 01114 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2; 01115 typedef reverse_iterator_base2<iterator2> reverse_iterator2; 01116 01117 // Element lookup 01118 BOOST_UBLAS_INLINE 01119 const_iterator1 find1 (int rank, size_type i, size_type j) const { 01120 if (triangular_type::other (i, j)) { 01121 if (triangular_type::other (size1 (), j)) { 01122 return const_iterator1 (*this, 0, 0, 01123 data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j), 01124 data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ())); 01125 } else { 01126 return const_iterator1 (*this, 0, 1, 01127 data ().find1 (rank, i, j), data ().find1 (rank, j, j), 01128 data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ())); 01129 } 01130 } else { 01131 if (triangular_type::other (size1 (), j)) { 01132 return const_iterator1 (*this, 1, 0, 01133 data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j), 01134 data ().find2 (rank, j, i), data ().find2 (rank, j, j)); 01135 } else { 01136 return const_iterator1 (*this, 1, 1, 01137 data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()), 01138 data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ())); 01139 } 01140 } 01141 } 01142 BOOST_UBLAS_INLINE 01143 iterator1 find1 (int rank, size_type i, size_type j) { 01144 if (rank == 1) 01145 i = triangular_type::mutable_restrict1 (i, j, size1(), size2()); 01146 return iterator1 (*this, data ().find1 (rank, i, j)); 01147 } 01148 BOOST_UBLAS_INLINE 01149 const_iterator2 find2 (int rank, size_type i, size_type j) const { 01150 if (triangular_type::other (i, j)) { 01151 if (triangular_type::other (i, size2 ())) { 01152 return const_iterator2 (*this, 1, 1, 01153 data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()), 01154 data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ())); 01155 } else { 01156 return const_iterator2 (*this, 1, 0, 01157 data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i), 01158 data ().find2 (rank, i, j), data ().find2 (rank, i, i)); 01159 } 01160 } else { 01161 if (triangular_type::other (i, size2 ())) { 01162 return const_iterator2 (*this, 0, 1, 01163 data ().find1 (rank, j, i), data ().find1 (rank, i, i), 01164 data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ())); 01165 } else { 01166 return const_iterator2 (*this, 0, 0, 01167 data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i), 01168 data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ())); 01169 } 01170 } 01171 } 01172 BOOST_UBLAS_INLINE 01173 iterator2 find2 (int rank, size_type i, size_type j) { 01174 if (rank == 1) 01175 j = triangular_type::mutable_restrict2 (i, j, size1(), size2()); 01176 return iterator2 (*this, data ().find2 (rank, i, j)); 01177 } 01178 01179 // Iterators simply are indices. 01180 01181 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 01182 class const_iterator1: 01183 public container_const_reference<symmetric_adaptor>, 01184 public random_access_iterator_base<typename iterator_restrict_traits< 01185 typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category, 01186 const_iterator1, value_type> { 01187 public: 01188 typedef typename const_subiterator1_type::value_type value_type; 01189 typedef typename const_subiterator1_type::difference_type difference_type; 01190 typedef typename const_subiterator1_type::reference reference; 01191 typedef typename const_subiterator1_type::pointer pointer; 01192 01193 typedef const_iterator2 dual_iterator_type; 01194 typedef const_reverse_iterator2 dual_reverse_iterator_type; 01195 01196 // Construction and destruction 01197 BOOST_UBLAS_INLINE 01198 const_iterator1 (): 01199 container_const_reference<self_type> (), 01200 begin_ (-1), end_ (-1), current_ (-1), 01201 it1_begin_ (), it1_end_ (), it1_ (), 01202 it2_begin_ (), it2_end_ (), it2_ () {} 01203 BOOST_UBLAS_INLINE 01204 const_iterator1 (const self_type &m, int begin, int end, 01205 const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end, 01206 const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end): 01207 container_const_reference<self_type> (m), 01208 begin_ (begin), end_ (end), current_ (begin), 01209 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_), 01210 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) { 01211 if (current_ == 0 && it1_ == it1_end_) 01212 current_ = 1; 01213 if (current_ == 1 && it2_ == it2_end_) 01214 current_ = 0; 01215 if ((current_ == 0 && it1_ == it1_end_) || 01216 (current_ == 1 && it2_ == it2_end_)) 01217 current_ = end_; 01218 BOOST_UBLAS_CHECK (current_ == end_ || 01219 (current_ == 0 && it1_ != it1_end_) || 01220 (current_ == 1 && it2_ != it2_end_), internal_logic ()); 01221 } 01222 // FIXME cannot compile 01223 // iterator1 does not have these members! 01224 BOOST_UBLAS_INLINE 01225 const_iterator1 (const iterator1 &it): 01226 container_const_reference<self_type> (it ()), 01227 begin_ (it.begin_), end_ (it.end_), current_ (it.current_), 01228 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_), 01229 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) { 01230 BOOST_UBLAS_CHECK (current_ == end_ || 01231 (current_ == 0 && it1_ != it1_end_) || 01232 (current_ == 1 && it2_ != it2_end_), internal_logic ()); 01233 } 01234 01235 // Arithmetic 01236 BOOST_UBLAS_INLINE 01237 const_iterator1 &operator ++ () { 01238 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01239 if (current_ == 0) { 01240 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 01241 ++ it1_; 01242 if (it1_ == it1_end_ && end_ == 1) { 01243 it2_ = it2_begin_; 01244 current_ = 1; 01245 } 01246 } else /* if (current_ == 1) */ { 01247 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 01248 ++ it2_; 01249 if (it2_ == it2_end_ && end_ == 0) { 01250 it1_ = it1_begin_; 01251 current_ = 0; 01252 } 01253 } 01254 return *this; 01255 } 01256 BOOST_UBLAS_INLINE 01257 const_iterator1 &operator -- () { 01258 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01259 if (current_ == 0) { 01260 if (it1_ == it1_begin_ && begin_ == 1) { 01261 it2_ = it2_end_; 01262 BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ()); 01263 -- it2_; 01264 current_ = 1; 01265 } else { 01266 -- it1_; 01267 } 01268 } else /* if (current_ == 1) */ { 01269 if (it2_ == it2_begin_ && begin_ == 0) { 01270 it1_ = it1_end_; 01271 BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ()); 01272 -- it1_; 01273 current_ = 0; 01274 } else { 01275 -- it2_; 01276 } 01277 } 01278 return *this; 01279 } 01280 BOOST_UBLAS_INLINE 01281 const_iterator1 &operator += (difference_type n) { 01282 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01283 if (current_ == 0) { 01284 size_type d = (std::min) (n, it1_end_ - it1_); 01285 it1_ += d; 01286 n -= d; 01287 if (n > 0 || (end_ == 1 && it1_ == it1_end_)) { 01288 BOOST_UBLAS_CHECK (end_ == 1, external_logic ()); 01289 d = (std::min) (n, it2_end_ - it2_begin_); 01290 it2_ = it2_begin_ + d; 01291 n -= d; 01292 current_ = 1; 01293 } 01294 } else /* if (current_ == 1) */ { 01295 size_type d = (std::min) (n, it2_end_ - it2_); 01296 it2_ += d; 01297 n -= d; 01298 if (n > 0 || (end_ == 0 && it2_ == it2_end_)) { 01299 BOOST_UBLAS_CHECK (end_ == 0, external_logic ()); 01300 d = (std::min) (n, it1_end_ - it1_begin_); 01301 it1_ = it1_begin_ + d; 01302 n -= d; 01303 current_ = 0; 01304 } 01305 } 01306 BOOST_UBLAS_CHECK (n == 0, external_logic ()); 01307 return *this; 01308 } 01309 BOOST_UBLAS_INLINE 01310 const_iterator1 &operator -= (difference_type n) { 01311 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01312 if (current_ == 0) { 01313 size_type d = (std::min) (n, it1_ - it1_begin_); 01314 it1_ -= d; 01315 n -= d; 01316 if (n > 0) { 01317 BOOST_UBLAS_CHECK (end_ == 1, external_logic ()); 01318 d = (std::min) (n, it2_end_ - it2_begin_); 01319 it2_ = it2_end_ - d; 01320 n -= d; 01321 current_ = 1; 01322 } 01323 } else /* if (current_ == 1) */ { 01324 size_type d = (std::min) (n, it2_ - it2_begin_); 01325 it2_ -= d; 01326 n -= d; 01327 if (n > 0) { 01328 BOOST_UBLAS_CHECK (end_ == 0, external_logic ()); 01329 d = (std::min) (n, it1_end_ - it1_begin_); 01330 it1_ = it1_end_ - d; 01331 n -= d; 01332 current_ = 0; 01333 } 01334 } 01335 BOOST_UBLAS_CHECK (n == 0, external_logic ()); 01336 return *this; 01337 } 01338 BOOST_UBLAS_INLINE 01339 difference_type operator - (const const_iterator1 &it) const { 01340 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 01341 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01342 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ()); 01343 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ()); 01344 if (current_ == 0 && it.current_ == 0) { 01345 return it1_ - it.it1_; 01346 } else if (current_ == 0 && it.current_ == 1) { 01347 if (end_ == 1 && it.end_ == 1) { 01348 return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_); 01349 } else /* if (end_ == 0 && it.end_ == 0) */ { 01350 return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_); 01351 } 01352 01353 } else if (current_ == 1 && it.current_ == 0) { 01354 if (end_ == 1 && it.end_ == 1) { 01355 return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_); 01356 } else /* if (end_ == 0 && it.end_ == 0) */ { 01357 return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_); 01358 } 01359 } 01360 /* current_ == 1 && it.current_ == 1 */ { 01361 return it2_ - it.it2_; 01362 } 01363 } 01364 01365 // Dereference 01366 BOOST_UBLAS_INLINE 01367 const_reference operator * () const { 01368 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01369 if (current_ == 0) { 01370 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 01371 return *it1_; 01372 } else /* if (current_ == 1) */ { 01373 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 01374 return *it2_; 01375 } 01376 } 01377 BOOST_UBLAS_INLINE 01378 const_reference operator [] (difference_type n) const { 01379 return *(*this + n); 01380 } 01381 01382 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 01383 BOOST_UBLAS_INLINE 01384 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01385 typename self_type:: 01386 #endif 01387 const_iterator2 begin () const { 01388 return (*this) ().find2 (1, index1 (), 0); 01389 } 01390 BOOST_UBLAS_INLINE 01391 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01392 typename self_type:: 01393 #endif 01394 const_iterator2 end () const { 01395 return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); 01396 } 01397 BOOST_UBLAS_INLINE 01398 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01399 typename self_type:: 01400 #endif 01401 const_reverse_iterator2 rbegin () const { 01402 return const_reverse_iterator2 (end ()); 01403 } 01404 BOOST_UBLAS_INLINE 01405 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01406 typename self_type:: 01407 #endif 01408 const_reverse_iterator2 rend () const { 01409 return const_reverse_iterator2 (begin ()); 01410 } 01411 #endif 01412 01413 // Indices 01414 BOOST_UBLAS_INLINE 01415 size_type index1 () const { 01416 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01417 if (current_ == 0) { 01418 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 01419 return it1_.index1 (); 01420 } else /* if (current_ == 1) */ { 01421 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 01422 return it2_.index2 (); 01423 } 01424 } 01425 BOOST_UBLAS_INLINE 01426 size_type index2 () const { 01427 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01428 if (current_ == 0) { 01429 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 01430 return it1_.index2 (); 01431 } else /* if (current_ == 1) */ { 01432 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 01433 return it2_.index1 (); 01434 } 01435 } 01436 01437 // Assignment 01438 BOOST_UBLAS_INLINE 01439 const_iterator1 &operator = (const const_iterator1 &it) { 01440 container_const_reference<self_type>::assign (&it ()); 01441 begin_ = it.begin_; 01442 end_ = it.end_; 01443 current_ = it.current_; 01444 it1_begin_ = it.it1_begin_; 01445 it1_end_ = it.it1_end_; 01446 it1_ = it.it1_; 01447 it2_begin_ = it.it2_begin_; 01448 it2_end_ = it.it2_end_; 01449 it2_ = it.it2_; 01450 return *this; 01451 } 01452 01453 // Comparison 01454 BOOST_UBLAS_INLINE 01455 bool operator == (const const_iterator1 &it) const { 01456 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 01457 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01458 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ()); 01459 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ()); 01460 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) || 01461 (current_ == 1 && it.current_ == 1 && it2_ == it.it2_); 01462 } 01463 BOOST_UBLAS_INLINE 01464 bool operator < (const const_iterator1 &it) const { 01465 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 01466 return it - *this > 0; 01467 } 01468 01469 private: 01470 int begin_; 01471 int end_; 01472 int current_; 01473 const_subiterator1_type it1_begin_; 01474 const_subiterator1_type it1_end_; 01475 const_subiterator1_type it1_; 01476 const_subiterator2_type it2_begin_; 01477 const_subiterator2_type it2_end_; 01478 const_subiterator2_type it2_; 01479 }; 01480 #endif 01481 01482 BOOST_UBLAS_INLINE 01483 const_iterator1 begin1 () const { 01484 return find1 (0, 0, 0); 01485 } 01486 BOOST_UBLAS_INLINE 01487 const_iterator1 end1 () const { 01488 return find1 (0, size1 (), 0); 01489 } 01490 01491 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 01492 class iterator1: 01493 public container_reference<symmetric_adaptor>, 01494 public random_access_iterator_base<typename iterator_restrict_traits< 01495 typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category, 01496 iterator1, value_type> { 01497 public: 01498 typedef typename subiterator1_type::value_type value_type; 01499 typedef typename subiterator1_type::difference_type difference_type; 01500 typedef typename subiterator1_type::reference reference; 01501 typedef typename subiterator1_type::pointer pointer; 01502 01503 typedef iterator2 dual_iterator_type; 01504 typedef reverse_iterator2 dual_reverse_iterator_type; 01505 01506 // Construction and destruction 01507 BOOST_UBLAS_INLINE 01508 iterator1 (): 01509 container_reference<self_type> (), it1_ () {} 01510 BOOST_UBLAS_INLINE 01511 iterator1 (self_type &m, const subiterator1_type &it1): 01512 container_reference<self_type> (m), it1_ (it1) {} 01513 01514 // Arithmetic 01515 BOOST_UBLAS_INLINE 01516 iterator1 &operator ++ () { 01517 ++ it1_; 01518 return *this; 01519 } 01520 BOOST_UBLAS_INLINE 01521 iterator1 &operator -- () { 01522 -- it1_; 01523 return *this; 01524 } 01525 BOOST_UBLAS_INLINE 01526 iterator1 &operator += (difference_type n) { 01527 it1_ += n; 01528 return *this; 01529 } 01530 BOOST_UBLAS_INLINE 01531 iterator1 &operator -= (difference_type n) { 01532 it1_ -= n; 01533 return *this; 01534 } 01535 BOOST_UBLAS_INLINE 01536 difference_type operator - (const iterator1 &it) const { 01537 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 01538 return it1_ - it.it1_; 01539 } 01540 01541 // Dereference 01542 BOOST_UBLAS_INLINE 01543 reference operator * () const { 01544 return *it1_; 01545 } 01546 BOOST_UBLAS_INLINE 01547 reference operator [] (difference_type n) const { 01548 return *(*this + n); 01549 } 01550 01551 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 01552 BOOST_UBLAS_INLINE 01553 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01554 typename self_type:: 01555 #endif 01556 iterator2 begin () const { 01557 return (*this) ().find2 (1, index1 (), 0); 01558 } 01559 BOOST_UBLAS_INLINE 01560 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01561 typename self_type:: 01562 #endif 01563 iterator2 end () const { 01564 return (*this) ().find2 (1, index1 (), (*this) ().size2 ()); 01565 } 01566 BOOST_UBLAS_INLINE 01567 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01568 typename self_type:: 01569 #endif 01570 reverse_iterator2 rbegin () const { 01571 return reverse_iterator2 (end ()); 01572 } 01573 BOOST_UBLAS_INLINE 01574 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01575 typename self_type:: 01576 #endif 01577 reverse_iterator2 rend () const { 01578 return reverse_iterator2 (begin ()); 01579 } 01580 #endif 01581 01582 // Indices 01583 BOOST_UBLAS_INLINE 01584 size_type index1 () const { 01585 return it1_.index1 (); 01586 } 01587 BOOST_UBLAS_INLINE 01588 size_type index2 () const { 01589 return it1_.index2 (); 01590 } 01591 01592 // Assignment 01593 BOOST_UBLAS_INLINE 01594 iterator1 &operator = (const iterator1 &it) { 01595 container_reference<self_type>::assign (&it ()); 01596 it1_ = it.it1_; 01597 return *this; 01598 } 01599 01600 // Comparison 01601 BOOST_UBLAS_INLINE 01602 bool operator == (const iterator1 &it) const { 01603 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 01604 return it1_ == it.it1_; 01605 } 01606 BOOST_UBLAS_INLINE 01607 bool operator < (const iterator1 &it) const { 01608 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 01609 return it1_ < it.it1_; 01610 } 01611 01612 private: 01613 subiterator1_type it1_; 01614 01615 friend class const_iterator1; 01616 }; 01617 #endif 01618 01619 BOOST_UBLAS_INLINE 01620 iterator1 begin1 () { 01621 return find1 (0, 0, 0); 01622 } 01623 BOOST_UBLAS_INLINE 01624 iterator1 end1 () { 01625 return find1 (0, size1 (), 0); 01626 } 01627 01628 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 01629 class const_iterator2: 01630 public container_const_reference<symmetric_adaptor>, 01631 public random_access_iterator_base<typename iterator_restrict_traits< 01632 typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category, 01633 const_iterator2, value_type> { 01634 public: 01635 typedef typename const_subiterator2_type::value_type value_type; 01636 typedef typename const_subiterator2_type::difference_type difference_type; 01637 typedef typename const_subiterator2_type::reference reference; 01638 typedef typename const_subiterator2_type::pointer pointer; 01639 01640 typedef const_iterator1 dual_iterator_type; 01641 typedef const_reverse_iterator1 dual_reverse_iterator_type; 01642 01643 // Construction and destruction 01644 BOOST_UBLAS_INLINE 01645 const_iterator2 (): 01646 container_const_reference<self_type> (), 01647 begin_ (-1), end_ (-1), current_ (-1), 01648 it1_begin_ (), it1_end_ (), it1_ (), 01649 it2_begin_ (), it2_end_ (), it2_ () {} 01650 BOOST_UBLAS_INLINE 01651 const_iterator2 (const self_type &m, int begin, int end, 01652 const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end, 01653 const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end): 01654 container_const_reference<self_type> (m), 01655 begin_ (begin), end_ (end), current_ (begin), 01656 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_), 01657 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) { 01658 if (current_ == 0 && it1_ == it1_end_) 01659 current_ = 1; 01660 if (current_ == 1 && it2_ == it2_end_) 01661 current_ = 0; 01662 if ((current_ == 0 && it1_ == it1_end_) || 01663 (current_ == 1 && it2_ == it2_end_)) 01664 current_ = end_; 01665 BOOST_UBLAS_CHECK (current_ == end_ || 01666 (current_ == 0 && it1_ != it1_end_) || 01667 (current_ == 1 && it2_ != it2_end_), internal_logic ()); 01668 } 01669 // FIXME cannot compiler 01670 // iterator2 does not have these members! 01671 BOOST_UBLAS_INLINE 01672 const_iterator2 (const iterator2 &it): 01673 container_const_reference<self_type> (it ()), 01674 begin_ (it.begin_), end_ (it.end_), current_ (it.current_), 01675 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_), 01676 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) { 01677 BOOST_UBLAS_CHECK (current_ == end_ || 01678 (current_ == 0 && it1_ != it1_end_) || 01679 (current_ == 1 && it2_ != it2_end_), internal_logic ()); 01680 } 01681 01682 // Arithmetic 01683 BOOST_UBLAS_INLINE 01684 const_iterator2 &operator ++ () { 01685 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01686 if (current_ == 0) { 01687 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 01688 ++ it1_; 01689 if (it1_ == it1_end_ && end_ == 1) { 01690 it2_ = it2_begin_; 01691 current_ = 1; 01692 } 01693 } else /* if (current_ == 1) */ { 01694 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 01695 ++ it2_; 01696 if (it2_ == it2_end_ && end_ == 0) { 01697 it1_ = it1_begin_; 01698 current_ = 0; 01699 } 01700 } 01701 return *this; 01702 } 01703 BOOST_UBLAS_INLINE 01704 const_iterator2 &operator -- () { 01705 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01706 if (current_ == 0) { 01707 if (it1_ == it1_begin_ && begin_ == 1) { 01708 it2_ = it2_end_; 01709 BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ()); 01710 -- it2_; 01711 current_ = 1; 01712 } else { 01713 -- it1_; 01714 } 01715 } else /* if (current_ == 1) */ { 01716 if (it2_ == it2_begin_ && begin_ == 0) { 01717 it1_ = it1_end_; 01718 BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ()); 01719 -- it1_; 01720 current_ = 0; 01721 } else { 01722 -- it2_; 01723 } 01724 } 01725 return *this; 01726 } 01727 BOOST_UBLAS_INLINE 01728 const_iterator2 &operator += (difference_type n) { 01729 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01730 if (current_ == 0) { 01731 size_type d = (std::min) (n, it1_end_ - it1_); 01732 it1_ += d; 01733 n -= d; 01734 if (n > 0 || (end_ == 1 && it1_ == it1_end_)) { 01735 BOOST_UBLAS_CHECK (end_ == 1, external_logic ()); 01736 d = (std::min) (n, it2_end_ - it2_begin_); 01737 it2_ = it2_begin_ + d; 01738 n -= d; 01739 current_ = 1; 01740 } 01741 } else /* if (current_ == 1) */ { 01742 size_type d = (std::min) (n, it2_end_ - it2_); 01743 it2_ += d; 01744 n -= d; 01745 if (n > 0 || (end_ == 0 && it2_ == it2_end_)) { 01746 BOOST_UBLAS_CHECK (end_ == 0, external_logic ()); 01747 d = (std::min) (n, it1_end_ - it1_begin_); 01748 it1_ = it1_begin_ + d; 01749 n -= d; 01750 current_ = 0; 01751 } 01752 } 01753 BOOST_UBLAS_CHECK (n == 0, external_logic ()); 01754 return *this; 01755 } 01756 BOOST_UBLAS_INLINE 01757 const_iterator2 &operator -= (difference_type n) { 01758 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01759 if (current_ == 0) { 01760 size_type d = (std::min) (n, it1_ - it1_begin_); 01761 it1_ -= d; 01762 n -= d; 01763 if (n > 0) { 01764 BOOST_UBLAS_CHECK (end_ == 1, external_logic ()); 01765 d = (std::min) (n, it2_end_ - it2_begin_); 01766 it2_ = it2_end_ - d; 01767 n -= d; 01768 current_ = 1; 01769 } 01770 } else /* if (current_ == 1) */ { 01771 size_type d = (std::min) (n, it2_ - it2_begin_); 01772 it2_ -= d; 01773 n -= d; 01774 if (n > 0) { 01775 BOOST_UBLAS_CHECK (end_ == 0, external_logic ()); 01776 d = (std::min) (n, it1_end_ - it1_begin_); 01777 it1_ = it1_end_ - d; 01778 n -= d; 01779 current_ = 0; 01780 } 01781 } 01782 BOOST_UBLAS_CHECK (n == 0, external_logic ()); 01783 return *this; 01784 } 01785 BOOST_UBLAS_INLINE 01786 difference_type operator - (const const_iterator2 &it) const { 01787 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 01788 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01789 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ()); 01790 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ()); 01791 if (current_ == 0 && it.current_ == 0) { 01792 return it1_ - it.it1_; 01793 } else if (current_ == 0 && it.current_ == 1) { 01794 if (end_ == 1 && it.end_ == 1) { 01795 return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_); 01796 } else /* if (end_ == 0 && it.end_ == 0) */ { 01797 return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_); 01798 } 01799 01800 } else if (current_ == 1 && it.current_ == 0) { 01801 if (end_ == 1 && it.end_ == 1) { 01802 return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_); 01803 } else /* if (end_ == 0 && it.end_ == 0) */ { 01804 return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_); 01805 } 01806 } 01807 /* current_ == 1 && it.current_ == 1 */ { 01808 return it2_ - it.it2_; 01809 } 01810 } 01811 01812 // Dereference 01813 BOOST_UBLAS_INLINE 01814 const_reference operator * () const { 01815 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01816 if (current_ == 0) { 01817 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 01818 return *it1_; 01819 } else /* if (current_ == 1) */ { 01820 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 01821 return *it2_; 01822 } 01823 } 01824 BOOST_UBLAS_INLINE 01825 const_reference operator [] (difference_type n) const { 01826 return *(*this + n); 01827 } 01828 01829 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 01830 BOOST_UBLAS_INLINE 01831 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01832 typename self_type:: 01833 #endif 01834 const_iterator1 begin () const { 01835 return (*this) ().find1 (1, 0, index2 ()); 01836 } 01837 BOOST_UBLAS_INLINE 01838 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01839 typename self_type:: 01840 #endif 01841 const_iterator1 end () const { 01842 return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); 01843 } 01844 BOOST_UBLAS_INLINE 01845 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01846 typename self_type:: 01847 #endif 01848 const_reverse_iterator1 rbegin () const { 01849 return const_reverse_iterator1 (end ()); 01850 } 01851 BOOST_UBLAS_INLINE 01852 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 01853 typename self_type:: 01854 #endif 01855 const_reverse_iterator1 rend () const { 01856 return const_reverse_iterator1 (begin ()); 01857 } 01858 #endif 01859 01860 // Indices 01861 BOOST_UBLAS_INLINE 01862 size_type index1 () const { 01863 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01864 if (current_ == 0) { 01865 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 01866 return it1_.index2 (); 01867 } else /* if (current_ == 1) */ { 01868 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 01869 return it2_.index1 (); 01870 } 01871 } 01872 BOOST_UBLAS_INLINE 01873 size_type index2 () const { 01874 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01875 if (current_ == 0) { 01876 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ()); 01877 return it1_.index1 (); 01878 } else /* if (current_ == 1) */ { 01879 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ()); 01880 return it2_.index2 (); 01881 } 01882 } 01883 01884 // Assignment 01885 BOOST_UBLAS_INLINE 01886 const_iterator2 &operator = (const const_iterator2 &it) { 01887 container_const_reference<self_type>::assign (&it ()); 01888 begin_ = it.begin_; 01889 end_ = it.end_; 01890 current_ = it.current_; 01891 it1_begin_ = it.it1_begin_; 01892 it1_end_ = it.it1_end_; 01893 it1_ = it.it1_; 01894 it2_begin_ = it.it2_begin_; 01895 it2_end_ = it.it2_end_; 01896 it2_ = it.it2_; 01897 return *this; 01898 } 01899 01900 // Comparison 01901 BOOST_UBLAS_INLINE 01902 bool operator == (const const_iterator2 &it) const { 01903 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 01904 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ()); 01905 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ()); 01906 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ()); 01907 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) || 01908 (current_ == 1 && it.current_ == 1 && it2_ == it.it2_); 01909 } 01910 BOOST_UBLAS_INLINE 01911 bool operator < (const const_iterator2 &it) const { 01912 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 01913 return it - *this > 0; 01914 } 01915 01916 private: 01917 int begin_; 01918 int end_; 01919 int current_; 01920 const_subiterator1_type it1_begin_; 01921 const_subiterator1_type it1_end_; 01922 const_subiterator1_type it1_; 01923 const_subiterator2_type it2_begin_; 01924 const_subiterator2_type it2_end_; 01925 const_subiterator2_type it2_; 01926 }; 01927 #endif 01928 01929 BOOST_UBLAS_INLINE 01930 const_iterator2 begin2 () const { 01931 return find2 (0, 0, 0); 01932 } 01933 BOOST_UBLAS_INLINE 01934 const_iterator2 end2 () const { 01935 return find2 (0, 0, size2 ()); 01936 } 01937 01938 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR 01939 class iterator2: 01940 public container_reference<symmetric_adaptor>, 01941 public random_access_iterator_base<typename iterator_restrict_traits< 01942 typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category, 01943 iterator2, value_type> { 01944 public: 01945 typedef typename subiterator2_type::value_type value_type; 01946 typedef typename subiterator2_type::difference_type difference_type; 01947 typedef typename subiterator2_type::reference reference; 01948 typedef typename subiterator2_type::pointer pointer; 01949 01950 typedef iterator1 dual_iterator_type; 01951 typedef reverse_iterator1 dual_reverse_iterator_type; 01952 01953 // Construction and destruction 01954 BOOST_UBLAS_INLINE 01955 iterator2 (): 01956 container_reference<self_type> (), it2_ () {} 01957 BOOST_UBLAS_INLINE 01958 iterator2 (self_type &m, const subiterator2_type &it2): 01959 container_reference<self_type> (m), it2_ (it2) {} 01960 01961 // Arithmetic 01962 BOOST_UBLAS_INLINE 01963 iterator2 &operator ++ () { 01964 ++ it2_; 01965 return *this; 01966 } 01967 BOOST_UBLAS_INLINE 01968 iterator2 &operator -- () { 01969 -- it2_; 01970 return *this; 01971 } 01972 BOOST_UBLAS_INLINE 01973 iterator2 &operator += (difference_type n) { 01974 it2_ += n; 01975 return *this; 01976 } 01977 BOOST_UBLAS_INLINE 01978 iterator2 &operator -= (difference_type n) { 01979 it2_ -= n; 01980 return *this; 01981 } 01982 BOOST_UBLAS_INLINE 01983 difference_type operator - (const iterator2 &it) const { 01984 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 01985 return it2_ - it.it2_; 01986 } 01987 01988 // Dereference 01989 BOOST_UBLAS_INLINE 01990 reference operator * () const { 01991 return *it2_; 01992 } 01993 BOOST_UBLAS_INLINE 01994 reference operator [] (difference_type n) const { 01995 return *(*this + n); 01996 } 01997 01998 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION 01999 BOOST_UBLAS_INLINE 02000 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 02001 typename self_type:: 02002 #endif 02003 iterator1 begin () const { 02004 return (*this) ().find1 (1, 0, index2 ()); 02005 } 02006 BOOST_UBLAS_INLINE 02007 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 02008 typename self_type:: 02009 #endif 02010 iterator1 end () const { 02011 return (*this) ().find1 (1, (*this) ().size1 (), index2 ()); 02012 } 02013 BOOST_UBLAS_INLINE 02014 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 02015 typename self_type:: 02016 #endif 02017 reverse_iterator1 rbegin () const { 02018 return reverse_iterator1 (end ()); 02019 } 02020 BOOST_UBLAS_INLINE 02021 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION 02022 typename self_type:: 02023 #endif 02024 reverse_iterator1 rend () const { 02025 return reverse_iterator1 (begin ()); 02026 } 02027 #endif 02028 02029 // Indices 02030 BOOST_UBLAS_INLINE 02031 size_type index1 () const { 02032 return it2_.index1 (); 02033 } 02034 BOOST_UBLAS_INLINE 02035 size_type index2 () const { 02036 return it2_.index2 (); 02037 } 02038 02039 // Assignment 02040 BOOST_UBLAS_INLINE 02041 iterator2 &operator = (const iterator2 &it) { 02042 container_reference<self_type>::assign (&it ()); 02043 it2_ = it.it2_; 02044 return *this; 02045 } 02046 02047 // Comparison 02048 BOOST_UBLAS_INLINE 02049 bool operator == (const iterator2 &it) const { 02050 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 02051 return it2_ == it.it2_; 02052 } 02053 BOOST_UBLAS_INLINE 02054 bool operator < (const iterator2 &it) const { 02055 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ()); 02056 return it2_ < it.it2_; 02057 } 02058 02059 private: 02060 subiterator2_type it2_; 02061 02062 friend class const_iterator2; 02063 }; 02064 #endif 02065 02066 BOOST_UBLAS_INLINE 02067 iterator2 begin2 () { 02068 return find2 (0, 0, 0); 02069 } 02070 BOOST_UBLAS_INLINE 02071 iterator2 end2 () { 02072 return find2 (0, 0, size2 ()); 02073 } 02074 02075 // Reverse iterators 02076 02077 BOOST_UBLAS_INLINE 02078 const_reverse_iterator1 rbegin1 () const { 02079 return const_reverse_iterator1 (end1 ()); 02080 } 02081 BOOST_UBLAS_INLINE 02082 const_reverse_iterator1 rend1 () const { 02083 return const_reverse_iterator1 (begin1 ()); 02084 } 02085 02086 BOOST_UBLAS_INLINE 02087 reverse_iterator1 rbegin1 () { 02088 return reverse_iterator1 (end1 ()); 02089 } 02090 BOOST_UBLAS_INLINE 02091 reverse_iterator1 rend1 () { 02092 return reverse_iterator1 (begin1 ()); 02093 } 02094 02095 BOOST_UBLAS_INLINE 02096 const_reverse_iterator2 rbegin2 () const { 02097 return const_reverse_iterator2 (end2 ()); 02098 } 02099 BOOST_UBLAS_INLINE 02100 const_reverse_iterator2 rend2 () const { 02101 return const_reverse_iterator2 (begin2 ()); 02102 } 02103 02104 BOOST_UBLAS_INLINE 02105 reverse_iterator2 rbegin2 () { 02106 return reverse_iterator2 (end2 ()); 02107 } 02108 BOOST_UBLAS_INLINE 02109 reverse_iterator2 rend2 () { 02110 return reverse_iterator2 (begin2 ()); 02111 } 02112 02113 private: 02114 matrix_closure_type data_; 02115 }; 02116 02117 // Specialization for temporary_traits 02118 template <class M, class TRI> 02119 struct vector_temporary_traits< symmetric_adaptor<M, TRI> > 02120 : vector_temporary_traits< M > {} ; 02121 template <class M, class TRI> 02122 struct vector_temporary_traits< const symmetric_adaptor<M, TRI> > 02123 : vector_temporary_traits< M > {} ; 02124 02125 template <class M, class TRI> 02126 struct matrix_temporary_traits< symmetric_adaptor<M, TRI> > 02127 : matrix_temporary_traits< M > {} ; 02128 template <class M, class TRI> 02129 struct matrix_temporary_traits< const symmetric_adaptor<M, TRI> > 02130 : matrix_temporary_traits< M > {} ; 02131 02132 }}} 02133 02134 #endif