Update contrib.
2 // Copyright (c) 2000-2002
3 // Joerg Walter, Mathias Koch
5 // Permission to use, copy, modify, distribute and sell this software
6 // and its documentation for any purpose is hereby granted without fee,
7 // provided that the above copyright notice appear in all copies and
8 // that both that copyright notice and this permission notice appear
9 // in supporting documentation. The authors make no representations
10 // about the suitability of this software for any purpose.
11 // It is provided "as is" without express or implied warranty.
13 // The authors gratefully acknowledge the support of
14 // GeNeSys mbH & Co. KG in producing this work.
17 #ifndef _BOOST_UBLAS_SYMMETRIC_
18 #define _BOOST_UBLAS_SYMMETRIC_
20 #include <boost/numeric/ublas/matrix.hpp>
21 #include <boost/numeric/ublas/detail/temporary.hpp>
23 // Iterators based on ideas of Jeremy Siek
24 // Symmetric matrices are square. Thanks to Peter Schmitteckert for spotting this.
26 namespace boost { namespace numeric { namespace ublas {
29 bool is_symmetric (const M &m) {
30 typedef typename M::size_type size_type;
32 if (m.size1 () != m.size2 ())
34 size_type size = BOOST_UBLAS_SAME (m.size1 (), m.size2 ());
35 for (size_type i = 0; i < size; ++ i) {
36 for (size_type j = i; j < size; ++ j) {
37 if (m (i, j) != m (j, i))
44 // Array based symmetric matrix class
45 template<class T, class TRI, class L, class A>
46 class symmetric_matrix:
47 public matrix_container<symmetric_matrix<T, TRI, L, A> > {
50 typedef TRI triangular_type;
51 typedef L layout_type;
52 typedef symmetric_matrix<T, TRI, L, A> self_type;
54 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
55 using matrix_container<self_type>::operator ();
57 typedef typename A::size_type size_type;
58 typedef typename A::difference_type difference_type;
60 typedef const T &const_reference;
64 typedef const matrix_reference<const self_type> const_closure_type;
65 typedef matrix_reference<self_type> closure_type;
66 typedef vector<T, A> vector_temporary_type;
67 typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix
68 typedef packed_tag storage_category;
69 typedef typename L::orientation_category orientation_category;
71 // Construction and destruction
74 matrix_container<self_type> (),
75 size_ (0), data_ (0) {}
77 symmetric_matrix (size_type size):
78 matrix_container<self_type> (),
79 size_ (BOOST_UBLAS_SAME (size, size)), data_ (triangular_type::packed_size (layout_type (), size, size)) {
82 symmetric_matrix (size_type size1, size_type size2):
83 matrix_container<self_type> (),
84 size_ (BOOST_UBLAS_SAME (size1, size2)), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
87 symmetric_matrix (size_type size, const array_type &data):
88 matrix_container<self_type> (),
89 size_ (size), data_ (data) {}
91 symmetric_matrix (const symmetric_matrix &m):
92 matrix_container<self_type> (),
93 size_ (m.size_), data_ (m.data_) {}
96 symmetric_matrix (const matrix_expression<AE> &ae):
97 matrix_container<self_type> (),
98 size_ (BOOST_UBLAS_SAME (ae ().size1 (), ae ().size2 ())),
99 data_ (triangular_type::packed_size (layout_type (), size_, size_)) {
100 matrix_assign<scalar_assign> (*this, ae);
105 size_type size1 () const {
109 size_type size2 () const {
115 const array_type &data () const {
119 array_type &data () {
125 void resize (size_type size, bool preserve = true) {
127 self_type temporary (size, size);
128 detail::matrix_resize_preserve<layout_type> (*this, temporary);
131 data ().resize (triangular_type::packed_size (layout_type (), size, size));
136 void resize (size_type size1, size_type size2, bool preserve = true) {
137 resize (BOOST_UBLAS_SAME (size1, size2), preserve);
140 void resize_packed_preserve (size_type size) {
141 size_ = BOOST_UBLAS_SAME (size, size);
142 data ().resize (triangular_type::packed_size (layout_type (), size_, size_), value_type ());
147 const_reference operator () (size_type i, size_type j) const {
148 BOOST_UBLAS_CHECK (i < size_, bad_index ());
149 BOOST_UBLAS_CHECK (j < size_, bad_index ());
150 if (triangular_type::other (i, j))
151 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
153 return data () [triangular_type::element (layout_type (), j, size_, i, size_)];
156 reference at_element (size_type i, size_type j) {
157 BOOST_UBLAS_CHECK (i < size_, bad_index ());
158 BOOST_UBLAS_CHECK (j < size_, bad_index ());
159 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
162 reference operator () (size_type i, size_type j) {
163 BOOST_UBLAS_CHECK (i < size_, bad_index ());
164 BOOST_UBLAS_CHECK (j < size_, bad_index ());
165 if (triangular_type::other (i, j))
166 return data () [triangular_type::element (layout_type (), i, size_, j, size_)];
168 return data () [triangular_type::element (layout_type (), j, size_, i, size_)];
171 // Element assignment
173 reference insert_element (size_type i, size_type j, const_reference t) {
174 return (operator () (i, j) = t);
177 void erase_element (size_type i, size_type j) {
178 operator () (i, j) = value_type/*zero*/();
185 std::fill (data ().begin (), data ().end (), value_type/*zero*/());
190 symmetric_matrix &operator = (const symmetric_matrix &m) {
196 symmetric_matrix &assign_temporary (symmetric_matrix &m) {
202 symmetric_matrix &operator = (const matrix_expression<AE> &ae) {
203 self_type temporary (ae);
204 return assign_temporary (temporary);
208 symmetric_matrix &assign (const matrix_expression<AE> &ae) {
209 matrix_assign<scalar_assign> (*this, ae);
214 symmetric_matrix& operator += (const matrix_expression<AE> &ae) {
215 self_type temporary (*this + ae);
216 return assign_temporary (temporary);
220 symmetric_matrix &plus_assign (const matrix_expression<AE> &ae) {
221 matrix_assign<scalar_plus_assign> (*this, ae);
226 symmetric_matrix& operator -= (const matrix_expression<AE> &ae) {
227 self_type temporary (*this - ae);
228 return assign_temporary (temporary);
232 symmetric_matrix &minus_assign (const matrix_expression<AE> &ae) {
233 matrix_assign<scalar_minus_assign> (*this, ae);
238 symmetric_matrix& operator *= (const AT &at) {
239 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
244 symmetric_matrix& operator /= (const AT &at) {
245 matrix_assign_scalar<scalar_divides_assign> (*this, at);
251 void swap (symmetric_matrix &m) {
253 std::swap (size_, m.size_);
254 data ().swap (m.data ());
258 friend void swap (symmetric_matrix &m1, symmetric_matrix &m2) {
263 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
264 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
265 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
266 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
267 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
269 class const_iterator1;
271 class const_iterator2;
274 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
275 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
276 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
277 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
281 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
282 return const_iterator1 (*this, i, j);
285 iterator1 find1 (int rank, size_type i, size_type j) {
287 i = triangular_type::mutable_restrict1 (i, j);
288 return iterator1 (*this, i, j);
291 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
292 return const_iterator2 (*this, i, j);
295 iterator2 find2 (int rank, size_type i, size_type j) {
297 j = triangular_type::mutable_restrict2 (i, j);
298 return iterator2 (*this, i, j);
301 // Iterators simply are indices.
303 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
304 class const_iterator1:
305 public container_const_reference<symmetric_matrix>,
306 public random_access_iterator_base<dense_random_access_iterator_tag,
307 const_iterator1, value_type> {
309 typedef typename symmetric_matrix::value_type value_type;
310 typedef typename symmetric_matrix::difference_type difference_type;
311 typedef typename symmetric_matrix::const_reference reference;
312 typedef const typename symmetric_matrix::pointer pointer;
314 typedef const_iterator2 dual_iterator_type;
315 typedef const_reverse_iterator2 dual_reverse_iterator_type;
317 // Construction and destruction
320 container_const_reference<self_type> (), it1_ (), it2_ () {}
322 const_iterator1 (const self_type &m, size_type it1, size_type it2):
323 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
325 const_iterator1 (const iterator1 &it):
326 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
330 const_iterator1 &operator ++ () {
335 const_iterator1 &operator -- () {
340 const_iterator1 &operator += (difference_type n) {
345 const_iterator1 &operator -= (difference_type n) {
350 difference_type operator - (const const_iterator1 &it) const {
351 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
352 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
353 return it1_ - it.it1_;
358 const_reference operator * () const {
359 return (*this) () (it1_, it2_);
362 const_reference operator [] (difference_type n) const {
366 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
368 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
371 const_iterator2 begin () const {
372 return (*this) ().find2 (1, it1_, 0);
375 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
378 const_iterator2 end () const {
379 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
382 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
385 const_reverse_iterator2 rbegin () const {
386 return const_reverse_iterator2 (end ());
389 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
392 const_reverse_iterator2 rend () const {
393 return const_reverse_iterator2 (begin ());
399 size_type index1 () const {
403 size_type index2 () const {
409 const_iterator1 &operator = (const const_iterator1 &it) {
410 container_const_reference<self_type>::assign (&it ());
418 bool operator == (const const_iterator1 &it) const {
419 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
420 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
421 return it1_ == it.it1_;
424 bool operator < (const const_iterator1 &it) const {
425 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
426 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
427 return it1_ < it.it1_;
437 const_iterator1 begin1 () const {
438 return find1 (0, 0, 0);
441 const_iterator1 end1 () const {
442 return find1 (0, size_, 0);
445 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
447 public container_reference<symmetric_matrix>,
448 public random_access_iterator_base<packed_random_access_iterator_tag,
449 iterator1, value_type> {
451 typedef typename symmetric_matrix::value_type value_type;
452 typedef typename symmetric_matrix::difference_type difference_type;
453 typedef typename symmetric_matrix::reference reference;
454 typedef typename symmetric_matrix::pointer pointer;
455 typedef iterator2 dual_iterator_type;
456 typedef reverse_iterator2 dual_reverse_iterator_type;
458 // Construction and destruction
461 container_reference<self_type> (), it1_ (), it2_ () {}
463 iterator1 (self_type &m, size_type it1, size_type it2):
464 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
468 iterator1 &operator ++ () {
473 iterator1 &operator -- () {
478 iterator1 &operator += (difference_type n) {
483 iterator1 &operator -= (difference_type n) {
488 difference_type operator - (const iterator1 &it) const {
489 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
490 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
491 return it1_ - it.it1_;
496 reference operator * () const {
497 return (*this) () (it1_, it2_);
500 reference operator [] (difference_type n) const {
504 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
506 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
509 iterator2 begin () const {
510 return (*this) ().find2 (1, it1_, 0);
513 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
516 iterator2 end () const {
517 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
520 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
523 reverse_iterator2 rbegin () const {
524 return reverse_iterator2 (end ());
527 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
530 reverse_iterator2 rend () const {
531 return reverse_iterator2 (begin ());
537 size_type index1 () const {
541 size_type index2 () const {
547 iterator1 &operator = (const iterator1 &it) {
548 container_reference<self_type>::assign (&it ());
556 bool operator == (const iterator1 &it) const {
557 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
558 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
559 return it1_ == it.it1_;
562 bool operator < (const iterator1 &it) const {
563 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
564 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
565 return it1_ < it.it1_;
572 friend class const_iterator1;
577 iterator1 begin1 () {
578 return find1 (0, 0, 0);
582 return find1 (0, size_, 0);
585 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
586 class const_iterator2:
587 public container_const_reference<symmetric_matrix>,
588 public random_access_iterator_base<dense_random_access_iterator_tag,
589 const_iterator2, value_type> {
591 typedef typename symmetric_matrix::value_type value_type;
592 typedef typename symmetric_matrix::difference_type difference_type;
593 typedef typename symmetric_matrix::const_reference reference;
594 typedef const typename symmetric_matrix::pointer pointer;
596 typedef const_iterator1 dual_iterator_type;
597 typedef const_reverse_iterator1 dual_reverse_iterator_type;
599 // Construction and destruction
602 container_const_reference<self_type> (), it1_ (), it2_ () {}
604 const_iterator2 (const self_type &m, size_type it1, size_type it2):
605 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
607 const_iterator2 (const iterator2 &it):
608 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
612 const_iterator2 &operator ++ () {
617 const_iterator2 &operator -- () {
622 const_iterator2 &operator += (difference_type n) {
627 const_iterator2 &operator -= (difference_type n) {
632 difference_type operator - (const const_iterator2 &it) const {
633 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
634 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
635 return it2_ - it.it2_;
640 const_reference operator * () const {
641 return (*this) () (it1_, it2_);
644 const_reference operator [] (difference_type n) const {
648 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
650 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
653 const_iterator1 begin () const {
654 return (*this) ().find1 (1, 0, it2_);
657 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
660 const_iterator1 end () const {
661 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
664 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
667 const_reverse_iterator1 rbegin () const {
668 return const_reverse_iterator1 (end ());
671 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
674 const_reverse_iterator1 rend () const {
675 return const_reverse_iterator1 (begin ());
681 size_type index1 () const {
685 size_type index2 () const {
691 const_iterator2 &operator = (const const_iterator2 &it) {
692 container_const_reference<self_type>::assign (&it ());
700 bool operator == (const const_iterator2 &it) const {
701 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
702 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
703 return it2_ == it.it2_;
706 bool operator < (const const_iterator2 &it) const {
707 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
708 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
709 return it2_ < it.it2_;
719 const_iterator2 begin2 () const {
720 return find2 (0, 0, 0);
723 const_iterator2 end2 () const {
724 return find2 (0, 0, size_);
727 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
729 public container_reference<symmetric_matrix>,
730 public random_access_iterator_base<packed_random_access_iterator_tag,
731 iterator2, value_type> {
733 typedef typename symmetric_matrix::value_type value_type;
734 typedef typename symmetric_matrix::difference_type difference_type;
735 typedef typename symmetric_matrix::reference reference;
736 typedef typename symmetric_matrix::pointer pointer;
738 typedef iterator1 dual_iterator_type;
739 typedef reverse_iterator1 dual_reverse_iterator_type;
741 // Construction and destruction
744 container_reference<self_type> (), it1_ (), it2_ () {}
746 iterator2 (self_type &m, size_type it1, size_type it2):
747 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
751 iterator2 &operator ++ () {
756 iterator2 &operator -- () {
761 iterator2 &operator += (difference_type n) {
766 iterator2 &operator -= (difference_type n) {
771 difference_type operator - (const iterator2 &it) const {
772 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
773 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
774 return it2_ - it.it2_;
779 reference operator * () const {
780 return (*this) () (it1_, it2_);
783 reference operator [] (difference_type n) const {
787 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
789 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
792 iterator1 begin () const {
793 return (*this) ().find1 (1, 0, it2_);
796 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
799 iterator1 end () const {
800 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
803 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
806 reverse_iterator1 rbegin () const {
807 return reverse_iterator1 (end ());
810 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
813 reverse_iterator1 rend () const {
814 return reverse_iterator1 (begin ());
820 size_type index1 () const {
824 size_type index2 () const {
830 iterator2 &operator = (const iterator2 &it) {
831 container_reference<self_type>::assign (&it ());
839 bool operator == (const iterator2 &it) const {
840 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
841 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
842 return it2_ == it.it2_;
845 bool operator < (const iterator2 &it) const {
846 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
847 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
848 return it2_ < it.it2_;
855 friend class const_iterator2;
860 iterator2 begin2 () {
861 return find2 (0, 0, 0);
865 return find2 (0, 0, size_);
871 const_reverse_iterator1 rbegin1 () const {
872 return const_reverse_iterator1 (end1 ());
875 const_reverse_iterator1 rend1 () const {
876 return const_reverse_iterator1 (begin1 ());
880 reverse_iterator1 rbegin1 () {
881 return reverse_iterator1 (end1 ());
884 reverse_iterator1 rend1 () {
885 return reverse_iterator1 (begin1 ());
889 const_reverse_iterator2 rbegin2 () const {
890 return const_reverse_iterator2 (end2 ());
893 const_reverse_iterator2 rend2 () const {
894 return const_reverse_iterator2 (begin2 ());
898 reverse_iterator2 rbegin2 () {
899 return reverse_iterator2 (end2 ());
902 reverse_iterator2 rend2 () {
903 return reverse_iterator2 (begin2 ());
912 // Symmetric matrix adaptor class
913 template<class M, class TRI>
914 class symmetric_adaptor:
915 public matrix_expression<symmetric_adaptor<M, TRI> > {
917 typedef symmetric_adaptor<M, TRI> self_type;
919 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
920 using matrix_expression<self_type>::operator ();
922 typedef const M const_matrix_type;
923 typedef M matrix_type;
924 typedef TRI triangular_type;
925 typedef typename M::size_type size_type;
926 typedef typename M::difference_type difference_type;
927 typedef typename M::value_type value_type;
928 typedef typename M::const_reference const_reference;
929 typedef typename boost::mpl::if_<boost::is_const<M>,
930 typename M::const_reference,
931 typename M::reference>::type reference;
932 typedef typename boost::mpl::if_<boost::is_const<M>,
933 typename M::const_closure_type,
934 typename M::closure_type>::type matrix_closure_type;
935 typedef const self_type const_closure_type;
936 typedef self_type closure_type;
937 // Replaced by _temporary_traits to avoid type requirements on M
938 //typedef typename M::vector_temporary_type vector_temporary_type;
939 //typedef typename M::matrix_temporary_type matrix_temporary_type;
940 typedef typename storage_restrict_traits<typename M::storage_category,
941 packed_proxy_tag>::storage_category storage_category;
942 typedef typename M::orientation_category orientation_category;
944 // Construction and destruction
946 symmetric_adaptor (matrix_type &data):
947 matrix_expression<self_type> (),
949 BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
952 symmetric_adaptor (const symmetric_adaptor &m):
953 matrix_expression<self_type> (),
955 BOOST_UBLAS_CHECK (data_.size1 () == data_.size2 (), bad_size ());
960 size_type size1 () const {
961 return data_.size1 ();
964 size_type size2 () const {
965 return data_.size2 ();
970 const matrix_closure_type &data () const {
974 matrix_closure_type &data () {
979 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
981 const_reference operator () (size_type i, size_type j) const {
982 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
983 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
984 if (triangular_type::other (i, j))
985 return data () (i, j);
987 return data () (j, i);
990 reference operator () (size_type i, size_type j) {
991 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
992 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
993 if (triangular_type::other (i, j))
994 return data () (i, j);
996 return data () (j, i);
1000 reference operator () (size_type i, size_type j) const {
1001 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1002 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1003 if (triangular_type::other (i, j))
1004 return data () (i, j);
1006 return data () (j, i);
1012 symmetric_adaptor &operator = (const symmetric_adaptor &m) {
1013 matrix_assign<scalar_assign, triangular_type> (*this, m);
1017 symmetric_adaptor &assign_temporary (symmetric_adaptor &m) {
1023 symmetric_adaptor &operator = (const matrix_expression<AE> &ae) {
1024 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (ae));
1029 symmetric_adaptor &assign (const matrix_expression<AE> &ae) {
1030 matrix_assign<scalar_assign, triangular_type> (*this, ae);
1035 symmetric_adaptor& operator += (const matrix_expression<AE> &ae) {
1036 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this + ae));
1041 symmetric_adaptor &plus_assign (const matrix_expression<AE> &ae) {
1042 matrix_assign<scalar_plus_assign, triangular_type> (*this, ae);
1047 symmetric_adaptor& operator -= (const matrix_expression<AE> &ae) {
1048 matrix_assign<scalar_assign, triangular_type> (*this, matrix<value_type> (*this - ae));
1053 symmetric_adaptor &minus_assign (const matrix_expression<AE> &ae) {
1054 matrix_assign<scalar_minus_assign, triangular_type> (*this, ae);
1059 symmetric_adaptor& operator *= (const AT &at) {
1060 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
1065 symmetric_adaptor& operator /= (const AT &at) {
1066 matrix_assign_scalar<scalar_divides_assign> (*this, at);
1070 // Closure comparison
1072 bool same_closure (const symmetric_adaptor &sa) const {
1073 return (*this).data ().same_closure (sa.data ());
1078 void swap (symmetric_adaptor &m) {
1080 matrix_swap<scalar_swap, triangular_type> (*this, m);
1083 friend void swap (symmetric_adaptor &m1, symmetric_adaptor &m2) {
1089 // Use matrix iterator
1090 typedef typename M::const_iterator1 const_subiterator1_type;
1091 typedef typename boost::mpl::if_<boost::is_const<M>,
1092 typename M::const_iterator1,
1093 typename M::iterator1>::type subiterator1_type;
1094 typedef typename M::const_iterator2 const_subiterator2_type;
1095 typedef typename boost::mpl::if_<boost::is_const<M>,
1096 typename M::const_iterator2,
1097 typename M::iterator2>::type subiterator2_type;
1100 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1101 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
1102 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
1103 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
1104 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
1106 class const_iterator1;
1108 class const_iterator2;
1111 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1112 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
1113 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1114 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
1118 const_iterator1 find1 (int rank, size_type i, size_type j) const {
1119 if (triangular_type::other (i, j)) {
1120 if (triangular_type::other (size1 (), j)) {
1121 return const_iterator1 (*this, 0, 0,
1122 data ().find1 (rank, i, j), data ().find1 (rank, size1 (), j),
1123 data ().find2 (rank, size2 (), size1 ()), data ().find2 (rank, size2 (), size1 ()));
1125 return const_iterator1 (*this, 0, 1,
1126 data ().find1 (rank, i, j), data ().find1 (rank, j, j),
1127 data ().find2 (rank, j, j), data ().find2 (rank, j, size1 ()));
1130 if (triangular_type::other (size1 (), j)) {
1131 return const_iterator1 (*this, 1, 0,
1132 data ().find1 (rank, j, j), data ().find1 (rank, size1 (), j),
1133 data ().find2 (rank, j, i), data ().find2 (rank, j, j));
1135 return const_iterator1 (*this, 1, 1,
1136 data ().find1 (rank, size1 (), size2 ()), data ().find1 (rank, size1 (), size2 ()),
1137 data ().find2 (rank, j, i), data ().find2 (rank, j, size1 ()));
1142 iterator1 find1 (int rank, size_type i, size_type j) {
1144 i = triangular_type::mutable_restrict1 (i, j);
1145 return iterator1 (*this, data ().find1 (rank, i, j));
1148 const_iterator2 find2 (int rank, size_type i, size_type j) const {
1149 if (triangular_type::other (i, j)) {
1150 if (triangular_type::other (i, size2 ())) {
1151 return const_iterator2 (*this, 1, 1,
1152 data ().find1 (rank, size2 (), size1 ()), data ().find1 (rank, size2 (), size1 ()),
1153 data ().find2 (rank, i, j), data ().find2 (rank, i, size2 ()));
1155 return const_iterator2 (*this, 1, 0,
1156 data ().find1 (rank, i, i), data ().find1 (rank, size2 (), i),
1157 data ().find2 (rank, i, j), data ().find2 (rank, i, i));
1160 if (triangular_type::other (i, size2 ())) {
1161 return const_iterator2 (*this, 0, 1,
1162 data ().find1 (rank, j, i), data ().find1 (rank, i, i),
1163 data ().find2 (rank, i, i), data ().find2 (rank, i, size2 ()));
1165 return const_iterator2 (*this, 0, 0,
1166 data ().find1 (rank, j, i), data ().find1 (rank, size2 (), i),
1167 data ().find2 (rank, size1 (), size2 ()), data ().find2 (rank, size2 (), size2 ()));
1172 iterator2 find2 (int rank, size_type i, size_type j) {
1174 j = triangular_type::mutable_restrict2 (i, j);
1175 return iterator2 (*this, data ().find2 (rank, i, j));
1178 // Iterators simply are indices.
1180 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1181 class const_iterator1:
1182 public container_const_reference<symmetric_adaptor>,
1183 public random_access_iterator_base<typename iterator_restrict_traits<
1184 typename const_subiterator1_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
1185 const_iterator1, value_type> {
1187 typedef typename const_subiterator1_type::value_type value_type;
1188 typedef typename const_subiterator1_type::difference_type difference_type;
1189 typedef typename const_subiterator1_type::reference reference;
1190 typedef typename const_subiterator1_type::pointer pointer;
1192 typedef const_iterator2 dual_iterator_type;
1193 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1195 // Construction and destruction
1198 container_const_reference<self_type> (),
1199 begin_ (-1), end_ (-1), current_ (-1),
1200 it1_begin_ (), it1_end_ (), it1_ (),
1201 it2_begin_ (), it2_end_ (), it2_ () {}
1203 const_iterator1 (const self_type &m, int begin, int end,
1204 const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
1205 const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
1206 container_const_reference<self_type> (m),
1207 begin_ (begin), end_ (end), current_ (begin),
1208 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
1209 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
1210 if (current_ == 0 && it1_ == it1_end_)
1212 if (current_ == 1 && it2_ == it2_end_)
1214 if ((current_ == 0 && it1_ == it1_end_) ||
1215 (current_ == 1 && it2_ == it2_end_))
1217 BOOST_UBLAS_CHECK (current_ == end_ ||
1218 (current_ == 0 && it1_ != it1_end_) ||
1219 (current_ == 1 && it2_ != it2_end_), internal_logic ());
1221 // FIXME cannot compile
1222 // iterator1 does not have these members!
1224 const_iterator1 (const iterator1 &it):
1225 container_const_reference<self_type> (it ()),
1226 begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
1227 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
1228 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
1229 BOOST_UBLAS_CHECK (current_ == end_ ||
1230 (current_ == 0 && it1_ != it1_end_) ||
1231 (current_ == 1 && it2_ != it2_end_), internal_logic ());
1236 const_iterator1 &operator ++ () {
1237 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1238 if (current_ == 0) {
1239 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1241 if (it1_ == it1_end_ && end_ == 1) {
1245 } else /* if (current_ == 1) */ {
1246 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1248 if (it2_ == it2_end_ && end_ == 0) {
1256 const_iterator1 &operator -- () {
1257 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1258 if (current_ == 0) {
1259 if (it1_ == it1_begin_ && begin_ == 1) {
1261 BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
1267 } else /* if (current_ == 1) */ {
1268 if (it2_ == it2_begin_ && begin_ == 0) {
1270 BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
1280 const_iterator1 &operator += (difference_type n) {
1281 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1282 if (current_ == 0) {
1283 size_type d = (std::min) (n, it1_end_ - it1_);
1286 if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
1287 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1288 d = (std::min) (n, it2_end_ - it2_begin_);
1289 it2_ = it2_begin_ + d;
1293 } else /* if (current_ == 1) */ {
1294 size_type d = (std::min) (n, it2_end_ - it2_);
1297 if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
1298 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1299 d = (std::min) (n, it1_end_ - it1_begin_);
1300 it1_ = it1_begin_ + d;
1305 BOOST_UBLAS_CHECK (n == 0, external_logic ());
1309 const_iterator1 &operator -= (difference_type n) {
1310 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1311 if (current_ == 0) {
1312 size_type d = (std::min) (n, it1_ - it1_begin_);
1316 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1317 d = (std::min) (n, it2_end_ - it2_begin_);
1318 it2_ = it2_end_ - d;
1322 } else /* if (current_ == 1) */ {
1323 size_type d = (std::min) (n, it2_ - it2_begin_);
1327 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1328 d = (std::min) (n, it1_end_ - it1_begin_);
1329 it1_ = it1_end_ - d;
1334 BOOST_UBLAS_CHECK (n == 0, external_logic ());
1338 difference_type operator - (const const_iterator1 &it) const {
1339 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1340 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1341 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1342 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1343 if (current_ == 0 && it.current_ == 0) {
1344 return it1_ - it.it1_;
1345 } else if (current_ == 0 && it.current_ == 1) {
1346 if (end_ == 1 && it.end_ == 1) {
1347 return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
1348 } else /* if (end_ == 0 && it.end_ == 0) */ {
1349 return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
1352 } else if (current_ == 1 && it.current_ == 0) {
1353 if (end_ == 1 && it.end_ == 1) {
1354 return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
1355 } else /* if (end_ == 0 && it.end_ == 0) */ {
1356 return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
1359 /* current_ == 1 && it.current_ == 1 */ {
1360 return it2_ - it.it2_;
1366 const_reference operator * () const {
1367 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1368 if (current_ == 0) {
1369 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1371 } else /* if (current_ == 1) */ {
1372 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1377 const_reference operator [] (difference_type n) const {
1378 return *(*this + n);
1381 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1383 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1384 typename self_type::
1386 const_iterator2 begin () const {
1387 return (*this) ().find2 (1, index1 (), 0);
1390 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1391 typename self_type::
1393 const_iterator2 end () const {
1394 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1397 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1398 typename self_type::
1400 const_reverse_iterator2 rbegin () const {
1401 return const_reverse_iterator2 (end ());
1404 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1405 typename self_type::
1407 const_reverse_iterator2 rend () const {
1408 return const_reverse_iterator2 (begin ());
1414 size_type index1 () const {
1415 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1416 if (current_ == 0) {
1417 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1418 return it1_.index1 ();
1419 } else /* if (current_ == 1) */ {
1420 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1421 return it2_.index2 ();
1425 size_type index2 () const {
1426 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1427 if (current_ == 0) {
1428 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1429 return it1_.index2 ();
1430 } else /* if (current_ == 1) */ {
1431 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1432 return it2_.index1 ();
1438 const_iterator1 &operator = (const const_iterator1 &it) {
1439 container_const_reference<self_type>::assign (&it ());
1442 current_ = it.current_;
1443 it1_begin_ = it.it1_begin_;
1444 it1_end_ = it.it1_end_;
1446 it2_begin_ = it.it2_begin_;
1447 it2_end_ = it.it2_end_;
1454 bool operator == (const const_iterator1 &it) const {
1455 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1456 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1457 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1458 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1459 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
1460 (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
1463 bool operator < (const const_iterator1 &it) const {
1464 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1465 return it - *this > 0;
1472 const_subiterator1_type it1_begin_;
1473 const_subiterator1_type it1_end_;
1474 const_subiterator1_type it1_;
1475 const_subiterator2_type it2_begin_;
1476 const_subiterator2_type it2_end_;
1477 const_subiterator2_type it2_;
1482 const_iterator1 begin1 () const {
1483 return find1 (0, 0, 0);
1486 const_iterator1 end1 () const {
1487 return find1 (0, size1 (), 0);
1490 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1492 public container_reference<symmetric_adaptor>,
1493 public random_access_iterator_base<typename iterator_restrict_traits<
1494 typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1495 iterator1, value_type> {
1497 typedef typename subiterator1_type::value_type value_type;
1498 typedef typename subiterator1_type::difference_type difference_type;
1499 typedef typename subiterator1_type::reference reference;
1500 typedef typename subiterator1_type::pointer pointer;
1502 typedef iterator2 dual_iterator_type;
1503 typedef reverse_iterator2 dual_reverse_iterator_type;
1505 // Construction and destruction
1508 container_reference<self_type> (), it1_ () {}
1510 iterator1 (self_type &m, const subiterator1_type &it1):
1511 container_reference<self_type> (m), it1_ (it1) {}
1515 iterator1 &operator ++ () {
1520 iterator1 &operator -- () {
1525 iterator1 &operator += (difference_type n) {
1530 iterator1 &operator -= (difference_type n) {
1535 difference_type operator - (const iterator1 &it) const {
1536 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1537 return it1_ - it.it1_;
1542 reference operator * () const {
1546 reference operator [] (difference_type n) const {
1547 return *(*this + n);
1550 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1552 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1553 typename self_type::
1555 iterator2 begin () const {
1556 return (*this) ().find2 (1, index1 (), 0);
1559 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1560 typename self_type::
1562 iterator2 end () const {
1563 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1566 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1567 typename self_type::
1569 reverse_iterator2 rbegin () const {
1570 return reverse_iterator2 (end ());
1573 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1574 typename self_type::
1576 reverse_iterator2 rend () const {
1577 return reverse_iterator2 (begin ());
1583 size_type index1 () const {
1584 return it1_.index1 ();
1587 size_type index2 () const {
1588 return it1_.index2 ();
1593 iterator1 &operator = (const iterator1 &it) {
1594 container_reference<self_type>::assign (&it ());
1601 bool operator == (const iterator1 &it) const {
1602 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1603 return it1_ == it.it1_;
1606 bool operator < (const iterator1 &it) const {
1607 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1608 return it1_ < it.it1_;
1612 subiterator1_type it1_;
1614 friend class const_iterator1;
1619 iterator1 begin1 () {
1620 return find1 (0, 0, 0);
1624 return find1 (0, size1 (), 0);
1627 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1628 class const_iterator2:
1629 public container_const_reference<symmetric_adaptor>,
1630 public random_access_iterator_base<typename iterator_restrict_traits<
1631 typename const_subiterator2_type::iterator_category, dense_random_access_iterator_tag>::iterator_category,
1632 const_iterator2, value_type> {
1634 typedef typename const_subiterator2_type::value_type value_type;
1635 typedef typename const_subiterator2_type::difference_type difference_type;
1636 typedef typename const_subiterator2_type::reference reference;
1637 typedef typename const_subiterator2_type::pointer pointer;
1639 typedef const_iterator1 dual_iterator_type;
1640 typedef const_reverse_iterator1 dual_reverse_iterator_type;
1642 // Construction and destruction
1645 container_const_reference<self_type> (),
1646 begin_ (-1), end_ (-1), current_ (-1),
1647 it1_begin_ (), it1_end_ (), it1_ (),
1648 it2_begin_ (), it2_end_ (), it2_ () {}
1650 const_iterator2 (const self_type &m, int begin, int end,
1651 const const_subiterator1_type &it1_begin, const const_subiterator1_type &it1_end,
1652 const const_subiterator2_type &it2_begin, const const_subiterator2_type &it2_end):
1653 container_const_reference<self_type> (m),
1654 begin_ (begin), end_ (end), current_ (begin),
1655 it1_begin_ (it1_begin), it1_end_ (it1_end), it1_ (it1_begin_),
1656 it2_begin_ (it2_begin), it2_end_ (it2_end), it2_ (it2_begin_) {
1657 if (current_ == 0 && it1_ == it1_end_)
1659 if (current_ == 1 && it2_ == it2_end_)
1661 if ((current_ == 0 && it1_ == it1_end_) ||
1662 (current_ == 1 && it2_ == it2_end_))
1664 BOOST_UBLAS_CHECK (current_ == end_ ||
1665 (current_ == 0 && it1_ != it1_end_) ||
1666 (current_ == 1 && it2_ != it2_end_), internal_logic ());
1668 // FIXME cannot compiler
1669 // iterator2 does not have these members!
1671 const_iterator2 (const iterator2 &it):
1672 container_const_reference<self_type> (it ()),
1673 begin_ (it.begin_), end_ (it.end_), current_ (it.current_),
1674 it1_begin_ (it.it1_begin_), it1_end_ (it.it1_end_), it1_ (it.it1_),
1675 it2_begin_ (it.it2_begin_), it2_end_ (it.it2_end_), it2_ (it.it2_) {
1676 BOOST_UBLAS_CHECK (current_ == end_ ||
1677 (current_ == 0 && it1_ != it1_end_) ||
1678 (current_ == 1 && it2_ != it2_end_), internal_logic ());
1683 const_iterator2 &operator ++ () {
1684 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1685 if (current_ == 0) {
1686 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1688 if (it1_ == it1_end_ && end_ == 1) {
1692 } else /* if (current_ == 1) */ {
1693 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1695 if (it2_ == it2_end_ && end_ == 0) {
1703 const_iterator2 &operator -- () {
1704 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1705 if (current_ == 0) {
1706 if (it1_ == it1_begin_ && begin_ == 1) {
1708 BOOST_UBLAS_CHECK (it2_ != it2_begin_, internal_logic ());
1714 } else /* if (current_ == 1) */ {
1715 if (it2_ == it2_begin_ && begin_ == 0) {
1717 BOOST_UBLAS_CHECK (it1_ != it1_begin_, internal_logic ());
1727 const_iterator2 &operator += (difference_type n) {
1728 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1729 if (current_ == 0) {
1730 size_type d = (std::min) (n, it1_end_ - it1_);
1733 if (n > 0 || (end_ == 1 && it1_ == it1_end_)) {
1734 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1735 d = (std::min) (n, it2_end_ - it2_begin_);
1736 it2_ = it2_begin_ + d;
1740 } else /* if (current_ == 1) */ {
1741 size_type d = (std::min) (n, it2_end_ - it2_);
1744 if (n > 0 || (end_ == 0 && it2_ == it2_end_)) {
1745 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1746 d = (std::min) (n, it1_end_ - it1_begin_);
1747 it1_ = it1_begin_ + d;
1752 BOOST_UBLAS_CHECK (n == 0, external_logic ());
1756 const_iterator2 &operator -= (difference_type n) {
1757 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1758 if (current_ == 0) {
1759 size_type d = (std::min) (n, it1_ - it1_begin_);
1763 BOOST_UBLAS_CHECK (end_ == 1, external_logic ());
1764 d = (std::min) (n, it2_end_ - it2_begin_);
1765 it2_ = it2_end_ - d;
1769 } else /* if (current_ == 1) */ {
1770 size_type d = (std::min) (n, it2_ - it2_begin_);
1774 BOOST_UBLAS_CHECK (end_ == 0, external_logic ());
1775 d = (std::min) (n, it1_end_ - it1_begin_);
1776 it1_ = it1_end_ - d;
1781 BOOST_UBLAS_CHECK (n == 0, external_logic ());
1785 difference_type operator - (const const_iterator2 &it) const {
1786 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1787 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1788 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1789 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1790 if (current_ == 0 && it.current_ == 0) {
1791 return it1_ - it.it1_;
1792 } else if (current_ == 0 && it.current_ == 1) {
1793 if (end_ == 1 && it.end_ == 1) {
1794 return (it1_ - it.it1_end_) + (it.it2_begin_ - it.it2_);
1795 } else /* if (end_ == 0 && it.end_ == 0) */ {
1796 return (it1_ - it.it1_begin_) + (it.it2_end_ - it.it2_);
1799 } else if (current_ == 1 && it.current_ == 0) {
1800 if (end_ == 1 && it.end_ == 1) {
1801 return (it2_ - it.it2_begin_) + (it.it1_end_ - it.it1_);
1802 } else /* if (end_ == 0 && it.end_ == 0) */ {
1803 return (it2_ - it.it2_end_) + (it.it1_begin_ - it.it1_);
1806 /* current_ == 1 && it.current_ == 1 */ {
1807 return it2_ - it.it2_;
1813 const_reference operator * () const {
1814 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1815 if (current_ == 0) {
1816 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1818 } else /* if (current_ == 1) */ {
1819 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1824 const_reference operator [] (difference_type n) const {
1825 return *(*this + n);
1828 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1830 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1831 typename self_type::
1833 const_iterator1 begin () const {
1834 return (*this) ().find1 (1, 0, index2 ());
1837 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1838 typename self_type::
1840 const_iterator1 end () const {
1841 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1844 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1845 typename self_type::
1847 const_reverse_iterator1 rbegin () const {
1848 return const_reverse_iterator1 (end ());
1851 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1852 typename self_type::
1854 const_reverse_iterator1 rend () const {
1855 return const_reverse_iterator1 (begin ());
1861 size_type index1 () const {
1862 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1863 if (current_ == 0) {
1864 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1865 return it1_.index2 ();
1866 } else /* if (current_ == 1) */ {
1867 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1868 return it2_.index1 ();
1872 size_type index2 () const {
1873 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1874 if (current_ == 0) {
1875 BOOST_UBLAS_CHECK (it1_ != it1_end_, internal_logic ());
1876 return it1_.index1 ();
1877 } else /* if (current_ == 1) */ {
1878 BOOST_UBLAS_CHECK (it2_ != it2_end_, internal_logic ());
1879 return it2_.index2 ();
1885 const_iterator2 &operator = (const const_iterator2 &it) {
1886 container_const_reference<self_type>::assign (&it ());
1889 current_ = it.current_;
1890 it1_begin_ = it.it1_begin_;
1891 it1_end_ = it.it1_end_;
1893 it2_begin_ = it.it2_begin_;
1894 it2_end_ = it.it2_end_;
1901 bool operator == (const const_iterator2 &it) const {
1902 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1903 BOOST_UBLAS_CHECK (current_ == 0 || current_ == 1, internal_logic ());
1904 BOOST_UBLAS_CHECK (it.current_ == 0 || it.current_ == 1, internal_logic ());
1905 BOOST_UBLAS_CHECK (/* begin_ == it.begin_ && */ end_ == it.end_, internal_logic ());
1906 return (current_ == 0 && it.current_ == 0 && it1_ == it.it1_) ||
1907 (current_ == 1 && it.current_ == 1 && it2_ == it.it2_);
1910 bool operator < (const const_iterator2 &it) const {
1911 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1912 return it - *this > 0;
1919 const_subiterator1_type it1_begin_;
1920 const_subiterator1_type it1_end_;
1921 const_subiterator1_type it1_;
1922 const_subiterator2_type it2_begin_;
1923 const_subiterator2_type it2_end_;
1924 const_subiterator2_type it2_;
1929 const_iterator2 begin2 () const {
1930 return find2 (0, 0, 0);
1933 const_iterator2 end2 () const {
1934 return find2 (0, 0, size2 ());
1937 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1939 public container_reference<symmetric_adaptor>,
1940 public random_access_iterator_base<typename iterator_restrict_traits<
1941 typename subiterator2_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1942 iterator2, value_type> {
1944 typedef typename subiterator2_type::value_type value_type;
1945 typedef typename subiterator2_type::difference_type difference_type;
1946 typedef typename subiterator2_type::reference reference;
1947 typedef typename subiterator2_type::pointer pointer;
1949 typedef iterator1 dual_iterator_type;
1950 typedef reverse_iterator1 dual_reverse_iterator_type;
1952 // Construction and destruction
1955 container_reference<self_type> (), it2_ () {}
1957 iterator2 (self_type &m, const subiterator2_type &it2):
1958 container_reference<self_type> (m), it2_ (it2) {}
1962 iterator2 &operator ++ () {
1967 iterator2 &operator -- () {
1972 iterator2 &operator += (difference_type n) {
1977 iterator2 &operator -= (difference_type n) {
1982 difference_type operator - (const iterator2 &it) const {
1983 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1984 return it2_ - it.it2_;
1989 reference operator * () const {
1993 reference operator [] (difference_type n) const {
1994 return *(*this + n);
1997 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1999 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2000 typename self_type::
2002 iterator1 begin () const {
2003 return (*this) ().find1 (1, 0, index2 ());
2006 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2007 typename self_type::
2009 iterator1 end () const {
2010 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
2013 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2014 typename self_type::
2016 reverse_iterator1 rbegin () const {
2017 return reverse_iterator1 (end ());
2020 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2021 typename self_type::
2023 reverse_iterator1 rend () const {
2024 return reverse_iterator1 (begin ());
2030 size_type index1 () const {
2031 return it2_.index1 ();
2034 size_type index2 () const {
2035 return it2_.index2 ();
2040 iterator2 &operator = (const iterator2 &it) {
2041 container_reference<self_type>::assign (&it ());
2048 bool operator == (const iterator2 &it) const {
2049 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2050 return it2_ == it.it2_;
2053 bool operator < (const iterator2 &it) const {
2054 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2055 return it2_ < it.it2_;
2059 subiterator2_type it2_;
2061 friend class const_iterator2;
2066 iterator2 begin2 () {
2067 return find2 (0, 0, 0);
2071 return find2 (0, 0, size2 ());
2074 // Reverse iterators
2077 const_reverse_iterator1 rbegin1 () const {
2078 return const_reverse_iterator1 (end1 ());
2081 const_reverse_iterator1 rend1 () const {
2082 return const_reverse_iterator1 (begin1 ());
2086 reverse_iterator1 rbegin1 () {
2087 return reverse_iterator1 (end1 ());
2090 reverse_iterator1 rend1 () {
2091 return reverse_iterator1 (begin1 ());
2095 const_reverse_iterator2 rbegin2 () const {
2096 return const_reverse_iterator2 (end2 ());
2099 const_reverse_iterator2 rend2 () const {
2100 return const_reverse_iterator2 (begin2 ());
2104 reverse_iterator2 rbegin2 () {
2105 return reverse_iterator2 (end2 ());
2108 reverse_iterator2 rend2 () {
2109 return reverse_iterator2 (begin2 ());
2113 matrix_closure_type data_;
2116 // Specialization for temporary_traits
2117 template <class M, class TRI>
2118 struct vector_temporary_traits< symmetric_adaptor<M, TRI> >
2119 : vector_temporary_traits< M > {} ;
2120 template <class M, class TRI>
2121 struct vector_temporary_traits< const symmetric_adaptor<M, TRI> >
2122 : vector_temporary_traits< M > {} ;
2124 template <class M, class TRI>
2125 struct matrix_temporary_traits< symmetric_adaptor<M, TRI> >
2126 : matrix_temporary_traits< M > {} ;
2127 template <class M, class TRI>
2128 struct matrix_temporary_traits< const symmetric_adaptor<M, TRI> >
2129 : matrix_temporary_traits< M > {} ;