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);
91 #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
93 const_reference operator () (size_type i) const {
94 return expression () (i);
97 reference operator () (size_type i) {
98 return expression () (i);
102 reference operator () (size_type i) const {
103 return expression () (i);
110 matrix_reference &operator = (const matrix_reference &m) {
111 expression ().operator = (m);
116 matrix_reference &operator = (const matrix_expression<AE> &ae) {
117 expression ().operator = (ae);
122 matrix_reference &assign (const matrix_expression<AE> &ae) {
123 expression ().assign (ae);
128 matrix_reference &operator += (const matrix_expression<AE> &ae) {
129 expression ().operator += (ae);
134 matrix_reference &plus_assign (const matrix_expression<AE> &ae) {
135 expression ().plus_assign (ae);
140 matrix_reference &operator -= (const matrix_expression<AE> &ae) {
141 expression ().operator -= (ae);
146 matrix_reference &minus_assign (const matrix_expression<AE> &ae) {
147 expression ().minus_assign (ae);
152 matrix_reference &operator *= (const AT &at) {
153 expression ().operator *= (at);
158 matrix_reference &operator /= (const AT &at) {
159 expression ().operator /= (at);
165 void swap (matrix_reference &m) {
166 expression ().swap (m.expression ());
169 // Closure comparison
171 bool same_closure (const matrix_reference &mr) const {
172 return &(*this).e_ == &mr.e_;
176 typedef typename E::const_iterator1 const_iterator1;
177 typedef typename boost::mpl::if_<boost::is_const<E>,
178 typename E::const_iterator1,
179 typename E::iterator1>::type iterator1;
180 typedef typename E::const_iterator2 const_iterator2;
181 typedef typename boost::mpl::if_<boost::is_const<E>,
182 typename E::const_iterator2,
183 typename E::iterator2>::type iterator2;
187 const_iterator1 find1 (int rank, size_type i, size_type j) const {
188 return expression ().find1 (rank, i, j);
191 iterator1 find1 (int rank, size_type i, size_type j) {
192 return expression ().find1 (rank, i, j);
195 const_iterator2 find2 (int rank, size_type i, size_type j) const {
196 return expression ().find2 (rank, i, j);
199 iterator2 find2 (int rank, size_type i, size_type j) {
200 return expression ().find2 (rank, i, j);
203 // Iterators are the iterators of the referenced expression.
206 const_iterator1 begin1 () const {
207 return expression ().begin1 ();
210 const_iterator1 cbegin1 () const {
214 const_iterator1 end1 () const {
215 return expression ().end1 ();
218 const_iterator1 cend1 () const {
223 iterator1 begin1 () {
224 return expression ().begin1 ();
228 return expression ().end1 ();
232 const_iterator2 begin2 () const {
233 return expression ().begin2 ();
236 const_iterator2 cbegin2 () const {
240 const_iterator2 end2 () const {
241 return expression ().end2 ();
244 const_iterator2 cend2 () const {
249 iterator2 begin2 () {
250 return expression ().begin2 ();
254 return expression ().end2 ();
258 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
259 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
262 const_reverse_iterator1 rbegin1 () const {
263 return const_reverse_iterator1 (end1 ());
266 const_reverse_iterator1 crbegin1 () const {
270 const_reverse_iterator1 rend1 () const {
271 return const_reverse_iterator1 (begin1 ());
274 const_reverse_iterator1 crend1 () const {
279 reverse_iterator1 rbegin1 () {
280 return reverse_iterator1 (end1 ());
283 reverse_iterator1 rend1 () {
284 return reverse_iterator1 (begin1 ());
287 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
288 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
291 const_reverse_iterator2 rbegin2 () const {
292 return const_reverse_iterator2 (end2 ());
295 const_reverse_iterator2 crbegin2 () const {
299 const_reverse_iterator2 rend2 () const {
300 return const_reverse_iterator2 (begin2 ());
303 const_reverse_iterator2 crend2 () const {
308 reverse_iterator2 rbegin2 () {
309 return reverse_iterator2 (end2 ());
312 reverse_iterator2 rend2 () {
313 return reverse_iterator2 (begin2 ());
321 template<class E1, class E2, class F>
322 class vector_matrix_binary:
323 public matrix_expression<vector_matrix_binary<E1, E2, F> > {
325 typedef E1 expression1_type;
326 typedef E2 expression2_type;
328 typedef typename E1::const_closure_type expression1_closure_type;
329 typedef typename E2::const_closure_type expression2_closure_type;
331 typedef vector_matrix_binary<E1, E2, F> self_type;
333 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
334 using matrix_expression<self_type>::operator ();
336 typedef F functor_type;
337 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
338 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
339 typedef typename F::result_type value_type;
340 typedef value_type const_reference;
341 typedef const_reference reference;
342 typedef const self_type const_closure_type;
343 typedef const_closure_type closure_type;
344 typedef unknown_orientation_tag orientation_category;
345 typedef unknown_storage_tag storage_category;
347 // Construction and destruction
349 vector_matrix_binary (const expression1_type &e1, const expression2_type &e2):
350 e1_ (e1), e2_ (e2) {}
354 size_type size1 () const {
358 size_type size2 () const {
363 // Expression accessors
365 const expression1_closure_type &expression1 () const {
369 const expression2_closure_type &expression2 () const {
376 const_reference operator () (size_type i, size_type j) const {
377 return functor_type::apply (e1_ (i), e2_ (j));
382 // Closure comparison
384 bool same_closure (const vector_matrix_binary &vmb) const {
385 return (*this).expression1 ().same_closure (vmb.expression1 ()) &&
386 (*this).expression2 ().same_closure (vmb.expression2 ());
391 typedef typename E1::const_iterator const_subiterator1_type;
392 typedef typename E2::const_iterator const_subiterator2_type;
393 typedef const value_type *const_pointer;
396 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
397 typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
398 typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
399 typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
400 typedef const_iterator1 iterator1;
401 typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
402 typedef const_iterator2 iterator2;
404 class const_iterator1;
405 typedef const_iterator1 iterator1;
406 class const_iterator2;
407 typedef const_iterator2 iterator2;
409 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
410 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
414 const_iterator1 find1 (int rank, size_type i, size_type j) const {
415 const_subiterator1_type it1 (e1_.find (i));
416 const_subiterator1_type it1_end (e1_.find (size1 ()));
417 const_subiterator2_type it2 (e2_.find (j));
418 const_subiterator2_type it2_end (e2_.find (size2 ()));
419 if (it2 == it2_end || (rank == 1 && (it2.index () != j || *it2 == typename E2::value_type/*zero*/()))) {
423 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
424 return const_iterator1 (*this, it1.index (), it2.index ());
426 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
427 return const_iterator1 (*this, it1, it2, it2 != it2_end ? *it2 : typename E2::value_type/*zero*/());
429 return const_iterator1 (*this, it1, it2);
434 const_iterator2 find2 (int rank, size_type i, size_type j) const {
435 const_subiterator2_type it2 (e2_.find (j));
436 const_subiterator2_type it2_end (e2_.find (size2 ()));
437 const_subiterator1_type it1 (e1_.find (i));
438 const_subiterator1_type it1_end (e1_.find (size1 ()));
439 if (it1 == it1_end || (rank == 1 && (it1.index () != i || *it1 == typename E1::value_type/*zero*/()))) {
443 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
444 return const_iterator2 (*this, it1.index (), it2.index ());
446 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
447 return const_iterator2 (*this, it1, it2, it1 != it1_end ? *it1 : typename E1::value_type/*zero*/());
449 return const_iterator2 (*this, it1, it2);
454 // Iterators enhance the iterators of the referenced expressions
455 // with the binary functor.
457 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
458 class const_iterator1:
459 public container_const_reference<vector_matrix_binary>,
460 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
461 typename E2::const_iterator::iterator_category>::iterator_category>::template
462 iterator_base<const_iterator1, value_type>::type {
464 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
465 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
466 typedef typename vector_matrix_binary::difference_type difference_type;
467 typedef typename vector_matrix_binary::value_type value_type;
468 typedef typename vector_matrix_binary::const_reference reference;
469 typedef typename vector_matrix_binary::const_pointer pointer;
471 typedef const_iterator2 dual_iterator_type;
472 typedef const_reverse_iterator2 dual_reverse_iterator_type;
474 // Construction and destruction
475 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
478 container_const_reference<self_type> (), it1_ (), it2_ (), t2_ () {}
480 const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t2):
481 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t2_ (t2) {}
485 container_const_reference<self_type> (), it1_ (), it2_ () {}
487 const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
488 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
493 const_iterator1 &operator ++ () {
498 const_iterator1 &operator -- () {
503 const_iterator1 &operator += (difference_type n) {
508 const_iterator1 &operator -= (difference_type n) {
513 difference_type operator - (const const_iterator1 &it) const {
514 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
515 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
516 return it1_ - it.it1_;
521 const_reference operator * () const {
522 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
523 return functor_type::apply (*it1_, t2_);
525 return functor_type::apply (*it1_, *it2_);
529 const_reference operator [] (difference_type n) const {
533 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
535 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
538 const_iterator2 begin () const {
539 return (*this) ().find2 (1, index1 (), 0);
542 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
545 const_iterator2 cbegin () const {
549 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
552 const_iterator2 end () const {
553 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
556 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
559 const_iterator2 cend () const {
563 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
566 const_reverse_iterator2 rbegin () const {
567 return const_reverse_iterator2 (end ());
570 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
573 const_reverse_iterator2 crbegin () const {
577 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
580 const_reverse_iterator2 rend () const {
581 return const_reverse_iterator2 (begin ());
584 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
587 const_reverse_iterator2 crend () const {
594 size_type index1 () const {
595 return it1_.index ();
598 size_type index2 () const {
599 return it2_.index ();
604 const_iterator1 &operator = (const const_iterator1 &it) {
605 container_const_reference<self_type>::assign (&it ());
608 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
616 bool operator == (const const_iterator1 &it) const {
617 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
618 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
619 return it1_ == it.it1_;
622 bool operator < (const const_iterator1 &it) const {
623 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
624 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
625 return it1_ < it.it1_;
629 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
630 const_subiterator1_type it1_;
631 // Mutable due to assignment
632 /* const */ const_subiterator2_type it2_;
635 const_subiterator1_type it1_;
636 const_subiterator2_type it2_;
642 const_iterator1 begin1 () const {
643 return find1 (0, 0, 0);
646 const_iterator1 cbegin1 () const {
650 const_iterator1 end1 () const {
651 return find1 (0, size1 (), 0);
654 const_iterator1 cend1 () const {
658 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
659 class const_iterator2:
660 public container_const_reference<vector_matrix_binary>,
661 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
662 typename E2::const_iterator::iterator_category>::iterator_category>::template
663 iterator_base<const_iterator2, value_type>::type {
665 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
666 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
667 typedef typename vector_matrix_binary::difference_type difference_type;
668 typedef typename vector_matrix_binary::value_type value_type;
669 typedef typename vector_matrix_binary::const_reference reference;
670 typedef typename vector_matrix_binary::const_pointer pointer;
672 typedef const_iterator1 dual_iterator_type;
673 typedef const_reverse_iterator1 dual_reverse_iterator_type;
675 // Construction and destruction
676 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
679 container_const_reference<self_type> (), it1_ (), it2_ (), t1_ () {}
681 const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t1):
682 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t1_ (t1) {}
686 container_const_reference<self_type> (), it1_ (), it2_ () {}
688 const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
689 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
694 const_iterator2 &operator ++ () {
699 const_iterator2 &operator -- () {
704 const_iterator2 &operator += (difference_type n) {
709 const_iterator2 &operator -= (difference_type n) {
714 difference_type operator - (const const_iterator2 &it) const {
715 BOOST_UBLAS_CHECK ((*this) ().same_closure(it ()), external_logic ());
716 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
717 return it2_ - it.it2_;
722 const_reference operator * () const {
723 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
724 return functor_type::apply (t1_, *it2_);
726 return functor_type::apply (*it1_, *it2_);
730 const_reference operator [] (difference_type n) const {
734 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
736 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
739 const_iterator1 begin () const {
740 return (*this) ().find1 (1, 0, index2 ());
743 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
746 const_iterator1 cbegin () const {
750 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
753 const_iterator1 end () const {
754 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
757 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
760 const_iterator1 cend () const {
764 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
767 const_reverse_iterator1 rbegin () const {
768 return const_reverse_iterator1 (end ());
771 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
774 const_reverse_iterator1 crbegin () const {
778 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
781 const_reverse_iterator1 rend () const {
782 return const_reverse_iterator1 (begin ());
785 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
788 const_reverse_iterator1 crend () const {
795 size_type index1 () const {
796 return it1_.index ();
799 size_type index2 () const {
800 return it2_.index ();
805 const_iterator2 &operator = (const const_iterator2 &it) {
806 container_const_reference<self_type>::assign (&it ());
809 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
817 bool operator == (const const_iterator2 &it) const {
818 BOOST_UBLAS_CHECK ((*this) ().same_closure( it ()), external_logic ());
819 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
820 return it2_ == it.it2_;
823 bool operator < (const const_iterator2 &it) const {
824 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
825 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
826 return it2_ < it.it2_;
830 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
831 // Mutable due to assignment
832 /* const */ const_subiterator1_type it1_;
833 const_subiterator2_type it2_;
836 const_subiterator1_type it1_;
837 const_subiterator2_type it2_;
843 const_iterator2 begin2 () const {
844 return find2 (0, 0, 0);
847 const_iterator2 cbegin2 () const {
851 const_iterator2 end2 () const {
852 return find2 (0, 0, size2 ());
855 const_iterator2 cend2 () const {
862 const_reverse_iterator1 rbegin1 () const {
863 return const_reverse_iterator1 (end1 ());
866 const_reverse_iterator1 crbegin1 () const {
870 const_reverse_iterator1 rend1 () const {
871 return const_reverse_iterator1 (begin1 ());
874 const_reverse_iterator1 crend1 () const {
878 const_reverse_iterator2 rbegin2 () const {
879 return const_reverse_iterator2 (end2 ());
882 const_reverse_iterator2 crbegin2 () const {
886 const_reverse_iterator2 rend2 () const {
887 return const_reverse_iterator2 (begin2 ());
890 const_reverse_iterator2 crend2 () const {
895 expression1_closure_type e1_;
896 expression2_closure_type e2_;
899 template<class E1, class E2, class F>
900 struct vector_matrix_binary_traits {
901 typedef vector_matrix_binary<E1, E2, F> expression_type;
902 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
903 typedef expression_type result_type;
905 // ISSUE matrix is arbitary temporary type
906 typedef matrix<typename F::value_type> result_type;
910 // (outer_prod (v1, v2)) [i] [j] = v1 [i] * v2 [j]
911 template<class E1, class E2>
913 typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::result_type
914 outer_prod (const vector_expression<E1> &e1,
915 const vector_expression<E2> &e2) {
916 BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
917 typedef typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::expression_type expression_type;
918 return expression_type (e1 (), e2 ());
921 template<class E, class F>
923 public matrix_expression<matrix_unary1<E, F> > {
925 typedef E expression_type;
926 typedef F functor_type;
928 typedef typename E::const_closure_type expression_closure_type;
930 typedef matrix_unary1<E, F> self_type;
932 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
933 using matrix_expression<self_type>::operator ();
935 typedef typename E::size_type size_type;
936 typedef typename E::difference_type difference_type;
937 typedef typename F::result_type value_type;
938 typedef value_type const_reference;
939 typedef const_reference reference;
940 typedef const self_type const_closure_type;
941 typedef const_closure_type closure_type;
942 typedef typename E::orientation_category orientation_category;
943 typedef unknown_storage_tag storage_category;
945 // Construction and destruction
947 explicit matrix_unary1 (const expression_type &e):
952 size_type size1 () const {
956 size_type size2 () const {
961 // Expression accessors
963 const expression_closure_type &expression () const {
970 const_reference operator () (size_type i, size_type j) const {
971 return functor_type::apply (e_ (i, j));
976 const_reference operator () (size_type i) const {
977 return functor_type::apply (e_ (i));
981 // Closure comparison
983 bool same_closure (const matrix_unary1 &mu1) const {
984 return (*this).expression ().same_closure (mu1.expression ());
989 typedef typename E::const_iterator1 const_subiterator1_type;
990 typedef typename E::const_iterator2 const_subiterator2_type;
991 typedef const value_type *const_pointer;
994 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
995 typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
996 typedef const_iterator1 iterator1;
997 typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
998 typedef const_iterator2 iterator2;
1000 class const_iterator1;
1001 typedef const_iterator1 iterator1;
1002 class const_iterator2;
1003 typedef const_iterator2 iterator2;
1005 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1006 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1010 const_iterator1 find1 (int rank, size_type i, size_type j) const {
1011 const_subiterator1_type it1 (e_.find1 (rank, i, j));
1012 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1013 return const_iterator1 (*this, it1.index1 (), it1.index2 ());
1015 return const_iterator1 (*this, it1);
1019 const_iterator2 find2 (int rank, size_type i, size_type j) const {
1020 const_subiterator2_type it2 (e_.find2 (rank, i, j));
1021 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1022 return const_iterator2 (*this, it2.index1 (), it2.index2 ());
1024 return const_iterator2 (*this, it2);
1028 // Iterators enhance the iterators of the referenced expression
1029 // with the unary functor.
1031 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1032 class const_iterator1:
1033 public container_const_reference<matrix_unary1>,
1034 public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
1035 iterator_base<const_iterator1, value_type>::type {
1037 typedef typename E::const_iterator1::iterator_category iterator_category;
1038 typedef typename matrix_unary1::difference_type difference_type;
1039 typedef typename matrix_unary1::value_type value_type;
1040 typedef typename matrix_unary1::const_reference reference;
1041 typedef typename matrix_unary1::const_pointer pointer;
1043 typedef const_iterator2 dual_iterator_type;
1044 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1046 // Construction and destruction
1049 container_const_reference<self_type> (), it_ () {}
1051 const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
1052 container_const_reference<self_type> (mu), it_ (it) {}
1056 const_iterator1 &operator ++ () {
1061 const_iterator1 &operator -- () {
1066 const_iterator1 &operator += (difference_type n) {
1071 const_iterator1 &operator -= (difference_type n) {
1076 difference_type operator - (const const_iterator1 &it) const {
1077 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1078 return it_ - it.it_;
1083 const_reference operator * () const {
1084 return functor_type::apply (*it_);
1087 const_reference operator [] (difference_type n) const {
1088 return *(*this + n);
1091 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1093 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1094 typename self_type::
1096 const_iterator2 begin () const {
1097 return (*this) ().find2 (1, index1 (), 0);
1100 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1101 typename self_type::
1103 const_iterator2 cbegin () const {
1107 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1108 typename self_type::
1110 const_iterator2 end () const {
1111 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1114 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1115 typename self_type::
1117 const_iterator2 cend () const {
1121 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1122 typename self_type::
1124 const_reverse_iterator2 rbegin () const {
1125 return const_reverse_iterator2 (end ());
1128 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1129 typename self_type::
1131 const_reverse_iterator2 crbegin () const {
1135 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1136 typename self_type::
1138 const_reverse_iterator2 rend () const {
1139 return const_reverse_iterator2 (begin ());
1142 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1143 typename self_type::
1145 const_reverse_iterator2 crend () const {
1152 size_type index1 () const {
1153 return it_.index1 ();
1156 size_type index2 () const {
1157 return it_.index2 ();
1162 const_iterator1 &operator = (const const_iterator1 &it) {
1163 container_const_reference<self_type>::assign (&it ());
1170 bool operator == (const const_iterator1 &it) const {
1171 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1172 return it_ == it.it_;
1175 bool operator < (const const_iterator1 &it) const {
1176 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1177 return it_ < it.it_;
1181 const_subiterator1_type it_;
1186 const_iterator1 begin1 () const {
1187 return find1 (0, 0, 0);
1190 const_iterator1 cbegin1 () const {
1194 const_iterator1 end1 () const {
1195 return find1 (0, size1 (), 0);
1198 const_iterator1 cend1 () const {
1202 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1203 class const_iterator2:
1204 public container_const_reference<matrix_unary1>,
1205 public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
1206 iterator_base<const_iterator2, value_type>::type {
1208 typedef typename E::const_iterator2::iterator_category iterator_category;
1209 typedef typename matrix_unary1::difference_type difference_type;
1210 typedef typename matrix_unary1::value_type value_type;
1211 typedef typename matrix_unary1::const_reference reference;
1212 typedef typename matrix_unary1::const_pointer pointer;
1214 typedef const_iterator1 dual_iterator_type;
1215 typedef const_reverse_iterator1 dual_reverse_iterator_type;
1217 // Construction and destruction
1220 container_const_reference<self_type> (), it_ () {}
1222 const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
1223 container_const_reference<self_type> (mu), it_ (it) {}
1227 const_iterator2 &operator ++ () {
1232 const_iterator2 &operator -- () {
1237 const_iterator2 &operator += (difference_type n) {
1242 const_iterator2 &operator -= (difference_type n) {
1247 difference_type operator - (const const_iterator2 &it) const {
1248 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1249 return it_ - it.it_;
1254 const_reference operator * () const {
1255 return functor_type::apply (*it_);
1258 const_reference operator [] (difference_type n) const {
1259 return *(*this + n);
1262 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1264 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1265 typename self_type::
1267 const_iterator1 begin () const {
1268 return (*this) ().find1 (1, 0, index2 ());
1271 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1272 typename self_type::
1274 const_iterator1 cbegin () const {
1278 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1279 typename self_type::
1281 const_iterator1 end () const {
1282 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1285 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1286 typename self_type::
1288 const_iterator1 cend () const {
1292 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1293 typename self_type::
1295 const_reverse_iterator1 rbegin () const {
1296 return const_reverse_iterator1 (end ());
1299 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1300 typename self_type::
1302 const_reverse_iterator1 crbegin () const {
1306 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1307 typename self_type::
1309 const_reverse_iterator1 rend () const {
1310 return const_reverse_iterator1 (begin ());
1313 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1314 typename self_type::
1316 const_reverse_iterator1 crend () const {
1323 size_type index1 () const {
1324 return it_.index1 ();
1327 size_type index2 () const {
1328 return it_.index2 ();
1333 const_iterator2 &operator = (const const_iterator2 &it) {
1334 container_const_reference<self_type>::assign (&it ());
1341 bool operator == (const const_iterator2 &it) const {
1342 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1343 return it_ == it.it_;
1346 bool operator < (const const_iterator2 &it) const {
1347 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1348 return it_ < it.it_;
1352 const_subiterator2_type it_;
1357 const_iterator2 begin2 () const {
1358 return find2 (0, 0, 0);
1361 const_iterator2 cbegin2 () const {
1365 const_iterator2 end2 () const {
1366 return find2 (0, 0, size2 ());
1369 const_iterator2 cend2 () const {
1373 // Reverse iterators
1376 const_reverse_iterator1 rbegin1 () const {
1377 return const_reverse_iterator1 (end1 ());
1380 const_reverse_iterator1 crbegin1 () const {
1384 const_reverse_iterator1 rend1 () const {
1385 return const_reverse_iterator1 (begin1 ());
1388 const_reverse_iterator1 crend1 () const {
1393 const_reverse_iterator2 rbegin2 () const {
1394 return const_reverse_iterator2 (end2 ());
1397 const_reverse_iterator2 crbegin2 () const {
1401 const_reverse_iterator2 rend2 () const {
1402 return const_reverse_iterator2 (begin2 ());
1405 const_reverse_iterator2 crend2 () const {
1410 expression_closure_type e_;
1413 template<class E, class F>
1414 struct matrix_unary1_traits {
1415 typedef matrix_unary1<E, F> expression_type;
1416 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1417 typedef expression_type result_type;
1419 typedef typename E::matrix_temporary_type result_type;
1423 // (- m) [i] [j] = - m [i] [j]
1426 typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::result_type
1427 operator - (const matrix_expression<E> &e) {
1428 typedef typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
1429 return expression_type (e ());
1432 // (conj m) [i] [j] = conj (m [i] [j])
1435 typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::result_type
1436 conj (const matrix_expression<E> &e) {
1437 typedef typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
1438 return expression_type (e ());
1441 // (real m) [i] [j] = real (m [i] [j])
1444 typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::result_type
1445 real (const matrix_expression<E> &e) {
1446 typedef typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
1447 return expression_type (e ());
1450 // (imag m) [i] [j] = imag (m [i] [j])
1453 typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::result_type
1454 imag (const matrix_expression<E> &e) {
1455 typedef typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
1456 return expression_type (e ());
1459 template<class E, class F>
1460 class matrix_unary2:
1461 public matrix_expression<matrix_unary2<E, F> > {
1463 typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
1465 const E>::type expression_type;
1466 typedef F functor_type;
1468 typedef typename boost::mpl::if_<boost::is_const<expression_type>,
1469 typename E::const_closure_type,
1470 typename E::closure_type>::type expression_closure_type;
1472 typedef matrix_unary2<E, F> self_type;
1474 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1475 using matrix_expression<self_type>::operator ();
1477 typedef typename E::size_type size_type;
1478 typedef typename E::difference_type difference_type;
1479 typedef typename F::result_type value_type;
1480 typedef value_type const_reference;
1481 typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
1482 typename E::reference,
1483 value_type>::type reference;
1485 typedef const self_type const_closure_type;
1486 typedef self_type closure_type;
1487 typedef typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
1490 typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
1493 typename E::orientation_category>::type>::type orientation_category;
1494 typedef typename E::storage_category storage_category;
1496 // Construction and destruction
1498 // matrix_unary2 may be used as mutable expression -
1499 // this is the only non const expression constructor
1500 explicit matrix_unary2 (expression_type &e):
1505 size_type size1 () const {
1509 size_type size2 () const {
1514 // Expression accessors
1516 const expression_closure_type &expression () const {
1523 const_reference operator () (size_type i, size_type j) const {
1524 return functor_type::apply (e_ (j, i));
1527 reference operator () (size_type i, size_type j) {
1528 BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
1534 const_reference operator () (size_type i) const {
1535 return functor_type::apply (e_ (i));
1538 reference operator () (size_type i) {
1539 BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
1543 // Closure comparison
1545 bool same_closure (const matrix_unary2 &mu2) const {
1546 return (*this).expression ().same_closure (mu2.expression ());
1551 typedef typename E::const_iterator1 const_subiterator2_type;
1552 typedef typename E::const_iterator2 const_subiterator1_type;
1553 typedef const value_type *const_pointer;
1556 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1557 typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
1558 typedef const_iterator1 iterator1;
1559 typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
1560 typedef const_iterator2 iterator2;
1562 class const_iterator1;
1563 typedef const_iterator1 iterator1;
1564 class const_iterator2;
1565 typedef const_iterator2 iterator2;
1567 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1568 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1572 const_iterator1 find1 (int rank, size_type i, size_type j) const {
1573 const_subiterator1_type it1 (e_.find2 (rank, j, i));
1574 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1575 return const_iterator1 (*this, it1.index2 (), it1.index1 ());
1577 return const_iterator1 (*this, it1);
1581 const_iterator2 find2 (int rank, size_type i, size_type j) const {
1582 const_subiterator2_type it2 (e_.find1 (rank, j, i));
1583 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1584 return const_iterator2 (*this, it2.index2 (), it2.index1 ());
1586 return const_iterator2 (*this, it2);
1590 // Iterators enhance the iterators of the referenced expression
1591 // with the unary functor.
1593 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1594 class const_iterator1:
1595 public container_const_reference<matrix_unary2>,
1596 public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
1597 iterator_base<const_iterator1, value_type>::type {
1599 typedef typename E::const_iterator2::iterator_category iterator_category;
1600 typedef typename matrix_unary2::difference_type difference_type;
1601 typedef typename matrix_unary2::value_type value_type;
1602 typedef typename matrix_unary2::const_reference reference;
1603 typedef typename matrix_unary2::const_pointer pointer;
1605 typedef const_iterator2 dual_iterator_type;
1606 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1608 // Construction and destruction
1611 container_const_reference<self_type> (), it_ () {}
1613 const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
1614 container_const_reference<self_type> (mu), it_ (it) {}
1618 const_iterator1 &operator ++ () {
1623 const_iterator1 &operator -- () {
1628 const_iterator1 &operator += (difference_type n) {
1633 const_iterator1 &operator -= (difference_type n) {
1638 difference_type operator - (const const_iterator1 &it) const {
1639 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1640 return it_ - it.it_;
1645 const_reference operator * () const {
1646 return functor_type::apply (*it_);
1649 const_reference operator [] (difference_type n) const {
1650 return *(*this + n);
1653 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1655 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1656 typename self_type::
1658 const_iterator2 begin () const {
1659 return (*this) ().find2 (1, index1 (), 0);
1662 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1663 typename self_type::
1665 const_iterator2 cbegin () const {
1669 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1670 typename self_type::
1672 const_iterator2 end () const {
1673 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1676 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1677 typename self_type::
1679 const_iterator2 cend () const {
1683 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1684 typename self_type::
1686 const_reverse_iterator2 rbegin () const {
1687 return const_reverse_iterator2 (end ());
1690 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1691 typename self_type::
1693 const_reverse_iterator2 crbegin () const {
1697 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1698 typename self_type::
1700 const_reverse_iterator2 rend () const {
1701 return const_reverse_iterator2 (begin ());
1704 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1705 typename self_type::
1707 const_reverse_iterator2 crend () const {
1714 size_type index1 () const {
1715 return it_.index2 ();
1718 size_type index2 () const {
1719 return it_.index1 ();
1724 const_iterator1 &operator = (const const_iterator1 &it) {
1725 container_const_reference<self_type>::assign (&it ());
1732 bool operator == (const const_iterator1 &it) const {
1733 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1734 return it_ == it.it_;
1737 bool operator < (const const_iterator1 &it) const {
1738 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1739 return it_ < it.it_;
1743 const_subiterator1_type it_;
1748 const_iterator1 begin1 () const {
1749 return find1 (0, 0, 0);
1752 const_iterator1 cbegin1 () const {
1756 const_iterator1 end1 () const {
1757 return find1 (0, size1 (), 0);
1760 const_iterator1 cend1 () const {
1764 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1765 class const_iterator2:
1766 public container_const_reference<matrix_unary2>,
1767 public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
1768 iterator_base<const_iterator2, value_type>::type {
1770 typedef typename E::const_iterator1::iterator_category iterator_category;
1771 typedef typename matrix_unary2::difference_type difference_type;
1772 typedef typename matrix_unary2::value_type value_type;
1773 typedef typename matrix_unary2::const_reference reference;
1774 typedef typename matrix_unary2::const_pointer pointer;
1776 typedef const_iterator1 dual_iterator_type;
1777 typedef const_reverse_iterator1 dual_reverse_iterator_type;
1779 // Construction and destruction
1782 container_const_reference<self_type> (), it_ () {}
1784 const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
1785 container_const_reference<self_type> (mu), it_ (it) {}
1789 const_iterator2 &operator ++ () {
1794 const_iterator2 &operator -- () {
1799 const_iterator2 &operator += (difference_type n) {
1804 const_iterator2 &operator -= (difference_type n) {
1809 difference_type operator - (const const_iterator2 &it) const {
1810 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1811 return it_ - it.it_;
1816 const_reference operator * () const {
1817 return functor_type::apply (*it_);
1820 const_reference operator [] (difference_type n) const {
1821 return *(*this + n);
1824 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1826 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1827 typename self_type::
1829 const_iterator1 begin () const {
1830 return (*this) ().find1 (1, 0, index2 ());
1833 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1834 typename self_type::
1836 const_iterator1 cbegin () const {
1840 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1841 typename self_type::
1843 const_iterator1 end () const {
1844 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1847 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1848 typename self_type::
1850 const_iterator1 cend () const {
1854 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1855 typename self_type::
1857 const_reverse_iterator1 rbegin () const {
1858 return const_reverse_iterator1 (end ());
1861 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1862 typename self_type::
1864 const_reverse_iterator1 crbegin () const {
1868 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1869 typename self_type::
1871 const_reverse_iterator1 rend () const {
1872 return const_reverse_iterator1 (begin ());
1875 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1876 typename self_type::
1878 const_reverse_iterator1 crend () const {
1885 size_type index1 () const {
1886 return it_.index2 ();
1889 size_type index2 () const {
1890 return it_.index1 ();
1895 const_iterator2 &operator = (const const_iterator2 &it) {
1896 container_const_reference<self_type>::assign (&it ());
1903 bool operator == (const const_iterator2 &it) const {
1904 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1905 return it_ == it.it_;
1908 bool operator < (const const_iterator2 &it) const {
1909 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1910 return it_ < it.it_;
1914 const_subiterator2_type it_;
1919 const_iterator2 begin2 () const {
1920 return find2 (0, 0, 0);
1923 const_iterator2 cbegin2 () const {
1927 const_iterator2 end2 () const {
1928 return find2 (0, 0, size2 ());
1931 const_iterator2 cend2 () const {
1935 // Reverse iterators
1938 const_reverse_iterator1 rbegin1 () const {
1939 return const_reverse_iterator1 (end1 ());
1942 const_reverse_iterator1 crbegin1 () const {
1946 const_reverse_iterator1 rend1 () const {
1947 return const_reverse_iterator1 (begin1 ());
1950 const_reverse_iterator1 crend1 () const {
1955 const_reverse_iterator2 rbegin2 () const {
1956 return const_reverse_iterator2 (end2 ());
1959 const_reverse_iterator2 crbegin2 () const {
1963 const_reverse_iterator2 rend2 () const {
1964 return const_reverse_iterator2 (begin2 ());
1967 const_reverse_iterator2 crend2 () const {
1972 expression_closure_type e_;
1975 template<class E, class F>
1976 struct matrix_unary2_traits {
1977 typedef matrix_unary2<E, F> expression_type;
1978 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1979 typedef expression_type result_type;
1981 typedef typename E::matrix_temporary_type result_type;
1985 // (trans m) [i] [j] = m [j] [i]
1988 typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::result_type
1989 trans (const matrix_expression<E> &e) {
1990 typedef typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
1991 return expression_type (e ());
1995 typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::result_type
1996 trans (matrix_expression<E> &e) {
1997 typedef typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
1998 return expression_type (e ());
2001 // (herm m) [i] [j] = conj (m [j] [i])
2004 typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::result_type
2005 herm (const matrix_expression<E> &e) {
2006 typedef typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
2007 return expression_type (e ());
2010 template<class E1, class E2, class F>
2011 class matrix_binary:
2012 public matrix_expression<matrix_binary<E1, E2, F> > {
2014 typedef E1 expression1_type;
2015 typedef E2 expression2_type;
2016 typedef F functor_type;
2018 typedef typename E1::const_closure_type expression1_closure_type;
2019 typedef typename E2::const_closure_type expression2_closure_type;
2021 typedef matrix_binary<E1, E2, F> self_type;
2023 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2024 using matrix_expression<self_type>::operator ();
2026 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
2027 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
2028 typedef typename F::result_type value_type;
2029 typedef value_type const_reference;
2030 typedef const_reference reference;
2031 typedef const self_type const_closure_type;
2032 typedef const_closure_type closure_type;
2033 typedef unknown_orientation_tag orientation_category;
2034 typedef unknown_storage_tag storage_category;
2036 // Construction and destruction
2038 matrix_binary (const E1 &e1, const E2 &e2):
2039 e1_ (e1), e2_ (e2) {}
2043 size_type size1 () const {
2044 return BOOST_UBLAS_SAME (e1_.size1 (), e2_.size1 ());
2047 size_type size2 () const {
2048 return BOOST_UBLAS_SAME (e1_.size2 (), e2_.size2 ());
2052 // Expression accessors
2054 const expression1_closure_type &expression1 () const {
2058 const expression2_closure_type &expression2 () const {
2065 const_reference operator () (size_type i, size_type j) const {
2066 return functor_type::apply (e1_ (i, j), e2_ (i, j));
2071 const_reference operator () (size_type i) const {
2072 return functor_type::apply (e1_ (i), e2_ (i));
2075 // Closure comparison
2077 bool same_closure (const matrix_binary &mb) const {
2078 return (*this).expression1 ().same_closure (mb.expression1 ()) &&
2079 (*this).expression2 ().same_closure (mb.expression2 ());
2084 typedef typename E1::const_iterator1 const_iterator11_type;
2085 typedef typename E1::const_iterator2 const_iterator12_type;
2086 typedef typename E2::const_iterator1 const_iterator21_type;
2087 typedef typename E2::const_iterator2 const_iterator22_type;
2088 typedef const value_type *const_pointer;
2091 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2092 typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
2093 typename const_iterator21_type::iterator_category>::iterator_category iterator_category1;
2094 typedef indexed_const_iterator1<const_closure_type, iterator_category1> const_iterator1;
2095 typedef const_iterator1 iterator1;
2096 typedef typename iterator_restrict_traits<typename const_iterator12_type::iterator_category,
2097 typename const_iterator22_type::iterator_category>::iterator_category iterator_category2;
2098 typedef indexed_const_iterator2<const_closure_type, iterator_category2> const_iterator2;
2099 typedef const_iterator2 iterator2;
2101 class const_iterator1;
2102 typedef const_iterator1 iterator1;
2103 class const_iterator2;
2104 typedef const_iterator2 iterator2;
2106 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2107 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2111 const_iterator1 find1 (int rank, size_type i, size_type j) const {
2112 const_iterator11_type it11 (e1_.find1 (rank, i, j));
2113 const_iterator11_type it11_end (e1_.find1 (rank, size1 (), j));
2114 const_iterator21_type it21 (e2_.find1 (rank, i, j));
2115 const_iterator21_type it21_end (e2_.find1 (rank, size1 (), j));
2116 BOOST_UBLAS_CHECK (rank == 0 || it11 == it11_end || it11.index2 () == j, internal_logic ())
2117 BOOST_UBLAS_CHECK (rank == 0 || it21 == it21_end || it21.index2 () == j, internal_logic ())
2118 i = (std::min) (it11 != it11_end ? it11.index1 () : size1 (),
2119 it21 != it21_end ? it21.index1 () : size1 ());
2120 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2121 return const_iterator1 (*this, i, j);
2123 return const_iterator1 (*this, i, j, it11, it11_end, it21, it21_end);
2127 const_iterator2 find2 (int rank, size_type i, size_type j) const {
2128 const_iterator12_type it12 (e1_.find2 (rank, i, j));
2129 const_iterator12_type it12_end (e1_.find2 (rank, i, size2 ()));
2130 const_iterator22_type it22 (e2_.find2 (rank, i, j));
2131 const_iterator22_type it22_end (e2_.find2 (rank, i, size2 ()));
2132 BOOST_UBLAS_CHECK (rank == 0 || it12 == it12_end || it12.index1 () == i, internal_logic ())
2133 BOOST_UBLAS_CHECK (rank == 0 || it22 == it22_end || it22.index1 () == i, internal_logic ())
2134 j = (std::min) (it12 != it12_end ? it12.index2 () : size2 (),
2135 it22 != it22_end ? it22.index2 () : size2 ());
2136 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2137 return const_iterator2 (*this, i, j);
2139 return const_iterator2 (*this, i, j, it12, it12_end, it22, it22_end);
2143 // Iterators enhance the iterators of the referenced expression
2144 // with the binary functor.
2146 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2147 class const_iterator1:
2148 public container_const_reference<matrix_binary>,
2149 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
2150 typename E2::const_iterator1::iterator_category>::iterator_category>::template
2151 iterator_base<const_iterator1, value_type>::type {
2153 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
2154 typename E2::const_iterator1::iterator_category>::iterator_category iterator_category;
2155 typedef typename matrix_binary::difference_type difference_type;
2156 typedef typename matrix_binary::value_type value_type;
2157 typedef typename matrix_binary::const_reference reference;
2158 typedef typename matrix_binary::const_pointer pointer;
2160 typedef const_iterator2 dual_iterator_type;
2161 typedef const_reverse_iterator2 dual_reverse_iterator_type;
2163 // Construction and destruction
2166 container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
2168 const_iterator1 (const self_type &mb, size_type i, size_type j,
2169 const const_iterator11_type &it1, const const_iterator11_type &it1_end,
2170 const const_iterator21_type &it2, const const_iterator21_type &it2_end):
2171 container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
2174 // Dense specializations
2176 void increment (dense_random_access_iterator_tag) {
2177 ++ i_; ++ it1_; ++ it2_;
2180 void decrement (dense_random_access_iterator_tag) {
2181 -- i_; -- it1_; -- it2_;
2184 void increment (dense_random_access_iterator_tag, difference_type n) {
2185 i_ += n; it1_ += n; it2_ += n;
2188 void decrement (dense_random_access_iterator_tag, difference_type n) {
2189 i_ -= n; it1_ -= n; it2_ -= n;
2192 value_type dereference (dense_random_access_iterator_tag) const {
2193 return functor_type::apply (*it1_, *it2_);
2196 // Packed specializations
2198 void increment (packed_random_access_iterator_tag) {
2199 if (it1_ != it1_end_)
2200 if (it1_.index1 () <= i_)
2202 if (it2_ != it2_end_)
2203 if (it2_.index1 () <= i_)
2208 void decrement (packed_random_access_iterator_tag) {
2209 if (it1_ != it1_end_)
2210 if (i_ <= it1_.index1 ())
2212 if (it2_ != it2_end_)
2213 if (i_ <= it2_.index1 ())
2218 void increment (packed_random_access_iterator_tag, difference_type n) {
2220 increment (packed_random_access_iterator_tag ());
2224 decrement (packed_random_access_iterator_tag ());
2229 void decrement (packed_random_access_iterator_tag, difference_type n) {
2231 decrement (packed_random_access_iterator_tag ());
2235 increment (packed_random_access_iterator_tag ());
2240 value_type dereference (packed_random_access_iterator_tag) const {
2241 typename E1::value_type t1 = typename E1::value_type/*zero*/();
2242 if (it1_ != it1_end_) {
2243 BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
2244 if (it1_.index1 () == i_)
2247 typename E2::value_type t2 = typename E2::value_type/*zero*/();
2248 if (it2_ != it2_end_) {
2249 BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
2250 if (it2_.index1 () == i_)
2253 return functor_type::apply (t1, t2);
2256 // Sparse specializations
2258 void increment (sparse_bidirectional_iterator_tag) {
2259 size_type index1 = (*this) ().size1 ();
2260 if (it1_ != it1_end_) {
2261 if (it1_.index1 () <= i_)
2263 if (it1_ != it1_end_)
2264 index1 = it1_.index1 ();
2266 size_type index2 = (*this) ().size1 ();
2267 if (it2_ != it2_end_)
2268 if (it2_.index1 () <= i_)
2270 if (it2_ != it2_end_) {
2271 index2 = it2_.index1 ();
2273 i_ = (std::min) (index1, index2);
2276 void decrement (sparse_bidirectional_iterator_tag) {
2277 size_type index1 = (*this) ().size1 ();
2278 if (it1_ != it1_end_) {
2279 if (i_ <= it1_.index1 ())
2281 if (it1_ != it1_end_)
2282 index1 = it1_.index1 ();
2284 size_type index2 = (*this) ().size1 ();
2285 if (it2_ != it2_end_) {
2286 if (i_ <= it2_.index1 ())
2288 if (it2_ != it2_end_)
2289 index2 = it2_.index1 ();
2291 i_ = (std::max) (index1, index2);
2294 void increment (sparse_bidirectional_iterator_tag, difference_type n) {
2296 increment (sparse_bidirectional_iterator_tag ());
2300 decrement (sparse_bidirectional_iterator_tag ());
2305 void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
2307 decrement (sparse_bidirectional_iterator_tag ());
2311 increment (sparse_bidirectional_iterator_tag ());
2316 value_type dereference (sparse_bidirectional_iterator_tag) const {
2317 typename E1::value_type t1 = typename E1::value_type/*zero*/();
2318 if (it1_ != it1_end_) {
2319 BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
2320 if (it1_.index1 () == i_)
2323 typename E2::value_type t2 = typename E2::value_type/*zero*/();
2324 if (it2_ != it2_end_) {
2325 BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
2326 if (it2_.index1 () == i_)
2329 return functor_type::apply (t1, t2);
2335 const_iterator1 &operator ++ () {
2336 increment (iterator_category ());
2340 const_iterator1 &operator -- () {
2341 decrement (iterator_category ());
2345 const_iterator1 &operator += (difference_type n) {
2346 increment (iterator_category (), n);
2350 const_iterator1 &operator -= (difference_type n) {
2351 decrement (iterator_category (), n);
2355 difference_type operator - (const const_iterator1 &it) const {
2356 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2357 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
2358 return index1 () - it.index1 ();
2363 const_reference operator * () const {
2364 return dereference (iterator_category ());
2367 const_reference operator [] (difference_type n) const {
2368 return *(*this + n);
2371 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2373 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2374 typename self_type::
2376 const_iterator2 begin () const {
2377 return (*this) ().find2 (1, index1 (), 0);
2380 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2381 typename self_type::
2383 const_iterator2 cbegin () const {
2387 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2388 typename self_type::
2390 const_iterator2 end () const {
2391 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
2394 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2395 typename self_type::
2397 const_iterator2 cend () const {
2401 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2402 typename self_type::
2404 const_reverse_iterator2 rbegin () const {
2405 return const_reverse_iterator2 (end ());
2408 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2409 typename self_type::
2411 const_reverse_iterator2 crbegin () const {
2415 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2416 typename self_type::
2418 const_reverse_iterator2 rend () const {
2419 return const_reverse_iterator2 (begin ());
2422 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2423 typename self_type::
2425 const_reverse_iterator2 crend () const {
2432 size_type index1 () const {
2436 size_type index2 () const {
2437 // if (it1_ != it1_end_ && it2_ != it2_end_)
2438 // return BOOST_UBLAS_SAME (it1_.index2 (), it2_.index2 ());
2445 const_iterator1 &operator = (const const_iterator1 &it) {
2446 container_const_reference<self_type>::assign (&it ());
2450 it1_end_ = it.it1_end_;
2452 it2_end_ = it.it2_end_;
2458 bool operator == (const const_iterator1 &it) const {
2459 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2460 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
2461 return index1 () == it.index1 ();
2464 bool operator < (const const_iterator1 &it) const {
2465 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2466 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
2467 return index1 () < it.index1 ();
2473 const_iterator11_type it1_;
2474 const_iterator11_type it1_end_;
2475 const_iterator21_type it2_;
2476 const_iterator21_type it2_end_;
2481 const_iterator1 begin1 () const {
2482 return find1 (0, 0, 0);
2485 const_iterator1 cbegin1 () const {
2489 const_iterator1 end1 () const {
2490 return find1 (0, size1 (), 0);
2493 const_iterator1 cend1 () const {
2497 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2498 class const_iterator2:
2499 public container_const_reference<matrix_binary>,
2500 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
2501 typename E2::const_iterator2::iterator_category>::iterator_category>::template
2502 iterator_base<const_iterator2, value_type>::type {
2504 typedef typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
2505 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
2506 typedef typename matrix_binary::difference_type difference_type;
2507 typedef typename matrix_binary::value_type value_type;
2508 typedef typename matrix_binary::const_reference reference;
2509 typedef typename matrix_binary::const_pointer pointer;
2511 typedef const_iterator1 dual_iterator_type;
2512 typedef const_reverse_iterator1 dual_reverse_iterator_type;
2514 // Construction and destruction
2517 container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
2519 const_iterator2 (const self_type &mb, size_type i, size_type j,
2520 const const_iterator12_type &it1, const const_iterator12_type &it1_end,
2521 const const_iterator22_type &it2, const const_iterator22_type &it2_end):
2522 container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
2525 // Dense access specializations
2527 void increment (dense_random_access_iterator_tag) {
2528 ++ j_; ++ it1_; ++ it2_;
2531 void decrement (dense_random_access_iterator_tag) {
2532 -- j_; -- it1_; -- it2_;
2535 void increment (dense_random_access_iterator_tag, difference_type n) {
2536 j_ += n; it1_ += n; it2_ += n;
2539 void decrement (dense_random_access_iterator_tag, difference_type n) {
2540 j_ -= n; it1_ -= n; it2_ -= n;
2543 value_type dereference (dense_random_access_iterator_tag) const {
2544 return functor_type::apply (*it1_, *it2_);
2547 // Packed specializations
2549 void increment (packed_random_access_iterator_tag) {
2550 if (it1_ != it1_end_)
2551 if (it1_.index2 () <= j_)
2553 if (it2_ != it2_end_)
2554 if (it2_.index2 () <= j_)
2559 void decrement (packed_random_access_iterator_tag) {
2560 if (it1_ != it1_end_)
2561 if (j_ <= it1_.index2 ())
2563 if (it2_ != it2_end_)
2564 if (j_ <= it2_.index2 ())
2569 void increment (packed_random_access_iterator_tag, difference_type n) {
2571 increment (packed_random_access_iterator_tag ());
2575 decrement (packed_random_access_iterator_tag ());
2580 void decrement (packed_random_access_iterator_tag, difference_type n) {
2582 decrement (packed_random_access_iterator_tag ());
2586 increment (packed_random_access_iterator_tag ());
2591 value_type dereference (packed_random_access_iterator_tag) const {
2592 typename E1::value_type t1 = typename E1::value_type/*zero*/();
2593 if (it1_ != it1_end_) {
2594 BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
2595 if (it1_.index2 () == j_)
2598 typename E2::value_type t2 = typename E2::value_type/*zero*/();
2599 if (it2_ != it2_end_) {
2600 BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
2601 if (it2_.index2 () == j_)
2604 return functor_type::apply (t1, t2);
2607 // Sparse specializations
2609 void increment (sparse_bidirectional_iterator_tag) {
2610 size_type index1 = (*this) ().size2 ();
2611 if (it1_ != it1_end_) {
2612 if (it1_.index2 () <= j_)
2614 if (it1_ != it1_end_)
2615 index1 = it1_.index2 ();
2617 size_type index2 = (*this) ().size2 ();
2618 if (it2_ != it2_end_) {
2619 if (it2_.index2 () <= j_)
2621 if (it2_ != it2_end_)
2622 index2 = it2_.index2 ();
2624 j_ = (std::min) (index1, index2);
2627 void decrement (sparse_bidirectional_iterator_tag) {
2628 size_type index1 = (*this) ().size2 ();
2629 if (it1_ != it1_end_) {
2630 if (j_ <= it1_.index2 ())
2632 if (it1_ != it1_end_)
2633 index1 = it1_.index2 ();
2635 size_type index2 = (*this) ().size2 ();
2636 if (it2_ != it2_end_) {
2637 if (j_ <= it2_.index2 ())
2639 if (it2_ != it2_end_)
2640 index2 = it2_.index2 ();
2642 j_ = (std::max) (index1, index2);
2645 void increment (sparse_bidirectional_iterator_tag, difference_type n) {
2647 increment (sparse_bidirectional_iterator_tag ());
2651 decrement (sparse_bidirectional_iterator_tag ());
2656 void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
2658 decrement (sparse_bidirectional_iterator_tag ());
2662 increment (sparse_bidirectional_iterator_tag ());
2667 value_type dereference (sparse_bidirectional_iterator_tag) const {
2668 typename E1::value_type t1 = typename E1::value_type/*zero*/();
2669 if (it1_ != it1_end_) {
2670 BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
2671 if (it1_.index2 () == j_)
2674 typename E2::value_type t2 = typename E2::value_type/*zero*/();
2675 if (it2_ != it2_end_) {
2676 BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
2677 if (it2_.index2 () == j_)
2680 return functor_type::apply (t1, t2);
2686 const_iterator2 &operator ++ () {
2687 increment (iterator_category ());
2691 const_iterator2 &operator -- () {
2692 decrement (iterator_category ());
2696 const_iterator2 &operator += (difference_type n) {
2697 increment (iterator_category (), n);
2701 const_iterator2 &operator -= (difference_type n) {
2702 decrement (iterator_category (), n);
2706 difference_type operator - (const const_iterator2 &it) const {
2707 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2708 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
2709 return index2 () - it.index2 ();
2714 const_reference operator * () const {
2715 return dereference (iterator_category ());
2718 const_reference operator [] (difference_type n) const {
2719 return *(*this + n);
2722 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2724 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2725 typename self_type::
2727 const_iterator1 begin () const {
2728 return (*this) ().find1 (1, 0, index2 ());
2731 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2732 typename self_type::
2734 const_iterator1 cbegin () const {
2738 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2739 typename self_type::
2741 const_iterator1 end () const {
2742 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
2745 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2746 typename self_type::
2748 const_iterator1 cend () const {
2752 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2753 typename self_type::
2755 const_reverse_iterator1 rbegin () const {
2756 return const_reverse_iterator1 (end ());
2759 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2760 typename self_type::
2762 const_reverse_iterator1 crbegin () const {
2766 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2767 typename self_type::
2769 const_reverse_iterator1 rend () const {
2770 return const_reverse_iterator1 (begin ());
2773 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2774 typename self_type::
2776 const_reverse_iterator1 crend () const {
2783 size_type index1 () const {
2784 // if (it1_ != it1_end_ && it2_ != it2_end_)
2785 // return BOOST_UBLAS_SAME (it1_.index1 (), it2_.index1 ());
2790 size_type index2 () const {
2796 const_iterator2 &operator = (const const_iterator2 &it) {
2797 container_const_reference<self_type>::assign (&it ());
2801 it1_end_ = it.it1_end_;
2803 it2_end_ = it.it2_end_;
2809 bool operator == (const const_iterator2 &it) const {
2810 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2811 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
2812 return index2 () == it.index2 ();
2815 bool operator < (const const_iterator2 &it) const {
2816 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2817 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
2818 return index2 () < it.index2 ();
2824 const_iterator12_type it1_;
2825 const_iterator12_type it1_end_;
2826 const_iterator22_type it2_;
2827 const_iterator22_type it2_end_;
2832 const_iterator2 begin2 () const {
2833 return find2 (0, 0, 0);
2836 const_iterator2 cbegin2 () const {
2840 const_iterator2 end2 () const {
2841 return find2 (0, 0, size2 ());
2844 const_iterator2 cend2 () const {
2848 // Reverse iterators
2851 const_reverse_iterator1 rbegin1 () const {
2852 return const_reverse_iterator1 (end1 ());
2855 const_reverse_iterator1 crbegin1 () const {
2859 const_reverse_iterator1 rend1 () const {
2860 return const_reverse_iterator1 (begin1 ());
2863 const_reverse_iterator1 crend1 () const {
2868 const_reverse_iterator2 rbegin2 () const {
2869 return const_reverse_iterator2 (end2 ());
2872 const_reverse_iterator2 crbegin2 () const {
2876 const_reverse_iterator2 rend2 () const {
2877 return const_reverse_iterator2 (begin2 ());
2880 const_reverse_iterator2 crend2 () const {
2885 expression1_closure_type e1_;
2886 expression2_closure_type e2_;
2889 template<class E1, class E2, class F>
2890 struct matrix_binary_traits {
2891 typedef matrix_binary<E1, E2, F> expression_type;
2892 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
2893 typedef expression_type result_type;
2895 typedef typename E1::matrix_temporary_type result_type;
2899 // (m1 + m2) [i] [j] = m1 [i] [j] + m2 [i] [j]
2900 template<class E1, class E2>
2902 typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
2903 typename E2::value_type> >::result_type
2904 operator + (const matrix_expression<E1> &e1,
2905 const matrix_expression<E2> &e2) {
2906 typedef typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
2907 typename E2::value_type> >::expression_type expression_type;
2908 return expression_type (e1 (), e2 ());
2911 // (m1 - m2) [i] [j] = m1 [i] [j] - m2 [i] [j]
2912 template<class E1, class E2>
2914 typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
2915 typename E2::value_type> >::result_type
2916 operator - (const matrix_expression<E1> &e1,
2917 const matrix_expression<E2> &e2) {
2918 typedef typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
2919 typename E2::value_type> >::expression_type expression_type;
2920 return expression_type (e1 (), e2 ());
2923 // (m1 * m2) [i] [j] = m1 [i] [j] * m2 [i] [j]
2924 template<class E1, class E2>
2926 typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
2927 typename E2::value_type> >::result_type
2928 element_prod (const matrix_expression<E1> &e1,
2929 const matrix_expression<E2> &e2) {
2930 typedef typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
2931 typename E2::value_type> >::expression_type expression_type;
2932 return expression_type (e1 (), e2 ());
2935 // (m1 / m2) [i] [j] = m1 [i] [j] / m2 [i] [j]
2936 template<class E1, class E2>
2938 typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
2939 typename E2::value_type> >::result_type
2940 element_div (const matrix_expression<E1> &e1,
2941 const matrix_expression<E2> &e2) {
2942 typedef typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
2943 typename E2::value_type> >::expression_type expression_type;
2944 return expression_type (e1 (), e2 ());
2947 template<class E1, class E2, class F>
2948 class matrix_binary_scalar1:
2949 public matrix_expression<matrix_binary_scalar1<E1, E2, F> > {
2951 typedef E1 expression1_type;
2952 typedef E2 expression2_type;
2953 typedef F functor_type;
2954 typedef const E1& expression1_closure_type;
2955 typedef typename E2::const_closure_type expression2_closure_type;
2956 typedef matrix_binary_scalar1<E1, E2, F> self_type;
2958 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2959 using matrix_expression<self_type>::operator ();
2961 typedef typename E2::size_type size_type;
2962 typedef typename E2::difference_type difference_type;
2963 typedef typename F::result_type value_type;
2964 typedef value_type const_reference;
2965 typedef const_reference reference;
2966 typedef const self_type const_closure_type;
2967 typedef const_closure_type closure_type;
2968 typedef typename E2::orientation_category orientation_category;
2969 typedef unknown_storage_tag storage_category;
2971 // Construction and destruction
2973 matrix_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
2974 e1_ (e1), e2_ (e2) {}
2978 size_type size1 () const {
2979 return e2_.size1 ();
2982 size_type size2 () const {
2983 return e2_.size2 ();
2989 const_reference operator () (size_type i, size_type j) const {
2990 return functor_type::apply (expression1_type (e1_), e2_ (i, j));
2995 const_reference operator () (size_type i) const {
2996 return functor_type::apply (expression1_type (e1_), e2_ (i));
2999 // Closure comparison
3001 bool same_closure (const matrix_binary_scalar1 &mbs1) const {
3002 return &e1_ == &(mbs1.e1_) &&
3003 (*this).e2_.same_closure (mbs1.e2_);
3008 typedef expression1_type const_subiterator1_type;
3009 typedef typename E2::const_iterator1 const_iterator21_type;
3010 typedef typename E2::const_iterator2 const_iterator22_type;
3011 typedef const value_type *const_pointer;
3014 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3015 typedef indexed_const_iterator1<const_closure_type, typename const_iterator21_type::iterator_category> const_iterator1;
3016 typedef const_iterator1 iterator1;
3017 typedef indexed_const_iterator2<const_closure_type, typename const_iterator22_type::iterator_category> const_iterator2;
3018 typedef const_iterator2 iterator2;
3020 class const_iterator1;
3021 typedef const_iterator1 iterator1;
3022 class const_iterator2;
3023 typedef const_iterator2 iterator2;
3025 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
3026 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
3030 const_iterator1 find1 (int rank, size_type i, size_type j) const {
3031 const_iterator21_type it21 (e2_.find1 (rank, i, j));
3032 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3033 return const_iterator1 (*this, it21.index1 (), it21.index2 ());
3035 return const_iterator1 (*this, const_subiterator1_type (e1_), it21);
3039 const_iterator2 find2 (int rank, size_type i, size_type j) const {
3040 const_iterator22_type it22 (e2_.find2 (rank, i, j));
3041 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3042 return const_iterator2 (*this, it22.index1 (), it22.index2 ());
3044 return const_iterator2 (*this, const_subiterator1_type (e1_), it22);
3048 // Iterators enhance the iterators of the referenced expression
3049 // with the binary functor.
3051 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3052 class const_iterator1:
3053 public container_const_reference<matrix_binary_scalar1>,
3054 public iterator_base_traits<typename E2::const_iterator1::iterator_category>::template
3055 iterator_base<const_iterator1, value_type>::type {
3057 typedef typename E2::const_iterator1::iterator_category iterator_category;
3058 typedef typename matrix_binary_scalar1::difference_type difference_type;
3059 typedef typename matrix_binary_scalar1::value_type value_type;
3060 typedef typename matrix_binary_scalar1::const_reference reference;
3061 typedef typename matrix_binary_scalar1::const_pointer pointer;
3063 typedef const_iterator2 dual_iterator_type;
3064 typedef const_reverse_iterator2 dual_reverse_iterator_type;
3066 // Construction and destruction
3069 container_const_reference<self_type> (), it1_ (), it2_ () {}
3071 const_iterator1 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator21_type &it2):
3072 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
3076 const_iterator1 &operator ++ () {
3081 const_iterator1 &operator -- () {
3086 const_iterator1 &operator += (difference_type n) {
3091 const_iterator1 &operator -= (difference_type n) {
3096 difference_type operator - (const const_iterator1 &it) const {
3097 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3098 // FIXME we shouldn't compare floats
3099 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3100 return it2_ - it.it2_;
3105 const_reference operator * () const {
3106 return functor_type::apply (it1_, *it2_);
3109 const_reference operator [] (difference_type n) const {
3110 return *(*this + n);
3113 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3115 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3116 typename self_type::
3118 const_iterator2 begin () const {
3119 return (*this) ().find2 (1, index1 (), 0);
3122 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3123 typename self_type::
3125 const_iterator2 cbegin () const {
3129 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3130 typename self_type::
3132 const_iterator2 end () const {
3133 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
3136 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3137 typename self_type::
3139 const_iterator2 cend () const {
3143 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3144 typename self_type::
3146 const_reverse_iterator2 rbegin () const {
3147 return const_reverse_iterator2 (end ());
3150 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3151 typename self_type::
3153 const_reverse_iterator2 crbegin () const {
3157 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3158 typename self_type::
3160 const_reverse_iterator2 rend () const {
3161 return const_reverse_iterator2 (begin ());
3164 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3165 typename self_type::
3167 const_reverse_iterator2 crend () const {
3174 size_type index1 () const {
3175 return it2_.index1 ();
3178 size_type index2 () const {
3179 return it2_.index2 ();
3184 const_iterator1 &operator = (const const_iterator1 &it) {
3185 container_const_reference<self_type>::assign (&it ());
3193 bool operator == (const const_iterator1 &it) const {
3194 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3195 // FIXME we shouldn't compare floats
3196 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3197 return it2_ == it.it2_;
3200 bool operator < (const const_iterator1 &it) const {
3201 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3202 // FIXME we shouldn't compare floats
3203 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3204 return it2_ < it.it2_;
3208 const_subiterator1_type it1_;
3209 const_iterator21_type it2_;
3214 const_iterator1 begin1 () const {
3215 return find1 (0, 0, 0);
3218 const_iterator1 cbegin1 () const {
3222 const_iterator1 end1 () const {
3223 return find1 (0, size1 (), 0);
3226 const_iterator1 cend1 () const {
3230 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3231 class const_iterator2:
3232 public container_const_reference<matrix_binary_scalar1>,
3233 public iterator_base_traits<typename E2::const_iterator2::iterator_category>::template
3234 iterator_base<const_iterator2, value_type>::type {
3236 typedef typename E2::const_iterator2::iterator_category iterator_category;
3237 typedef typename matrix_binary_scalar1::difference_type difference_type;
3238 typedef typename matrix_binary_scalar1::value_type value_type;
3239 typedef typename matrix_binary_scalar1::const_reference reference;
3240 typedef typename matrix_binary_scalar1::const_pointer pointer;
3242 typedef const_iterator1 dual_iterator_type;
3243 typedef const_reverse_iterator1 dual_reverse_iterator_type;
3245 // Construction and destruction
3248 container_const_reference<self_type> (), it1_ (), it2_ () {}
3250 const_iterator2 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator22_type &it2):
3251 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
3255 const_iterator2 &operator ++ () {
3260 const_iterator2 &operator -- () {
3265 const_iterator2 &operator += (difference_type n) {
3270 const_iterator2 &operator -= (difference_type n) {
3275 difference_type operator - (const const_iterator2 &it) const {
3276 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3277 // FIXME we shouldn't compare floats
3278 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3279 return it2_ - it.it2_;
3284 const_reference operator * () const {
3285 return functor_type::apply (it1_, *it2_);
3288 const_reference operator [] (difference_type n) const {
3289 return *(*this + n);
3292 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3294 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3295 typename self_type::
3297 const_iterator1 begin () const {
3298 return (*this) ().find1 (1, 0, index2 ());
3301 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3302 typename self_type::
3304 const_iterator1 cbegin () const {
3308 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3309 typename self_type::
3311 const_iterator1 end () const {
3312 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
3315 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3316 typename self_type::
3318 const_iterator1 cend () const {
3322 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3323 typename self_type::
3325 const_reverse_iterator1 rbegin () const {
3326 return const_reverse_iterator1 (end ());
3329 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3330 typename self_type::
3332 const_reverse_iterator1 crbegin () const {
3336 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3337 typename self_type::
3339 const_reverse_iterator1 rend () const {
3340 return const_reverse_iterator1 (begin ());
3343 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3344 typename self_type::
3346 const_reverse_iterator1 crend () const {
3353 size_type index1 () const {
3354 return it2_.index1 ();
3357 size_type index2 () const {
3358 return it2_.index2 ();
3363 const_iterator2 &operator = (const const_iterator2 &it) {
3364 container_const_reference<self_type>::assign (&it ());
3372 bool operator == (const const_iterator2 &it) const {
3373 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3374 // FIXME we shouldn't compare floats
3375 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3376 return it2_ == it.it2_;
3379 bool operator < (const const_iterator2 &it) const {
3380 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3381 // FIXME we shouldn't compare floats
3382 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3383 return it2_ < it.it2_;
3387 const_subiterator1_type it1_;
3388 const_iterator22_type it2_;
3393 const_iterator2 begin2 () const {
3394 return find2 (0, 0, 0);
3397 const_iterator2 cbegin2 () const {
3401 const_iterator2 end2 () const {
3402 return find2 (0, 0, size2 ());
3405 const_iterator2 cend2 () const {
3409 // Reverse iterators
3412 const_reverse_iterator1 rbegin1 () const {
3413 return const_reverse_iterator1 (end1 ());
3416 const_reverse_iterator1 crbegin1 () const {
3420 const_reverse_iterator1 rend1 () const {
3421 return const_reverse_iterator1 (begin1 ());
3424 const_reverse_iterator1 crend1 () const {
3429 const_reverse_iterator2 rbegin2 () const {
3430 return const_reverse_iterator2 (end2 ());
3433 const_reverse_iterator2 crbegin2 () const {
3437 const_reverse_iterator2 rend2 () const {
3438 return const_reverse_iterator2 (begin2 ());
3441 const_reverse_iterator2 crend2 () const {
3446 expression1_closure_type e1_;
3447 expression2_closure_type e2_;
3450 template<class E1, class E2, class F>
3451 struct matrix_binary_scalar1_traits {
3452 typedef matrix_binary_scalar1<E1, E2, F> expression_type; // allow E1 to be builtin type
3453 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
3454 typedef expression_type result_type;
3456 typedef typename E2::matrix_temporary_type result_type;
3460 // (t * m) [i] [j] = t * m [i] [j]
3461 template<class T1, class E2>
3463 typename boost::enable_if< is_convertible<T1, typename E2::value_type >,
3464 typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
3466 operator * (const T1 &e1,
3467 const matrix_expression<E2> &e2) {
3468 typedef typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
3469 return expression_type (e1, e2 ());
3473 template<class E1, class E2, class F>
3474 class matrix_binary_scalar2:
3475 public matrix_expression<matrix_binary_scalar2<E1, E2, F> > {
3477 typedef E1 expression1_type;
3478 typedef E2 expression2_type;
3479 typedef F functor_type;
3481 typedef typename E1::const_closure_type expression1_closure_type;
3482 typedef const E2& expression2_closure_type;
3484 typedef matrix_binary_scalar2<E1, E2, F> self_type;
3486 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
3487 using matrix_expression<self_type>::operator ();
3489 typedef typename E1::size_type size_type;
3490 typedef typename E1::difference_type difference_type;
3491 typedef typename F::result_type value_type;
3492 typedef value_type const_reference;
3493 typedef const_reference reference;
3495 typedef const self_type const_closure_type;
3496 typedef const_closure_type closure_type;
3497 typedef typename E1::orientation_category orientation_category;
3498 typedef unknown_storage_tag storage_category;
3500 // Construction and destruction
3502 matrix_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
3503 e1_ (e1), e2_ (e2) {}
3507 size_type size1 () const {
3508 return e1_.size1 ();
3511 size_type size2 () const {
3512 return e1_.size2 ();
3518 const_reference operator () (size_type i, size_type j) const {
3519 return functor_type::apply (e1_ (i, j), expression2_type (e2_));
3523 const_reference operator () (size_type i) const {
3524 return functor_type::apply (e1_ (i), expression2_type (e2_));
3527 // Closure comparison
3529 bool same_closure (const matrix_binary_scalar2 &mbs2) const {
3530 return (*this).e1_.same_closure (mbs2.e1_) &&
3531 &e2_ == &(mbs2.e2_);
3536 typedef typename E1::const_iterator1 const_iterator11_type;
3537 typedef typename E1::const_iterator2 const_iterator12_type;
3538 typedef expression2_type const_subiterator2_type;
3539 typedef const value_type *const_pointer;
3542 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3543 typedef indexed_const_iterator1<const_closure_type, typename const_iterator11_type::iterator_category> const_iterator1;
3544 typedef const_iterator1 iterator1;
3545 typedef indexed_const_iterator2<const_closure_type, typename const_iterator12_type::iterator_category> const_iterator2;
3546 typedef const_iterator2 iterator2;
3548 class const_iterator1;
3549 typedef const_iterator1 iterator1;
3550 class const_iterator2;
3551 typedef const_iterator2 iterator2;
3553 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
3554 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
3558 const_iterator1 find1 (int rank, size_type i, size_type j) const {
3559 const_iterator11_type it11 (e1_.find1 (rank, i, j));
3560 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3561 return const_iterator1 (*this, it11.index1 (), it11.index2 ());
3563 return const_iterator1 (*this, it11, const_subiterator2_type (e2_));
3567 const_iterator2 find2 (int rank, size_type i, size_type j) const {
3568 const_iterator12_type it12 (e1_.find2 (rank, i, j));
3569 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3570 return const_iterator2 (*this, it12.index1 (), it12.index2 ());
3572 return const_iterator2 (*this, it12, const_subiterator2_type (e2_));
3576 // Iterators enhance the iterators of the referenced expression
3577 // with the binary functor.
3579 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3580 class const_iterator1:
3581 public container_const_reference<matrix_binary_scalar2>,
3582 public iterator_base_traits<typename E1::const_iterator1::iterator_category>::template
3583 iterator_base<const_iterator1, value_type>::type {
3585 typedef typename E1::const_iterator1::iterator_category iterator_category;
3586 typedef typename matrix_binary_scalar2::difference_type difference_type;
3587 typedef typename matrix_binary_scalar2::value_type value_type;
3588 typedef typename matrix_binary_scalar2::const_reference reference;
3589 typedef typename matrix_binary_scalar2::const_pointer pointer;
3591 typedef const_iterator2 dual_iterator_type;
3592 typedef const_reverse_iterator2 dual_reverse_iterator_type;
3594 // Construction and destruction
3597 container_const_reference<self_type> (), it1_ (), it2_ () {}
3599 const_iterator1 (const self_type &mbs, const const_iterator11_type &it1, const const_subiterator2_type &it2):
3600 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
3604 const_iterator1 &operator ++ () {
3609 const_iterator1 &operator -- () {
3614 const_iterator1 &operator += (difference_type n) {
3619 const_iterator1 &operator -= (difference_type n) {
3624 difference_type operator - (const const_iterator1 &it) const {
3625 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3626 // FIXME we shouldn't compare floats
3627 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3628 return it1_ - it.it1_;
3633 const_reference operator * () const {
3634 return functor_type::apply (*it1_, it2_);
3637 const_reference operator [] (difference_type n) const {
3638 return *(*this + n);
3641 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3643 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3644 typename self_type::
3646 const_iterator2 begin () const {
3647 return (*this) ().find2 (1, index1 (), 0);
3650 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3651 typename self_type::
3653 const_iterator2 cbegin () const {
3657 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3658 typename self_type::
3660 const_iterator2 end () const {
3661 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
3664 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3665 typename self_type::
3667 const_iterator2 cend () const {
3671 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3672 typename self_type::
3674 const_reverse_iterator2 rbegin () const {
3675 return const_reverse_iterator2 (end ());
3678 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3679 typename self_type::
3681 const_reverse_iterator2 crbegin () const {
3685 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3686 typename self_type::
3688 const_reverse_iterator2 rend () const {
3689 return const_reverse_iterator2 (begin ());
3692 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3693 typename self_type::
3695 const_reverse_iterator2 crend () const {
3702 size_type index1 () const {
3703 return it1_.index1 ();
3706 size_type index2 () const {
3707 return it1_.index2 ();
3712 const_iterator1 &operator = (const const_iterator1 &it) {
3713 container_const_reference<self_type>::assign (&it ());
3721 bool operator == (const const_iterator1 &it) const {
3722 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3723 // FIXME we shouldn't compare floats
3724 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3725 return it1_ == it.it1_;
3728 bool operator < (const const_iterator1 &it) const {
3729 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3730 // FIXME we shouldn't compare floats
3731 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3732 return it1_ < it.it1_;
3736 const_iterator11_type it1_;
3737 const_subiterator2_type it2_;
3742 const_iterator1 begin1 () const {
3743 return find1 (0, 0, 0);
3746 const_iterator1 cbegin1 () const {
3750 const_iterator1 end1 () const {
3751 return find1 (0, size1 (), 0);
3754 const_iterator1 cend1 () const {
3758 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3759 class const_iterator2:
3760 public container_const_reference<matrix_binary_scalar2>,
3761 public iterator_base_traits<typename E1::const_iterator2::iterator_category>::template
3762 iterator_base<const_iterator2, value_type>::type {
3764 typedef typename E1::const_iterator2::iterator_category iterator_category;
3765 typedef typename matrix_binary_scalar2::difference_type difference_type;
3766 typedef typename matrix_binary_scalar2::value_type value_type;
3767 typedef typename matrix_binary_scalar2::const_reference reference;
3768 typedef typename matrix_binary_scalar2::const_pointer pointer;
3770 typedef const_iterator1 dual_iterator_type;
3771 typedef const_reverse_iterator1 dual_reverse_iterator_type;
3773 // Construction and destruction
3776 container_const_reference<self_type> (), it1_ (), it2_ () {}
3778 const_iterator2 (const self_type &mbs, const const_iterator12_type &it1, const const_subiterator2_type &it2):
3779 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
3783 const_iterator2 &operator ++ () {
3788 const_iterator2 &operator -- () {
3793 const_iterator2 &operator += (difference_type n) {
3798 const_iterator2 &operator -= (difference_type n) {
3803 difference_type operator - (const const_iterator2 &it) const {
3804 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3805 // FIXME we shouldn't compare floats
3806 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3807 return it1_ - it.it1_;
3812 const_reference operator * () const {
3813 return functor_type::apply (*it1_, it2_);
3816 const_reference operator [] (difference_type n) const {
3817 return *(*this + n);
3820 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3822 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3823 typename self_type::
3825 const_iterator1 begin () const {
3826 return (*this) ().find1 (1, 0, index2 ());
3829 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3830 typename self_type::
3832 const_iterator1 cbegin () const {
3836 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3837 typename self_type::
3839 const_iterator1 end () const {
3840 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
3843 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3844 typename self_type::
3846 const_iterator1 cend () const {
3850 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3851 typename self_type::
3853 const_reverse_iterator1 rbegin () const {
3854 return const_reverse_iterator1 (end ());
3857 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3858 typename self_type::
3860 const_reverse_iterator1 crbegin () const {
3864 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3865 typename self_type::
3867 const_reverse_iterator1 rend () const {
3868 return const_reverse_iterator1 (begin ());
3871 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3872 typename self_type::
3874 const_reverse_iterator1 crend () const {
3881 size_type index1 () const {
3882 return it1_.index1 ();
3885 size_type index2 () const {
3886 return it1_.index2 ();
3891 const_iterator2 &operator = (const const_iterator2 &it) {
3892 container_const_reference<self_type>::assign (&it ());
3900 bool operator == (const const_iterator2 &it) const {
3901 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3902 // FIXME we shouldn't compare floats
3903 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3904 return it1_ == it.it1_;
3907 bool operator < (const const_iterator2 &it) const {
3908 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
3909 // FIXME we shouldn't compare floats
3910 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3911 return it1_ < it.it1_;
3915 const_iterator12_type it1_;
3916 const_subiterator2_type it2_;
3921 const_iterator2 begin2 () const {
3922 return find2 (0, 0, 0);
3925 const_iterator2 cbegin2 () const {
3929 const_iterator2 end2 () const {
3930 return find2 (0, 0, size2 ());
3933 const_iterator2 cend2 () const {
3937 // Reverse iterators
3940 const_reverse_iterator1 rbegin1 () const {
3941 return const_reverse_iterator1 (end1 ());
3944 const_reverse_iterator1 crbegin1 () const {
3948 const_reverse_iterator1 rend1 () const {
3949 return const_reverse_iterator1 (begin1 ());
3952 const_reverse_iterator1 crend1 () const {
3957 const_reverse_iterator2 rbegin2 () const {
3958 return const_reverse_iterator2 (end2 ());
3961 const_reverse_iterator2 crbegin2 () const {
3965 const_reverse_iterator2 rend2 () const {
3966 return const_reverse_iterator2 (begin2 ());
3969 const_reverse_iterator2 crend2 () const {
3974 expression1_closure_type e1_;
3975 expression2_closure_type e2_;
3978 template<class E1, class E2, class F>
3979 struct matrix_binary_scalar2_traits {
3980 typedef matrix_binary_scalar2<E1, E2, F> expression_type; // allow E2 to be builtin type
3981 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
3982 typedef expression_type result_type;
3984 typedef typename E1::matrix_temporary_type result_type;
3988 // (m * t) [i] [j] = m [i] [j] * t
3989 template<class E1, class T2>
3991 typename boost::enable_if< is_convertible<T2, typename E1::value_type>,
3992 typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
3994 operator * (const matrix_expression<E1> &e1,
3996 typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
3997 return expression_type (e1 (), e2);
4000 // (m / t) [i] [j] = m [i] [j] / t
4001 template<class E1, class T2>
4003 typename boost::enable_if< is_convertible<T2, typename E1::value_type>,
4004 typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
4006 operator / (const matrix_expression<E1> &e1,
4008 typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
4009 return expression_type (e1 (), e2);
4013 template<class E1, class E2, class F>
4014 class matrix_vector_binary1:
4015 public vector_expression<matrix_vector_binary1<E1, E2, F> > {
4018 typedef E1 expression1_type;
4019 typedef E2 expression2_type;
4021 typedef F functor_type;
4023 typedef typename E1::const_closure_type expression1_closure_type;
4024 typedef typename E2::const_closure_type expression2_closure_type;
4026 typedef matrix_vector_binary1<E1, E2, F> self_type;
4028 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4029 using vector_expression<self_type>::operator ();
4031 static const unsigned complexity = 1;
4032 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
4033 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
4034 typedef typename F::result_type value_type;
4035 typedef value_type const_reference;
4036 typedef const_reference reference;
4037 typedef const self_type const_closure_type;
4038 typedef const_closure_type closure_type;
4039 typedef unknown_storage_tag storage_category;
4041 // Construction and destruction
4043 matrix_vector_binary1 (const expression1_type &e1, const expression2_type &e2):
4044 e1_ (e1), e2_ (e2) {}
4048 size_type size () const {
4049 return e1_.size1 ();
4053 // Expression accessors
4055 const expression1_closure_type &expression1 () const {
4059 const expression2_closure_type &expression2 () const {
4066 const_reference operator () (size_type i) const {
4067 return functor_type::apply (e1_, e2_, i);
4070 // Closure comparison
4072 bool same_closure (const matrix_vector_binary1 &mvb1) const {
4073 return (*this).expression1 ().same_closure (mvb1.expression1 ()) &&
4074 (*this).expression2 ().same_closure (mvb1.expression2 ());
4079 typedef typename E1::const_iterator1 const_subiterator1_type;
4080 typedef typename E2::const_iterator const_subiterator2_type;
4081 typedef const value_type *const_pointer;
4084 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4085 typedef indexed_const_iterator<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator;
4086 typedef const_iterator iterator;
4088 class const_iterator;
4089 typedef const_iterator iterator;
4094 const_iterator find (size_type i) const {
4095 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4096 const_subiterator1_type it1 (e1_.find1 (0, i, 0));
4097 return const_iterator (*this, it1.index1 ());
4099 return const_iterator (*this, e1_.find1 (0, i, 0));
4104 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4105 class const_iterator:
4106 public container_const_reference<matrix_vector_binary1>,
4107 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
4108 typename E2::const_iterator::iterator_category>::iterator_category>::template
4109 iterator_base<const_iterator, value_type>::type {
4111 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
4112 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
4113 typedef typename matrix_vector_binary1::difference_type difference_type;
4114 typedef typename matrix_vector_binary1::value_type value_type;
4115 typedef typename matrix_vector_binary1::const_reference reference;
4116 typedef typename matrix_vector_binary1::const_pointer pointer;
4118 // Construction and destruction
4119 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4122 container_const_reference<self_type> (), it1_ (), e2_begin_ (), e2_end_ () {}
4124 const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
4125 container_const_reference<self_type> (mvb), it1_ (it1), e2_begin_ (mvb.expression2 ().begin ()), e2_end_ (mvb.expression2 ().end ()) {}
4129 container_const_reference<self_type> (), it1_ () {}
4131 const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
4132 container_const_reference<self_type> (mvb), it1_ (it1) {}
4136 // Dense random access specialization
4138 value_type dereference (dense_random_access_iterator_tag) const {
4139 const self_type &mvb = (*this) ();
4140 #ifdef BOOST_UBLAS_USE_INDEXING
4141 return mvb (index ());
4142 #elif BOOST_UBLAS_USE_ITERATING
4143 difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
4144 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4145 return functor_type::apply (size, it1_.begin (), e2_begin_);
4147 return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
4150 difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
4151 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
4152 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4153 return functor_type::apply (size, it1_.begin (), e2_begin_);
4155 return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
4158 return mvb (index ());
4162 // Packed bidirectional specialization
4164 value_type dereference (packed_random_access_iterator_tag) const {
4165 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4166 return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_);
4168 const self_type &mvb = (*this) ();
4169 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4170 return functor_type::apply (it1_.begin (), it1_.end (),
4171 mvb.expression2 ().begin (), mvb.expression2 ().end ());
4173 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
4174 boost::numeric::ublas::end (it1_, iterator1_tag ()),
4175 mvb.expression2 ().begin (), mvb.expression2 ().end ());
4180 // Sparse bidirectional specialization
4182 value_type dereference (sparse_bidirectional_iterator_tag) const {
4183 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4184 return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_, sparse_bidirectional_iterator_tag ());
4186 const self_type &mvb = (*this) ();
4187 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4188 return functor_type::apply (it1_.begin (), it1_.end (),
4189 mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
4191 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
4192 boost::numeric::ublas::end (it1_, iterator1_tag ()),
4193 mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
4201 const_iterator &operator ++ () {
4206 const_iterator &operator -- () {
4211 const_iterator &operator += (difference_type n) {
4216 const_iterator &operator -= (difference_type n) {
4221 difference_type operator - (const const_iterator &it) const {
4222 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4223 return it1_ - it.it1_;
4228 const_reference operator * () const {
4229 return dereference (iterator_category ());
4232 const_reference operator [] (difference_type n) const {
4233 return *(*this + n);
4238 size_type index () const {
4239 return it1_.index1 ();
4244 const_iterator &operator = (const const_iterator &it) {
4245 container_const_reference<self_type>::assign (&it ());
4247 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4248 e2_begin_ = it.e2_begin_;
4249 e2_end_ = it.e2_end_;
4256 bool operator == (const const_iterator &it) const {
4257 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4258 return it1_ == it.it1_;
4261 bool operator < (const const_iterator &it) const {
4262 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4263 return it1_ < it.it1_;
4267 const_subiterator1_type it1_;
4268 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4269 // Mutable due to assignment
4270 /* const */ const_subiterator2_type e2_begin_;
4271 /* const */ const_subiterator2_type e2_end_;
4277 const_iterator begin () const {
4281 const_iterator cbegin () const {
4285 const_iterator end () const {
4286 return find (size ());
4289 const_iterator cend () const {
4294 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
4297 const_reverse_iterator rbegin () const {
4298 return const_reverse_iterator (end ());
4301 const_reverse_iterator crbegin () const {
4305 const_reverse_iterator rend () const {
4306 return const_reverse_iterator (begin ());
4309 const_reverse_iterator crend () const {
4314 expression1_closure_type e1_;
4315 expression2_closure_type e2_;
4318 template<class T1, class E1, class T2, class E2>
4319 struct matrix_vector_binary1_traits {
4320 typedef unknown_storage_tag storage_category;
4321 typedef row_major_tag orientation_category;
4322 typedef typename promote_traits<T1, T2>::promote_type promote_type;
4323 typedef matrix_vector_binary1<E1, E2, matrix_vector_prod1<E1, E2, promote_type> > expression_type;
4324 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
4325 typedef expression_type result_type;
4327 typedef typename E1::vector_temporary_type result_type;
4331 template<class E1, class E2>
4333 typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4334 typename E2::value_type, E2>::result_type
4335 prod (const matrix_expression<E1> &e1,
4336 const vector_expression<E2> &e2,
4337 unknown_storage_tag,
4339 typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4340 typename E2::value_type, E2>::expression_type expression_type;
4341 return expression_type (e1 (), e2 ());
4345 template<class E1, class E2>
4347 typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4348 typename E2::value_type, E2>::result_type
4349 prod (const matrix_expression<E1> &e1,
4350 const vector_expression<E2> &e2) {
4351 BOOST_STATIC_ASSERT (E2::complexity == 0);
4352 typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4353 typename E2::value_type, E2>::storage_category storage_category;
4354 typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
4355 typename E2::value_type, E2>::orientation_category orientation_category;
4356 return prod (e1, e2, storage_category (), orientation_category ());
4359 template<class E1, class E2>
4361 typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4362 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
4363 prec_prod (const matrix_expression<E1> &e1,
4364 const vector_expression<E2> &e2,
4365 unknown_storage_tag,
4367 typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4368 typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
4369 return expression_type (e1 (), e2 ());
4373 template<class E1, class E2>
4375 typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4376 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
4377 prec_prod (const matrix_expression<E1> &e1,
4378 const vector_expression<E2> &e2) {
4379 BOOST_STATIC_ASSERT (E2::complexity == 0);
4380 typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4381 typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
4382 typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4383 typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
4384 return prec_prod (e1, e2, storage_category (), orientation_category ());
4387 template<class V, class E1, class E2>
4390 prod (const matrix_expression<E1> &e1,
4391 const vector_expression<E2> &e2,
4393 return v.assign (prod (e1, e2));
4396 template<class V, class E1, class E2>
4399 prec_prod (const matrix_expression<E1> &e1,
4400 const vector_expression<E2> &e2,
4402 return v.assign (prec_prod (e1, e2));
4405 template<class V, class E1, class E2>
4408 prod (const matrix_expression<E1> &e1,
4409 const vector_expression<E2> &e2) {
4410 return V (prod (e1, e2));
4413 template<class V, class E1, class E2>
4416 prec_prod (const matrix_expression<E1> &e1,
4417 const vector_expression<E2> &e2) {
4418 return V (prec_prod (e1, e2));
4421 template<class E1, class E2, class F>
4422 class matrix_vector_binary2:
4423 public vector_expression<matrix_vector_binary2<E1, E2, F> > {
4425 typedef E1 expression1_type;
4426 typedef E2 expression2_type;
4427 typedef F functor_type;
4429 typedef typename E1::const_closure_type expression1_closure_type;
4430 typedef typename E2::const_closure_type expression2_closure_type;
4432 typedef matrix_vector_binary2<E1, E2, F> self_type;
4434 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4435 using vector_expression<self_type>::operator ();
4437 static const unsigned complexity = 1;
4438 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
4439 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
4440 typedef typename F::result_type value_type;
4441 typedef value_type const_reference;
4442 typedef const_reference reference;
4443 typedef const self_type const_closure_type;
4444 typedef const_closure_type closure_type;
4445 typedef unknown_storage_tag storage_category;
4447 // Construction and destruction
4449 matrix_vector_binary2 (const expression1_type &e1, const expression2_type &e2):
4450 e1_ (e1), e2_ (e2) {}
4454 size_type size () const {
4455 return e2_.size2 ();
4459 // Expression accessors
4461 const expression1_closure_type &expression1 () const {
4465 const expression2_closure_type &expression2 () const {
4472 const_reference operator () (size_type j) const {
4473 return functor_type::apply (e1_, e2_, j);
4476 // Closure comparison
4478 bool same_closure (const matrix_vector_binary2 &mvb2) const {
4479 return (*this).expression1 ().same_closure (mvb2.expression1 ()) &&
4480 (*this).expression2 ().same_closure (mvb2.expression2 ());
4485 typedef typename E1::const_iterator const_subiterator1_type;
4486 typedef typename E2::const_iterator2 const_subiterator2_type;
4487 typedef const value_type *const_pointer;
4490 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4491 typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
4492 typedef const_iterator iterator;
4494 class const_iterator;
4495 typedef const_iterator iterator;
4500 const_iterator find (size_type j) const {
4501 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4502 const_subiterator2_type it2 (e2_.find2 (0, 0, j));
4503 return const_iterator (*this, it2.index2 ());
4505 return const_iterator (*this, e2_.find2 (0, 0, j));
4510 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4511 class const_iterator:
4512 public container_const_reference<matrix_vector_binary2>,
4513 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
4514 typename E2::const_iterator2::iterator_category>::iterator_category>::template
4515 iterator_base<const_iterator, value_type>::type {
4517 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
4518 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
4519 typedef typename matrix_vector_binary2::difference_type difference_type;
4520 typedef typename matrix_vector_binary2::value_type value_type;
4521 typedef typename matrix_vector_binary2::const_reference reference;
4522 typedef typename matrix_vector_binary2::const_pointer pointer;
4524 // Construction and destruction
4525 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4528 container_const_reference<self_type> (), it2_ (), e1_begin_ (), e1_end_ () {}
4530 const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
4531 container_const_reference<self_type> (mvb), it2_ (it2), e1_begin_ (mvb.expression1 ().begin ()), e1_end_ (mvb.expression1 ().end ()) {}
4535 container_const_reference<self_type> (), it2_ () {}
4537 const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
4538 container_const_reference<self_type> (mvb), it2_ (it2) {}
4542 // Dense random access specialization
4544 value_type dereference (dense_random_access_iterator_tag) const {
4545 const self_type &mvb = (*this) ();
4546 #ifdef BOOST_UBLAS_USE_INDEXING
4547 return mvb (index ());
4548 #elif BOOST_UBLAS_USE_ITERATING
4549 difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
4550 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4551 return functor_type::apply (size, e1_begin_, it2_.begin ());
4553 return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
4556 difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
4557 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
4558 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4559 return functor_type::apply (size, e1_begin_, it2_.begin ());
4561 return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
4564 return mvb (index ());
4568 // Packed bidirectional specialization
4570 value_type dereference (packed_random_access_iterator_tag) const {
4571 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4572 return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end ());
4574 const self_type &mvb = (*this) ();
4575 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4576 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
4577 it2_.begin (), it2_.end ());
4579 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
4580 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
4581 boost::numeric::ublas::end (it2_, iterator2_tag ()));
4586 // Sparse bidirectional specialization
4588 value_type dereference (sparse_bidirectional_iterator_tag) const {
4589 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4590 return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
4592 const self_type &mvb = (*this) ();
4593 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4594 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
4595 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
4597 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
4598 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
4599 boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
4607 const_iterator &operator ++ () {
4612 const_iterator &operator -- () {
4617 const_iterator &operator += (difference_type n) {
4622 const_iterator &operator -= (difference_type n) {
4627 difference_type operator - (const const_iterator &it) const {
4628 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4629 return it2_ - it.it2_;
4634 const_reference operator * () const {
4635 return dereference (iterator_category ());
4638 const_reference operator [] (difference_type n) const {
4639 return *(*this + n);
4644 size_type index () const {
4645 return it2_.index2 ();
4650 const_iterator &operator = (const const_iterator &it) {
4651 container_const_reference<self_type>::assign (&it ());
4653 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4654 e1_begin_ = it.e1_begin_;
4655 e1_end_ = it.e1_end_;
4662 bool operator == (const const_iterator &it) const {
4663 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4664 return it2_ == it.it2_;
4667 bool operator < (const const_iterator &it) const {
4668 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
4669 return it2_ < it.it2_;
4673 const_subiterator2_type it2_;
4674 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4675 // Mutable due to assignment
4676 /* const */ const_subiterator1_type e1_begin_;
4677 /* const */ const_subiterator1_type e1_end_;
4683 const_iterator begin () const {
4687 const_iterator cbegin () const {
4691 const_iterator end () const {
4692 return find (size ());
4695 const_iterator cend () const {
4700 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
4703 const_reverse_iterator rbegin () const {
4704 return const_reverse_iterator (end ());
4707 const_reverse_iterator crbegin () const {
4711 const_reverse_iterator rend () const {
4712 return const_reverse_iterator (begin ());
4715 const_reverse_iterator crend () const {
4720 expression1_closure_type e1_;
4721 expression2_closure_type e2_;
4724 template<class T1, class E1, class T2, class E2>
4725 struct matrix_vector_binary2_traits {
4726 typedef unknown_storage_tag storage_category;
4727 typedef column_major_tag orientation_category;
4728 typedef typename promote_traits<T1, T2>::promote_type promote_type;
4729 typedef matrix_vector_binary2<E1, E2, matrix_vector_prod2<E1, E2, promote_type> > expression_type;
4730 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
4731 typedef expression_type result_type;
4733 typedef typename E2::vector_temporary_type result_type;
4737 template<class E1, class E2>
4739 typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4740 typename E2::value_type, E2>::result_type
4741 prod (const vector_expression<E1> &e1,
4742 const matrix_expression<E2> &e2,
4743 unknown_storage_tag,
4745 typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4746 typename E2::value_type, E2>::expression_type expression_type;
4747 return expression_type (e1 (), e2 ());
4751 template<class E1, class E2>
4753 typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4754 typename E2::value_type, E2>::result_type
4755 prod (const vector_expression<E1> &e1,
4756 const matrix_expression<E2> &e2) {
4757 BOOST_STATIC_ASSERT (E1::complexity == 0);
4758 typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4759 typename E2::value_type, E2>::storage_category storage_category;
4760 typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
4761 typename E2::value_type, E2>::orientation_category orientation_category;
4762 return prod (e1, e2, storage_category (), orientation_category ());
4765 template<class E1, class E2>
4767 typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4768 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
4769 prec_prod (const vector_expression<E1> &e1,
4770 const matrix_expression<E2> &e2,
4771 unknown_storage_tag,
4773 typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4774 typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
4775 return expression_type (e1 (), e2 ());
4779 template<class E1, class E2>
4781 typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4782 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
4783 prec_prod (const vector_expression<E1> &e1,
4784 const matrix_expression<E2> &e2) {
4785 BOOST_STATIC_ASSERT (E1::complexity == 0);
4786 typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4787 typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
4788 typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
4789 typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
4790 return prec_prod (e1, e2, storage_category (), orientation_category ());
4793 template<class V, class E1, class E2>
4796 prod (const vector_expression<E1> &e1,
4797 const matrix_expression<E2> &e2,
4799 return v.assign (prod (e1, e2));
4802 template<class V, class E1, class E2>
4805 prec_prod (const vector_expression<E1> &e1,
4806 const matrix_expression<E2> &e2,
4808 return v.assign (prec_prod (e1, e2));
4811 template<class V, class E1, class E2>
4814 prod (const vector_expression<E1> &e1,
4815 const matrix_expression<E2> &e2) {
4816 return V (prod (e1, e2));
4819 template<class V, class E1, class E2>
4822 prec_prod (const vector_expression<E1> &e1,
4823 const matrix_expression<E2> &e2) {
4824 return V (prec_prod (e1, e2));
4827 template<class E1, class E2, class F>
4828 class matrix_matrix_binary:
4829 public matrix_expression<matrix_matrix_binary<E1, E2, F> > {
4832 typedef E1 expression1_type;
4833 typedef E2 expression2_type;
4835 typedef F functor_type;
4837 typedef typename E1::const_closure_type expression1_closure_type;
4838 typedef typename E2::const_closure_type expression2_closure_type;
4840 typedef matrix_matrix_binary<E1, E2, F> self_type;
4842 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4843 using matrix_expression<self_type>::operator ();
4845 static const unsigned complexity = 1;
4846 typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
4847 typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
4848 typedef typename F::result_type value_type;
4849 typedef value_type const_reference;
4850 typedef const_reference reference;
4851 typedef const self_type const_closure_type;
4852 typedef const_closure_type closure_type;
4853 typedef unknown_orientation_tag orientation_category;
4854 typedef unknown_storage_tag storage_category;
4856 // Construction and destruction
4858 matrix_matrix_binary (const expression1_type &e1, const expression2_type &e2):
4859 e1_ (e1), e2_ (e2) {}
4863 size_type size1 () const {
4864 return e1_.size1 ();
4867 size_type size2 () const {
4868 return e2_.size2 ();
4872 // Expression accessors
4874 const expression1_closure_type &expression1 () const {
4878 const expression2_closure_type &expression2 () const {
4885 const_reference operator () (size_type i, size_type j) const {
4886 return functor_type::apply (e1_, e2_, i, j);
4891 const_reference operator () (size_type i) const {
4892 return functor_type::apply (e1_, e2_, i);
4895 // Closure comparison
4897 bool same_closure (const matrix_matrix_binary &mmb) const {
4898 return (*this).expression1 ().same_closure (mmb.expression1 ()) &&
4899 (*this).expression2 ().same_closure (mmb.expression2 ());
4904 typedef typename E1::const_iterator1 const_iterator11_type;
4905 typedef typename E1::const_iterator2 const_iterator12_type;
4906 typedef typename E2::const_iterator1 const_iterator21_type;
4907 typedef typename E2::const_iterator2 const_iterator22_type;
4908 typedef const value_type *const_pointer;
4911 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4912 typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
4913 typename const_iterator22_type::iterator_category>::iterator_category iterator_category;
4914 typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
4915 typedef const_iterator1 iterator1;
4916 typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
4917 typedef const_iterator2 iterator2;
4919 class const_iterator1;
4920 typedef const_iterator1 iterator1;
4921 class const_iterator2;
4922 typedef const_iterator2 iterator2;
4924 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
4925 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
4929 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
4930 // FIXME sparse matrix tests fail!
4931 // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
4932 const_iterator11_type it11 (e1_.find1 (0, i, 0));
4933 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4934 return const_iterator1 (*this, it11.index1 (), j);
4936 // FIXME sparse matrix tests fail!
4937 // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
4938 const_iterator22_type it22 (e2_.find2 (0, 0, j));
4939 return const_iterator1 (*this, it11, it22);
4943 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
4944 // FIXME sparse matrix tests fail!
4945 // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
4946 const_iterator22_type it22 (e2_.find2 (0, 0, j));
4947 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4948 return const_iterator2 (*this, i, it22.index2 ());
4950 // FIXME sparse matrix tests fail!
4951 // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
4952 const_iterator11_type it11 (e1_.find1 (0, i, 0));
4953 return const_iterator2 (*this, it11, it22);
4958 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4959 class const_iterator1:
4960 public container_const_reference<matrix_matrix_binary>,
4961 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
4962 typename E2::const_iterator2::iterator_category>::iterator_category>::template
4963 iterator_base<const_iterator1, value_type>::type {
4965 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
4966 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
4967 typedef typename matrix_matrix_binary::difference_type difference_type;
4968 typedef typename matrix_matrix_binary::value_type value_type;
4969 typedef typename matrix_matrix_binary::const_reference reference;
4970 typedef typename matrix_matrix_binary::const_pointer pointer;
4972 typedef const_iterator2 dual_iterator_type;
4973 typedef const_reverse_iterator2 dual_reverse_iterator_type;
4975 // Construction and destruction
4976 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
4979 container_const_reference<self_type> (), it1_ (), it2_ (), it2_begin_ (), it2_end_ () {}
4981 const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
4982 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it2_begin_ (it2.begin ()), it2_end_ (it2.end ()) {}
4986 container_const_reference<self_type> (), it1_ (), it2_ () {}
4988 const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
4989 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
4993 // Random access specialization
4995 value_type dereference (dense_random_access_iterator_tag) const {
4996 const self_type &mmb = (*this) ();
4997 #ifdef BOOST_UBLAS_USE_INDEXING
4998 return mmb (index1 (), index2 ());
4999 #elif BOOST_UBLAS_USE_ITERATING
5000 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
5001 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5002 return functor_type::apply (size, it1_.begin (), it2_begin_);
5004 return functor_type::apply (size, it1_.begin (), it2_.begin ());
5007 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
5008 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
5009 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5010 return functor_type::apply (size, it1_.begin (), it2_begin_);
5012 return functor_type::apply (size, it1_.begin (), it2_.begin ());
5015 return mmb (index1 (), index2 ());
5019 // Packed bidirectional specialization
5021 value_type dereference (packed_random_access_iterator_tag) const {
5022 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5023 return functor_type::apply (it1_.begin (), it1_.end (),
5024 it2_begin_, it2_end_, packed_random_access_iterator_tag ());
5026 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5027 return functor_type::apply (it1_.begin (), it1_.end (),
5028 it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
5030 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
5031 boost::numeric::ublas::end (it1_, iterator1_tag ()),
5032 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
5033 boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
5038 // Sparse bidirectional specialization
5040 value_type dereference (sparse_bidirectional_iterator_tag) const {
5041 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5042 return functor_type::apply (it1_.begin (), it1_.end (),
5043 it2_begin_, it2_end_, sparse_bidirectional_iterator_tag ());
5045 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5046 return functor_type::apply (it1_.begin (), it1_.end (),
5047 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
5049 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
5050 boost::numeric::ublas::end (it1_, iterator1_tag ()),
5051 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
5052 boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
5060 const_iterator1 &operator ++ () {
5065 const_iterator1 &operator -- () {
5070 const_iterator1 &operator += (difference_type n) {
5075 const_iterator1 &operator -= (difference_type n) {
5080 difference_type operator - (const const_iterator1 &it) const {
5081 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5082 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
5083 return it1_ - it.it1_;
5088 const_reference operator * () const {
5089 return dereference (iterator_category ());
5092 const_reference operator [] (difference_type n) const {
5093 return *(*this + n);
5096 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5098 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5099 typename self_type::
5101 const_iterator2 begin () const {
5102 return (*this) ().find2 (1, index1 (), 0);
5105 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5106 typename self_type::
5108 const_iterator2 cbegin () const {
5112 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5113 typename self_type::
5115 const_iterator2 end () const {
5116 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
5119 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5120 typename self_type::
5122 const_iterator2 cend () const {
5126 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5127 typename self_type::
5129 const_reverse_iterator2 rbegin () const {
5130 return const_reverse_iterator2 (end ());
5133 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5134 typename self_type::
5136 const_reverse_iterator2 crbegin () const {
5140 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5141 typename self_type::
5143 const_reverse_iterator2 rend () const {
5144 return const_reverse_iterator2 (begin ());
5147 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5148 typename self_type::
5150 const_reverse_iterator2 crend () const {
5157 size_type index1 () const {
5158 return it1_.index1 ();
5161 size_type index2 () const {
5162 return it2_.index2 ();
5167 const_iterator1 &operator = (const const_iterator1 &it) {
5168 container_const_reference<self_type>::assign (&it ());
5171 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5172 it2_begin_ = it.it2_begin_;
5173 it2_end_ = it.it2_end_;
5180 bool operator == (const const_iterator1 &it) const {
5181 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5182 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
5183 return it1_ == it.it1_;
5186 bool operator < (const const_iterator1 &it) const {
5187 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5188 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
5189 return it1_ < it.it1_;
5193 const_iterator11_type it1_;
5194 // Mutable due to assignment
5195 /* const */ const_iterator22_type it2_;
5196 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5197 /* const */ const_iterator21_type it2_begin_;
5198 /* const */ const_iterator21_type it2_end_;
5204 const_iterator1 begin1 () const {
5205 return find1 (0, 0, 0);
5208 const_iterator1 cbegin1 () const {
5212 const_iterator1 end1 () const {
5213 return find1 (0, size1 (), 0);
5216 const_iterator1 cend1 () const {
5220 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
5221 class const_iterator2:
5222 public container_const_reference<matrix_matrix_binary>,
5223 public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
5224 typename E2::const_iterator2::iterator_category>::iterator_category>::template
5225 iterator_base<const_iterator2, value_type>::type {
5227 typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
5228 typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
5229 typedef typename matrix_matrix_binary::difference_type difference_type;
5230 typedef typename matrix_matrix_binary::value_type value_type;
5231 typedef typename matrix_matrix_binary::const_reference reference;
5232 typedef typename matrix_matrix_binary::const_pointer pointer;
5234 typedef const_iterator1 dual_iterator_type;
5235 typedef const_reverse_iterator1 dual_reverse_iterator_type;
5237 // Construction and destruction
5238 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5241 container_const_reference<self_type> (), it1_ (), it2_ (), it1_begin_ (), it1_end_ () {}
5243 const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
5244 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it1_begin_ (it1.begin ()), it1_end_ (it1.end ()) {}
5248 container_const_reference<self_type> (), it1_ (), it2_ () {}
5250 const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
5251 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
5255 // Random access specialization
5257 value_type dereference (dense_random_access_iterator_tag) const {
5258 const self_type &mmb = (*this) ();
5259 #ifdef BOOST_UBLAS_USE_INDEXING
5260 return mmb (index1 (), index2 ());
5261 #elif BOOST_UBLAS_USE_ITERATING
5262 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
5263 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5264 return functor_type::apply (size, it1_begin_, it2_.begin ());
5266 return functor_type::apply (size, it1_.begin (), it2_.begin ());
5269 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
5270 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
5271 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5272 return functor_type::apply (size, it1_begin_, it2_.begin ());
5274 return functor_type::apply (size, it1_.begin (), it2_.begin ());
5277 return mmb (index1 (), index2 ());
5281 // Packed bidirectional specialization
5283 value_type dereference (packed_random_access_iterator_tag) const {
5284 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5285 return functor_type::apply (it1_begin_, it1_end_,
5286 it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
5288 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5289 return functor_type::apply (it1_.begin (), it1_.end (),
5290 it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
5292 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
5293 boost::numeric::ublas::end (it1_, iterator1_tag ()),
5294 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
5295 boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
5300 // Sparse bidirectional specialization
5302 value_type dereference (sparse_bidirectional_iterator_tag) const {
5303 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5304 return functor_type::apply (it1_begin_, it1_end_,
5305 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
5307 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5308 return functor_type::apply (it1_.begin (), it1_.end (),
5309 it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
5311 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
5312 boost::numeric::ublas::end (it1_, iterator1_tag ()),
5313 boost::numeric::ublas::begin (it2_, iterator2_tag ()),
5314 boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
5322 const_iterator2 &operator ++ () {
5327 const_iterator2 &operator -- () {
5332 const_iterator2 &operator += (difference_type n) {
5337 const_iterator2 &operator -= (difference_type n) {
5342 difference_type operator - (const const_iterator2 &it) const {
5343 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5344 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5345 return it2_ - it.it2_;
5350 const_reference operator * () const {
5351 return dereference (iterator_category ());
5354 const_reference operator [] (difference_type n) const {
5355 return *(*this + n);
5358 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5360 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5361 typename self_type::
5363 const_iterator1 begin () const {
5364 return (*this) ().find1 (1, 0, index2 ());
5367 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5368 typename self_type::
5370 const_iterator1 cbegin () const {
5374 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5375 typename self_type::
5377 const_iterator1 end () const {
5378 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
5381 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5382 typename self_type::
5384 const_iterator1 cend () const {
5388 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5389 typename self_type::
5391 const_reverse_iterator1 rbegin () const {
5392 return const_reverse_iterator1 (end ());
5395 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5396 typename self_type::
5398 const_reverse_iterator1 crbegin () const {
5402 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5403 typename self_type::
5405 const_reverse_iterator1 rend () const {
5406 return const_reverse_iterator1 (begin ());
5409 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5410 typename self_type::
5412 const_reverse_iterator1 crend () const {
5419 size_type index1 () const {
5420 return it1_.index1 ();
5423 size_type index2 () const {
5424 return it2_.index2 ();
5429 const_iterator2 &operator = (const const_iterator2 &it) {
5430 container_const_reference<self_type>::assign (&it ());
5433 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5434 it1_begin_ = it.it1_begin_;
5435 it1_end_ = it.it1_end_;
5442 bool operator == (const const_iterator2 &it) const {
5443 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5444 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5445 return it2_ == it.it2_;
5448 bool operator < (const const_iterator2 &it) const {
5449 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
5450 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
5451 return it2_ < it.it2_;
5455 // Mutable due to assignment
5456 /* const */ const_iterator11_type it1_;
5457 const_iterator22_type it2_;
5458 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
5459 /* const */ const_iterator12_type it1_begin_;
5460 /* const */ const_iterator12_type it1_end_;
5466 const_iterator2 begin2 () const {
5467 return find2 (0, 0, 0);
5470 const_iterator2 cbegin2 () const {
5474 const_iterator2 end2 () const {
5475 return find2 (0, 0, size2 ());
5478 const_iterator2 cend2 () const {
5482 // Reverse iterators
5485 const_reverse_iterator1 rbegin1 () const {
5486 return const_reverse_iterator1 (end1 ());
5489 const_reverse_iterator1 crbegin1 () const {
5493 const_reverse_iterator1 rend1 () const {
5494 return const_reverse_iterator1 (begin1 ());
5497 const_reverse_iterator1 crend1 () const {
5502 const_reverse_iterator2 rbegin2 () const {
5503 return const_reverse_iterator2 (end2 ());
5506 const_reverse_iterator2 crbegin2 () const {
5510 const_reverse_iterator2 rend2 () const {
5511 return const_reverse_iterator2 (begin2 ());
5514 const_reverse_iterator2 crend2 () const {
5519 expression1_closure_type e1_;
5520 expression2_closure_type e2_;
5523 template<class T1, class E1, class T2, class E2>
5524 struct matrix_matrix_binary_traits {
5525 typedef unknown_storage_tag storage_category;
5526 typedef unknown_orientation_tag orientation_category;
5527 typedef typename promote_traits<T1, T2>::promote_type promote_type;
5528 typedef matrix_matrix_binary<E1, E2, matrix_matrix_prod<E1, E2, promote_type> > expression_type;
5529 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
5530 typedef expression_type result_type;
5532 typedef typename E1::matrix_temporary_type result_type;
5536 template<class E1, class E2>
5538 typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5539 typename E2::value_type, E2>::result_type
5540 prod (const matrix_expression<E1> &e1,
5541 const matrix_expression<E2> &e2,
5542 unknown_storage_tag,
5543 unknown_orientation_tag) {
5544 typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5545 typename E2::value_type, E2>::expression_type expression_type;
5546 return expression_type (e1 (), e2 ());
5550 template<class E1, class E2>
5552 typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5553 typename E2::value_type, E2>::result_type
5554 prod (const matrix_expression<E1> &e1,
5555 const matrix_expression<E2> &e2) {
5556 BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
5557 typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5558 typename E2::value_type, E2>::storage_category storage_category;
5559 typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
5560 typename E2::value_type, E2>::orientation_category orientation_category;
5561 return prod (e1, e2, storage_category (), orientation_category ());
5564 template<class E1, class E2>
5566 typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5567 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
5568 prec_prod (const matrix_expression<E1> &e1,
5569 const matrix_expression<E2> &e2,
5570 unknown_storage_tag,
5571 unknown_orientation_tag) {
5572 typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5573 typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
5574 return expression_type (e1 (), e2 ());
5578 template<class E1, class E2>
5580 typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5581 typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
5582 prec_prod (const matrix_expression<E1> &e1,
5583 const matrix_expression<E2> &e2) {
5584 BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
5585 typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5586 typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
5587 typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
5588 typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
5589 return prec_prod (e1, e2, storage_category (), orientation_category ());
5592 template<class M, class E1, class E2>
5595 prod (const matrix_expression<E1> &e1,
5596 const matrix_expression<E2> &e2,
5598 return m.assign (prod (e1, e2));
5601 template<class M, class E1, class E2>
5604 prec_prod (const matrix_expression<E1> &e1,
5605 const matrix_expression<E2> &e2,
5607 return m.assign (prec_prod (e1, e2));
5610 template<class M, class E1, class E2>
5613 prod (const matrix_expression<E1> &e1,
5614 const matrix_expression<E2> &e2) {
5615 return M (prod (e1, e2));
5618 template<class M, class E1, class E2>
5621 prec_prod (const matrix_expression<E1> &e1,
5622 const matrix_expression<E2> &e2) {
5623 return M (prec_prod (e1, e2));
5626 template<class E, class F>
5627 class matrix_scalar_unary:
5628 public scalar_expression<matrix_scalar_unary<E, F> > {
5630 typedef E expression_type;
5631 typedef F functor_type;
5632 typedef typename F::result_type value_type;
5633 typedef typename E::const_closure_type expression_closure_type;
5635 // Construction and destruction
5637 explicit matrix_scalar_unary (const expression_type &e):
5641 // Expression accessors
5643 const expression_closure_type &expression () const {
5649 operator value_type () const {
5650 return functor_type::apply (e_);
5654 expression_closure_type e_;
5657 template<class E, class F>
5658 struct matrix_scalar_unary_traits {
5659 typedef matrix_scalar_unary<E, F> expression_type;
5660 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
5661 typedef expression_type result_type;
5663 typedef typename F::result_type result_type;
5669 typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::result_type
5670 norm_1 (const matrix_expression<E> &e) {
5671 typedef typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::expression_type expression_type;
5672 return expression_type (e ());
5677 typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::result_type
5678 norm_frobenius (const matrix_expression<E> &e) {
5679 typedef typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::expression_type expression_type;
5680 return expression_type (e ());
5685 typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::result_type
5686 norm_inf (const matrix_expression<E> &e) {
5687 typedef typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::expression_type expression_type;
5688 return expression_type (e ());