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