2 // Copyright (c) 2000-2002
3 // Joerg Walter, Mathias Koch
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 // The authors gratefully acknowledge the support of
10 // GeNeSys mbH & Co. KG in producing this work.
13 #ifndef _BOOST_UBLAS_MATRIX_PROXY_
14 #define _BOOST_UBLAS_MATRIX_PROXY_
16 #include <boost/numeric/ublas/matrix_expression.hpp>
17 #include <boost/numeric/ublas/detail/vector_assign.hpp>
18 #include <boost/numeric/ublas/detail/matrix_assign.hpp>
19 #include <boost/numeric/ublas/detail/temporary.hpp>
21 // Iterators based on ideas of Jeremy Siek
23 namespace boost { namespace numeric { namespace ublas {
29 public vector_expression<matrix_row<M> > {
31 typedef matrix_row<M> self_type;
33 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
34 using vector_expression<self_type>::operator ();
36 typedef M matrix_type;
37 typedef typename M::size_type size_type;
38 typedef typename M::difference_type difference_type;
39 typedef typename M::value_type value_type;
40 typedef typename M::const_reference const_reference;
41 typedef typename boost::mpl::if_<boost::is_const<M>,
42 typename M::const_reference,
43 typename M::reference>::type reference;
44 typedef typename boost::mpl::if_<boost::is_const<M>,
45 typename M::const_closure_type,
46 typename M::closure_type>::type matrix_closure_type;
47 typedef const self_type const_closure_type;
48 typedef self_type closure_type;
49 typedef typename storage_restrict_traits<typename M::storage_category,
50 dense_proxy_tag>::storage_category storage_category;
52 // Construction and destruction
54 matrix_row (matrix_type &data, size_type i):
55 data_ (data), i_ (i) {
56 // Early checking of preconditions here.
57 // BOOST_UBLAS_CHECK (i_ < data_.size1 (), bad_index ());
62 size_type size () const {
63 return data_.size2 ();
66 size_type index () const {
72 const matrix_closure_type &data () const {
76 matrix_closure_type &data () {
81 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
83 const_reference operator () (size_type j) const {
87 reference operator () (size_type j) {
92 const_reference operator [] (size_type j) const {
96 reference operator [] (size_type j) {
101 reference operator () (size_type j) const {
102 return data_ (i_, j);
106 reference operator [] (size_type j) const {
113 matrix_row &operator = (const matrix_row &mr) {
114 // ISSUE need a temporary, proxy can be overlaping alias
115 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mr));
119 matrix_row &assign_temporary (matrix_row &mr) {
120 // assign elements, proxied container remains the same
121 vector_assign<scalar_assign> (*this, mr);
126 matrix_row &operator = (const vector_expression<AE> &ae) {
127 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
132 matrix_row &assign (const vector_expression<AE> &ae) {
133 vector_assign<scalar_assign> (*this, ae);
138 matrix_row &operator += (const vector_expression<AE> &ae) {
139 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
144 matrix_row &plus_assign (const vector_expression<AE> &ae) {
145 vector_assign<scalar_plus_assign> (*this, ae);
150 matrix_row &operator -= (const vector_expression<AE> &ae) {
151 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
156 matrix_row &minus_assign (const vector_expression<AE> &ae) {
157 vector_assign<scalar_minus_assign> (*this, ae);
162 matrix_row &operator *= (const AT &at) {
163 vector_assign_scalar<scalar_multiplies_assign> (*this, at);
168 matrix_row &operator /= (const AT &at) {
169 vector_assign_scalar<scalar_divides_assign> (*this, at);
173 // Closure comparison
175 bool same_closure (const matrix_row &mr) const {
176 return (*this).data_.same_closure (mr.data_);
181 bool operator == (const matrix_row &mr) const {
182 return (*this).data_ == mr.data_ && index () == mr.index ();
187 void swap (matrix_row mr) {
189 BOOST_UBLAS_CHECK (size () == mr.size (), bad_size ());
190 // Sparse ranges may be nonconformant now.
191 // std::swap_ranges (begin (), end (), mr.begin ());
192 vector_swap<scalar_swap> (*this, mr);
196 friend void swap (matrix_row mr1, matrix_row mr2) {
202 typedef typename M::const_iterator2 const_subiterator_type;
203 typedef typename boost::mpl::if_<boost::is_const<M>,
204 typename M::const_iterator2,
205 typename M::iterator2>::type subiterator_type;
208 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
209 typedef indexed_iterator<matrix_row<matrix_type>,
210 typename subiterator_type::iterator_category> iterator;
211 typedef indexed_const_iterator<matrix_row<matrix_type>,
212 typename const_subiterator_type::iterator_category> const_iterator;
214 class const_iterator;
220 const_iterator find (size_type j) const {
221 const_subiterator_type it2 (data_.find2 (1, i_, j));
222 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
223 return const_iterator (*this, it2.index2 ());
225 return const_iterator (*this, it2);
229 iterator find (size_type j) {
230 subiterator_type it2 (data_.find2 (1, i_, j));
231 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
232 return iterator (*this, it2.index2 ());
234 return iterator (*this, it2);
238 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
239 class const_iterator:
240 public container_const_reference<matrix_row>,
241 public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
242 iterator_base<const_iterator, value_type>::type {
244 typedef typename const_subiterator_type::value_type value_type;
245 typedef typename const_subiterator_type::difference_type difference_type;
246 typedef typename const_subiterator_type::reference reference;
247 typedef typename const_subiterator_type::pointer pointer;
249 // Construction and destruction
252 container_const_reference<self_type> (), it_ () {}
254 const_iterator (const self_type &mr, const const_subiterator_type &it):
255 container_const_reference<self_type> (mr), it_ (it) {}
257 const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
258 container_const_reference<self_type> (it ()), it_ (it.it_) {}
262 const_iterator &operator ++ () {
267 const_iterator &operator -- () {
272 const_iterator &operator += (difference_type n) {
277 const_iterator &operator -= (difference_type n) {
282 difference_type operator - (const const_iterator &it) const {
283 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
289 const_reference operator * () const {
290 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
294 const_reference operator [] (difference_type n) const {
300 size_type index () const {
301 return it_.index2 ();
306 const_iterator &operator = (const const_iterator &it) {
307 container_const_reference<self_type>::assign (&it ());
314 bool operator == (const const_iterator &it) const {
315 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
316 return it_ == it.it_;
319 bool operator < (const const_iterator &it) const {
320 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
325 const_subiterator_type it_;
330 const_iterator begin () const {
334 const_iterator cbegin () const {
338 const_iterator end () const {
339 return find (size ());
342 const_iterator cend () const {
346 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
348 public container_reference<matrix_row>,
349 public iterator_base_traits<typename subiterator_type::iterator_category>::template
350 iterator_base<iterator, value_type>::type {
352 typedef typename subiterator_type::value_type value_type;
353 typedef typename subiterator_type::difference_type difference_type;
354 typedef typename subiterator_type::reference reference;
355 typedef typename subiterator_type::pointer pointer;
357 // Construction and destruction
360 container_reference<self_type> (), it_ () {}
362 iterator (self_type &mr, const subiterator_type &it):
363 container_reference<self_type> (mr), it_ (it) {}
367 iterator &operator ++ () {
372 iterator &operator -- () {
377 iterator &operator += (difference_type n) {
382 iterator &operator -= (difference_type n) {
387 difference_type operator - (const iterator &it) const {
388 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
394 reference operator * () const {
395 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
399 reference operator [] (difference_type n) const {
405 size_type index () const {
406 return it_.index2 ();
411 iterator &operator = (const iterator &it) {
412 container_reference<self_type>::assign (&it ());
419 bool operator == (const iterator &it) const {
420 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
421 return it_ == it.it_;
424 bool operator < (const iterator &it) const {
425 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
430 subiterator_type it_;
432 friend class const_iterator;
442 return find (size ());
446 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
447 typedef reverse_iterator_base<iterator> reverse_iterator;
450 const_reverse_iterator rbegin () const {
451 return const_reverse_iterator (end ());
454 const_reverse_iterator crbegin () const {
458 const_reverse_iterator rend () const {
459 return const_reverse_iterator (begin ());
462 const_reverse_iterator crend () const {
466 reverse_iterator rbegin () {
467 return reverse_iterator (end ());
470 reverse_iterator rend () {
471 return reverse_iterator (begin ());
475 matrix_closure_type data_;
482 matrix_row<M> row (M &data, typename M::size_type i) {
483 return matrix_row<M> (data, i);
487 const matrix_row<const M> row (const M &data, typename M::size_type i) {
488 return matrix_row<const M> (data, i);
491 // Specialize temporary
493 struct vector_temporary_traits< matrix_row<M> >
494 : vector_temporary_traits< M > {} ;
496 struct vector_temporary_traits< const matrix_row<M> >
497 : vector_temporary_traits< M > {} ;
499 // Matrix based column vector class
502 public vector_expression<matrix_column<M> > {
504 typedef matrix_column<M> self_type;
506 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
507 using vector_expression<self_type>::operator ();
509 typedef M matrix_type;
510 typedef typename M::size_type size_type;
511 typedef typename M::difference_type difference_type;
512 typedef typename M::value_type value_type;
513 typedef typename M::const_reference const_reference;
514 typedef typename boost::mpl::if_<boost::is_const<M>,
515 typename M::const_reference,
516 typename M::reference>::type reference;
517 typedef typename boost::mpl::if_<boost::is_const<M>,
518 typename M::const_closure_type,
519 typename M::closure_type>::type matrix_closure_type;
520 typedef const self_type const_closure_type;
521 typedef self_type closure_type;
522 typedef typename storage_restrict_traits<typename M::storage_category,
523 dense_proxy_tag>::storage_category storage_category;
525 // Construction and destruction
527 matrix_column (matrix_type &data, size_type j):
528 data_ (data), j_ (j) {
529 // Early checking of preconditions here.
530 // BOOST_UBLAS_CHECK (j_ < data_.size2 (), bad_index ());
535 size_type size () const {
536 return data_.size1 ();
539 size_type index () const {
545 const matrix_closure_type &data () const {
549 matrix_closure_type &data () {
554 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
556 const_reference operator () (size_type i) const {
557 return data_ (i, j_);
560 reference operator () (size_type i) {
561 return data_ (i, j_);
565 const_reference operator [] (size_type i) const {
569 reference operator [] (size_type i) {
574 reference operator () (size_type i) const {
575 return data_ (i, j_);
579 reference operator [] (size_type i) const {
586 matrix_column &operator = (const matrix_column &mc) {
587 // ISSUE need a temporary, proxy can be overlaping alias
588 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mc));
592 matrix_column &assign_temporary (matrix_column &mc) {
593 // assign elements, proxied container remains the same
594 vector_assign<scalar_assign> (*this, mc);
599 matrix_column &operator = (const vector_expression<AE> &ae) {
600 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
605 matrix_column &assign (const vector_expression<AE> &ae) {
606 vector_assign<scalar_assign> (*this, ae);
611 matrix_column &operator += (const vector_expression<AE> &ae) {
612 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
617 matrix_column &plus_assign (const vector_expression<AE> &ae) {
618 vector_assign<scalar_plus_assign> (*this, ae);
623 matrix_column &operator -= (const vector_expression<AE> &ae) {
624 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
629 matrix_column &minus_assign (const vector_expression<AE> &ae) {
630 vector_assign<scalar_minus_assign> (*this, ae);
635 matrix_column &operator *= (const AT &at) {
636 vector_assign_scalar<scalar_multiplies_assign> (*this, at);
641 matrix_column &operator /= (const AT &at) {
642 vector_assign_scalar<scalar_divides_assign> (*this, at);
646 // Closure comparison
648 bool same_closure (const matrix_column &mc) const {
649 return (*this).data_.same_closure (mc.data_);
654 bool operator == (const matrix_column &mc) const {
655 return (*this).data_ == mc.data_ && index () == mc.index ();
660 void swap (matrix_column mc) {
662 BOOST_UBLAS_CHECK (size () == mc.size (), bad_size ());
663 // Sparse ranges may be nonconformant now.
664 // std::swap_ranges (begin (), end (), mc.begin ());
665 vector_swap<scalar_swap> (*this, mc);
669 friend void swap (matrix_column mc1, matrix_column mc2) {
675 typedef typename M::const_iterator1 const_subiterator_type;
676 typedef typename boost::mpl::if_<boost::is_const<M>,
677 typename M::const_iterator1,
678 typename M::iterator1>::type subiterator_type;
681 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
682 typedef indexed_iterator<matrix_column<matrix_type>,
683 typename subiterator_type::iterator_category> iterator;
684 typedef indexed_const_iterator<matrix_column<matrix_type>,
685 typename const_subiterator_type::iterator_category> const_iterator;
687 class const_iterator;
693 const_iterator find (size_type i) const {
694 const_subiterator_type it1 (data_.find1 (1, i, j_));
695 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
696 return const_iterator (*this, it1.index1 ());
698 return const_iterator (*this, it1);
702 iterator find (size_type i) {
703 subiterator_type it1 (data_.find1 (1, i, j_));
704 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
705 return iterator (*this, it1.index1 ());
707 return iterator (*this, it1);
711 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
712 class const_iterator:
713 public container_const_reference<matrix_column>,
714 public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
715 iterator_base<const_iterator, value_type>::type {
717 typedef typename const_subiterator_type::value_type value_type;
718 typedef typename const_subiterator_type::difference_type difference_type;
719 typedef typename const_subiterator_type::reference reference;
720 typedef typename const_subiterator_type::pointer pointer;
722 // Construction and destruction
725 container_const_reference<self_type> (), it_ () {}
727 const_iterator (const self_type &mc, const const_subiterator_type &it):
728 container_const_reference<self_type> (mc), it_ (it) {}
730 const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
731 container_const_reference<self_type> (it ()), it_ (it.it_) {}
735 const_iterator &operator ++ () {
740 const_iterator &operator -- () {
745 const_iterator &operator += (difference_type n) {
750 const_iterator &operator -= (difference_type n) {
755 difference_type operator - (const const_iterator &it) const {
756 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
762 const_reference operator * () const {
763 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
767 const_reference operator [] (difference_type n) const {
773 size_type index () const {
774 return it_.index1 ();
779 const_iterator &operator = (const const_iterator &it) {
780 container_const_reference<self_type>::assign (&it ());
787 bool operator == (const const_iterator &it) const {
788 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
789 return it_ == it.it_;
792 bool operator < (const const_iterator &it) const {
793 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
798 const_subiterator_type it_;
803 const_iterator begin () const {
807 const_iterator cbegin () const {
811 const_iterator end () const {
812 return find (size ());
815 const_iterator cend () const {
819 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
821 public container_reference<matrix_column>,
822 public iterator_base_traits<typename subiterator_type::iterator_category>::template
823 iterator_base<iterator, value_type>::type {
825 typedef typename subiterator_type::value_type value_type;
826 typedef typename subiterator_type::difference_type difference_type;
827 typedef typename subiterator_type::reference reference;
828 typedef typename subiterator_type::pointer pointer;
830 // Construction and destruction
833 container_reference<self_type> (), it_ () {}
835 iterator (self_type &mc, const subiterator_type &it):
836 container_reference<self_type> (mc), it_ (it) {}
840 iterator &operator ++ () {
845 iterator &operator -- () {
850 iterator &operator += (difference_type n) {
855 iterator &operator -= (difference_type n) {
860 difference_type operator - (const iterator &it) const {
861 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
867 reference operator * () const {
868 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
872 reference operator [] (difference_type n) const {
878 size_type index () const {
879 return it_.index1 ();
884 iterator &operator = (const iterator &it) {
885 container_reference<self_type>::assign (&it ());
892 bool operator == (const iterator &it) const {
893 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
894 return it_ == it.it_;
897 bool operator < (const iterator &it) const {
898 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
903 subiterator_type it_;
905 friend class const_iterator;
915 return find (size ());
919 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
920 typedef reverse_iterator_base<iterator> reverse_iterator;
923 const_reverse_iterator rbegin () const {
924 return const_reverse_iterator (end ());
927 const_reverse_iterator crbegin () const {
931 const_reverse_iterator rend () const {
932 return const_reverse_iterator (begin ());
935 const_reverse_iterator crend () const {
938 reverse_iterator rbegin () {
939 return reverse_iterator (end ());
942 reverse_iterator rend () {
943 return reverse_iterator (begin ());
947 matrix_closure_type data_;
954 matrix_column<M> column (M &data, typename M::size_type j) {
955 return matrix_column<M> (data, j);
959 const matrix_column<const M> column (const M &data, typename M::size_type j) {
960 return matrix_column<const M> (data, j);
963 // Specialize temporary
965 struct vector_temporary_traits< matrix_column<M> >
966 : vector_temporary_traits< M > {} ;
968 struct vector_temporary_traits< const matrix_column<M> >
969 : vector_temporary_traits< M > {} ;
971 // Matrix based vector range class
973 class matrix_vector_range:
974 public vector_expression<matrix_vector_range<M> > {
976 typedef matrix_vector_range<M> self_type;
978 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
979 using vector_expression<self_type>::operator ();
981 typedef M matrix_type;
982 typedef typename M::size_type size_type;
983 typedef typename M::difference_type difference_type;
984 typedef typename M::value_type value_type;
985 typedef typename M::const_reference const_reference;
986 typedef typename boost::mpl::if_<boost::is_const<M>,
987 typename M::const_reference,
988 typename M::reference>::type reference;
989 typedef typename boost::mpl::if_<boost::is_const<M>,
990 typename M::const_closure_type,
991 typename M::closure_type>::type matrix_closure_type;
992 typedef basic_range<size_type, difference_type> range_type;
993 typedef const self_type const_closure_type;
994 typedef self_type closure_type;
995 typedef typename storage_restrict_traits<typename M::storage_category,
996 dense_proxy_tag>::storage_category storage_category;
998 // Construction and destruction
1000 matrix_vector_range (matrix_type &data, const range_type &r1, const range_type &r2):
1001 data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {
1002 // Early checking of preconditions here.
1003 // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
1004 // r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
1005 // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
1006 // r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
1007 // BOOST_UBLAS_CHECK (r1_.size () == r2_.size (), bad_size ());
1012 size_type start1 () const {
1013 return r1_.start ();
1016 size_type start2 () const {
1017 return r2_.start ();
1020 size_type size () const {
1021 return BOOST_UBLAS_SAME (r1_.size (), r2_.size ());
1024 // Storage accessors
1026 const matrix_closure_type &data () const {
1030 matrix_closure_type &data () {
1035 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1037 const_reference operator () (size_type i) const {
1038 return data_ (r1_ (i), r2_ (i));
1041 reference operator () (size_type i) {
1042 return data_ (r1_ (i), r2_ (i));
1046 const_reference operator [] (size_type i) const {
1050 reference operator [] (size_type i) {
1055 reference operator () (size_type i) const {
1056 return data_ (r1_ (i), r2_ (i));
1060 reference operator [] (size_type i) const {
1067 matrix_vector_range &operator = (const matrix_vector_range &mvr) {
1068 // ISSUE need a temporary, proxy can be overlaping alias
1069 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvr));
1073 matrix_vector_range &assign_temporary (matrix_vector_range &mvr) {
1074 // assign elements, proxied container remains the same
1075 vector_assign<scalar_assign> (*this, mvr);
1080 matrix_vector_range &operator = (const vector_expression<AE> &ae) {
1081 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
1086 matrix_vector_range &assign (const vector_expression<AE> &ae) {
1087 vector_assign<scalar_assign> (*this, ae);
1092 matrix_vector_range &operator += (const vector_expression<AE> &ae) {
1093 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
1098 matrix_vector_range &plus_assign (const vector_expression<AE> &ae) {
1099 vector_assign<scalar_plus_assign> (*this, ae);
1104 matrix_vector_range &operator -= (const vector_expression<AE> &ae) {
1105 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
1110 matrix_vector_range &minus_assign (const vector_expression<AE> &ae) {
1111 vector_assign<scalar_minus_assign> (*this, ae);
1116 matrix_vector_range &operator *= (const AT &at) {
1117 vector_assign_scalar<scalar_multiplies_assign> (*this, at);
1122 matrix_vector_range &operator /= (const AT &at) {
1123 vector_assign_scalar<scalar_divides_assign> (*this, at);
1127 // Closure comparison
1129 bool same_closure (const matrix_vector_range &mvr) const {
1130 return (*this).data_.same_closure (mvr.data_);
1135 bool operator == (const matrix_vector_range &mvr) const {
1136 return (*this).data_ == mvr.data_ && r1_ == mvr.r1_ && r2_ == mvr.r2_;
1141 void swap (matrix_vector_range mvr) {
1143 BOOST_UBLAS_CHECK (size () == mvr.size (), bad_size ());
1144 // Sparse ranges may be nonconformant now.
1145 // std::swap_ranges (begin (), end (), mvr.begin ());
1146 vector_swap<scalar_swap> (*this, mvr);
1150 friend void swap (matrix_vector_range mvr1, matrix_vector_range mvr2) {
1156 // Use range as an index - FIXME this fails for packed assignment
1157 typedef typename range_type::const_iterator const_subiterator1_type;
1158 typedef typename range_type::const_iterator subiterator1_type;
1159 typedef typename range_type::const_iterator const_subiterator2_type;
1160 typedef typename range_type::const_iterator subiterator2_type;
1163 class const_iterator;
1168 const_iterator find (size_type i) const {
1169 return const_iterator (*this, r1_.begin () + i, r2_.begin () + i);
1172 iterator find (size_type i) {
1173 return iterator (*this, r1_.begin () + i, r2_.begin () + i);
1176 class const_iterator:
1177 public container_const_reference<matrix_vector_range>,
1178 public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
1179 iterator_base<const_iterator, value_type>::type {
1181 // FIXME Iterator can never be different code was:
1182 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
1183 BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
1185 typedef typename matrix_vector_range::value_type value_type;
1186 typedef typename matrix_vector_range::difference_type difference_type;
1187 typedef typename matrix_vector_range::const_reference reference;
1188 typedef const typename matrix_vector_range::value_type *pointer;
1190 // Construction and destruction
1193 container_const_reference<self_type> (), it1_ (), it2_ () {}
1195 const_iterator (const self_type &mvr, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
1196 container_const_reference<self_type> (mvr), it1_ (it1), it2_ (it2) {}
1198 const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
1199 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
1203 const_iterator &operator ++ () {
1209 const_iterator &operator -- () {
1215 const_iterator &operator += (difference_type n) {
1221 const_iterator &operator -= (difference_type n) {
1227 difference_type operator - (const const_iterator &it) const {
1228 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1229 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
1234 const_reference operator * () const {
1235 // FIXME replace find with at_element
1236 return (*this) ().data_ (*it1_, *it2_);
1239 const_reference operator [] (difference_type n) const {
1240 return *(*this + n);
1245 size_type index () const {
1246 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
1251 const_iterator &operator = (const const_iterator &it) {
1252 container_const_reference<self_type>::assign (&it ());
1260 bool operator == (const const_iterator &it) const {
1261 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1262 return it1_ == it.it1_ && it2_ == it.it2_;
1265 bool operator < (const const_iterator &it) const {
1266 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1267 return it1_ < it.it1_ && it2_ < it.it2_;
1271 const_subiterator1_type it1_;
1272 const_subiterator2_type it2_;
1276 const_iterator begin () const {
1280 const_iterator cbegin () const {
1284 const_iterator end () const {
1285 return find (size ());
1288 const_iterator cend () const {
1293 public container_reference<matrix_vector_range>,
1294 public iterator_base_traits<typename M::iterator1::iterator_category>::template
1295 iterator_base<iterator, value_type>::type {
1297 // FIXME Iterator can never be different code was:
1298 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
1299 BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
1301 typedef typename matrix_vector_range::value_type value_type;
1302 typedef typename matrix_vector_range::difference_type difference_type;
1303 typedef typename matrix_vector_range::reference reference;
1304 typedef typename matrix_vector_range::value_type *pointer;
1306 // Construction and destruction
1309 container_reference<self_type> (), it1_ (), it2_ () {}
1311 iterator (self_type &mvr, const subiterator1_type &it1, const subiterator2_type &it2):
1312 container_reference<self_type> (mvr), it1_ (it1), it2_ (it2) {}
1316 iterator &operator ++ () {
1322 iterator &operator -- () {
1328 iterator &operator += (difference_type n) {
1334 iterator &operator -= (difference_type n) {
1340 difference_type operator - (const iterator &it) const {
1341 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1342 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
1347 reference operator * () const {
1348 // FIXME replace find with at_element
1349 return (*this) ().data_ (*it1_, *it2_);
1352 reference operator [] (difference_type n) const {
1353 return *(*this + n);
1358 size_type index () const {
1359 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
1364 iterator &operator = (const iterator &it) {
1365 container_reference<self_type>::assign (&it ());
1373 bool operator == (const iterator &it) const {
1374 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1375 return it1_ == it.it1_ && it2_ == it.it2_;
1378 bool operator < (const iterator &it) const {
1379 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1380 return it1_ < it.it1_ && it2_ < it.it2_;
1384 subiterator1_type it1_;
1385 subiterator2_type it2_;
1387 friend class const_iterator;
1396 return find (size ());
1400 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1401 typedef reverse_iterator_base<iterator> reverse_iterator;
1404 const_reverse_iterator rbegin () const {
1405 return const_reverse_iterator (end ());
1408 const_reverse_iterator crbegin () const {
1412 const_reverse_iterator rend () const {
1413 return const_reverse_iterator (begin ());
1416 const_reverse_iterator crend () const {
1420 reverse_iterator rbegin () {
1421 return reverse_iterator (end ());
1424 reverse_iterator rend () {
1425 return reverse_iterator (begin ());
1429 matrix_closure_type data_;
1434 // Specialize temporary
1436 struct vector_temporary_traits< matrix_vector_range<M> >
1437 : vector_temporary_traits< M > {} ;
1439 struct vector_temporary_traits< const matrix_vector_range<M> >
1440 : vector_temporary_traits< M > {} ;
1442 // Matrix based vector slice class
1444 class matrix_vector_slice:
1445 public vector_expression<matrix_vector_slice<M> > {
1447 typedef matrix_vector_slice<M> self_type;
1449 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1450 using vector_expression<self_type>::operator ();
1452 typedef M matrix_type;
1453 typedef typename M::size_type size_type;
1454 typedef typename M::difference_type difference_type;
1455 typedef typename M::value_type value_type;
1456 typedef typename M::const_reference const_reference;
1457 typedef typename boost::mpl::if_<boost::is_const<M>,
1458 typename M::const_reference,
1459 typename M::reference>::type reference;
1460 typedef typename boost::mpl::if_<boost::is_const<M>,
1461 typename M::const_closure_type,
1462 typename M::closure_type>::type matrix_closure_type;
1463 typedef basic_range<size_type, difference_type> range_type;
1464 typedef basic_slice<size_type, difference_type> slice_type;
1465 typedef const self_type const_closure_type;
1466 typedef self_type closure_type;
1467 typedef typename storage_restrict_traits<typename M::storage_category,
1468 dense_proxy_tag>::storage_category storage_category;
1470 // Construction and destruction
1472 matrix_vector_slice (matrix_type &data, const slice_type &s1, const slice_type &s2):
1473 data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {
1474 // Early checking of preconditions here.
1475 // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
1476 // s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
1477 // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
1478 // s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
1483 size_type start1 () const {
1484 return s1_.start ();
1487 size_type start2 () const {
1488 return s2_.start ();
1491 difference_type stride1 () const {
1492 return s1_.stride ();
1495 difference_type stride2 () const {
1496 return s2_.stride ();
1499 size_type size () const {
1500 return BOOST_UBLAS_SAME (s1_.size (), s2_.size ());
1503 // Storage accessors
1505 const matrix_closure_type &data () const {
1509 matrix_closure_type &data () {
1514 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1516 const_reference operator () (size_type i) const {
1517 return data_ (s1_ (i), s2_ (i));
1520 reference operator () (size_type i) {
1521 return data_ (s1_ (i), s2_ (i));
1525 const_reference operator [] (size_type i) const {
1529 reference operator [] (size_type i) {
1534 reference operator () (size_type i) const {
1535 return data_ (s1_ (i), s2_ (i));
1539 reference operator [] (size_type i) const {
1546 matrix_vector_slice &operator = (const matrix_vector_slice &mvs) {
1547 // ISSUE need a temporary, proxy can be overlaping alias
1548 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvs));
1552 matrix_vector_slice &assign_temporary (matrix_vector_slice &mvs) {
1553 // assign elements, proxied container remains the same
1554 vector_assign<scalar_assign> (*this, mvs);
1559 matrix_vector_slice &operator = (const vector_expression<AE> &ae) {
1560 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
1565 matrix_vector_slice &assign (const vector_expression<AE> &ae) {
1566 vector_assign<scalar_assign> (*this, ae);
1571 matrix_vector_slice &operator += (const vector_expression<AE> &ae) {
1572 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
1577 matrix_vector_slice &plus_assign (const vector_expression<AE> &ae) {
1578 vector_assign<scalar_plus_assign> (*this, ae);
1583 matrix_vector_slice &operator -= (const vector_expression<AE> &ae) {
1584 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
1589 matrix_vector_slice &minus_assign (const vector_expression<AE> &ae) {
1590 vector_assign<scalar_minus_assign> (*this, ae);
1595 matrix_vector_slice &operator *= (const AT &at) {
1596 vector_assign_scalar<scalar_multiplies_assign> (*this, at);
1601 matrix_vector_slice &operator /= (const AT &at) {
1602 vector_assign_scalar<scalar_divides_assign> (*this, at);
1606 // Closure comparison
1608 bool same_closure (const matrix_vector_slice &mvs) const {
1609 return (*this).data_.same_closure (mvs.data_);
1614 bool operator == (const matrix_vector_slice &mvs) const {
1615 return (*this).data_ == mvs.data_ && s1_ == mvs.s1_ && s2_ == mvs.s2_;
1620 void swap (matrix_vector_slice mvs) {
1622 BOOST_UBLAS_CHECK (size () == mvs.size (), bad_size ());
1623 // Sparse ranges may be nonconformant now.
1624 // std::swap_ranges (begin (), end (), mvs.begin ());
1625 vector_swap<scalar_swap> (*this, mvs);
1629 friend void swap (matrix_vector_slice mvs1, matrix_vector_slice mvs2) {
1635 // Use slice as an index - FIXME this fails for packed assignment
1636 typedef typename slice_type::const_iterator const_subiterator1_type;
1637 typedef typename slice_type::const_iterator subiterator1_type;
1638 typedef typename slice_type::const_iterator const_subiterator2_type;
1639 typedef typename slice_type::const_iterator subiterator2_type;
1642 class const_iterator;
1647 const_iterator find (size_type i) const {
1648 return const_iterator (*this, s1_.begin () + i, s2_.begin () + i);
1651 iterator find (size_type i) {
1652 return iterator (*this, s1_.begin () + i, s2_.begin () + i);
1655 // Iterators simply are indices.
1657 class const_iterator:
1658 public container_const_reference<matrix_vector_slice>,
1659 public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
1660 iterator_base<const_iterator, value_type>::type {
1662 // FIXME Iterator can never be different code was:
1663 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
1664 BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
1666 typedef typename matrix_vector_slice::value_type value_type;
1667 typedef typename matrix_vector_slice::difference_type difference_type;
1668 typedef typename matrix_vector_slice::const_reference reference;
1669 typedef const typename matrix_vector_slice::value_type *pointer;
1671 // Construction and destruction
1674 container_const_reference<self_type> (), it1_ (), it2_ () {}
1676 const_iterator (const self_type &mvs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
1677 container_const_reference<self_type> (mvs), it1_ (it1), it2_ (it2) {}
1679 const_iterator (const typename self_type::iterator &it): // ISSUE vector:: stops VC8 using std::iterator here
1680 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
1684 const_iterator &operator ++ () {
1690 const_iterator &operator -- () {
1696 const_iterator &operator += (difference_type n) {
1702 const_iterator &operator -= (difference_type n) {
1708 difference_type operator - (const const_iterator &it) const {
1709 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1710 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
1715 const_reference operator * () const {
1716 // FIXME replace find with at_element
1717 return (*this) ().data_ (*it1_, *it2_);
1720 const_reference operator [] (difference_type n) const {
1721 return *(*this + n);
1726 size_type index () const {
1727 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
1732 const_iterator &operator = (const const_iterator &it) {
1733 container_const_reference<self_type>::assign (&it ());
1741 bool operator == (const const_iterator &it) const {
1742 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1743 return it1_ == it.it1_ && it2_ == it.it2_;
1746 bool operator < (const const_iterator &it) const {
1747 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1748 return it1_ < it.it1_ && it2_ < it.it2_;
1752 const_subiterator1_type it1_;
1753 const_subiterator2_type it2_;
1757 const_iterator begin () const {
1761 const_iterator cbegin () const {
1765 const_iterator end () const {
1766 return find (size ());
1769 const_iterator cend () const {
1774 public container_reference<matrix_vector_slice>,
1775 public iterator_base_traits<typename M::iterator1::iterator_category>::template
1776 iterator_base<iterator, value_type>::type {
1778 // FIXME Iterator can never be different code was:
1779 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
1780 BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
1782 typedef typename matrix_vector_slice::value_type value_type;
1783 typedef typename matrix_vector_slice::difference_type difference_type;
1784 typedef typename matrix_vector_slice::reference reference;
1785 typedef typename matrix_vector_slice::value_type *pointer;
1787 // Construction and destruction
1790 container_reference<self_type> (), it1_ (), it2_ () {}
1792 iterator (self_type &mvs, const subiterator1_type &it1, const subiterator2_type &it2):
1793 container_reference<self_type> (mvs), it1_ (it1), it2_ (it2) {}
1797 iterator &operator ++ () {
1803 iterator &operator -- () {
1809 iterator &operator += (difference_type n) {
1815 iterator &operator -= (difference_type n) {
1821 difference_type operator - (const iterator &it) const {
1822 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1823 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
1828 reference operator * () const {
1829 // FIXME replace find with at_element
1830 return (*this) ().data_ (*it1_, *it2_);
1833 reference operator [] (difference_type n) const {
1834 return *(*this + n);
1839 size_type index () const {
1840 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
1845 iterator &operator = (const iterator &it) {
1846 container_reference<self_type>::assign (&it ());
1854 bool operator == (const iterator &it) const {
1855 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1856 return it1_ == it.it1_ && it2_ == it.it2_;
1859 bool operator < (const iterator &it) const {
1860 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1861 return it1_ < it.it1_ && it2_ < it.it2_;
1865 subiterator1_type it1_;
1866 subiterator2_type it2_;
1868 friend class const_iterator;
1877 return find (size ());
1881 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1882 typedef reverse_iterator_base<iterator> reverse_iterator;
1885 const_reverse_iterator rbegin () const {
1886 return const_reverse_iterator (end ());
1889 const_reverse_iterator crbegin () const {
1893 const_reverse_iterator rend () const {
1894 return const_reverse_iterator (begin ());
1897 const_reverse_iterator crend () const {
1901 reverse_iterator rbegin () {
1902 return reverse_iterator (end ());
1905 reverse_iterator rend () {
1906 return reverse_iterator (begin ());
1910 matrix_closure_type data_;
1915 // Specialize temporary
1917 struct vector_temporary_traits< matrix_vector_slice<M> >
1918 : vector_temporary_traits< M > {} ;
1920 struct vector_temporary_traits< const matrix_vector_slice<M> >
1921 : vector_temporary_traits< M > {} ;
1923 // Matrix based vector indirection class
1925 template<class M, class IA>
1926 class matrix_vector_indirect:
1927 public vector_expression<matrix_vector_indirect<M, IA> > {
1929 typedef matrix_vector_indirect<M, IA> self_type;
1931 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1932 using vector_expression<self_type>::operator ();
1934 typedef M matrix_type;
1935 typedef IA indirect_array_type;
1936 typedef typename M::size_type size_type;
1937 typedef typename M::difference_type difference_type;
1938 typedef typename M::value_type value_type;
1939 typedef typename M::const_reference const_reference;
1940 typedef typename boost::mpl::if_<boost::is_const<M>,
1941 typename M::const_reference,
1942 typename M::reference>::type reference;
1943 typedef typename boost::mpl::if_<boost::is_const<M>,
1944 typename M::const_closure_type,
1945 typename M::closure_type>::type matrix_closure_type;
1946 typedef const self_type const_closure_type;
1947 typedef self_type closure_type;
1948 typedef typename storage_restrict_traits<typename M::storage_category,
1949 dense_proxy_tag>::storage_category storage_category;
1951 // Construction and destruction
1953 matrix_vector_indirect (matrix_type &data, size_type size):
1954 data_ (data), ia1_ (size), ia2_ (size) {}
1956 matrix_vector_indirect (matrix_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2):
1957 data_ (data), ia1_ (ia1), ia2_ (ia2) {
1958 // Early checking of preconditions here.
1959 // BOOST_UBLAS_CHECK (ia1_.size () == ia2_.size (), bad_size ());
1964 size_type size () const {
1965 return BOOST_UBLAS_SAME (ia1_.size (), ia2_.size ());
1968 const indirect_array_type &indirect1 () const {
1972 indirect_array_type &indirect1 () {
1976 const indirect_array_type &indirect2 () const {
1980 indirect_array_type &indirect2 () {
1984 // Storage accessors
1986 const matrix_closure_type &data () const {
1990 matrix_closure_type &data () {
1995 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1997 const_reference operator () (size_type i) const {
1998 return data_ (ia1_ (i), ia2_ (i));
2001 reference operator () (size_type i) {
2002 return data_ (ia1_ (i), ia2_ (i));
2006 const_reference operator [] (size_type i) const {
2010 reference operator [] (size_type i) {
2015 reference operator () (size_type i) const {
2016 return data_ (ia1_ (i), ia2_ (i));
2020 reference operator [] (size_type i) const {
2027 matrix_vector_indirect &operator = (const matrix_vector_indirect &mvi) {
2028 // ISSUE need a temporary, proxy can be overlaping alias
2029 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvi));
2033 matrix_vector_indirect &assign_temporary (matrix_vector_indirect &mvi) {
2034 // assign elements, proxied container remains the same
2035 vector_assign<scalar_assign> (*this, mvi);
2040 matrix_vector_indirect &operator = (const vector_expression<AE> &ae) {
2041 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
2046 matrix_vector_indirect &assign (const vector_expression<AE> &ae) {
2047 vector_assign<scalar_assign> (*this, ae);
2052 matrix_vector_indirect &operator += (const vector_expression<AE> &ae) {
2053 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
2058 matrix_vector_indirect &plus_assign (const vector_expression<AE> &ae) {
2059 vector_assign<scalar_plus_assign> (*this, ae);
2064 matrix_vector_indirect &operator -= (const vector_expression<AE> &ae) {
2065 vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
2070 matrix_vector_indirect &minus_assign (const vector_expression<AE> &ae) {
2071 vector_assign<scalar_minus_assign> (*this, ae);
2076 matrix_vector_indirect &operator *= (const AT &at) {
2077 vector_assign_scalar<scalar_multiplies_assign> (*this, at);
2082 matrix_vector_indirect &operator /= (const AT &at) {
2083 vector_assign_scalar<scalar_divides_assign> (*this, at);
2087 // Closure comparison
2089 bool same_closure (const matrix_vector_indirect &mvi) const {
2090 return (*this).data_.same_closure (mvi.data_);
2095 bool operator == (const matrix_vector_indirect &mvi) const {
2096 return (*this).data_ == mvi.data_ && ia1_ == mvi.ia1_ && ia2_ == mvi.ia2_;
2101 void swap (matrix_vector_indirect mvi) {
2103 BOOST_UBLAS_CHECK (size () == mvi.size (), bad_size ());
2104 // Sparse ranges may be nonconformant now.
2105 // std::swap_ranges (begin (), end (), mvi.begin ());
2106 vector_swap<scalar_swap> (*this, mvi);
2110 friend void swap (matrix_vector_indirect mvi1, matrix_vector_indirect mvi2) {
2116 // Use indirect array as an index - FIXME this fails for packed assignment
2117 typedef typename IA::const_iterator const_subiterator1_type;
2118 typedef typename IA::const_iterator subiterator1_type;
2119 typedef typename IA::const_iterator const_subiterator2_type;
2120 typedef typename IA::const_iterator subiterator2_type;
2123 class const_iterator;
2128 const_iterator find (size_type i) const {
2129 return const_iterator (*this, ia1_.begin () + i, ia2_.begin () + i);
2132 iterator find (size_type i) {
2133 return iterator (*this, ia1_.begin () + i, ia2_.begin () + i);
2136 // Iterators simply are indices.
2138 class const_iterator:
2139 public container_const_reference<matrix_vector_indirect>,
2140 public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
2141 iterator_base<const_iterator, value_type>::type {
2143 // FIXME Iterator can never be different code was:
2144 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
2145 BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
2147 typedef typename matrix_vector_indirect::value_type value_type;
2148 typedef typename matrix_vector_indirect::difference_type difference_type;
2149 typedef typename matrix_vector_indirect::const_reference reference;
2150 typedef const typename matrix_vector_indirect::value_type *pointer;
2152 // Construction and destruction
2155 container_const_reference<self_type> (), it1_ (), it2_ () {}
2157 const_iterator (const self_type &mvi, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
2158 container_const_reference<self_type> (mvi), it1_ (it1), it2_ (it2) {}
2160 const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
2161 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
2165 const_iterator &operator ++ () {
2171 const_iterator &operator -- () {
2177 const_iterator &operator += (difference_type n) {
2183 const_iterator &operator -= (difference_type n) {
2189 difference_type operator - (const const_iterator &it) const {
2190 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2191 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
2196 const_reference operator * () const {
2197 // FIXME replace find with at_element
2198 return (*this) ().data_ (*it1_, *it2_);
2201 const_reference operator [] (difference_type n) const {
2202 return *(*this + n);
2207 size_type index () const {
2208 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
2213 const_iterator &operator = (const const_iterator &it) {
2214 container_const_reference<self_type>::assign (&it ());
2222 bool operator == (const const_iterator &it) const {
2223 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2224 return it1_ == it.it1_ && it2_ == it.it2_;
2227 bool operator < (const const_iterator &it) const {
2228 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2229 return it1_ < it.it1_ && it2_ < it.it2_;
2233 const_subiterator1_type it1_;
2234 const_subiterator2_type it2_;
2238 const_iterator begin () const {
2242 const_iterator cbegin () const {
2246 const_iterator end () const {
2247 return find (size ());
2250 const_iterator cend () const {
2255 public container_reference<matrix_vector_indirect>,
2256 public iterator_base_traits<typename M::iterator1::iterator_category>::template
2257 iterator_base<iterator, value_type>::type {
2259 // FIXME Iterator can never be different code was:
2260 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
2261 BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
2263 typedef typename matrix_vector_indirect::value_type value_type;
2264 typedef typename matrix_vector_indirect::difference_type difference_type;
2265 typedef typename matrix_vector_indirect::reference reference;
2266 typedef typename matrix_vector_indirect::value_type *pointer;
2268 // Construction and destruction
2271 container_reference<self_type> (), it1_ (), it2_ () {}
2273 iterator (self_type &mvi, const subiterator1_type &it1, const subiterator2_type &it2):
2274 container_reference<self_type> (mvi), it1_ (it1), it2_ (it2) {}
2278 iterator &operator ++ () {
2284 iterator &operator -- () {
2290 iterator &operator += (difference_type n) {
2296 iterator &operator -= (difference_type n) {
2302 difference_type operator - (const iterator &it) const {
2303 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2304 return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
2309 reference operator * () const {
2310 // FIXME replace find with at_element
2311 return (*this) ().data_ (*it1_, *it2_);
2314 reference operator [] (difference_type n) const {
2315 return *(*this + n);
2320 size_type index () const {
2321 return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
2326 iterator &operator = (const iterator &it) {
2327 container_reference<self_type>::assign (&it ());
2335 bool operator == (const iterator &it) const {
2336 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2337 return it1_ == it.it1_ && it2_ == it.it2_;
2340 bool operator < (const iterator &it) const {
2341 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2342 return it1_ < it.it1_ && it2_ < it.it2_;
2346 subiterator1_type it1_;
2347 subiterator2_type it2_;
2349 friend class const_iterator;
2358 return find (size ());
2362 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
2363 typedef reverse_iterator_base<iterator> reverse_iterator;
2366 const_reverse_iterator rbegin () const {
2367 return const_reverse_iterator (end ());
2370 const_reverse_iterator crbegin () const {
2374 const_reverse_iterator rend () const {
2375 return const_reverse_iterator (begin ());
2378 const_reverse_iterator crend () const {
2382 reverse_iterator rbegin () {
2383 return reverse_iterator (end ());
2386 reverse_iterator rend () {
2387 return reverse_iterator (begin ());
2391 matrix_closure_type data_;
2392 indirect_array_type ia1_;
2393 indirect_array_type ia2_;
2396 // Specialize temporary
2397 template <class M, class IA>
2398 struct vector_temporary_traits< matrix_vector_indirect<M,IA> >
2399 : vector_temporary_traits< M > {} ;
2400 template <class M, class IA>
2401 struct vector_temporary_traits< const matrix_vector_indirect<M,IA> >
2402 : vector_temporary_traits< M > {} ;
2404 // Matrix based range class
2407 public matrix_expression<matrix_range<M> > {
2409 typedef matrix_range<M> self_type;
2411 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2412 using matrix_expression<self_type>::operator ();
2414 typedef M matrix_type;
2415 typedef typename M::size_type size_type;
2416 typedef typename M::difference_type difference_type;
2417 typedef typename M::value_type value_type;
2418 typedef typename M::const_reference const_reference;
2419 typedef typename boost::mpl::if_<boost::is_const<M>,
2420 typename M::const_reference,
2421 typename M::reference>::type reference;
2422 typedef typename boost::mpl::if_<boost::is_const<M>,
2423 typename M::const_closure_type,
2424 typename M::closure_type>::type matrix_closure_type;
2425 typedef basic_range<size_type, difference_type> range_type;
2426 typedef const self_type const_closure_type;
2427 typedef self_type closure_type;
2428 typedef typename storage_restrict_traits<typename M::storage_category,
2429 dense_proxy_tag>::storage_category storage_category;
2430 typedef typename M::orientation_category orientation_category;
2432 // Construction and destruction
2434 matrix_range (matrix_type &data, const range_type &r1, const range_type &r2):
2435 data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {
2436 // Early checking of preconditions here.
2437 // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
2438 // r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
2439 // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
2440 // r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
2443 matrix_range (const matrix_closure_type &data, const range_type &r1, const range_type &r2, int):
2444 data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {
2445 // Early checking of preconditions here.
2446 // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
2447 // r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
2448 // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
2449 // r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
2454 size_type start1 () const {
2455 return r1_.start ();
2458 size_type size1 () const {
2462 size_type start2() const {
2463 return r2_.start ();
2466 size_type size2 () const {
2470 // Storage accessors
2472 const matrix_closure_type &data () const {
2476 matrix_closure_type &data () {
2481 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
2483 const_reference operator () (size_type i, size_type j) const {
2484 return data_ (r1_ (i), r2_ (j));
2487 reference operator () (size_type i, size_type j) {
2488 return data_ (r1_ (i), r2_ (j));
2492 reference operator () (size_type i, size_type j) const {
2493 return data_ (r1_ (i), r2_ (j));
2497 // ISSUE can this be done in free project function?
2498 // Although a const function can create a non-const proxy to a non-const object
2499 // Critical is that matrix_type and data_ (vector_closure_type) are const correct
2501 matrix_range<matrix_type> project (const range_type &r1, const range_type &r2) const {
2502 return matrix_range<matrix_type> (data_, r1_.compose (r1.preprocess (data_.size1 ())), r2_.compose (r2.preprocess (data_.size2 ())), 0);
2507 matrix_range &operator = (const matrix_range &mr) {
2508 matrix_assign<scalar_assign> (*this, mr);
2512 matrix_range &assign_temporary (matrix_range &mr) {
2517 matrix_range &operator = (const matrix_expression<AE> &ae) {
2518 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae));
2523 matrix_range &assign (const matrix_expression<AE> &ae) {
2524 matrix_assign<scalar_assign> (*this, ae);
2529 matrix_range& operator += (const matrix_expression<AE> &ae) {
2530 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae));
2535 matrix_range &plus_assign (const matrix_expression<AE> &ae) {
2536 matrix_assign<scalar_plus_assign> (*this, ae);
2541 matrix_range& operator -= (const matrix_expression<AE> &ae) {
2542 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae));
2547 matrix_range &minus_assign (const matrix_expression<AE> &ae) {
2548 matrix_assign<scalar_minus_assign> (*this, ae);
2553 matrix_range& operator *= (const AT &at) {
2554 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
2559 matrix_range& operator /= (const AT &at) {
2560 matrix_assign_scalar<scalar_divides_assign> (*this, at);
2564 // Closure comparison
2566 bool same_closure (const matrix_range &mr) const {
2567 return (*this).data_.same_closure (mr.data_);
2572 bool operator == (const matrix_range &mr) const {
2573 return (*this).data_ == (mr.data_) && r1_ == mr.r1_ && r2_ == mr.r2_;
2578 void swap (matrix_range mr) {
2580 BOOST_UBLAS_CHECK (size1 () == mr.size1 (), bad_size ());
2581 BOOST_UBLAS_CHECK (size2 () == mr.size2 (), bad_size ());
2582 matrix_swap<scalar_swap> (*this, mr);
2586 friend void swap (matrix_range mr1, matrix_range mr2) {
2592 typedef typename M::const_iterator1 const_subiterator1_type;
2593 typedef typename boost::mpl::if_<boost::is_const<M>,
2594 typename M::const_iterator1,
2595 typename M::iterator1>::type subiterator1_type;
2596 typedef typename M::const_iterator2 const_subiterator2_type;
2597 typedef typename boost::mpl::if_<boost::is_const<M>,
2598 typename M::const_iterator2,
2599 typename M::iterator2>::type subiterator2_type;
2602 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2603 typedef indexed_iterator1<matrix_range<matrix_type>,
2604 typename subiterator1_type::iterator_category> iterator1;
2605 typedef indexed_iterator2<matrix_range<matrix_type>,
2606 typename subiterator2_type::iterator_category> iterator2;
2607 typedef indexed_const_iterator1<matrix_range<matrix_type>,
2608 typename const_subiterator1_type::iterator_category> const_iterator1;
2609 typedef indexed_const_iterator2<matrix_range<matrix_type>,
2610 typename const_subiterator2_type::iterator_category> const_iterator2;
2612 class const_iterator1;
2614 class const_iterator2;
2617 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2618 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
2619 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2620 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
2624 const_iterator1 find1 (int rank, size_type i, size_type j) const {
2625 const_subiterator1_type it1 (data_.find1 (rank, start1 () + i, start2 () + j));
2626 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2627 return const_iterator1 (*this, it1.index1 (), it1.index2 ());
2629 return const_iterator1 (*this, it1);
2633 iterator1 find1 (int rank, size_type i, size_type j) {
2634 subiterator1_type it1 (data_.find1 (rank, start1 () + i, start2 () + j));
2635 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2636 return iterator1 (*this, it1.index1 (), it1.index2 ());
2638 return iterator1 (*this, it1);
2642 const_iterator2 find2 (int rank, size_type i, size_type j) const {
2643 const_subiterator2_type it2 (data_.find2 (rank, start1 () + i, start2 () + j));
2644 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2645 return const_iterator2 (*this, it2.index1 (), it2.index2 ());
2647 return const_iterator2 (*this, it2);
2651 iterator2 find2 (int rank, size_type i, size_type j) {
2652 subiterator2_type it2 (data_.find2 (rank, start1 () + i, start2 () + j));
2653 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2654 return iterator2 (*this, it2.index1 (), it2.index2 ());
2656 return iterator2 (*this, it2);
2661 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2662 class const_iterator1:
2663 public container_const_reference<matrix_range>,
2664 public iterator_base_traits<typename const_subiterator1_type::iterator_category>::template
2665 iterator_base<const_iterator1, value_type>::type {
2667 typedef typename const_subiterator1_type::value_type value_type;
2668 typedef typename const_subiterator1_type::difference_type difference_type;
2669 typedef typename const_subiterator1_type::reference reference;
2670 typedef typename const_subiterator1_type::pointer pointer;
2671 typedef const_iterator2 dual_iterator_type;
2672 typedef const_reverse_iterator2 dual_reverse_iterator_type;
2674 // Construction and destruction
2677 container_const_reference<self_type> (), it_ () {}
2679 const_iterator1 (const self_type &mr, const const_subiterator1_type &it):
2680 container_const_reference<self_type> (mr), it_ (it) {}
2682 const_iterator1 (const iterator1 &it):
2683 container_const_reference<self_type> (it ()), it_ (it.it_) {}
2687 const_iterator1 &operator ++ () {
2692 const_iterator1 &operator -- () {
2697 const_iterator1 &operator += (difference_type n) {
2702 const_iterator1 &operator -= (difference_type n) {
2707 difference_type operator - (const const_iterator1 &it) const {
2708 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2709 return it_ - it.it_;
2714 const_reference operator * () const {
2718 const_reference operator [] (difference_type n) const {
2719 return *(*this + n);
2722 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2724 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2725 typename self_type::
2727 const_iterator2 begin () const {
2728 const self_type &mr = (*this) ();
2729 return mr.find2 (1, index1 (), 0);
2732 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2733 typename self_type::
2735 const_iterator2 cbegin () const {
2739 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2740 typename self_type::
2742 const_iterator2 end () const {
2743 const self_type &mr = (*this) ();
2744 return mr.find2 (1, index1 (), mr.size2 ());
2747 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2748 typename self_type::
2750 const_iterator2 cend () const {
2754 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2755 typename self_type::
2757 const_reverse_iterator2 rbegin () const {
2758 return const_reverse_iterator2 (end ());
2761 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2762 typename self_type::
2764 const_reverse_iterator2 crbegin () const {
2768 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2769 typename self_type::
2771 const_reverse_iterator2 rend () const {
2772 return const_reverse_iterator2 (begin ());
2775 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2776 typename self_type::
2778 const_reverse_iterator2 crend () const {
2785 size_type index1 () const {
2786 return it_.index1 () - (*this) ().start1 ();
2789 size_type index2 () const {
2790 return it_.index2 () - (*this) ().start2 ();
2795 const_iterator1 &operator = (const const_iterator1 &it) {
2796 container_const_reference<self_type>::assign (&it ());
2803 bool operator == (const const_iterator1 &it) const {
2804 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2805 return it_ == it.it_;
2808 bool operator < (const const_iterator1 &it) const {
2809 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2810 return it_ < it.it_;
2814 const_subiterator1_type it_;
2819 const_iterator1 begin1 () const {
2820 return find1 (0, 0, 0);
2823 const_iterator1 cbegin1 () const {
2827 const_iterator1 end1 () const {
2828 return find1 (0, size1 (), 0);
2831 const_iterator1 cend1 () const {
2835 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2837 public container_reference<matrix_range>,
2838 public iterator_base_traits<typename subiterator1_type::iterator_category>::template
2839 iterator_base<iterator1, value_type>::type {
2841 typedef typename subiterator1_type::value_type value_type;
2842 typedef typename subiterator1_type::difference_type difference_type;
2843 typedef typename subiterator1_type::reference reference;
2844 typedef typename subiterator1_type::pointer pointer;
2845 typedef iterator2 dual_iterator_type;
2846 typedef reverse_iterator2 dual_reverse_iterator_type;
2848 // Construction and destruction
2851 container_reference<self_type> (), it_ () {}
2853 iterator1 (self_type &mr, const subiterator1_type &it):
2854 container_reference<self_type> (mr), it_ (it) {}
2858 iterator1 &operator ++ () {
2863 iterator1 &operator -- () {
2868 iterator1 &operator += (difference_type n) {
2873 iterator1 &operator -= (difference_type n) {
2878 difference_type operator - (const iterator1 &it) const {
2879 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2880 return it_ - it.it_;
2885 reference operator * () const {
2889 reference operator [] (difference_type n) const {
2890 return *(*this + n);
2893 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2895 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2896 typename self_type::
2898 iterator2 begin () const {
2899 self_type &mr = (*this) ();
2900 return mr.find2 (1, index1 (), 0);
2903 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2904 typename self_type::
2906 iterator2 end () const {
2907 self_type &mr = (*this) ();
2908 return mr.find2 (1, index1 (), mr.size2 ());
2911 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2912 typename self_type::
2914 reverse_iterator2 rbegin () const {
2915 return reverse_iterator2 (end ());
2918 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2919 typename self_type::
2921 reverse_iterator2 rend () const {
2922 return reverse_iterator2 (begin ());
2928 size_type index1 () const {
2929 return it_.index1 () - (*this) ().start1 ();
2932 size_type index2 () const {
2933 return it_.index2 () - (*this) ().start2 ();
2938 iterator1 &operator = (const iterator1 &it) {
2939 container_reference<self_type>::assign (&it ());
2946 bool operator == (const iterator1 &it) const {
2947 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2948 return it_ == it.it_;
2951 bool operator < (const iterator1 &it) const {
2952 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2953 return it_ < it.it_;
2957 subiterator1_type it_;
2959 friend class const_iterator1;
2964 iterator1 begin1 () {
2965 return find1 (0, 0, 0);
2969 return find1 (0, size1 (), 0);
2972 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2973 class const_iterator2:
2974 public container_const_reference<matrix_range>,
2975 public iterator_base_traits<typename const_subiterator2_type::iterator_category>::template
2976 iterator_base<const_iterator2, value_type>::type {
2978 typedef typename const_subiterator2_type::value_type value_type;
2979 typedef typename const_subiterator2_type::difference_type difference_type;
2980 typedef typename const_subiterator2_type::reference reference;
2981 typedef typename const_subiterator2_type::pointer pointer;
2982 typedef const_iterator1 dual_iterator_type;
2983 typedef const_reverse_iterator1 dual_reverse_iterator_type;
2985 // Construction and destruction
2988 container_const_reference<self_type> (), it_ () {}
2990 const_iterator2 (const self_type &mr, const const_subiterator2_type &it):
2991 container_const_reference<self_type> (mr), it_ (it) {}
2993 const_iterator2 (const iterator2 &it):
2994 container_const_reference<self_type> (it ()), it_ (it.it_) {}
2998 const_iterator2 &operator ++ () {
3003 const_iterator2 &operator -- () {
3008 const_iterator2 &operator += (difference_type n) {
3013 const_iterator2 &operator -= (difference_type n) {
3018 difference_type operator - (const const_iterator2 &it) const {
3019 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3020 return it_ - it.it_;
3025 const_reference operator * () const {
3029 const_reference operator [] (difference_type n) const {
3030 return *(*this + n);
3033 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3035 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3036 typename self_type::
3038 const_iterator1 begin () const {
3039 const self_type &mr = (*this) ();
3040 return mr.find1 (1, 0, index2 ());
3043 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3044 typename self_type::
3046 const_iterator1 cbegin () const {
3050 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3051 typename self_type::
3053 const_iterator1 end () const {
3054 const self_type &mr = (*this) ();
3055 return mr.find1 (1, mr.size1 (), index2 ());
3058 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3059 typename self_type::
3061 const_iterator1 cend () const {
3065 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3066 typename self_type::
3068 const_reverse_iterator1 rbegin () const {
3069 return const_reverse_iterator1 (end ());
3072 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3073 typename self_type::
3075 const_reverse_iterator1 crbegin () const {
3079 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3080 typename self_type::
3082 const_reverse_iterator1 rend () const {
3083 return const_reverse_iterator1 (begin ());
3086 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3087 typename self_type::
3089 const_reverse_iterator1 crend () const {
3096 size_type index1 () const {
3097 return it_.index1 () - (*this) ().start1 ();
3100 size_type index2 () const {
3101 return it_.index2 () - (*this) ().start2 ();
3106 const_iterator2 &operator = (const const_iterator2 &it) {
3107 container_const_reference<self_type>::assign (&it ());
3114 bool operator == (const const_iterator2 &it) const {
3115 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3116 return it_ == it.it_;
3119 bool operator < (const const_iterator2 &it) const {
3120 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3121 return it_ < it.it_;
3125 const_subiterator2_type it_;
3130 const_iterator2 begin2 () const {
3131 return find2 (0, 0, 0);
3134 const_iterator2 cbegin2 () const {
3138 const_iterator2 end2 () const {
3139 return find2 (0, 0, size2 ());
3142 const_iterator2 cend2 () const {
3146 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3148 public container_reference<matrix_range>,
3149 public iterator_base_traits<typename subiterator2_type::iterator_category>::template
3150 iterator_base<iterator2, value_type>::type {
3152 typedef typename subiterator2_type::value_type value_type;
3153 typedef typename subiterator2_type::difference_type difference_type;
3154 typedef typename subiterator2_type::reference reference;
3155 typedef typename subiterator2_type::pointer pointer;
3156 typedef iterator1 dual_iterator_type;
3157 typedef reverse_iterator1 dual_reverse_iterator_type;
3159 // Construction and destruction
3162 container_reference<self_type> (), it_ () {}
3164 iterator2 (self_type &mr, const subiterator2_type &it):
3165 container_reference<self_type> (mr), it_ (it) {}
3169 iterator2 &operator ++ () {
3174 iterator2 &operator -- () {
3179 iterator2 &operator += (difference_type n) {
3184 iterator2 &operator -= (difference_type n) {
3189 difference_type operator - (const iterator2 &it) const {
3190 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3191 return it_ - it.it_;
3196 reference operator * () const {
3200 reference operator [] (difference_type n) const {
3201 return *(*this + n);
3204 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3206 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3207 typename self_type::
3209 iterator1 begin () const {
3210 self_type &mr = (*this) ();
3211 return mr.find1 (1, 0, index2 ());
3214 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3215 typename self_type::
3217 iterator1 end () const {
3218 self_type &mr = (*this) ();
3219 return mr.find1 (1, mr.size1 (), index2 ());
3222 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3223 typename self_type::
3225 reverse_iterator1 rbegin () const {
3226 return reverse_iterator1 (end ());
3229 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3230 typename self_type::
3232 reverse_iterator1 rend () const {
3233 return reverse_iterator1 (begin ());
3239 size_type index1 () const {
3240 return it_.index1 () - (*this) ().start1 ();
3243 size_type index2 () const {
3244 return it_.index2 () - (*this) ().start2 ();
3249 iterator2 &operator = (const iterator2 &it) {
3250 container_reference<self_type>::assign (&it ());
3257 bool operator == (const iterator2 &it) const {
3258 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3259 return it_ == it.it_;
3262 bool operator < (const iterator2 &it) const {
3263 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3264 return it_ < it.it_;
3268 subiterator2_type it_;
3270 friend class const_iterator2;
3275 iterator2 begin2 () {
3276 return find2 (0, 0, 0);
3280 return find2 (0, 0, size2 ());
3283 // Reverse iterators
3286 const_reverse_iterator1 rbegin1 () const {
3287 return const_reverse_iterator1 (end1 ());
3290 const_reverse_iterator1 crbegin1 () const {
3294 const_reverse_iterator1 rend1 () const {
3295 return const_reverse_iterator1 (begin1 ());
3298 const_reverse_iterator1 crend1 () const {
3303 reverse_iterator1 rbegin1 () {
3304 return reverse_iterator1 (end1 ());
3307 reverse_iterator1 rend1 () {
3308 return reverse_iterator1 (begin1 ());
3312 const_reverse_iterator2 rbegin2 () const {
3313 return const_reverse_iterator2 (end2 ());
3316 const_reverse_iterator2 crbegin2 () const {
3320 const_reverse_iterator2 rend2 () const {
3321 return const_reverse_iterator2 (begin2 ());
3324 const_reverse_iterator2 crend2 () const {
3329 reverse_iterator2 rbegin2 () {
3330 return reverse_iterator2 (end2 ());
3333 reverse_iterator2 rend2 () {
3334 return reverse_iterator2 (begin2 ());
3338 matrix_closure_type data_;
3343 // Simple Projections
3346 matrix_range<M> subrange (M &data, typename M::size_type start1, typename M::size_type stop1, typename M::size_type start2, typename M::size_type stop2) {
3347 typedef basic_range<typename M::size_type, typename M::difference_type> range_type;
3348 return matrix_range<M> (data, range_type (start1, stop1), range_type (start2, stop2));
3352 matrix_range<const M> subrange (const M &data, typename M::size_type start1, typename M::size_type stop1, typename M::size_type start2, typename M::size_type stop2) {
3353 typedef basic_range<typename M::size_type, typename M::difference_type> range_type;
3354 return matrix_range<const M> (data, range_type (start1, stop1), range_type (start2, stop2));
3357 // Generic Projections
3360 matrix_range<M> project (M &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
3361 return matrix_range<M> (data, r1, r2);
3365 const matrix_range<const M> project (const M &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
3366 // ISSUE was: return matrix_range<M> (const_cast<M &> (data), r1, r2);
3367 return matrix_range<const M> (data, r1, r2);
3371 matrix_range<M> project (matrix_range<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
3372 return data.project (r1, r2);
3376 const matrix_range<M> project (const matrix_range<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
3377 return data.project (r1, r2);
3380 // Specialization of temporary_traits
3382 struct matrix_temporary_traits< matrix_range<M> >
3383 : matrix_temporary_traits< M > {} ;
3385 struct matrix_temporary_traits< const matrix_range<M> >
3386 : matrix_temporary_traits< M > {} ;
3389 struct vector_temporary_traits< matrix_range<M> >
3390 : vector_temporary_traits< M > {} ;
3392 struct vector_temporary_traits< const matrix_range<M> >
3393 : vector_temporary_traits< M > {} ;
3395 // Matrix based slice class
3398 public matrix_expression<matrix_slice<M> > {
3400 typedef matrix_slice<M> self_type;
3402 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
3403 using matrix_expression<self_type>::operator ();
3405 typedef M matrix_type;
3406 typedef typename M::size_type size_type;
3407 typedef typename M::difference_type difference_type;
3408 typedef typename M::value_type value_type;
3409 typedef typename M::const_reference const_reference;
3410 typedef typename boost::mpl::if_<boost::is_const<M>,
3411 typename M::const_reference,
3412 typename M::reference>::type reference;
3413 typedef typename boost::mpl::if_<boost::is_const<M>,
3414 typename M::const_closure_type,
3415 typename M::closure_type>::type matrix_closure_type;
3416 typedef basic_range<size_type, difference_type> range_type;
3417 typedef basic_slice<size_type, difference_type> slice_type;
3418 typedef const self_type const_closure_type;
3419 typedef self_type closure_type;
3420 typedef typename storage_restrict_traits<typename M::storage_category,
3421 dense_proxy_tag>::storage_category storage_category;
3422 typedef typename M::orientation_category orientation_category;
3424 // Construction and destruction
3426 matrix_slice (matrix_type &data, const slice_type &s1, const slice_type &s2):
3427 data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {
3428 // Early checking of preconditions here.
3429 // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
3430 // s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
3431 // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
3432 // s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
3435 matrix_slice (const matrix_closure_type &data, const slice_type &s1, const slice_type &s2, int):
3436 data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {
3437 // Early checking of preconditions.
3438 // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
3439 // s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
3440 // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
3441 // s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
3446 size_type start1 () const {
3447 return s1_.start ();
3450 size_type start2 () const {
3451 return s2_.start ();
3454 difference_type stride1 () const {
3455 return s1_.stride ();
3458 difference_type stride2 () const {
3459 return s2_.stride ();
3462 size_type size1 () const {
3466 size_type size2 () const {
3470 // Storage accessors
3472 const matrix_closure_type &data () const {
3476 matrix_closure_type &data () {
3481 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
3483 const_reference operator () (size_type i, size_type j) const {
3484 return data_ (s1_ (i), s2_ (j));
3487 reference operator () (size_type i, size_type j) {
3488 return data_ (s1_ (i), s2_ (j));
3492 reference operator () (size_type i, size_type j) const {
3493 return data_ (s1_ (i), s2_ (j));
3497 // ISSUE can this be done in free project function?
3498 // Although a const function can create a non-const proxy to a non-const object
3499 // Critical is that matrix_type and data_ (vector_closure_type) are const correct
3501 matrix_slice<matrix_type> project (const range_type &r1, const range_type &r2) const {
3502 return matrix_slice<matrix_type> (data_, s1_.compose (r1.preprocess (data_.size1 ())), s2_.compose (r2.preprocess (data_.size2 ())), 0);
3505 matrix_slice<matrix_type> project (const slice_type &s1, const slice_type &s2) const {
3506 return matrix_slice<matrix_type> (data_, s1_.compose (s1.preprocess (data_.size1 ())), s2_.compose (s2.preprocess (data_.size2 ())), 0);
3511 matrix_slice &operator = (const matrix_slice &ms) {
3512 matrix_assign<scalar_assign> (*this, ms);
3516 matrix_slice &assign_temporary (matrix_slice &ms) {
3521 matrix_slice &operator = (const matrix_expression<AE> &ae) {
3522 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae));
3527 matrix_slice &assign (const matrix_expression<AE> &ae) {
3528 matrix_assign<scalar_assign> (*this, ae);
3533 matrix_slice& operator += (const matrix_expression<AE> &ae) {
3534 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae));
3539 matrix_slice &plus_assign (const matrix_expression<AE> &ae) {
3540 matrix_assign<scalar_plus_assign> (*this, ae);
3545 matrix_slice& operator -= (const matrix_expression<AE> &ae) {
3546 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae));
3551 matrix_slice &minus_assign (const matrix_expression<AE> &ae) {
3552 matrix_assign<scalar_minus_assign> (*this, ae);
3557 matrix_slice& operator *= (const AT &at) {
3558 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
3563 matrix_slice& operator /= (const AT &at) {
3564 matrix_assign_scalar<scalar_divides_assign> (*this, at);
3568 // Closure comparison
3570 bool same_closure (const matrix_slice &ms) const {
3571 return (*this).data_.same_closure (ms.data_);
3576 bool operator == (const matrix_slice &ms) const {
3577 return (*this).data_ == ms.data_ && s1_ == ms.s1_ && s2_ == ms.s2_;
3582 void swap (matrix_slice ms) {
3584 BOOST_UBLAS_CHECK (size1 () == ms.size1 (), bad_size ());
3585 BOOST_UBLAS_CHECK (size2 () == ms.size2 (), bad_size ());
3586 matrix_swap<scalar_swap> (*this, ms);
3590 friend void swap (matrix_slice ms1, matrix_slice ms2) {
3596 // Use slice as an index - FIXME this fails for packed assignment
3597 typedef typename slice_type::const_iterator const_subiterator1_type;
3598 typedef typename slice_type::const_iterator subiterator1_type;
3599 typedef typename slice_type::const_iterator const_subiterator2_type;
3600 typedef typename slice_type::const_iterator subiterator2_type;
3603 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3604 typedef indexed_iterator1<matrix_slice<matrix_type>,
3605 typename matrix_type::iterator1::iterator_category> iterator1;
3606 typedef indexed_iterator2<matrix_slice<matrix_type>,
3607 typename matrix_type::iterator2::iterator_category> iterator2;
3608 typedef indexed_const_iterator1<matrix_slice<matrix_type>,
3609 typename matrix_type::const_iterator1::iterator_category> const_iterator1;
3610 typedef indexed_const_iterator2<matrix_slice<matrix_type>,
3611 typename matrix_type::const_iterator2::iterator_category> const_iterator2;
3613 class const_iterator1;
3615 class const_iterator2;
3618 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
3619 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
3620 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
3621 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
3625 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
3626 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3627 return const_iterator1 (*this, i, j);
3629 return const_iterator1 (*this, s1_.begin () + i, s2_.begin () + j);
3633 iterator1 find1 (int /* rank */, size_type i, size_type j) {
3634 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3635 return iterator1 (*this, i, j);
3637 return iterator1 (*this, s1_.begin () + i, s2_.begin () + j);
3641 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
3642 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3643 return const_iterator2 (*this, i, j);
3645 return const_iterator2 (*this, s1_.begin () + i, s2_.begin () + j);
3649 iterator2 find2 (int /* rank */, size_type i, size_type j) {
3650 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3651 return iterator2 (*this, i, j);
3653 return iterator2 (*this, s1_.begin () + i, s2_.begin () + j);
3657 // Iterators simply are indices.
3659 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3660 class const_iterator1:
3661 public container_const_reference<matrix_slice>,
3662 public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
3663 iterator_base<const_iterator1, value_type>::type {
3665 typedef typename M::const_iterator1::value_type value_type;
3666 typedef typename M::const_iterator1::difference_type difference_type;
3667 typedef typename M::const_reference reference; //FIXME due to indexing access
3668 typedef typename M::const_iterator1::pointer pointer;
3669 typedef const_iterator2 dual_iterator_type;
3670 typedef const_reverse_iterator2 dual_reverse_iterator_type;
3672 // Construction and destruction
3675 container_const_reference<self_type> (), it1_ (), it2_ () {}
3677 const_iterator1 (const self_type &ms, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
3678 container_const_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
3680 const_iterator1 (const iterator1 &it):
3681 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
3685 const_iterator1 &operator ++ () {
3690 const_iterator1 &operator -- () {
3695 const_iterator1 &operator += (difference_type n) {
3700 const_iterator1 &operator -= (difference_type n) {
3705 difference_type operator - (const const_iterator1 &it) const {
3706 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3707 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3708 return it1_ - it.it1_;
3713 const_reference operator * () const {
3714 // FIXME replace find with at_element
3715 return (*this) ().data_ (*it1_, *it2_);
3718 const_reference operator [] (difference_type n) const {
3719 return *(*this + n);
3722 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3724 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3725 typename self_type::
3727 const_iterator2 begin () const {
3728 return const_iterator2 ((*this) (), it1_, it2_ ().begin ());
3731 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3732 typename self_type::
3734 const_iterator2 cbegin () const {
3738 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3739 typename self_type::
3741 const_iterator2 end () const {
3742 return const_iterator2 ((*this) (), it1_, it2_ ().end ());
3745 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3746 typename self_type::
3748 const_iterator2 cend () const {
3752 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3753 typename self_type::
3755 const_reverse_iterator2 rbegin () const {
3756 return const_reverse_iterator2 (end ());
3759 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3760 typename self_type::
3762 const_reverse_iterator2 crbegin () const {
3766 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3767 typename self_type::
3769 const_reverse_iterator2 rend () const {
3770 return const_reverse_iterator2 (begin ());
3773 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3774 typename self_type::
3776 const_reverse_iterator2 crend () const {
3783 size_type index1 () const {
3784 return it1_.index ();
3787 size_type index2 () const {
3788 return it2_.index ();
3793 const_iterator1 &operator = (const const_iterator1 &it) {
3794 container_const_reference<self_type>::assign (&it ());
3802 bool operator == (const const_iterator1 &it) const {
3803 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3804 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3805 return it1_ == it.it1_;
3808 bool operator < (const const_iterator1 &it) const {
3809 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3810 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3811 return it1_ < it.it1_;
3815 const_subiterator1_type it1_;
3816 const_subiterator2_type it2_;
3821 const_iterator1 begin1 () const {
3822 return find1 (0, 0, 0);
3825 const_iterator1 cbegin1 () const {
3829 const_iterator1 end1 () const {
3830 return find1 (0, size1 (), 0);
3833 const_iterator1 cend1 () const {
3837 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3839 public container_reference<matrix_slice>,
3840 public iterator_base_traits<typename M::iterator1::iterator_category>::template
3841 iterator_base<iterator1, value_type>::type {
3843 typedef typename M::iterator1::value_type value_type;
3844 typedef typename M::iterator1::difference_type difference_type;
3845 typedef typename M::reference reference; //FIXME due to indexing access
3846 typedef typename M::iterator1::pointer pointer;
3847 typedef iterator2 dual_iterator_type;
3848 typedef reverse_iterator2 dual_reverse_iterator_type;
3850 // Construction and destruction
3853 container_reference<self_type> (), it1_ (), it2_ () {}
3855 iterator1 (self_type &ms, const subiterator1_type &it1, const subiterator2_type &it2):
3856 container_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
3860 iterator1 &operator ++ () {
3865 iterator1 &operator -- () {
3870 iterator1 &operator += (difference_type n) {
3875 iterator1 &operator -= (difference_type n) {
3880 difference_type operator - (const iterator1 &it) const {
3881 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3882 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3883 return it1_ - it.it1_;
3888 reference operator * () const {
3889 // FIXME replace find with at_element
3890 return (*this) ().data_ (*it1_, *it2_);
3893 reference operator [] (difference_type n) const {
3894 return *(*this + n);
3897 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3899 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3900 typename self_type::
3902 iterator2 begin () const {
3903 return iterator2 ((*this) (), it1_, it2_ ().begin ());
3906 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3907 typename self_type::
3909 iterator2 end () const {
3910 return iterator2 ((*this) (), it1_, it2_ ().end ());
3913 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3914 typename self_type::
3916 reverse_iterator2 rbegin () const {
3917 return reverse_iterator2 (end ());
3920 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3921 typename self_type::
3923 reverse_iterator2 rend () const {
3924 return reverse_iterator2 (begin ());
3930 size_type index1 () const {
3931 return it1_.index ();
3934 size_type index2 () const {
3935 return it2_.index ();
3940 iterator1 &operator = (const iterator1 &it) {
3941 container_reference<self_type>::assign (&it ());
3949 bool operator == (const iterator1 &it) const {
3950 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3951 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3952 return it1_ == it.it1_;
3955 bool operator < (const iterator1 &it) const {
3956 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3957 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3958 return it1_ < it.it1_;
3962 subiterator1_type it1_;
3963 subiterator2_type it2_;
3965 friend class const_iterator1;
3970 iterator1 begin1 () {
3971 return find1 (0, 0, 0);
3975 return find1 (0, size1 (), 0);
3978 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3979 class const_iterator2:
3980 public container_const_reference<matrix_slice>,
3981 public iterator_base_traits<typename M::const_iterator2::iterator_category>::template
3982 iterator_base<const_iterator2, value_type>::type {
3984 typedef typename M::const_iterator2::value_type value_type;
3985 typedef typename M::const_iterator2::difference_type difference_type;
3986 typedef typename M::const_reference reference; //FIXME due to indexing access
3987 typedef typename M::const_iterator2::pointer pointer;
3988 typedef const_iterator1 dual_iterator_type;
3989 typedef const_reverse_iterator1 dual_reverse_iterator_type;
3991 // Construction and destruction
3994 container_const_reference<self_type> (), it1_ (), it2_ () {}
3996 const_iterator2 (const self_type &ms, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
3997 container_const_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
3999 const_iterator2 (const iterator2 &it):
4000 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
4004 const_iterator2 &operator ++ () {
4009 const_iterator2 &operator -- () {
4014 const_iterator2 &operator += (difference_type n) {
4019 const_iterator2 &operator -= (difference_type n) {
4024 difference_type operator - (const const_iterator2 &it) const {
4025 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4026 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4027 return it2_ - it.it2_;
4032 const_reference operator * () const {
4033 // FIXME replace find with at_element
4034 return (*this) ().data_ (*it1_, *it2_);
4037 const_reference operator [] (difference_type n) const {
4038 return *(*this + n);
4041 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4043 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4044 typename self_type::
4046 const_iterator1 begin () const {
4047 return const_iterator1 ((*this) (), it1_ ().begin (), it2_);
4050 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4051 typename self_type::
4053 const_iterator1 cbegin () const {
4057 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4058 typename self_type::
4060 const_iterator1 end () const {
4061 return const_iterator1 ((*this) (), it1_ ().end (), it2_);
4064 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4065 typename self_type::
4067 const_iterator1 cend () const {
4071 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4072 typename self_type::
4074 const_reverse_iterator1 rbegin () const {
4075 return const_reverse_iterator1 (end ());
4078 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4079 typename self_type::
4081 const_reverse_iterator1 crbegin () const {
4085 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4086 typename self_type::
4088 const_reverse_iterator1 rend () const {
4089 return const_reverse_iterator1 (begin ());
4092 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4093 typename self_type::
4095 const_reverse_iterator1 crend () const {
4102 size_type index1 () const {
4103 return it1_.index ();
4106 size_type index2 () const {
4107 return it2_.index ();
4112 const_iterator2 &operator = (const const_iterator2 &it) {
4113 container_const_reference<self_type>::assign (&it ());
4121 bool operator == (const const_iterator2 &it) const {
4122 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4123 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4124 return it2_ == it.it2_;
4127 bool operator < (const const_iterator2 &it) const {
4128 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4129 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4130 return it2_ < it.it2_;
4134 const_subiterator1_type it1_;
4135 const_subiterator2_type it2_;
4140 const_iterator2 begin2 () const {
4141 return find2 (0, 0, 0);
4144 const_iterator2 cbegin2 () const {
4148 const_iterator2 end2 () const {
4149 return find2 (0, 0, size2 ());
4152 const_iterator2 cend2 () const {
4156 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4158 public container_reference<matrix_slice>,
4159 public iterator_base_traits<typename M::iterator2::iterator_category>::template
4160 iterator_base<iterator2, value_type>::type {
4162 typedef typename M::iterator2::value_type value_type;
4163 typedef typename M::iterator2::difference_type difference_type;
4164 typedef typename M::reference reference; //FIXME due to indexing access
4165 typedef typename M::iterator2::pointer pointer;
4166 typedef iterator1 dual_iterator_type;
4167 typedef reverse_iterator1 dual_reverse_iterator_type;
4169 // Construction and destruction
4172 container_reference<self_type> (), it1_ (), it2_ () {}
4174 iterator2 (self_type &ms, const subiterator1_type &it1, const subiterator2_type &it2):
4175 container_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
4179 iterator2 &operator ++ () {
4184 iterator2 &operator -- () {
4189 iterator2 &operator += (difference_type n) {
4194 iterator2 &operator -= (difference_type n) {
4199 difference_type operator - (const iterator2 &it) const {
4200 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4201 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4202 return it2_ - it.it2_;
4207 reference operator * () const {
4208 // FIXME replace find with at_element
4209 return (*this) ().data_ (*it1_, *it2_);
4212 reference operator [] (difference_type n) const {
4213 return *(*this + n);
4216 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4218 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4219 typename self_type::
4221 iterator1 begin () const {
4222 return iterator1 ((*this) (), it1_ ().begin (), it2_);
4225 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4226 typename self_type::
4228 iterator1 end () const {
4229 return iterator1 ((*this) (), it1_ ().end (), it2_);
4232 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4233 typename self_type::
4235 reverse_iterator1 rbegin () const {
4236 return reverse_iterator1 (end ());
4239 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4240 typename self_type::
4242 reverse_iterator1 rend () const {
4243 return reverse_iterator1 (begin ());
4249 size_type index1 () const {
4250 return it1_.index ();
4253 size_type index2 () const {
4254 return it2_.index ();
4259 iterator2 &operator = (const iterator2 &it) {
4260 container_reference<self_type>::assign (&it ());
4268 bool operator == (const iterator2 &it) const {
4269 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4270 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4271 return it2_ == it.it2_;
4274 bool operator < (const iterator2 &it) const {
4275 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4276 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4277 return it2_ < it.it2_;
4281 subiterator1_type it1_;
4282 subiterator2_type it2_;
4284 friend class const_iterator2;
4289 iterator2 begin2 () {
4290 return find2 (0, 0, 0);
4294 return find2 (0, 0, size2 ());
4297 // Reverse iterators
4300 const_reverse_iterator1 rbegin1 () const {
4301 return const_reverse_iterator1 (end1 ());
4304 const_reverse_iterator1 crbegin1 () const {
4308 const_reverse_iterator1 rend1 () const {
4309 return const_reverse_iterator1 (begin1 ());
4312 const_reverse_iterator1 crend1 () const {
4317 reverse_iterator1 rbegin1 () {
4318 return reverse_iterator1 (end1 ());
4321 reverse_iterator1 rend1 () {
4322 return reverse_iterator1 (begin1 ());
4326 const_reverse_iterator2 rbegin2 () const {
4327 return const_reverse_iterator2 (end2 ());
4330 const_reverse_iterator2 crbegin2 () const {
4334 const_reverse_iterator2 rend2 () const {
4335 return const_reverse_iterator2 (begin2 ());
4338 const_reverse_iterator2 crend2 () const {
4343 reverse_iterator2 rbegin2 () {
4344 return reverse_iterator2 (end2 ());
4347 reverse_iterator2 rend2 () {
4348 return reverse_iterator2 (begin2 ());
4352 matrix_closure_type data_;
4357 // Simple Projections
4360 matrix_slice<M> subslice (M &data, typename M::size_type start1, typename M::difference_type stride1, typename M::size_type size1, typename M::size_type start2, typename M::difference_type stride2, typename M::size_type size2) {
4361 typedef basic_slice<typename M::size_type, typename M::difference_type> slice_type;
4362 return matrix_slice<M> (data, slice_type (start1, stride1, size1), slice_type (start2, stride2, size2));
4366 matrix_slice<const M> subslice (const M &data, typename M::size_type start1, typename M::difference_type stride1, typename M::size_type size1, typename M::size_type start2, typename M::difference_type stride2, typename M::size_type size2) {
4367 typedef basic_slice<typename M::size_type, typename M::difference_type> slice_type;
4368 return matrix_slice<const M> (data, slice_type (start1, stride1, size1), slice_type (start2, stride2, size2));
4371 // Generic Projections
4374 matrix_slice<M> project (M &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
4375 return matrix_slice<M> (data, s1, s2);
4379 const matrix_slice<const M> project (const M &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
4380 // ISSUE was: return matrix_slice<M> (const_cast<M &> (data), s1, s2);
4381 return matrix_slice<const M> (data, s1, s2);
4383 // ISSUE in the following two functions it would be logical to use matrix_slice<V>::range_type but this confuses VC7.1 and 8.0
4386 matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
4387 return data.project (r1, r2);
4391 const matrix_slice<M> project (const matrix_slice<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
4392 return data.project (r1, r2);
4396 matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
4397 return data.project (s1, s2);
4401 const matrix_slice<M> project (const matrix_slice<M> &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
4402 return data.project (s1, s2);
4405 // Specialization of temporary_traits
4407 struct matrix_temporary_traits< matrix_slice<M> >
4408 : matrix_temporary_traits< M > {};
4410 struct matrix_temporary_traits< const matrix_slice<M> >
4411 : matrix_temporary_traits< M > {};
4414 struct vector_temporary_traits< matrix_slice<M> >
4415 : vector_temporary_traits< M > {};
4417 struct vector_temporary_traits< const matrix_slice<M> >
4418 : vector_temporary_traits< M > {};
4420 // Matrix based indirection class
4421 // Contributed by Toon Knapen.
4422 // Extended and optimized by Kresimir Fresl.
4423 /** \brief A matrix referencing a non continuous submatrix of elements given another matrix of indices.
4425 * It is the most general version of any submatrices because it uses another matrix of indices to reference
4428 * The matrix of indices can be of any type with the restriction that its elements must be
4429 * type-compatible with the size_type \c of the container. In practice, the following are good candidates:
4430 * - \c boost::numeric::ublas::indirect_array<A> where \c A can be \c int, \c size_t, \c long, etc...
4431 * - \c boost::numeric::ublas::matrix<int> can work too (\c int can be replaced by another integer type)
4434 * An indirect matrix can be used as a normal matrix in any expression. If the specified indirect matrix
4435 * falls outside that of the indices of the matrix, then the \c matrix_indirect is not a well formed
4436 * \i Matrix \i Expression and access to an element outside of indices of the matrix is \b undefined.
4438 * \tparam V the type of the referenced matrix, for example \c matrix<double>)
4439 * \tparam IA the type of index matrix. Default is \c ublas::indirect_array<>
4441 template<class M, class IA>
4442 class matrix_indirect:
4443 public matrix_expression<matrix_indirect<M, IA> > {
4445 typedef matrix_indirect<M, IA> self_type;
4447 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4448 using matrix_expression<self_type>::operator ();
4450 typedef M matrix_type;
4451 typedef IA indirect_array_type;
4452 typedef typename M::size_type size_type;
4453 typedef typename M::difference_type difference_type;
4454 typedef typename M::value_type value_type;
4455 typedef typename M::const_reference const_reference;
4456 typedef typename boost::mpl::if_<boost::is_const<M>,
4457 typename M::const_reference,
4458 typename M::reference>::type reference;
4459 typedef typename boost::mpl::if_<boost::is_const<M>,
4460 typename M::const_closure_type,
4461 typename M::closure_type>::type matrix_closure_type;
4462 typedef basic_range<size_type, difference_type> range_type;
4463 typedef basic_slice<size_type, difference_type> slice_type;
4464 typedef const self_type const_closure_type;
4465 typedef self_type closure_type;
4466 typedef typename storage_restrict_traits<typename M::storage_category,
4467 dense_proxy_tag>::storage_category storage_category;
4468 typedef typename M::orientation_category orientation_category;
4470 // Construction and destruction
4472 matrix_indirect (matrix_type &data, size_type size1, size_type size2):
4473 data_ (data), ia1_ (size1), ia2_ (size2) {}
4475 matrix_indirect (matrix_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2):
4476 data_ (data), ia1_ (ia1.preprocess (data.size1 ())), ia2_ (ia2.preprocess (data.size2 ())) {}
4478 matrix_indirect (const matrix_closure_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2, int):
4479 data_ (data), ia1_ (ia1.preprocess (data.size1 ())), ia2_ (ia2.preprocess (data.size2 ())) {}
4483 size_type size1 () const {
4484 return ia1_.size ();
4487 size_type size2 () const {
4488 return ia2_.size ();
4491 const indirect_array_type &indirect1 () const {
4495 indirect_array_type &indirect1 () {
4499 const indirect_array_type &indirect2 () const {
4503 indirect_array_type &indirect2 () {
4507 // Storage accessors
4509 const matrix_closure_type &data () const {
4513 matrix_closure_type &data () {
4518 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
4520 const_reference operator () (size_type i, size_type j) const {
4521 return data_ (ia1_ (i), ia2_ (j));
4524 reference operator () (size_type i, size_type j) {
4525 return data_ (ia1_ (i), ia2_ (j));
4529 reference operator () (size_type i, size_type j) const {
4530 return data_ (ia1_ (i), ia2_ (j));
4534 // ISSUE can this be done in free project function?
4535 // Although a const function can create a non-const proxy to a non-const object
4536 // Critical is that matrix_type and data_ (vector_closure_type) are const correct
4538 matrix_indirect<matrix_type, indirect_array_type> project (const range_type &r1, const range_type &r2) const {
4539 return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (r1.preprocess (data_.size1 ())), ia2_.compose (r2.preprocess (data_.size2 ())), 0);
4542 matrix_indirect<matrix_type, indirect_array_type> project (const slice_type &s1, const slice_type &s2) const {
4543 return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (s1.preprocess (data_.size1 ())), ia2_.compose (s2.preprocess (data_.size2 ())), 0);
4546 matrix_indirect<matrix_type, indirect_array_type> project (const indirect_array_type &ia1, const indirect_array_type &ia2) const {
4547 return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (ia1.preprocess (data_.size1 ())), ia2_.compose (ia2.preprocess (data_.size2 ())), 0);
4552 matrix_indirect &operator = (const matrix_indirect &mi) {
4553 matrix_assign<scalar_assign> (*this, mi);
4557 matrix_indirect &assign_temporary (matrix_indirect &mi) {
4562 matrix_indirect &operator = (const matrix_expression<AE> &ae) {
4563 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae));
4568 matrix_indirect &assign (const matrix_expression<AE> &ae) {
4569 matrix_assign<scalar_assign> (*this, ae);
4574 matrix_indirect& operator += (const matrix_expression<AE> &ae) {
4575 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae));
4580 matrix_indirect &plus_assign (const matrix_expression<AE> &ae) {
4581 matrix_assign<scalar_plus_assign> (*this, ae);
4586 matrix_indirect& operator -= (const matrix_expression<AE> &ae) {
4587 matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae));
4592 matrix_indirect &minus_assign (const matrix_expression<AE> &ae) {
4593 matrix_assign<scalar_minus_assign> (*this, ae);
4598 matrix_indirect& operator *= (const AT &at) {
4599 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
4604 matrix_indirect& operator /= (const AT &at) {
4605 matrix_assign_scalar<scalar_divides_assign> (*this, at);
4609 // Closure comparison
4611 bool same_closure (const matrix_indirect &mi) const {
4612 return (*this).data_.same_closure (mi.data_);
4617 bool operator == (const matrix_indirect &mi) const {
4618 return (*this).data_ == mi.data_ && ia1_ == mi.ia1_ && ia2_ == mi.ia2_;
4623 void swap (matrix_indirect mi) {
4625 BOOST_UBLAS_CHECK (size1 () == mi.size1 (), bad_size ());
4626 BOOST_UBLAS_CHECK (size2 () == mi.size2 (), bad_size ());
4627 matrix_swap<scalar_swap> (*this, mi);
4631 friend void swap (matrix_indirect mi1, matrix_indirect mi2) {
4637 typedef typename IA::const_iterator const_subiterator1_type;
4638 typedef typename IA::const_iterator subiterator1_type;
4639 typedef typename IA::const_iterator const_subiterator2_type;
4640 typedef typename IA::const_iterator subiterator2_type;
4643 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4644 typedef indexed_iterator1<matrix_indirect<matrix_type, indirect_array_type>,
4645 typename matrix_type::iterator1::iterator_category> iterator1;
4646 typedef indexed_iterator2<matrix_indirect<matrix_type, indirect_array_type>,
4647 typename matrix_type::iterator2::iterator_category> iterator2;
4648 typedef indexed_const_iterator1<matrix_indirect<matrix_type, indirect_array_type>,
4649 typename matrix_type::const_iterator1::iterator_category> const_iterator1;
4650 typedef indexed_const_iterator2<matrix_indirect<matrix_type, indirect_array_type>,
4651 typename matrix_type::const_iterator2::iterator_category> const_iterator2;
4653 class const_iterator1;
4655 class const_iterator2;
4658 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
4659 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
4660 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
4661 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
4665 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
4666 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4667 return const_iterator1 (*this, i, j);
4669 return const_iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j);
4673 iterator1 find1 (int /* rank */, size_type i, size_type j) {
4674 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4675 return iterator1 (*this, i, j);
4677 return iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j);
4681 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
4682 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4683 return const_iterator2 (*this, i, j);
4685 return const_iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j);
4689 iterator2 find2 (int /* rank */, size_type i, size_type j) {
4690 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4691 return iterator2 (*this, i, j);
4693 return iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j);
4697 // Iterators simply are indices.
4699 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4700 class const_iterator1:
4701 public container_const_reference<matrix_indirect>,
4702 public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
4703 iterator_base<const_iterator1, value_type>::type {
4705 typedef typename M::const_iterator1::value_type value_type;
4706 typedef typename M::const_iterator1::difference_type difference_type;
4707 typedef typename M::const_reference reference; //FIXME due to indexing access
4708 typedef typename M::const_iterator1::pointer pointer;
4709 typedef const_iterator2 dual_iterator_type;
4710 typedef const_reverse_iterator2 dual_reverse_iterator_type;
4712 // Construction and destruction
4715 container_const_reference<self_type> (), it1_ (), it2_ () {}
4717 const_iterator1 (const self_type &mi, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
4718 container_const_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
4720 const_iterator1 (const iterator1 &it):
4721 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
4725 const_iterator1 &operator ++ () {
4730 const_iterator1 &operator -- () {
4735 const_iterator1 &operator += (difference_type n) {
4740 const_iterator1 &operator -= (difference_type n) {
4745 difference_type operator - (const const_iterator1 &it) const {
4746 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4747 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4748 return it1_ - it.it1_;
4753 const_reference operator * () const {
4754 // FIXME replace find with at_element
4755 return (*this) ().data_ (*it1_, *it2_);
4758 const_reference operator [] (difference_type n) const {
4759 return *(*this + n);
4762 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4764 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4765 typename self_type::
4767 const_iterator2 begin () const {
4768 return const_iterator2 ((*this) (), it1_, it2_ ().begin ());
4771 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4772 typename self_type::
4774 const_iterator2 cbegin () const {
4778 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4779 typename self_type::
4781 const_iterator2 end () const {
4782 return const_iterator2 ((*this) (), it1_, it2_ ().end ());
4785 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4786 typename self_type::
4788 const_iterator2 cend () const {
4792 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4793 typename self_type::
4795 const_reverse_iterator2 rbegin () const {
4796 return const_reverse_iterator2 (end ());
4799 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4800 typename self_type::
4802 const_reverse_iterator2 crbegin () const {
4806 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4807 typename self_type::
4809 const_reverse_iterator2 rend () const {
4810 return const_reverse_iterator2 (begin ());
4813 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4814 typename self_type::
4816 const_reverse_iterator2 crend () const {
4823 size_type index1 () const {
4824 return it1_.index ();
4827 size_type index2 () const {
4828 return it2_.index ();
4833 const_iterator1 &operator = (const const_iterator1 &it) {
4834 container_const_reference<self_type>::assign (&it ());
4842 bool operator == (const const_iterator1 &it) const {
4843 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4844 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4845 return it1_ == it.it1_;
4848 bool operator < (const const_iterator1 &it) const {
4849 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4850 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4851 return it1_ < it.it1_;
4855 const_subiterator1_type it1_;
4856 const_subiterator2_type it2_;
4861 const_iterator1 begin1 () const {
4862 return find1 (0, 0, 0);
4865 const_iterator1 cbegin1 () const {
4869 const_iterator1 end1 () const {
4870 return find1 (0, size1 (), 0);
4873 const_iterator1 cend1 () const {
4877 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4879 public container_reference<matrix_indirect>,
4880 public iterator_base_traits<typename M::iterator1::iterator_category>::template
4881 iterator_base<iterator1, value_type>::type {
4883 typedef typename M::iterator1::value_type value_type;
4884 typedef typename M::iterator1::difference_type difference_type;
4885 typedef typename M::reference reference; //FIXME due to indexing access
4886 typedef typename M::iterator1::pointer pointer;
4887 typedef iterator2 dual_iterator_type;
4888 typedef reverse_iterator2 dual_reverse_iterator_type;
4890 // Construction and destruction
4893 container_reference<self_type> (), it1_ (), it2_ () {}
4895 iterator1 (self_type &mi, const subiterator1_type &it1, const subiterator2_type &it2):
4896 container_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
4900 iterator1 &operator ++ () {
4905 iterator1 &operator -- () {
4910 iterator1 &operator += (difference_type n) {
4915 iterator1 &operator -= (difference_type n) {
4920 difference_type operator - (const iterator1 &it) const {
4921 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4922 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4923 return it1_ - it.it1_;
4928 reference operator * () const {
4929 // FIXME replace find with at_element
4930 return (*this) ().data_ (*it1_, *it2_);
4933 reference operator [] (difference_type n) const {
4934 return *(*this + n);
4937 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4939 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4940 typename self_type::
4942 iterator2 begin () const {
4943 return iterator2 ((*this) (), it1_, it2_ ().begin ());
4946 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4947 typename self_type::
4949 iterator2 end () const {
4950 return iterator2 ((*this) (), it1_, it2_ ().end ());
4953 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4954 typename self_type::
4956 reverse_iterator2 rbegin () const {
4957 return reverse_iterator2 (end ());
4960 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4961 typename self_type::
4963 reverse_iterator2 rend () const {
4964 return reverse_iterator2 (begin ());
4970 size_type index1 () const {
4971 return it1_.index ();
4974 size_type index2 () const {
4975 return it2_.index ();
4980 iterator1 &operator = (const iterator1 &it) {
4981 container_reference<self_type>::assign (&it ());
4989 bool operator == (const iterator1 &it) const {
4990 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4991 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4992 return it1_ == it.it1_;
4995 bool operator < (const iterator1 &it) const {
4996 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4997 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4998 return it1_ < it.it1_;
5002 subiterator1_type it1_;
5003 subiterator2_type it2_;
5005 friend class const_iterator1;
5010 iterator1 begin1 () {
5011 return find1 (0, 0, 0);
5015 return find1 (0, size1 (), 0);
5018 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
5019 class const_iterator2:
5020 public container_const_reference<matrix_indirect>,
5021 public iterator_base_traits<typename M::const_iterator2::iterator_category>::template
5022 iterator_base<const_iterator2, value_type>::type {
5024 typedef typename M::const_iterator2::value_type value_type;
5025 typedef typename M::const_iterator2::difference_type difference_type;
5026 typedef typename M::const_reference reference; //FIXME due to indexing access
5027 typedef typename M::const_iterator2::pointer pointer;
5028 typedef const_iterator1 dual_iterator_type;
5029 typedef const_reverse_iterator1 dual_reverse_iterator_type;
5031 // Construction and destruction
5034 container_const_reference<self_type> (), it1_ (), it2_ () {}
5036 const_iterator2 (const self_type &mi, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
5037 container_const_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
5039 const_iterator2 (const iterator2 &it):
5040 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
5044 const_iterator2 &operator ++ () {
5049 const_iterator2 &operator -- () {
5054 const_iterator2 &operator += (difference_type n) {
5059 const_iterator2 &operator -= (difference_type n) {
5064 difference_type operator - (const const_iterator2 &it) const {
5065 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5066 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5067 return it2_ - it.it2_;
5072 const_reference operator * () const {
5073 // FIXME replace find with at_element
5074 return (*this) ().data_ (*it1_, *it2_);
5077 const_reference operator [] (difference_type n) const {
5078 return *(*this + n);
5081 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5083 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5084 typename self_type::
5086 const_iterator1 begin () const {
5087 return const_iterator1 ((*this) (), it1_ ().begin (), it2_);
5090 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5091 typename self_type::
5093 const_iterator1 cbegin () const {
5097 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5098 typename self_type::
5100 const_iterator1 end () const {
5101 return const_iterator1 ((*this) (), it1_ ().end (), it2_);
5104 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5105 typename self_type::
5107 const_iterator1 cend () const {
5111 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5112 typename self_type::
5114 const_reverse_iterator1 rbegin () const {
5115 return const_reverse_iterator1 (end ());
5118 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5119 typename self_type::
5121 const_reverse_iterator1 crbegin () const {
5125 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5126 typename self_type::
5128 const_reverse_iterator1 rend () const {
5129 return const_reverse_iterator1 (begin ());
5132 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5133 typename self_type::
5135 const_reverse_iterator1 crend () const {
5142 size_type index1 () const {
5143 return it1_.index ();
5146 size_type index2 () const {
5147 return it2_.index ();
5152 const_iterator2 &operator = (const const_iterator2 &it) {
5153 container_const_reference<self_type>::assign (&it ());
5161 bool operator == (const const_iterator2 &it) const {
5162 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5163 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5164 return it2_ == it.it2_;
5167 bool operator < (const const_iterator2 &it) const {
5168 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5169 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5170 return it2_ < it.it2_;
5174 const_subiterator1_type it1_;
5175 const_subiterator2_type it2_;
5180 const_iterator2 begin2 () const {
5181 return find2 (0, 0, 0);
5184 const_iterator2 cbegin2 () const {
5188 const_iterator2 end2 () const {
5189 return find2 (0, 0, size2 ());
5192 const_iterator2 cend2 () const {
5196 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
5198 public container_reference<matrix_indirect>,
5199 public iterator_base_traits<typename M::iterator2::iterator_category>::template
5200 iterator_base<iterator2, value_type>::type {
5202 typedef typename M::iterator2::value_type value_type;
5203 typedef typename M::iterator2::difference_type difference_type;
5204 typedef typename M::reference reference; //FIXME due to indexing access
5205 typedef typename M::iterator2::pointer pointer;
5206 typedef iterator1 dual_iterator_type;
5207 typedef reverse_iterator1 dual_reverse_iterator_type;
5209 // Construction and destruction
5212 container_reference<self_type> (), it1_ (), it2_ () {}
5214 iterator2 (self_type &mi, const subiterator1_type &it1, const subiterator2_type &it2):
5215 container_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
5219 iterator2 &operator ++ () {
5224 iterator2 &operator -- () {
5229 iterator2 &operator += (difference_type n) {
5234 iterator2 &operator -= (difference_type n) {
5239 difference_type operator - (const iterator2 &it) const {
5240 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5241 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5242 return it2_ - it.it2_;
5247 reference operator * () const {
5248 // FIXME replace find with at_element
5249 return (*this) ().data_ (*it1_, *it2_);
5252 reference operator [] (difference_type n) const {
5253 return *(*this + n);
5256 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5258 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5259 typename self_type::
5261 iterator1 begin () const {
5262 return iterator1 ((*this) (), it1_ ().begin (), it2_);
5265 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5266 typename self_type::
5268 iterator1 end () const {
5269 return iterator1 ((*this) (), it1_ ().end (), it2_);
5272 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5273 typename self_type::
5275 reverse_iterator1 rbegin () const {
5276 return reverse_iterator1 (end ());
5279 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5280 typename self_type::
5282 reverse_iterator1 rend () const {
5283 return reverse_iterator1 (begin ());
5289 size_type index1 () const {
5290 return it1_.index ();
5293 size_type index2 () const {
5294 return it2_.index ();
5299 iterator2 &operator = (const iterator2 &it) {
5300 container_reference<self_type>::assign (&it ());
5308 bool operator == (const iterator2 &it) const {
5309 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5310 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5311 return it2_ == it.it2_;
5314 bool operator < (const iterator2 &it) const {
5315 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5316 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5317 return it2_ < it.it2_;
5321 subiterator1_type it1_;
5322 subiterator2_type it2_;
5324 friend class const_iterator2;
5329 iterator2 begin2 () {
5330 return find2 (0, 0, 0);
5334 return find2 (0, 0, size2 ());
5337 // Reverse iterators
5340 const_reverse_iterator1 rbegin1 () const {
5341 return const_reverse_iterator1 (end1 ());
5344 const_reverse_iterator1 crbegin1 () const {
5348 const_reverse_iterator1 rend1 () const {
5349 return const_reverse_iterator1 (begin1 ());
5352 const_reverse_iterator1 crend1 () const {
5357 reverse_iterator1 rbegin1 () {
5358 return reverse_iterator1 (end1 ());
5361 reverse_iterator1 rend1 () {
5362 return reverse_iterator1 (begin1 ());
5366 const_reverse_iterator2 rbegin2 () const {
5367 return const_reverse_iterator2 (end2 ());
5370 const_reverse_iterator2 crbegin2 () const {
5374 const_reverse_iterator2 rend2 () const {
5375 return const_reverse_iterator2 (begin2 ());
5378 const_reverse_iterator2 crend2 () const {
5383 reverse_iterator2 rbegin2 () {
5384 return reverse_iterator2 (end2 ());
5387 reverse_iterator2 rend2 () {
5388 return reverse_iterator2 (begin2 ());
5392 matrix_closure_type data_;
5393 indirect_array_type ia1_;
5394 indirect_array_type ia2_;
5398 template<class M, class A>
5400 matrix_indirect<M, indirect_array<A> > project (M &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
5401 return matrix_indirect<M, indirect_array<A> > (data, ia1, ia2);
5403 template<class M, class A>
5405 const matrix_indirect<const M, indirect_array<A> > project (const M &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
5406 // ISSUE was: return matrix_indirect<M, indirect_array<A> > (const_cast<M &> (data), ia1, ia2);
5407 return matrix_indirect<const M, indirect_array<A> > (data, ia1, ia2);
5409 template<class M, class IA>
5411 matrix_indirect<M, IA> project (matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::range_type &r1, const typename matrix_indirect<M, IA>::range_type &r2) {
5412 return data.project (r1, r2);
5414 template<class M, class IA>
5416 const matrix_indirect<M, IA> project (const matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::range_type &r1, const typename matrix_indirect<M, IA>::range_type &r2) {
5417 return data.project (r1, r2);
5419 template<class M, class IA>
5421 matrix_indirect<M, IA> project (matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::slice_type &s1, const typename matrix_indirect<M, IA>::slice_type &s2) {
5422 return data.project (s1, s2);
5424 template<class M, class IA>
5426 const matrix_indirect<M, IA> project (const matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::slice_type &s1, const typename matrix_indirect<M, IA>::slice_type &s2) {
5427 return data.project (s1, s2);
5429 template<class M, class A>
5431 matrix_indirect<M, indirect_array<A> > project (matrix_indirect<M, indirect_array<A> > &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
5432 return data.project (ia1, ia2);
5434 template<class M, class A>
5436 const matrix_indirect<M, indirect_array<A> > project (const matrix_indirect<M, indirect_array<A> > &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
5437 return data.project (ia1, ia2);
5440 /// Specialization of temporary_traits
5442 struct matrix_temporary_traits< matrix_indirect<M> >
5443 : matrix_temporary_traits< M > {};
5445 struct matrix_temporary_traits< const matrix_indirect<M> >
5446 : matrix_temporary_traits< M > {};
5449 struct vector_temporary_traits< matrix_indirect<M> >
5450 : vector_temporary_traits< M > {};
5452 struct vector_temporary_traits< const matrix_indirect<M> >
5453 : vector_temporary_traits< M > {};