00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
00021
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
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;
00065 typedef packed_tag storage_category;
00066 typedef typename L::orientation_category orientation_category;
00067
00068
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
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
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
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
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
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();
00176 }
00177
00178
00179 BOOST_UBLAS_INLINE
00180 void clear () {
00181
00182 std::fill (data ().begin (), data ().end (), value_type());
00183 }
00184
00185
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
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
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
00277 BOOST_UBLAS_INLINE
00278 const_iterator1 find1 (int , 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 , 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
00939
00940
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
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
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
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
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
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
01072 BOOST_UBLAS_INLINE
01073 bool same_closure (const symmetric_adaptor &sa) const {
01074 return (*this).data ().same_closure (sa.data ());
01075 }
01076
01077
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
01089 private:
01090
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
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
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
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
01223
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
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 {
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 {
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 {
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 {
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 ( 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 {
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 {
01357 return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
01358 }
01359 }
01360 {
01361 return it2_ - it.it2_;
01362 }
01363 }
01364
01365
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 {
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
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 {
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 {
01432 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
01433 return it2_.index1 ();
01434 }
01435 }
01436
01437
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
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 ( 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
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
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
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
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
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
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
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
01670
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
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 {
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 {
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 {
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 {
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 ( 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 {
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 {
01804 return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
01805 }
01806 }
01807 {
01808 return it2_ - it.it2_;
01809 }
01810 }
01811
01812
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 {
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
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 {
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 {
01879 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
01880 return it2_.index2 ();
01881 }
01882 }
01883
01884
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
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 ( 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
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
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
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
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
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
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
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
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