First public contribution.
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_MATRIX_
18 #define _BOOST_UBLAS_MATRIX_
20 #include <boost/numeric/ublas/vector.hpp>
21 #include <boost/numeric/ublas/matrix_expression.hpp>
22 #include <boost/numeric/ublas/detail/matrix_assign.hpp>
24 // Iterators based on ideas of Jeremy Siek
26 namespace boost { namespace numeric { namespace ublas {
29 using namespace boost::numeric::ublas;
31 // Matrix resizing algorithm
32 template <class L, class M>
34 void matrix_resize_preserve (M& m, M& temporary) {
35 typedef L layout_type;
36 typedef typename M::size_type size_type;
37 const size_type msize1 (m.size1 ()); // original size
38 const size_type msize2 (m.size2 ());
39 const size_type size1 (temporary.size1 ()); // new size is specified by temporary
40 const size_type size2 (temporary.size2 ());
41 // Common elements to preserve
42 const size_type size1_min = (std::min) (size1, msize1);
43 const size_type size2_min = (std::min) (size2, msize2);
44 // Order loop for i-major and j-minor sizes
45 const size_type i_size = layout_type::size1 (size1_min, size2_min);
46 const size_type j_size = layout_type::size2 (size1_min, size2_min);
47 for (size_type i = 0; i != i_size; ++i) { // indexing copy over major
48 for (size_type j = 0; j != j_size; ++j) {
49 const size_type element1 = layout_type::element1(i,i_size, j,j_size);
50 const size_type element2 = layout_type::element2(i,i_size, j,j_size);
51 temporary.data () [layout_type::element (element1, size1, element2, size2)] =
52 m.data() [layout_type::element (element1, msize1, element2, msize2)];
55 m.assign_temporary (temporary);
60 // Array based matrix class
61 template<class T, class L, class A>
63 public matrix_container<matrix<T, L, A> > {
66 typedef L layout_type;
67 typedef matrix<T, L, A> self_type;
69 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
70 using matrix_container<self_type>::operator ();
72 typedef typename A::size_type size_type;
73 typedef typename A::difference_type difference_type;
75 typedef const T &const_reference;
78 typedef const matrix_reference<const self_type> const_closure_type;
79 typedef matrix_reference<self_type> closure_type;
80 typedef vector<T, A> vector_temporary_type;
81 typedef self_type matrix_temporary_type;
82 typedef dense_tag storage_category;
83 // This could be better for performance,
84 // typedef typename unknown_orientation_tag orientation_category;
85 // but others depend on the orientation information...
86 typedef typename L::orientation_category orientation_category;
88 // Construction and destruction
91 matrix_container<self_type> (),
92 size1_ (0), size2_ (0), data_ () {}
94 matrix (size_type size1, size_type size2):
95 matrix_container<self_type> (),
96 size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2)) {
99 matrix (size_type size1, size_type size2, const array_type &data):
100 matrix_container<self_type> (),
101 size1_ (size1), size2_ (size2), data_ (data) {}
103 matrix (const matrix &m):
104 matrix_container<self_type> (),
105 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
108 matrix (const matrix_expression<AE> &ae):
109 matrix_container<self_type> (),
110 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::storage_size (size1_, size2_)) {
111 matrix_assign<scalar_assign> (*this, ae);
116 size_type size1 () const {
120 size_type size2 () const {
126 const array_type &data () const {
130 array_type &data () {
136 void resize (size_type size1, size_type size2, bool preserve = true) {
138 self_type temporary (size1, size2);
139 detail::matrix_resize_preserve<layout_type> (*this, temporary);
142 data ().resize (layout_type::storage_size (size1, size2));
150 const_reference operator () (size_type i, size_type j) const {
151 return data () [layout_type::element (i, size1_, j, size2_)];
154 reference at_element (size_type i, size_type j) {
155 return data () [layout_type::element (i, size1_, j, size2_)];
158 reference operator () (size_type i, size_type j) {
159 return at_element (i, j);
162 // Element assignment
164 reference insert_element (size_type i, size_type j, const_reference t) {
165 return (at_element (i, j) = t);
167 void erase_element (size_type i, size_type j) {
168 at_element (i, j) = value_type/*zero*/();
174 std::fill (data ().begin (), data ().end (), value_type/*zero*/());
179 matrix &operator = (const matrix &m) {
185 template<class C> // Container assignment without temporary
187 matrix &operator = (const matrix_container<C> &m) {
188 resize (m ().size1 (), m ().size2 (), false);
193 matrix &assign_temporary (matrix &m) {
199 matrix &operator = (const matrix_expression<AE> &ae) {
200 self_type temporary (ae);
201 return assign_temporary (temporary);
205 matrix &assign (const matrix_expression<AE> &ae) {
206 matrix_assign<scalar_assign> (*this, ae);
211 matrix& operator += (const matrix_expression<AE> &ae) {
212 self_type temporary (*this + ae);
213 return assign_temporary (temporary);
215 template<class C> // Container assignment without temporary
217 matrix &operator += (const matrix_container<C> &m) {
223 matrix &plus_assign (const matrix_expression<AE> &ae) {
224 matrix_assign<scalar_plus_assign> (*this, ae);
229 matrix& operator -= (const matrix_expression<AE> &ae) {
230 self_type temporary (*this - ae);
231 return assign_temporary (temporary);
233 template<class C> // Container assignment without temporary
235 matrix &operator -= (const matrix_container<C> &m) {
241 matrix &minus_assign (const matrix_expression<AE> &ae) {
242 matrix_assign<scalar_minus_assign> (*this, ae);
247 matrix& operator *= (const AT &at) {
248 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
253 matrix& operator /= (const AT &at) {
254 matrix_assign_scalar<scalar_divides_assign> (*this, at);
260 void swap (matrix &m) {
262 std::swap (size1_, m.size1_);
263 std::swap (size2_, m.size2_);
264 data ().swap (m.data ());
268 friend void swap (matrix &m1, matrix &m2) {
274 // Use the storage array iterator
275 typedef typename A::const_iterator const_subiterator_type;
276 typedef typename A::iterator subiterator_type;
279 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
280 typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
281 typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
282 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
283 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
285 class const_iterator1;
287 class const_iterator2;
290 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
291 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
292 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
293 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
297 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
298 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
299 return const_iterator1 (*this, i, j);
301 return const_iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
305 iterator1 find1 (int /* rank */, size_type i, size_type j) {
306 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
307 return iterator1 (*this, i, j);
309 return iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
313 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
314 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
315 return const_iterator2 (*this, i, j);
317 return const_iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
321 iterator2 find2 (int /* rank */, size_type i, size_type j) {
322 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
323 return iterator2 (*this, i, j);
325 return iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
330 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
331 class const_iterator1:
332 public container_const_reference<matrix>,
333 public random_access_iterator_base<dense_random_access_iterator_tag,
334 const_iterator1, value_type> {
336 typedef typename matrix::value_type value_type;
337 typedef typename matrix::difference_type difference_type;
338 typedef typename matrix::const_reference reference;
339 typedef const typename matrix::pointer pointer;
341 typedef const_iterator2 dual_iterator_type;
342 typedef const_reverse_iterator2 dual_reverse_iterator_type;
344 // Construction and destruction
347 container_const_reference<self_type> (), it_ () {}
349 const_iterator1 (const self_type &m, const const_subiterator_type &it):
350 container_const_reference<self_type> (m), it_ (it) {}
352 const_iterator1 (const iterator1 &it):
353 container_const_reference<self_type> (it ()), it_ (it.it_) {}
357 const_iterator1 &operator ++ () {
358 layout_type::increment1 (it_, (*this) ().size1 (), (*this) ().size2 ());
362 const_iterator1 &operator -- () {
363 layout_type::decrement1 (it_, (*this) ().size1 (), (*this) ().size2 ());
367 const_iterator1 &operator += (difference_type n) {
368 it_ += n * layout_type::one1 ((*this) ().size1 (), (*this) ().size2 ());
372 const_iterator1 &operator -= (difference_type n) {
373 it_ -= n * layout_type::one1 ((*this) ().size1 (), (*this) ().size2 ());
377 difference_type operator - (const const_iterator1 &it) const {
378 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
379 return layout_type::distance1 (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
384 const_reference operator * () const {
385 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
386 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
390 const_reference operator [] (difference_type n) const {
394 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
396 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
399 const_iterator2 begin () const {
400 const self_type &m = (*this) ();
401 return m.find2 (1, index1 (), 0);
404 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
407 const_iterator2 end () const {
408 const self_type &m = (*this) ();
409 return m.find2 (1, index1 (), m.size2 ());
412 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
415 const_reverse_iterator2 rbegin () const {
416 return const_reverse_iterator2 (end ());
419 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
422 const_reverse_iterator2 rend () const {
423 return const_reverse_iterator2 (begin ());
429 size_type index1 () const {
430 const self_type &m = (*this) ();
431 return layout_type::index1 (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
434 size_type index2 () const {
435 const self_type &m = (*this) ();
436 return layout_type::index2 (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
441 const_iterator1 &operator = (const const_iterator1 &it) {
442 container_const_reference<self_type>::assign (&it ());
449 bool operator == (const const_iterator1 &it) const {
450 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
451 return it_ == it.it_;
454 bool operator < (const const_iterator1 &it) const {
455 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
460 const_subiterator_type it_;
462 friend class iterator1;
467 const_iterator1 begin1 () const {
468 return find1 (0, 0, 0);
471 const_iterator1 end1 () const {
472 return find1 (0, size1_, 0);
475 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
477 public container_reference<matrix>,
478 public random_access_iterator_base<dense_random_access_iterator_tag,
479 iterator1, value_type> {
481 typedef typename matrix::value_type value_type;
482 typedef typename matrix::difference_type difference_type;
483 typedef typename matrix::reference reference;
484 typedef typename matrix::pointer pointer;
486 typedef iterator2 dual_iterator_type;
487 typedef reverse_iterator2 dual_reverse_iterator_type;
489 // Construction and destruction
492 container_reference<self_type> (), it_ () {}
494 iterator1 (self_type &m, const subiterator_type &it):
495 container_reference<self_type> (m), it_ (it) {}
499 iterator1 &operator ++ () {
500 layout_type::increment1 (it_, (*this) ().size1 (), (*this) ().size2 ());
504 iterator1 &operator -- () {
505 layout_type::decrement1 (it_, (*this) ().size1 (), (*this) ().size2 ());
509 iterator1 &operator += (difference_type n) {
510 it_ += n * layout_type::one1 ((*this) ().size1 (), (*this) ().size2 ());
514 iterator1 &operator -= (difference_type n) {
515 it_ -= n * layout_type::one1 ((*this) ().size1 (), (*this) ().size2 ());
519 difference_type operator - (const iterator1 &it) const {
520 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
521 return layout_type::distance1 (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
526 reference operator * () const {
527 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
528 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
532 reference operator [] (difference_type n) const {
536 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
538 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
541 iterator2 begin () const {
542 self_type &m = (*this) ();
543 return m.find2 (1, index1 (), 0);
546 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
549 iterator2 end () const {
550 self_type &m = (*this) ();
551 return m.find2 (1, index1 (), m.size2 ());
554 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
557 reverse_iterator2 rbegin () const {
558 return reverse_iterator2 (end ());
561 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
564 reverse_iterator2 rend () const {
565 return reverse_iterator2 (begin ());
571 size_type index1 () const {
572 self_type &m = (*this) ();
573 return layout_type::index1 (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
576 size_type index2 () const {
577 self_type &m = (*this) ();
578 return layout_type::index2 (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
583 iterator1 &operator = (const iterator1 &it) {
584 container_reference<self_type>::assign (&it ());
591 bool operator == (const iterator1 &it) const {
592 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
593 return it_ == it.it_;
596 bool operator < (const iterator1 &it) const {
597 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
602 subiterator_type it_;
604 friend class const_iterator1;
609 iterator1 begin1 () {
610 return find1 (0, 0, 0);
614 return find1 (0, size1_, 0);
617 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
618 class const_iterator2:
619 public container_const_reference<matrix>,
620 public random_access_iterator_base<dense_random_access_iterator_tag,
621 const_iterator2, value_type> {
623 typedef typename matrix::value_type value_type;
624 typedef typename matrix::difference_type difference_type;
625 typedef typename matrix::const_reference reference;
626 typedef const typename matrix::pointer pointer;
628 typedef const_iterator1 dual_iterator_type;
629 typedef const_reverse_iterator1 dual_reverse_iterator_type;
631 // Construction and destruction
634 container_const_reference<self_type> (), it_ () {}
636 const_iterator2 (const self_type &m, const const_subiterator_type &it):
637 container_const_reference<self_type> (m), it_ (it) {}
639 const_iterator2 (const iterator2 &it):
640 container_const_reference<self_type> (it ()), it_ (it.it_) {}
644 const_iterator2 &operator ++ () {
645 layout_type::increment2 (it_, (*this) ().size1 (), (*this) ().size2 ());
649 const_iterator2 &operator -- () {
650 layout_type::decrement2 (it_, (*this) ().size1 (), (*this) ().size2 ());
654 const_iterator2 &operator += (difference_type n) {
655 it_ += n * layout_type::one2 ((*this) ().size1 (), (*this) ().size2 ());
659 const_iterator2 &operator -= (difference_type n) {
660 it_ -= n * layout_type::one2 ((*this) ().size1 (), (*this) ().size2 ());
664 difference_type operator - (const const_iterator2 &it) const {
665 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
666 return layout_type::distance2 (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
671 const_reference operator * () const {
672 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
673 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
677 const_reference operator [] (difference_type n) const {
681 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
683 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
686 const_iterator1 begin () const {
687 const self_type &m = (*this) ();
688 return m.find1 (1, 0, index2 ());
691 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
694 const_iterator1 end () const {
695 const self_type &m = (*this) ();
696 return m.find1 (1, m.size1 (), index2 ());
699 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
702 const_reverse_iterator1 rbegin () const {
703 return const_reverse_iterator1 (end ());
706 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
709 const_reverse_iterator1 rend () const {
710 return const_reverse_iterator1 (begin ());
716 size_type index1 () const {
717 const self_type &m = (*this) ();
718 return layout_type::index1 (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
721 size_type index2 () const {
722 const self_type &m = (*this) ();
723 return layout_type::index2 (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
728 const_iterator2 &operator = (const const_iterator2 &it) {
729 container_const_reference<self_type>::assign (&it ());
736 bool operator == (const const_iterator2 &it) const {
737 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
738 return it_ == it.it_;
741 bool operator < (const const_iterator2 &it) const {
742 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
747 const_subiterator_type it_;
749 friend class iterator2;
754 const_iterator2 begin2 () const {
755 return find2 (0, 0, 0);
758 const_iterator2 end2 () const {
759 return find2 (0, 0, size2_);
762 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
764 public container_reference<matrix>,
765 public random_access_iterator_base<dense_random_access_iterator_tag,
766 iterator2, value_type> {
768 typedef typename matrix::value_type value_type;
769 typedef typename matrix::difference_type difference_type;
770 typedef typename matrix::reference reference;
771 typedef typename matrix::pointer pointer;
773 typedef iterator1 dual_iterator_type;
774 typedef reverse_iterator1 dual_reverse_iterator_type;
776 // Construction and destruction
779 container_reference<self_type> (), it_ () {}
781 iterator2 (self_type &m, const subiterator_type &it):
782 container_reference<self_type> (m), it_ (it) {}
786 iterator2 &operator ++ () {
787 layout_type::increment2 (it_, (*this) ().size1 (), (*this) ().size2 ());
791 iterator2 &operator -- () {
792 layout_type::decrement2 (it_, (*this) ().size1 (), (*this) ().size2 ());
796 iterator2 &operator += (difference_type n) {
797 it_ += n * layout_type::one2 ((*this) ().size1 (), (*this) ().size2 ());
801 iterator2 &operator -= (difference_type n) {
802 it_ -= n * layout_type::one2 ((*this) ().size1 (), (*this) ().size2 ());
806 difference_type operator - (const iterator2 &it) const {
807 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
808 return layout_type::distance2 (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
813 reference operator * () const {
814 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
815 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
819 reference operator [] (difference_type n) const {
823 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
825 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
828 iterator1 begin () const {
829 self_type &m = (*this) ();
830 return m.find1 (1, 0, index2 ());
833 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
836 iterator1 end () const {
837 self_type &m = (*this) ();
838 return m.find1 (1, m.size1 (), index2 ());
841 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
844 reverse_iterator1 rbegin () const {
845 return reverse_iterator1 (end ());
848 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
851 reverse_iterator1 rend () const {
852 return reverse_iterator1 (begin ());
858 size_type index1 () const {
859 self_type &m = (*this) ();
860 return layout_type::index1 (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
863 size_type index2 () const {
864 self_type &m = (*this) ();
865 return layout_type::index2 (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
870 iterator2 &operator = (const iterator2 &it) {
871 container_reference<self_type>::assign (&it ());
878 bool operator == (const iterator2 &it) const {
879 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
880 return it_ == it.it_;
883 bool operator < (const iterator2 &it) const {
884 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
889 subiterator_type it_;
891 friend class const_iterator2;
896 iterator2 begin2 () {
897 return find2 (0, 0, 0);
901 return find2 (0, 0, size2_);
907 const_reverse_iterator1 rbegin1 () const {
908 return const_reverse_iterator1 (end1 ());
911 const_reverse_iterator1 rend1 () const {
912 return const_reverse_iterator1 (begin1 ());
916 reverse_iterator1 rbegin1 () {
917 return reverse_iterator1 (end1 ());
920 reverse_iterator1 rend1 () {
921 return reverse_iterator1 (begin1 ());
925 const_reverse_iterator2 rbegin2 () const {
926 return const_reverse_iterator2 (end2 ());
929 const_reverse_iterator2 rend2 () const {
930 return const_reverse_iterator2 (begin2 ());
934 reverse_iterator2 rbegin2 () {
935 return reverse_iterator2 (end2 ());
938 reverse_iterator2 rend2 () {
939 return reverse_iterator2 (begin2 ());
949 // Bounded matrix class
950 template<class T, std::size_t M, std::size_t N, class L>
951 class bounded_matrix:
952 public matrix<T, L, bounded_array<T, M * N> > {
954 typedef matrix<T, L, bounded_array<T, M * N> > matrix_type;
956 typedef typename matrix_type::size_type size_type;
957 static const size_type max_size1 = M;
958 static const size_type max_size2 = N;
960 // Construction and destruction
963 matrix_type (M, N) {}
965 bounded_matrix (size_type size1, size_type size2):
966 matrix_type (size1, size2) {}
968 bounded_matrix (const bounded_matrix &m):
970 template<class A2> // Allow matrix<T, L, bounded_array<M,N> > construction
972 bounded_matrix (const matrix<T, L, A2> &m):
976 bounded_matrix (const matrix_expression<AE> &ae):
979 ~bounded_matrix () {}
983 bounded_matrix &operator = (const bounded_matrix &m) {
984 matrix_type::operator = (m);
987 template<class L2, class A2> // Generic matrix assignment
989 bounded_matrix &operator = (const matrix<T, L2, A2> &m) {
990 matrix_type::operator = (m);
993 template<class C> // Container assignment without temporary
995 bounded_matrix &operator = (const matrix_container<C> &m) {
996 matrix_type::operator = (m);
1001 bounded_matrix &operator = (const matrix_expression<AE> &ae) {
1002 matrix_type::operator = (ae);
1008 // Array based matrix class
1009 template<class T, class L, class A>
1010 class vector_of_vector:
1011 public matrix_container<vector_of_vector<T, L, A> > {
1014 typedef L layout_type;
1015 typedef vector_of_vector<T, L, A> self_type;
1017 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1018 using matrix_container<self_type>::operator ();
1020 typedef typename A::size_type size_type;
1021 typedef typename A::difference_type difference_type;
1022 typedef T value_type;
1023 typedef const T &const_reference;
1024 typedef T &reference;
1025 typedef A array_type;
1026 typedef const matrix_reference<const self_type> const_closure_type;
1027 typedef matrix_reference<self_type> closure_type;
1028 typedef vector<T, typename A::value_type> vector_temporary_type;
1029 typedef self_type matrix_temporary_type;
1030 typedef dense_tag storage_category;
1031 // This could be better for performance,
1032 // typedef typename unknown_orientation_tag orientation_category;
1033 // but others depend on the orientation information...
1034 typedef typename L::orientation_category orientation_category;
1036 // Construction and destruction
1038 vector_of_vector ():
1039 matrix_container<self_type> (),
1040 size1_ (0), size2_ (0), data_ (1) {}
1042 vector_of_vector (size_type size1, size_type size2):
1043 matrix_container<self_type> (),
1044 size1_ (size1), size2_ (size2), data_ (1) {
1045 resize (size1, size2, true);
1048 vector_of_vector (const vector_of_vector &m):
1049 matrix_container<self_type> (),
1050 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
1053 vector_of_vector (const matrix_expression<AE> &ae):
1054 matrix_container<self_type> (),
1055 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size1 (size1_, size2_) + 1) {
1056 for (size_type k = 0; k < layout_type::size1 (size1_, size2_); ++ k)
1057 data ()[k].resize (layout_type::size2 (size1_, size2_));
1058 matrix_assign<scalar_assign> (*this, ae);
1063 size_type size1 () const {
1067 size_type size2 () const {
1071 // Storage accessors
1073 const array_type &data () const {
1077 array_type &data () {
1083 void resize (size_type size1, size_type size2, bool preserve = true) {
1087 data ().resize (layout_type::size1 (size1, size2) + 1, typename array_type::value_type ());
1089 data ().resize (layout_type::size1 (size1, size2) + 1);
1090 for (size_type k = 0; k < layout_type::size1 (size1, size2); ++ k) {
1092 data () [k].resize (layout_type::size2 (size1, size2), value_type ());
1094 data () [k].resize (layout_type::size2 (size1, size2));
1100 const_reference operator () (size_type i, size_type j) const {
1101 return data () [layout_type::element1 (i, size1_, j, size2_)] [layout_type::element2 (i, size1_, j, size2_)];
1104 reference at_element (size_type i, size_type j) {
1105 return data () [layout_type::element1 (i, size1_, j, size2_)] [layout_type::element2 (i, size1_, j, size2_)];
1108 reference operator () (size_type i, size_type j) {
1109 return at_element (i, j);
1112 // Element assignment
1114 reference insert_element (size_type i, size_type j, const_reference t) {
1115 return (at_element (i, j) = t);
1118 void erase_element (size_type i, size_type j) {
1119 at_element (i, j) = value_type/*zero*/();
1125 for (size_type k = 0; k < layout_type::size1 (size1_, size2_); ++ k)
1126 std::fill (data () [k].begin (), data () [k].end (), value_type/*zero*/());
1131 vector_of_vector &operator = (const vector_of_vector &m) {
1134 data () = m.data ();
1138 vector_of_vector &assign_temporary (vector_of_vector &m) {
1144 vector_of_vector &operator = (const matrix_expression<AE> &ae) {
1145 self_type temporary (ae);
1146 return assign_temporary (temporary);
1148 template<class C> // Container assignment without temporary
1150 vector_of_vector &operator = (const matrix_container<C> &m) {
1151 resize (m ().size1 (), m ().size2 (), false);
1157 vector_of_vector &assign (const matrix_expression<AE> &ae) {
1158 matrix_assign<scalar_assign> (*this, ae);
1163 vector_of_vector& operator += (const matrix_expression<AE> &ae) {
1164 self_type temporary (*this + ae);
1165 return assign_temporary (temporary);
1167 template<class C> // Container assignment without temporary
1169 vector_of_vector &operator += (const matrix_container<C> &m) {
1175 vector_of_vector &plus_assign (const matrix_expression<AE> &ae) {
1176 matrix_assign<scalar_plus_assign> (*this, ae);
1181 vector_of_vector& operator -= (const matrix_expression<AE> &ae) {
1182 self_type temporary (*this - ae);
1183 return assign_temporary (temporary);
1185 template<class C> // Container assignment without temporary
1187 vector_of_vector &operator -= (const matrix_container<C> &m) {
1193 vector_of_vector &minus_assign (const matrix_expression<AE> &ae) {
1194 matrix_assign<scalar_minus_assign> (*this, ae);
1199 vector_of_vector& operator *= (const AT &at) {
1200 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
1205 vector_of_vector& operator /= (const AT &at) {
1206 matrix_assign_scalar<scalar_divides_assign> (*this, at);
1212 void swap (vector_of_vector &m) {
1214 std::swap (size1_, m.size1_);
1215 std::swap (size2_, m.size2_);
1216 data ().swap (m.data ());
1220 friend void swap (vector_of_vector &m1, vector_of_vector &m2) {
1226 // Use the vector iterator
1227 typedef typename A::value_type::const_iterator const_subiterator_type;
1228 typedef typename A::value_type::iterator subiterator_type;
1230 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1231 typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
1232 typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
1233 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
1234 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
1236 class const_iterator1;
1238 class const_iterator2;
1241 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1242 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
1243 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1244 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
1248 const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
1249 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1250 return const_iterator1 (*this, i, j);
1252 return const_iterator1 (*this, i, j, data () [layout_type::address1 (i, size1_, j, size2_)].begin () + layout_type::address2 (i, size1_, j, size2_));
1256 iterator1 find1 (int /*rank*/, size_type i, size_type j) {
1257 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1258 return iterator1 (*this, i, j);
1260 return iterator1 (*this, i, j, data () [layout_type::address1 (i, size1_, j, size2_)].begin () + layout_type::address2 (i, size1_, j, size2_));
1264 const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
1265 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1266 return const_iterator2 (*this, i, j);
1268 return const_iterator2 (*this, i, j, data () [layout_type::address1 (i, size1_, j, size2_)].begin () + layout_type::address2 (i, size1_, j, size2_));
1272 iterator2 find2 (int /*rank*/, size_type i, size_type j) {
1273 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1274 return iterator2 (*this, i, j);
1276 return iterator2 (*this, i, j, data () [layout_type::address1 (i, size1_, j, size2_)].begin () + layout_type::address2 (i, size1_, j, size2_));
1281 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1282 class const_iterator1:
1283 public container_const_reference<vector_of_vector>,
1284 public random_access_iterator_base<dense_random_access_iterator_tag,
1285 const_iterator1, value_type> {
1287 typedef typename vector_of_vector::value_type value_type;
1288 typedef typename vector_of_vector::difference_type difference_type;
1289 typedef typename vector_of_vector::const_reference reference;
1290 typedef const typename vector_of_vector::pointer pointer;
1292 typedef const_iterator2 dual_iterator_type;
1293 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1295 // Construction and destruction
1298 container_const_reference<self_type> (), i_ (), j_ (), it_ () {}
1300 const_iterator1 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it):
1301 container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
1303 const_iterator1 (const iterator1 &it):
1304 container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
1308 const_iterator1 &operator ++ () {
1310 const self_type &m = (*this) ();
1311 if (layout_type::fast1 ())
1314 it_ = m.find1 (1, i_, j_).it_;
1318 const_iterator1 &operator -- () {
1320 const self_type &m = (*this) ();
1321 if (layout_type::fast1 ())
1324 it_ = m.find1 (1, i_, j_).it_;
1328 const_iterator1 &operator += (difference_type n) {
1330 const self_type &m = (*this) ();
1331 it_ = m.find1 (1, i_, j_).it_;
1335 const_iterator1 &operator -= (difference_type n) {
1337 const self_type &m = (*this) ();
1338 it_ = m.find1 (1, i_, j_).it_;
1342 difference_type operator - (const const_iterator1 &it) const {
1343 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1344 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
1345 return index1 () - it.index1 ();
1350 const_reference operator * () const {
1351 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1352 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1356 const_reference operator [] (difference_type n) const {
1357 return *(*this + n);
1360 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1362 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1363 typename self_type::
1365 const_iterator2 begin () const {
1366 const self_type &m = (*this) ();
1367 return m.find2 (1, index1 (), 0);
1370 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1371 typename self_type::
1373 const_iterator2 end () const {
1374 const self_type &m = (*this) ();
1375 return m.find2 (1, index1 (), m.size2 ());
1378 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1379 typename self_type::
1381 const_reverse_iterator2 rbegin () const {
1382 return const_reverse_iterator2 (end ());
1385 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1386 typename self_type::
1388 const_reverse_iterator2 rend () const {
1389 return const_reverse_iterator2 (begin ());
1395 size_type index1 () const {
1399 size_type index2 () const {
1405 const_iterator1 &operator = (const const_iterator1 &it) {
1406 container_const_reference<self_type>::assign (&it ());
1413 bool operator == (const const_iterator1 &it) const {
1414 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1415 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
1416 return it_ == it.it_;
1419 bool operator < (const const_iterator1 &it) const {
1420 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1421 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
1422 return it_ < it.it_;
1428 const_subiterator_type it_;
1430 friend class iterator1;
1435 const_iterator1 begin1 () const {
1436 return find1 (0, 0, 0);
1439 const_iterator1 end1 () const {
1440 return find1 (0, size1_, 0);
1443 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1445 public container_reference<vector_of_vector>,
1446 public random_access_iterator_base<dense_random_access_iterator_tag,
1447 iterator1, value_type> {
1449 typedef typename vector_of_vector::value_type value_type;
1450 typedef typename vector_of_vector::difference_type difference_type;
1451 typedef typename vector_of_vector::reference reference;
1452 typedef typename vector_of_vector::pointer pointer;
1454 typedef iterator2 dual_iterator_type;
1455 typedef reverse_iterator2 dual_reverse_iterator_type;
1457 // Construction and destruction
1460 container_reference<self_type> (), i_ (), j_ (), it_ () {}
1462 iterator1 (self_type &m, size_type i, size_type j, const subiterator_type &it):
1463 container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
1467 iterator1 &operator ++ () {
1469 self_type &m = (*this) ();
1470 if (layout_type::fast1 ())
1473 it_ = m.find1 (1, i_, j_).it_;
1477 iterator1 &operator -- () {
1479 self_type &m = (*this) ();
1480 if (layout_type::fast1 ())
1483 it_ = m.find1 (1, i_, j_).it_;
1487 iterator1 &operator += (difference_type n) {
1489 self_type &m = (*this) ();
1490 it_ = m.find1 (1, i_, j_).it_;
1494 iterator1 &operator -= (difference_type n) {
1496 self_type &m = (*this) ();
1497 it_ = m.find1 (1, i_, j_).it_;
1501 difference_type operator - (const iterator1 &it) const {
1502 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1503 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
1504 return index1 () - it.index1 ();
1509 reference operator * () const {
1510 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1511 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1515 reference operator [] (difference_type n) const {
1516 return *(*this + n);
1519 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1521 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1522 typename self_type::
1524 iterator2 begin () const {
1525 self_type &m = (*this) ();
1526 return m.find2 (1, index1 (), 0);
1529 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1530 typename self_type::
1532 iterator2 end () const {
1533 self_type &m = (*this) ();
1534 return m.find2 (1, index1 (), m.size2 ());
1537 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1538 typename self_type::
1540 reverse_iterator2 rbegin () const {
1541 return reverse_iterator2 (end ());
1544 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1545 typename self_type::
1547 reverse_iterator2 rend () const {
1548 return reverse_iterator2 (begin ());
1554 size_type index1 () const {
1558 size_type index2 () const {
1564 iterator1 &operator = (const iterator1 &it) {
1565 container_reference<self_type>::assign (&it ());
1572 bool operator == (const iterator1 &it) const {
1573 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1574 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
1575 return it_ == it.it_;
1578 bool operator < (const iterator1 &it) const {
1579 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1580 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
1581 return it_ < it.it_;
1587 subiterator_type it_;
1589 friend class const_iterator1;
1594 iterator1 begin1 () {
1595 return find1 (0, 0, 0);
1599 return find1 (0, size1_, 0);
1602 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1603 class const_iterator2:
1604 public container_const_reference<vector_of_vector>,
1605 public random_access_iterator_base<dense_random_access_iterator_tag,
1606 const_iterator2, value_type> {
1608 typedef typename vector_of_vector::value_type value_type;
1609 typedef typename vector_of_vector::difference_type difference_type;
1610 typedef typename vector_of_vector::const_reference reference;
1611 typedef const typename vector_of_vector::pointer pointer;
1613 typedef const_iterator1 dual_iterator_type;
1614 typedef const_reverse_iterator1 dual_reverse_iterator_type;
1616 // Construction and destruction
1619 container_const_reference<self_type> (), i_ (), j_ (), it_ () {}
1621 const_iterator2 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it):
1622 container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
1624 const_iterator2 (const iterator2 &it):
1625 container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
1629 const_iterator2 &operator ++ () {
1631 const self_type &m = (*this) ();
1632 if (layout_type::fast2 ())
1635 it_ = m.find2 (1, i_, j_).it_;
1639 const_iterator2 &operator -- () {
1641 const self_type &m = (*this) ();
1642 if (layout_type::fast2 ())
1645 it_ = m.find2 (1, i_, j_).it_;
1649 const_iterator2 &operator += (difference_type n) {
1651 const self_type &m = (*this) ();
1652 it_ = m.find2 (1, i_, j_).it_;
1656 const_iterator2 &operator -= (difference_type n) {
1658 const self_type &m = (*this) ();
1659 it_ = m.find2 (1, i_, j_).it_;
1663 difference_type operator - (const const_iterator2 &it) const {
1664 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1665 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
1666 return index2 () - it.index2 ();
1671 const_reference operator * () const {
1672 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1673 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1677 const_reference operator [] (difference_type n) const {
1678 return *(*this + n);
1681 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1683 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1684 typename self_type::
1686 const_iterator1 begin () const {
1687 const self_type &m = (*this) ();
1688 return m.find1 (1, 0, index2 ());
1691 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1692 typename self_type::
1694 const_iterator1 end () const {
1695 const self_type &m = (*this) ();
1696 return m.find1 (1, m.size1 (), index2 ());
1699 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1700 typename self_type::
1702 const_reverse_iterator1 rbegin () const {
1703 return const_reverse_iterator1 (end ());
1706 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1707 typename self_type::
1709 const_reverse_iterator1 rend () const {
1710 return const_reverse_iterator1 (begin ());
1716 size_type index1 () const {
1720 size_type index2 () const {
1726 const_iterator2 &operator = (const const_iterator2 &it) {
1727 container_const_reference<self_type>::assign (&it ());
1734 bool operator == (const const_iterator2 &it) const {
1735 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1736 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
1737 return it_ == it.it_;
1740 bool operator < (const const_iterator2 &it) const {
1741 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1742 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
1743 return it_ < it.it_;
1749 const_subiterator_type it_;
1751 friend class iterator2;
1756 const_iterator2 begin2 () const {
1757 return find2 (0, 0, 0);
1760 const_iterator2 end2 () const {
1761 return find2 (0, 0, size2_);
1764 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1766 public container_reference<vector_of_vector>,
1767 public random_access_iterator_base<dense_random_access_iterator_tag,
1768 iterator2, value_type> {
1770 typedef typename vector_of_vector::value_type value_type;
1771 typedef typename vector_of_vector::difference_type difference_type;
1772 typedef typename vector_of_vector::reference reference;
1773 typedef typename vector_of_vector::pointer pointer;
1775 typedef iterator1 dual_iterator_type;
1776 typedef reverse_iterator1 dual_reverse_iterator_type;
1778 // Construction and destruction
1781 container_reference<self_type> (), i_ (), j_ (), it_ () {}
1783 iterator2 (self_type &m, size_type i, size_type j, const subiterator_type &it):
1784 container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
1788 iterator2 &operator ++ () {
1790 self_type &m = (*this) ();
1791 if (layout_type::fast2 ())
1794 it_ = m.find2 (1, i_, j_).it_;
1798 iterator2 &operator -- () {
1800 self_type &m = (*this) ();
1801 if (layout_type::fast2 ())
1804 it_ = m.find2 (1, i_, j_).it_;
1808 iterator2 &operator += (difference_type n) {
1810 self_type &m = (*this) ();
1811 it_ = m.find2 (1, i_, j_).it_;
1815 iterator2 &operator -= (difference_type n) {
1817 self_type &m = (*this) ();
1818 it_ = m.find2 (1, i_, j_).it_;
1822 difference_type operator - (const iterator2 &it) const {
1823 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1824 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
1825 return index2 () - it.index2 ();
1830 reference operator * () const {
1831 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1832 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1836 reference operator [] (difference_type n) const {
1837 return *(*this + n);
1840 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1842 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1843 typename self_type::
1845 iterator1 begin () const {
1846 self_type &m = (*this) ();
1847 return m.find1 (1, 0, index2 ());
1850 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1851 typename self_type::
1853 iterator1 end () const {
1854 self_type &m = (*this) ();
1855 return m.find1 (1, m.size1 (), index2 ());
1858 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1859 typename self_type::
1861 reverse_iterator1 rbegin () const {
1862 return reverse_iterator1 (end ());
1865 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1866 typename self_type::
1868 reverse_iterator1 rend () const {
1869 return reverse_iterator1 (begin ());
1875 size_type index1 () const {
1879 size_type index2 () const {
1885 iterator2 &operator = (const iterator2 &it) {
1886 container_reference<self_type>::assign (&it ());
1893 bool operator == (const iterator2 &it) const {
1894 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1895 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
1896 return it_ == it.it_;
1899 bool operator < (const iterator2 &it) const {
1900 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1901 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
1902 return it_ < it.it_;
1908 subiterator_type it_;
1910 friend class const_iterator2;
1915 iterator2 begin2 () {
1916 return find2 (0, 0, 0);
1920 return find2 (0, 0, size2_);
1923 // Reverse iterators
1926 const_reverse_iterator1 rbegin1 () const {
1927 return const_reverse_iterator1 (end1 ());
1930 const_reverse_iterator1 rend1 () const {
1931 return const_reverse_iterator1 (begin1 ());
1935 reverse_iterator1 rbegin1 () {
1936 return reverse_iterator1 (end1 ());
1939 reverse_iterator1 rend1 () {
1940 return reverse_iterator1 (begin1 ());
1944 const_reverse_iterator2 rbegin2 () const {
1945 return const_reverse_iterator2 (end2 ());
1948 const_reverse_iterator2 rend2 () const {
1949 return const_reverse_iterator2 (begin2 ());
1953 reverse_iterator2 rbegin2 () {
1954 return reverse_iterator2 (end2 ());
1957 reverse_iterator2 rend2 () {
1958 return reverse_iterator2 (begin2 ());
1968 // Zero matrix class
1971 public matrix_container<zero_matrix<T> > {
1973 typedef const T *const_pointer;
1974 typedef zero_matrix<T> self_type;
1976 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1977 using matrix_container<self_type>::operator ();
1979 typedef std::size_t size_type;
1980 typedef std::ptrdiff_t difference_type;
1981 typedef T value_type;
1982 typedef const T &const_reference;
1983 typedef T &reference;
1984 typedef const matrix_reference<const self_type> const_closure_type;
1985 typedef matrix_reference<self_type> closure_type;
1986 typedef sparse_tag storage_category;
1987 typedef unknown_orientation_tag orientation_category;
1989 // Construction and destruction
1992 matrix_container<self_type> (),
1993 size1_ (0), size2_ (0) {}
1995 zero_matrix (size_type size):
1996 matrix_container<self_type> (),
1997 size1_ (size), size2_ (size) {}
1999 zero_matrix (size_type size1, size_type size2):
2000 matrix_container<self_type> (),
2001 size1_ (size1), size2_ (size2) {}
2003 zero_matrix (const zero_matrix &m):
2004 matrix_container<self_type> (),
2005 size1_ (m.size1_), size2_ (m.size2_) {}
2009 size_type size1 () const {
2013 size_type size2 () const {
2019 void resize (size_type size, bool preserve = true) {
2024 void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
2031 const_reference operator () (size_type /* i */, size_type /* j */) const {
2037 zero_matrix &operator = (const zero_matrix &m) {
2043 zero_matrix &assign_temporary (zero_matrix &m) {
2050 void swap (zero_matrix &m) {
2052 std::swap (size1_, m.size1_);
2053 std::swap (size2_, m.size2_);
2057 friend void swap (zero_matrix &m1, zero_matrix &m2) {
2063 class const_iterator1;
2064 class const_iterator2;
2065 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2066 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2070 const_iterator1 find1 (int /*rank*/, size_type /*i*/, size_type /*j*/) const {
2071 return const_iterator1 (*this);
2074 const_iterator2 find2 (int /*rank*/, size_type /*i*/, size_type /*j*/) const {
2075 return const_iterator2 (*this);
2078 class const_iterator1:
2079 public container_const_reference<zero_matrix>,
2080 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
2081 const_iterator1, value_type> {
2083 typedef typename zero_matrix::value_type value_type;
2084 typedef typename zero_matrix::difference_type difference_type;
2085 typedef typename zero_matrix::const_reference reference;
2086 typedef typename zero_matrix::const_pointer pointer;
2088 typedef const_iterator2 dual_iterator_type;
2089 typedef const_reverse_iterator2 dual_reverse_iterator_type;
2091 // Construction and destruction
2094 container_const_reference<self_type> () {}
2096 const_iterator1 (const self_type &m):
2097 container_const_reference<self_type> (m) {}
2101 const_iterator1 &operator ++ () {
2102 BOOST_UBLAS_CHECK_FALSE (bad_index ());
2106 const_iterator1 &operator -- () {
2107 BOOST_UBLAS_CHECK_FALSE (bad_index ());
2113 const_reference operator * () const {
2114 BOOST_UBLAS_CHECK_FALSE (bad_index ());
2115 return zero_; // arbitary return value
2118 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2120 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2121 typename self_type::
2123 const_iterator2 begin () const {
2124 return const_iterator2 ((*this) ());
2127 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2128 typename self_type::
2130 const_iterator2 end () const {
2131 return const_iterator2 ((*this) ());
2134 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2135 typename self_type::
2137 const_reverse_iterator2 rbegin () const {
2138 return const_reverse_iterator2 (end ());
2141 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2142 typename self_type::
2144 const_reverse_iterator2 rend () const {
2145 return const_reverse_iterator2 (begin ());
2151 size_type index1 () const {
2152 BOOST_UBLAS_CHECK_FALSE (bad_index ());
2153 return 0; // arbitary return value
2156 size_type index2 () const {
2157 BOOST_UBLAS_CHECK_FALSE (bad_index ());
2158 return 0; // arbitary return value
2163 const_iterator1 &operator = (const const_iterator1 &it) {
2164 container_const_reference<self_type>::assign (&it ());
2170 bool operator == (const const_iterator1 &it) const {
2171 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2176 typedef const_iterator1 iterator1;
2179 const_iterator1 begin1 () const {
2180 return const_iterator1 (*this);
2183 const_iterator1 end1 () const {
2184 return const_iterator1 (*this);
2187 class const_iterator2:
2188 public container_const_reference<zero_matrix>,
2189 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
2190 const_iterator2, value_type> {
2192 typedef typename zero_matrix::value_type value_type;
2193 typedef typename zero_matrix::difference_type difference_type;
2194 typedef typename zero_matrix::const_reference reference;
2195 typedef typename zero_matrix::const_pointer pointer;
2197 typedef const_iterator1 dual_iterator_type;
2198 typedef const_reverse_iterator1 dual_reverse_iterator_type;
2200 // Construction and destruction
2203 container_const_reference<self_type> () {}
2205 const_iterator2 (const self_type &m):
2206 container_const_reference<self_type> (m) {}
2210 const_iterator2 &operator ++ () {
2211 BOOST_UBLAS_CHECK_FALSE (bad_index ());
2215 const_iterator2 &operator -- () {
2216 BOOST_UBLAS_CHECK_FALSE (bad_index ());
2222 const_reference operator * () const {
2223 BOOST_UBLAS_CHECK_FALSE (bad_index ());
2224 return zero_; // arbitary return value
2227 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2229 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2230 typename self_type::
2232 const_iterator1 begin () const {
2233 return const_iterator1 ((*this) ());
2236 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2237 typename self_type::
2239 const_iterator1 end () const {
2240 return const_iterator1 ((*this) ());
2243 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2244 typename self_type::
2246 const_reverse_iterator1 rbegin () const {
2247 return const_reverse_iterator1 (end ());
2250 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2251 typename self_type::
2253 const_reverse_iterator1 rend () const {
2254 return const_reverse_iterator1 (begin ());
2260 size_type index1 () const {
2261 BOOST_UBLAS_CHECK_FALSE (bad_index ());
2262 return 0; // arbitary return value
2265 size_type index2 () const {
2266 BOOST_UBLAS_CHECK_FALSE (bad_index ());
2267 return 0; // arbitary return value
2272 const_iterator2 &operator = (const const_iterator2 &it) {
2273 container_const_reference<self_type>::assign (&it ());
2279 bool operator == (const const_iterator2 &it) const {
2280 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2285 typedef const_iterator2 iterator2;
2288 const_iterator2 begin2 () const {
2289 return find2 (0, 0, 0);
2292 const_iterator2 end2 () const {
2293 return find2 (0, 0, size2_);
2296 // Reverse iterators
2299 const_reverse_iterator1 rbegin1 () const {
2300 return const_reverse_iterator1 (end1 ());
2303 const_reverse_iterator1 rend1 () const {
2304 return const_reverse_iterator1 (begin1 ());
2308 const_reverse_iterator2 rbegin2 () const {
2309 return const_reverse_iterator2 (end2 ());
2312 const_reverse_iterator2 rend2 () const {
2313 return const_reverse_iterator2 (begin2 ());
2319 static const value_type zero_;
2323 const typename zero_matrix<T>::value_type zero_matrix<T>::zero_ (0);
2326 // Identity matrix class
2328 class identity_matrix:
2329 public matrix_container<identity_matrix<T> > {
2331 typedef const T *const_pointer;
2332 typedef identity_matrix<T> self_type;
2334 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2335 using matrix_container<self_type>::operator ();
2337 typedef std::size_t size_type;
2338 typedef std::ptrdiff_t difference_type;
2339 typedef T value_type;
2340 typedef const T &const_reference;
2341 typedef T &reference;
2342 typedef const matrix_reference<const self_type> const_closure_type;
2343 typedef matrix_reference<self_type> closure_type;
2344 typedef sparse_tag storage_category;
2345 typedef unknown_orientation_tag orientation_category;
2347 // Construction and destruction
2350 matrix_container<self_type> (),
2351 size1_ (0), size2_ (0), size_common_ (0) {}
2353 identity_matrix (size_type size):
2354 matrix_container<self_type> (),
2355 size1_ (size), size2_ (size), size_common_ ((std::min) (size1_, size2_)) {}
2357 identity_matrix (size_type size1, size_type size2):
2358 matrix_container<self_type> (),
2359 size1_ (size1), size2_ (size2), size_common_ ((std::min) (size1_, size2_)) {}
2361 identity_matrix (const identity_matrix &m):
2362 matrix_container<self_type> (),
2363 size1_ (m.size1_), size2_ (m.size2_), size_common_ ((std::min) (size1_, size2_)) {}
2367 size_type size1 () const {
2371 size_type size2 () const {
2377 void resize (size_type size, bool preserve = true) {
2382 void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
2389 const_reference operator () (size_type i, size_type j) const {
2398 identity_matrix &operator = (const identity_matrix &m) {
2404 identity_matrix &assign_temporary (identity_matrix &m) {
2411 void swap (identity_matrix &m) {
2413 std::swap (size1_, m.size1_);
2414 std::swap (size2_, m.size2_);
2418 friend void swap (identity_matrix &m1, identity_matrix &m2) {
2425 typedef size_type const_subiterator_type;
2428 class const_iterator1;
2429 class const_iterator2;
2430 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2431 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2435 const_iterator1 find1 (int rank, size_type i, size_type j) const {
2437 i = (std::max) (i, j);
2438 i = (std::min) (i, j + 1);
2440 return const_iterator1 (*this, i);
2443 const_iterator2 find2 (int rank, size_type i, size_type j) const {
2445 j = (std::max) (j, i);
2446 j = (std::min) (j, i + 1);
2448 return const_iterator2 (*this, j);
2452 class const_iterator1:
2453 public container_const_reference<identity_matrix>,
2454 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
2455 const_iterator1, value_type> {
2457 typedef typename identity_matrix::value_type value_type;
2458 typedef typename identity_matrix::difference_type difference_type;
2459 typedef typename identity_matrix::const_reference reference;
2460 typedef typename identity_matrix::const_pointer pointer;
2462 typedef const_iterator2 dual_iterator_type;
2463 typedef const_reverse_iterator2 dual_reverse_iterator_type;
2465 // Construction and destruction
2468 container_const_reference<self_type> (), it_ () {}
2470 const_iterator1 (const self_type &m, const const_subiterator_type &it):
2471 container_const_reference<self_type> (m), it_ (it) {}
2475 const_iterator1 &operator ++ () {
2476 BOOST_UBLAS_CHECK (it_ < (*this) ().size1 (), bad_index ());
2481 const_iterator1 &operator -- () {
2482 BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
2489 const_reference operator * () const {
2493 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2495 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2496 typename self_type::
2498 const_iterator2 begin () const {
2499 return const_iterator2 ((*this) (), it_);
2502 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2503 typename self_type::
2505 const_iterator2 end () const {
2506 return const_iterator2 ((*this) (), it_ + 1);
2509 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2510 typename self_type::
2512 const_reverse_iterator2 rbegin () const {
2513 return const_reverse_iterator2 (end ());
2516 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2517 typename self_type::
2519 const_reverse_iterator2 rend () const {
2520 return const_reverse_iterator2 (begin ());
2526 size_type index1 () const {
2530 size_type index2 () const {
2536 const_iterator1 &operator = (const const_iterator1 &it) {
2537 container_const_reference<self_type>::assign (&it ());
2544 bool operator == (const const_iterator1 &it) const {
2545 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2546 return it_ == it.it_;
2550 const_subiterator_type it_;
2553 typedef const_iterator1 iterator1;
2556 const_iterator1 begin1 () const {
2557 return const_iterator1 (*this, 0);
2560 const_iterator1 end1 () const {
2561 return const_iterator1 (*this, size_common_);
2564 class const_iterator2:
2565 public container_const_reference<identity_matrix>,
2566 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
2567 const_iterator2, value_type> {
2569 typedef typename identity_matrix::value_type value_type;
2570 typedef typename identity_matrix::difference_type difference_type;
2571 typedef typename identity_matrix::const_reference reference;
2572 typedef typename identity_matrix::const_pointer pointer;
2574 typedef const_iterator1 dual_iterator_type;
2575 typedef const_reverse_iterator1 dual_reverse_iterator_type;
2577 // Construction and destruction
2580 container_const_reference<self_type> (), it_ () {}
2582 const_iterator2 (const self_type &m, const const_subiterator_type &it):
2583 container_const_reference<self_type> (m), it_ (it) {}
2587 const_iterator2 &operator ++ () {
2588 BOOST_UBLAS_CHECK (it_ < (*this) ().size_common_, bad_index ());
2593 const_iterator2 &operator -- () {
2594 BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
2601 const_reference operator * () const {
2605 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2607 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2608 typename self_type::
2610 const_iterator1 begin () const {
2611 return const_iterator1 ((*this) (), it_);
2614 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2615 typename self_type::
2617 const_iterator1 end () const {
2618 return const_iterator1 ((*this) (), it_ + 1);
2621 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2622 typename self_type::
2624 const_reverse_iterator1 rbegin () const {
2625 return const_reverse_iterator1 (end ());
2628 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2629 typename self_type::
2631 const_reverse_iterator1 rend () const {
2632 return const_reverse_iterator1 (begin ());
2638 size_type index1 () const {
2642 size_type index2 () const {
2648 const_iterator2 &operator = (const const_iterator2 &it) {
2649 container_const_reference<self_type>::assign (&it ());
2656 bool operator == (const const_iterator2 &it) const {
2657 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2658 return it_ == it.it_;
2662 const_subiterator_type it_;
2665 typedef const_iterator2 iterator2;
2668 const_iterator2 begin2 () const {
2669 return const_iterator2 (*this, 0);
2672 const_iterator2 end2 () const {
2673 return const_iterator2 (*this, size_common_);
2676 // Reverse iterators
2679 const_reverse_iterator1 rbegin1 () const {
2680 return const_reverse_iterator1 (end1 ());
2683 const_reverse_iterator1 rend1 () const {
2684 return const_reverse_iterator1 (begin1 ());
2688 const_reverse_iterator2 rbegin2 () const {
2689 return const_reverse_iterator2 (end2 ());
2692 const_reverse_iterator2 rend2 () const {
2693 return const_reverse_iterator2 (begin2 ());
2699 size_type size_common_;
2700 static const value_type zero_;
2701 static const value_type one_;
2705 const typename identity_matrix<T>::value_type identity_matrix<T>::zero_ (0);
2707 const typename identity_matrix<T>::value_type identity_matrix<T>::one_ (1);
2710 // Scalar matrix class
2712 class scalar_matrix:
2713 public matrix_container<scalar_matrix<T> > {
2715 typedef const T *const_pointer;
2716 typedef scalar_matrix<T> self_type;
2718 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2719 using matrix_container<self_type>::operator ();
2721 typedef std::size_t size_type;
2722 typedef std::ptrdiff_t difference_type;
2723 typedef T value_type;
2724 typedef const T &const_reference;
2725 typedef T &reference;
2726 typedef const matrix_reference<const self_type> const_closure_type;
2727 typedef dense_tag storage_category;
2728 typedef unknown_orientation_tag orientation_category;
2730 // Construction and destruction
2733 matrix_container<self_type> (),
2734 size1_ (0), size2_ (0), value_ () {}
2736 scalar_matrix (size_type size1, size_type size2, const value_type &value = value_type(1)):
2737 matrix_container<self_type> (),
2738 size1_ (size1), size2_ (size2), value_ (value) {}
2740 scalar_matrix (const scalar_matrix &m):
2741 matrix_container<self_type> (),
2742 size1_ (m.size1_), size2_ (m.size2_), value_ (m.value_) {}
2746 size_type size1 () const {
2750 size_type size2 () const {
2756 void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
2763 const_reference operator () (size_type /*i*/, size_type /*j*/) const {
2769 scalar_matrix &operator = (const scalar_matrix &m) {
2776 scalar_matrix &assign_temporary (scalar_matrix &m) {
2783 void swap (scalar_matrix &m) {
2785 std::swap (size1_, m.size1_);
2786 std::swap (size2_, m.size2_);
2787 std::swap (value_, m.value_);
2791 friend void swap (scalar_matrix &m1, scalar_matrix &m2) {
2798 typedef size_type const_subiterator_type;
2801 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2802 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
2803 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
2804 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
2805 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
2807 class const_iterator1;
2808 class const_iterator2;
2810 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2811 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2815 const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
2816 return const_iterator1 (*this, i, j);
2819 const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
2820 return const_iterator2 (*this, i, j);
2824 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2825 class const_iterator1:
2826 public container_const_reference<scalar_matrix>,
2827 public random_access_iterator_base<dense_random_access_iterator_tag,
2828 const_iterator1, value_type> {
2830 typedef typename scalar_matrix::value_type value_type;
2831 typedef typename scalar_matrix::difference_type difference_type;
2832 typedef typename scalar_matrix::const_reference reference;
2833 typedef typename scalar_matrix::const_pointer pointer;
2835 typedef const_iterator2 dual_iterator_type;
2836 typedef const_reverse_iterator2 dual_reverse_iterator_type;
2838 // Construction and destruction
2841 container_const_reference<scalar_matrix> (), it1_ (), it2_ () {}
2843 const_iterator1 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2):
2844 container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {}
2848 const_iterator1 &operator ++ () {
2853 const_iterator1 &operator -- () {
2858 const_iterator1 &operator += (difference_type n) {
2863 const_iterator1 &operator -= (difference_type n) {
2868 difference_type operator - (const const_iterator1 &it) const {
2869 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2870 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
2871 return it1_ - it.it1_;
2876 const_reference operator * () const {
2877 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
2878 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
2879 return (*this) () (index1 (), index2 ());
2882 const_reference operator [] (difference_type n) const {
2883 return *(*this + n);
2886 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2888 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2889 typename self_type::
2891 const_iterator2 begin () const {
2892 const scalar_matrix &m = (*this) ();
2893 return m.find2 (1, index1 (), 0);
2896 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2897 typename self_type::
2899 const_iterator2 end () const {
2900 const scalar_matrix &m = (*this) ();
2901 return m.find2 (1, index1 (), m.size2 ());
2904 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2905 typename self_type::
2907 const_reverse_iterator2 rbegin () const {
2908 return const_reverse_iterator2 (end ());
2911 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2912 typename self_type::
2914 const_reverse_iterator2 rend () const {
2915 return const_reverse_iterator2 (begin ());
2921 size_type index1 () const {
2925 size_type index2 () const {
2931 const_iterator1 &operator = (const const_iterator1 &it) {
2932 container_const_reference<scalar_matrix>::assign (&it ());
2940 bool operator == (const const_iterator1 &it) const {
2941 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2942 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
2943 return it1_ == it.it1_;
2946 bool operator < (const const_iterator1 &it) const {
2947 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2948 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
2949 return it1_ < it.it1_;
2953 const_subiterator_type it1_;
2954 const_subiterator_type it2_;
2957 typedef const_iterator1 iterator1;
2961 const_iterator1 begin1 () const {
2962 return find1 (0, 0, 0);
2965 const_iterator1 end1 () const {
2966 return find1 (0, size1_, 0);
2969 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2970 class const_iterator2:
2971 public container_const_reference<scalar_matrix>,
2972 public random_access_iterator_base<dense_random_access_iterator_tag,
2973 const_iterator2, value_type> {
2975 typedef typename scalar_matrix::value_type value_type;
2976 typedef typename scalar_matrix::difference_type difference_type;
2977 typedef typename scalar_matrix::const_reference reference;
2978 typedef typename scalar_matrix::const_pointer pointer;
2980 typedef const_iterator1 dual_iterator_type;
2981 typedef const_reverse_iterator1 dual_reverse_iterator_type;
2983 // Construction and destruction
2986 container_const_reference<scalar_matrix> (), it1_ (), it2_ () {}
2988 const_iterator2 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2):
2989 container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {}
2993 const_iterator2 &operator ++ () {
2998 const_iterator2 &operator -- () {
3003 const_iterator2 &operator += (difference_type n) {
3008 const_iterator2 &operator -= (difference_type n) {
3013 difference_type operator - (const const_iterator2 &it) const {
3014 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3015 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3016 return it2_ - it.it2_;
3021 const_reference operator * () const {
3022 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
3023 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
3024 return (*this) () (index1 (), index2 ());
3027 const_reference operator [] (difference_type n) const {
3028 return *(*this + n);
3031 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3033 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3034 typename self_type::
3036 const_iterator1 begin () const {
3037 const scalar_matrix &m = (*this) ();
3038 return m.find1 (1, 0, index2 ());
3041 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3042 typename self_type::
3044 const_iterator1 end () const {
3045 const scalar_matrix &m = (*this) ();
3046 return m.find1 (1, m.size1 (), index2 ());
3049 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3050 typename self_type::
3052 const_reverse_iterator1 rbegin () const {
3053 return const_reverse_iterator1 (end ());
3056 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3057 typename self_type::
3059 const_reverse_iterator1 rend () const {
3060 return const_reverse_iterator1 (begin ());
3066 size_type index1 () const {
3070 size_type index2 () const {
3076 const_iterator2 &operator = (const const_iterator2 &it) {
3077 container_const_reference<scalar_matrix>::assign (&it ());
3085 bool operator == (const const_iterator2 &it) const {
3086 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3087 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3088 return it2_ == it.it2_;
3091 bool operator < (const const_iterator2 &it) const {
3092 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3093 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3094 return it2_ < it.it2_;
3098 const_subiterator_type it1_;
3099 const_subiterator_type it2_;
3102 typedef const_iterator2 iterator2;
3106 const_iterator2 begin2 () const {
3107 return find2 (0, 0, 0);
3110 const_iterator2 end2 () const {
3111 return find2 (0, 0, size2_);
3114 // Reverse iterators
3117 const_reverse_iterator1 rbegin1 () const {
3118 return const_reverse_iterator1 (end1 ());
3121 const_reverse_iterator1 rend1 () const {
3122 return const_reverse_iterator1 (begin1 ());
3126 const_reverse_iterator2 rbegin2 () const {
3127 return const_reverse_iterator2 (end2 ());
3130 const_reverse_iterator2 rend2 () const {
3131 return const_reverse_iterator2 (begin2 ());
3141 // Array based matrix class
3142 template<class T, std::size_t N, std::size_t M>
3144 public matrix_container<c_matrix<T, N, M> > {
3146 typedef c_matrix<T, N, M> self_type;
3148 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
3149 using matrix_container<self_type>::operator ();
3151 typedef std::size_t size_type;
3152 typedef std::ptrdiff_t difference_type;
3153 typedef T value_type;
3154 typedef const T &const_reference;
3155 typedef T &reference;
3156 typedef const T *const_pointer;
3158 typedef const matrix_reference<const self_type> const_closure_type;
3159 typedef matrix_reference<self_type> closure_type;
3160 typedef c_vector<T, N * M> vector_temporary_type; // vector able to store all elements of c_matrix
3161 typedef self_type matrix_temporary_type;
3162 typedef dense_tag storage_category;
3163 // This could be better for performance,
3164 // typedef typename unknown_orientation_tag orientation_category;
3165 // but others depend on the orientation information...
3166 typedef row_major_tag orientation_category;
3168 // Construction and destruction
3171 size1_ (N), size2_ (M) /* , data_ () */ {
3174 c_matrix (size_type size1, size_type size2):
3175 size1_ (size1), size2_ (size2) /* , data_ () */ {
3176 if (size1_ > N || size2_ > M)
3177 bad_size ().raise ();
3180 c_matrix (const c_matrix &m):
3181 size1_ (m.size1_), size2_ (m.size2_) /* , data_ () */ {
3182 if (size1_ > N || size2_ > M)
3183 bad_size ().raise ();
3188 c_matrix (const matrix_expression<AE> &ae):
3189 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()) /* , data_ () */ {
3190 if (size1_ > N || size2_ > M)
3191 bad_size ().raise ();
3192 matrix_assign<scalar_assign> (*this, ae);
3197 size_type size1 () const {
3201 size_type size2 () const {
3205 const_pointer data () const {
3206 return reinterpret_cast<const_pointer> (data_);
3210 return reinterpret_cast<pointer> (data_);
3215 void resize (size_type size1, size_type size2, bool preserve = true) {
3216 if (size1 > N || size2 > M)
3217 bad_size ().raise ();
3219 self_type temporary (size1, size2);
3220 // Common elements to preserve
3221 const size_type size1_min = (std::min) (size1, size1_);
3222 const size_type size2_min = (std::min) (size2, size2_);
3223 for (size_type i = 0; i != size1_min; ++i) { // indexing copy over major
3224 for (size_type j = 0; j != size2_min; ++j) {
3225 temporary.data_[i][j] = data_[i][j];
3228 assign_temporary (temporary);
3238 const_reference operator () (size_type i, size_type j) const {
3239 BOOST_UBLAS_CHECK (i < size1_, bad_index ());
3240 BOOST_UBLAS_CHECK (j < size2_, bad_index ());
3241 return data_ [i] [j];
3244 reference at_element (size_type i, size_type j) {
3245 BOOST_UBLAS_CHECK (i < size1_, bad_index ());
3246 BOOST_UBLAS_CHECK (j < size2_, bad_index ());
3247 return data_ [i] [j];
3250 reference operator () (size_type i, size_type j) {
3251 return at_element (i, j);
3254 // Element assignment
3256 reference insert_element (size_type i, size_type j, const_reference t) {
3257 return (at_element (i, j) = t);
3263 for (size_type i = 0; i < size1_; ++ i)
3264 std::fill (data_ [i], data_ [i] + size2_, value_type/*zero*/());
3269 c_matrix &operator = (const c_matrix &m) {
3272 for (size_type i = 0; i < m.size1_; ++ i)
3273 std::copy (m.data_ [i], m.data_ [i] + m.size2_, data_ [i]);
3276 template<class C> // Container assignment without temporary
3278 c_matrix &operator = (const matrix_container<C> &m) {
3279 resize (m ().size1 (), m ().size2 (), false);
3284 c_matrix &assign_temporary (c_matrix &m) {
3290 c_matrix &operator = (const matrix_expression<AE> &ae) {
3291 self_type temporary (ae);
3292 return assign_temporary (temporary);
3296 c_matrix &assign (const matrix_expression<AE> &ae) {
3297 matrix_assign<scalar_assign> (*this, ae);
3302 c_matrix& operator += (const matrix_expression<AE> &ae) {
3303 self_type temporary (*this + ae);
3304 return assign_temporary (temporary);
3306 template<class C> // Container assignment without temporary
3308 c_matrix &operator += (const matrix_container<C> &m) {
3314 c_matrix &plus_assign (const matrix_expression<AE> &ae) {
3315 matrix_assign<scalar_plus_assign> (*this, ae);
3320 c_matrix& operator -= (const matrix_expression<AE> &ae) {
3321 self_type temporary (*this - ae);
3322 return assign_temporary (temporary);
3324 template<class C> // Container assignment without temporary
3326 c_matrix &operator -= (const matrix_container<C> &m) {
3332 c_matrix &minus_assign (const matrix_expression<AE> &ae) {
3333 matrix_assign<scalar_minus_assign> (*this, ae);
3338 c_matrix& operator *= (const AT &at) {
3339 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
3344 c_matrix& operator /= (const AT &at) {
3345 matrix_assign_scalar<scalar_divides_assign> (*this, at);
3351 void swap (c_matrix &m) {
3353 BOOST_UBLAS_CHECK (size1_ == m.size1_, bad_size ());
3354 BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ());
3355 std::swap (size1_, m.size1_);
3356 std::swap (size2_, m.size2_);
3357 for (size_type i = 0; i < size1_; ++ i)
3358 std::swap_ranges (data_ [i], data_ [i] + size2_, m.data_ [i]);
3362 friend void swap (c_matrix &m1, c_matrix &m2) {
3368 // Use pointers for iterator
3369 typedef const_pointer const_subiterator_type;
3370 typedef pointer subiterator_type;
3373 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3374 typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
3375 typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
3376 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
3377 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
3379 class const_iterator1;
3381 class const_iterator2;
3384 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
3385 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
3386 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
3387 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
3391 const_iterator1 find1 (int rank, size_type i, size_type j) const {
3392 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3393 return const_iterator1 (*this, i, j);
3395 return const_iterator1 (*this, &data_ [i] [j]);
3399 iterator1 find1 (int rank, size_type i, size_type j) {
3400 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3401 return iterator1 (*this, i, j);
3403 return iterator1 (*this, &data_ [i] [j]);
3407 const_iterator2 find2 (int rank, size_type i, size_type j) const {
3408 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3409 return const_iterator2 (*this, i, j);
3411 return const_iterator2 (*this, &data_ [i] [j]);
3415 iterator2 find2 (int rank, size_type i, size_type j) {
3416 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3417 return iterator2 (*this, i, j);
3419 return iterator2 (*this, &data_ [i] [j]);
3424 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3425 class const_iterator1:
3426 public container_const_reference<c_matrix>,
3427 public random_access_iterator_base<dense_random_access_iterator_tag,
3428 const_iterator1, value_type> {
3430 typedef typename c_matrix::difference_type difference_type;
3431 typedef typename c_matrix::value_type value_type;
3432 typedef typename c_matrix::const_reference reference;
3433 typedef typename c_matrix::const_pointer pointer;
3435 typedef const_iterator2 dual_iterator_type;
3436 typedef const_reverse_iterator2 dual_reverse_iterator_type;
3438 // Construction and destruction
3441 container_const_reference<self_type> (), it_ () {}
3443 const_iterator1 (const self_type &m, const const_subiterator_type &it):
3444 container_const_reference<self_type> (m), it_ (it) {}
3446 const_iterator1 (const iterator1 &it):
3447 container_const_reference<self_type> (it ()), it_ (it.it_) {}
3451 const_iterator1 &operator ++ () {
3456 const_iterator1 &operator -- () {
3461 const_iterator1 &operator += (difference_type n) {
3466 const_iterator1 &operator -= (difference_type n) {
3471 difference_type operator - (const const_iterator1 &it) const {
3472 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3473 return (it_ - it.it_) / M;
3478 const_reference operator * () const {
3479 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
3480 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
3484 const_reference operator [] (difference_type n) const {
3485 return *(*this + n);
3488 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3490 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3491 typename self_type::
3493 const_iterator2 begin () const {
3494 const self_type &m = (*this) ();
3495 return m.find2 (1, index1 (), 0);
3498 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3499 typename self_type::
3501 const_iterator2 end () const {
3502 const self_type &m = (*this) ();
3503 return m.find2 (1, index1 (), m.size2 ());
3506 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3507 typename self_type::
3509 const_reverse_iterator2 rbegin () const {
3510 return const_reverse_iterator2 (end ());
3513 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3514 typename self_type::
3516 const_reverse_iterator2 rend () const {
3517 return const_reverse_iterator2 (begin ());
3523 size_type index1 () const {
3524 const self_type &m = (*this) ();
3525 return (it_ - m.begin1 ().it_) / M;
3528 size_type index2 () const {
3529 const self_type &m = (*this) ();
3530 return (it_ - m.begin1 ().it_) % M;
3535 const_iterator1 &operator = (const const_iterator1 &it) {
3536 container_const_reference<self_type>::assign (&it ());
3543 bool operator == (const const_iterator1 &it) const {
3544 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3545 return it_ == it.it_;
3548 bool operator < (const const_iterator1 &it) const {
3549 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3550 return it_ < it.it_;
3554 const_subiterator_type it_;
3556 friend class iterator1;
3561 const_iterator1 begin1 () const {
3562 return find1 (0, 0, 0);
3565 const_iterator1 end1 () const {
3566 return find1 (0, size1_, 0);
3569 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3571 public container_reference<c_matrix>,
3572 public random_access_iterator_base<dense_random_access_iterator_tag,
3573 iterator1, value_type> {
3576 typedef typename c_matrix::difference_type difference_type;
3577 typedef typename c_matrix::value_type value_type;
3578 typedef typename c_matrix::reference reference;
3579 typedef typename c_matrix::pointer pointer;
3581 typedef iterator2 dual_iterator_type;
3582 typedef reverse_iterator2 dual_reverse_iterator_type;
3584 // Construction and destruction
3587 container_reference<self_type> (), it_ () {}
3589 iterator1 (self_type &m, const subiterator_type &it):
3590 container_reference<self_type> (m), it_ (it) {}
3594 iterator1 &operator ++ () {
3599 iterator1 &operator -- () {
3604 iterator1 &operator += (difference_type n) {
3609 iterator1 &operator -= (difference_type n) {
3614 difference_type operator - (const iterator1 &it) const {
3615 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3616 return (it_ - it.it_) / M;
3621 reference operator * () const {
3622 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
3623 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
3627 reference operator [] (difference_type n) const {
3628 return *(*this + n);
3631 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3633 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3634 typename self_type::
3636 iterator2 begin () const {
3637 self_type &m = (*this) ();
3638 return m.find2 (1, index1 (), 0);
3641 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3642 typename self_type::
3644 iterator2 end () const {
3645 self_type &m = (*this) ();
3646 return m.find2 (1, index1 (), m.size2 ());
3649 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3650 typename self_type::
3652 reverse_iterator2 rbegin () const {
3653 return reverse_iterator2 (end ());
3656 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3657 typename self_type::
3659 reverse_iterator2 rend () const {
3660 return reverse_iterator2 (begin ());
3666 size_type index1 () const {
3667 const self_type &m = (*this) ();
3668 return (it_ - m.begin1 ().it_) / M;
3671 size_type index2 () const {
3672 const self_type &m = (*this) ();
3673 return (it_ - m.begin1 ().it_) % M;
3678 iterator1 &operator = (const iterator1 &it) {
3679 container_reference<self_type>::assign (&it ());
3686 bool operator == (const iterator1 &it) const {
3687 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3688 return it_ == it.it_;
3691 bool operator < (const iterator1 &it) const {
3692 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3693 return it_ < it.it_;
3697 subiterator_type it_;
3699 friend class const_iterator1;
3704 iterator1 begin1 () {
3705 return find1 (0, 0, 0);
3709 return find1 (0, size1_, 0);
3712 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3713 class const_iterator2:
3714 public container_const_reference<c_matrix>,
3715 public random_access_iterator_base<dense_random_access_iterator_tag,
3716 const_iterator2, value_type> {
3718 typedef typename c_matrix::difference_type difference_type;
3719 typedef typename c_matrix::value_type value_type;
3720 typedef typename c_matrix::const_reference reference;
3721 typedef typename c_matrix::const_reference pointer;
3723 typedef const_iterator1 dual_iterator_type;
3724 typedef const_reverse_iterator1 dual_reverse_iterator_type;
3726 // Construction and destruction
3729 container_const_reference<self_type> (), it_ () {}
3731 const_iterator2 (const self_type &m, const const_subiterator_type &it):
3732 container_const_reference<self_type> (m), it_ (it) {}
3734 const_iterator2 (const iterator2 &it):
3735 container_const_reference<self_type> (it ()), it_ (it.it_) {}
3739 const_iterator2 &operator ++ () {
3744 const_iterator2 &operator -- () {
3749 const_iterator2 &operator += (difference_type n) {
3754 const_iterator2 &operator -= (difference_type n) {
3759 difference_type operator - (const const_iterator2 &it) const {
3760 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3761 return it_ - it.it_;
3766 const_reference operator * () const {
3767 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
3768 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
3772 const_reference operator [] (difference_type n) const {
3773 return *(*this + n);
3776 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3778 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3779 typename self_type::
3781 const_iterator1 begin () const {
3782 const self_type &m = (*this) ();
3783 return m.find1 (1, 0, index2 ());
3786 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3787 typename self_type::
3789 const_iterator1 end () const {
3790 const self_type &m = (*this) ();
3791 return m.find1 (1, m.size1 (), index2 ());
3794 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3795 typename self_type::
3797 const_reverse_iterator1 rbegin () const {
3798 return const_reverse_iterator1 (end ());
3801 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3802 typename self_type::
3804 const_reverse_iterator1 rend () const {
3805 return const_reverse_iterator1 (begin ());
3811 size_type index1 () const {
3812 const self_type &m = (*this) ();
3813 return (it_ - m.begin2 ().it_) / M;
3816 size_type index2 () const {
3817 const self_type &m = (*this) ();
3818 return (it_ - m.begin2 ().it_) % M;
3823 const_iterator2 &operator = (const const_iterator2 &it) {
3824 container_const_reference<self_type>::assign (&it ());
3831 bool operator == (const const_iterator2 &it) const {
3832 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3833 return it_ == it.it_;
3836 bool operator < (const const_iterator2 &it) const {
3837 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3838 return it_ < it.it_;
3842 const_subiterator_type it_;
3844 friend class iterator2;
3849 const_iterator2 begin2 () const {
3850 return find2 (0, 0, 0);
3853 const_iterator2 end2 () const {
3854 return find2 (0, 0, size2_);
3857 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3859 public container_reference<c_matrix>,
3860 public random_access_iterator_base<dense_random_access_iterator_tag,
3861 iterator2, value_type> {
3863 typedef typename c_matrix::difference_type difference_type;
3864 typedef typename c_matrix::value_type value_type;
3865 typedef typename c_matrix::reference reference;
3866 typedef typename c_matrix::pointer pointer;
3868 typedef iterator1 dual_iterator_type;
3869 typedef reverse_iterator1 dual_reverse_iterator_type;
3871 // Construction and destruction
3874 container_reference<self_type> (), it_ () {}
3876 iterator2 (self_type &m, const subiterator_type &it):
3877 container_reference<self_type> (m), it_ (it) {}
3881 iterator2 &operator ++ () {
3886 iterator2 &operator -- () {
3891 iterator2 &operator += (difference_type n) {
3896 iterator2 &operator -= (difference_type n) {
3901 difference_type operator - (const iterator2 &it) const {
3902 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3903 return it_ - it.it_;
3908 reference operator * () const {
3909 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
3910 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
3914 reference operator [] (difference_type n) const {
3915 return *(*this + n);
3918 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3920 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3921 typename self_type::
3923 iterator1 begin () const {
3924 self_type &m = (*this) ();
3925 return m.find1 (1, 0, index2 ());
3928 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3929 typename self_type::
3931 iterator1 end () const {
3932 self_type &m = (*this) ();
3933 return m.find1 (1, m.size1 (), index2 ());
3936 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3937 typename self_type::
3939 reverse_iterator1 rbegin () const {
3940 return reverse_iterator1 (end ());
3943 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3944 typename self_type::
3946 reverse_iterator1 rend () const {
3947 return reverse_iterator1 (begin ());
3953 size_type index1 () const {
3954 const self_type &m = (*this) ();
3955 return (it_ - m.begin2 ().it_) / M;
3958 size_type index2 () const {
3959 const self_type &m = (*this) ();
3960 return (it_ - m.begin2 ().it_) % M;
3965 iterator2 &operator = (const iterator2 &it) {
3966 container_reference<self_type>::assign (&it ());
3973 bool operator == (const iterator2 &it) const {
3974 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3975 return it_ == it.it_;
3978 bool operator < (const iterator2 &it) const {
3979 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3980 return it_ < it.it_;
3984 subiterator_type it_;
3986 friend class const_iterator2;
3991 iterator2 begin2 () {
3992 return find2 (0, 0, 0);
3996 return find2 (0, 0, size2_);
3999 // Reverse iterators
4002 const_reverse_iterator1 rbegin1 () const {
4003 return const_reverse_iterator1 (end1 ());
4006 const_reverse_iterator1 rend1 () const {
4007 return const_reverse_iterator1 (begin1 ());
4011 reverse_iterator1 rbegin1 () {
4012 return reverse_iterator1 (end1 ());
4015 reverse_iterator1 rend1 () {
4016 return reverse_iterator1 (begin1 ());
4020 const_reverse_iterator2 rbegin2 () const {
4021 return const_reverse_iterator2 (end2 ());
4024 const_reverse_iterator2 rend2 () const {
4025 return const_reverse_iterator2 (begin2 ());
4029 reverse_iterator2 rbegin2 () {
4030 return reverse_iterator2 (end2 ());
4033 reverse_iterator2 rend2 () {
4034 return reverse_iterator2 (begin2 ());
4040 value_type data_ [N] [M];