Update contrib.
2 // Copyright (c) 2000-2002
3 // Joerg Walter, Mathias Koch
5 // Permission to use, copy, modify, distribute and sell this software
6 // and its documentation for any purpose is hereby granted without fee,
7 // provided that the above copyright notice appear in all copies and
8 // that both that copyright notice and this permission notice appear
9 // in supporting documentation. The authors make no representations
10 // about the suitability of this software for any purpose.
11 // It is provided "as is" without express or implied warranty.
13 // The authors gratefully acknowledge the support of
14 // GeNeSys mbH & Co. KG in producing this work.
17 #ifndef _BOOST_UBLAS_TRIANGULAR_
18 #define _BOOST_UBLAS_TRIANGULAR_
20 #include <boost/numeric/ublas/matrix.hpp>
21 #include <boost/numeric/ublas/detail/temporary.hpp>
22 #include <boost/type_traits/remove_const.hpp>
24 // Iterators based on ideas of Jeremy Siek
26 namespace boost { namespace numeric { namespace ublas {
28 // Array based triangular matrix class
29 template<class T, class TRI, class L, class A>
30 class triangular_matrix:
31 public matrix_container<triangular_matrix<T, TRI, L, A> > {
34 typedef TRI triangular_type;
35 typedef L layout_type;
36 typedef triangular_matrix<T, TRI, L, A> self_type;
38 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
39 using matrix_container<self_type>::operator ();
41 typedef typename A::size_type size_type;
42 typedef typename A::difference_type difference_type;
44 typedef const T &const_reference;
48 typedef const matrix_reference<const self_type> const_closure_type;
49 typedef matrix_reference<self_type> closure_type;
50 typedef vector<T, A> vector_temporary_type;
51 typedef matrix<T, L, A> matrix_temporary_type; // general sub-matrix
52 typedef packed_tag storage_category;
53 typedef typename L::orientation_category orientation_category;
55 // Construction and destruction
58 matrix_container<self_type> (),
59 size1_ (0), size2_ (0), data_ (0) {}
61 triangular_matrix (size_type size1, size_type size2):
62 matrix_container<self_type> (),
63 size1_ (size1), size2_ (size2), data_ (triangular_type::packed_size (layout_type (), size1, size2)) {
66 triangular_matrix (size_type size1, size_type size2, const array_type &data):
67 matrix_container<self_type> (),
68 size1_ (size1), size2_ (size2), data_ (data) {}
70 triangular_matrix (const triangular_matrix &m):
71 matrix_container<self_type> (),
72 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
75 triangular_matrix (const matrix_expression<AE> &ae):
76 matrix_container<self_type> (),
77 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()),
78 data_ (triangular_type::packed_size (layout_type (), size1_, size2_)) {
79 matrix_assign<scalar_assign> (*this, ae);
84 size_type size1 () const {
88 size_type size2 () const {
94 const array_type &data () const {
104 void resize (size_type size1, size_type size2, bool preserve = true) {
106 self_type temporary (size1, size2);
107 detail::matrix_resize_preserve<layout_type> (*this, temporary);
110 data ().resize (triangular_type::packed_size (layout_type (), size1, size2));
116 void resize_packed_preserve (size_type size1, size_type size2) {
119 data ().resize (triangular_type::packed_size (layout_type (), size1_, size2_), value_type ());
124 const_reference operator () (size_type i, size_type j) const {
125 BOOST_UBLAS_CHECK (i < size1_, bad_index ());
126 BOOST_UBLAS_CHECK (j < size2_, bad_index ());
127 if (triangular_type::other (i, j))
128 return data () [triangular_type::element (layout_type (), i, size1_, j, size2_)];
129 else if (triangular_type::one (i, j))
135 reference at_element (size_type i, size_type j) {
136 BOOST_UBLAS_CHECK (i < size1_, bad_index ());
137 BOOST_UBLAS_CHECK (j < size2_, bad_index ());
138 return data () [triangular_type::element (layout_type (), i, size1_, j, size2_)];
141 reference operator () (size_type i, size_type j) {
142 BOOST_UBLAS_CHECK (i < size1_, bad_index ());
143 BOOST_UBLAS_CHECK (j < size2_, bad_index ());
144 if (triangular_type::other (i, j))
145 return data () [triangular_type::element (layout_type (), i, size1_, j, size2_)];
147 bad_index ().raise ();
148 // arbitary return value
149 return const_cast<reference>(zero_);
153 // Element assignment
155 reference insert_element (size_type i, size_type j, const_reference t) {
156 return (operator () (i, j) = t);
159 void erase_element (size_type i, size_type j) {
160 operator () (i, j) = value_type/*zero*/();
167 std::fill (data ().begin (), data ().end (), value_type/*zero*/());
172 triangular_matrix &operator = (const triangular_matrix &m) {
179 triangular_matrix &assign_temporary (triangular_matrix &m) {
185 triangular_matrix &operator = (const matrix_expression<AE> &ae) {
186 self_type temporary (ae);
187 return assign_temporary (temporary);
191 triangular_matrix &assign (const matrix_expression<AE> &ae) {
192 matrix_assign<scalar_assign> (*this, ae);
197 triangular_matrix& operator += (const matrix_expression<AE> &ae) {
198 self_type temporary (*this + ae);
199 return assign_temporary (temporary);
203 triangular_matrix &plus_assign (const matrix_expression<AE> &ae) {
204 matrix_assign<scalar_plus_assign> (*this, ae);
209 triangular_matrix& operator -= (const matrix_expression<AE> &ae) {
210 self_type temporary (*this - ae);
211 return assign_temporary (temporary);
215 triangular_matrix &minus_assign (const matrix_expression<AE> &ae) {
216 matrix_assign<scalar_minus_assign> (*this, ae);
221 triangular_matrix& operator *= (const AT &at) {
222 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
227 triangular_matrix& operator /= (const AT &at) {
228 matrix_assign_scalar<scalar_divides_assign> (*this, at);
234 void swap (triangular_matrix &m) {
236 // BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ());
237 std::swap (size1_, m.size1_);
238 std::swap (size2_, m.size2_);
239 data ().swap (m.data ());
243 friend void swap (triangular_matrix &m1, triangular_matrix &m2) {
248 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
249 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
250 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
251 typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
252 typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
254 class const_iterator1;
256 class const_iterator2;
259 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
260 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
261 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
262 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
266 const_iterator1 find1 (int rank, size_type i, size_type j) const {
268 i = triangular_type::restrict1 (i, j);
269 return const_iterator1 (*this, i, j);
272 iterator1 find1 (int rank, size_type i, size_type j) {
274 i = triangular_type::mutable_restrict1 (i, j);
275 return iterator1 (*this, i, j);
278 const_iterator2 find2 (int rank, size_type i, size_type j) const {
280 j = triangular_type::restrict2 (i, j);
281 return const_iterator2 (*this, i, j);
284 iterator2 find2 (int rank, size_type i, size_type j) {
286 j = triangular_type::mutable_restrict2 (i, j);
287 return iterator2 (*this, i, j);
290 // Iterators simply are indices.
292 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
293 class const_iterator1:
294 public container_const_reference<triangular_matrix>,
295 public random_access_iterator_base<packed_random_access_iterator_tag,
296 const_iterator1, value_type> {
298 typedef typename triangular_matrix::value_type value_type;
299 typedef typename triangular_matrix::difference_type difference_type;
300 typedef typename triangular_matrix::const_reference reference;
301 typedef const typename triangular_matrix::pointer pointer;
303 typedef const_iterator2 dual_iterator_type;
304 typedef const_reverse_iterator2 dual_reverse_iterator_type;
306 // Construction and destruction
309 container_const_reference<self_type> (), it1_ (), it2_ () {}
311 const_iterator1 (const self_type &m, size_type it1, size_type it2):
312 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
314 const_iterator1 (const iterator1 &it):
315 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
319 const_iterator1 &operator ++ () {
324 const_iterator1 &operator -- () {
329 const_iterator1 &operator += (difference_type n) {
334 const_iterator1 &operator -= (difference_type n) {
339 difference_type operator - (const const_iterator1 &it) const {
340 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
341 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
342 return it1_ - it.it1_;
347 const_reference operator * () const {
348 return (*this) () (it1_, it2_);
351 const_reference operator [] (difference_type n) const {
355 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
357 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
360 const_iterator2 begin () const {
361 return (*this) ().find2 (1, it1_, 0);
364 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
367 const_iterator2 end () const {
368 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
371 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
374 const_reverse_iterator2 rbegin () const {
375 return const_reverse_iterator2 (end ());
378 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
381 const_reverse_iterator2 rend () const {
382 return const_reverse_iterator2 (begin ());
388 size_type index1 () const {
392 size_type index2 () const {
398 const_iterator1 &operator = (const const_iterator1 &it) {
399 container_const_reference<self_type>::assign (&it ());
407 bool operator == (const const_iterator1 &it) const {
408 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
409 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
410 return it1_ == it.it1_;
413 bool operator < (const const_iterator1 &it) const {
414 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
415 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
416 return it1_ < it.it1_;
426 const_iterator1 begin1 () const {
427 return find1 (0, 0, 0);
430 const_iterator1 end1 () const {
431 return find1 (0, size1_, 0);
434 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
436 public container_reference<triangular_matrix>,
437 public random_access_iterator_base<packed_random_access_iterator_tag,
438 iterator1, value_type> {
440 typedef typename triangular_matrix::value_type value_type;
441 typedef typename triangular_matrix::difference_type difference_type;
442 typedef typename triangular_matrix::reference reference;
443 typedef typename triangular_matrix::pointer pointer;
445 typedef iterator2 dual_iterator_type;
446 typedef reverse_iterator2 dual_reverse_iterator_type;
448 // Construction and destruction
451 container_reference<self_type> (), it1_ (), it2_ () {}
453 iterator1 (self_type &m, size_type it1, size_type it2):
454 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
458 iterator1 &operator ++ () {
463 iterator1 &operator -- () {
468 iterator1 &operator += (difference_type n) {
473 iterator1 &operator -= (difference_type n) {
478 difference_type operator - (const iterator1 &it) const {
479 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
480 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
481 return it1_ - it.it1_;
486 reference operator * () const {
487 return (*this) () (it1_, it2_);
490 reference operator [] (difference_type n) const {
494 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
496 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
499 iterator2 begin () const {
500 return (*this) ().find2 (1, it1_, 0);
503 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
506 iterator2 end () const {
507 return (*this) ().find2 (1, it1_, (*this) ().size2 ());
510 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
513 reverse_iterator2 rbegin () const {
514 return reverse_iterator2 (end ());
517 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
520 reverse_iterator2 rend () const {
521 return reverse_iterator2 (begin ());
527 size_type index1 () const {
531 size_type index2 () const {
537 iterator1 &operator = (const iterator1 &it) {
538 container_reference<self_type>::assign (&it ());
546 bool operator == (const iterator1 &it) const {
547 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
548 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
549 return it1_ == it.it1_;
552 bool operator < (const iterator1 &it) const {
553 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
554 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
555 return it1_ < it.it1_;
562 friend class const_iterator1;
567 iterator1 begin1 () {
568 return find1 (0, 0, 0);
572 return find1 (0, size1_, 0);
575 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
576 class const_iterator2:
577 public container_const_reference<triangular_matrix>,
578 public random_access_iterator_base<packed_random_access_iterator_tag,
579 const_iterator2, value_type> {
581 typedef typename triangular_matrix::value_type value_type;
582 typedef typename triangular_matrix::difference_type difference_type;
583 typedef typename triangular_matrix::const_reference reference;
584 typedef const typename triangular_matrix::pointer pointer;
586 typedef const_iterator1 dual_iterator_type;
587 typedef const_reverse_iterator1 dual_reverse_iterator_type;
589 // Construction and destruction
592 container_const_reference<self_type> (), it1_ (), it2_ () {}
594 const_iterator2 (const self_type &m, size_type it1, size_type it2):
595 container_const_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
597 const_iterator2 (const iterator2 &it):
598 container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
602 const_iterator2 &operator ++ () {
607 const_iterator2 &operator -- () {
612 const_iterator2 &operator += (difference_type n) {
617 const_iterator2 &operator -= (difference_type n) {
622 difference_type operator - (const const_iterator2 &it) const {
623 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
624 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
625 return it2_ - it.it2_;
630 const_reference operator * () const {
631 return (*this) () (it1_, it2_);
634 const_reference operator [] (difference_type n) const {
638 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
640 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
643 const_iterator1 begin () const {
644 return (*this) ().find1 (1, 0, it2_);
647 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
650 const_iterator1 end () const {
651 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
654 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
657 const_reverse_iterator1 rbegin () const {
658 return const_reverse_iterator1 (end ());
661 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
664 const_reverse_iterator1 rend () const {
665 return const_reverse_iterator1 (begin ());
671 size_type index1 () const {
675 size_type index2 () const {
681 const_iterator2 &operator = (const const_iterator2 &it) {
682 container_const_reference<self_type>::assign (&it ());
690 bool operator == (const const_iterator2 &it) const {
691 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
692 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
693 return it2_ == it.it2_;
696 bool operator < (const const_iterator2 &it) const {
697 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
698 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
699 return it2_ < it.it2_;
709 const_iterator2 begin2 () const {
710 return find2 (0, 0, 0);
713 const_iterator2 end2 () const {
714 return find2 (0, 0, size2_);
717 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
719 public container_reference<triangular_matrix>,
720 public random_access_iterator_base<packed_random_access_iterator_tag,
721 iterator2, value_type> {
723 typedef typename triangular_matrix::value_type value_type;
724 typedef typename triangular_matrix::difference_type difference_type;
725 typedef typename triangular_matrix::reference reference;
726 typedef typename triangular_matrix::pointer pointer;
728 typedef iterator1 dual_iterator_type;
729 typedef reverse_iterator1 dual_reverse_iterator_type;
731 // Construction and destruction
734 container_reference<self_type> (), it1_ (), it2_ () {}
736 iterator2 (self_type &m, size_type it1, size_type it2):
737 container_reference<self_type> (m), it1_ (it1), it2_ (it2) {}
741 iterator2 &operator ++ () {
746 iterator2 &operator -- () {
751 iterator2 &operator += (difference_type n) {
756 iterator2 &operator -= (difference_type n) {
761 difference_type operator - (const iterator2 &it) const {
762 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
763 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
764 return it2_ - it.it2_;
769 reference operator * () const {
770 return (*this) () (it1_, it2_);
773 reference operator [] (difference_type n) const {
777 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
779 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
782 iterator1 begin () const {
783 return (*this) ().find1 (1, 0, it2_);
786 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
789 iterator1 end () const {
790 return (*this) ().find1 (1, (*this) ().size1 (), it2_);
793 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
796 reverse_iterator1 rbegin () const {
797 return reverse_iterator1 (end ());
800 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
803 reverse_iterator1 rend () const {
804 return reverse_iterator1 (begin ());
810 size_type index1 () const {
814 size_type index2 () const {
820 iterator2 &operator = (const iterator2 &it) {
821 container_reference<self_type>::assign (&it ());
829 bool operator == (const iterator2 &it) const {
830 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
831 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
832 return it2_ == it.it2_;
835 bool operator < (const iterator2 &it) const {
836 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
837 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
838 return it2_ < it.it2_;
845 friend class const_iterator2;
850 iterator2 begin2 () {
851 return find2 (0, 0, 0);
855 return find2 (0, 0, size2_);
861 const_reverse_iterator1 rbegin1 () const {
862 return const_reverse_iterator1 (end1 ());
865 const_reverse_iterator1 rend1 () const {
866 return const_reverse_iterator1 (begin1 ());
870 reverse_iterator1 rbegin1 () {
871 return reverse_iterator1 (end1 ());
874 reverse_iterator1 rend1 () {
875 return reverse_iterator1 (begin1 ());
879 const_reverse_iterator2 rbegin2 () const {
880 return const_reverse_iterator2 (end2 ());
883 const_reverse_iterator2 rend2 () const {
884 return const_reverse_iterator2 (begin2 ());
888 reverse_iterator2 rbegin2 () {
889 return reverse_iterator2 (end2 ());
892 reverse_iterator2 rend2 () {
893 return reverse_iterator2 (begin2 ());
900 static const value_type zero_;
901 static const value_type one_;
904 template<class T, class TRI, class L, class A>
905 const typename triangular_matrix<T, TRI, L, A>::value_type triangular_matrix<T, TRI, L, A>::zero_ = value_type/*zero*/();
906 template<class T, class TRI, class L, class A>
907 const typename triangular_matrix<T, TRI, L, A>::value_type triangular_matrix<T, TRI, L, A>::one_ (1);
910 // Triangular matrix adaptor class
911 template<class M, class TRI>
912 class triangular_adaptor:
913 public matrix_expression<triangular_adaptor<M, TRI> > {
915 typedef triangular_adaptor<M, TRI> self_type;
918 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
919 using matrix_expression<self_type>::operator ();
921 typedef const M const_matrix_type;
922 typedef M matrix_type;
923 typedef TRI triangular_type;
924 typedef typename M::size_type size_type;
925 typedef typename M::difference_type difference_type;
926 typedef typename M::value_type value_type;
927 typedef typename M::const_reference const_reference;
928 typedef typename boost::mpl::if_<boost::is_const<M>,
929 typename M::const_reference,
930 typename M::reference>::type reference;
931 typedef typename boost::mpl::if_<boost::is_const<M>,
932 typename M::const_closure_type,
933 typename M::closure_type>::type matrix_closure_type;
934 typedef const self_type const_closure_type;
935 typedef self_type closure_type;
936 // Replaced by _temporary_traits to avoid type requirements on M
937 //typedef typename M::vector_temporary_type vector_temporary_type;
938 //typedef typename M::matrix_temporary_type matrix_temporary_type;
939 typedef typename storage_restrict_traits<typename M::storage_category,
940 packed_proxy_tag>::storage_category storage_category;
941 typedef typename M::orientation_category orientation_category;
943 // Construction and destruction
945 triangular_adaptor (matrix_type &data):
946 matrix_expression<self_type> (),
949 triangular_adaptor (const triangular_adaptor &m):
950 matrix_expression<self_type> (),
955 size_type size1 () const {
956 return data_.size1 ();
959 size_type size2 () const {
960 return data_.size2 ();
965 const matrix_closure_type &data () const {
969 matrix_closure_type &data () {
974 #ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
976 const_reference operator () (size_type i, size_type j) const {
977 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
978 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
979 if (triangular_type::other (i, j))
980 return data () (i, j);
981 else if (triangular_type::one (i, j))
987 reference operator () (size_type i, size_type j) {
988 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
989 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
990 if (triangular_type::other (i, j))
991 return data () (i, j);
992 else if (triangular_type::one (i, j)) {
993 bad_index ().raise ();
994 // arbitary return value
995 return const_cast<reference>(one_);
997 bad_index ().raise ();
998 // arbitary return value
999 return const_cast<reference>(zero_);
1004 reference operator () (size_type i, size_type j) const {
1005 BOOST_UBLAS_CHECK (i < size1 (), bad_index ());
1006 BOOST_UBLAS_CHECK (j < size2 (), bad_index ());
1007 if (triangular_type::other (i, j))
1008 return data () (i, j);
1009 else if (triangular_type::one (i, j)) {
1010 bad_index ().raise ();
1011 // arbitary return value
1012 return const_cast<reference>(one_);
1014 bad_index ().raise ();
1015 // arbitary return value
1016 return const_cast<reference>(zero_);
1023 triangular_adaptor &operator = (const triangular_adaptor &m) {
1024 matrix_assign<scalar_assign> (*this, m);
1028 triangular_adaptor &assign_temporary (triangular_adaptor &m) {
1034 triangular_adaptor &operator = (const matrix_expression<AE> &ae) {
1035 matrix_assign<scalar_assign> (*this, matrix<value_type> (ae));
1040 triangular_adaptor &assign (const matrix_expression<AE> &ae) {
1041 matrix_assign<scalar_assign> (*this, ae);
1046 triangular_adaptor& operator += (const matrix_expression<AE> &ae) {
1047 matrix_assign<scalar_assign> (*this, matrix<value_type> (*this + ae));
1052 triangular_adaptor &plus_assign (const matrix_expression<AE> &ae) {
1053 matrix_assign<scalar_plus_assign> (*this, ae);
1058 triangular_adaptor& operator -= (const matrix_expression<AE> &ae) {
1059 matrix_assign<scalar_assign> (*this, matrix<value_type> (*this - ae));
1064 triangular_adaptor &minus_assign (const matrix_expression<AE> &ae) {
1065 matrix_assign<scalar_minus_assign> (*this, ae);
1070 triangular_adaptor& operator *= (const AT &at) {
1071 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
1076 triangular_adaptor& operator /= (const AT &at) {
1077 matrix_assign_scalar<scalar_divides_assign> (*this, at);
1081 // Closure comparison
1083 bool same_closure (const triangular_adaptor &ta) const {
1084 return (*this).data ().same_closure (ta.data ());
1089 void swap (triangular_adaptor &m) {
1091 matrix_swap<scalar_swap> (*this, m);
1094 friend void swap (triangular_adaptor &m1, triangular_adaptor &m2) {
1100 typedef typename M::const_iterator1 const_subiterator1_type;
1101 typedef typename boost::mpl::if_<boost::is_const<M>,
1102 typename M::const_iterator1,
1103 typename M::iterator1>::type subiterator1_type;
1104 typedef typename M::const_iterator2 const_subiterator2_type;
1105 typedef typename boost::mpl::if_<boost::is_const<M>,
1106 typename M::const_iterator2,
1107 typename M::iterator2>::type subiterator2_type;
1110 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1111 typedef indexed_iterator1<self_type, packed_random_access_iterator_tag> iterator1;
1112 typedef indexed_iterator2<self_type, packed_random_access_iterator_tag> iterator2;
1113 typedef indexed_const_iterator1<self_type, packed_random_access_iterator_tag> const_iterator1;
1114 typedef indexed_const_iterator2<self_type, packed_random_access_iterator_tag> const_iterator2;
1116 class const_iterator1;
1118 class const_iterator2;
1121 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1122 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
1123 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1124 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
1128 const_iterator1 find1 (int rank, size_type i, size_type j) const {
1130 i = triangular_type::restrict1 (i, j);
1131 return const_iterator1 (*this, data ().find1 (rank, i, j));
1134 iterator1 find1 (int rank, size_type i, size_type j) {
1136 i = triangular_type::mutable_restrict1 (i, j);
1137 return iterator1 (*this, data ().find1 (rank, i, j));
1140 const_iterator2 find2 (int rank, size_type i, size_type j) const {
1142 j = triangular_type::restrict2 (i, j);
1143 return const_iterator2 (*this, data ().find2 (rank, i, j));
1146 iterator2 find2 (int rank, size_type i, size_type j) {
1148 j = triangular_type::mutable_restrict2 (i, j);
1149 return iterator2 (*this, data ().find2 (rank, i, j));
1152 // Iterators simply are indices.
1154 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1155 class const_iterator1:
1156 public container_const_reference<triangular_adaptor>,
1157 public random_access_iterator_base<typename iterator_restrict_traits<
1158 typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1159 const_iterator1, value_type> {
1161 typedef typename const_subiterator1_type::value_type value_type;
1162 typedef typename const_subiterator1_type::difference_type difference_type;
1163 typedef typename const_subiterator1_type::reference reference;
1164 typedef typename const_subiterator1_type::pointer pointer;
1166 typedef const_iterator2 dual_iterator_type;
1167 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1169 // Construction and destruction
1172 container_const_reference<self_type> (), it1_ () {}
1174 const_iterator1 (const self_type &m, const const_subiterator1_type &it1):
1175 container_const_reference<self_type> (m), it1_ (it1) {}
1177 const_iterator1 (const iterator1 &it):
1178 container_const_reference<self_type> (it ()), it1_ (it.it1_) {}
1182 const_iterator1 &operator ++ () {
1187 const_iterator1 &operator -- () {
1192 const_iterator1 &operator += (difference_type n) {
1197 const_iterator1 &operator -= (difference_type n) {
1202 difference_type operator - (const const_iterator1 &it) const {
1203 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1204 return it1_ - it.it1_;
1209 const_reference operator * () const {
1210 size_type i = index1 ();
1211 size_type j = index2 ();
1212 BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
1213 BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
1214 if (triangular_type::other (i, j))
1217 return (*this) () (i, j);
1220 const_reference operator [] (difference_type n) const {
1221 return *(*this + n);
1224 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1226 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1227 typename self_type::
1229 const_iterator2 begin () const {
1230 return (*this) ().find2 (1, index1 (), 0);
1233 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1234 typename self_type::
1236 const_iterator2 end () const {
1237 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1240 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1241 typename self_type::
1243 const_reverse_iterator2 rbegin () const {
1244 return const_reverse_iterator2 (end ());
1247 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1248 typename self_type::
1250 const_reverse_iterator2 rend () const {
1251 return const_reverse_iterator2 (begin ());
1257 size_type index1 () const {
1258 return it1_.index1 ();
1261 size_type index2 () const {
1262 return it1_.index2 ();
1267 const_iterator1 &operator = (const const_iterator1 &it) {
1268 container_const_reference<self_type>::assign (&it ());
1275 bool operator == (const const_iterator1 &it) const {
1276 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1277 return it1_ == it.it1_;
1280 bool operator < (const const_iterator1 &it) const {
1281 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1282 return it1_ < it.it1_;
1286 const_subiterator1_type it1_;
1291 const_iterator1 begin1 () const {
1292 return find1 (0, 0, 0);
1295 const_iterator1 end1 () const {
1296 return find1 (0, size1 (), 0);
1299 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1301 public container_reference<triangular_adaptor>,
1302 public random_access_iterator_base<typename iterator_restrict_traits<
1303 typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1304 iterator1, value_type> {
1306 typedef typename subiterator1_type::value_type value_type;
1307 typedef typename subiterator1_type::difference_type difference_type;
1308 typedef typename subiterator1_type::reference reference;
1309 typedef typename subiterator1_type::pointer pointer;
1311 typedef iterator2 dual_iterator_type;
1312 typedef reverse_iterator2 dual_reverse_iterator_type;
1314 // Construction and destruction
1317 container_reference<self_type> (), it1_ () {}
1319 iterator1 (self_type &m, const subiterator1_type &it1):
1320 container_reference<self_type> (m), it1_ (it1) {}
1324 iterator1 &operator ++ () {
1329 iterator1 &operator -- () {
1334 iterator1 &operator += (difference_type n) {
1339 iterator1 &operator -= (difference_type n) {
1344 difference_type operator - (const iterator1 &it) const {
1345 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1346 return it1_ - it.it1_;
1351 reference operator * () const {
1352 size_type i = index1 ();
1353 size_type j = index2 ();
1354 BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
1355 BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
1356 if (triangular_type::other (i, j))
1359 return (*this) () (i, j);
1362 reference operator [] (difference_type n) const {
1363 return *(*this + n);
1366 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1368 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1369 typename self_type::
1371 iterator2 begin () const {
1372 return (*this) ().find2 (1, index1 (), 0);
1375 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1376 typename self_type::
1378 iterator2 end () const {
1379 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
1382 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1383 typename self_type::
1385 reverse_iterator2 rbegin () const {
1386 return reverse_iterator2 (end ());
1389 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1390 typename self_type::
1392 reverse_iterator2 rend () const {
1393 return reverse_iterator2 (begin ());
1399 size_type index1 () const {
1400 return it1_.index1 ();
1403 size_type index2 () const {
1404 return it1_.index2 ();
1409 iterator1 &operator = (const iterator1 &it) {
1410 container_reference<self_type>::assign (&it ());
1417 bool operator == (const iterator1 &it) const {
1418 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1419 return it1_ == it.it1_;
1422 bool operator < (const iterator1 &it) const {
1423 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1424 return it1_ < it.it1_;
1428 subiterator1_type it1_;
1430 friend class const_iterator1;
1435 iterator1 begin1 () {
1436 return find1 (0, 0, 0);
1440 return find1 (0, size1 (), 0);
1443 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1444 class const_iterator2:
1445 public container_const_reference<triangular_adaptor>,
1446 public random_access_iterator_base<typename iterator_restrict_traits<
1447 typename const_subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1448 const_iterator2, value_type> {
1450 typedef typename const_subiterator2_type::value_type value_type;
1451 typedef typename const_subiterator2_type::difference_type difference_type;
1452 typedef typename const_subiterator2_type::reference reference;
1453 typedef typename const_subiterator2_type::pointer pointer;
1455 typedef const_iterator1 dual_iterator_type;
1456 typedef const_reverse_iterator1 dual_reverse_iterator_type;
1458 // Construction and destruction
1461 container_const_reference<self_type> (), it2_ () {}
1463 const_iterator2 (const self_type &m, const const_subiterator2_type &it2):
1464 container_const_reference<self_type> (m), it2_ (it2) {}
1466 const_iterator2 (const iterator2 &it):
1467 container_const_reference<self_type> (it ()), it2_ (it.it2_) {}
1471 const_iterator2 &operator ++ () {
1476 const_iterator2 &operator -- () {
1481 const_iterator2 &operator += (difference_type n) {
1486 const_iterator2 &operator -= (difference_type n) {
1491 difference_type operator - (const const_iterator2 &it) const {
1492 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1493 return it2_ - it.it2_;
1498 const_reference operator * () const {
1499 size_type i = index1 ();
1500 size_type j = index2 ();
1501 BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
1502 BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
1503 if (triangular_type::other (i, j))
1506 return (*this) () (i, j);
1509 const_reference operator [] (difference_type n) const {
1510 return *(*this + n);
1513 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1515 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1516 typename self_type::
1518 const_iterator1 begin () const {
1519 return (*this) ().find1 (1, 0, index2 ());
1522 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1523 typename self_type::
1525 const_iterator1 end () const {
1526 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1529 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1530 typename self_type::
1532 const_reverse_iterator1 rbegin () const {
1533 return const_reverse_iterator1 (end ());
1536 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1537 typename self_type::
1539 const_reverse_iterator1 rend () const {
1540 return const_reverse_iterator1 (begin ());
1546 size_type index1 () const {
1547 return it2_.index1 ();
1550 size_type index2 () const {
1551 return it2_.index2 ();
1556 const_iterator2 &operator = (const const_iterator2 &it) {
1557 container_const_reference<self_type>::assign (&it ());
1564 bool operator == (const const_iterator2 &it) const {
1565 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1566 return it2_ == it.it2_;
1569 bool operator < (const const_iterator2 &it) const {
1570 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1571 return it2_ < it.it2_;
1575 const_subiterator2_type it2_;
1580 const_iterator2 begin2 () const {
1581 return find2 (0, 0, 0);
1584 const_iterator2 end2 () const {
1585 return find2 (0, 0, size2 ());
1588 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1590 public container_reference<triangular_adaptor>,
1591 public random_access_iterator_base<typename iterator_restrict_traits<
1592 typename subiterator1_type::iterator_category, packed_random_access_iterator_tag>::iterator_category,
1593 iterator2, value_type> {
1595 typedef typename subiterator2_type::value_type value_type;
1596 typedef typename subiterator2_type::difference_type difference_type;
1597 typedef typename subiterator2_type::reference reference;
1598 typedef typename subiterator2_type::pointer pointer;
1600 typedef iterator1 dual_iterator_type;
1601 typedef reverse_iterator1 dual_reverse_iterator_type;
1603 // Construction and destruction
1606 container_reference<self_type> (), it2_ () {}
1608 iterator2 (self_type &m, const subiterator2_type &it2):
1609 container_reference<self_type> (m), it2_ (it2) {}
1613 iterator2 &operator ++ () {
1618 iterator2 &operator -- () {
1623 iterator2 &operator += (difference_type n) {
1628 iterator2 &operator -= (difference_type n) {
1633 difference_type operator - (const iterator2 &it) const {
1634 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1635 return it2_ - it.it2_;
1640 reference operator * () const {
1641 size_type i = index1 ();
1642 size_type j = index2 ();
1643 BOOST_UBLAS_CHECK (i < (*this) ().size1 (), bad_index ());
1644 BOOST_UBLAS_CHECK (j < (*this) ().size2 (), bad_index ());
1645 if (triangular_type::other (i, j))
1648 return (*this) () (i, j);
1651 reference operator [] (difference_type n) const {
1652 return *(*this + n);
1655 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1657 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1658 typename self_type::
1660 iterator1 begin () const {
1661 return (*this) ().find1 (1, 0, index2 ());
1664 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1665 typename self_type::
1667 iterator1 end () const {
1668 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
1671 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1672 typename self_type::
1674 reverse_iterator1 rbegin () const {
1675 return reverse_iterator1 (end ());
1678 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1679 typename self_type::
1681 reverse_iterator1 rend () const {
1682 return reverse_iterator1 (begin ());
1688 size_type index1 () const {
1689 return it2_.index1 ();
1692 size_type index2 () const {
1693 return it2_.index2 ();
1698 iterator2 &operator = (const iterator2 &it) {
1699 container_reference<self_type>::assign (&it ());
1706 bool operator == (const iterator2 &it) const {
1707 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1708 return it2_ == it.it2_;
1711 bool operator < (const iterator2 &it) const {
1712 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1713 return it2_ < it.it2_;
1717 subiterator2_type it2_;
1719 friend class const_iterator2;
1724 iterator2 begin2 () {
1725 return find2 (0, 0, 0);
1729 return find2 (0, 0, size2 ());
1732 // Reverse iterators
1735 const_reverse_iterator1 rbegin1 () const {
1736 return const_reverse_iterator1 (end1 ());
1739 const_reverse_iterator1 rend1 () const {
1740 return const_reverse_iterator1 (begin1 ());
1744 reverse_iterator1 rbegin1 () {
1745 return reverse_iterator1 (end1 ());
1748 reverse_iterator1 rend1 () {
1749 return reverse_iterator1 (begin1 ());
1753 const_reverse_iterator2 rbegin2 () const {
1754 return const_reverse_iterator2 (end2 ());
1757 const_reverse_iterator2 rend2 () const {
1758 return const_reverse_iterator2 (begin2 ());
1762 reverse_iterator2 rbegin2 () {
1763 return reverse_iterator2 (end2 ());
1766 reverse_iterator2 rend2 () {
1767 return reverse_iterator2 (begin2 ());
1771 matrix_closure_type data_;
1772 static const value_type zero_;
1773 static const value_type one_;
1776 template<class M, class TRI>
1777 const typename triangular_adaptor<M, TRI>::value_type triangular_adaptor<M, TRI>::zero_ = value_type/*zero*/();
1778 template<class M, class TRI>
1779 const typename triangular_adaptor<M, TRI>::value_type triangular_adaptor<M, TRI>::one_ (1);
1781 template <class M, class TRI>
1782 struct vector_temporary_traits< triangular_adaptor<M, TRI> >
1783 : vector_temporary_traits< typename boost::remove_const<M>::type > {} ;
1784 template <class M, class TRI>
1785 struct vector_temporary_traits< const triangular_adaptor<M, TRI> >
1786 : vector_temporary_traits< typename boost::remove_const<M>::type > {} ;
1788 template <class M, class TRI>
1789 struct matrix_temporary_traits< triangular_adaptor<M, TRI> >
1790 : matrix_temporary_traits< typename boost::remove_const<M>::type > {};
1791 template <class M, class TRI>
1792 struct matrix_temporary_traits< const triangular_adaptor<M, TRI> >
1793 : matrix_temporary_traits< typename boost::remove_const<M>::type > {};
1796 template<class E1, class E2>
1797 struct matrix_vector_solve_traits {
1798 typedef typename promote_traits<typename E1::value_type, typename E2::value_type>::promote_type promote_type;
1799 typedef vector<promote_type> result_type;
1803 // n * (n - 1) / 2 + n = n * (n + 1) / 2 multiplications,
1804 // n * (n - 1) / 2 additions
1806 // Dense (proxy) case
1807 template<class E1, class E2>
1809 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1810 lower_tag, column_major_tag, dense_proxy_tag) {
1811 typedef typename E2::size_type size_type;
1812 typedef typename E2::difference_type difference_type;
1813 typedef typename E2::value_type value_type;
1815 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
1816 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
1817 size_type size = e2 ().size ();
1818 for (size_type n = 0; n < size; ++ n) {
1819 #ifndef BOOST_UBLAS_SINGULAR_CHECK
1820 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
1822 if (e1 () (n, n) == value_type/*zero*/())
1823 singular ().raise ();
1825 value_type t = e2 () (n) /= e1 () (n, n);
1826 if (t != value_type/*zero*/()) {
1827 for (size_type m = n + 1; m < size; ++ m)
1828 e2 () (m) -= e1 () (m, n) * t;
1832 // Packed (proxy) case
1833 template<class E1, class E2>
1835 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1836 lower_tag, column_major_tag, packed_proxy_tag) {
1837 typedef typename E2::size_type size_type;
1838 typedef typename E2::difference_type difference_type;
1839 typedef typename E2::value_type value_type;
1841 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
1842 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
1843 size_type size = e2 ().size ();
1844 for (size_type n = 0; n < size; ++ n) {
1845 #ifndef BOOST_UBLAS_SINGULAR_CHECK
1846 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
1848 if (e1 () (n, n) == value_type/*zero*/())
1849 singular ().raise ();
1851 value_type t = e2 () (n) /= e1 () (n, n);
1852 if (t != value_type/*zero*/()) {
1853 typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
1854 typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
1855 difference_type m (it1e1_end - it1e1);
1857 e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
1861 // Sparse (proxy) case
1862 template<class E1, class E2>
1864 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1865 lower_tag, column_major_tag, unknown_storage_tag) {
1866 typedef typename E2::size_type size_type;
1867 typedef typename E2::difference_type difference_type;
1868 typedef typename E2::value_type value_type;
1870 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
1871 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
1872 size_type size = e2 ().size ();
1873 for (size_type n = 0; n < size; ++ n) {
1874 #ifndef BOOST_UBLAS_SINGULAR_CHECK
1875 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
1877 if (e1 () (n, n) == value_type/*zero*/())
1878 singular ().raise ();
1880 value_type t = e2 () (n) /= e1 () (n, n);
1881 if (t != value_type/*zero*/()) {
1882 typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
1883 typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
1884 while (it1e1 != it1e1_end)
1885 e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
1890 template<class E1, class E2>
1892 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1893 lower_tag, column_major_tag) {
1894 typedef typename E1::storage_category storage_category;
1895 inplace_solve (e1, e2,
1896 lower_tag (), column_major_tag (), storage_category ());
1898 template<class E1, class E2>
1900 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1901 lower_tag, row_major_tag) {
1902 typedef typename E1::storage_category storage_category;
1903 inplace_solve (e2, trans (e1),
1904 upper_tag (), row_major_tag (), storage_category ());
1907 template<class E1, class E2>
1909 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1911 typedef typename E1::orientation_category orientation_category;
1912 inplace_solve (e1, e2,
1913 lower_tag (), orientation_category ());
1915 template<class E1, class E2>
1917 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1919 typedef typename E1::orientation_category orientation_category;
1920 inplace_solve (triangular_adaptor<const E1, unit_lower> (e1 ()), e2,
1921 unit_lower_tag (), orientation_category ());
1924 // Dense (proxy) case
1925 template<class E1, class E2>
1927 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1928 upper_tag, column_major_tag, dense_proxy_tag) {
1929 typedef typename E2::size_type size_type;
1930 typedef typename E2::difference_type difference_type;
1931 typedef typename E2::value_type value_type;
1933 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
1934 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
1935 size_type size = e2 ().size ();
1936 for (difference_type n = size - 1; n >= 0; -- n) {
1937 #ifndef BOOST_UBLAS_SINGULAR_CHECK
1938 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
1940 if (e1 () (n, n) == value_type/*zero*/())
1941 singular ().raise ();
1943 value_type t = e2 () (n) /= e1 () (n, n);
1944 if (t != value_type/*zero*/()) {
1945 for (difference_type m = n - 1; m >= 0; -- m)
1946 e2 () (m) -= e1 () (m, n) * t;
1950 // Packed (proxy) case
1951 template<class E1, class E2>
1953 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1954 upper_tag, column_major_tag, packed_proxy_tag) {
1955 typedef typename E2::size_type size_type;
1956 typedef typename E2::difference_type difference_type;
1957 typedef typename E2::value_type value_type;
1959 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
1960 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
1961 size_type size = e2 ().size ();
1962 for (difference_type n = size - 1; n >= 0; -- n) {
1963 #ifndef BOOST_UBLAS_SINGULAR_CHECK
1964 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
1966 if (e1 () (n, n) == value_type/*zero*/())
1967 singular ().raise ();
1969 value_type t = e2 () (n) /= e1 () (n, n);
1970 if (t != value_type/*zero*/()) {
1971 typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
1972 typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
1973 difference_type m (it1e1_rend - it1e1);
1975 e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
1979 // Sparse (proxy) case
1980 template<class E1, class E2>
1982 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
1983 upper_tag, column_major_tag, unknown_storage_tag) {
1984 typedef typename E2::size_type size_type;
1985 typedef typename E2::difference_type difference_type;
1986 typedef typename E2::value_type value_type;
1988 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
1989 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size (), bad_size ());
1990 size_type size = e2 ().size ();
1991 for (difference_type n = size - 1; n >= 0; -- n) {
1992 #ifndef BOOST_UBLAS_SINGULAR_CHECK
1993 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
1995 if (e1 () (n, n) == value_type/*zero*/())
1996 singular ().raise ();
1998 value_type t = e2 () (n) /= e1 () (n, n);
1999 if (t != value_type/*zero*/()) {
2000 typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
2001 typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
2002 while (it1e1 != it1e1_rend)
2003 e2 () (it1e1.index1 ()) -= *it1e1 * t, ++ it1e1;
2008 template<class E1, class E2>
2010 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
2011 upper_tag, column_major_tag) {
2012 typedef typename E1::storage_category storage_category;
2013 inplace_solve (e1, e2,
2014 upper_tag (), column_major_tag (), storage_category ());
2016 template<class E1, class E2>
2018 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
2019 upper_tag, row_major_tag) {
2020 typedef typename E1::storage_category storage_category;
2021 inplace_solve (e2, trans (e1),
2022 lower_tag (), row_major_tag (), storage_category ());
2025 template<class E1, class E2>
2027 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
2029 typedef typename E1::orientation_category orientation_category;
2030 inplace_solve (e1, e2,
2031 upper_tag (), orientation_category ());
2033 template<class E1, class E2>
2035 void inplace_solve (const matrix_expression<E1> &e1, vector_expression<E2> &e2,
2037 typedef typename E1::orientation_category orientation_category;
2038 inplace_solve (triangular_adaptor<const E1, unit_upper> (e1 ()), e2,
2039 unit_upper_tag (), orientation_category ());
2042 template<class E1, class E2, class C>
2044 typename matrix_vector_solve_traits<E1, E2>::result_type
2045 solve (const matrix_expression<E1> &e1,
2046 const vector_expression<E2> &e2,
2048 typename matrix_vector_solve_traits<E1, E2>::result_type r (e2);
2049 inplace_solve (e1, r, C ());
2053 // Dense (proxy) case
2054 template<class E1, class E2>
2056 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2057 lower_tag, row_major_tag, dense_proxy_tag) {
2058 typedef typename E1::size_type size_type;
2059 typedef typename E1::difference_type difference_type;
2060 typedef typename E1::value_type value_type;
2062 BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
2063 BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
2064 size_type size = e1 ().size ();
2065 for (difference_type n = size - 1; n >= 0; -- n) {
2066 #ifndef BOOST_UBLAS_SINGULAR_CHECK
2067 BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
2069 if (e2 () (n, n) == value_type/*zero*/())
2070 singular ().raise ();
2072 value_type t = e1 () (n) /= e2 () (n, n);
2073 if (t != value_type/*zero*/()) {
2074 for (difference_type m = n - 1; m >= 0; -- m)
2075 e1 () (m) -= t * e2 () (n, m);
2079 // Packed (proxy) case
2080 template<class E1, class E2>
2082 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2083 lower_tag, row_major_tag, packed_proxy_tag) {
2084 typedef typename E1::size_type size_type;
2085 typedef typename E1::difference_type difference_type;
2086 typedef typename E1::value_type value_type;
2088 BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
2089 BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
2090 size_type size = e1 ().size ();
2091 for (difference_type n = size - 1; n >= 0; -- n) {
2092 #ifndef BOOST_UBLAS_SINGULAR_CHECK
2093 BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
2095 if (e2 () (n, n) == value_type/*zero*/())
2096 singular ().raise ();
2098 value_type t = e1 () (n) /= e2 () (n, n);
2099 if (t != value_type/*zero*/()) {
2100 typename E2::const_reverse_iterator2 it2e2 (e2 ().find2 (1, n, n));
2101 typename E2::const_reverse_iterator2 it2e2_rend (e2 ().find2 (1, n, 0));
2102 difference_type m (it2e2_rend - it2e2);
2104 e1 () (it2e2.index2 ()) -= *it2e2 * t, ++ it2e2;
2108 // Sparse (proxy) case
2109 template<class E1, class E2>
2111 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2112 lower_tag, row_major_tag, unknown_storage_tag) {
2113 typedef typename E1::size_type size_type;
2114 typedef typename E1::difference_type difference_type;
2115 typedef typename E1::value_type value_type;
2117 BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
2118 BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
2119 size_type size = e1 ().size ();
2120 for (difference_type n = size - 1; n >= 0; -- n) {
2121 #ifndef BOOST_UBLAS_SINGULAR_CHECK
2122 BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
2124 if (e2 () (n, n) == value_type/*zero*/())
2125 singular ().raise ();
2127 value_type t = e1 () (n) /= e2 () (n, n);
2128 if (t != value_type/*zero*/()) {
2129 typename E2::const_reverse_iterator2 it2e2 (e2 ().find2 (1, n, n));
2130 typename E2::const_reverse_iterator2 it2e2_rend (e2 ().find2 (1, n, 0));
2131 while (it2e2 != it2e2_rend)
2132 e1 () (it2e2.index2 ()) -= *it2e2 * t, ++ it2e2;
2137 template<class E1, class E2>
2139 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2140 lower_tag, row_major_tag) {
2141 typedef typename E1::storage_category storage_category;
2142 inplace_solve (e1, e2,
2143 lower_tag (), row_major_tag (), storage_category ());
2145 template<class E1, class E2>
2147 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2148 lower_tag, column_major_tag) {
2149 typedef typename E1::storage_category storage_category;
2150 inplace_solve (trans (e2), e1,
2151 upper_tag (), row_major_tag (), storage_category ());
2154 template<class E1, class E2>
2156 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2158 typedef typename E2::orientation_category orientation_category;
2159 inplace_solve (e1, e2,
2160 lower_tag (), orientation_category ());
2162 template<class E1, class E2>
2164 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2166 typedef typename E2::orientation_category orientation_category;
2167 inplace_solve (e1, triangular_adaptor<const E2, unit_lower> (e2 ()),
2168 unit_lower_tag (), orientation_category ());
2171 // Dense (proxy) case
2172 template<class E1, class E2>
2174 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2175 upper_tag, row_major_tag, dense_proxy_tag) {
2176 typedef typename E1::size_type size_type;
2177 typedef typename E1::difference_type difference_type;
2178 typedef typename E1::value_type value_type;
2180 BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
2181 BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
2182 size_type size = e1 ().size ();
2183 for (size_type n = 0; n < size; ++ n) {
2184 #ifndef BOOST_UBLAS_SINGULAR_CHECK
2185 BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
2187 if (e2 () (n, n) == value_type/*zero*/())
2188 singular ().raise ();
2190 value_type t = e1 () (n) /= e2 () (n, n);
2191 if (t != value_type/*zero*/()) {
2192 for (size_type m = n + 1; m < size; ++ m)
2193 e1 () (m) -= t * e2 () (n, m);
2197 // Packed (proxy) case
2198 template<class E1, class E2>
2200 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2201 upper_tag, row_major_tag, packed_proxy_tag) {
2202 typedef typename E1::size_type size_type;
2203 typedef typename E1::difference_type difference_type;
2204 typedef typename E1::value_type value_type;
2206 BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
2207 BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
2208 size_type size = e1 ().size ();
2209 for (size_type n = 0; n < size; ++ n) {
2210 #ifndef BOOST_UBLAS_SINGULAR_CHECK
2211 BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
2213 if (e2 () (n, n) == value_type/*zero*/())
2214 singular ().raise ();
2216 value_type t = e1 () (n) /= e2 () (n, n);
2217 if (t != value_type/*zero*/()) {
2218 typename E2::const_iterator2 it2e2 (e2 ().find2 (1, n, n + 1));
2219 typename E2::const_iterator2 it2e2_end (e2 ().find2 (1, n, e2 ().size2 ()));
2220 difference_type m (it2e2_end - it2e2);
2222 e1 () (it2e2.index2 ()) -= *it2e2 * t, ++ it2e2;
2226 // Sparse (proxy) case
2227 template<class E1, class E2>
2229 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2230 upper_tag, row_major_tag, unknown_storage_tag) {
2231 typedef typename E1::size_type size_type;
2232 typedef typename E1::difference_type difference_type;
2233 typedef typename E1::value_type value_type;
2235 BOOST_UBLAS_CHECK (e1 ().size () == e2 ().size1 (), bad_size ());
2236 BOOST_UBLAS_CHECK (e2 ().size1 () == e2 ().size2 (), bad_size ());
2237 size_type size = e1 ().size ();
2238 for (size_type n = 0; n < size; ++ n) {
2239 #ifndef BOOST_UBLAS_SINGULAR_CHECK
2240 BOOST_UBLAS_CHECK (e2 () (n, n) != value_type/*zero*/(), singular ());
2242 if (e2 () (n, n) == value_type/*zero*/())
2243 singular ().raise ();
2245 value_type t = e1 () (n) /= e2 () (n, n);
2246 if (t != value_type/*zero*/()) {
2247 typename E2::const_iterator2 it2e2 (e2 ().find2 (1, n, n + 1));
2248 typename E2::const_iterator2 it2e2_end (e2 ().find2 (1, n, e2 ().size2 ()));
2249 while (it2e2 != it2e2_end)
2250 e1 () (it2e2.index2 ()) -= *it2e2 * t, ++ it2e2;
2255 template<class E1, class E2>
2257 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2258 upper_tag, row_major_tag) {
2259 typedef typename E1::storage_category storage_category;
2260 inplace_solve (e1, e2,
2261 upper_tag (), row_major_tag (), storage_category ());
2263 template<class E1, class E2>
2265 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2266 upper_tag, column_major_tag) {
2267 typedef typename E1::storage_category storage_category;
2268 inplace_solve (trans (e2), e1,
2269 lower_tag (), row_major_tag (), storage_category ());
2272 template<class E1, class E2>
2274 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2276 typedef typename E2::orientation_category orientation_category;
2277 inplace_solve (e1, e2,
2278 upper_tag (), orientation_category ());
2280 template<class E1, class E2>
2282 void inplace_solve (vector_expression<E1> &e1, const matrix_expression<E2> &e2,
2284 typedef typename E2::orientation_category orientation_category;
2285 inplace_solve (e1, triangular_adaptor<const E2, unit_upper> (e2 ()),
2286 unit_upper_tag (), orientation_category ());
2289 template<class E1, class E2, class C>
2291 typename matrix_vector_solve_traits<E1, E2>::result_type
2292 solve (const vector_expression<E1> &e1,
2293 const matrix_expression<E2> &e2,
2295 typename matrix_vector_solve_traits<E1, E2>::result_type r (e1);
2296 inplace_solve (r, e2, C ());
2300 template<class E1, class E2>
2301 struct matrix_matrix_solve_traits {
2302 typedef typename promote_traits<typename E1::value_type, typename E2::value_type>::promote_type promote_type;
2303 typedef matrix<promote_type> result_type;
2307 // k * n * (n - 1) / 2 + k * n = k * n * (n + 1) / 2 multiplications,
2308 // k * n * (n - 1) / 2 additions
2310 // Dense (proxy) case
2311 template<class E1, class E2>
2313 void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2314 lower_tag, dense_proxy_tag) {
2315 typedef typename E2::size_type size_type;
2316 typedef typename E2::difference_type difference_type;
2317 typedef typename E2::value_type value_type;
2319 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2320 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
2321 size_type size1 = e2 ().size1 ();
2322 size_type size2 = e2 ().size2 ();
2323 for (size_type n = 0; n < size1; ++ n) {
2324 #ifndef BOOST_UBLAS_SINGULAR_CHECK
2325 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2327 if (e1 () (n, n) == value_type/*zero*/())
2328 singular ().raise ();
2330 for (size_type l = 0; l < size2; ++ l) {
2331 value_type t = e2 () (n, l) /= e1 () (n, n);
2332 if (t != value_type/*zero*/()) {
2333 for (size_type m = n + 1; m < size1; ++ m)
2334 e2 () (m, l) -= e1 () (m, n) * t;
2339 // Packed (proxy) case
2340 template<class E1, class E2>
2342 void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2343 lower_tag, packed_proxy_tag) {
2344 typedef typename E2::size_type size_type;
2345 typedef typename E2::difference_type difference_type;
2346 typedef typename E2::value_type value_type;
2348 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2349 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
2350 size_type size1 = e2 ().size1 ();
2351 size_type size2 = e2 ().size2 ();
2352 for (size_type n = 0; n < size1; ++ n) {
2353 #ifndef BOOST_UBLAS_SINGULAR_CHECK
2354 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2356 if (e1 () (n, n) == value_type/*zero*/())
2357 singular ().raise ();
2359 for (size_type l = 0; l < size2; ++ l) {
2360 value_type t = e2 () (n, l) /= e1 () (n, n);
2361 if (t != value_type/*zero*/()) {
2362 typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
2363 typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
2364 difference_type m (it1e1_end - it1e1);
2366 e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
2371 // Sparse (proxy) case
2372 template<class E1, class E2>
2374 void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2375 lower_tag, unknown_storage_tag) {
2376 typedef typename E2::size_type size_type;
2377 typedef typename E2::difference_type difference_type;
2378 typedef typename E2::value_type value_type;
2380 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2381 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
2382 size_type size1 = e2 ().size1 ();
2383 size_type size2 = e2 ().size2 ();
2384 for (size_type n = 0; n < size1; ++ n) {
2385 #ifndef BOOST_UBLAS_SINGULAR_CHECK
2386 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2388 if (e1 () (n, n) == value_type/*zero*/())
2389 singular ().raise ();
2391 for (size_type l = 0; l < size2; ++ l) {
2392 value_type t = e2 () (n, l) /= e1 () (n, n);
2393 if (t != value_type/*zero*/()) {
2394 typename E1::const_iterator1 it1e1 (e1 ().find1 (1, n + 1, n));
2395 typename E1::const_iterator1 it1e1_end (e1 ().find1 (1, e1 ().size1 (), n));
2396 while (it1e1 != it1e1_end)
2397 e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
2403 template<class E1, class E2>
2405 void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2407 typedef typename E1::storage_category dispatch_category;
2408 inplace_solve (e1, e2,
2409 lower_tag (), dispatch_category ());
2411 template<class E1, class E2>
2413 void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2415 typedef typename E1::storage_category dispatch_category;
2416 inplace_solve (triangular_adaptor<const E1, unit_lower> (e1 ()), e2,
2417 unit_lower_tag (), dispatch_category ());
2420 // Dense (proxy) case
2421 template<class E1, class E2>
2423 void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2424 upper_tag, dense_proxy_tag) {
2425 typedef typename E2::size_type size_type;
2426 typedef typename E2::difference_type difference_type;
2427 typedef typename E2::value_type value_type;
2429 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2430 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
2431 size_type size1 = e2 ().size1 ();
2432 size_type size2 = e2 ().size2 ();
2433 for (difference_type n = size1 - 1; n >= 0; -- n) {
2434 #ifndef BOOST_UBLAS_SINGULAR_CHECK
2435 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2437 if (e1 () (n, n) == value_type/*zero*/())
2438 singular ().raise ();
2440 for (difference_type l = size2 - 1; l >= 0; -- l) {
2441 value_type t = e2 () (n, l) /= e1 () (n, n);
2442 if (t != value_type/*zero*/()) {
2443 for (difference_type m = n - 1; m >= 0; -- m)
2444 e2 () (m, l) -= e1 () (m, n) * t;
2449 // Packed (proxy) case
2450 template<class E1, class E2>
2452 void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2453 upper_tag, packed_proxy_tag) {
2454 typedef typename E2::size_type size_type;
2455 typedef typename E2::difference_type difference_type;
2456 typedef typename E2::value_type value_type;
2458 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2459 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
2460 size_type size1 = e2 ().size1 ();
2461 size_type size2 = e2 ().size2 ();
2462 for (difference_type n = size1 - 1; n >= 0; -- n) {
2463 #ifndef BOOST_UBLAS_SINGULAR_CHECK
2464 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2466 if (e1 () (n, n) == value_type/*zero*/())
2467 singular ().raise ();
2469 for (difference_type l = size2 - 1; l >= 0; -- l) {
2470 value_type t = e2 () (n, l) /= e1 () (n, n);
2471 if (t != value_type/*zero*/()) {
2472 typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
2473 typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
2474 difference_type m (it1e1_rend - it1e1);
2476 e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
2481 // Sparse (proxy) case
2482 template<class E1, class E2>
2484 void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2485 upper_tag, unknown_storage_tag) {
2486 typedef typename E2::size_type size_type;
2487 typedef typename E2::difference_type difference_type;
2488 typedef typename E2::value_type value_type;
2490 BOOST_UBLAS_CHECK (e1 ().size1 () == e1 ().size2 (), bad_size ());
2491 BOOST_UBLAS_CHECK (e1 ().size2 () == e2 ().size1 (), bad_size ());
2492 size_type size1 = e2 ().size1 ();
2493 size_type size2 = e2 ().size2 ();
2494 for (difference_type n = size1 - 1; n >= 0; -- n) {
2495 #ifndef BOOST_UBLAS_SINGULAR_CHECK
2496 BOOST_UBLAS_CHECK (e1 () (n, n) != value_type/*zero*/(), singular ());
2498 if (e1 () (n, n) == value_type/*zero*/())
2499 singular ().raise ();
2501 for (difference_type l = size2 - 1; l >= 0; -- l) {
2502 value_type t = e2 () (n, l) /= e1 () (n, n);
2503 if (t != value_type/*zero*/()) {
2504 typename E1::const_reverse_iterator1 it1e1 (e1 ().find1 (1, n, n));
2505 typename E1::const_reverse_iterator1 it1e1_rend (e1 ().find1 (1, 0, n));
2506 while (it1e1 != it1e1_rend)
2507 e2 () (it1e1.index1 (), l) -= *it1e1 * t, ++ it1e1;
2513 template<class E1, class E2>
2515 void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2517 typedef typename E1::storage_category dispatch_category;
2518 inplace_solve (e1, e2,
2519 upper_tag (), dispatch_category ());
2521 template<class E1, class E2>
2523 void inplace_solve (const matrix_expression<E1> &e1, matrix_expression<E2> &e2,
2525 typedef typename E1::storage_category dispatch_category;
2526 inplace_solve (triangular_adaptor<const E1, unit_upper> (e1 ()), e2,
2527 unit_upper_tag (), dispatch_category ());
2530 template<class E1, class E2, class C>
2532 typename matrix_matrix_solve_traits<E1, E2>::result_type
2533 solve (const matrix_expression<E1> &e1,
2534 const matrix_expression<E2> &e2,
2536 typename matrix_matrix_solve_traits<E1, E2>::result_type r (e2);
2537 inplace_solve (e1, r, C ());