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
{
25 // Matrix based row vector class
28 public vector_expression
<matrix_row
<M
> > {
30 typedef matrix_row
<M
> self_type
;
32 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
33 using vector_expression
<self_type
>::operator ();
35 typedef M matrix_type
;
36 typedef typename
M::size_type size_type
;
37 typedef typename
M::difference_type difference_type
;
38 typedef typename
M::value_type value_type
;
39 typedef typename
M::const_reference const_reference
;
40 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
41 typename
M::const_reference
,
42 typename
M::reference
>::type reference
;
43 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
44 typename
M::const_closure_type
,
45 typename
M::closure_type
>::type matrix_closure_type
;
46 typedef const self_type const_closure_type
;
47 typedef self_type closure_type
;
48 typedef typename storage_restrict_traits
<typename
M::storage_category
,
49 dense_proxy_tag
>::storage_category storage_category
;
51 // Construction and destruction
53 matrix_row (matrix_type
&data
, size_type i
):
54 data_ (data
), i_ (i
) {
55 // Early checking of preconditions here.
56 // BOOST_UBLAS_CHECK (i_ < data_.size1 (), bad_index ());
61 size_type
size () const {
62 return data_
.size2 ();
65 size_type
index () const {
71 const matrix_closure_type
&data () const {
75 matrix_closure_type
&data () {
80 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
82 const_reference
operator () (size_type j
) const {
86 reference
operator () (size_type j
) {
91 const_reference
operator [] (size_type j
) const {
95 reference
operator [] (size_type j
) {
100 reference
operator () (size_type j
) const {
101 return data_ (i_
, j
);
105 reference
operator [] (size_type j
) const {
112 matrix_row
&operator = (const matrix_row
&mr
) {
113 // ISSUE need a temporary, proxy can be overlaping alias
114 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (mr
));
118 matrix_row
&assign_temporary (matrix_row
&mr
) {
119 // assign elements, proxied container remains the same
120 vector_assign
<scalar_assign
> (*this, mr
);
125 matrix_row
&operator = (const vector_expression
<AE
> &ae
) {
126 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (ae
));
131 matrix_row
&assign (const vector_expression
<AE
> &ae
) {
132 vector_assign
<scalar_assign
> (*this, ae
);
137 matrix_row
&operator += (const vector_expression
<AE
> &ae
) {
138 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (*this + ae
));
143 matrix_row
&plus_assign (const vector_expression
<AE
> &ae
) {
144 vector_assign
<scalar_plus_assign
> (*this, ae
);
149 matrix_row
&operator -= (const vector_expression
<AE
> &ae
) {
150 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (*this - ae
));
155 matrix_row
&minus_assign (const vector_expression
<AE
> &ae
) {
156 vector_assign
<scalar_minus_assign
> (*this, ae
);
161 matrix_row
&operator *= (const AT
&at
) {
162 vector_assign_scalar
<scalar_multiplies_assign
> (*this, at
);
167 matrix_row
&operator /= (const AT
&at
) {
168 vector_assign_scalar
<scalar_divides_assign
> (*this, at
);
172 // Closure comparison
174 bool same_closure (const matrix_row
&mr
) const {
175 return (*this).data_
.same_closure (mr
.data_
);
180 bool operator == (const matrix_row
&mr
) const {
181 return (*this).data_
== mr
.data_
&& index () == mr
.index ();
186 void swap (matrix_row mr
) {
188 BOOST_UBLAS_CHECK (size () == mr
.size (), bad_size ());
189 // Sparse ranges may be nonconformant now.
190 // std::swap_ranges (begin (), end (), mr.begin ());
191 vector_swap
<scalar_swap
> (*this, mr
);
195 friend void swap (matrix_row mr1
, matrix_row mr2
) {
201 typedef typename
M::const_iterator2 const_subiterator_type
;
202 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
203 typename
M::const_iterator2
,
204 typename
M::iterator2
>::type subiterator_type
;
207 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
208 typedef indexed_iterator
<matrix_row
<matrix_type
>,
209 typename
subiterator_type::iterator_category
> iterator
;
210 typedef indexed_const_iterator
<matrix_row
<matrix_type
>,
211 typename
const_subiterator_type::iterator_category
> const_iterator
;
213 class const_iterator
;
219 const_iterator
find (size_type j
) const {
220 const_subiterator_type
it2 (data_
.find2 (1, i_
, j
));
221 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
222 return const_iterator (*this, it2
.index2 ());
224 return const_iterator (*this, it2
);
228 iterator
find (size_type j
) {
229 subiterator_type
it2 (data_
.find2 (1, i_
, j
));
230 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
231 return iterator (*this, it2
.index2 ());
233 return iterator (*this, it2
);
237 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
238 class const_iterator
:
239 public container_const_reference
<matrix_row
>,
240 public iterator_base_traits
<typename
const_subiterator_type::iterator_category
>::template
241 iterator_base
<const_iterator
, value_type
>::type
{
243 typedef typename
const_subiterator_type::value_type value_type
;
244 typedef typename
const_subiterator_type::difference_type difference_type
;
245 typedef typename
const_subiterator_type::reference reference
;
246 typedef typename
const_subiterator_type::pointer pointer
;
248 // Construction and destruction
251 container_const_reference
<self_type
> (), it_ () {}
253 const_iterator (const self_type
&mr
, const const_subiterator_type
&it
):
254 container_const_reference
<self_type
> (mr
), it_ (it
) {}
256 const_iterator (const typename
self_type::iterator
&it
): // ISSUE self_type:: stops VC8 using std::iterator here
257 container_const_reference
<self_type
> (it ()), it_ (it
.it_
) {}
261 const_iterator
&operator ++ () {
266 const_iterator
&operator -- () {
271 const_iterator
&operator += (difference_type n
) {
276 const_iterator
&operator -= (difference_type n
) {
281 difference_type
operator - (const const_iterator
&it
) const {
282 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
288 const_reference
operator * () const {
289 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
293 const_reference
operator [] (difference_type n
) const {
299 size_type
index () const {
300 return it_
.index2 ();
305 const_iterator
&operator = (const const_iterator
&it
) {
306 container_const_reference
<self_type
>::assign (&it ());
313 bool operator == (const const_iterator
&it
) const {
314 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
315 return it_
== it
.it_
;
318 bool operator < (const const_iterator
&it
) const {
319 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
324 const_subiterator_type it_
;
329 const_iterator
begin () const {
333 const_iterator
end () const {
334 return find (size ());
337 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
339 public container_reference
<matrix_row
>,
340 public iterator_base_traits
<typename
subiterator_type::iterator_category
>::template
341 iterator_base
<iterator
, value_type
>::type
{
343 typedef typename
subiterator_type::value_type value_type
;
344 typedef typename
subiterator_type::difference_type difference_type
;
345 typedef typename
subiterator_type::reference reference
;
346 typedef typename
subiterator_type::pointer pointer
;
348 // Construction and destruction
351 container_reference
<self_type
> (), it_ () {}
353 iterator (self_type
&mr
, const subiterator_type
&it
):
354 container_reference
<self_type
> (mr
), it_ (it
) {}
358 iterator
&operator ++ () {
363 iterator
&operator -- () {
368 iterator
&operator += (difference_type n
) {
373 iterator
&operator -= (difference_type n
) {
378 difference_type
operator - (const iterator
&it
) const {
379 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
385 reference
operator * () const {
386 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
390 reference
operator [] (difference_type n
) const {
396 size_type
index () const {
397 return it_
.index2 ();
402 iterator
&operator = (const iterator
&it
) {
403 container_reference
<self_type
>::assign (&it ());
410 bool operator == (const iterator
&it
) const {
411 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
412 return it_
== it
.it_
;
415 bool operator < (const iterator
&it
) const {
416 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
421 subiterator_type it_
;
423 friend class const_iterator
;
433 return find (size ());
437 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
438 typedef reverse_iterator_base
<iterator
> reverse_iterator
;
441 const_reverse_iterator
rbegin () const {
442 return const_reverse_iterator (end ());
445 const_reverse_iterator
rend () const {
446 return const_reverse_iterator (begin ());
449 reverse_iterator
rbegin () {
450 return reverse_iterator (end ());
453 reverse_iterator
rend () {
454 return reverse_iterator (begin ());
458 matrix_closure_type data_
;
465 matrix_row
<M
> row (M
&data
, typename
M::size_type i
) {
466 return matrix_row
<M
> (data
, i
);
470 const matrix_row
<const M
> row (const M
&data
, typename
M::size_type i
) {
471 return matrix_row
<const M
> (data
, i
);
474 // Specialize temporary
476 struct vector_temporary_traits
< matrix_row
<M
> >
477 : vector_temporary_traits
< M
> {} ;
479 struct vector_temporary_traits
< const matrix_row
<M
> >
480 : vector_temporary_traits
< M
> {} ;
482 // Matrix based column vector class
485 public vector_expression
<matrix_column
<M
> > {
487 typedef matrix_column
<M
> self_type
;
489 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
490 using vector_expression
<self_type
>::operator ();
492 typedef M matrix_type
;
493 typedef typename
M::size_type size_type
;
494 typedef typename
M::difference_type difference_type
;
495 typedef typename
M::value_type value_type
;
496 typedef typename
M::const_reference const_reference
;
497 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
498 typename
M::const_reference
,
499 typename
M::reference
>::type reference
;
500 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
501 typename
M::const_closure_type
,
502 typename
M::closure_type
>::type matrix_closure_type
;
503 typedef const self_type const_closure_type
;
504 typedef self_type closure_type
;
505 typedef typename storage_restrict_traits
<typename
M::storage_category
,
506 dense_proxy_tag
>::storage_category storage_category
;
508 // Construction and destruction
510 matrix_column (matrix_type
&data
, size_type j
):
511 data_ (data
), j_ (j
) {
512 // Early checking of preconditions here.
513 // BOOST_UBLAS_CHECK (j_ < data_.size2 (), bad_index ());
518 size_type
size () const {
519 return data_
.size1 ();
522 size_type
index () const {
528 const matrix_closure_type
&data () const {
532 matrix_closure_type
&data () {
537 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
539 const_reference
operator () (size_type i
) const {
540 return data_ (i
, j_
);
543 reference
operator () (size_type i
) {
544 return data_ (i
, j_
);
548 const_reference
operator [] (size_type i
) const {
552 reference
operator [] (size_type i
) {
557 reference
operator () (size_type i
) const {
558 return data_ (i
, j_
);
562 reference
operator [] (size_type i
) const {
569 matrix_column
&operator = (const matrix_column
&mc
) {
570 // ISSUE need a temporary, proxy can be overlaping alias
571 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (mc
));
575 matrix_column
&assign_temporary (matrix_column
&mc
) {
576 // assign elements, proxied container remains the same
577 vector_assign
<scalar_assign
> (*this, mc
);
582 matrix_column
&operator = (const vector_expression
<AE
> &ae
) {
583 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (ae
));
588 matrix_column
&assign (const vector_expression
<AE
> &ae
) {
589 vector_assign
<scalar_assign
> (*this, ae
);
594 matrix_column
&operator += (const vector_expression
<AE
> &ae
) {
595 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (*this + ae
));
600 matrix_column
&plus_assign (const vector_expression
<AE
> &ae
) {
601 vector_assign
<scalar_plus_assign
> (*this, ae
);
606 matrix_column
&operator -= (const vector_expression
<AE
> &ae
) {
607 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (*this - ae
));
612 matrix_column
&minus_assign (const vector_expression
<AE
> &ae
) {
613 vector_assign
<scalar_minus_assign
> (*this, ae
);
618 matrix_column
&operator *= (const AT
&at
) {
619 vector_assign_scalar
<scalar_multiplies_assign
> (*this, at
);
624 matrix_column
&operator /= (const AT
&at
) {
625 vector_assign_scalar
<scalar_divides_assign
> (*this, at
);
629 // Closure comparison
631 bool same_closure (const matrix_column
&mc
) const {
632 return (*this).data_
.same_closure (mc
.data_
);
637 bool operator == (const matrix_column
&mc
) const {
638 return (*this).data_
== mc
.data_
&& index () == mc
.index ();
643 void swap (matrix_column mc
) {
645 BOOST_UBLAS_CHECK (size () == mc
.size (), bad_size ());
646 // Sparse ranges may be nonconformant now.
647 // std::swap_ranges (begin (), end (), mc.begin ());
648 vector_swap
<scalar_swap
> (*this, mc
);
652 friend void swap (matrix_column mc1
, matrix_column mc2
) {
658 typedef typename
M::const_iterator1 const_subiterator_type
;
659 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
660 typename
M::const_iterator1
,
661 typename
M::iterator1
>::type subiterator_type
;
664 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
665 typedef indexed_iterator
<matrix_column
<matrix_type
>,
666 typename
subiterator_type::iterator_category
> iterator
;
667 typedef indexed_const_iterator
<matrix_column
<matrix_type
>,
668 typename
const_subiterator_type::iterator_category
> const_iterator
;
670 class const_iterator
;
676 const_iterator
find (size_type i
) const {
677 const_subiterator_type
it1 (data_
.find1 (1, i
, j_
));
678 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
679 return const_iterator (*this, it1
.index1 ());
681 return const_iterator (*this, it1
);
685 iterator
find (size_type i
) {
686 subiterator_type
it1 (data_
.find1 (1, i
, j_
));
687 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
688 return iterator (*this, it1
.index1 ());
690 return iterator (*this, it1
);
694 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
695 class const_iterator
:
696 public container_const_reference
<matrix_column
>,
697 public iterator_base_traits
<typename
const_subiterator_type::iterator_category
>::template
698 iterator_base
<const_iterator
, value_type
>::type
{
700 typedef typename
const_subiterator_type::value_type value_type
;
701 typedef typename
const_subiterator_type::difference_type difference_type
;
702 typedef typename
const_subiterator_type::reference reference
;
703 typedef typename
const_subiterator_type::pointer pointer
;
705 // Construction and destruction
708 container_const_reference
<self_type
> (), it_ () {}
710 const_iterator (const self_type
&mc
, const const_subiterator_type
&it
):
711 container_const_reference
<self_type
> (mc
), it_ (it
) {}
713 const_iterator (const typename
self_type::iterator
&it
): // ISSUE self_type:: stops VC8 using std::iterator here
714 container_const_reference
<self_type
> (it ()), it_ (it
.it_
) {}
718 const_iterator
&operator ++ () {
723 const_iterator
&operator -- () {
728 const_iterator
&operator += (difference_type n
) {
733 const_iterator
&operator -= (difference_type n
) {
738 difference_type
operator - (const const_iterator
&it
) const {
739 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
745 const_reference
operator * () const {
746 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
750 const_reference
operator [] (difference_type n
) const {
756 size_type
index () const {
757 return it_
.index1 ();
762 const_iterator
&operator = (const const_iterator
&it
) {
763 container_const_reference
<self_type
>::assign (&it ());
770 bool operator == (const const_iterator
&it
) const {
771 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
772 return it_
== it
.it_
;
775 bool operator < (const const_iterator
&it
) const {
776 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
781 const_subiterator_type it_
;
786 const_iterator
begin () const {
790 const_iterator
end () const {
791 return find (size ());
794 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
796 public container_reference
<matrix_column
>,
797 public iterator_base_traits
<typename
subiterator_type::iterator_category
>::template
798 iterator_base
<iterator
, value_type
>::type
{
800 typedef typename
subiterator_type::value_type value_type
;
801 typedef typename
subiterator_type::difference_type difference_type
;
802 typedef typename
subiterator_type::reference reference
;
803 typedef typename
subiterator_type::pointer pointer
;
805 // Construction and destruction
808 container_reference
<self_type
> (), it_ () {}
810 iterator (self_type
&mc
, const subiterator_type
&it
):
811 container_reference
<self_type
> (mc
), it_ (it
) {}
815 iterator
&operator ++ () {
820 iterator
&operator -- () {
825 iterator
&operator += (difference_type n
) {
830 iterator
&operator -= (difference_type n
) {
835 difference_type
operator - (const iterator
&it
) const {
836 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
842 reference
operator * () const {
843 BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
847 reference
operator [] (difference_type n
) const {
853 size_type
index () const {
854 return it_
.index1 ();
859 iterator
&operator = (const iterator
&it
) {
860 container_reference
<self_type
>::assign (&it ());
867 bool operator == (const iterator
&it
) const {
868 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
869 return it_
== it
.it_
;
872 bool operator < (const iterator
&it
) const {
873 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
878 subiterator_type it_
;
880 friend class const_iterator
;
890 return find (size ());
894 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
895 typedef reverse_iterator_base
<iterator
> reverse_iterator
;
898 const_reverse_iterator
rbegin () const {
899 return const_reverse_iterator (end ());
902 const_reverse_iterator
rend () const {
903 return const_reverse_iterator (begin ());
905 reverse_iterator
rbegin () {
906 return reverse_iterator (end ());
909 reverse_iterator
rend () {
910 return reverse_iterator (begin ());
914 matrix_closure_type data_
;
921 matrix_column
<M
> column (M
&data
, typename
M::size_type j
) {
922 return matrix_column
<M
> (data
, j
);
926 const matrix_column
<const M
> column (const M
&data
, typename
M::size_type j
) {
927 return matrix_column
<const M
> (data
, j
);
930 // Specialize temporary
932 struct vector_temporary_traits
< matrix_column
<M
> >
933 : vector_temporary_traits
< M
> {} ;
935 struct vector_temporary_traits
< const matrix_column
<M
> >
936 : vector_temporary_traits
< M
> {} ;
938 // Matrix based vector range class
940 class matrix_vector_range
:
941 public vector_expression
<matrix_vector_range
<M
> > {
943 typedef matrix_vector_range
<M
> self_type
;
945 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
946 using vector_expression
<self_type
>::operator ();
948 typedef M matrix_type
;
949 typedef typename
M::size_type size_type
;
950 typedef typename
M::difference_type difference_type
;
951 typedef typename
M::value_type value_type
;
952 typedef typename
M::const_reference const_reference
;
953 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
954 typename
M::const_reference
,
955 typename
M::reference
>::type reference
;
956 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
957 typename
M::const_closure_type
,
958 typename
M::closure_type
>::type matrix_closure_type
;
959 typedef basic_range
<size_type
, difference_type
> range_type
;
960 typedef const self_type const_closure_type
;
961 typedef self_type closure_type
;
962 typedef typename storage_restrict_traits
<typename
M::storage_category
,
963 dense_proxy_tag
>::storage_category storage_category
;
965 // Construction and destruction
967 matrix_vector_range (matrix_type
&data
, const range_type
&r1
, const range_type
&r2
):
968 data_ (data
), r1_ (r1
.preprocess (data
.size1 ())), r2_ (r2
.preprocess (data
.size2 ())) {
969 // Early checking of preconditions here.
970 // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
971 // r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
972 // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
973 // r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
974 // BOOST_UBLAS_CHECK (r1_.size () == r2_.size (), bad_size ());
979 size_type
start1 () const {
983 size_type
start2 () const {
987 size_type
size () const {
988 return BOOST_UBLAS_SAME (r1_
.size (), r2_
.size ());
993 const matrix_closure_type
&data () const {
997 matrix_closure_type
&data () {
1002 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1004 const_reference
operator () (size_type i
) const {
1005 return data_ (r1_ (i
), r2_ (i
));
1008 reference
operator () (size_type i
) {
1009 return data_ (r1_ (i
), r2_ (i
));
1013 const_reference
operator [] (size_type i
) const {
1017 reference
operator [] (size_type i
) {
1022 reference
operator () (size_type i
) const {
1023 return data_ (r1_ (i
), r2_ (i
));
1027 reference
operator [] (size_type i
) const {
1034 matrix_vector_range
&operator = (const matrix_vector_range
&mvr
) {
1035 // ISSUE need a temporary, proxy can be overlaping alias
1036 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (mvr
));
1040 matrix_vector_range
&assign_temporary (matrix_vector_range
&mvr
) {
1041 // assign elements, proxied container remains the same
1042 vector_assign
<scalar_assign
> (*this, mvr
);
1047 matrix_vector_range
&operator = (const vector_expression
<AE
> &ae
) {
1048 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (ae
));
1053 matrix_vector_range
&assign (const vector_expression
<AE
> &ae
) {
1054 vector_assign
<scalar_assign
> (*this, ae
);
1059 matrix_vector_range
&operator += (const vector_expression
<AE
> &ae
) {
1060 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (*this + ae
));
1065 matrix_vector_range
&plus_assign (const vector_expression
<AE
> &ae
) {
1066 vector_assign
<scalar_plus_assign
> (*this, ae
);
1071 matrix_vector_range
&operator -= (const vector_expression
<AE
> &ae
) {
1072 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (*this - ae
));
1077 matrix_vector_range
&minus_assign (const vector_expression
<AE
> &ae
) {
1078 vector_assign
<scalar_minus_assign
> (*this, ae
);
1083 matrix_vector_range
&operator *= (const AT
&at
) {
1084 vector_assign_scalar
<scalar_multiplies_assign
> (*this, at
);
1089 matrix_vector_range
&operator /= (const AT
&at
) {
1090 vector_assign_scalar
<scalar_divides_assign
> (*this, at
);
1094 // Closure comparison
1096 bool same_closure (const matrix_vector_range
&mvr
) const {
1097 return (*this).data_
.same_closure (mvr
.data_
);
1102 bool operator == (const matrix_vector_range
&mvr
) const {
1103 return (*this).data_
== mvr
.data_
&& r1_
== mvr
.r1_
&& r2_
== mvr
.r2_
;
1108 void swap (matrix_vector_range mvr
) {
1110 BOOST_UBLAS_CHECK (size () == mvr
.size (), bad_size ());
1111 // Sparse ranges may be nonconformant now.
1112 // std::swap_ranges (begin (), end (), mvr.begin ());
1113 vector_swap
<scalar_swap
> (*this, mvr
);
1117 friend void swap (matrix_vector_range mvr1
, matrix_vector_range mvr2
) {
1123 // Use range as an index - FIXME this fails for packed assignment
1124 typedef typename
range_type::const_iterator const_subiterator1_type
;
1125 typedef typename
range_type::const_iterator subiterator1_type
;
1126 typedef typename
range_type::const_iterator const_subiterator2_type
;
1127 typedef typename
range_type::const_iterator subiterator2_type
;
1130 class const_iterator
;
1135 const_iterator
find (size_type i
) const {
1136 return const_iterator (*this, r1_
.begin () + i
, r2_
.begin () + i
);
1139 iterator
find (size_type i
) {
1140 return iterator (*this, r1_
.begin () + i
, r2_
.begin () + i
);
1143 class const_iterator
:
1144 public container_const_reference
<matrix_vector_range
>,
1145 public iterator_base_traits
<typename
M::const_iterator1::iterator_category
>::template
1146 iterator_base
<const_iterator
, value_type
>::type
{
1148 // FIXME Iterator can never be different code was:
1149 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
1150 BOOST_STATIC_ASSERT ((boost::is_same
<typename
M::const_iterator1::iterator_category
, typename
M::const_iterator2::iterator_category
>::value
));
1152 typedef typename
matrix_vector_range::value_type value_type
;
1153 typedef typename
matrix_vector_range::difference_type difference_type
;
1154 typedef typename
matrix_vector_range::const_reference reference
;
1155 typedef const typename
matrix_vector_range::value_type
*pointer
;
1157 // Construction and destruction
1160 container_const_reference
<self_type
> (), it1_ (), it2_ () {}
1162 const_iterator (const self_type
&mvr
, const const_subiterator1_type
&it1
, const const_subiterator2_type
&it2
):
1163 container_const_reference
<self_type
> (mvr
), it1_ (it1
), it2_ (it2
) {}
1165 const_iterator (const typename
self_type::iterator
&it
): // ISSUE self_type:: stops VC8 using std::iterator here
1166 container_const_reference
<self_type
> (it ()), it1_ (it
.it1_
), it2_ (it
.it2_
) {}
1170 const_iterator
&operator ++ () {
1176 const_iterator
&operator -- () {
1182 const_iterator
&operator += (difference_type n
) {
1188 const_iterator
&operator -= (difference_type n
) {
1194 difference_type
operator - (const const_iterator
&it
) const {
1195 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1196 return BOOST_UBLAS_SAME (it1_
- it
.it1_
, it2_
- it
.it2_
);
1201 const_reference
operator * () const {
1202 // FIXME replace find with at_element
1203 return (*this) ().data_ (*it1_
, *it2_
);
1206 const_reference
operator [] (difference_type n
) const {
1207 return *(*this + n
);
1212 size_type
index () const {
1213 return BOOST_UBLAS_SAME (it1_
.index (), it2_
.index ());
1218 const_iterator
&operator = (const const_iterator
&it
) {
1219 container_const_reference
<self_type
>::assign (&it ());
1227 bool operator == (const const_iterator
&it
) const {
1228 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1229 return it1_
== it
.it1_
&& it2_
== it
.it2_
;
1232 bool operator < (const const_iterator
&it
) const {
1233 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1234 return it1_
< it
.it1_
&& it2_
< it
.it2_
;
1238 const_subiterator1_type it1_
;
1239 const_subiterator2_type it2_
;
1243 const_iterator
begin () const {
1247 const_iterator
end () const {
1248 return find (size ());
1252 public container_reference
<matrix_vector_range
>,
1253 public iterator_base_traits
<typename
M::iterator1::iterator_category
>::template
1254 iterator_base
<iterator
, value_type
>::type
{
1256 // FIXME Iterator can never be different code was:
1257 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
1258 BOOST_STATIC_ASSERT ((boost::is_same
<typename
M::const_iterator1::iterator_category
, typename
M::const_iterator2::iterator_category
>::value
));
1260 typedef typename
matrix_vector_range::value_type value_type
;
1261 typedef typename
matrix_vector_range::difference_type difference_type
;
1262 typedef typename
matrix_vector_range::reference reference
;
1263 typedef typename
matrix_vector_range::value_type
*pointer
;
1265 // Construction and destruction
1268 container_reference
<self_type
> (), it1_ (), it2_ () {}
1270 iterator (self_type
&mvr
, const subiterator1_type
&it1
, const subiterator2_type
&it2
):
1271 container_reference
<self_type
> (mvr
), it1_ (it1
), it2_ (it2
) {}
1275 iterator
&operator ++ () {
1281 iterator
&operator -- () {
1287 iterator
&operator += (difference_type n
) {
1293 iterator
&operator -= (difference_type n
) {
1299 difference_type
operator - (const iterator
&it
) const {
1300 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1301 return BOOST_UBLAS_SAME (it1_
- it
.it1_
, it2_
- it
.it2_
);
1306 reference
operator * () const {
1307 // FIXME replace find with at_element
1308 return (*this) ().data_ (*it1_
, *it2_
);
1311 reference
operator [] (difference_type n
) const {
1312 return *(*this + n
);
1317 size_type
index () const {
1318 return BOOST_UBLAS_SAME (it1_
.index (), it2_
.index ());
1323 iterator
&operator = (const iterator
&it
) {
1324 container_reference
<self_type
>::assign (&it ());
1332 bool operator == (const iterator
&it
) const {
1333 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1334 return it1_
== it
.it1_
&& it2_
== it
.it2_
;
1337 bool operator < (const iterator
&it
) const {
1338 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1339 return it1_
< it
.it1_
&& it2_
< it
.it2_
;
1343 subiterator1_type it1_
;
1344 subiterator2_type it2_
;
1346 friend class const_iterator
;
1355 return find (size ());
1359 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
1360 typedef reverse_iterator_base
<iterator
> reverse_iterator
;
1363 const_reverse_iterator
rbegin () const {
1364 return const_reverse_iterator (end ());
1367 const_reverse_iterator
rend () const {
1368 return const_reverse_iterator (begin ());
1371 reverse_iterator
rbegin () {
1372 return reverse_iterator (end ());
1375 reverse_iterator
rend () {
1376 return reverse_iterator (begin ());
1380 matrix_closure_type data_
;
1385 // Specialize temporary
1387 struct vector_temporary_traits
< matrix_vector_range
<M
> >
1388 : vector_temporary_traits
< M
> {} ;
1390 struct vector_temporary_traits
< const matrix_vector_range
<M
> >
1391 : vector_temporary_traits
< M
> {} ;
1393 // Matrix based vector slice class
1395 class matrix_vector_slice
:
1396 public vector_expression
<matrix_vector_slice
<M
> > {
1398 typedef matrix_vector_slice
<M
> self_type
;
1400 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1401 using vector_expression
<self_type
>::operator ();
1403 typedef M matrix_type
;
1404 typedef typename
M::size_type size_type
;
1405 typedef typename
M::difference_type difference_type
;
1406 typedef typename
M::value_type value_type
;
1407 typedef typename
M::const_reference const_reference
;
1408 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
1409 typename
M::const_reference
,
1410 typename
M::reference
>::type reference
;
1411 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
1412 typename
M::const_closure_type
,
1413 typename
M::closure_type
>::type matrix_closure_type
;
1414 typedef basic_range
<size_type
, difference_type
> range_type
;
1415 typedef basic_slice
<size_type
, difference_type
> slice_type
;
1416 typedef const self_type const_closure_type
;
1417 typedef self_type closure_type
;
1418 typedef typename storage_restrict_traits
<typename
M::storage_category
,
1419 dense_proxy_tag
>::storage_category storage_category
;
1421 // Construction and destruction
1423 matrix_vector_slice (matrix_type
&data
, const slice_type
&s1
, const slice_type
&s2
):
1424 data_ (data
), s1_ (s1
.preprocess (data
.size1 ())), s2_ (s2
.preprocess (data
.size2 ())) {
1425 // Early checking of preconditions here.
1426 // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
1427 // s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
1428 // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
1429 // s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
1434 size_type
start1 () const {
1435 return s1_
.start ();
1438 size_type
start2 () const {
1439 return s2_
.start ();
1442 difference_type
stride1 () const {
1443 return s1_
.stride ();
1446 difference_type
stride2 () const {
1447 return s2_
.stride ();
1450 size_type
size () const {
1451 return BOOST_UBLAS_SAME (s1_
.size (), s2_
.size ());
1454 // Storage accessors
1456 const matrix_closure_type
&data () const {
1460 matrix_closure_type
&data () {
1465 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1467 const_reference
operator () (size_type i
) const {
1468 return data_ (s1_ (i
), s2_ (i
));
1471 reference
operator () (size_type i
) {
1472 return data_ (s1_ (i
), s2_ (i
));
1476 const_reference
operator [] (size_type i
) const {
1480 reference
operator [] (size_type i
) {
1485 reference
operator () (size_type i
) const {
1486 return data_ (s1_ (i
), s2_ (i
));
1490 reference
operator [] (size_type i
) const {
1497 matrix_vector_slice
&operator = (const matrix_vector_slice
&mvs
) {
1498 // ISSUE need a temporary, proxy can be overlaping alias
1499 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (mvs
));
1503 matrix_vector_slice
&assign_temporary (matrix_vector_slice
&mvs
) {
1504 // assign elements, proxied container remains the same
1505 vector_assign
<scalar_assign
> (*this, mvs
);
1510 matrix_vector_slice
&operator = (const vector_expression
<AE
> &ae
) {
1511 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (ae
));
1516 matrix_vector_slice
&assign (const vector_expression
<AE
> &ae
) {
1517 vector_assign
<scalar_assign
> (*this, ae
);
1522 matrix_vector_slice
&operator += (const vector_expression
<AE
> &ae
) {
1523 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (*this + ae
));
1528 matrix_vector_slice
&plus_assign (const vector_expression
<AE
> &ae
) {
1529 vector_assign
<scalar_plus_assign
> (*this, ae
);
1534 matrix_vector_slice
&operator -= (const vector_expression
<AE
> &ae
) {
1535 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (*this - ae
));
1540 matrix_vector_slice
&minus_assign (const vector_expression
<AE
> &ae
) {
1541 vector_assign
<scalar_minus_assign
> (*this, ae
);
1546 matrix_vector_slice
&operator *= (const AT
&at
) {
1547 vector_assign_scalar
<scalar_multiplies_assign
> (*this, at
);
1552 matrix_vector_slice
&operator /= (const AT
&at
) {
1553 vector_assign_scalar
<scalar_divides_assign
> (*this, at
);
1557 // Closure comparison
1559 bool same_closure (const matrix_vector_slice
&mvs
) const {
1560 return (*this).data_
.same_closure (mvs
.data_
);
1565 bool operator == (const matrix_vector_slice
&mvs
) const {
1566 return (*this).data_
== mvs
.data_
&& s1_
== mvs
.s1_
&& s2_
== mvs
.s2_
;
1571 void swap (matrix_vector_slice mvs
) {
1573 BOOST_UBLAS_CHECK (size () == mvs
.size (), bad_size ());
1574 // Sparse ranges may be nonconformant now.
1575 // std::swap_ranges (begin (), end (), mvs.begin ());
1576 vector_swap
<scalar_swap
> (*this, mvs
);
1580 friend void swap (matrix_vector_slice mvs1
, matrix_vector_slice mvs2
) {
1586 // Use slice as an index - FIXME this fails for packed assignment
1587 typedef typename
slice_type::const_iterator const_subiterator1_type
;
1588 typedef typename
slice_type::const_iterator subiterator1_type
;
1589 typedef typename
slice_type::const_iterator const_subiterator2_type
;
1590 typedef typename
slice_type::const_iterator subiterator2_type
;
1593 class const_iterator
;
1598 const_iterator
find (size_type i
) const {
1599 return const_iterator (*this, s1_
.begin () + i
, s2_
.begin () + i
);
1602 iterator
find (size_type i
) {
1603 return iterator (*this, s1_
.begin () + i
, s2_
.begin () + i
);
1606 // Iterators simply are indices.
1608 class const_iterator
:
1609 public container_const_reference
<matrix_vector_slice
>,
1610 public iterator_base_traits
<typename
M::const_iterator1::iterator_category
>::template
1611 iterator_base
<const_iterator
, value_type
>::type
{
1613 // FIXME Iterator can never be different code was:
1614 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
1615 BOOST_STATIC_ASSERT ((boost::is_same
<typename
M::const_iterator1::iterator_category
, typename
M::const_iterator2::iterator_category
>::value
));
1617 typedef typename
matrix_vector_slice::value_type value_type
;
1618 typedef typename
matrix_vector_slice::difference_type difference_type
;
1619 typedef typename
matrix_vector_slice::const_reference reference
;
1620 typedef const typename
matrix_vector_slice::value_type
*pointer
;
1622 // Construction and destruction
1625 container_const_reference
<self_type
> (), it1_ (), it2_ () {}
1627 const_iterator (const self_type
&mvs
, const const_subiterator1_type
&it1
, const const_subiterator2_type
&it2
):
1628 container_const_reference
<self_type
> (mvs
), it1_ (it1
), it2_ (it2
) {}
1630 const_iterator (const typename
self_type::iterator
&it
): // ISSUE vector:: stops VC8 using std::iterator here
1631 container_const_reference
<self_type
> (it ()), it1_ (it
.it1_
), it2_ (it
.it2_
) {}
1635 const_iterator
&operator ++ () {
1641 const_iterator
&operator -- () {
1647 const_iterator
&operator += (difference_type n
) {
1653 const_iterator
&operator -= (difference_type n
) {
1659 difference_type
operator - (const const_iterator
&it
) const {
1660 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1661 return BOOST_UBLAS_SAME (it1_
- it
.it1_
, it2_
- it
.it2_
);
1666 const_reference
operator * () const {
1667 // FIXME replace find with at_element
1668 return (*this) ().data_ (*it1_
, *it2_
);
1671 const_reference
operator [] (difference_type n
) const {
1672 return *(*this + n
);
1677 size_type
index () const {
1678 return BOOST_UBLAS_SAME (it1_
.index (), it2_
.index ());
1683 const_iterator
&operator = (const const_iterator
&it
) {
1684 container_const_reference
<self_type
>::assign (&it ());
1692 bool operator == (const const_iterator
&it
) const {
1693 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1694 return it1_
== it
.it1_
&& it2_
== it
.it2_
;
1697 bool operator < (const const_iterator
&it
) const {
1698 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1699 return it1_
< it
.it1_
&& it2_
< it
.it2_
;
1703 const_subiterator1_type it1_
;
1704 const_subiterator2_type it2_
;
1708 const_iterator
begin () const {
1712 const_iterator
end () const {
1713 return find (size ());
1717 public container_reference
<matrix_vector_slice
>,
1718 public iterator_base_traits
<typename
M::iterator1::iterator_category
>::template
1719 iterator_base
<iterator
, value_type
>::type
{
1721 // FIXME Iterator can never be different code was:
1722 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
1723 BOOST_STATIC_ASSERT ((boost::is_same
<typename
M::const_iterator1::iterator_category
, typename
M::const_iterator2::iterator_category
>::value
));
1725 typedef typename
matrix_vector_slice::value_type value_type
;
1726 typedef typename
matrix_vector_slice::difference_type difference_type
;
1727 typedef typename
matrix_vector_slice::reference reference
;
1728 typedef typename
matrix_vector_slice::value_type
*pointer
;
1730 // Construction and destruction
1733 container_reference
<self_type
> (), it1_ (), it2_ () {}
1735 iterator (self_type
&mvs
, const subiterator1_type
&it1
, const subiterator2_type
&it2
):
1736 container_reference
<self_type
> (mvs
), it1_ (it1
), it2_ (it2
) {}
1740 iterator
&operator ++ () {
1746 iterator
&operator -- () {
1752 iterator
&operator += (difference_type n
) {
1758 iterator
&operator -= (difference_type n
) {
1764 difference_type
operator - (const iterator
&it
) const {
1765 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1766 return BOOST_UBLAS_SAME (it1_
- it
.it1_
, it2_
- it
.it2_
);
1771 reference
operator * () const {
1772 // FIXME replace find with at_element
1773 return (*this) ().data_ (*it1_
, *it2_
);
1776 reference
operator [] (difference_type n
) const {
1777 return *(*this + n
);
1782 size_type
index () const {
1783 return BOOST_UBLAS_SAME (it1_
.index (), it2_
.index ());
1788 iterator
&operator = (const iterator
&it
) {
1789 container_reference
<self_type
>::assign (&it ());
1797 bool operator == (const iterator
&it
) const {
1798 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1799 return it1_
== it
.it1_
&& it2_
== it
.it2_
;
1802 bool operator < (const iterator
&it
) const {
1803 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1804 return it1_
< it
.it1_
&& it2_
< it
.it2_
;
1808 subiterator1_type it1_
;
1809 subiterator2_type it2_
;
1811 friend class const_iterator
;
1820 return find (size ());
1824 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
1825 typedef reverse_iterator_base
<iterator
> reverse_iterator
;
1828 const_reverse_iterator
rbegin () const {
1829 return const_reverse_iterator (end ());
1832 const_reverse_iterator
rend () const {
1833 return const_reverse_iterator (begin ());
1836 reverse_iterator
rbegin () {
1837 return reverse_iterator (end ());
1840 reverse_iterator
rend () {
1841 return reverse_iterator (begin ());
1845 matrix_closure_type data_
;
1850 // Specialize temporary
1852 struct vector_temporary_traits
< matrix_vector_slice
<M
> >
1853 : vector_temporary_traits
< M
> {} ;
1855 struct vector_temporary_traits
< const matrix_vector_slice
<M
> >
1856 : vector_temporary_traits
< M
> {} ;
1858 // Matrix based vector indirection class
1859 template<class M
, class IA
>
1860 class matrix_vector_indirect
:
1861 public vector_expression
<matrix_vector_indirect
<M
, IA
> > {
1863 typedef matrix_vector_indirect
<M
, IA
> self_type
;
1865 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1866 using vector_expression
<self_type
>::operator ();
1868 typedef M matrix_type
;
1869 typedef IA indirect_array_type
;
1870 typedef typename
M::size_type size_type
;
1871 typedef typename
M::difference_type difference_type
;
1872 typedef typename
M::value_type value_type
;
1873 typedef typename
M::const_reference const_reference
;
1874 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
1875 typename
M::const_reference
,
1876 typename
M::reference
>::type reference
;
1877 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
1878 typename
M::const_closure_type
,
1879 typename
M::closure_type
>::type matrix_closure_type
;
1880 typedef const self_type const_closure_type
;
1881 typedef self_type closure_type
;
1882 typedef typename storage_restrict_traits
<typename
M::storage_category
,
1883 dense_proxy_tag
>::storage_category storage_category
;
1885 // Construction and destruction
1887 matrix_vector_indirect (matrix_type
&data
, size_type size
):
1888 data_ (data
), ia1_ (size
), ia2_ (size
) {}
1890 matrix_vector_indirect (matrix_type
&data
, const indirect_array_type
&ia1
, const indirect_array_type
&ia2
):
1891 data_ (data
), ia1_ (ia1
), ia2_ (ia2
) {
1892 // Early checking of preconditions here.
1893 // BOOST_UBLAS_CHECK (ia1_.size () == ia2_.size (), bad_size ());
1898 size_type
size () const {
1899 return BOOST_UBLAS_SAME (ia1_
.size (), ia2_
.size ());
1902 const indirect_array_type
&indirect1 () const {
1906 indirect_array_type
&indirect1 () {
1910 const indirect_array_type
&indirect2 () const {
1914 indirect_array_type
&indirect2 () {
1918 // Storage accessors
1920 const matrix_closure_type
&data () const {
1924 matrix_closure_type
&data () {
1929 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1931 const_reference
operator () (size_type i
) const {
1932 return data_ (ia1_ (i
), ia2_ (i
));
1935 reference
operator () (size_type i
) {
1936 return data_ (ia1_ (i
), ia2_ (i
));
1940 const_reference
operator [] (size_type i
) const {
1944 reference
operator [] (size_type i
) {
1949 reference
operator () (size_type i
) const {
1950 return data_ (ia1_ (i
), ia2_ (i
));
1954 reference
operator [] (size_type i
) const {
1961 matrix_vector_indirect
&operator = (const matrix_vector_indirect
&mvi
) {
1962 // ISSUE need a temporary, proxy can be overlaping alias
1963 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (mvi
));
1967 matrix_vector_indirect
&assign_temporary (matrix_vector_indirect
&mvi
) {
1968 // assign elements, proxied container remains the same
1969 vector_assign
<scalar_assign
> (*this, mvi
);
1974 matrix_vector_indirect
&operator = (const vector_expression
<AE
> &ae
) {
1975 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (ae
));
1980 matrix_vector_indirect
&assign (const vector_expression
<AE
> &ae
) {
1981 vector_assign
<scalar_assign
> (*this, ae
);
1986 matrix_vector_indirect
&operator += (const vector_expression
<AE
> &ae
) {
1987 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (*this + ae
));
1992 matrix_vector_indirect
&plus_assign (const vector_expression
<AE
> &ae
) {
1993 vector_assign
<scalar_plus_assign
> (*this, ae
);
1998 matrix_vector_indirect
&operator -= (const vector_expression
<AE
> &ae
) {
1999 vector_assign
<scalar_assign
> (*this, typename vector_temporary_traits
<M
>::type (*this - ae
));
2004 matrix_vector_indirect
&minus_assign (const vector_expression
<AE
> &ae
) {
2005 vector_assign
<scalar_minus_assign
> (*this, ae
);
2010 matrix_vector_indirect
&operator *= (const AT
&at
) {
2011 vector_assign_scalar
<scalar_multiplies_assign
> (*this, at
);
2016 matrix_vector_indirect
&operator /= (const AT
&at
) {
2017 vector_assign_scalar
<scalar_divides_assign
> (*this, at
);
2021 // Closure comparison
2023 bool same_closure (const matrix_vector_indirect
&mvi
) const {
2024 return (*this).data_
.same_closure (mvi
.data_
);
2029 bool operator == (const matrix_vector_indirect
&mvi
) const {
2030 return (*this).data_
== mvi
.data_
&& ia1_
== mvi
.ia1_
&& ia2_
== mvi
.ia2_
;
2035 void swap (matrix_vector_indirect mvi
) {
2037 BOOST_UBLAS_CHECK (size () == mvi
.size (), bad_size ());
2038 // Sparse ranges may be nonconformant now.
2039 // std::swap_ranges (begin (), end (), mvi.begin ());
2040 vector_swap
<scalar_swap
> (*this, mvi
);
2044 friend void swap (matrix_vector_indirect mvi1
, matrix_vector_indirect mvi2
) {
2050 // Use indirect array as an index - FIXME this fails for packed assignment
2051 typedef typename
IA::const_iterator const_subiterator1_type
;
2052 typedef typename
IA::const_iterator subiterator1_type
;
2053 typedef typename
IA::const_iterator const_subiterator2_type
;
2054 typedef typename
IA::const_iterator subiterator2_type
;
2057 class const_iterator
;
2062 const_iterator
find (size_type i
) const {
2063 return const_iterator (*this, ia1_
.begin () + i
, ia2_
.begin () + i
);
2066 iterator
find (size_type i
) {
2067 return iterator (*this, ia1_
.begin () + i
, ia2_
.begin () + i
);
2070 // Iterators simply are indices.
2072 class const_iterator
:
2073 public container_const_reference
<matrix_vector_indirect
>,
2074 public iterator_base_traits
<typename
M::const_iterator1::iterator_category
>::template
2075 iterator_base
<const_iterator
, value_type
>::type
{
2077 // FIXME Iterator can never be different code was:
2078 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
2079 BOOST_STATIC_ASSERT ((boost::is_same
<typename
M::const_iterator1::iterator_category
, typename
M::const_iterator2::iterator_category
>::value
));
2081 typedef typename
matrix_vector_indirect::value_type value_type
;
2082 typedef typename
matrix_vector_indirect::difference_type difference_type
;
2083 typedef typename
matrix_vector_indirect::const_reference reference
;
2084 typedef const typename
matrix_vector_indirect::value_type
*pointer
;
2086 // Construction and destruction
2089 container_const_reference
<self_type
> (), it1_ (), it2_ () {}
2091 const_iterator (const self_type
&mvi
, const const_subiterator1_type
&it1
, const const_subiterator2_type
&it2
):
2092 container_const_reference
<self_type
> (mvi
), it1_ (it1
), it2_ (it2
) {}
2094 const_iterator (const typename
self_type::iterator
&it
): // ISSUE self_type:: stops VC8 using std::iterator here
2095 container_const_reference
<self_type
> (it ()), it1_ (it
.it1_
), it2_ (it
.it2_
) {}
2099 const_iterator
&operator ++ () {
2105 const_iterator
&operator -- () {
2111 const_iterator
&operator += (difference_type n
) {
2117 const_iterator
&operator -= (difference_type n
) {
2123 difference_type
operator - (const const_iterator
&it
) const {
2124 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2125 return BOOST_UBLAS_SAME (it1_
- it
.it1_
, it2_
- it
.it2_
);
2130 const_reference
operator * () const {
2131 // FIXME replace find with at_element
2132 return (*this) ().data_ (*it1_
, *it2_
);
2135 const_reference
operator [] (difference_type n
) const {
2136 return *(*this + n
);
2141 size_type
index () const {
2142 return BOOST_UBLAS_SAME (it1_
.index (), it2_
.index ());
2147 const_iterator
&operator = (const const_iterator
&it
) {
2148 container_const_reference
<self_type
>::assign (&it ());
2156 bool operator == (const const_iterator
&it
) const {
2157 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2158 return it1_
== it
.it1_
&& it2_
== it
.it2_
;
2161 bool operator < (const const_iterator
&it
) const {
2162 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2163 return it1_
< it
.it1_
&& it2_
< it
.it2_
;
2167 const_subiterator1_type it1_
;
2168 const_subiterator2_type it2_
;
2172 const_iterator
begin () const {
2176 const_iterator
end () const {
2177 return find (size ());
2181 public container_reference
<matrix_vector_indirect
>,
2182 public iterator_base_traits
<typename
M::iterator1::iterator_category
>::template
2183 iterator_base
<iterator
, value_type
>::type
{
2185 // FIXME Iterator can never be different code was:
2186 // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
2187 BOOST_STATIC_ASSERT ((boost::is_same
<typename
M::const_iterator1::iterator_category
, typename
M::const_iterator2::iterator_category
>::value
));
2189 typedef typename
matrix_vector_indirect::value_type value_type
;
2190 typedef typename
matrix_vector_indirect::difference_type difference_type
;
2191 typedef typename
matrix_vector_indirect::reference reference
;
2192 typedef typename
matrix_vector_indirect::value_type
*pointer
;
2194 // Construction and destruction
2197 container_reference
<self_type
> (), it1_ (), it2_ () {}
2199 iterator (self_type
&mvi
, const subiterator1_type
&it1
, const subiterator2_type
&it2
):
2200 container_reference
<self_type
> (mvi
), it1_ (it1
), it2_ (it2
) {}
2204 iterator
&operator ++ () {
2210 iterator
&operator -- () {
2216 iterator
&operator += (difference_type n
) {
2222 iterator
&operator -= (difference_type n
) {
2228 difference_type
operator - (const iterator
&it
) const {
2229 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2230 return BOOST_UBLAS_SAME (it1_
- it
.it1_
, it2_
- it
.it2_
);
2235 reference
operator * () const {
2236 // FIXME replace find with at_element
2237 return (*this) ().data_ (*it1_
, *it2_
);
2240 reference
operator [] (difference_type n
) const {
2241 return *(*this + n
);
2246 size_type
index () const {
2247 return BOOST_UBLAS_SAME (it1_
.index (), it2_
.index ());
2252 iterator
&operator = (const iterator
&it
) {
2253 container_reference
<self_type
>::assign (&it ());
2261 bool operator == (const iterator
&it
) const {
2262 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2263 return it1_
== it
.it1_
&& it2_
== it
.it2_
;
2266 bool operator < (const iterator
&it
) const {
2267 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2268 return it1_
< it
.it1_
&& it2_
< it
.it2_
;
2272 subiterator1_type it1_
;
2273 subiterator2_type it2_
;
2275 friend class const_iterator
;
2284 return find (size ());
2288 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
2289 typedef reverse_iterator_base
<iterator
> reverse_iterator
;
2292 const_reverse_iterator
rbegin () const {
2293 return const_reverse_iterator (end ());
2296 const_reverse_iterator
rend () const {
2297 return const_reverse_iterator (begin ());
2300 reverse_iterator
rbegin () {
2301 return reverse_iterator (end ());
2304 reverse_iterator
rend () {
2305 return reverse_iterator (begin ());
2309 matrix_closure_type data_
;
2310 indirect_array_type ia1_
;
2311 indirect_array_type ia2_
;
2314 // Specialize temporary
2315 template <class M
, class IA
>
2316 struct vector_temporary_traits
< matrix_vector_indirect
<M
,IA
> >
2317 : vector_temporary_traits
< M
> {} ;
2318 template <class M
, class IA
>
2319 struct vector_temporary_traits
< const matrix_vector_indirect
<M
,IA
> >
2320 : vector_temporary_traits
< M
> {} ;
2322 // Matrix based range class
2325 public matrix_expression
<matrix_range
<M
> > {
2327 typedef matrix_range
<M
> self_type
;
2329 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2330 using matrix_expression
<self_type
>::operator ();
2332 typedef M matrix_type
;
2333 typedef typename
M::size_type size_type
;
2334 typedef typename
M::difference_type difference_type
;
2335 typedef typename
M::value_type value_type
;
2336 typedef typename
M::const_reference const_reference
;
2337 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
2338 typename
M::const_reference
,
2339 typename
M::reference
>::type reference
;
2340 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
2341 typename
M::const_closure_type
,
2342 typename
M::closure_type
>::type matrix_closure_type
;
2343 typedef basic_range
<size_type
, difference_type
> range_type
;
2344 typedef const self_type const_closure_type
;
2345 typedef self_type closure_type
;
2346 typedef typename storage_restrict_traits
<typename
M::storage_category
,
2347 dense_proxy_tag
>::storage_category storage_category
;
2348 typedef typename
M::orientation_category orientation_category
;
2350 // Construction and destruction
2352 matrix_range (matrix_type
&data
, const range_type
&r1
, const range_type
&r2
):
2353 data_ (data
), r1_ (r1
.preprocess (data
.size1 ())), r2_ (r2
.preprocess (data
.size2 ())) {
2354 // Early checking of preconditions here.
2355 // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
2356 // r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
2357 // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
2358 // r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
2361 matrix_range (const matrix_closure_type
&data
, const range_type
&r1
, const range_type
&r2
, int):
2362 data_ (data
), r1_ (r1
.preprocess (data
.size1 ())), r2_ (r2
.preprocess (data
.size2 ())) {
2363 // Early checking of preconditions here.
2364 // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
2365 // r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
2366 // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
2367 // r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
2372 size_type
start1 () const {
2373 return r1_
.start ();
2376 size_type
size1 () const {
2380 size_type
start2() const {
2381 return r2_
.start ();
2384 size_type
size2 () const {
2388 // Storage accessors
2390 const matrix_closure_type
&data () const {
2394 matrix_closure_type
&data () {
2399 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
2401 const_reference
operator () (size_type i
, size_type j
) const {
2402 return data_ (r1_ (i
), r2_ (j
));
2405 reference
operator () (size_type i
, size_type j
) {
2406 return data_ (r1_ (i
), r2_ (j
));
2410 reference
operator () (size_type i
, size_type j
) const {
2411 return data_ (r1_ (i
), r2_ (j
));
2415 // ISSUE can this be done in free project function?
2416 // Although a const function can create a non-const proxy to a non-const object
2417 // Critical is that matrix_type and data_ (vector_closure_type) are const correct
2419 matrix_range
<matrix_type
> project (const range_type
&r1
, const range_type
&r2
) const {
2420 return matrix_range
<matrix_type
> (data_
, r1_
.compose (r1
.preprocess (data_
.size1 ())), r2_
.compose (r2
.preprocess (data_
.size2 ())), 0);
2425 matrix_range
&operator = (const matrix_range
&mr
) {
2426 matrix_assign
<scalar_assign
> (*this, mr
);
2430 matrix_range
&assign_temporary (matrix_range
&mr
) {
2435 matrix_range
&operator = (const matrix_expression
<AE
> &ae
) {
2436 matrix_assign
<scalar_assign
> (*this, typename matrix_temporary_traits
<M
>::type (ae
));
2441 matrix_range
&assign (const matrix_expression
<AE
> &ae
) {
2442 matrix_assign
<scalar_assign
> (*this, ae
);
2447 matrix_range
& operator += (const matrix_expression
<AE
> &ae
) {
2448 matrix_assign
<scalar_assign
> (*this, typename matrix_temporary_traits
<M
>::type (*this + ae
));
2453 matrix_range
&plus_assign (const matrix_expression
<AE
> &ae
) {
2454 matrix_assign
<scalar_plus_assign
> (*this, ae
);
2459 matrix_range
& operator -= (const matrix_expression
<AE
> &ae
) {
2460 matrix_assign
<scalar_assign
> (*this, typename matrix_temporary_traits
<M
>::type (*this - ae
));
2465 matrix_range
&minus_assign (const matrix_expression
<AE
> &ae
) {
2466 matrix_assign
<scalar_minus_assign
> (*this, ae
);
2471 matrix_range
& operator *= (const AT
&at
) {
2472 matrix_assign_scalar
<scalar_multiplies_assign
> (*this, at
);
2477 matrix_range
& operator /= (const AT
&at
) {
2478 matrix_assign_scalar
<scalar_divides_assign
> (*this, at
);
2482 // Closure comparison
2484 bool same_closure (const matrix_range
&mr
) const {
2485 return (*this).data_
.same_closure (mr
.data_
);
2490 bool operator == (const matrix_range
&mr
) const {
2491 return (*this).data_
== (mr
.data_
) && r1_
== mr
.r1_
&& r2_
== mr
.r2_
;
2496 void swap (matrix_range mr
) {
2498 BOOST_UBLAS_CHECK (size1 () == mr
.size1 (), bad_size ());
2499 BOOST_UBLAS_CHECK (size2 () == mr
.size2 (), bad_size ());
2500 matrix_swap
<scalar_swap
> (*this, mr
);
2504 friend void swap (matrix_range mr1
, matrix_range mr2
) {
2510 typedef typename
M::const_iterator1 const_subiterator1_type
;
2511 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
2512 typename
M::const_iterator1
,
2513 typename
M::iterator1
>::type subiterator1_type
;
2514 typedef typename
M::const_iterator2 const_subiterator2_type
;
2515 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
2516 typename
M::const_iterator2
,
2517 typename
M::iterator2
>::type subiterator2_type
;
2520 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2521 typedef indexed_iterator1
<matrix_range
<matrix_type
>,
2522 typename
subiterator1_type::iterator_category
> iterator1
;
2523 typedef indexed_iterator2
<matrix_range
<matrix_type
>,
2524 typename
subiterator2_type::iterator_category
> iterator2
;
2525 typedef indexed_const_iterator1
<matrix_range
<matrix_type
>,
2526 typename
const_subiterator1_type::iterator_category
> const_iterator1
;
2527 typedef indexed_const_iterator2
<matrix_range
<matrix_type
>,
2528 typename
const_subiterator2_type::iterator_category
> const_iterator2
;
2530 class const_iterator1
;
2532 class const_iterator2
;
2535 typedef reverse_iterator_base1
<const_iterator1
> const_reverse_iterator1
;
2536 typedef reverse_iterator_base1
<iterator1
> reverse_iterator1
;
2537 typedef reverse_iterator_base2
<const_iterator2
> const_reverse_iterator2
;
2538 typedef reverse_iterator_base2
<iterator2
> reverse_iterator2
;
2542 const_iterator1
find1 (int rank
, size_type i
, size_type j
) const {
2543 const_subiterator1_type
it1 (data_
.find1 (rank
, start1 () + i
, start2 () + j
));
2544 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2545 return const_iterator1 (*this, it1
.index1 (), it1
.index2 ());
2547 return const_iterator1 (*this, it1
);
2551 iterator1
find1 (int rank
, size_type i
, size_type j
) {
2552 subiterator1_type
it1 (data_
.find1 (rank
, start1 () + i
, start2 () + j
));
2553 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2554 return iterator1 (*this, it1
.index1 (), it1
.index2 ());
2556 return iterator1 (*this, it1
);
2560 const_iterator2
find2 (int rank
, size_type i
, size_type j
) const {
2561 const_subiterator2_type
it2 (data_
.find2 (rank
, start1 () + i
, start2 () + j
));
2562 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2563 return const_iterator2 (*this, it2
.index1 (), it2
.index2 ());
2565 return const_iterator2 (*this, it2
);
2569 iterator2
find2 (int rank
, size_type i
, size_type j
) {
2570 subiterator2_type
it2 (data_
.find2 (rank
, start1 () + i
, start2 () + j
));
2571 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2572 return iterator2 (*this, it2
.index1 (), it2
.index2 ());
2574 return iterator2 (*this, it2
);
2579 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2580 class const_iterator1
:
2581 public container_const_reference
<matrix_range
>,
2582 public iterator_base_traits
<typename
const_subiterator1_type::iterator_category
>::template
2583 iterator_base
<const_iterator1
, value_type
>::type
{
2585 typedef typename
const_subiterator1_type::value_type value_type
;
2586 typedef typename
const_subiterator1_type::difference_type difference_type
;
2587 typedef typename
const_subiterator1_type::reference reference
;
2588 typedef typename
const_subiterator1_type::pointer pointer
;
2589 typedef const_iterator2 dual_iterator_type
;
2590 typedef const_reverse_iterator2 dual_reverse_iterator_type
;
2592 // Construction and destruction
2595 container_const_reference
<self_type
> (), it_ () {}
2597 const_iterator1 (const self_type
&mr
, const const_subiterator1_type
&it
):
2598 container_const_reference
<self_type
> (mr
), it_ (it
) {}
2600 const_iterator1 (const iterator1
&it
):
2601 container_const_reference
<self_type
> (it ()), it_ (it
.it_
) {}
2605 const_iterator1
&operator ++ () {
2610 const_iterator1
&operator -- () {
2615 const_iterator1
&operator += (difference_type n
) {
2620 const_iterator1
&operator -= (difference_type n
) {
2625 difference_type
operator - (const const_iterator1
&it
) const {
2626 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2627 return it_
- it
.it_
;
2632 const_reference
operator * () const {
2636 const_reference
operator [] (difference_type n
) const {
2637 return *(*this + n
);
2640 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2642 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2643 typename
self_type::
2645 const_iterator2
begin () const {
2646 const self_type
&mr
= (*this) ();
2647 return mr
.find2 (1, index1 (), 0);
2650 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2651 typename
self_type::
2653 const_iterator2
end () const {
2654 const self_type
&mr
= (*this) ();
2655 return mr
.find2 (1, index1 (), mr
.size2 ());
2658 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2659 typename
self_type::
2661 const_reverse_iterator2
rbegin () const {
2662 return const_reverse_iterator2 (end ());
2665 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2666 typename
self_type::
2668 const_reverse_iterator2
rend () const {
2669 return const_reverse_iterator2 (begin ());
2675 size_type
index1 () const {
2676 return it_
.index1 () - (*this) ().start1 ();
2679 size_type
index2 () const {
2680 return it_
.index2 () - (*this) ().start2 ();
2685 const_iterator1
&operator = (const const_iterator1
&it
) {
2686 container_const_reference
<self_type
>::assign (&it ());
2693 bool operator == (const const_iterator1
&it
) const {
2694 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2695 return it_
== it
.it_
;
2698 bool operator < (const const_iterator1
&it
) const {
2699 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2700 return it_
< it
.it_
;
2704 const_subiterator1_type it_
;
2709 const_iterator1
begin1 () const {
2710 return find1 (0, 0, 0);
2713 const_iterator1
end1 () const {
2714 return find1 (0, size1 (), 0);
2717 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2719 public container_reference
<matrix_range
>,
2720 public iterator_base_traits
<typename
subiterator1_type::iterator_category
>::template
2721 iterator_base
<iterator1
, value_type
>::type
{
2723 typedef typename
subiterator1_type::value_type value_type
;
2724 typedef typename
subiterator1_type::difference_type difference_type
;
2725 typedef typename
subiterator1_type::reference reference
;
2726 typedef typename
subiterator1_type::pointer pointer
;
2727 typedef iterator2 dual_iterator_type
;
2728 typedef reverse_iterator2 dual_reverse_iterator_type
;
2730 // Construction and destruction
2733 container_reference
<self_type
> (), it_ () {}
2735 iterator1 (self_type
&mr
, const subiterator1_type
&it
):
2736 container_reference
<self_type
> (mr
), it_ (it
) {}
2740 iterator1
&operator ++ () {
2745 iterator1
&operator -- () {
2750 iterator1
&operator += (difference_type n
) {
2755 iterator1
&operator -= (difference_type n
) {
2760 difference_type
operator - (const iterator1
&it
) const {
2761 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2762 return it_
- it
.it_
;
2767 reference
operator * () const {
2771 reference
operator [] (difference_type n
) const {
2772 return *(*this + n
);
2775 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2777 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2778 typename
self_type::
2780 iterator2
begin () const {
2781 self_type
&mr
= (*this) ();
2782 return mr
.find2 (1, index1 (), 0);
2785 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2786 typename
self_type::
2788 iterator2
end () const {
2789 self_type
&mr
= (*this) ();
2790 return mr
.find2 (1, index1 (), mr
.size2 ());
2793 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2794 typename
self_type::
2796 reverse_iterator2
rbegin () const {
2797 return reverse_iterator2 (end ());
2800 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2801 typename
self_type::
2803 reverse_iterator2
rend () const {
2804 return reverse_iterator2 (begin ());
2810 size_type
index1 () const {
2811 return it_
.index1 () - (*this) ().start1 ();
2814 size_type
index2 () const {
2815 return it_
.index2 () - (*this) ().start2 ();
2820 iterator1
&operator = (const iterator1
&it
) {
2821 container_reference
<self_type
>::assign (&it ());
2828 bool operator == (const iterator1
&it
) const {
2829 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2830 return it_
== it
.it_
;
2833 bool operator < (const iterator1
&it
) const {
2834 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2835 return it_
< it
.it_
;
2839 subiterator1_type it_
;
2841 friend class const_iterator1
;
2846 iterator1
begin1 () {
2847 return find1 (0, 0, 0);
2851 return find1 (0, size1 (), 0);
2854 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2855 class const_iterator2
:
2856 public container_const_reference
<matrix_range
>,
2857 public iterator_base_traits
<typename
const_subiterator2_type::iterator_category
>::template
2858 iterator_base
<const_iterator2
, value_type
>::type
{
2860 typedef typename
const_subiterator2_type::value_type value_type
;
2861 typedef typename
const_subiterator2_type::difference_type difference_type
;
2862 typedef typename
const_subiterator2_type::reference reference
;
2863 typedef typename
const_subiterator2_type::pointer pointer
;
2864 typedef const_iterator1 dual_iterator_type
;
2865 typedef const_reverse_iterator1 dual_reverse_iterator_type
;
2867 // Construction and destruction
2870 container_const_reference
<self_type
> (), it_ () {}
2872 const_iterator2 (const self_type
&mr
, const const_subiterator2_type
&it
):
2873 container_const_reference
<self_type
> (mr
), it_ (it
) {}
2875 const_iterator2 (const iterator2
&it
):
2876 container_const_reference
<self_type
> (it ()), it_ (it
.it_
) {}
2880 const_iterator2
&operator ++ () {
2885 const_iterator2
&operator -- () {
2890 const_iterator2
&operator += (difference_type n
) {
2895 const_iterator2
&operator -= (difference_type n
) {
2900 difference_type
operator - (const const_iterator2
&it
) const {
2901 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2902 return it_
- it
.it_
;
2907 const_reference
operator * () const {
2911 const_reference
operator [] (difference_type n
) const {
2912 return *(*this + n
);
2915 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2917 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2918 typename
self_type::
2920 const_iterator1
begin () const {
2921 const self_type
&mr
= (*this) ();
2922 return mr
.find1 (1, 0, index2 ());
2925 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2926 typename
self_type::
2928 const_iterator1
end () const {
2929 const self_type
&mr
= (*this) ();
2930 return mr
.find1 (1, mr
.size1 (), index2 ());
2933 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2934 typename
self_type::
2936 const_reverse_iterator1
rbegin () const {
2937 return const_reverse_iterator1 (end ());
2940 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2941 typename
self_type::
2943 const_reverse_iterator1
rend () const {
2944 return const_reverse_iterator1 (begin ());
2950 size_type
index1 () const {
2951 return it_
.index1 () - (*this) ().start1 ();
2954 size_type
index2 () const {
2955 return it_
.index2 () - (*this) ().start2 ();
2960 const_iterator2
&operator = (const const_iterator2
&it
) {
2961 container_const_reference
<self_type
>::assign (&it ());
2968 bool operator == (const const_iterator2
&it
) const {
2969 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2970 return it_
== it
.it_
;
2973 bool operator < (const const_iterator2
&it
) const {
2974 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2975 return it_
< it
.it_
;
2979 const_subiterator2_type it_
;
2984 const_iterator2
begin2 () const {
2985 return find2 (0, 0, 0);
2988 const_iterator2
end2 () const {
2989 return find2 (0, 0, size2 ());
2992 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2994 public container_reference
<matrix_range
>,
2995 public iterator_base_traits
<typename
subiterator2_type::iterator_category
>::template
2996 iterator_base
<iterator2
, value_type
>::type
{
2998 typedef typename
subiterator2_type::value_type value_type
;
2999 typedef typename
subiterator2_type::difference_type difference_type
;
3000 typedef typename
subiterator2_type::reference reference
;
3001 typedef typename
subiterator2_type::pointer pointer
;
3002 typedef iterator1 dual_iterator_type
;
3003 typedef reverse_iterator1 dual_reverse_iterator_type
;
3005 // Construction and destruction
3008 container_reference
<self_type
> (), it_ () {}
3010 iterator2 (self_type
&mr
, const subiterator2_type
&it
):
3011 container_reference
<self_type
> (mr
), it_ (it
) {}
3015 iterator2
&operator ++ () {
3020 iterator2
&operator -- () {
3025 iterator2
&operator += (difference_type n
) {
3030 iterator2
&operator -= (difference_type n
) {
3035 difference_type
operator - (const iterator2
&it
) const {
3036 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3037 return it_
- it
.it_
;
3042 reference
operator * () const {
3046 reference
operator [] (difference_type n
) const {
3047 return *(*this + n
);
3050 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3052 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3053 typename
self_type::
3055 iterator1
begin () const {
3056 self_type
&mr
= (*this) ();
3057 return mr
.find1 (1, 0, index2 ());
3060 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3061 typename
self_type::
3063 iterator1
end () const {
3064 self_type
&mr
= (*this) ();
3065 return mr
.find1 (1, mr
.size1 (), index2 ());
3068 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3069 typename
self_type::
3071 reverse_iterator1
rbegin () const {
3072 return reverse_iterator1 (end ());
3075 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3076 typename
self_type::
3078 reverse_iterator1
rend () const {
3079 return reverse_iterator1 (begin ());
3085 size_type
index1 () const {
3086 return it_
.index1 () - (*this) ().start1 ();
3089 size_type
index2 () const {
3090 return it_
.index2 () - (*this) ().start2 ();
3095 iterator2
&operator = (const iterator2
&it
) {
3096 container_reference
<self_type
>::assign (&it ());
3103 bool operator == (const iterator2
&it
) const {
3104 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3105 return it_
== it
.it_
;
3108 bool operator < (const iterator2
&it
) const {
3109 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3110 return it_
< it
.it_
;
3114 subiterator2_type it_
;
3116 friend class const_iterator2
;
3121 iterator2
begin2 () {
3122 return find2 (0, 0, 0);
3126 return find2 (0, 0, size2 ());
3129 // Reverse iterators
3132 const_reverse_iterator1
rbegin1 () const {
3133 return const_reverse_iterator1 (end1 ());
3136 const_reverse_iterator1
rend1 () const {
3137 return const_reverse_iterator1 (begin1 ());
3141 reverse_iterator1
rbegin1 () {
3142 return reverse_iterator1 (end1 ());
3145 reverse_iterator1
rend1 () {
3146 return reverse_iterator1 (begin1 ());
3150 const_reverse_iterator2
rbegin2 () const {
3151 return const_reverse_iterator2 (end2 ());
3154 const_reverse_iterator2
rend2 () const {
3155 return const_reverse_iterator2 (begin2 ());
3159 reverse_iterator2
rbegin2 () {
3160 return reverse_iterator2 (end2 ());
3163 reverse_iterator2
rend2 () {
3164 return reverse_iterator2 (begin2 ());
3168 matrix_closure_type data_
;
3173 // Simple Projections
3176 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
) {
3177 typedef basic_range
<typename
M::size_type
, typename
M::difference_type
> range_type
;
3178 return matrix_range
<M
> (data
, range_type (start1
, stop1
), range_type (start2
, stop2
));
3182 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
) {
3183 typedef basic_range
<typename
M::size_type
, typename
M::difference_type
> range_type
;
3184 return matrix_range
<const M
> (data
, range_type (start1
, stop1
), range_type (start2
, stop2
));
3187 // Generic Projections
3190 matrix_range
<M
> project (M
&data
, const typename matrix_range
<M
>::range_type
&r1
, const typename matrix_range
<M
>::range_type
&r2
) {
3191 return matrix_range
<M
> (data
, r1
, r2
);
3195 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
) {
3196 // ISSUE was: return matrix_range<M> (const_cast<M &> (data), r1, r2);
3197 return matrix_range
<const M
> (data
, r1
, r2
);
3201 matrix_range
<M
> project (matrix_range
<M
> &data
, const typename matrix_range
<M
>::range_type
&r1
, const typename matrix_range
<M
>::range_type
&r2
) {
3202 return data
.project (r1
, r2
);
3206 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
) {
3207 return data
.project (r1
, r2
);
3210 // Specialization of temporary_traits
3212 struct matrix_temporary_traits
< matrix_range
<M
> >
3213 : matrix_temporary_traits
< M
> {} ;
3215 struct matrix_temporary_traits
< const matrix_range
<M
> >
3216 : matrix_temporary_traits
< M
> {} ;
3219 struct vector_temporary_traits
< matrix_range
<M
> >
3220 : vector_temporary_traits
< M
> {} ;
3222 struct vector_temporary_traits
< const matrix_range
<M
> >
3223 : vector_temporary_traits
< M
> {} ;
3225 // Matrix based slice class
3228 public matrix_expression
<matrix_slice
<M
> > {
3230 typedef matrix_slice
<M
> self_type
;
3232 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
3233 using matrix_expression
<self_type
>::operator ();
3235 typedef M matrix_type
;
3236 typedef typename
M::size_type size_type
;
3237 typedef typename
M::difference_type difference_type
;
3238 typedef typename
M::value_type value_type
;
3239 typedef typename
M::const_reference const_reference
;
3240 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
3241 typename
M::const_reference
,
3242 typename
M::reference
>::type reference
;
3243 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
3244 typename
M::const_closure_type
,
3245 typename
M::closure_type
>::type matrix_closure_type
;
3246 typedef basic_range
<size_type
, difference_type
> range_type
;
3247 typedef basic_slice
<size_type
, difference_type
> slice_type
;
3248 typedef const self_type const_closure_type
;
3249 typedef self_type closure_type
;
3250 typedef typename storage_restrict_traits
<typename
M::storage_category
,
3251 dense_proxy_tag
>::storage_category storage_category
;
3252 typedef typename
M::orientation_category orientation_category
;
3254 // Construction and destruction
3256 matrix_slice (matrix_type
&data
, const slice_type
&s1
, const slice_type
&s2
):
3257 data_ (data
), s1_ (s1
.preprocess (data
.size1 ())), s2_ (s2
.preprocess (data
.size2 ())) {
3258 // Early checking of preconditions here.
3259 // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
3260 // s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
3261 // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
3262 // s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
3265 matrix_slice (const matrix_closure_type
&data
, const slice_type
&s1
, const slice_type
&s2
, int):
3266 data_ (data
), s1_ (s1
.preprocess (data
.size1 ())), s2_ (s2
.preprocess (data
.size2 ())) {
3267 // Early checking of preconditions.
3268 // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
3269 // s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
3270 // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
3271 // s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
3276 size_type
start1 () const {
3277 return s1_
.start ();
3280 size_type
start2 () const {
3281 return s2_
.start ();
3284 difference_type
stride1 () const {
3285 return s1_
.stride ();
3288 difference_type
stride2 () const {
3289 return s2_
.stride ();
3292 size_type
size1 () const {
3296 size_type
size2 () const {
3300 // Storage accessors
3302 const matrix_closure_type
&data () const {
3306 matrix_closure_type
&data () {
3311 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
3313 const_reference
operator () (size_type i
, size_type j
) const {
3314 return data_ (s1_ (i
), s2_ (j
));
3317 reference
operator () (size_type i
, size_type j
) {
3318 return data_ (s1_ (i
), s2_ (j
));
3322 reference
operator () (size_type i
, size_type j
) const {
3323 return data_ (s1_ (i
), s2_ (j
));
3327 // ISSUE can this be done in free project function?
3328 // Although a const function can create a non-const proxy to a non-const object
3329 // Critical is that matrix_type and data_ (vector_closure_type) are const correct
3331 matrix_slice
<matrix_type
> project (const range_type
&r1
, const range_type
&r2
) const {
3332 return matrix_slice
<matrix_type
> (data_
, s1_
.compose (r1
.preprocess (data_
.size1 ())), s2_
.compose (r2
.preprocess (data_
.size2 ())), 0);
3335 matrix_slice
<matrix_type
> project (const slice_type
&s1
, const slice_type
&s2
) const {
3336 return matrix_slice
<matrix_type
> (data_
, s1_
.compose (s1
.preprocess (data_
.size1 ())), s2_
.compose (s2
.preprocess (data_
.size2 ())), 0);
3341 matrix_slice
&operator = (const matrix_slice
&ms
) {
3342 matrix_assign
<scalar_assign
> (*this, ms
);
3346 matrix_slice
&assign_temporary (matrix_slice
&ms
) {
3351 matrix_slice
&operator = (const matrix_expression
<AE
> &ae
) {
3352 matrix_assign
<scalar_assign
> (*this, typename matrix_temporary_traits
<M
>::type (ae
));
3357 matrix_slice
&assign (const matrix_expression
<AE
> &ae
) {
3358 matrix_assign
<scalar_assign
> (*this, ae
);
3363 matrix_slice
& operator += (const matrix_expression
<AE
> &ae
) {
3364 matrix_assign
<scalar_assign
> (*this, typename matrix_temporary_traits
<M
>::type (*this + ae
));
3369 matrix_slice
&plus_assign (const matrix_expression
<AE
> &ae
) {
3370 matrix_assign
<scalar_plus_assign
> (*this, ae
);
3375 matrix_slice
& operator -= (const matrix_expression
<AE
> &ae
) {
3376 matrix_assign
<scalar_assign
> (*this, typename matrix_temporary_traits
<M
>::type (*this - ae
));
3381 matrix_slice
&minus_assign (const matrix_expression
<AE
> &ae
) {
3382 matrix_assign
<scalar_minus_assign
> (*this, ae
);
3387 matrix_slice
& operator *= (const AT
&at
) {
3388 matrix_assign_scalar
<scalar_multiplies_assign
> (*this, at
);
3393 matrix_slice
& operator /= (const AT
&at
) {
3394 matrix_assign_scalar
<scalar_divides_assign
> (*this, at
);
3398 // Closure comparison
3400 bool same_closure (const matrix_slice
&ms
) const {
3401 return (*this).data_
.same_closure (ms
.data_
);
3406 bool operator == (const matrix_slice
&ms
) const {
3407 return (*this).data_
== ms
.data_
&& s1_
== ms
.s1_
&& s2_
== ms
.s2_
;
3412 void swap (matrix_slice ms
) {
3414 BOOST_UBLAS_CHECK (size1 () == ms
.size1 (), bad_size ());
3415 BOOST_UBLAS_CHECK (size2 () == ms
.size2 (), bad_size ());
3416 matrix_swap
<scalar_swap
> (*this, ms
);
3420 friend void swap (matrix_slice ms1
, matrix_slice ms2
) {
3426 // Use slice as an index - FIXME this fails for packed assignment
3427 typedef typename
slice_type::const_iterator const_subiterator1_type
;
3428 typedef typename
slice_type::const_iterator subiterator1_type
;
3429 typedef typename
slice_type::const_iterator const_subiterator2_type
;
3430 typedef typename
slice_type::const_iterator subiterator2_type
;
3433 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3434 typedef indexed_iterator1
<matrix_slice
<matrix_type
>,
3435 typename
matrix_type::iterator1::iterator_category
> iterator1
;
3436 typedef indexed_iterator2
<matrix_slice
<matrix_type
>,
3437 typename
matrix_type::iterator2::iterator_category
> iterator2
;
3438 typedef indexed_const_iterator1
<matrix_slice
<matrix_type
>,
3439 typename
matrix_type::const_iterator1::iterator_category
> const_iterator1
;
3440 typedef indexed_const_iterator2
<matrix_slice
<matrix_type
>,
3441 typename
matrix_type::const_iterator2::iterator_category
> const_iterator2
;
3443 class const_iterator1
;
3445 class const_iterator2
;
3448 typedef reverse_iterator_base1
<const_iterator1
> const_reverse_iterator1
;
3449 typedef reverse_iterator_base1
<iterator1
> reverse_iterator1
;
3450 typedef reverse_iterator_base2
<const_iterator2
> const_reverse_iterator2
;
3451 typedef reverse_iterator_base2
<iterator2
> reverse_iterator2
;
3455 const_iterator1
find1 (int /* rank */, size_type i
, size_type j
) const {
3456 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3457 return const_iterator1 (*this, i
, j
);
3459 return const_iterator1 (*this, s1_
.begin () + i
, s2_
.begin () + j
);
3463 iterator1
find1 (int /* rank */, size_type i
, size_type j
) {
3464 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3465 return iterator1 (*this, i
, j
);
3467 return iterator1 (*this, s1_
.begin () + i
, s2_
.begin () + j
);
3471 const_iterator2
find2 (int /* rank */, size_type i
, size_type j
) const {
3472 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3473 return const_iterator2 (*this, i
, j
);
3475 return const_iterator2 (*this, s1_
.begin () + i
, s2_
.begin () + j
);
3479 iterator2
find2 (int /* rank */, size_type i
, size_type j
) {
3480 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3481 return iterator2 (*this, i
, j
);
3483 return iterator2 (*this, s1_
.begin () + i
, s2_
.begin () + j
);
3487 // Iterators simply are indices.
3489 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3490 class const_iterator1
:
3491 public container_const_reference
<matrix_slice
>,
3492 public iterator_base_traits
<typename
M::const_iterator1::iterator_category
>::template
3493 iterator_base
<const_iterator1
, value_type
>::type
{
3495 typedef typename
M::const_iterator1::value_type value_type
;
3496 typedef typename
M::const_iterator1::difference_type difference_type
;
3497 typedef typename
M::const_reference reference
; //FIXME due to indexing access
3498 typedef typename
M::const_iterator1::pointer pointer
;
3499 typedef const_iterator2 dual_iterator_type
;
3500 typedef const_reverse_iterator2 dual_reverse_iterator_type
;
3502 // Construction and destruction
3505 container_const_reference
<self_type
> (), it1_ (), it2_ () {}
3507 const_iterator1 (const self_type
&ms
, const const_subiterator1_type
&it1
, const const_subiterator2_type
&it2
):
3508 container_const_reference
<self_type
> (ms
), it1_ (it1
), it2_ (it2
) {}
3510 const_iterator1 (const iterator1
&it
):
3511 container_const_reference
<self_type
> (it ()), it1_ (it
.it1_
), it2_ (it
.it2_
) {}
3515 const_iterator1
&operator ++ () {
3520 const_iterator1
&operator -- () {
3525 const_iterator1
&operator += (difference_type n
) {
3530 const_iterator1
&operator -= (difference_type n
) {
3535 difference_type
operator - (const const_iterator1
&it
) const {
3536 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3537 BOOST_UBLAS_CHECK (it2_
== it
.it2_
, external_logic ());
3538 return it1_
- it
.it1_
;
3543 const_reference
operator * () const {
3544 // FIXME replace find with at_element
3545 return (*this) ().data_ (*it1_
, *it2_
);
3548 const_reference
operator [] (difference_type n
) const {
3549 return *(*this + n
);
3552 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3554 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3555 typename
self_type::
3557 const_iterator2
begin () const {
3558 return const_iterator2 ((*this) (), it1_
, it2_ ().begin ());
3561 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3562 typename
self_type::
3564 const_iterator2
end () const {
3565 return const_iterator2 ((*this) (), it1_
, it2_ ().end ());
3568 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3569 typename
self_type::
3571 const_reverse_iterator2
rbegin () const {
3572 return const_reverse_iterator2 (end ());
3575 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3576 typename
self_type::
3578 const_reverse_iterator2
rend () const {
3579 return const_reverse_iterator2 (begin ());
3585 size_type
index1 () const {
3586 return it1_
.index ();
3589 size_type
index2 () const {
3590 return it2_
.index ();
3595 const_iterator1
&operator = (const const_iterator1
&it
) {
3596 container_const_reference
<self_type
>::assign (&it ());
3604 bool operator == (const const_iterator1
&it
) const {
3605 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3606 BOOST_UBLAS_CHECK (it2_
== it
.it2_
, external_logic ());
3607 return it1_
== it
.it1_
;
3610 bool operator < (const const_iterator1
&it
) const {
3611 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3612 BOOST_UBLAS_CHECK (it2_
== it
.it2_
, external_logic ());
3613 return it1_
< it
.it1_
;
3617 const_subiterator1_type it1_
;
3618 const_subiterator2_type it2_
;
3623 const_iterator1
begin1 () const {
3624 return find1 (0, 0, 0);
3627 const_iterator1
end1 () const {
3628 return find1 (0, size1 (), 0);
3631 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3633 public container_reference
<matrix_slice
>,
3634 public iterator_base_traits
<typename
M::iterator1::iterator_category
>::template
3635 iterator_base
<iterator1
, value_type
>::type
{
3637 typedef typename
M::iterator1::value_type value_type
;
3638 typedef typename
M::iterator1::difference_type difference_type
;
3639 typedef typename
M::reference reference
; //FIXME due to indexing access
3640 typedef typename
M::iterator1::pointer pointer
;
3641 typedef iterator2 dual_iterator_type
;
3642 typedef reverse_iterator2 dual_reverse_iterator_type
;
3644 // Construction and destruction
3647 container_reference
<self_type
> (), it1_ (), it2_ () {}
3649 iterator1 (self_type
&ms
, const subiterator1_type
&it1
, const subiterator2_type
&it2
):
3650 container_reference
<self_type
> (ms
), it1_ (it1
), it2_ (it2
) {}
3654 iterator1
&operator ++ () {
3659 iterator1
&operator -- () {
3664 iterator1
&operator += (difference_type n
) {
3669 iterator1
&operator -= (difference_type n
) {
3674 difference_type
operator - (const iterator1
&it
) const {
3675 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3676 BOOST_UBLAS_CHECK (it2_
== it
.it2_
, external_logic ());
3677 return it1_
- it
.it1_
;
3682 reference
operator * () const {
3683 // FIXME replace find with at_element
3684 return (*this) ().data_ (*it1_
, *it2_
);
3687 reference
operator [] (difference_type n
) const {
3688 return *(*this + n
);
3691 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3693 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3694 typename
self_type::
3696 iterator2
begin () const {
3697 return iterator2 ((*this) (), it1_
, it2_ ().begin ());
3700 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3701 typename
self_type::
3703 iterator2
end () const {
3704 return iterator2 ((*this) (), it1_
, it2_ ().end ());
3707 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3708 typename
self_type::
3710 reverse_iterator2
rbegin () const {
3711 return reverse_iterator2 (end ());
3714 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3715 typename
self_type::
3717 reverse_iterator2
rend () const {
3718 return reverse_iterator2 (begin ());
3724 size_type
index1 () const {
3725 return it1_
.index ();
3728 size_type
index2 () const {
3729 return it2_
.index ();
3734 iterator1
&operator = (const iterator1
&it
) {
3735 container_reference
<self_type
>::assign (&it ());
3743 bool operator == (const iterator1
&it
) const {
3744 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3745 BOOST_UBLAS_CHECK (it2_
== it
.it2_
, external_logic ());
3746 return it1_
== it
.it1_
;
3749 bool operator < (const iterator1
&it
) const {
3750 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3751 BOOST_UBLAS_CHECK (it2_
== it
.it2_
, external_logic ());
3752 return it1_
< it
.it1_
;
3756 subiterator1_type it1_
;
3757 subiterator2_type it2_
;
3759 friend class const_iterator1
;
3764 iterator1
begin1 () {
3765 return find1 (0, 0, 0);
3769 return find1 (0, size1 (), 0);
3772 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3773 class const_iterator2
:
3774 public container_const_reference
<matrix_slice
>,
3775 public iterator_base_traits
<typename
M::const_iterator2::iterator_category
>::template
3776 iterator_base
<const_iterator2
, value_type
>::type
{
3778 typedef typename
M::const_iterator2::value_type value_type
;
3779 typedef typename
M::const_iterator2::difference_type difference_type
;
3780 typedef typename
M::const_reference reference
; //FIXME due to indexing access
3781 typedef typename
M::const_iterator2::pointer pointer
;
3782 typedef const_iterator1 dual_iterator_type
;
3783 typedef const_reverse_iterator1 dual_reverse_iterator_type
;
3785 // Construction and destruction
3788 container_const_reference
<self_type
> (), it1_ (), it2_ () {}
3790 const_iterator2 (const self_type
&ms
, const const_subiterator1_type
&it1
, const const_subiterator2_type
&it2
):
3791 container_const_reference
<self_type
> (ms
), it1_ (it1
), it2_ (it2
) {}
3793 const_iterator2 (const iterator2
&it
):
3794 container_const_reference
<self_type
> (it ()), it1_ (it
.it1_
), it2_ (it
.it2_
) {}
3798 const_iterator2
&operator ++ () {
3803 const_iterator2
&operator -- () {
3808 const_iterator2
&operator += (difference_type n
) {
3813 const_iterator2
&operator -= (difference_type n
) {
3818 difference_type
operator - (const const_iterator2
&it
) const {
3819 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3820 BOOST_UBLAS_CHECK (it1_
== it
.it1_
, external_logic ());
3821 return it2_
- it
.it2_
;
3826 const_reference
operator * () const {
3827 // FIXME replace find with at_element
3828 return (*this) ().data_ (*it1_
, *it2_
);
3831 const_reference
operator [] (difference_type n
) const {
3832 return *(*this + n
);
3835 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3837 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3838 typename
self_type::
3840 const_iterator1
begin () const {
3841 return const_iterator1 ((*this) (), it1_ ().begin (), it2_
);
3844 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3845 typename
self_type::
3847 const_iterator1
end () const {
3848 return const_iterator1 ((*this) (), it1_ ().end (), it2_
);
3851 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3852 typename
self_type::
3854 const_reverse_iterator1
rbegin () const {
3855 return const_reverse_iterator1 (end ());
3858 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3859 typename
self_type::
3861 const_reverse_iterator1
rend () const {
3862 return const_reverse_iterator1 (begin ());
3868 size_type
index1 () const {
3869 return it1_
.index ();
3872 size_type
index2 () const {
3873 return it2_
.index ();
3878 const_iterator2
&operator = (const const_iterator2
&it
) {
3879 container_const_reference
<self_type
>::assign (&it ());
3887 bool operator == (const const_iterator2
&it
) const {
3888 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3889 BOOST_UBLAS_CHECK (it1_
== it
.it1_
, external_logic ());
3890 return it2_
== it
.it2_
;
3893 bool operator < (const const_iterator2
&it
) const {
3894 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3895 BOOST_UBLAS_CHECK (it1_
== it
.it1_
, external_logic ());
3896 return it2_
< it
.it2_
;
3900 const_subiterator1_type it1_
;
3901 const_subiterator2_type it2_
;
3906 const_iterator2
begin2 () const {
3907 return find2 (0, 0, 0);
3910 const_iterator2
end2 () const {
3911 return find2 (0, 0, size2 ());
3914 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3916 public container_reference
<matrix_slice
>,
3917 public iterator_base_traits
<typename
M::iterator2::iterator_category
>::template
3918 iterator_base
<iterator2
, value_type
>::type
{
3920 typedef typename
M::iterator2::value_type value_type
;
3921 typedef typename
M::iterator2::difference_type difference_type
;
3922 typedef typename
M::reference reference
; //FIXME due to indexing access
3923 typedef typename
M::iterator2::pointer pointer
;
3924 typedef iterator1 dual_iterator_type
;
3925 typedef reverse_iterator1 dual_reverse_iterator_type
;
3927 // Construction and destruction
3930 container_reference
<self_type
> (), it1_ (), it2_ () {}
3932 iterator2 (self_type
&ms
, const subiterator1_type
&it1
, const subiterator2_type
&it2
):
3933 container_reference
<self_type
> (ms
), it1_ (it1
), it2_ (it2
) {}
3937 iterator2
&operator ++ () {
3942 iterator2
&operator -- () {
3947 iterator2
&operator += (difference_type n
) {
3952 iterator2
&operator -= (difference_type n
) {
3957 difference_type
operator - (const iterator2
&it
) const {
3958 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3959 BOOST_UBLAS_CHECK (it1_
== it
.it1_
, external_logic ());
3960 return it2_
- it
.it2_
;
3965 reference
operator * () const {
3966 // FIXME replace find with at_element
3967 return (*this) ().data_ (*it1_
, *it2_
);
3970 reference
operator [] (difference_type n
) const {
3971 return *(*this + n
);
3974 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3976 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3977 typename
self_type::
3979 iterator1
begin () const {
3980 return iterator1 ((*this) (), it1_ ().begin (), it2_
);
3983 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3984 typename
self_type::
3986 iterator1
end () const {
3987 return iterator1 ((*this) (), it1_ ().end (), it2_
);
3990 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3991 typename
self_type::
3993 reverse_iterator1
rbegin () const {
3994 return reverse_iterator1 (end ());
3997 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3998 typename
self_type::
4000 reverse_iterator1
rend () const {
4001 return reverse_iterator1 (begin ());
4007 size_type
index1 () const {
4008 return it1_
.index ();
4011 size_type
index2 () const {
4012 return it2_
.index ();
4017 iterator2
&operator = (const iterator2
&it
) {
4018 container_reference
<self_type
>::assign (&it ());
4026 bool operator == (const iterator2
&it
) const {
4027 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4028 BOOST_UBLAS_CHECK (it1_
== it
.it1_
, external_logic ());
4029 return it2_
== it
.it2_
;
4032 bool operator < (const iterator2
&it
) const {
4033 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4034 BOOST_UBLAS_CHECK (it1_
== it
.it1_
, external_logic ());
4035 return it2_
< it
.it2_
;
4039 subiterator1_type it1_
;
4040 subiterator2_type it2_
;
4042 friend class const_iterator2
;
4047 iterator2
begin2 () {
4048 return find2 (0, 0, 0);
4052 return find2 (0, 0, size2 ());
4055 // Reverse iterators
4058 const_reverse_iterator1
rbegin1 () const {
4059 return const_reverse_iterator1 (end1 ());
4062 const_reverse_iterator1
rend1 () const {
4063 return const_reverse_iterator1 (begin1 ());
4067 reverse_iterator1
rbegin1 () {
4068 return reverse_iterator1 (end1 ());
4071 reverse_iterator1
rend1 () {
4072 return reverse_iterator1 (begin1 ());
4076 const_reverse_iterator2
rbegin2 () const {
4077 return const_reverse_iterator2 (end2 ());
4080 const_reverse_iterator2
rend2 () const {
4081 return const_reverse_iterator2 (begin2 ());
4085 reverse_iterator2
rbegin2 () {
4086 return reverse_iterator2 (end2 ());
4089 reverse_iterator2
rend2 () {
4090 return reverse_iterator2 (begin2 ());
4094 matrix_closure_type data_
;
4099 // Simple Projections
4102 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
) {
4103 typedef basic_slice
<typename
M::size_type
, typename
M::difference_type
> slice_type
;
4104 return matrix_slice
<M
> (data
, slice_type (start1
, stride1
, size1
), slice_type (start2
, stride2
, size2
));
4108 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
) {
4109 typedef basic_slice
<typename
M::size_type
, typename
M::difference_type
> slice_type
;
4110 return matrix_slice
<const M
> (data
, slice_type (start1
, stride1
, size1
), slice_type (start2
, stride2
, size2
));
4113 // Generic Projections
4116 matrix_slice
<M
> project (M
&data
, const typename matrix_slice
<M
>::slice_type
&s1
, const typename matrix_slice
<M
>::slice_type
&s2
) {
4117 return matrix_slice
<M
> (data
, s1
, s2
);
4121 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
) {
4122 // ISSUE was: return matrix_slice<M> (const_cast<M &> (data), s1, s2);
4123 return matrix_slice
<const M
> (data
, s1
, s2
);
4125 // 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
4128 matrix_slice
<M
> project (matrix_slice
<M
> &data
, const typename matrix_range
<M
>::range_type
&r1
, const typename matrix_range
<M
>::range_type
&r2
) {
4129 return data
.project (r1
, r2
);
4133 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
) {
4134 return data
.project (r1
, r2
);
4138 matrix_slice
<M
> project (matrix_slice
<M
> &data
, const typename matrix_slice
<M
>::slice_type
&s1
, const typename matrix_slice
<M
>::slice_type
&s2
) {
4139 return data
.project (s1
, s2
);
4143 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
) {
4144 return data
.project (s1
, s2
);
4147 // Specialization of temporary_traits
4149 struct matrix_temporary_traits
< matrix_slice
<M
> >
4150 : matrix_temporary_traits
< M
> {};
4152 struct matrix_temporary_traits
< const matrix_slice
<M
> >
4153 : matrix_temporary_traits
< M
> {};
4156 struct vector_temporary_traits
< matrix_slice
<M
> >
4157 : vector_temporary_traits
< M
> {};
4159 struct vector_temporary_traits
< const matrix_slice
<M
> >
4160 : vector_temporary_traits
< M
> {};
4162 // Matrix based indirection class
4163 // Contributed by Toon Knapen.
4164 // Extended and optimized by Kresimir Fresl.
4165 template<class M
, class IA
>
4166 class matrix_indirect
:
4167 public matrix_expression
<matrix_indirect
<M
, IA
> > {
4169 typedef matrix_indirect
<M
, IA
> self_type
;
4171 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4172 using matrix_expression
<self_type
>::operator ();
4174 typedef M matrix_type
;
4175 typedef IA indirect_array_type
;
4176 typedef typename
M::size_type size_type
;
4177 typedef typename
M::difference_type difference_type
;
4178 typedef typename
M::value_type value_type
;
4179 typedef typename
M::const_reference const_reference
;
4180 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
4181 typename
M::const_reference
,
4182 typename
M::reference
>::type reference
;
4183 typedef typename
boost::mpl::if_
<boost::is_const
<M
>,
4184 typename
M::const_closure_type
,
4185 typename
M::closure_type
>::type matrix_closure_type
;
4186 typedef basic_range
<size_type
, difference_type
> range_type
;
4187 typedef basic_slice
<size_type
, difference_type
> slice_type
;
4188 typedef const self_type const_closure_type
;
4189 typedef self_type closure_type
;
4190 typedef typename storage_restrict_traits
<typename
M::storage_category
,
4191 dense_proxy_tag
>::storage_category storage_category
;
4192 typedef typename
M::orientation_category orientation_category
;
4194 // Construction and destruction
4196 matrix_indirect (matrix_type
&data
, size_type size1
, size_type size2
):
4197 data_ (data
), ia1_ (size1
), ia2_ (size2
) {}
4199 matrix_indirect (matrix_type
&data
, const indirect_array_type
&ia1
, const indirect_array_type
&ia2
):
4200 data_ (data
), ia1_ (ia1
.preprocess (data
.size1 ())), ia2_ (ia2
.preprocess (data
.size2 ())) {}
4202 matrix_indirect (const matrix_closure_type
&data
, const indirect_array_type
&ia1
, const indirect_array_type
&ia2
, int):
4203 data_ (data
), ia1_ (ia1
.preprocess (data
.size1 ())), ia2_ (ia2
.preprocess (data
.size2 ())) {}
4207 size_type
size1 () const {
4208 return ia1_
.size ();
4211 size_type
size2 () const {
4212 return ia2_
.size ();
4215 const indirect_array_type
&indirect1 () const {
4219 indirect_array_type
&indirect1 () {
4223 const indirect_array_type
&indirect2 () const {
4227 indirect_array_type
&indirect2 () {
4231 // Storage accessors
4233 const matrix_closure_type
&data () const {
4237 matrix_closure_type
&data () {
4242 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
4244 const_reference
operator () (size_type i
, size_type j
) const {
4245 return data_ (ia1_ (i
), ia2_ (j
));
4248 reference
operator () (size_type i
, size_type j
) {
4249 return data_ (ia1_ (i
), ia2_ (j
));
4253 reference
operator () (size_type i
, size_type j
) const {
4254 return data_ (ia1_ (i
), ia2_ (j
));
4258 // ISSUE can this be done in free project function?
4259 // Although a const function can create a non-const proxy to a non-const object
4260 // Critical is that matrix_type and data_ (vector_closure_type) are const correct
4262 matrix_indirect
<matrix_type
, indirect_array_type
> project (const range_type
&r1
, const range_type
&r2
) const {
4263 return matrix_indirect
<matrix_type
, indirect_array_type
> (data_
, ia1_
.compose (r1
.preprocess (data_
.size1 ())), ia2_
.compose (r2
.preprocess (data_
.size2 ())), 0);
4266 matrix_indirect
<matrix_type
, indirect_array_type
> project (const slice_type
&s1
, const slice_type
&s2
) const {
4267 return matrix_indirect
<matrix_type
, indirect_array_type
> (data_
, ia1_
.compose (s1
.preprocess (data_
.size1 ())), ia2_
.compose (s2
.preprocess (data_
.size2 ())), 0);
4270 matrix_indirect
<matrix_type
, indirect_array_type
> project (const indirect_array_type
&ia1
, const indirect_array_type
&ia2
) const {
4271 return matrix_indirect
<matrix_type
, indirect_array_type
> (data_
, ia1_
.compose (ia1
.preprocess (data_
.size1 ())), ia2_
.compose (ia2
.preprocess (data_
.size2 ())), 0);
4276 matrix_indirect
&operator = (const matrix_indirect
&mi
) {
4277 matrix_assign
<scalar_assign
> (*this, mi
);
4281 matrix_indirect
&assign_temporary (matrix_indirect
&mi
) {
4286 matrix_indirect
&operator = (const matrix_expression
<AE
> &ae
) {
4287 matrix_assign
<scalar_assign
> (*this, typename matrix_temporary_traits
<M
>::type (ae
));
4292 matrix_indirect
&assign (const matrix_expression
<AE
> &ae
) {
4293 matrix_assign
<scalar_assign
> (*this, ae
);
4298 matrix_indirect
& operator += (const matrix_expression
<AE
> &ae
) {
4299 matrix_assign
<scalar_assign
> (*this, typename matrix_temporary_traits
<M
>::type (*this + ae
));
4304 matrix_indirect
&plus_assign (const matrix_expression
<AE
> &ae
) {
4305 matrix_assign
<scalar_plus_assign
> (*this, ae
);
4310 matrix_indirect
& operator -= (const matrix_expression
<AE
> &ae
) {
4311 matrix_assign
<scalar_assign
> (*this, typename matrix_temporary_traits
<M
>::type (*this - ae
));
4316 matrix_indirect
&minus_assign (const matrix_expression
<AE
> &ae
) {
4317 matrix_assign
<scalar_minus_assign
> (*this, ae
);
4322 matrix_indirect
& operator *= (const AT
&at
) {
4323 matrix_assign_scalar
<scalar_multiplies_assign
> (*this, at
);
4328 matrix_indirect
& operator /= (const AT
&at
) {
4329 matrix_assign_scalar
<scalar_divides_assign
> (*this, at
);
4333 // Closure comparison
4335 bool same_closure (const matrix_indirect
&mi
) const {
4336 return (*this).data_
.same_closure (mi
.data_
);
4341 bool operator == (const matrix_indirect
&mi
) const {
4342 return (*this).data_
== mi
.data_
&& ia1_
== mi
.ia1_
&& ia2_
== mi
.ia2_
;
4347 void swap (matrix_indirect mi
) {
4349 BOOST_UBLAS_CHECK (size1 () == mi
.size1 (), bad_size ());
4350 BOOST_UBLAS_CHECK (size2 () == mi
.size2 (), bad_size ());
4351 matrix_swap
<scalar_swap
> (*this, mi
);
4355 friend void swap (matrix_indirect mi1
, matrix_indirect mi2
) {
4361 typedef typename
IA::const_iterator const_subiterator1_type
;
4362 typedef typename
IA::const_iterator subiterator1_type
;
4363 typedef typename
IA::const_iterator const_subiterator2_type
;
4364 typedef typename
IA::const_iterator subiterator2_type
;
4367 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4368 typedef indexed_iterator1
<matrix_indirect
<matrix_type
, indirect_array_type
>,
4369 typename
matrix_type::iterator1::iterator_category
> iterator1
;
4370 typedef indexed_iterator2
<matrix_indirect
<matrix_type
, indirect_array_type
>,
4371 typename
matrix_type::iterator2::iterator_category
> iterator2
;
4372 typedef indexed_const_iterator1
<matrix_indirect
<matrix_type
, indirect_array_type
>,
4373 typename
matrix_type::const_iterator1::iterator_category
> const_iterator1
;
4374 typedef indexed_const_iterator2
<matrix_indirect
<matrix_type
, indirect_array_type
>,
4375 typename
matrix_type::const_iterator2::iterator_category
> const_iterator2
;
4377 class const_iterator1
;
4379 class const_iterator2
;
4382 typedef reverse_iterator_base1
<const_iterator1
> const_reverse_iterator1
;
4383 typedef reverse_iterator_base1
<iterator1
> reverse_iterator1
;
4384 typedef reverse_iterator_base2
<const_iterator2
> const_reverse_iterator2
;
4385 typedef reverse_iterator_base2
<iterator2
> reverse_iterator2
;
4389 const_iterator1
find1 (int /* rank */, size_type i
, size_type j
) const {
4390 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4391 return const_iterator1 (*this, i
, j
);
4393 return const_iterator1 (*this, ia1_
.begin () + i
, ia2_
.begin () + j
);
4397 iterator1
find1 (int /* rank */, size_type i
, size_type j
) {
4398 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4399 return iterator1 (*this, i
, j
);
4401 return iterator1 (*this, ia1_
.begin () + i
, ia2_
.begin () + j
);
4405 const_iterator2
find2 (int /* rank */, size_type i
, size_type j
) const {
4406 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4407 return const_iterator2 (*this, i
, j
);
4409 return const_iterator2 (*this, ia1_
.begin () + i
, ia2_
.begin () + j
);
4413 iterator2
find2 (int /* rank */, size_type i
, size_type j
) {
4414 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4415 return iterator2 (*this, i
, j
);
4417 return iterator2 (*this, ia1_
.begin () + i
, ia2_
.begin () + j
);
4421 // Iterators simply are indices.
4423 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4424 class const_iterator1
:
4425 public container_const_reference
<matrix_indirect
>,
4426 public iterator_base_traits
<typename
M::const_iterator1::iterator_category
>::template
4427 iterator_base
<const_iterator1
, value_type
>::type
{
4429 typedef typename
M::const_iterator1::value_type value_type
;
4430 typedef typename
M::const_iterator1::difference_type difference_type
;
4431 typedef typename
M::const_reference reference
; //FIXME due to indexing access
4432 typedef typename
M::const_iterator1::pointer pointer
;
4433 typedef const_iterator2 dual_iterator_type
;
4434 typedef const_reverse_iterator2 dual_reverse_iterator_type
;
4436 // Construction and destruction
4439 container_const_reference
<self_type
> (), it1_ (), it2_ () {}
4441 const_iterator1 (const self_type
&mi
, const const_subiterator1_type
&it1
, const const_subiterator2_type
&it2
):
4442 container_const_reference
<self_type
> (mi
), it1_ (it1
), it2_ (it2
) {}
4444 const_iterator1 (const iterator1
&it
):
4445 container_const_reference
<self_type
> (it ()), it1_ (it
.it1_
), it2_ (it
.it2_
) {}
4449 const_iterator1
&operator ++ () {
4454 const_iterator1
&operator -- () {
4459 const_iterator1
&operator += (difference_type n
) {
4464 const_iterator1
&operator -= (difference_type n
) {
4469 difference_type
operator - (const const_iterator1
&it
) const {
4470 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4471 BOOST_UBLAS_CHECK (it2_
== it
.it2_
, external_logic ());
4472 return it1_
- it
.it1_
;
4477 const_reference
operator * () const {
4478 // FIXME replace find with at_element
4479 return (*this) ().data_ (*it1_
, *it2_
);
4482 const_reference
operator [] (difference_type n
) const {
4483 return *(*this + n
);
4486 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4488 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4489 typename
self_type::
4491 const_iterator2
begin () const {
4492 return const_iterator2 ((*this) (), it1_
, it2_ ().begin ());
4495 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4496 typename
self_type::
4498 const_iterator2
end () const {
4499 return const_iterator2 ((*this) (), it1_
, it2_ ().end ());
4502 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4503 typename
self_type::
4505 const_reverse_iterator2
rbegin () const {
4506 return const_reverse_iterator2 (end ());
4509 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4510 typename
self_type::
4512 const_reverse_iterator2
rend () const {
4513 return const_reverse_iterator2 (begin ());
4519 size_type
index1 () const {
4520 return it1_
.index ();
4523 size_type
index2 () const {
4524 return it2_
.index ();
4529 const_iterator1
&operator = (const const_iterator1
&it
) {
4530 container_const_reference
<self_type
>::assign (&it ());
4538 bool operator == (const const_iterator1
&it
) const {
4539 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4540 BOOST_UBLAS_CHECK (it2_
== it
.it2_
, external_logic ());
4541 return it1_
== it
.it1_
;
4544 bool operator < (const const_iterator1
&it
) const {
4545 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4546 BOOST_UBLAS_CHECK (it2_
== it
.it2_
, external_logic ());
4547 return it1_
< it
.it1_
;
4551 const_subiterator1_type it1_
;
4552 const_subiterator2_type it2_
;
4557 const_iterator1
begin1 () const {
4558 return find1 (0, 0, 0);
4561 const_iterator1
end1 () const {
4562 return find1 (0, size1 (), 0);
4565 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4567 public container_reference
<matrix_indirect
>,
4568 public iterator_base_traits
<typename
M::iterator1::iterator_category
>::template
4569 iterator_base
<iterator1
, value_type
>::type
{
4571 typedef typename
M::iterator1::value_type value_type
;
4572 typedef typename
M::iterator1::difference_type difference_type
;
4573 typedef typename
M::reference reference
; //FIXME due to indexing access
4574 typedef typename
M::iterator1::pointer pointer
;
4575 typedef iterator2 dual_iterator_type
;
4576 typedef reverse_iterator2 dual_reverse_iterator_type
;
4578 // Construction and destruction
4581 container_reference
<self_type
> (), it1_ (), it2_ () {}
4583 iterator1 (self_type
&mi
, const subiterator1_type
&it1
, const subiterator2_type
&it2
):
4584 container_reference
<self_type
> (mi
), it1_ (it1
), it2_ (it2
) {}
4588 iterator1
&operator ++ () {
4593 iterator1
&operator -- () {
4598 iterator1
&operator += (difference_type n
) {
4603 iterator1
&operator -= (difference_type n
) {
4608 difference_type
operator - (const iterator1
&it
) const {
4609 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4610 BOOST_UBLAS_CHECK (it2_
== it
.it2_
, external_logic ());
4611 return it1_
- it
.it1_
;
4616 reference
operator * () const {
4617 // FIXME replace find with at_element
4618 return (*this) ().data_ (*it1_
, *it2_
);
4621 reference
operator [] (difference_type n
) const {
4622 return *(*this + n
);
4625 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4627 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4628 typename
self_type::
4630 iterator2
begin () const {
4631 return iterator2 ((*this) (), it1_
, it2_ ().begin ());
4634 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4635 typename
self_type::
4637 iterator2
end () const {
4638 return iterator2 ((*this) (), it1_
, it2_ ().end ());
4641 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4642 typename
self_type::
4644 reverse_iterator2
rbegin () const {
4645 return reverse_iterator2 (end ());
4648 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4649 typename
self_type::
4651 reverse_iterator2
rend () const {
4652 return reverse_iterator2 (begin ());
4658 size_type
index1 () const {
4659 return it1_
.index ();
4662 size_type
index2 () const {
4663 return it2_
.index ();
4668 iterator1
&operator = (const iterator1
&it
) {
4669 container_reference
<self_type
>::assign (&it ());
4677 bool operator == (const iterator1
&it
) const {
4678 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4679 BOOST_UBLAS_CHECK (it2_
== it
.it2_
, external_logic ());
4680 return it1_
== it
.it1_
;
4683 bool operator < (const iterator1
&it
) const {
4684 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4685 BOOST_UBLAS_CHECK (it2_
== it
.it2_
, external_logic ());
4686 return it1_
< it
.it1_
;
4690 subiterator1_type it1_
;
4691 subiterator2_type it2_
;
4693 friend class const_iterator1
;
4698 iterator1
begin1 () {
4699 return find1 (0, 0, 0);
4703 return find1 (0, size1 (), 0);
4706 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4707 class const_iterator2
:
4708 public container_const_reference
<matrix_indirect
>,
4709 public iterator_base_traits
<typename
M::const_iterator2::iterator_category
>::template
4710 iterator_base
<const_iterator2
, value_type
>::type
{
4712 typedef typename
M::const_iterator2::value_type value_type
;
4713 typedef typename
M::const_iterator2::difference_type difference_type
;
4714 typedef typename
M::const_reference reference
; //FIXME due to indexing access
4715 typedef typename
M::const_iterator2::pointer pointer
;
4716 typedef const_iterator1 dual_iterator_type
;
4717 typedef const_reverse_iterator1 dual_reverse_iterator_type
;
4719 // Construction and destruction
4722 container_const_reference
<self_type
> (), it1_ (), it2_ () {}
4724 const_iterator2 (const self_type
&mi
, const const_subiterator1_type
&it1
, const const_subiterator2_type
&it2
):
4725 container_const_reference
<self_type
> (mi
), it1_ (it1
), it2_ (it2
) {}
4727 const_iterator2 (const iterator2
&it
):
4728 container_const_reference
<self_type
> (it ()), it1_ (it
.it1_
), it2_ (it
.it2_
) {}
4732 const_iterator2
&operator ++ () {
4737 const_iterator2
&operator -- () {
4742 const_iterator2
&operator += (difference_type n
) {
4747 const_iterator2
&operator -= (difference_type n
) {
4752 difference_type
operator - (const const_iterator2
&it
) const {
4753 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4754 BOOST_UBLAS_CHECK (it1_
== it
.it1_
, external_logic ());
4755 return it2_
- it
.it2_
;
4760 const_reference
operator * () const {
4761 // FIXME replace find with at_element
4762 return (*this) ().data_ (*it1_
, *it2_
);
4765 const_reference
operator [] (difference_type n
) const {
4766 return *(*this + n
);
4769 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4771 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4772 typename
self_type::
4774 const_iterator1
begin () const {
4775 return const_iterator1 ((*this) (), it1_ ().begin (), it2_
);
4778 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4779 typename
self_type::
4781 const_iterator1
end () const {
4782 return const_iterator1 ((*this) (), it1_ ().end (), it2_
);
4785 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4786 typename
self_type::
4788 const_reverse_iterator1
rbegin () const {
4789 return const_reverse_iterator1 (end ());
4792 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4793 typename
self_type::
4795 const_reverse_iterator1
rend () const {
4796 return const_reverse_iterator1 (begin ());
4802 size_type
index1 () const {
4803 return it1_
.index ();
4806 size_type
index2 () const {
4807 return it2_
.index ();
4812 const_iterator2
&operator = (const const_iterator2
&it
) {
4813 container_const_reference
<self_type
>::assign (&it ());
4821 bool operator == (const const_iterator2
&it
) const {
4822 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4823 BOOST_UBLAS_CHECK (it1_
== it
.it1_
, external_logic ());
4824 return it2_
== it
.it2_
;
4827 bool operator < (const const_iterator2
&it
) const {
4828 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4829 BOOST_UBLAS_CHECK (it1_
== it
.it1_
, external_logic ());
4830 return it2_
< it
.it2_
;
4834 const_subiterator1_type it1_
;
4835 const_subiterator2_type it2_
;
4840 const_iterator2
begin2 () const {
4841 return find2 (0, 0, 0);
4844 const_iterator2
end2 () const {
4845 return find2 (0, 0, size2 ());
4848 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4850 public container_reference
<matrix_indirect
>,
4851 public iterator_base_traits
<typename
M::iterator2::iterator_category
>::template
4852 iterator_base
<iterator2
, value_type
>::type
{
4854 typedef typename
M::iterator2::value_type value_type
;
4855 typedef typename
M::iterator2::difference_type difference_type
;
4856 typedef typename
M::reference reference
; //FIXME due to indexing access
4857 typedef typename
M::iterator2::pointer pointer
;
4858 typedef iterator1 dual_iterator_type
;
4859 typedef reverse_iterator1 dual_reverse_iterator_type
;
4861 // Construction and destruction
4864 container_reference
<self_type
> (), it1_ (), it2_ () {}
4866 iterator2 (self_type
&mi
, const subiterator1_type
&it1
, const subiterator2_type
&it2
):
4867 container_reference
<self_type
> (mi
), it1_ (it1
), it2_ (it2
) {}
4871 iterator2
&operator ++ () {
4876 iterator2
&operator -- () {
4881 iterator2
&operator += (difference_type n
) {
4886 iterator2
&operator -= (difference_type n
) {
4891 difference_type
operator - (const iterator2
&it
) const {
4892 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4893 BOOST_UBLAS_CHECK (it1_
== it
.it1_
, external_logic ());
4894 return it2_
- it
.it2_
;
4899 reference
operator * () const {
4900 // FIXME replace find with at_element
4901 return (*this) ().data_ (*it1_
, *it2_
);
4904 reference
operator [] (difference_type n
) const {
4905 return *(*this + n
);
4908 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4910 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4911 typename
self_type::
4913 iterator1
begin () const {
4914 return iterator1 ((*this) (), it1_ ().begin (), it2_
);
4917 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4918 typename
self_type::
4920 iterator1
end () const {
4921 return iterator1 ((*this) (), it1_ ().end (), it2_
);
4924 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4925 typename
self_type::
4927 reverse_iterator1
rbegin () const {
4928 return reverse_iterator1 (end ());
4931 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4932 typename
self_type::
4934 reverse_iterator1
rend () const {
4935 return reverse_iterator1 (begin ());
4941 size_type
index1 () const {
4942 return it1_
.index ();
4945 size_type
index2 () const {
4946 return it2_
.index ();
4951 iterator2
&operator = (const iterator2
&it
) {
4952 container_reference
<self_type
>::assign (&it ());
4960 bool operator == (const iterator2
&it
) const {
4961 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4962 BOOST_UBLAS_CHECK (it1_
== it
.it1_
, external_logic ());
4963 return it2_
== it
.it2_
;
4966 bool operator < (const iterator2
&it
) const {
4967 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4968 BOOST_UBLAS_CHECK (it1_
== it
.it1_
, external_logic ());
4969 return it2_
< it
.it2_
;
4973 subiterator1_type it1_
;
4974 subiterator2_type it2_
;
4976 friend class const_iterator2
;
4981 iterator2
begin2 () {
4982 return find2 (0, 0, 0);
4986 return find2 (0, 0, size2 ());
4989 // Reverse iterators
4992 const_reverse_iterator1
rbegin1 () const {
4993 return const_reverse_iterator1 (end1 ());
4996 const_reverse_iterator1
rend1 () const {
4997 return const_reverse_iterator1 (begin1 ());
5001 reverse_iterator1
rbegin1 () {
5002 return reverse_iterator1 (end1 ());
5005 reverse_iterator1
rend1 () {
5006 return reverse_iterator1 (begin1 ());
5010 const_reverse_iterator2
rbegin2 () const {
5011 return const_reverse_iterator2 (end2 ());
5014 const_reverse_iterator2
rend2 () const {
5015 return const_reverse_iterator2 (begin2 ());
5019 reverse_iterator2
rbegin2 () {
5020 return reverse_iterator2 (end2 ());
5023 reverse_iterator2
rend2 () {
5024 return reverse_iterator2 (begin2 ());
5028 matrix_closure_type data_
;
5029 indirect_array_type ia1_
;
5030 indirect_array_type ia2_
;
5034 template<class M
, class A
>
5036 matrix_indirect
<M
, indirect_array
<A
> > project (M
&data
, const indirect_array
<A
> &ia1
, const indirect_array
<A
> &ia2
) {
5037 return matrix_indirect
<M
, indirect_array
<A
> > (data
, ia1
, ia2
);
5039 template<class M
, class A
>
5041 const matrix_indirect
<const M
, indirect_array
<A
> > project (const M
&data
, const indirect_array
<A
> &ia1
, const indirect_array
<A
> &ia2
) {
5042 // ISSUE was: return matrix_indirect<M, indirect_array<A> > (const_cast<M &> (data), ia1, ia2);
5043 return matrix_indirect
<const M
, indirect_array
<A
> > (data
, ia1
, ia2
);
5045 template<class M
, class IA
>
5047 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
) {
5048 return data
.project (r1
, r2
);
5050 template<class M
, class IA
>
5052 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
) {
5053 return data
.project (r1
, r2
);
5055 template<class M
, class IA
>
5057 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
) {
5058 return data
.project (s1
, s2
);
5060 template<class M
, class IA
>
5062 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
) {
5063 return data
.project (s1
, s2
);
5065 template<class M
, class A
>
5067 matrix_indirect
<M
, indirect_array
<A
> > project (matrix_indirect
<M
, indirect_array
<A
> > &data
, const indirect_array
<A
> &ia1
, const indirect_array
<A
> &ia2
) {
5068 return data
.project (ia1
, ia2
);
5070 template<class M
, class A
>
5072 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
) {
5073 return data
.project (ia1
, ia2
);
5076 /// Specialization of temporary_traits
5078 struct matrix_temporary_traits
< matrix_indirect
<M
> >
5079 : matrix_temporary_traits
< M
> {};
5081 struct matrix_temporary_traits
< const matrix_indirect
<M
> >
5082 : matrix_temporary_traits
< M
> {};
5085 struct vector_temporary_traits
< matrix_indirect
<M
> >
5086 : vector_temporary_traits
< M
> {};
5088 struct vector_temporary_traits
< const matrix_indirect
<M
> >
5089 : vector_temporary_traits
< M
> {};