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_EXPRESSION_
14 #define _BOOST_UBLAS_MATRIX_EXPRESSION_
16 #include <boost/numeric/ublas/vector_expression.hpp>
18 // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
19 // Iterators based on ideas of Jeremy Siek
21 // Classes that model the Matrix Expression concept
23 namespace boost { namespace numeric { namespace ublas {
26 class matrix_reference:
27 public matrix_expression<matrix_reference<E> > {
29 typedef matrix_reference<E> self_type;
31 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
32 using matrix_expression<self_type>::operator ();
34 typedef typename E::size_type size_type;
35 typedef typename E::difference_type difference_type;
36 typedef typename E::value_type value_type;
37 typedef typename E::const_reference const_reference;
38 typedef typename boost::mpl::if_<boost::is_const<E>,
39 typename E::const_reference,
40 typename E::reference>::type reference;
41 typedef E referred_type;
42 typedef const self_type const_closure_type;
43 typedef self_type closure_type;
44 typedef typename E::orientation_category orientation_category;
45 typedef typename E::storage_category storage_category;
47 // Construction and destruction
49 explicit matrix_reference (referred_type &e):
54 size_type size1 () const {
58 size_type size2 () const {
63 // Expression accessors - const correct
65 const referred_type &expression () const {
69 referred_type &expression () {
75 #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
77 const_reference operator () (size_type i, size_type j) const {
78 return expression () (i, j);
81 reference operator () (size_type i, size_type j) {
82 return expression () (i, j);
86 reference operator () (size_type i, size_type j) const {
87 return expression () (i, j);
93 matrix_reference &operator = (const matrix_reference &m) {
94 expression ().operator = (m);
99 matrix_reference &operator = (const matrix_expression<AE> &ae) {
100 expression ().operator = (ae);
105 matrix_reference &assign (const matrix_expression<AE> &ae) {
106 expression ().assign (ae);
111 matrix_reference &operator += (const matrix_expression<AE> &ae) {
112 expression ().operator += (ae);
117 matrix_reference &plus_assign (const matrix_expression<AE> &ae) {
118 expression ().plus_assign (ae);
123 matrix_reference &operator -= (const matrix_expression<AE> &ae) {
124 expression ().operator -= (ae);
129 matrix_reference &minus_assign (const matrix_expression<AE> &ae) {
130 expression ().minus_assign (ae);
135 matrix_reference &operator *= (const AT &at) {
136 expression ().operator *= (at);
141 matrix_reference &operator /= (const AT &at) {
142 expression ().operator /= (at);
148 void swap (matrix_reference &m) {
149 expression ().swap (m.expression ());
152 // Closure comparison
154 bool same_closure (const matrix_reference &mr) const {
155 return &(*this).e_ == &mr.e_;
159 typedef typename E::const_iterator1 const_iterator1;
160 typedef typename boost::mpl::if_<boost::is_const<E>,
161 typename E::const_iterator1,
162 typename E::iterator1>::type iterator1;
163 typedef typename E::const_iterator2 const_iterator2;
164 typedef typename boost::mpl::if_<boost::is_const<E>,
165 typename E::const_iterator2,
166 typename E::iterator2>::type iterator2;
170 const_iterator1 find1 (int rank, size_type i, size_type j) const {
171 return expression ().find1 (rank, i, j);
174 iterator1 find1 (int rank, size_type i, size_type j) {
175 return expression ().find1 (rank, i, j);
178 const_iterator2 find2 (int rank, size_type i, size_type j) const {
179 return expression ().find2 (rank, i, j);
182 iterator2 find2 (int rank, size_type i, size_type j) {
183 return expression ().find2 (rank, i, j);
186 // Iterators are the iterators of the referenced expression.
189 const_iterator1 begin1 () const {
190 return expression ().begin1 ();
193 const_iterator1 cbegin1 () const {
197 const_iterator1 end1 () const {
198 return expression ().end1 ();
201 const_iterator1 cend1 () const {
206 iterator1 begin1 () {
207 return expression ().begin1 ();
211 return expression ().end1 ();
215 const_iterator2 begin2 () const {
216 return expression ().begin2 ();
219 const_iterator2 cbegin2 () const {
223 const_iterator2 end2 () const {
224 return expression ().end2 ();
227 const_iterator2 cend2 () const {
232 iterator2 begin2 () {
233 return expression ().begin2 ();
237 return expression ().end2 ();
241 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
242 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
245 const_reverse_iterator1 rbegin1 () const {
246 return const_reverse_iterator1 (end1 ());
249 const_reverse_iterator1 crbegin1 () const {
253 const_reverse_iterator1 rend1 () const {
254 return const_reverse_iterator1 (begin1 ());
257 const_reverse_iterator1 crend1 () const {
262 reverse_iterator1 rbegin1 () {
263 return reverse_iterator1 (end1 ());
266 reverse_iterator1 rend1 () {
267 return reverse_iterator1 (begin1 ());
270 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
271 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
274 const_reverse_iterator2 rbegin2 () const {
275 return const_reverse_iterator2 (end2 ());
278 const_reverse_iterator2 crbegin2 () const {
282 const_reverse_iterator2 rend2 () const {
283 return const_reverse_iterator2 (begin2 ());
286 const_reverse_iterator2 crend2 () const {
291 reverse_iterator2 rbegin2 () {
292 return reverse_iterator2 (end2 ());
295 reverse_iterator2 rend2 () {
296 return reverse_iterator2 (begin2 ());
304 template<class E1, class E2, class F>
305 class vector_matrix_binary:
306 public matrix_expression<vector_matrix_binary<E1, E2, F> > {
308 typedef E1 expression1_type;
309 typedef E2 expression2_type;
311 typedef typename E1::const_closure_type expression1_closure_type;
312 typedef typename E2::const_closure_type expression2_closure_type;
314 typedef vector_matrix_binary<E1, E2, F> self_type;
316 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
317 using matrix_expression<self_type>::operator ();
319 typedef F functor_type;
320 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
321 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
322 typedef typename F::result_type value_type;
323 typedef value_type const_reference;
324 typedef const_reference reference;
325 typedef const self_type const_closure_type;
326 typedef const_closure_type closure_type;
327 typedef unknown_orientation_tag orientation_category;
328 typedef unknown_storage_tag storage_category;
330 // Construction and destruction
332 vector_matrix_binary (const expression1_type &e1, const expression2_type &e2):
333 e1_ (e1), e2_ (e2) {}
337 size_type size1 () const {
341 size_type size2 () const {
346 // Expression accessors
348 const expression1_closure_type &expression1 () const {
352 const expression2_closure_type &expression2 () const {
359 const_reference operator () (size_type i, size_type j) const {
360 return functor_type::apply (e1_ (i), e2_ (j));
363 // Closure comparison
365 bool same_closure (const vector_matrix_binary &vmb) const {
366 return (*this).expression1 ().same_closure (vmb.expression1 ()) &&
367 (*this).expression2 ().same_closure (vmb.expression2 ());
372 typedef typename E1::const_iterator const_subiterator1_type;
373 typedef typename E2::const_iterator const_subiterator2_type;
374 typedef const value_type *const_pointer;
377 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
378 typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
379 typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
380 typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
381 typedef const_iterator1 iterator1;
382 typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
383 typedef const_iterator2 iterator2;
385 class const_iterator1;
386 typedef const_iterator1 iterator1;
387 class const_iterator2;
388 typedef const_iterator2 iterator2;
390 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
391 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
395 const_iterator1 find1 (int rank, size_type i, size_type j) const {
396 const_subiterator1_type it1 (e1_.find (i));
397 const_subiterator1_type it1_end (e1_.find (size1 ()));
398 const_subiterator2_type it2 (e2_.find (j));
399 const_subiterator2_type it2_end (e2_.find (size2 ()));
400 if (it2 == it2_end || (rank == 1 && (it2.index () != j || *it2 == value_type/*zero*/()))) {
404 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
405 return const_iterator1 (*this, it1.index (), it2.index ());
407 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
408 return const_iterator1 (*this, it1, it2, it2 != it2_end ? *it2 : value_type/*zero*/());
410 return const_iterator1 (*this, it1, it2);
415 const_iterator2 find2 (int rank, size_type i, size_type j) const {
416 const_subiterator2_type it2 (e2_.find (j));
417 const_subiterator2_type it2_end (e2_.find (size2 ()));
418 const_subiterator1_type it1 (e1_.find (i));
419 const_subiterator1_type it1_end (e1_.find (size1 ()));
420 if (it1 == it1_end || (rank == 1 && (it1.index () != i || *it1 == value_type/*zero*/()))) {
424 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
425 return const_iterator2 (*this, it1.index (), it2.index ());
427 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
428 return const_iterator2 (*this, it1, it2, it1 != it1_end ? *it1 : value_type/*zero*/());
430 return const_iterator2 (*this, it1, it2);
435 // Iterators enhance the iterators of the referenced expressions
436 // with the binary functor.
438 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
439 class const_iterator1:
440 public container_const_reference<vector_matrix_binary>,
441 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
442 typename E2::const_iterator::iterator_category>::iterator_category>::template
443 iterator_base<const_iterator1, value_type>::type {
445 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
446 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
447 typedef typename vector_matrix_binary::difference_type difference_type;
448 typedef typename vector_matrix_binary::value_type value_type;
449 typedef typename vector_matrix_binary::const_reference reference;
450 typedef typename vector_matrix_binary::const_pointer pointer;
452 typedef const_iterator2 dual_iterator_type;
453 typedef const_reverse_iterator2 dual_reverse_iterator_type;
455 // Construction and destruction
456 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
459 container_const_reference<self_type> (), it1_ (), it2_ (), t2_ () {}
461 const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t2):
462 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t2_ (t2) {}
466 container_const_reference<self_type> (), it1_ (), it2_ () {}
468 const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
469 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
474 const_iterator1 &operator ++ () {
479 const_iterator1 &operator -- () {
484 const_iterator1 &operator += (difference_type n) {
489 const_iterator1 &operator -= (difference_type n) {
494 difference_type operator - (const const_iterator1 &it) const {
495 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
496 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
497 return it1_ - it.it1_;
502 const_reference operator * () const {
503 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
504 return functor_type::apply (*it1_, t2_);
506 return functor_type::apply (*it1_, *it2_);
510 const_reference operator [] (difference_type n) const {
514 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
516 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
519 const_iterator2 begin () const {
520 return (*this) ().find2 (1, index1 (), 0);
523 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
526 const_iterator2 cbegin () const {
530 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
533 const_iterator2 end () const {
534 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
537 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
540 const_iterator2 cend () const {
544 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
547 const_reverse_iterator2 rbegin () const {
548 return const_reverse_iterator2 (end ());
551 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
554 const_reverse_iterator2 crbegin () const {
558 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
561 const_reverse_iterator2 rend () const {
562 return const_reverse_iterator2 (begin ());
565 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
568 const_reverse_iterator2 crend () const {
575 size_type index1 () const {
576 return it1_.index ();
579 size_type index2 () const {
580 return it2_.index ();
585 const_iterator1 &operator = (const const_iterator1 &it) {
586 container_const_reference<self_type>::assign (&it ());
589 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
597 bool operator == (const const_iterator1 &it) const {
598 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
599 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
600 return it1_ == it.it1_;
603 bool operator < (const const_iterator1 &it) const {
604 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
605 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
606 return it1_ < it.it1_;
610 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
611 const_subiterator1_type it1_;
612 // Mutable due to assignment
613 /* const */ const_subiterator2_type it2_;
616 const_subiterator1_type it1_;
617 const_subiterator2_type it2_;
623 const_iterator1 begin1 () const {
624 return find1 (0, 0, 0);
627 const_iterator1 cbegin1 () const {
631 const_iterator1 end1 () const {
632 return find1 (0, size1 (), 0);
635 const_iterator1 cend1 () const {
639 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
640 class const_iterator2:
641 public container_const_reference<vector_matrix_binary>,
642 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
643 typename E2::const_iterator::iterator_category>::iterator_category>::template
644 iterator_base<const_iterator2, value_type>::type {
646 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
647 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
648 typedef typename vector_matrix_binary::difference_type difference_type;
649 typedef typename vector_matrix_binary::value_type value_type;
650 typedef typename vector_matrix_binary::const_reference reference;
651 typedef typename vector_matrix_binary::const_pointer pointer;
653 typedef const_iterator1 dual_iterator_type;
654 typedef const_reverse_iterator1 dual_reverse_iterator_type;
656 // Construction and destruction
657 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
660 container_const_reference<self_type> (), it1_ (), it2_ (), t1_ () {}
662 const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t1):
663 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t1_ (t1) {}
667 container_const_reference<self_type> (), it1_ (), it2_ () {}
669 const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
670 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
675 const_iterator2 &operator ++ () {
680 const_iterator2 &operator -- () {
685 const_iterator2 &operator += (difference_type n) {
690 const_iterator2 &operator -= (difference_type n) {
695 difference_type operator - (const const_iterator2 &it) const {
696 BOOST_UBLAS_CHECK ((*this) ().same_closure(it ()), external_logic ());
697 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
698 return it2_ - it.it2_;
703 const_reference operator * () const {
704 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
705 return functor_type::apply (t1_, *it2_);
707 return functor_type::apply (*it1_, *it2_);
711 const_reference operator [] (difference_type n) const {
715 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
717 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
720 const_iterator1 begin () const {
721 return (*this) ().find1 (1, 0, index2 ());
724 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
727 const_iterator1 cbegin () const {
731 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
734 const_iterator1 end () const {
735 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
738 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
741 const_iterator1 cend () const {
745 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
748 const_reverse_iterator1 rbegin () const {
749 return const_reverse_iterator1 (end ());
752 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
755 const_reverse_iterator1 crbegin () const {
759 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
762 const_reverse_iterator1 rend () const {
763 return const_reverse_iterator1 (begin ());
766 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
769 const_reverse_iterator1 crend () const {
776 size_type index1 () const {
777 return it1_.index ();
780 size_type index2 () const {
781 return it2_.index ();
786 const_iterator2 &operator = (const const_iterator2 &it) {
787 container_const_reference<self_type>::assign (&it ());
790 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
798 bool operator == (const const_iterator2 &it) const {
799 BOOST_UBLAS_CHECK ((*this) ().same_closure( it ()), external_logic ());
800 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
801 return it2_ == it.it2_;
804 bool operator < (const const_iterator2 &it) const {
805 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
806 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
807 return it2_ < it.it2_;
811 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
812 // Mutable due to assignment
813 /* const */ const_subiterator1_type it1_;
814 const_subiterator2_type it2_;
817 const_subiterator1_type it1_;
818 const_subiterator2_type it2_;
824 const_iterator2 begin2 () const {
825 return find2 (0, 0, 0);
828 const_iterator2 cbegin2 () const {
832 const_iterator2 end2 () const {
833 return find2 (0, 0, size2 ());
836 const_iterator2 cend2 () const {
843 const_reverse_iterator1 rbegin1 () const {
844 return const_reverse_iterator1 (end1 ());
847 const_reverse_iterator1 crbegin1 () const {
851 const_reverse_iterator1 rend1 () const {
852 return const_reverse_iterator1 (begin1 ());
855 const_reverse_iterator1 crend1 () const {
859 const_reverse_iterator2 rbegin2 () const {
860 return const_reverse_iterator2 (end2 ());
863 const_reverse_iterator2 crbegin2 () const {
867 const_reverse_iterator2 rend2 () const {
868 return const_reverse_iterator2 (begin2 ());
871 const_reverse_iterator2 crend2 () const {
876 expression1_closure_type e1_;
877 expression2_closure_type e2_;
880 template<class E1, class E2, class F>
881 struct vector_matrix_binary_traits {
882 typedef vector_matrix_binary<E1, E2, F> expression_type;
883 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
884 typedef expression_type result_type;
886 // ISSUE matrix is arbitary temporary type
887 typedef matrix<typename F::value_type> result_type;
891 // (outer_prod (v1, v2)) [i] [j] = v1 [i] * v2 [j]
892 template<class E1, class E2>
894 typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::result_type
895 outer_prod (const vector_expression<E1> &e1,
896 const vector_expression<E2> &e2) {
897 BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
898 typedef typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::expression_type expression_type;
899 return expression_type (e1 (), e2 ());
902 template<class E, class F>
904 public matrix_expression<matrix_unary1<E, F> > {
906 typedef E expression_type;
907 typedef F functor_type;
909 typedef typename E::const_closure_type expression_closure_type;
911 typedef matrix_unary1<E, F> self_type;
913 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
914 using matrix_expression<self_type>::operator ();
916 typedef typename E::size_type size_type;
917 typedef typename E::difference_type difference_type;
918 typedef typename F::result_type value_type;
919 typedef value_type const_reference;
920 typedef const_reference reference;
921 typedef const self_type const_closure_type;
922 typedef const_closure_type closure_type;
923 typedef typename E::orientation_category orientation_category;
924 typedef unknown_storage_tag storage_category;
926 // Construction and destruction
928 explicit matrix_unary1 (const expression_type &e):
933 size_type size1 () const {
937 size_type size2 () const {
942 // Expression accessors
944 const expression_closure_type &expression () const {
951 const_reference operator () (size_type i, size_type j) const {
952 return functor_type::apply (e_ (i, j));
955 // Closure comparison
957 bool same_closure (const matrix_unary1 &mu1) const {
958 return (*this).expression ().same_closure (mu1.expression ());
963 typedef typename E::const_iterator1 const_subiterator1_type;
964 typedef typename E::const_iterator2 const_subiterator2_type;
965 typedef const value_type *const_pointer;
968 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
969 typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
970 typedef const_iterator1 iterator1;
971 typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
972 typedef const_iterator2 iterator2;
974 class const_iterator1;
975 typedef const_iterator1 iterator1;
976 class const_iterator2;
977 typedef const_iterator2 iterator2;
979 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
980 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
984 const_iterator1 find1 (int rank, size_type i, size_type j) const {
985 const_subiterator1_type it1 (e_.find1 (rank, i, j));
986 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
987 return const_iterator1 (*this, it1.index1 (), it1.index2 ());
989 return const_iterator1 (*this, it1);
993 const_iterator2 find2 (int rank, size_type i, size_type j) const {
994 const_subiterator2_type it2 (e_.find2 (rank, i, j));
995 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
996 return const_iterator2 (*this, it2.index1 (), it2.index2 ());
998 return const_iterator2 (*this, it2);
1002 // Iterators enhance the iterators of the referenced expression
1003 // with the unary functor.
1005 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1006 class const_iterator1:
1007 public container_const_reference<matrix_unary1>,
1008 public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
1009 iterator_base<const_iterator1, value_type>::type {
1011 typedef typename E::const_iterator1::iterator_category iterator_category;
1012 typedef typename matrix_unary1::difference_type difference_type;
1013 typedef typename matrix_unary1::value_type value_type;
1014 typedef typename matrix_unary1::const_reference reference;
1015 typedef typename matrix_unary1::const_pointer pointer;
1017 typedef const_iterator2 dual_iterator_type;
1018 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1020 // Construction and destruction
1023 container_const_reference<self_type> (), it_ () {}
1025 const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
1026 container_const_reference<self_type> (mu), it_ (it) {}
1030 const_iterator1 &operator ++ () {
1035 const_iterator1 &operator -- () {
1040 const_iterator1 &operator += (difference_type n) {
1045 const_iterator1 &operator -= (difference_type n) {
1050 difference_type operator - (const const_iterator1 &it) const {
1051 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1052 return it_ - it.it_;
1057 const_reference operator * () const {
1058 return functor_type::apply (*it_);
1061 const_reference operator [] (difference_type n) const {
1062 return *(*this + n);
1065 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1067 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1068 typename self_type::
1070 const_iterator2 begin () const {
1071 return (*this) ().find2 (1, index1 (), 0);
1074 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1075 typename self_type::
1077 const_iterator2 cbegin () const {
1081 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1082 typename self_type::
1084 const_iterator2 end () const {
1085 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1088 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1089 typename self_type::
1091 const_iterator2 cend () const {
1095 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1096 typename self_type::
1098 const_reverse_iterator2 rbegin () const {
1099 return const_reverse_iterator2 (end ());
1102 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1103 typename self_type::
1105 const_reverse_iterator2 crbegin () const {
1109 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1110 typename self_type::
1112 const_reverse_iterator2 rend () const {
1113 return const_reverse_iterator2 (begin ());
1116 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1117 typename self_type::
1119 const_reverse_iterator2 crend () const {
1126 size_type index1 () const {
1127 return it_.index1 ();
1130 size_type index2 () const {
1131 return it_.index2 ();
1136 const_iterator1 &operator = (const const_iterator1 &it) {
1137 container_const_reference<self_type>::assign (&it ());
1144 bool operator == (const const_iterator1 &it) const {
1145 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1146 return it_ == it.it_;
1149 bool operator < (const const_iterator1 &it) const {
1150 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1151 return it_ < it.it_;
1155 const_subiterator1_type it_;
1160 const_iterator1 begin1 () const {
1161 return find1 (0, 0, 0);
1164 const_iterator1 cbegin1 () const {
1168 const_iterator1 end1 () const {
1169 return find1 (0, size1 (), 0);
1172 const_iterator1 cend1 () const {
1176 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1177 class const_iterator2:
1178 public container_const_reference<matrix_unary1>,
1179 public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
1180 iterator_base<const_iterator2, value_type>::type {
1182 typedef typename E::const_iterator2::iterator_category iterator_category;
1183 typedef typename matrix_unary1::difference_type difference_type;
1184 typedef typename matrix_unary1::value_type value_type;
1185 typedef typename matrix_unary1::const_reference reference;
1186 typedef typename matrix_unary1::const_pointer pointer;
1188 typedef const_iterator1 dual_iterator_type;
1189 typedef const_reverse_iterator1 dual_reverse_iterator_type;
1191 // Construction and destruction
1194 container_const_reference<self_type> (), it_ () {}
1196 const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
1197 container_const_reference<self_type> (mu), it_ (it) {}
1201 const_iterator2 &operator ++ () {
1206 const_iterator2 &operator -- () {
1211 const_iterator2 &operator += (difference_type n) {
1216 const_iterator2 &operator -= (difference_type n) {
1221 difference_type operator - (const const_iterator2 &it) const {
1222 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1223 return it_ - it.it_;
1228 const_reference operator * () const {
1229 return functor_type::apply (*it_);
1232 const_reference operator [] (difference_type n) const {
1233 return *(*this + n);
1236 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1238 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1239 typename self_type::
1241 const_iterator1 begin () const {
1242 return (*this) ().find1 (1, 0, index2 ());
1245 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1246 typename self_type::
1248 const_iterator1 cbegin () const {
1252 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1253 typename self_type::
1255 const_iterator1 end () const {
1256 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1259 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1260 typename self_type::
1262 const_iterator1 cend () const {
1266 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1267 typename self_type::
1269 const_reverse_iterator1 rbegin () const {
1270 return const_reverse_iterator1 (end ());
1273 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1274 typename self_type::
1276 const_reverse_iterator1 crbegin () const {
1280 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1281 typename self_type::
1283 const_reverse_iterator1 rend () const {
1284 return const_reverse_iterator1 (begin ());
1287 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1288 typename self_type::
1290 const_reverse_iterator1 crend () const {
1297 size_type index1 () const {
1298 return it_.index1 ();
1301 size_type index2 () const {
1302 return it_.index2 ();
1307 const_iterator2 &operator = (const const_iterator2 &it) {
1308 container_const_reference<self_type>::assign (&it ());
1315 bool operator == (const const_iterator2 &it) const {
1316 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1317 return it_ == it.it_;
1320 bool operator < (const const_iterator2 &it) const {
1321 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1322 return it_ < it.it_;
1326 const_subiterator2_type it_;
1331 const_iterator2 begin2 () const {
1332 return find2 (0, 0, 0);
1335 const_iterator2 cbegin2 () const {
1339 const_iterator2 end2 () const {
1340 return find2 (0, 0, size2 ());
1343 const_iterator2 cend2 () const {
1347 // Reverse iterators
1350 const_reverse_iterator1 rbegin1 () const {
1351 return const_reverse_iterator1 (end1 ());
1354 const_reverse_iterator1 crbegin1 () const {
1358 const_reverse_iterator1 rend1 () const {
1359 return const_reverse_iterator1 (begin1 ());
1362 const_reverse_iterator1 crend1 () const {
1367 const_reverse_iterator2 rbegin2 () const {
1368 return const_reverse_iterator2 (end2 ());
1371 const_reverse_iterator2 crbegin2 () const {
1375 const_reverse_iterator2 rend2 () const {
1376 return const_reverse_iterator2 (begin2 ());
1379 const_reverse_iterator2 crend2 () const {
1384 expression_closure_type e_;
1387 template<class E, class F>
1388 struct matrix_unary1_traits {
1389 typedef matrix_unary1<E, F> expression_type;
1390 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1391 typedef expression_type result_type;
1393 typedef typename E::matrix_temporary_type result_type;
1397 // (- m) [i] [j] = - m [i] [j]
1400 typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::result_type
1401 operator - (const matrix_expression<E> &e) {
1402 typedef typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
1403 return expression_type (e ());
1406 // (conj m) [i] [j] = conj (m [i] [j])
1409 typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::result_type
1410 conj (const matrix_expression<E> &e) {
1411 typedef typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
1412 return expression_type (e ());
1415 // (real m) [i] [j] = real (m [i] [j])
1418 typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::result_type
1419 real (const matrix_expression<E> &e) {
1420 typedef typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
1421 return expression_type (e ());
1424 // (imag m) [i] [j] = imag (m [i] [j])
1427 typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::result_type
1428 imag (const matrix_expression<E> &e) {
1429 typedef typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
1430 return expression_type (e ());
1433 template<class E, class F>
1434 class matrix_unary2:
1435 public matrix_expression<matrix_unary2<E, F> > {
1437 typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
1439 const E>::type expression_type;
1440 typedef F functor_type;
1442 typedef typename boost::mpl::if_<boost::is_const<expression_type>,
1443 typename E::const_closure_type,
1444 typename E::closure_type>::type expression_closure_type;
1446 typedef matrix_unary2<E, F> self_type;
1448 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1449 using matrix_expression<self_type>::operator ();
1451 typedef typename E::size_type size_type;
1452 typedef typename E::difference_type difference_type;
1453 typedef typename F::result_type value_type;
1454 typedef value_type const_reference;
1455 typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
1456 typename E::reference,
1457 value_type>::type reference;
1459 typedef const self_type const_closure_type;
1460 typedef self_type closure_type;
1461 typedef typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
1464 typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
1467 typename E::orientation_category>::type>::type orientation_category;
1468 typedef typename E::storage_category storage_category;
1470 // Construction and destruction
1472 // matrix_unary2 may be used as mutable expression -
1473 // this is the only non const expression constructor
1474 explicit matrix_unary2 (expression_type &e):
1479 size_type size1 () const {
1483 size_type size2 () const {
1488 // Expression accessors
1490 const expression_closure_type &expression () const {
1497 const_reference operator () (size_type i, size_type j) const {
1498 return functor_type::apply (e_ (j, i));
1501 reference operator () (size_type i, size_type j) {
1502 BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
1506 // Closure comparison
1508 bool same_closure (const matrix_unary2 &mu2) const {
1509 return (*this).expression ().same_closure (mu2.expression ());
1514 typedef typename E::const_iterator1 const_subiterator2_type;
1515 typedef typename E::const_iterator2 const_subiterator1_type;
1516 typedef const value_type *const_pointer;
1519 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1520 typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
1521 typedef const_iterator1 iterator1;
1522 typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
1523 typedef const_iterator2 iterator2;
1525 class const_iterator1;
1526 typedef const_iterator1 iterator1;
1527 class const_iterator2;
1528 typedef const_iterator2 iterator2;
1530 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1531 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1535 const_iterator1 find1 (int rank, size_type i, size_type j) const {
1536 const_subiterator1_type it1 (e_.find2 (rank, j, i));
1537 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1538 return const_iterator1 (*this, it1.index2 (), it1.index1 ());
1540 return const_iterator1 (*this, it1);
1544 const_iterator2 find2 (int rank, size_type i, size_type j) const {
1545 const_subiterator2_type it2 (e_.find1 (rank, j, i));
1546 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1547 return const_iterator2 (*this, it2.index2 (), it2.index1 ());
1549 return const_iterator2 (*this, it2);
1553 // Iterators enhance the iterators of the referenced expression
1554 // with the unary functor.
1556 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1557 class const_iterator1:
1558 public container_const_reference<matrix_unary2>,
1559 public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
1560 iterator_base<const_iterator1, value_type>::type {
1562 typedef typename E::const_iterator2::iterator_category iterator_category;
1563 typedef typename matrix_unary2::difference_type difference_type;
1564 typedef typename matrix_unary2::value_type value_type;
1565 typedef typename matrix_unary2::const_reference reference;
1566 typedef typename matrix_unary2::const_pointer pointer;
1568 typedef const_iterator2 dual_iterator_type;
1569 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1571 // Construction and destruction
1574 container_const_reference<self_type> (), it_ () {}
1576 const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
1577 container_const_reference<self_type> (mu), it_ (it) {}
1581 const_iterator1 &operator ++ () {
1586 const_iterator1 &operator -- () {
1591 const_iterator1 &operator += (difference_type n) {
1596 const_iterator1 &operator -= (difference_type n) {
1601 difference_type operator - (const const_iterator1 &it) const {
1602 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1603 return it_ - it.it_;
1608 const_reference operator * () const {
1609 return functor_type::apply (*it_);
1612 const_reference operator [] (difference_type n) const {
1613 return *(*this + n);
1616 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1618 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1619 typename self_type::
1621 const_iterator2 begin () const {
1622 return (*this) ().find2 (1, index1 (), 0);
1625 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1626 typename self_type::
1628 const_iterator2 cbegin () const {
1632 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1633 typename self_type::
1635 const_iterator2 end () const {
1636 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1639 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1640 typename self_type::
1642 const_iterator2 cend () const {
1646 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1647 typename self_type::
1649 const_reverse_iterator2 rbegin () const {
1650 return const_reverse_iterator2 (end ());
1653 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1654 typename self_type::
1656 const_reverse_iterator2 crbegin () const {
1660 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1661 typename self_type::
1663 const_reverse_iterator2 rend () const {
1664 return const_reverse_iterator2 (begin ());
1667 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1668 typename self_type::
1670 const_reverse_iterator2 crend () const {
1677 size_type index1 () const {
1678 return it_.index2 ();
1681 size_type index2 () const {
1682 return it_.index1 ();
1687 const_iterator1 &operator = (const const_iterator1 &it) {
1688 container_const_reference<self_type>::assign (&it ());
1695 bool operator == (const const_iterator1 &it) const {
1696 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1697 return it_ == it.it_;
1700 bool operator < (const const_iterator1 &it) const {
1701 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1702 return it_ < it.it_;
1706 const_subiterator1_type it_;
1711 const_iterator1 begin1 () const {
1712 return find1 (0, 0, 0);
1715 const_iterator1 cbegin1 () const {
1719 const_iterator1 end1 () const {
1720 return find1 (0, size1 (), 0);
1723 const_iterator1 cend1 () const {
1727 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1728 class const_iterator2:
1729 public container_const_reference<matrix_unary2>,
1730 public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
1731 iterator_base<const_iterator2, value_type>::type {
1733 typedef typename E::const_iterator1::iterator_category iterator_category;
1734 typedef typename matrix_unary2::difference_type difference_type;
1735 typedef typename matrix_unary2::value_type value_type;
1736 typedef typename matrix_unary2::const_reference reference;
1737 typedef typename matrix_unary2::const_pointer pointer;
1739 typedef const_iterator1 dual_iterator_type;
1740 typedef const_reverse_iterator1 dual_reverse_iterator_type;
1742 // Construction and destruction
1745 container_const_reference<self_type> (), it_ () {}
1747 const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
1748 container_const_reference<self_type> (mu), it_ (it) {}
1752 const_iterator2 &operator ++ () {
1757 const_iterator2 &operator -- () {
1762 const_iterator2 &operator += (difference_type n) {
1767 const_iterator2 &operator -= (difference_type n) {
1772 difference_type operator - (const const_iterator2 &it) const {
1773 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1774 return it_ - it.it_;
1779 const_reference operator * () const {
1780 return functor_type::apply (*it_);
1783 const_reference operator [] (difference_type n) const {
1784 return *(*this + n);
1787 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1789 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1790 typename self_type::
1792 const_iterator1 begin () const {
1793 return (*this) ().find1 (1, 0, index2 ());
1796 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1797 typename self_type::
1799 const_iterator1 cbegin () const {
1803 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1804 typename self_type::
1806 const_iterator1 end () const {
1807 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1810 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1811 typename self_type::
1813 const_iterator1 cend () const {
1817 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1818 typename self_type::
1820 const_reverse_iterator1 rbegin () const {
1821 return const_reverse_iterator1 (end ());
1824 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1825 typename self_type::
1827 const_reverse_iterator1 crbegin () const {
1831 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1832 typename self_type::
1834 const_reverse_iterator1 rend () const {
1835 return const_reverse_iterator1 (begin ());
1838 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1839 typename self_type::
1841 const_reverse_iterator1 crend () const {
1848 size_type index1 () const {
1849 return it_.index2 ();
1852 size_type index2 () const {
1853 return it_.index1 ();
1858 const_iterator2 &operator = (const const_iterator2 &it) {
1859 container_const_reference<self_type>::assign (&it ());
1866 bool operator == (const const_iterator2 &it) const {
1867 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1868 return it_ == it.it_;
1871 bool operator < (const const_iterator2 &it) const {
1872 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1873 return it_ < it.it_;
1877 const_subiterator2_type it_;
1882 const_iterator2 begin2 () const {
1883 return find2 (0, 0, 0);
1886 const_iterator2 cbegin2 () const {
1890 const_iterator2 end2 () const {
1891 return find2 (0, 0, size2 ());
1894 const_iterator2 cend2 () const {
1898 // Reverse iterators
1901 const_reverse_iterator1 rbegin1 () const {
1902 return const_reverse_iterator1 (end1 ());
1905 const_reverse_iterator1 crbegin1 () const {
1909 const_reverse_iterator1 rend1 () const {
1910 return const_reverse_iterator1 (begin1 ());
1913 const_reverse_iterator1 crend1 () const {
1918 const_reverse_iterator2 rbegin2 () const {
1919 return const_reverse_iterator2 (end2 ());
1922 const_reverse_iterator2 crbegin2 () const {
1926 const_reverse_iterator2 rend2 () const {
1927 return const_reverse_iterator2 (begin2 ());
1930 const_reverse_iterator2 crend2 () const {
1935 expression_closure_type e_;
1938 template<class E, class F>
1939 struct matrix_unary2_traits {
1940 typedef matrix_unary2<E, F> expression_type;
1941 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1942 typedef expression_type result_type;
1944 typedef typename E::matrix_temporary_type result_type;
1948 // (trans m) [i] [j] = m [j] [i]
1951 typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::result_type
1952 trans (const matrix_expression<E> &e) {
1953 typedef typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
1954 return expression_type (e ());
1958 typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::result_type
1959 trans (matrix_expression<E> &e) {
1960 typedef typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
1961 return expression_type (e ());
1964 // (herm m) [i] [j] = conj (m [j] [i])
1967 typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::result_type
1968 herm (const matrix_expression<E> &e) {
1969 typedef typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
1970 return expression_type (e ());
1973 template<class E1, class E2, class F>
1974 class matrix_binary:
1975 public matrix_expression<matrix_binary<E1, E2, F> > {
1977 typedef E1 expression1_type;
1978 typedef E2 expression2_type;
1979 typedef F functor_type;
1981 typedef typename E1::const_closure_type expression1_closure_type;
1982 typedef typename E2::const_closure_type expression2_closure_type;
1984 typedef matrix_binary<E1, E2, F> self_type;
1986 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1987 using matrix_expression<self_type>::operator ();
1989 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
1990 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
1991 typedef typename F::result_type value_type;
1992 typedef value_type const_reference;
1993 typedef const_reference reference;
1994 typedef const self_type const_closure_type;
1995 typedef const_closure_type closure_type;
1996 typedef unknown_orientation_tag orientation_category;
1997 typedef unknown_storage_tag storage_category;
1999 // Construction and destruction
2001 matrix_binary (const E1 &e1, const E2 &e2):
2002 e1_ (e1), e2_ (e2) {}
2006 size_type size1 () const {
2007 return BOOST_UBLAS_SAME (e1_.size1 (), e2_.size1 ());
2010 size_type size2 () const {
2011 return BOOST_UBLAS_SAME (e1_.size2 (), e2_.size2 ());
2015 // Expression accessors
2017 const expression1_closure_type &expression1 () const {
2021 const expression2_closure_type &expression2 () const {
2028 const_reference operator () (size_type i, size_type j) const {
2029 return functor_type::apply (e1_ (i, j), e2_ (i, j));
2032 // Closure comparison
2034 bool same_closure (const matrix_binary &mb) const {
2035 return (*this).expression1 ().same_closure (mb.expression1 ()) &&
2036 (*this).expression2 ().same_closure (mb.expression2 ());
2041 typedef typename E1::const_iterator1 const_iterator11_type;
2042 typedef typename E1::const_iterator2 const_iterator12_type;
2043 typedef typename E2::const_iterator1 const_iterator21_type;
2044 typedef typename E2::const_iterator2 const_iterator22_type;
2045 typedef const value_type *const_pointer;
2048 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2049 typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
2050 typename const_iterator21_type::iterator_category>::iterator_category iterator_category1;
2051 typedef indexed_const_iterator1<const_closure_type, iterator_category1> const_iterator1;
2052 typedef const_iterator1 iterator1;
2053 typedef typename iterator_restrict_traits<typename const_iterator12_type::iterator_category,
2054 typename const_iterator22_type::iterator_category>::iterator_category iterator_category2;
2055 typedef indexed_const_iterator2<const_closure_type, iterator_category2> const_iterator2;
2056 typedef const_iterator2 iterator2;
2058 class const_iterator1;
2059 typedef const_iterator1 iterator1;
2060 class const_iterator2;
2061 typedef const_iterator2 iterator2;
2063 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2064 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2068 const_iterator1 find1 (int rank, size_type i, size_type j) const {
2069 const_iterator11_type it11 (e1_.find1 (rank, i, j));
2070 const_iterator11_type it11_end (e1_.find1 (rank, size1 (), j));
2071 const_iterator21_type it21 (e2_.find1 (rank, i, j));
2072 const_iterator21_type it21_end (e2_.find1 (rank, size1 (), j));
2073 BOOST_UBLAS_CHECK (rank == 0 || it11 == it11_end || it11.index2 () == j, internal_logic ())
2074 BOOST_UBLAS_CHECK (rank == 0 || it21 == it21_end || it21.index2 () == j, internal_logic ())
2075 i = (std::min) (it11 != it11_end ? it11.index1 () : size1 (),
2076 it21 != it21_end ? it21.index1 () : size1 ());
2077 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2078 return const_iterator1 (*this, i, j);
2080 return const_iterator1 (*this, i, j, it11, it11_end, it21, it21_end);
2084 const_iterator2 find2 (int rank, size_type i, size_type j) const {
2085 const_iterator12_type it12 (e1_.find2 (rank, i, j));
2086 const_iterator12_type it12_end (e1_.find2 (rank, i, size2 ()));
2087 const_iterator22_type it22 (e2_.find2 (rank, i, j));
2088 const_iterator22_type it22_end (e2_.find2 (rank, i, size2 ()));
2089 BOOST_UBLAS_CHECK (rank == 0 || it12 == it12_end || it12.index1 () == i, internal_logic ())
2090 BOOST_UBLAS_CHECK (rank == 0 || it22 == it22_end || it22.index1 () == i, internal_logic ())
2091 j = (std::min) (it12 != it12_end ? it12.index2 () : size2 (),
2092 it22 != it22_end ? it22.index2 () : size2 ());
2093 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2094 return const_iterator2 (*this, i, j);
2096 return const_iterator2 (*this, i, j, it12, it12_end, it22, it22_end);
2100 // Iterators enhance the iterators of the referenced expression
2101 // with the binary functor.
2103 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2104 class const_iterator1:
2105 public container_const_reference<matrix_binary>,
2106 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
2107 typename E2::const_iterator1::iterator_category>::iterator_category>::template
2108 iterator_base<const_iterator1, value_type>::type {
2110 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
2111 typename E2::const_iterator1::iterator_category>::iterator_category iterator_category;
2112 typedef typename matrix_binary::difference_type difference_type;
2113 typedef typename matrix_binary::value_type value_type;
2114 typedef typename matrix_binary::const_reference reference;
2115 typedef typename matrix_binary::const_pointer pointer;
2117 typedef const_iterator2 dual_iterator_type;
2118 typedef const_reverse_iterator2 dual_reverse_iterator_type;
2120 // Construction and destruction
2123 container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
2125 const_iterator1 (const self_type &mb, size_type i, size_type j,
2126 const const_iterator11_type &it1, const const_iterator11_type &it1_end,
2127 const const_iterator21_type &it2, const const_iterator21_type &it2_end):
2128 container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
2131 // Dense specializations
2133 void increment (dense_random_access_iterator_tag) {
2134 ++ i_; ++ it1_; ++ it2_;
2137 void decrement (dense_random_access_iterator_tag) {
2138 -- i_; -- it1_; -- it2_;
2141 void increment (dense_random_access_iterator_tag, difference_type n) {
2142 i_ += n; it1_ += n; it2_ += n;
2145 void decrement (dense_random_access_iterator_tag, difference_type n) {
2146 i_ -= n; it1_ -= n; it2_ -= n;
2149 value_type dereference (dense_random_access_iterator_tag) const {
2150 return functor_type::apply (*it1_, *it2_);
2153 // Packed specializations
2155 void increment (packed_random_access_iterator_tag) {
2156 if (it1_ != it1_end_)
2157 if (it1_.index1 () <= i_)
2159 if (it2_ != it2_end_)
2160 if (it2_.index1 () <= i_)
2165 void decrement (packed_random_access_iterator_tag) {
2166 if (it1_ != it1_end_)
2167 if (i_ <= it1_.index1 ())
2169 if (it2_ != it2_end_)
2170 if (i_ <= it2_.index1 ())
2175 void increment (packed_random_access_iterator_tag, difference_type n) {
2177 increment (packed_random_access_iterator_tag ());
2181 decrement (packed_random_access_iterator_tag ());
2186 void decrement (packed_random_access_iterator_tag, difference_type n) {
2188 decrement (packed_random_access_iterator_tag ());
2192 increment (packed_random_access_iterator_tag ());
2197 value_type dereference (packed_random_access_iterator_tag) const {
2198 value_type t1 = value_type/*zero*/();
2199 if (it1_ != it1_end_) {
2200 BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
2201 if (it1_.index1 () == i_)
2204 value_type t2 = value_type/*zero*/();
2205 if (it2_ != it2_end_) {
2206 BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
2207 if (it2_.index1 () == i_)
2210 return functor_type::apply (t1, t2);
2213 // Sparse specializations
2215 void increment (sparse_bidirectional_iterator_tag) {
2216 size_type index1 = (*this) ().size1 ();
2217 if (it1_ != it1_end_) {
2218 if (it1_.index1 () <= i_)
2220 if (it1_ != it1_end_)
2221 index1 = it1_.index1 ();
2223 size_type index2 = (*this) ().size1 ();
2224 if (it2_ != it2_end_)
2225 if (it2_.index1 () <= i_)
2227 if (it2_ != it2_end_) {
2228 index2 = it2_.index1 ();
2230 i_ = (std::min) (index1, index2);
2233 void decrement (sparse_bidirectional_iterator_tag) {
2234 size_type index1 = (*this) ().size1 ();
2235 if (it1_ != it1_end_) {
2236 if (i_ <= it1_.index1 ())
2238 if (it1_ != it1_end_)
2239 index1 = it1_.index1 ();
2241 size_type index2 = (*this) ().size1 ();
2242 if (it2_ != it2_end_) {
2243 if (i_ <= it2_.index1 ())
2245 if (it2_ != it2_end_)
2246 index2 = it2_.index1 ();
2248 i_ = (std::max) (index1, index2);
2251 void increment (sparse_bidirectional_iterator_tag, difference_type n) {
2253 increment (sparse_bidirectional_iterator_tag ());
2257 decrement (sparse_bidirectional_iterator_tag ());
2262 void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
2264 decrement (sparse_bidirectional_iterator_tag ());
2268 increment (sparse_bidirectional_iterator_tag ());
2273 value_type dereference (sparse_bidirectional_iterator_tag) const {
2274 value_type t1 = value_type/*zero*/();
2275 if (it1_ != it1_end_) {
2276 BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
2277 if (it1_.index1 () == i_)
2280 value_type t2 = value_type/*zero*/();
2281 if (it2_ != it2_end_) {
2282 BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
2283 if (it2_.index1 () == i_)
2286 return functor_type::apply (t1, t2);
2292 const_iterator1 &operator ++ () {
2293 increment (iterator_category ());
2297 const_iterator1 &operator -- () {
2298 decrement (iterator_category ());
2302 const_iterator1 &operator += (difference_type n) {
2303 increment (iterator_category (), n);
2307 const_iterator1 &operator -= (difference_type n) {
2308 decrement (iterator_category (), n);
2312 difference_type operator - (const const_iterator1 &it) const {
2313 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2314 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
2315 return index1 () - it.index1 ();
2320 const_reference operator * () const {
2321 return dereference (iterator_category ());
2324 const_reference operator [] (difference_type n) const {
2325 return *(*this + n);
2328 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2330 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2331 typename self_type::
2333 const_iterator2 begin () const {
2334 return (*this) ().find2 (1, index1 (), 0);
2337 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2338 typename self_type::
2340 const_iterator2 cbegin () const {
2344 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2345 typename self_type::
2347 const_iterator2 end () const {
2348 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
2351 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2352 typename self_type::
2354 const_iterator2 cend () const {
2358 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2359 typename self_type::
2361 const_reverse_iterator2 rbegin () const {
2362 return const_reverse_iterator2 (end ());
2365 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2366 typename self_type::
2368 const_reverse_iterator2 crbegin () const {
2372 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2373 typename self_type::
2375 const_reverse_iterator2 rend () const {
2376 return const_reverse_iterator2 (begin ());
2379 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2380 typename self_type::
2382 const_reverse_iterator2 crend () const {
2389 size_type index1 () const {
2393 size_type index2 () const {
2394 // if (it1_ != it1_end_ && it2_ != it2_end_)
2395 // return BOOST_UBLAS_SAME (it1_.index2 (), it2_.index2 ());
2402 const_iterator1 &operator = (const const_iterator1 &it) {
2403 container_const_reference<self_type>::assign (&it ());
2407 it1_end_ = it.it1_end_;
2409 it2_end_ = it.it2_end_;
2415 bool operator == (const const_iterator1 &it) const {
2416 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2417 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
2418 return index1 () == it.index1 ();
2421 bool operator < (const const_iterator1 &it) const {
2422 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2423 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
2424 return index1 () < it.index1 ();
2430 const_iterator11_type it1_;
2431 const_iterator11_type it1_end_;
2432 const_iterator21_type it2_;
2433 const_iterator21_type it2_end_;
2438 const_iterator1 begin1 () const {
2439 return find1 (0, 0, 0);
2442 const_iterator1 cbegin1 () const {
2446 const_iterator1 end1 () const {
2447 return find1 (0, size1 (), 0);
2450 const_iterator1 cend1 () const {
2454 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2455 class const_iterator2:
2456 public container_const_reference<matrix_binary>,
2457 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
2458 typename E2::const_iterator2::iterator_category>::iterator_category>::template
2459 iterator_base<const_iterator2, value_type>::type {
2461 typedef typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
2462 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
2463 typedef typename matrix_binary::difference_type difference_type;
2464 typedef typename matrix_binary::value_type value_type;
2465 typedef typename matrix_binary::const_reference reference;
2466 typedef typename matrix_binary::const_pointer pointer;
2468 typedef const_iterator1 dual_iterator_type;
2469 typedef const_reverse_iterator1 dual_reverse_iterator_type;
2471 // Construction and destruction
2474 container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
2476 const_iterator2 (const self_type &mb, size_type i, size_type j,
2477 const const_iterator12_type &it1, const const_iterator12_type &it1_end,
2478 const const_iterator22_type &it2, const const_iterator22_type &it2_end):
2479 container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
2482 // Dense access specializations
2484 void increment (dense_random_access_iterator_tag) {
2485 ++ j_; ++ it1_; ++ it2_;
2488 void decrement (dense_random_access_iterator_tag) {
2489 -- j_; -- it1_; -- it2_;
2492 void increment (dense_random_access_iterator_tag, difference_type n) {
2493 j_ += n; it1_ += n; it2_ += n;
2496 void decrement (dense_random_access_iterator_tag, difference_type n) {
2497 j_ -= n; it1_ -= n; it2_ -= n;
2500 value_type dereference (dense_random_access_iterator_tag) const {
2501 return functor_type::apply (*it1_, *it2_);
2504 // Packed specializations
2506 void increment (packed_random_access_iterator_tag) {
2507 if (it1_ != it1_end_)
2508 if (it1_.index2 () <= j_)
2510 if (it2_ != it2_end_)
2511 if (it2_.index2 () <= j_)
2516 void decrement (packed_random_access_iterator_tag) {
2517 if (it1_ != it1_end_)
2518 if (j_ <= it1_.index2 ())
2520 if (it2_ != it2_end_)
2521 if (j_ <= it2_.index2 ())
2526 void increment (packed_random_access_iterator_tag, difference_type n) {
2528 increment (packed_random_access_iterator_tag ());
2532 decrement (packed_random_access_iterator_tag ());
2537 void decrement (packed_random_access_iterator_tag, difference_type n) {
2539 decrement (packed_random_access_iterator_tag ());
2543 increment (packed_random_access_iterator_tag ());
2548 value_type dereference (packed_random_access_iterator_tag) const {
2549 value_type t1 = value_type/*zero*/();
2550 if (it1_ != it1_end_) {
2551 BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
2552 if (it1_.index2 () == j_)
2555 value_type t2 = value_type/*zero*/();
2556 if (it2_ != it2_end_) {
2557 BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
2558 if (it2_.index2 () == j_)
2561 return functor_type::apply (t1, t2);
2564 // Sparse specializations
2566 void increment (sparse_bidirectional_iterator_tag) {
2567 size_type index1 = (*this) ().size2 ();
2568 if (it1_ != it1_end_) {
2569 if (it1_.index2 () <= j_)
2571 if (it1_ != it1_end_)
2572 index1 = it1_.index2 ();
2574 size_type index2 = (*this) ().size2 ();
2575 if (it2_ != it2_end_) {
2576 if (it2_.index2 () <= j_)
2578 if (it2_ != it2_end_)
2579 index2 = it2_.index2 ();
2581 j_ = (std::min) (index1, index2);
2584 void decrement (sparse_bidirectional_iterator_tag) {
2585 size_type index1 = (*this) ().size2 ();
2586 if (it1_ != it1_end_) {
2587 if (j_ <= it1_.index2 ())
2589 if (it1_ != it1_end_)
2590 index1 = it1_.index2 ();
2592 size_type index2 = (*this) ().size2 ();
2593 if (it2_ != it2_end_) {
2594 if (j_ <= it2_.index2 ())
2596 if (it2_ != it2_end_)
2597 index2 = it2_.index2 ();
2599 j_ = (std::max) (index1, index2);
2602 void increment (sparse_bidirectional_iterator_tag, difference_type n) {
2604 increment (sparse_bidirectional_iterator_tag ());
2608 decrement (sparse_bidirectional_iterator_tag ());
2613 void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
2615 decrement (sparse_bidirectional_iterator_tag ());
2619 increment (sparse_bidirectional_iterator_tag ());
2624 value_type dereference (sparse_bidirectional_iterator_tag) const {
2625 value_type t1 = value_type/*zero*/();
2626 if (it1_ != it1_end_) {
2627 BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
2628 if (it1_.index2 () == j_)
2631 value_type t2 = value_type/*zero*/();
2632 if (it2_ != it2_end_) {
2633 BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
2634 if (it2_.index2 () == j_)
2637 return functor_type::apply (t1, t2);
2643 const_iterator2 &operator ++ () {
2644 increment (iterator_category ());
2648 const_iterator2 &operator -- () {
2649 decrement (iterator_category ());
2653 const_iterator2 &operator += (difference_type n) {
2654 increment (iterator_category (), n);
2658 const_iterator2 &operator -= (difference_type n) {
2659 decrement (iterator_category (), n);
2663 difference_type operator - (const const_iterator2 &it) const {
2664 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2665 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
2666 return index2 () - it.index2 ();
2671 const_reference operator * () const {
2672 return dereference (iterator_category ());
2675 const_reference operator [] (difference_type n) const {
2676 return *(*this + n);
2679 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2681 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2682 typename self_type::
2684 const_iterator1 begin () const {
2685 return (*this) ().find1 (1, 0, index2 ());
2688 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2689 typename self_type::
2691 const_iterator1 cbegin () const {
2695 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2696 typename self_type::
2698 const_iterator1 end () const {
2699 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
2702 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2703 typename self_type::
2705 const_iterator1 cend () const {
2709 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2710 typename self_type::
2712 const_reverse_iterator1 rbegin () const {
2713 return const_reverse_iterator1 (end ());
2716 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2717 typename self_type::
2719 const_reverse_iterator1 crbegin () const {
2723 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2724 typename self_type::
2726 const_reverse_iterator1 rend () const {
2727 return const_reverse_iterator1 (begin ());
2730 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2731 typename self_type::
2733 const_reverse_iterator1 crend () const {
2740 size_type index1 () const {
2741 // if (it1_ != it1_end_ && it2_ != it2_end_)
2742 // return BOOST_UBLAS_SAME (it1_.index1 (), it2_.index1 ());
2747 size_type index2 () const {
2753 const_iterator2 &operator = (const const_iterator2 &it) {
2754 container_const_reference<self_type>::assign (&it ());
2758 it1_end_ = it.it1_end_;
2760 it2_end_ = it.it2_end_;
2766 bool operator == (const const_iterator2 &it) const {
2767 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2768 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
2769 return index2 () == it.index2 ();
2772 bool operator < (const const_iterator2 &it) const {
2773 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2774 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
2775 return index2 () < it.index2 ();
2781 const_iterator12_type it1_;
2782 const_iterator12_type it1_end_;
2783 const_iterator22_type it2_;
2784 const_iterator22_type it2_end_;
2789 const_iterator2 begin2 () const {
2790 return find2 (0, 0, 0);
2793 const_iterator2 cbegin2 () const {
2797 const_iterator2 end2 () const {
2798 return find2 (0, 0, size2 ());
2801 const_iterator2 cend2 () const {
2805 // Reverse iterators
2808 const_reverse_iterator1 rbegin1 () const {
2809 return const_reverse_iterator1 (end1 ());
2812 const_reverse_iterator1 crbegin1 () const {
2816 const_reverse_iterator1 rend1 () const {
2817 return const_reverse_iterator1 (begin1 ());
2820 const_reverse_iterator1 crend1 () const {
2825 const_reverse_iterator2 rbegin2 () const {
2826 return const_reverse_iterator2 (end2 ());
2829 const_reverse_iterator2 crbegin2 () const {
2833 const_reverse_iterator2 rend2 () const {
2834 return const_reverse_iterator2 (begin2 ());
2837 const_reverse_iterator2 crend2 () const {
2842 expression1_closure_type e1_;
2843 expression2_closure_type e2_;
2846 template<class E1, class E2, class F>
2847 struct matrix_binary_traits {
2848 typedef matrix_binary<E1, E2, F> expression_type;
2849 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
2850 typedef expression_type result_type;
2852 typedef typename E1::matrix_temporary_type result_type;
2856 // (m1 + m2) [i] [j] = m1 [i] [j] + m2 [i] [j]
2857 template<class E1, class E2>
2859 typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
2860 typename E2::value_type> >::result_type
2861 operator + (const matrix_expression<E1> &e1,
2862 const matrix_expression<E2> &e2) {
2863 typedef typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
2864 typename E2::value_type> >::expression_type expression_type;
2865 return expression_type (e1 (), e2 ());
2868 // (m1 - m2) [i] [j] = m1 [i] [j] - m2 [i] [j]
2869 template<class E1, class E2>
2871 typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
2872 typename E2::value_type> >::result_type
2873 operator - (const matrix_expression<E1> &e1,
2874 const matrix_expression<E2> &e2) {
2875 typedef typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
2876 typename E2::value_type> >::expression_type expression_type;
2877 return expression_type (e1 (), e2 ());
2880 // (m1 * m2) [i] [j] = m1 [i] [j] * m2 [i] [j]
2881 template<class E1, class E2>
2883 typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
2884 typename E2::value_type> >::result_type
2885 element_prod (const matrix_expression<E1> &e1,
2886 const matrix_expression<E2> &e2) {
2887 typedef typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
2888 typename E2::value_type> >::expression_type expression_type;
2889 return expression_type (e1 (), e2 ());
2892 // (m1 / m2) [i] [j] = m1 [i] [j] / m2 [i] [j]
2893 template<class E1, class E2>
2895 typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
2896 typename E2::value_type> >::result_type
2897 element_div (const matrix_expression<E1> &e1,
2898 const matrix_expression<E2> &e2) {
2899 typedef typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
2900 typename E2::value_type> >::expression_type expression_type;
2901 return expression_type (e1 (), e2 ());
2904 template<class E1, class E2, class F>
2905 class matrix_binary_scalar1:
2906 public matrix_expression<matrix_binary_scalar1<E1, E2, F> > {
2908 typedef E1 expression1_type;
2909 typedef E2 expression2_type;
2910 typedef F functor_type;
2911 typedef const E1& expression1_closure_type;
2912 typedef typename E2::const_closure_type expression2_closure_type;
2913 typedef matrix_binary_scalar1<E1, E2, F> self_type;
2915 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2916 using matrix_expression<self_type>::operator ();
2918 typedef typename E2::size_type size_type;
2919 typedef typename E2::difference_type difference_type;
2920 typedef typename F::result_type value_type;
2921 typedef value_type const_reference;
2922 typedef const_reference reference;
2923 typedef const self_type const_closure_type;
2924 typedef const_closure_type closure_type;
2925 typedef typename E2::orientation_category orientation_category;
2926 typedef unknown_storage_tag storage_category;
2928 // Construction and destruction
2930 matrix_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
2931 e1_ (e1), e2_ (e2) {}
2935 size_type size1 () const {
2936 return e2_.size1 ();
2939 size_type size2 () const {
2940 return e2_.size2 ();
2946 const_reference operator () (size_type i, size_type j) const {
2947 return functor_type::apply (expression1_type (e1_), e2_ (i, j));
2950 // Closure comparison
2952 bool same_closure (const matrix_binary_scalar1 &mbs1) const {
2953 return &e1_ == &(mbs1.e1_) &&
2954 (*this).e2_.same_closure (mbs1.e2_);
2959 typedef expression1_type const_subiterator1_type;
2960 typedef typename E2::const_iterator1 const_iterator21_type;
2961 typedef typename E2::const_iterator2 const_iterator22_type;
2962 typedef const value_type *const_pointer;
2965 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2966 typedef indexed_const_iterator1<const_closure_type, typename const_iterator21_type::iterator_category> const_iterator1;
2967 typedef const_iterator1 iterator1;
2968 typedef indexed_const_iterator2<const_closure_type, typename const_iterator22_type::iterator_category> const_iterator2;
2969 typedef const_iterator2 iterator2;
2971 class const_iterator1;
2972 typedef const_iterator1 iterator1;
2973 class const_iterator2;
2974 typedef const_iterator2 iterator2;
2976 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2977 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2981 const_iterator1 find1 (int rank, size_type i, size_type j) const {
2982 const_iterator21_type it21 (e2_.find1 (rank, i, j));
2983 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2984 return const_iterator1 (*this, it21.index1 (), it21.index2 ());
2986 return const_iterator1 (*this, const_subiterator1_type (e1_), it21);
2990 const_iterator2 find2 (int rank, size_type i, size_type j) const {
2991 const_iterator22_type it22 (e2_.find2 (rank, i, j));
2992 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2993 return const_iterator2 (*this, it22.index1 (), it22.index2 ());
2995 return const_iterator2 (*this, const_subiterator1_type (e1_), it22);
2999 // Iterators enhance the iterators of the referenced expression
3000 // with the binary functor.
3002 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3003 class const_iterator1:
3004 public container_const_reference<matrix_binary_scalar1>,
3005 public iterator_base_traits<typename E2::const_iterator1::iterator_category>::template
3006 iterator_base<const_iterator1, value_type>::type {
3008 typedef typename E2::const_iterator1::iterator_category iterator_category;
3009 typedef typename matrix_binary_scalar1::difference_type difference_type;
3010 typedef typename matrix_binary_scalar1::value_type value_type;
3011 typedef typename matrix_binary_scalar1::const_reference reference;
3012 typedef typename matrix_binary_scalar1::const_pointer pointer;
3014 typedef const_iterator2 dual_iterator_type;
3015 typedef const_reverse_iterator2 dual_reverse_iterator_type;
3017 // Construction and destruction
3020 container_const_reference<self_type> (), it1_ (), it2_ () {}
3022 const_iterator1 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator21_type &it2):
3023 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
3027 const_iterator1 &operator ++ () {
3032 const_iterator1 &operator -- () {
3037 const_iterator1 &operator += (difference_type n) {
3042 const_iterator1 &operator -= (difference_type n) {
3047 difference_type operator - (const const_iterator1 &it) const {
3048 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3049 // FIXME we shouldn't compare floats
3050 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3051 return it2_ - it.it2_;
3056 const_reference operator * () const {
3057 return functor_type::apply (it1_, *it2_);
3060 const_reference operator [] (difference_type n) const {
3061 return *(*this + n);
3064 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3066 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3067 typename self_type::
3069 const_iterator2 begin () const {
3070 return (*this) ().find2 (1, index1 (), 0);
3073 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3074 typename self_type::
3076 const_iterator2 cbegin () const {
3080 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3081 typename self_type::
3083 const_iterator2 end () const {
3084 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
3087 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3088 typename self_type::
3090 const_iterator2 cend () const {
3094 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3095 typename self_type::
3097 const_reverse_iterator2 rbegin () const {
3098 return const_reverse_iterator2 (end ());
3101 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3102 typename self_type::
3104 const_reverse_iterator2 crbegin () const {
3108 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3109 typename self_type::
3111 const_reverse_iterator2 rend () const {
3112 return const_reverse_iterator2 (begin ());
3115 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3116 typename self_type::
3118 const_reverse_iterator2 crend () const {
3125 size_type index1 () const {
3126 return it2_.index1 ();
3129 size_type index2 () const {
3130 return it2_.index2 ();
3135 const_iterator1 &operator = (const const_iterator1 &it) {
3136 container_const_reference<self_type>::assign (&it ());
3144 bool operator == (const const_iterator1 &it) const {
3145 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3146 // FIXME we shouldn't compare floats
3147 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3148 return it2_ == it.it2_;
3151 bool operator < (const const_iterator1 &it) const {
3152 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3153 // FIXME we shouldn't compare floats
3154 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3155 return it2_ < it.it2_;
3159 const_subiterator1_type it1_;
3160 const_iterator21_type it2_;
3165 const_iterator1 begin1 () const {
3166 return find1 (0, 0, 0);
3169 const_iterator1 cbegin1 () const {
3173 const_iterator1 end1 () const {
3174 return find1 (0, size1 (), 0);
3177 const_iterator1 cend1 () const {
3181 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3182 class const_iterator2:
3183 public container_const_reference<matrix_binary_scalar1>,
3184 public iterator_base_traits<typename E2::const_iterator2::iterator_category>::template
3185 iterator_base<const_iterator2, value_type>::type {
3187 typedef typename E2::const_iterator2::iterator_category iterator_category;
3188 typedef typename matrix_binary_scalar1::difference_type difference_type;
3189 typedef typename matrix_binary_scalar1::value_type value_type;
3190 typedef typename matrix_binary_scalar1::const_reference reference;
3191 typedef typename matrix_binary_scalar1::const_pointer pointer;
3193 typedef const_iterator1 dual_iterator_type;
3194 typedef const_reverse_iterator1 dual_reverse_iterator_type;
3196 // Construction and destruction
3199 container_const_reference<self_type> (), it1_ (), it2_ () {}
3201 const_iterator2 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator22_type &it2):
3202 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
3206 const_iterator2 &operator ++ () {
3211 const_iterator2 &operator -- () {
3216 const_iterator2 &operator += (difference_type n) {
3221 const_iterator2 &operator -= (difference_type n) {
3226 difference_type operator - (const const_iterator2 &it) const {
3227 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3228 // FIXME we shouldn't compare floats
3229 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3230 return it2_ - it.it2_;
3235 const_reference operator * () const {
3236 return functor_type::apply (it1_, *it2_);
3239 const_reference operator [] (difference_type n) const {
3240 return *(*this + n);
3243 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3245 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3246 typename self_type::
3248 const_iterator1 begin () const {
3249 return (*this) ().find1 (1, 0, index2 ());
3252 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3253 typename self_type::
3255 const_iterator1 cbegin () const {
3259 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3260 typename self_type::
3262 const_iterator1 end () const {
3263 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
3266 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3267 typename self_type::
3269 const_iterator1 cend () const {
3273 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3274 typename self_type::
3276 const_reverse_iterator1 rbegin () const {
3277 return const_reverse_iterator1 (end ());
3280 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3281 typename self_type::
3283 const_reverse_iterator1 crbegin () const {
3287 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3288 typename self_type::
3290 const_reverse_iterator1 rend () const {
3291 return const_reverse_iterator1 (begin ());
3294 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3295 typename self_type::
3297 const_reverse_iterator1 crend () const {
3304 size_type index1 () const {
3305 return it2_.index1 ();
3308 size_type index2 () const {
3309 return it2_.index2 ();
3314 const_iterator2 &operator = (const const_iterator2 &it) {
3315 container_const_reference<self_type>::assign (&it ());
3323 bool operator == (const const_iterator2 &it) const {
3324 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3325 // FIXME we shouldn't compare floats
3326 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3327 return it2_ == it.it2_;
3330 bool operator < (const const_iterator2 &it) const {
3331 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3332 // FIXME we shouldn't compare floats
3333 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3334 return it2_ < it.it2_;
3338 const_subiterator1_type it1_;
3339 const_iterator22_type it2_;
3344 const_iterator2 begin2 () const {
3345 return find2 (0, 0, 0);
3348 const_iterator2 cbegin2 () const {
3352 const_iterator2 end2 () const {
3353 return find2 (0, 0, size2 ());
3356 const_iterator2 cend2 () const {
3360 // Reverse iterators
3363 const_reverse_iterator1 rbegin1 () const {
3364 return const_reverse_iterator1 (end1 ());
3367 const_reverse_iterator1 crbegin1 () const {
3371 const_reverse_iterator1 rend1 () const {
3372 return const_reverse_iterator1 (begin1 ());
3375 const_reverse_iterator1 crend1 () const {
3380 const_reverse_iterator2 rbegin2 () const {
3381 return const_reverse_iterator2 (end2 ());
3384 const_reverse_iterator2 crbegin2 () const {
3388 const_reverse_iterator2 rend2 () const {
3389 return const_reverse_iterator2 (begin2 ());
3392 const_reverse_iterator2 crend2 () const {
3397 expression1_closure_type e1_;
3398 expression2_closure_type e2_;
3401 template<class E1, class E2, class F>
3402 struct matrix_binary_scalar1_traits {
3403 typedef matrix_binary_scalar1<E1, E2, F> expression_type; // allow E1 to be builtin type
3404 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
3405 typedef expression_type result_type;
3407 typedef typename E2::matrix_temporary_type result_type;
3411 // (t * m) [i] [j] = t * m [i] [j]
3412 template<class T1, class E2>
3414 typename enable_if< is_convertible<T1, typename E2::value_type >,
3415 typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
3417 operator * (const T1 &e1,
3418 const matrix_expression<E2> &e2) {
3419 typedef typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
3420 return expression_type (e1, e2 ());
3424 template<class E1, class E2, class F>
3425 class matrix_binary_scalar2:
3426 public matrix_expression<matrix_binary_scalar2<E1, E2, F> > {
3428 typedef E1 expression1_type;
3429 typedef E2 expression2_type;
3430 typedef F functor_type;
3432 typedef typename E1::const_closure_type expression1_closure_type;
3433 typedef const E2& expression2_closure_type;
3435 typedef matrix_binary_scalar2<E1, E2, F> self_type;
3437 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
3438 using matrix_expression<self_type>::operator ();
3440 typedef typename E1::size_type size_type;
3441 typedef typename E1::difference_type difference_type;
3442 typedef typename F::result_type value_type;
3443 typedef value_type const_reference;
3444 typedef const_reference reference;
3446 typedef const self_type const_closure_type;
3447 typedef const_closure_type closure_type;
3448 typedef typename E1::orientation_category orientation_category;
3449 typedef unknown_storage_tag storage_category;
3451 // Construction and destruction
3453 matrix_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
3454 e1_ (e1), e2_ (e2) {}
3458 size_type size1 () const {
3459 return e1_.size1 ();
3462 size_type size2 () const {
3463 return e1_.size2 ();
3469 const_reference operator () (size_type i, size_type j) const {
3470 return functor_type::apply (e1_ (i, j), expression2_type (e2_));
3473 // Closure comparison
3475 bool same_closure (const matrix_binary_scalar2 &mbs2) const {
3476 return (*this).e1_.same_closure (mbs2.e1_) &&
3477 &e2_ == &(mbs2.e2_);
3482 typedef typename E1::const_iterator1 const_iterator11_type;
3483 typedef typename E1::const_iterator2 const_iterator12_type;
3484 typedef expression2_type const_subiterator2_type;
3485 typedef const value_type *const_pointer;
3488 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3489 typedef indexed_const_iterator1<const_closure_type, typename const_iterator11_type::iterator_category> const_iterator1;
3490 typedef const_iterator1 iterator1;
3491 typedef indexed_const_iterator2<const_closure_type, typename const_iterator12_type::iterator_category> const_iterator2;
3492 typedef const_iterator2 iterator2;
3494 class const_iterator1;
3495 typedef const_iterator1 iterator1;
3496 class const_iterator2;
3497 typedef const_iterator2 iterator2;
3499 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
3500 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
3504 const_iterator1 find1 (int rank, size_type i, size_type j) const {
3505 const_iterator11_type it11 (e1_.find1 (rank, i, j));
3506 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3507 return const_iterator1 (*this, it11.index1 (), it11.index2 ());
3509 return const_iterator1 (*this, it11, const_subiterator2_type (e2_));
3513 const_iterator2 find2 (int rank, size_type i, size_type j) const {
3514 const_iterator12_type it12 (e1_.find2 (rank, i, j));
3515 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3516 return const_iterator2 (*this, it12.index1 (), it12.index2 ());
3518 return const_iterator2 (*this, it12, const_subiterator2_type (e2_));
3522 // Iterators enhance the iterators of the referenced expression
3523 // with the binary functor.
3525 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3526 class const_iterator1:
3527 public container_const_reference<matrix_binary_scalar2>,
3528 public iterator_base_traits<typename E1::const_iterator1::iterator_category>::template
3529 iterator_base<const_iterator1, value_type>::type {
3531 typedef typename E1::const_iterator1::iterator_category iterator_category;
3532 typedef typename matrix_binary_scalar2::difference_type difference_type;
3533 typedef typename matrix_binary_scalar2::value_type value_type;
3534 typedef typename matrix_binary_scalar2::const_reference reference;
3535 typedef typename matrix_binary_scalar2::const_pointer pointer;
3537 typedef const_iterator2 dual_iterator_type;
3538 typedef const_reverse_iterator2 dual_reverse_iterator_type;
3540 // Construction and destruction
3543 container_const_reference<self_type> (), it1_ (), it2_ () {}
3545 const_iterator1 (const self_type &mbs, const const_iterator11_type &it1, const const_subiterator2_type &it2):
3546 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
3550 const_iterator1 &operator ++ () {
3555 const_iterator1 &operator -- () {
3560 const_iterator1 &operator += (difference_type n) {
3565 const_iterator1 &operator -= (difference_type n) {
3570 difference_type operator - (const const_iterator1 &it) const {
3571 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3572 // FIXME we shouldn't compare floats
3573 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3574 return it1_ - it.it1_;
3579 const_reference operator * () const {
3580 return functor_type::apply (*it1_, it2_);
3583 const_reference operator [] (difference_type n) const {
3584 return *(*this + n);
3587 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3589 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3590 typename self_type::
3592 const_iterator2 begin () const {
3593 return (*this) ().find2 (1, index1 (), 0);
3596 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3597 typename self_type::
3599 const_iterator2 cbegin () const {
3603 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3604 typename self_type::
3606 const_iterator2 end () const {
3607 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
3610 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3611 typename self_type::
3613 const_iterator2 cend () const {
3617 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3618 typename self_type::
3620 const_reverse_iterator2 rbegin () const {
3621 return const_reverse_iterator2 (end ());
3624 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3625 typename self_type::
3627 const_reverse_iterator2 crbegin () const {
3631 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3632 typename self_type::
3634 const_reverse_iterator2 rend () const {
3635 return const_reverse_iterator2 (begin ());
3638 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3639 typename self_type::
3641 const_reverse_iterator2 crend () const {
3648 size_type index1 () const {
3649 return it1_.index1 ();
3652 size_type index2 () const {
3653 return it1_.index2 ();
3658 const_iterator1 &operator = (const const_iterator1 &it) {
3659 container_const_reference<self_type>::assign (&it ());
3667 bool operator == (const const_iterator1 &it) const {
3668 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3669 // FIXME we shouldn't compare floats
3670 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3671 return it1_ == it.it1_;
3674 bool operator < (const const_iterator1 &it) const {
3675 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3676 // FIXME we shouldn't compare floats
3677 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3678 return it1_ < it.it1_;
3682 const_iterator11_type it1_;
3683 const_subiterator2_type it2_;
3688 const_iterator1 begin1 () const {
3689 return find1 (0, 0, 0);
3692 const_iterator1 cbegin1 () const {
3696 const_iterator1 end1 () const {
3697 return find1 (0, size1 (), 0);
3700 const_iterator1 cend1 () const {
3704 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3705 class const_iterator2:
3706 public container_const_reference<matrix_binary_scalar2>,
3707 public iterator_base_traits<typename E1::const_iterator2::iterator_category>::template
3708 iterator_base<const_iterator2, value_type>::type {
3710 typedef typename E1::const_iterator2::iterator_category iterator_category;
3711 typedef typename matrix_binary_scalar2::difference_type difference_type;
3712 typedef typename matrix_binary_scalar2::value_type value_type;
3713 typedef typename matrix_binary_scalar2::const_reference reference;
3714 typedef typename matrix_binary_scalar2::const_pointer pointer;
3716 typedef const_iterator1 dual_iterator_type;
3717 typedef const_reverse_iterator1 dual_reverse_iterator_type;
3719 // Construction and destruction
3722 container_const_reference<self_type> (), it1_ (), it2_ () {}
3724 const_iterator2 (const self_type &mbs, const const_iterator12_type &it1, const const_subiterator2_type &it2):
3725 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
3729 const_iterator2 &operator ++ () {
3734 const_iterator2 &operator -- () {
3739 const_iterator2 &operator += (difference_type n) {
3744 const_iterator2 &operator -= (difference_type n) {
3749 difference_type operator - (const const_iterator2 &it) const {
3750 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3751 // FIXME we shouldn't compare floats
3752 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3753 return it1_ - it.it1_;
3758 const_reference operator * () const {
3759 return functor_type::apply (*it1_, it2_);
3762 const_reference operator [] (difference_type n) const {
3763 return *(*this + n);
3766 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3768 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3769 typename self_type::
3771 const_iterator1 begin () const {
3772 return (*this) ().find1 (1, 0, index2 ());
3775 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3776 typename self_type::
3778 const_iterator1 cbegin () const {
3782 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3783 typename self_type::
3785 const_iterator1 end () const {
3786 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
3789 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3790 typename self_type::
3792 const_iterator1 cend () const {
3796 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3797 typename self_type::
3799 const_reverse_iterator1 rbegin () const {
3800 return const_reverse_iterator1 (end ());
3803 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3804 typename self_type::
3806 const_reverse_iterator1 crbegin () const {
3810 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3811 typename self_type::
3813 const_reverse_iterator1 rend () const {
3814 return const_reverse_iterator1 (begin ());
3817 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3818 typename self_type::
3820 const_reverse_iterator1 crend () const {
3827 size_type index1 () const {
3828 return it1_.index1 ();
3831 size_type index2 () const {
3832 return it1_.index2 ();
3837 const_iterator2 &operator = (const const_iterator2 &it) {
3838 container_const_reference<self_type>::assign (&it ());
3846 bool operator == (const const_iterator2 &it) const {
3847 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3848 // FIXME we shouldn't compare floats
3849 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3850 return it1_ == it.it1_;
3853 bool operator < (const const_iterator2 &it) const {
3854 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3855 // FIXME we shouldn't compare floats
3856 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3857 return it1_ < it.it1_;
3861 const_iterator12_type it1_;
3862 const_subiterator2_type it2_;
3867 const_iterator2 begin2 () const {
3868 return find2 (0, 0, 0);
3871 const_iterator2 cbegin2 () const {
3875 const_iterator2 end2 () const {
3876 return find2 (0, 0, size2 ());
3879 const_iterator2 cend2 () const {
3883 // Reverse iterators
3886 const_reverse_iterator1 rbegin1 () const {
3887 return const_reverse_iterator1 (end1 ());
3890 const_reverse_iterator1 crbegin1 () const {
3894 const_reverse_iterator1 rend1 () const {
3895 return const_reverse_iterator1 (begin1 ());
3898 const_reverse_iterator1 crend1 () const {
3903 const_reverse_iterator2 rbegin2 () const {
3904 return const_reverse_iterator2 (end2 ());
3907 const_reverse_iterator2 crbegin2 () const {
3911 const_reverse_iterator2 rend2 () const {
3912 return const_reverse_iterator2 (begin2 ());
3915 const_reverse_iterator2 crend2 () const {
3920 expression1_closure_type e1_;
3921 expression2_closure_type e2_;
3924 template<class E1, class E2, class F>
3925 struct matrix_binary_scalar2_traits {
3926 typedef matrix_binary_scalar2<E1, E2, F> expression_type; // allow E2 to be builtin type
3927 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
3928 typedef expression_type result_type;
3930 typedef typename E1::matrix_temporary_type result_type;
3934 // (m * t) [i] [j] = m [i] [j] * t
3935 template<class E1, class T2>
3937 typename enable_if< is_convertible<T2, typename E1::value_type>,
3938 typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
3940 operator * (const matrix_expression<E1> &e1,
3942 typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
3943 return expression_type (e1 (), e2);
3946 // (m / t) [i] [j] = m [i] [j] / t
3947 template<class E1, class T2>
3949 typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
3950 operator / (const matrix_expression<E1> &e1,
3952 typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
3953 return expression_type (e1 (), e2);
3957 template<class E1, class E2, class F>
3958 class matrix_vector_binary1:
3959 public vector_expression<matrix_vector_binary1<E1, E2, F> > {
3962 typedef E1 expression1_type;
3963 typedef E2 expression2_type;
3965 typedef F functor_type;
3967 typedef typename E1::const_closure_type expression1_closure_type;
3968 typedef typename E2::const_closure_type expression2_closure_type;
3970 typedef matrix_vector_binary1<E1, E2, F> self_type;
3972 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
3973 using vector_expression<self_type>::operator ();
3975 static const unsigned complexity = 1;
3976 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
3977 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
3978 typedef typename F::result_type value_type;
3979 typedef value_type const_reference;
3980 typedef const_reference reference;
3981 typedef const self_type const_closure_type;
3982 typedef const_closure_type closure_type;
3983 typedef unknown_storage_tag storage_category;
3985 // Construction and destruction
3987 matrix_vector_binary1 (const expression1_type &e1, const expression2_type &e2):
3988 e1_ (e1), e2_ (e2) {}
3992 size_type size () const {
3993 return e1_.size1 ();
3997 // Expression accessors
3999 const expression1_closure_type &expression1 () const {
4003 const expression2_closure_type &expression2 () const {
4010 const_reference operator () (size_type i) const {
4011 return functor_type::apply (e1_, e2_, i);
4014 // Closure comparison
4016 bool same_closure (const matrix_vector_binary1 &mvb1) const {
4017 return (*this).expression1 ().same_closure (mvb1.expression1 ()) &&
4018 (*this).expression2 ().same_closure (mvb1.expression2 ());
4023 typedef typename E1::const_iterator1 const_subiterator1_type;
4024 typedef typename E2::const_iterator const_subiterator2_type;
4025 typedef const value_type *const_pointer;
4028 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4029 typedef indexed_const_iterator<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator;
4030 typedef const_iterator iterator;
4032 class const_iterator;
4033 typedef const_iterator iterator;
4038 const_iterator find (size_type i) const {
4039 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4040 const_subiterator1_type it1 (e1_.find1 (0, i, 0));
4041 return const_iterator (*this, it1.index1 ());
4043 return const_iterator (*this, e1_.find1 (0, i, 0));
4048 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4049 class const_iterator:
4050 public container_const_reference<matrix_vector_binary1>,
4051 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
4052 typename E2::const_iterator::iterator_category>::iterator_category>::template
4053 iterator_base<const_iterator, value_type>::type {
4055 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
4056 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
4057 typedef typename matrix_vector_binary1::difference_type difference_type;
4058 typedef typename matrix_vector_binary1::value_type value_type;
4059 typedef typename matrix_vector_binary1::const_reference reference;
4060 typedef typename matrix_vector_binary1::const_pointer pointer;
4062 // Construction and destruction
4063 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4066 container_const_reference<self_type> (), it1_ (), e2_begin_ (), e2_end_ () {}
4068 const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
4069 container_const_reference<self_type> (mvb), it1_ (it1), e2_begin_ (mvb.expression2 ().begin ()), e2_end_ (mvb.expression2 ().end ()) {}
4073 container_const_reference<self_type> (), it1_ () {}
4075 const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
4076 container_const_reference<self_type> (mvb), it1_ (it1) {}
4080 // Dense random access specialization
4082 value_type dereference (dense_random_access_iterator_tag) const {
4083 const self_type &mvb = (*this) ();
4084 #ifdef BOOST_UBLAS_USE_INDEXING
4085 return mvb (index ());
4086 #elif BOOST_UBLAS_USE_ITERATING
4087 difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
4088 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4089 return functor_type::apply (size, it1_.begin (), e2_begin_);
4091 return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
4094 difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
4095 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
4096 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4097 return functor_type::apply (size, it1_.begin (), e2_begin_);
4099 return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
4102 return mvb (index ());
4106 // Packed bidirectional specialization
4108 value_type dereference (packed_random_access_iterator_tag) const {
4109 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4110 return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_);
4112 const self_type &mvb = (*this) ();
4113 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4114 return functor_type::apply (it1_.begin (), it1_.end (),
4115 mvb.expression2 ().begin (), mvb.expression2 ().end ());
4117 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
4118 boost::numeric::ublas::end (it1_, iterator1_tag ()),
4119 mvb.expression2 ().begin (), mvb.expression2 ().end ());
4124 // Sparse bidirectional specialization
4126 value_type dereference (sparse_bidirectional_iterator_tag) const {
4127 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4128 return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_, sparse_bidirectional_iterator_tag ());
4130 const self_type &mvb = (*this) ();
4131 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4132 return functor_type::apply (it1_.begin (), it1_.end (),
4133 mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
4135 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
4136 boost::numeric::ublas::end (it1_, iterator1_tag ()),
4137 mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
4145 const_iterator &operator ++ () {
4150 const_iterator &operator -- () {
4155 const_iterator &operator += (difference_type n) {
4160 const_iterator &operator -= (difference_type n) {
4165 difference_type operator - (const const_iterator &it) const {
4166 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4167 return it1_ - it.it1_;
4172 const_reference operator * () const {
4173 return dereference (iterator_category ());
4176 const_reference operator [] (difference_type n) const {
4177 return *(*this + n);
4182 size_type index () const {
4183 return it1_.index1 ();
4188 const_iterator &operator = (const const_iterator &it) {
4189 container_const_reference<self_type>::assign (&it ());
4191 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4192 e2_begin_ = it.e2_begin_;
4193 e2_end_ = it.e2_end_;
4200 bool operator == (const const_iterator &it) const {
4201 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4202 return it1_ == it.it1_;
4205 bool operator < (const const_iterator &it) const {
4206 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4207 return it1_ < it.it1_;
4211 const_subiterator1_type it1_;
4212 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4213 // Mutable due to assignment
4214 /* const */ const_subiterator2_type e2_begin_;
4215 /* const */ const_subiterator2_type e2_end_;
4221 const_iterator begin () const {
4225 const_iterator cbegin () const {
4229 const_iterator end () const {
4230 return find (size ());
4233 const_iterator cend () const {
4238 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
4241 const_reverse_iterator rbegin () const {
4242 return const_reverse_iterator (end ());
4245 const_reverse_iterator crbegin () const {
4249 const_reverse_iterator rend () const {
4250 return const_reverse_iterator (begin ());
4253 const_reverse_iterator crend () const {
4258 expression1_closure_type e1_;
4259 expression2_closure_type e2_;
4262 template<class T1, class E1, class T2, class E2>
4263 struct matrix_vector_binary1_traits {
4264 typedef unknown_storage_tag storage_category;
4265 typedef row_major_tag orientation_category;
4266 typedef typename promote_traits<T1, T2>::promote_type promote_type;
4267 typedef matrix_vector_binary1<E1, E2, matrix_vector_prod1<E1, E2, promote_type> > expression_type;
4268 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
4269 typedef expression_type result_type;
4271 typedef typename E1::vector_temporary_type result_type;
4275 template<class E1, class E2>
4277 typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4278 typename E2::value_type, E2>::result_type
4279 prod (const matrix_expression<E1> &e1,
4280 const vector_expression<E2> &e2,
4281 unknown_storage_tag,
4283 typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4284 typename E2::value_type, E2>::expression_type expression_type;
4285 return expression_type (e1 (), e2 ());
4289 template<class E1, class E2>
4291 typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4292 typename E2::value_type, E2>::result_type
4293 prod (const matrix_expression<E1> &e1,
4294 const vector_expression<E2> &e2) {
4295 BOOST_STATIC_ASSERT (E2::complexity == 0);
4296 typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4297 typename E2::value_type, E2>::storage_category storage_category;
4298 typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4299 typename E2::value_type, E2>::orientation_category orientation_category;
4300 return prod (e1, e2, storage_category (), orientation_category ());
4303 template<class E1, class E2>
4305 typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4306 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
4307 prec_prod (const matrix_expression<E1> &e1,
4308 const vector_expression<E2> &e2,
4309 unknown_storage_tag,
4311 typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4312 typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
4313 return expression_type (e1 (), e2 ());
4317 template<class E1, class E2>
4319 typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4320 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
4321 prec_prod (const matrix_expression<E1> &e1,
4322 const vector_expression<E2> &e2) {
4323 BOOST_STATIC_ASSERT (E2::complexity == 0);
4324 typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4325 typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
4326 typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4327 typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
4328 return prec_prod (e1, e2, storage_category (), orientation_category ());
4331 template<class V, class E1, class E2>
4334 prod (const matrix_expression<E1> &e1,
4335 const vector_expression<E2> &e2,
4337 return v.assign (prod (e1, e2));
4340 template<class V, class E1, class E2>
4343 prec_prod (const matrix_expression<E1> &e1,
4344 const vector_expression<E2> &e2,
4346 return v.assign (prec_prod (e1, e2));
4349 template<class V, class E1, class E2>
4352 prod (const matrix_expression<E1> &e1,
4353 const vector_expression<E2> &e2) {
4354 return V (prod (e1, e2));
4357 template<class V, class E1, class E2>
4360 prec_prod (const matrix_expression<E1> &e1,
4361 const vector_expression<E2> &e2) {
4362 return V (prec_prod (e1, e2));
4365 template<class E1, class E2, class F>
4366 class matrix_vector_binary2:
4367 public vector_expression<matrix_vector_binary2<E1, E2, F> > {
4369 typedef E1 expression1_type;
4370 typedef E2 expression2_type;
4371 typedef F functor_type;
4373 typedef typename E1::const_closure_type expression1_closure_type;
4374 typedef typename E2::const_closure_type expression2_closure_type;
4376 typedef matrix_vector_binary2<E1, E2, F> self_type;
4378 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4379 using vector_expression<self_type>::operator ();
4381 static const unsigned complexity = 1;
4382 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
4383 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
4384 typedef typename F::result_type value_type;
4385 typedef value_type const_reference;
4386 typedef const_reference reference;
4387 typedef const self_type const_closure_type;
4388 typedef const_closure_type closure_type;
4389 typedef unknown_storage_tag storage_category;
4391 // Construction and destruction
4393 matrix_vector_binary2 (const expression1_type &e1, const expression2_type &e2):
4394 e1_ (e1), e2_ (e2) {}
4398 size_type size () const {
4399 return e2_.size2 ();
4403 // Expression accessors
4405 const expression1_closure_type &expression1 () const {
4409 const expression2_closure_type &expression2 () const {
4416 const_reference operator () (size_type j) const {
4417 return functor_type::apply (e1_, e2_, j);
4420 // Closure comparison
4422 bool same_closure (const matrix_vector_binary2 &mvb2) const {
4423 return (*this).expression1 ().same_closure (mvb2.expression1 ()) &&
4424 (*this).expression2 ().same_closure (mvb2.expression2 ());
4429 typedef typename E1::const_iterator const_subiterator1_type;
4430 typedef typename E2::const_iterator2 const_subiterator2_type;
4431 typedef const value_type *const_pointer;
4434 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4435 typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
4436 typedef const_iterator iterator;
4438 class const_iterator;
4439 typedef const_iterator iterator;
4444 const_iterator find (size_type j) const {
4445 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4446 const_subiterator2_type it2 (e2_.find2 (0, 0, j));
4447 return const_iterator (*this, it2.index2 ());
4449 return const_iterator (*this, e2_.find2 (0, 0, j));
4454 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4455 class const_iterator:
4456 public container_const_reference<matrix_vector_binary2>,
4457 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
4458 typename E2::const_iterator2::iterator_category>::iterator_category>::template
4459 iterator_base<const_iterator, value_type>::type {
4461 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
4462 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
4463 typedef typename matrix_vector_binary2::difference_type difference_type;
4464 typedef typename matrix_vector_binary2::value_type value_type;
4465 typedef typename matrix_vector_binary2::const_reference reference;
4466 typedef typename matrix_vector_binary2::const_pointer pointer;
4468 // Construction and destruction
4469 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4472 container_const_reference<self_type> (), it2_ (), e1_begin_ (), e1_end_ () {}
4474 const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
4475 container_const_reference<self_type> (mvb), it2_ (it2), e1_begin_ (mvb.expression1 ().begin ()), e1_end_ (mvb.expression1 ().end ()) {}
4479 container_const_reference<self_type> (), it2_ () {}
4481 const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
4482 container_const_reference<self_type> (mvb), it2_ (it2) {}
4486 // Dense random access specialization
4488 value_type dereference (dense_random_access_iterator_tag) const {
4489 const self_type &mvb = (*this) ();
4490 #ifdef BOOST_UBLAS_USE_INDEXING
4491 return mvb (index ());
4492 #elif BOOST_UBLAS_USE_ITERATING
4493 difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
4494 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4495 return functor_type::apply (size, e1_begin_, it2_.begin ());
4497 return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
4500 difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
4501 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
4502 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4503 return functor_type::apply (size, e1_begin_, it2_.begin ());
4505 return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
4508 return mvb (index ());
4512 // Packed bidirectional specialization
4514 value_type dereference (packed_random_access_iterator_tag) const {
4515 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4516 return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end ());
4518 const self_type &mvb = (*this) ();
4519 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4520 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
4521 it2_.begin (), it2_.end ());
4523 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
4524 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
4525 boost::numeric::ublas::end (it2_, iterator2_tag ()));
4530 // Sparse bidirectional specialization
4532 value_type dereference (sparse_bidirectional_iterator_tag) const {
4533 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4534 return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
4536 const self_type &mvb = (*this) ();
4537 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4538 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
4539 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
4541 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
4542 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
4543 boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
4551 const_iterator &operator ++ () {
4556 const_iterator &operator -- () {
4561 const_iterator &operator += (difference_type n) {
4566 const_iterator &operator -= (difference_type n) {
4571 difference_type operator - (const const_iterator &it) const {
4572 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4573 return it2_ - it.it2_;
4578 const_reference operator * () const {
4579 return dereference (iterator_category ());
4582 const_reference operator [] (difference_type n) const {
4583 return *(*this + n);
4588 size_type index () const {
4589 return it2_.index2 ();
4594 const_iterator &operator = (const const_iterator &it) {
4595 container_const_reference<self_type>::assign (&it ());
4597 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4598 e1_begin_ = it.e1_begin_;
4599 e1_end_ = it.e1_end_;
4606 bool operator == (const const_iterator &it) const {
4607 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4608 return it2_ == it.it2_;
4611 bool operator < (const const_iterator &it) const {
4612 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4613 return it2_ < it.it2_;
4617 const_subiterator2_type it2_;
4618 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4619 // Mutable due to assignment
4620 /* const */ const_subiterator1_type e1_begin_;
4621 /* const */ const_subiterator1_type e1_end_;
4627 const_iterator begin () const {
4631 const_iterator cbegin () const {
4635 const_iterator end () const {
4636 return find (size ());
4639 const_iterator cend () const {
4644 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
4647 const_reverse_iterator rbegin () const {
4648 return const_reverse_iterator (end ());
4651 const_reverse_iterator crbegin () const {
4655 const_reverse_iterator rend () const {
4656 return const_reverse_iterator (begin ());
4659 const_reverse_iterator crend () const {
4664 expression1_closure_type e1_;
4665 expression2_closure_type e2_;
4668 template<class T1, class E1, class T2, class E2>
4669 struct matrix_vector_binary2_traits {
4670 typedef unknown_storage_tag storage_category;
4671 typedef column_major_tag orientation_category;
4672 typedef typename promote_traits<T1, T2>::promote_type promote_type;
4673 typedef matrix_vector_binary2<E1, E2, matrix_vector_prod2<E1, E2, promote_type> > expression_type;
4674 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
4675 typedef expression_type result_type;
4677 typedef typename E2::vector_temporary_type result_type;
4681 template<class E1, class E2>
4683 typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4684 typename E2::value_type, E2>::result_type
4685 prod (const vector_expression<E1> &e1,
4686 const matrix_expression<E2> &e2,
4687 unknown_storage_tag,
4689 typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4690 typename E2::value_type, E2>::expression_type expression_type;
4691 return expression_type (e1 (), e2 ());
4695 template<class E1, class E2>
4697 typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4698 typename E2::value_type, E2>::result_type
4699 prod (const vector_expression<E1> &e1,
4700 const matrix_expression<E2> &e2) {
4701 BOOST_STATIC_ASSERT (E1::complexity == 0);
4702 typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4703 typename E2::value_type, E2>::storage_category storage_category;
4704 typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4705 typename E2::value_type, E2>::orientation_category orientation_category;
4706 return prod (e1, e2, storage_category (), orientation_category ());
4709 template<class E1, class E2>
4711 typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4712 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
4713 prec_prod (const vector_expression<E1> &e1,
4714 const matrix_expression<E2> &e2,
4715 unknown_storage_tag,
4717 typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4718 typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
4719 return expression_type (e1 (), e2 ());
4723 template<class E1, class E2>
4725 typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4726 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
4727 prec_prod (const vector_expression<E1> &e1,
4728 const matrix_expression<E2> &e2) {
4729 BOOST_STATIC_ASSERT (E1::complexity == 0);
4730 typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4731 typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
4732 typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4733 typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
4734 return prec_prod (e1, e2, storage_category (), orientation_category ());
4737 template<class V, class E1, class E2>
4740 prod (const vector_expression<E1> &e1,
4741 const matrix_expression<E2> &e2,
4743 return v.assign (prod (e1, e2));
4746 template<class V, class E1, class E2>
4749 prec_prod (const vector_expression<E1> &e1,
4750 const matrix_expression<E2> &e2,
4752 return v.assign (prec_prod (e1, e2));
4755 template<class V, class E1, class E2>
4758 prod (const vector_expression<E1> &e1,
4759 const matrix_expression<E2> &e2) {
4760 return V (prod (e1, e2));
4763 template<class V, class E1, class E2>
4766 prec_prod (const vector_expression<E1> &e1,
4767 const matrix_expression<E2> &e2) {
4768 return V (prec_prod (e1, e2));
4771 template<class E1, class E2, class F>
4772 class matrix_matrix_binary:
4773 public matrix_expression<matrix_matrix_binary<E1, E2, F> > {
4776 typedef E1 expression1_type;
4777 typedef E2 expression2_type;
4779 typedef F functor_type;
4781 typedef typename E1::const_closure_type expression1_closure_type;
4782 typedef typename E2::const_closure_type expression2_closure_type;
4784 typedef matrix_matrix_binary<E1, E2, F> self_type;
4786 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4787 using matrix_expression<self_type>::operator ();
4789 static const unsigned complexity = 1;
4790 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
4791 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
4792 typedef typename F::result_type value_type;
4793 typedef value_type const_reference;
4794 typedef const_reference reference;
4795 typedef const self_type const_closure_type;
4796 typedef const_closure_type closure_type;
4797 typedef unknown_orientation_tag orientation_category;
4798 typedef unknown_storage_tag storage_category;
4800 // Construction and destruction
4802 matrix_matrix_binary (const expression1_type &e1, const expression2_type &e2):
4803 e1_ (e1), e2_ (e2) {}
4807 size_type size1 () const {
4808 return e1_.size1 ();
4811 size_type size2 () const {
4812 return e2_.size2 ();
4816 // Expression accessors
4818 const expression1_closure_type &expression1 () const {
4822 const expression2_closure_type &expression2 () const {
4829 const_reference operator () (size_type i, size_type j) const {
4830 return functor_type::apply (e1_, e2_, i, j);
4833 // Closure comparison
4835 bool same_closure (const matrix_matrix_binary &mmb) const {
4836 return (*this).expression1 ().same_closure (mmb.expression1 ()) &&
4837 (*this).expression2 ().same_closure (mmb.expression2 ());
4842 typedef typename E1::const_iterator1 const_iterator11_type;
4843 typedef typename E1::const_iterator2 const_iterator12_type;
4844 typedef typename E2::const_iterator1 const_iterator21_type;
4845 typedef typename E2::const_iterator2 const_iterator22_type;
4846 typedef const value_type *const_pointer;
4849 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4850 typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
4851 typename const_iterator22_type::iterator_category>::iterator_category iterator_category;
4852 typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
4853 typedef const_iterator1 iterator1;
4854 typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
4855 typedef const_iterator2 iterator2;
4857 class const_iterator1;
4858 typedef const_iterator1 iterator1;
4859 class const_iterator2;
4860 typedef const_iterator2 iterator2;
4862 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
4863 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
4867 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
4868 // FIXME sparse matrix tests fail!
4869 // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
4870 const_iterator11_type it11 (e1_.find1 (0, i, 0));
4871 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4872 return const_iterator1 (*this, it11.index1 (), j);
4874 // FIXME sparse matrix tests fail!
4875 // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
4876 const_iterator22_type it22 (e2_.find2 (0, 0, j));
4877 return const_iterator1 (*this, it11, it22);
4881 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
4882 // FIXME sparse matrix tests fail!
4883 // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
4884 const_iterator22_type it22 (e2_.find2 (0, 0, j));
4885 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4886 return const_iterator2 (*this, i, it22.index2 ());
4888 // FIXME sparse matrix tests fail!
4889 // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
4890 const_iterator11_type it11 (e1_.find1 (0, i, 0));
4891 return const_iterator2 (*this, it11, it22);
4896 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4897 class const_iterator1:
4898 public container_const_reference<matrix_matrix_binary>,
4899 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
4900 typename E2::const_iterator2::iterator_category>::iterator_category>::template
4901 iterator_base<const_iterator1, value_type>::type {
4903 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
4904 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
4905 typedef typename matrix_matrix_binary::difference_type difference_type;
4906 typedef typename matrix_matrix_binary::value_type value_type;
4907 typedef typename matrix_matrix_binary::const_reference reference;
4908 typedef typename matrix_matrix_binary::const_pointer pointer;
4910 typedef const_iterator2 dual_iterator_type;
4911 typedef const_reverse_iterator2 dual_reverse_iterator_type;
4913 // Construction and destruction
4914 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4917 container_const_reference<self_type> (), it1_ (), it2_ (), it2_begin_ (), it2_end_ () {}
4919 const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
4920 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it2_begin_ (it2.begin ()), it2_end_ (it2.end ()) {}
4924 container_const_reference<self_type> (), it1_ (), it2_ () {}
4926 const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
4927 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
4931 // Random access specialization
4933 value_type dereference (dense_random_access_iterator_tag) const {
4934 const self_type &mmb = (*this) ();
4935 #ifdef BOOST_UBLAS_USE_INDEXING
4936 return mmb (index1 (), index2 ());
4937 #elif BOOST_UBLAS_USE_ITERATING
4938 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
4939 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4940 return functor_type::apply (size, it1_.begin (), it2_begin_);
4942 return functor_type::apply (size, it1_.begin (), it2_.begin ());
4945 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
4946 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
4947 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4948 return functor_type::apply (size, it1_.begin (), it2_begin_);
4950 return functor_type::apply (size, it1_.begin (), it2_.begin ());
4953 return mmb (index1 (), index2 ());
4957 // Packed bidirectional specialization
4959 value_type dereference (packed_random_access_iterator_tag) const {
4960 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4961 return functor_type::apply (it1_.begin (), it1_.end (),
4962 it2_begin_, it2_end_, packed_random_access_iterator_tag ());
4964 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4965 return functor_type::apply (it1_.begin (), it1_.end (),
4966 it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
4968 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
4969 boost::numeric::ublas::end (it1_, iterator1_tag ()),
4970 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
4971 boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
4976 // Sparse bidirectional specialization
4978 value_type dereference (sparse_bidirectional_iterator_tag) const {
4979 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4980 return functor_type::apply (it1_.begin (), it1_.end (),
4981 it2_begin_, it2_end_, sparse_bidirectional_iterator_tag ());
4983 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4984 return functor_type::apply (it1_.begin (), it1_.end (),
4985 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
4987 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
4988 boost::numeric::ublas::end (it1_, iterator1_tag ()),
4989 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
4990 boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
4998 const_iterator1 &operator ++ () {
5003 const_iterator1 &operator -- () {
5008 const_iterator1 &operator += (difference_type n) {
5013 const_iterator1 &operator -= (difference_type n) {
5018 difference_type operator - (const const_iterator1 &it) const {
5019 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5020 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
5021 return it1_ - it.it1_;
5026 const_reference operator * () const {
5027 return dereference (iterator_category ());
5030 const_reference operator [] (difference_type n) const {
5031 return *(*this + n);
5034 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5036 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5037 typename self_type::
5039 const_iterator2 begin () const {
5040 return (*this) ().find2 (1, index1 (), 0);
5043 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5044 typename self_type::
5046 const_iterator2 cbegin () const {
5050 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5051 typename self_type::
5053 const_iterator2 end () const {
5054 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
5057 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5058 typename self_type::
5060 const_iterator2 cend () const {
5064 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5065 typename self_type::
5067 const_reverse_iterator2 rbegin () const {
5068 return const_reverse_iterator2 (end ());
5071 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5072 typename self_type::
5074 const_reverse_iterator2 crbegin () const {
5078 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5079 typename self_type::
5081 const_reverse_iterator2 rend () const {
5082 return const_reverse_iterator2 (begin ());
5085 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5086 typename self_type::
5088 const_reverse_iterator2 crend () const {
5095 size_type index1 () const {
5096 return it1_.index1 ();
5099 size_type index2 () const {
5100 return it2_.index2 ();
5105 const_iterator1 &operator = (const const_iterator1 &it) {
5106 container_const_reference<self_type>::assign (&it ());
5109 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5110 it2_begin_ = it.it2_begin_;
5111 it2_end_ = it.it2_end_;
5118 bool operator == (const const_iterator1 &it) const {
5119 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5120 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
5121 return it1_ == it.it1_;
5124 bool operator < (const const_iterator1 &it) const {
5125 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5126 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
5127 return it1_ < it.it1_;
5131 const_iterator11_type it1_;
5132 // Mutable due to assignment
5133 /* const */ const_iterator22_type it2_;
5134 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5135 /* const */ const_iterator21_type it2_begin_;
5136 /* const */ const_iterator21_type it2_end_;
5142 const_iterator1 begin1 () const {
5143 return find1 (0, 0, 0);
5146 const_iterator1 cbegin1 () const {
5150 const_iterator1 end1 () const {
5151 return find1 (0, size1 (), 0);
5154 const_iterator1 cend1 () const {
5158 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
5159 class const_iterator2:
5160 public container_const_reference<matrix_matrix_binary>,
5161 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
5162 typename E2::const_iterator2::iterator_category>::iterator_category>::template
5163 iterator_base<const_iterator2, value_type>::type {
5165 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
5166 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
5167 typedef typename matrix_matrix_binary::difference_type difference_type;
5168 typedef typename matrix_matrix_binary::value_type value_type;
5169 typedef typename matrix_matrix_binary::const_reference reference;
5170 typedef typename matrix_matrix_binary::const_pointer pointer;
5172 typedef const_iterator1 dual_iterator_type;
5173 typedef const_reverse_iterator1 dual_reverse_iterator_type;
5175 // Construction and destruction
5176 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5179 container_const_reference<self_type> (), it1_ (), it2_ (), it1_begin_ (), it1_end_ () {}
5181 const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
5182 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it1_begin_ (it1.begin ()), it1_end_ (it1.end ()) {}
5186 container_const_reference<self_type> (), it1_ (), it2_ () {}
5188 const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
5189 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
5193 // Random access specialization
5195 value_type dereference (dense_random_access_iterator_tag) const {
5196 const self_type &mmb = (*this) ();
5197 #ifdef BOOST_UBLAS_USE_INDEXING
5198 return mmb (index1 (), index2 ());
5199 #elif BOOST_UBLAS_USE_ITERATING
5200 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
5201 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5202 return functor_type::apply (size, it1_begin_, it2_.begin ());
5204 return functor_type::apply (size, it1_.begin (), it2_.begin ());
5207 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
5208 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
5209 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5210 return functor_type::apply (size, it1_begin_, it2_.begin ());
5212 return functor_type::apply (size, it1_.begin (), it2_.begin ());
5215 return mmb (index1 (), index2 ());
5219 // Packed bidirectional specialization
5221 value_type dereference (packed_random_access_iterator_tag) const {
5222 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5223 return functor_type::apply (it1_begin_, it1_end_,
5224 it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
5226 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5227 return functor_type::apply (it1_.begin (), it1_.end (),
5228 it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
5230 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
5231 boost::numeric::ublas::end (it1_, iterator1_tag ()),
5232 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
5233 boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
5238 // Sparse bidirectional specialization
5240 value_type dereference (sparse_bidirectional_iterator_tag) const {
5241 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5242 return functor_type::apply (it1_begin_, it1_end_,
5243 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
5245 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5246 return functor_type::apply (it1_.begin (), it1_.end (),
5247 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
5249 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
5250 boost::numeric::ublas::end (it1_, iterator1_tag ()),
5251 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
5252 boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
5260 const_iterator2 &operator ++ () {
5265 const_iterator2 &operator -- () {
5270 const_iterator2 &operator += (difference_type n) {
5275 const_iterator2 &operator -= (difference_type n) {
5280 difference_type operator - (const const_iterator2 &it) const {
5281 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5282 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5283 return it2_ - it.it2_;
5288 const_reference operator * () const {
5289 return dereference (iterator_category ());
5292 const_reference operator [] (difference_type n) const {
5293 return *(*this + n);
5296 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5298 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5299 typename self_type::
5301 const_iterator1 begin () const {
5302 return (*this) ().find1 (1, 0, index2 ());
5305 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5306 typename self_type::
5308 const_iterator1 cbegin () const {
5312 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5313 typename self_type::
5315 const_iterator1 end () const {
5316 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
5319 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5320 typename self_type::
5322 const_iterator1 cend () const {
5326 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5327 typename self_type::
5329 const_reverse_iterator1 rbegin () const {
5330 return const_reverse_iterator1 (end ());
5333 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5334 typename self_type::
5336 const_reverse_iterator1 crbegin () const {
5340 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5341 typename self_type::
5343 const_reverse_iterator1 rend () const {
5344 return const_reverse_iterator1 (begin ());
5347 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5348 typename self_type::
5350 const_reverse_iterator1 crend () const {
5357 size_type index1 () const {
5358 return it1_.index1 ();
5361 size_type index2 () const {
5362 return it2_.index2 ();
5367 const_iterator2 &operator = (const const_iterator2 &it) {
5368 container_const_reference<self_type>::assign (&it ());
5371 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5372 it1_begin_ = it.it1_begin_;
5373 it1_end_ = it.it1_end_;
5380 bool operator == (const const_iterator2 &it) const {
5381 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5382 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5383 return it2_ == it.it2_;
5386 bool operator < (const const_iterator2 &it) const {
5387 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5388 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5389 return it2_ < it.it2_;
5393 // Mutable due to assignment
5394 /* const */ const_iterator11_type it1_;
5395 const_iterator22_type it2_;
5396 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5397 /* const */ const_iterator12_type it1_begin_;
5398 /* const */ const_iterator12_type it1_end_;
5404 const_iterator2 begin2 () const {
5405 return find2 (0, 0, 0);
5408 const_iterator2 cbegin2 () const {
5412 const_iterator2 end2 () const {
5413 return find2 (0, 0, size2 ());
5416 const_iterator2 cend2 () const {
5420 // Reverse iterators
5423 const_reverse_iterator1 rbegin1 () const {
5424 return const_reverse_iterator1 (end1 ());
5427 const_reverse_iterator1 crbegin1 () const {
5431 const_reverse_iterator1 rend1 () const {
5432 return const_reverse_iterator1 (begin1 ());
5435 const_reverse_iterator1 crend1 () const {
5440 const_reverse_iterator2 rbegin2 () const {
5441 return const_reverse_iterator2 (end2 ());
5444 const_reverse_iterator2 crbegin2 () const {
5448 const_reverse_iterator2 rend2 () const {
5449 return const_reverse_iterator2 (begin2 ());
5452 const_reverse_iterator2 crend2 () const {
5457 expression1_closure_type e1_;
5458 expression2_closure_type e2_;
5461 template<class T1, class E1, class T2, class E2>
5462 struct matrix_matrix_binary_traits {
5463 typedef unknown_storage_tag storage_category;
5464 typedef unknown_orientation_tag orientation_category;
5465 typedef typename promote_traits<T1, T2>::promote_type promote_type;
5466 typedef matrix_matrix_binary<E1, E2, matrix_matrix_prod<E1, E2, promote_type> > expression_type;
5467 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
5468 typedef expression_type result_type;
5470 typedef typename E1::matrix_temporary_type result_type;
5474 template<class E1, class E2>
5476 typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5477 typename E2::value_type, E2>::result_type
5478 prod (const matrix_expression<E1> &e1,
5479 const matrix_expression<E2> &e2,
5480 unknown_storage_tag,
5481 unknown_orientation_tag) {
5482 typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5483 typename E2::value_type, E2>::expression_type expression_type;
5484 return expression_type (e1 (), e2 ());
5488 template<class E1, class E2>
5490 typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5491 typename E2::value_type, E2>::result_type
5492 prod (const matrix_expression<E1> &e1,
5493 const matrix_expression<E2> &e2) {
5494 BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
5495 typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5496 typename E2::value_type, E2>::storage_category storage_category;
5497 typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5498 typename E2::value_type, E2>::orientation_category orientation_category;
5499 return prod (e1, e2, storage_category (), orientation_category ());
5502 template<class E1, class E2>
5504 typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5505 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
5506 prec_prod (const matrix_expression<E1> &e1,
5507 const matrix_expression<E2> &e2,
5508 unknown_storage_tag,
5509 unknown_orientation_tag) {
5510 typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5511 typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
5512 return expression_type (e1 (), e2 ());
5516 template<class E1, class E2>
5518 typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5519 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
5520 prec_prod (const matrix_expression<E1> &e1,
5521 const matrix_expression<E2> &e2) {
5522 BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
5523 typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5524 typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
5525 typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5526 typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
5527 return prec_prod (e1, e2, storage_category (), orientation_category ());
5530 template<class M, class E1, class E2>
5533 prod (const matrix_expression<E1> &e1,
5534 const matrix_expression<E2> &e2,
5536 return m.assign (prod (e1, e2));
5539 template<class M, class E1, class E2>
5542 prec_prod (const matrix_expression<E1> &e1,
5543 const matrix_expression<E2> &e2,
5545 return m.assign (prec_prod (e1, e2));
5548 template<class M, class E1, class E2>
5551 prod (const matrix_expression<E1> &e1,
5552 const matrix_expression<E2> &e2) {
5553 return M (prod (e1, e2));
5556 template<class M, class E1, class E2>
5559 prec_prod (const matrix_expression<E1> &e1,
5560 const matrix_expression<E2> &e2) {
5561 return M (prec_prod (e1, e2));
5564 template<class E, class F>
5565 class matrix_scalar_unary:
5566 public scalar_expression<matrix_scalar_unary<E, F> > {
5568 typedef E expression_type;
5569 typedef F functor_type;
5570 typedef typename F::result_type value_type;
5571 typedef typename E::const_closure_type expression_closure_type;
5573 // Construction and destruction
5575 explicit matrix_scalar_unary (const expression_type &e):
5579 // Expression accessors
5581 const expression_closure_type &expression () const {
5587 operator value_type () const {
5588 return functor_type::apply (e_);
5592 expression_closure_type e_;
5595 template<class E, class F>
5596 struct matrix_scalar_unary_traits {
5597 typedef matrix_scalar_unary<E, F> expression_type;
5598 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
5599 typedef expression_type result_type;
5601 typedef typename F::result_type result_type;
5607 typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::result_type
5608 norm_1 (const matrix_expression<E> &e) {
5609 typedef typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::expression_type expression_type;
5610 return expression_type (e ());
5615 typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::result_type
5616 norm_frobenius (const matrix_expression<E> &e) {
5617 typedef typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::expression_type expression_type;
5618 return expression_type (e ());
5623 typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::result_type
5624 norm_inf (const matrix_expression<E> &e) {
5625 typedef typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::expression_type expression_type;
5626 return expression_type (e ());