2 // Copyright (c) 2000-2010
3 // Joerg Walter, Mathias Koch, Gunter Winkler, David Bellot
4 // Copyright (c) 2014, Athanasios Iliopoulos
6 // Distributed under the Boost Software License, Version 1.0. (See
7 // accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
10 // The authors gratefully acknowledge the support of
11 // GeNeSys mbH & Co. KG in producing this work.
14 #ifndef _BOOST_UBLAS_MATRIX_
15 #define _BOOST_UBLAS_MATRIX_
17 #include <boost/config.hpp>
18 #include <boost/numeric/ublas/vector.hpp>
19 #include <boost/numeric/ublas/matrix_expression.hpp>
20 #include <boost/numeric/ublas/detail/matrix_assign.hpp>
21 #include <boost/serialization/collection_size_type.hpp>
22 #include <boost/serialization/array.hpp>
23 #include <boost/serialization/nvp.hpp>
25 // Iterators based on ideas of Jeremy Siek
27 namespace boost { namespace numeric {
29 /** \brief main namespace of uBLAS.
31 * Use this namespace for all operations with uBLAS. It can also be abbreviated with
32 * \code namespace ublas = boost::numeric::ublas; \endcode
34 * A common practice is to bring this namespace into the current scope with
35 * \code using namespace boost::numeric::ublas; \endcode.
37 * However, be warned that using the ublas namespace and the std::vector at the same time can lead to the compiler to confusion.
38 * The solution is simply to prefix each ublas vector like \c boost::numeric::ublas::vector<T>. If you think it's too long to
39 * write, you can define a new namespace like \c namespace ublas = boost::numeric::ublas and then just declare your vectors
40 * with \c ublas::vector<T>. STL vectors will be declared as vector<T>. No need to prefix with \c std::
45 using namespace boost::numeric::ublas;
47 // Matrix resizing algorithm
48 template <class L, class M>
50 void matrix_resize_preserve (M& m, M& temporary) {
51 typedef L layout_type;
52 typedef typename M::size_type size_type;
53 const size_type msize1 (m.size1 ()); // original size
54 const size_type msize2 (m.size2 ());
55 const size_type size1 (temporary.size1 ()); // new size is specified by temporary
56 const size_type size2 (temporary.size2 ());
57 // Common elements to preserve
58 const size_type size1_min = (std::min) (size1, msize1);
59 const size_type size2_min = (std::min) (size2, msize2);
60 // Order for major and minor sizes
61 const size_type major_size = layout_type::size_M (size1_min, size2_min);
62 const size_type minor_size = layout_type::size_m (size1_min, size2_min);
63 // Indexing copy over major
64 for (size_type major = 0; major != major_size; ++major) {
65 for (size_type minor = 0; minor != minor_size; ++minor) {
66 // find indexes - use invertability of element_ functions
67 const size_type i1 = layout_type::index_M(major, minor);
68 const size_type i2 = layout_type::index_m(major, minor);
69 temporary.data () [layout_type::element (i1, size1, i2, size2)] =
70 m.data() [layout_type::element (i1, msize1, i2, msize2)];
73 m.assign_temporary (temporary);
77 /** \brief A dense matrix of values of type \c T.
79 * For a \f$(m \times n)\f$-dimensional matrix and \f$ 0 \leq i < m, 0 \leq j < n\f$, every element \f$ m_{i,j} \f$ is mapped to
80 * the \f$(i.n + j)\f$-th element of the container for row major orientation or the \f$ (i + j.m) \f$-th element of
81 * the container for column major orientation. In a dense matrix all elements are represented in memory in a
82 * contiguous chunk of memory by definition.
84 * Orientation and storage can also be specified, otherwise a \c row_major and \c unbounded_array are used. It is \b not
85 * required by the storage to initialize elements of the matrix.
87 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
88 * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major
89 * \tparam A the type of Storage array. Default is \c unbounded_array
91 template<class T, class L, class A>
93 public matrix_container<matrix<T, L, A> > {
96 typedef L layout_type;
97 typedef matrix<T, L, A> self_type;
99 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
100 using matrix_container<self_type>::operator ();
102 typedef typename A::size_type size_type;
103 typedef typename A::difference_type difference_type;
104 typedef T value_type;
105 typedef const T &const_reference;
106 typedef T &reference;
107 typedef A array_type;
108 typedef const matrix_reference<const self_type> const_closure_type;
109 typedef matrix_reference<self_type> closure_type;
110 typedef vector<T, A> vector_temporary_type;
111 typedef self_type matrix_temporary_type;
112 typedef dense_tag storage_category;
113 // This could be better for performance,
114 // typedef typename unknown_orientation_tag orientation_category;
115 // but others depend on the orientation information...
116 typedef typename L::orientation_category orientation_category;
118 // Construction and destruction
120 /// Default dense matrix constructor. Make a dense matrix of size (0,0)
123 matrix_container<self_type> (),
124 size1_ (0), size2_ (0), data_ () {}
126 /** Dense matrix constructor with defined size
127 * \param size1 number of rows
128 * \param size2 number of columns
131 matrix (size_type size1, size_type size2):
132 matrix_container<self_type> (),
133 size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2)) {
136 /** Dense matrix constructor with defined size a initial value for all the matrix elements
137 * \param size1 number of rows
138 * \param size2 number of columns
139 * \param init initial value assigned to all elements
141 matrix (size_type size1, size_type size2, const value_type &init):
142 matrix_container<self_type> (),
143 size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2), init) {
146 /** Dense matrix constructor with defined size and an initial data array
147 * \param size1 number of rows
148 * \param size2 number of columns
149 * \param data array to copy into the matrix. Must have the same dimension as the matrix
152 matrix (size_type size1, size_type size2, const array_type &data):
153 matrix_container<self_type> (),
154 size1_ (size1), size2_ (size2), data_ (data) {}
156 /** Copy-constructor of a dense matrix
157 * \param m is a dense matrix
160 matrix (const matrix &m):
161 matrix_container<self_type> (),
162 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
164 /** Copy-constructor of a dense matrix from a matrix expression
165 * \param ae is a matrix expression
169 matrix (const matrix_expression<AE> &ae):
170 matrix_container<self_type> (),
171 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::storage_size (size1_, size2_)) {
172 matrix_assign<scalar_assign> (*this, ae);
176 /** Return the number of rows of the matrix
177 * You can also use the free size<>() function in operation/size.hpp as size<1>(m) where m is a matrix
180 size_type size1 () const {
184 /** Return the number of colums of the matrix
185 * You can also use the free size<>() function in operation/size.hpp as size<2>(m) where m is a matrix
188 size_type size2 () const {
193 /** Return a constant reference to the internal storage of a dense matrix, i.e. the raw data
194 * It's type depends on the type used by the matrix to store its data
197 const array_type &data () const {
200 /** Return a reference to the internal storage of a dense matrix, i.e. the raw data
201 * It's type depends on the type used by the matrix to store its data
204 array_type &data () {
209 /** Resize a matrix to new dimensions
210 * If data are preserved, then if the size if bigger at least on one dimension, extra values are filled with zeros.
211 * If data are not preserved, then nothing has to be assumed regarding the content of the matrix after resizing.
212 * \param size1 the new number of rows
213 * \param size2 the new number of colums
214 * \param preserve a boolean to say if one wants the data to be preserved during the resizing. Default is true.
217 void resize (size_type size1, size_type size2, bool preserve = true) {
219 self_type temporary (size1, size2);
220 detail::matrix_resize_preserve<layout_type> (*this, temporary);
223 data ().resize (layout_type::storage_size (size1, size2));
231 /** Access a matrix element. Here we return a const reference
232 * \param i the first coordinate of the element. By default it's the row
233 * \param j the second coordinate of the element. By default it's the column
234 * \return a const reference to the element
237 const_reference operator () (size_type i, size_type j) const {
238 return data () [layout_type::element (i, size1_, j, size2_)];
241 /** Access a matrix element. Here we return a reference
242 * \param i the first coordinate of the element. By default it's the row
243 * \param j the second coordinate of the element. By default it's the column
244 * \return a reference to the element
247 reference at_element (size_type i, size_type j) {
248 return data () [layout_type::element (i, size1_, j, size2_)];
251 /** Access a matrix element. Here we return a reference
252 * \param i the first coordinate of the element. By default it's the row
253 * \param j the second coordinate of the element. By default it's the column
254 * \return a reference to the element
257 reference operator () (size_type i, size_type j) {
258 return at_element (i, j);
261 // Element assignment
263 /** Change the value of a matrix element. Return back a reference to it
264 * \param i the first coordinate of the element. By default it's the row
265 * \param j the second coordinate of the element. By default it's the column
266 * \param t the new value of the element
267 * \return a reference to the newly changed element
270 reference insert_element (size_type i, size_type j, const_reference t) {
271 return (at_element (i, j) = t);
274 /** Erase the element
275 * For most types (int, double, etc...) it means setting 0 (zero) the element at zero in fact.
276 * For user-defined types, it could be another value if you decided it. Your type in that case must
277 * contain a default null value.
278 * \param i the first coordinate of the element. By default it's the row
279 * \param j the second coordinate of the element. By default it's the column
281 void erase_element (size_type i, size_type j) {
282 at_element (i, j) = value_type/*zero*/();
286 /** Erase all elements in the matrix
287 * For most types (int, double, etc...) it means writing 0 (zero) everywhere.
288 * For user-defined types, it could be another value if you decided it. Your type in that case must
289 * contain a default null value.
293 std::fill (data ().begin (), data ().end (), value_type/*zero*/());
297 #ifdef BOOST_UBLAS_MOVE_SEMANTICS
299 /*! @note "pass by value" the key idea to enable move semantics */
301 matrix &operator = (matrix m) {
307 matrix &operator = (const matrix &m) {
314 template<class C> // Container assignment without temporary
316 matrix &operator = (const matrix_container<C> &m) {
317 resize (m ().size1 (), m ().size2 (), false);
322 matrix &assign_temporary (matrix &m) {
328 matrix &operator = (const matrix_expression<AE> &ae) {
329 self_type temporary (ae);
330 return assign_temporary (temporary);
334 matrix &assign (const matrix_expression<AE> &ae) {
335 matrix_assign<scalar_assign> (*this, ae);
340 matrix& operator += (const matrix_expression<AE> &ae) {
341 self_type temporary (*this + ae);
342 return assign_temporary (temporary);
344 template<class C> // Container assignment without temporary
346 matrix &operator += (const matrix_container<C> &m) {
352 matrix &plus_assign (const matrix_expression<AE> &ae) {
353 matrix_assign<scalar_plus_assign> (*this, ae);
358 matrix& operator -= (const matrix_expression<AE> &ae) {
359 self_type temporary (*this - ae);
360 return assign_temporary (temporary);
362 template<class C> // Container assignment without temporary
364 matrix &operator -= (const matrix_container<C> &m) {
370 matrix &minus_assign (const matrix_expression<AE> &ae) {
371 matrix_assign<scalar_minus_assign> (*this, ae);
376 matrix& operator *= (const AT &at) {
377 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
382 matrix& operator /= (const AT &at) {
383 matrix_assign_scalar<scalar_divides_assign> (*this, at);
389 void swap (matrix &m) {
391 std::swap (size1_, m.size1_);
392 std::swap (size2_, m.size2_);
393 data ().swap (m.data ());
397 friend void swap (matrix &m1, matrix &m2) {
403 // Use the storage array iterator
404 typedef typename A::const_iterator const_subiterator_type;
405 typedef typename A::iterator subiterator_type;
408 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
409 typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
410 typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
411 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
412 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
414 class const_iterator1;
416 class const_iterator2;
419 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
420 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
421 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
422 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
426 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
427 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
428 return const_iterator1 (*this, i, j);
430 return const_iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
434 iterator1 find1 (int /* rank */, size_type i, size_type j) {
435 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
436 return iterator1 (*this, i, j);
438 return iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
442 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
443 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
444 return const_iterator2 (*this, i, j);
446 return const_iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
450 iterator2 find2 (int /* rank */, size_type i, size_type j) {
451 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
452 return iterator2 (*this, i, j);
454 return iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
459 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
460 class const_iterator1:
461 public container_const_reference<matrix>,
462 public random_access_iterator_base<dense_random_access_iterator_tag,
463 const_iterator1, value_type> {
465 typedef typename matrix::value_type value_type;
466 typedef typename matrix::difference_type difference_type;
467 typedef typename matrix::const_reference reference;
468 typedef const typename matrix::pointer pointer;
470 typedef const_iterator2 dual_iterator_type;
471 typedef const_reverse_iterator2 dual_reverse_iterator_type;
473 // Construction and destruction
476 container_const_reference<self_type> (), it_ () {}
478 const_iterator1 (const self_type &m, const const_subiterator_type &it):
479 container_const_reference<self_type> (m), it_ (it) {}
481 const_iterator1 (const iterator1 &it):
482 container_const_reference<self_type> (it ()), it_ (it.it_) {}
486 const_iterator1 &operator ++ () {
487 layout_type::increment_i (it_, (*this) ().size1 (), (*this) ().size2 ());
491 const_iterator1 &operator -- () {
492 layout_type::decrement_i (it_, (*this) ().size1 (), (*this) ().size2 ());
496 const_iterator1 &operator += (difference_type n) {
497 layout_type::increment_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
501 const_iterator1 &operator -= (difference_type n) {
502 layout_type::decrement_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
506 difference_type operator - (const const_iterator1 &it) const {
507 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
508 return layout_type::distance_i (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
513 const_reference operator * () const {
514 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
515 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
519 const_reference operator [] (difference_type n) const {
523 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
525 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
528 const_iterator2 begin () const {
529 const self_type &m = (*this) ();
530 return m.find2 (1, index1 (), 0);
533 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
536 const_iterator2 cbegin () const {
540 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
543 const_iterator2 end () const {
544 const self_type &m = (*this) ();
545 return m.find2 (1, index1 (), m.size2 ());
548 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
551 const_iterator2 cend () const {
555 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
558 const_reverse_iterator2 rbegin () const {
559 return const_reverse_iterator2 (end ());
562 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
565 const_reverse_iterator2 crbegin () const {
569 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
572 const_reverse_iterator2 rend () const {
573 return const_reverse_iterator2 (begin ());
576 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
579 const_reverse_iterator2 crend () const {
586 size_type index1 () const {
587 const self_type &m = (*this) ();
588 return layout_type::index_i (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
591 size_type index2 () const {
592 const self_type &m = (*this) ();
593 return layout_type::index_j (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
598 const_iterator1 &operator = (const const_iterator1 &it) {
599 container_const_reference<self_type>::assign (&it ());
606 bool operator == (const const_iterator1 &it) const {
607 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
608 return it_ == it.it_;
611 bool operator < (const const_iterator1 &it) const {
612 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
617 const_subiterator_type it_;
619 friend class iterator1;
624 const_iterator1 begin1 () const {
625 return find1 (0, 0, 0);
628 const_iterator1 cbegin1 () const {
632 const_iterator1 end1 () const {
633 return find1 (0, size1_, 0);
636 const_iterator1 cend1 () const {
640 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
642 public container_reference<matrix>,
643 public random_access_iterator_base<dense_random_access_iterator_tag,
644 iterator1, value_type> {
646 typedef typename matrix::value_type value_type;
647 typedef typename matrix::difference_type difference_type;
648 typedef typename matrix::reference reference;
649 typedef typename matrix::pointer pointer;
651 typedef iterator2 dual_iterator_type;
652 typedef reverse_iterator2 dual_reverse_iterator_type;
654 // Construction and destruction
657 container_reference<self_type> (), it_ () {}
659 iterator1 (self_type &m, const subiterator_type &it):
660 container_reference<self_type> (m), it_ (it) {}
664 iterator1 &operator ++ () {
665 layout_type::increment_i (it_, (*this) ().size1 (), (*this) ().size2 ());
669 iterator1 &operator -- () {
670 layout_type::decrement_i (it_, (*this) ().size1 (), (*this) ().size2 ());
674 iterator1 &operator += (difference_type n) {
675 layout_type::increment_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
679 iterator1 &operator -= (difference_type n) {
680 layout_type::decrement_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
684 difference_type operator - (const iterator1 &it) const {
685 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
686 return layout_type::distance_i (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
691 reference operator * () const {
692 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
693 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
697 reference operator [] (difference_type n) const {
701 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
703 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
706 iterator2 begin () const {
707 self_type &m = (*this) ();
708 return m.find2 (1, index1 (), 0);
711 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
714 iterator2 end () const {
715 self_type &m = (*this) ();
716 return m.find2 (1, index1 (), m.size2 ());
719 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
722 reverse_iterator2 rbegin () const {
723 return reverse_iterator2 (end ());
726 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
729 reverse_iterator2 rend () const {
730 return reverse_iterator2 (begin ());
736 size_type index1 () const {
737 self_type &m = (*this) ();
738 return layout_type::index_i (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
741 size_type index2 () const {
742 self_type &m = (*this) ();
743 return layout_type::index_j (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
748 iterator1 &operator = (const iterator1 &it) {
749 container_reference<self_type>::assign (&it ());
756 bool operator == (const iterator1 &it) const {
757 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
758 return it_ == it.it_;
761 bool operator < (const iterator1 &it) const {
762 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
767 subiterator_type it_;
769 friend class const_iterator1;
774 iterator1 begin1 () {
775 return find1 (0, 0, 0);
779 return find1 (0, size1_, 0);
782 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
783 class const_iterator2:
784 public container_const_reference<matrix>,
785 public random_access_iterator_base<dense_random_access_iterator_tag,
786 const_iterator2, value_type> {
788 typedef typename matrix::value_type value_type;
789 typedef typename matrix::difference_type difference_type;
790 typedef typename matrix::const_reference reference;
791 typedef const typename matrix::pointer pointer;
793 typedef const_iterator1 dual_iterator_type;
794 typedef const_reverse_iterator1 dual_reverse_iterator_type;
796 // Construction and destruction
799 container_const_reference<self_type> (), it_ () {}
801 const_iterator2 (const self_type &m, const const_subiterator_type &it):
802 container_const_reference<self_type> (m), it_ (it) {}
804 const_iterator2 (const iterator2 &it):
805 container_const_reference<self_type> (it ()), it_ (it.it_) {}
809 const_iterator2 &operator ++ () {
810 layout_type::increment_j (it_, (*this) ().size1 (), (*this) ().size2 ());
814 const_iterator2 &operator -- () {
815 layout_type::decrement_j (it_, (*this) ().size1 (), (*this) ().size2 ());
819 const_iterator2 &operator += (difference_type n) {
820 layout_type::increment_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
824 const_iterator2 &operator -= (difference_type n) {
825 layout_type::decrement_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
829 difference_type operator - (const const_iterator2 &it) const {
830 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
831 return layout_type::distance_j (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
836 const_reference operator * () const {
837 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
838 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
842 const_reference operator [] (difference_type n) const {
846 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
848 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
851 const_iterator1 begin () const {
852 const self_type &m = (*this) ();
853 return m.find1 (1, 0, index2 ());
856 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
859 const_iterator1 cbegin () const {
863 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
866 const_iterator1 end () const {
867 const self_type &m = (*this) ();
868 return m.find1 (1, m.size1 (), index2 ());
871 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
874 const_iterator1 cend () const {
878 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
881 const_reverse_iterator1 rbegin () const {
882 return const_reverse_iterator1 (end ());
885 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
888 const_reverse_iterator1 crbegin () const {
892 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
895 const_reverse_iterator1 rend () const {
896 return const_reverse_iterator1 (begin ());
899 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
902 const_reverse_iterator1 crend () const {
909 size_type index1 () const {
910 const self_type &m = (*this) ();
911 return layout_type::index_i (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
914 size_type index2 () const {
915 const self_type &m = (*this) ();
916 return layout_type::index_j (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
921 const_iterator2 &operator = (const const_iterator2 &it) {
922 container_const_reference<self_type>::assign (&it ());
929 bool operator == (const const_iterator2 &it) const {
930 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
931 return it_ == it.it_;
934 bool operator < (const const_iterator2 &it) const {
935 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
940 const_subiterator_type it_;
942 friend class iterator2;
947 const_iterator2 begin2 () const {
948 return find2 (0, 0, 0);
951 const_iterator2 cbegin2 () const {
955 const_iterator2 end2 () const {
956 return find2 (0, 0, size2_);
959 const_iterator2 cend2 () const {
963 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
965 public container_reference<matrix>,
966 public random_access_iterator_base<dense_random_access_iterator_tag,
967 iterator2, value_type> {
969 typedef typename matrix::value_type value_type;
970 typedef typename matrix::difference_type difference_type;
971 typedef typename matrix::reference reference;
972 typedef typename matrix::pointer pointer;
974 typedef iterator1 dual_iterator_type;
975 typedef reverse_iterator1 dual_reverse_iterator_type;
977 // Construction and destruction
980 container_reference<self_type> (), it_ () {}
982 iterator2 (self_type &m, const subiterator_type &it):
983 container_reference<self_type> (m), it_ (it) {}
987 iterator2 &operator ++ () {
988 layout_type::increment_j (it_, (*this) ().size1 (), (*this) ().size2 ());
992 iterator2 &operator -- () {
993 layout_type::decrement_j (it_, (*this) ().size1 (), (*this) ().size2 ());
997 iterator2 &operator += (difference_type n) {
998 layout_type::increment_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
1002 iterator2 &operator -= (difference_type n) {
1003 layout_type::decrement_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
1007 difference_type operator - (const iterator2 &it) const {
1008 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1009 return layout_type::distance_j (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
1014 reference operator * () const {
1015 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1016 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1020 reference operator [] (difference_type n) const {
1021 return *(*this + n);
1024 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1026 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1027 typename self_type::
1029 iterator1 begin () const {
1030 self_type &m = (*this) ();
1031 return m.find1 (1, 0, index2 ());
1034 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1035 typename self_type::
1037 iterator1 end () const {
1038 self_type &m = (*this) ();
1039 return m.find1 (1, m.size1 (), index2 ());
1042 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1043 typename self_type::
1045 reverse_iterator1 rbegin () const {
1046 return reverse_iterator1 (end ());
1049 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1050 typename self_type::
1052 reverse_iterator1 rend () const {
1053 return reverse_iterator1 (begin ());
1059 size_type index1 () const {
1060 self_type &m = (*this) ();
1061 return layout_type::index_i (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
1064 size_type index2 () const {
1065 self_type &m = (*this) ();
1066 return layout_type::index_j (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
1071 iterator2 &operator = (const iterator2 &it) {
1072 container_reference<self_type>::assign (&it ());
1079 bool operator == (const iterator2 &it) const {
1080 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1081 return it_ == it.it_;
1084 bool operator < (const iterator2 &it) const {
1085 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1086 return it_ < it.it_;
1090 subiterator_type it_;
1092 friend class const_iterator2;
1097 iterator2 begin2 () {
1098 return find2 (0, 0, 0);
1102 return find2 (0, 0, size2_);
1105 // Reverse iterators
1108 const_reverse_iterator1 rbegin1 () const {
1109 return const_reverse_iterator1 (end1 ());
1112 const_reverse_iterator1 crbegin1 () const {
1116 const_reverse_iterator1 rend1 () const {
1117 return const_reverse_iterator1 (begin1 ());
1120 const_reverse_iterator1 crend1 () const {
1125 reverse_iterator1 rbegin1 () {
1126 return reverse_iterator1 (end1 ());
1129 reverse_iterator1 rend1 () {
1130 return reverse_iterator1 (begin1 ());
1134 const_reverse_iterator2 rbegin2 () const {
1135 return const_reverse_iterator2 (end2 ());
1138 const_reverse_iterator2 crbegin2 () const {
1142 const_reverse_iterator2 rend2 () const {
1143 return const_reverse_iterator2 (begin2 ());
1146 const_reverse_iterator2 crend2 () const {
1151 reverse_iterator2 rbegin2 () {
1152 return reverse_iterator2 (end2 ());
1155 reverse_iterator2 rend2 () {
1156 return reverse_iterator2 (begin2 ());
1160 template<class Archive>
1161 void serialize(Archive & ar, const unsigned int /* file_version */){
1163 // we need to copy to a collection_size_type to get a portable
1164 // and efficient serialization
1165 serialization::collection_size_type s1 (size1_);
1166 serialization::collection_size_type s2 (size2_);
1168 // serialize the sizes
1169 ar & serialization::make_nvp("size1",s1)
1170 & serialization::make_nvp("size2",s2);
1172 // copy the values back if loading
1173 if (Archive::is_loading::value) {
1177 ar & serialization::make_nvp("data",data_);
1187 #ifdef BOOST_UBLAS_CPP_GE_2011
1188 /** \brief A fixed size dense matrix of values of type \c T. Equivalent to a c-style 2 dimensional array.
1190 * For a \f$(m \times n)\f$-dimensional fixed_matrix and \f$ 0 \leq i < m, 0 \leq j < n\f$, every element \f$ m_{i,j} \f$ is mapped to
1191 * the \f$(i.n + j)\f$-th element of the container for row major orientation or the \f$ (i + j.m) \f$-th element of
1192 * the container for column major orientation. In a dense matrix all elements are represented in memory in a
1193 * contiguous chunk of memory by definition.
1195 * Orientation and storage can also be specified, otherwise \c row_major and \c std::array are used. It is \b not
1196 * required by the storage container to initialize elements of the matrix.
1198 * \tparam T the type of object stored in the matrix (like double, float, std::complex<double>, etc...)
1199 * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major
1200 * \tparam A the type of Storage array. Default is \c std::array<T, M*N>
1202 template<class T, std::size_t M, std::size_t N, class L, class A>
1204 public matrix_container<fixed_matrix<T, M, N, L, A> > {
1207 typedef L layout_type;
1208 typedef fixed_matrix<T, M, N, L, A> self_type;
1210 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1211 using matrix_container<self_type>::operator ();
1213 typedef typename A::size_type size_type;
1214 typedef typename A::difference_type difference_type;
1215 typedef T value_type;
1216 typedef const T &const_reference;
1217 typedef T &reference;
1218 typedef A array_type;
1219 typedef const matrix_reference<const self_type> const_closure_type;
1220 typedef matrix_reference<self_type> closure_type;
1221 typedef vector<T, A> vector_temporary_type;
1222 typedef self_type matrix_temporary_type;
1223 typedef dense_tag storage_category;
1224 // This could be better for performance,
1225 // typedef typename unknown_orientation_tag orientation_category;
1226 // but others depend on the orientation information...
1227 typedef typename L::orientation_category orientation_category;
1229 // Construction and destruction
1231 /// Default dense fixed_matrix constructor. Make a dense fixed_matrix of size M x N
1234 matrix_container<self_type> (),
1237 /// \brief Construct a fixed_matrix from a list of values
1238 /// The list may be included in curly braces. Typical syntax is choices are :
1239 /// fixed_matrix<double, 2,2> v = { 1, 2, 3, 4 } or fixed_matrix<double,4> v( {1, 2, 3, 4} ) or fixed_matrix<double,2,2> v( 1, 2, 3, 4 )
1240 template <typename... Types>
1241 fixed_matrix(value_type v0, Types... vrest) :
1242 matrix_container<self_type> (),
1243 data_{ { v0, vrest... } } {}
1245 /** Dense fixed_matrix constructor with defined initial value for all the matrix elements
1246 * \param init initial value assigned to all elements
1248 fixed_matrix (const value_type &init):
1249 matrix_container<self_type> (),
1254 /** Dense matrix constructor with defined initial data array
1255 * \param data array to copy into the matrix. Must have the same dimension as the matrix
1258 fixed_matrix (const array_type &data):
1259 matrix_container<self_type> (),
1262 /** Copy-constructor of a dense fixed_matrix
1263 * \param m is a dense fixed_matrix
1266 fixed_matrix (const fixed_matrix &m):
1267 matrix_container<self_type> (),
1270 /** Copy-constructor of a dense matrix from a matrix expression
1271 * \param ae is a matrix expression
1275 fixed_matrix (const matrix_expression<AE> &ae):
1276 matrix_container<self_type> (),
1278 matrix_assign<scalar_assign> (*this, ae);
1282 /** Return the number of rows of the fixed_matrix
1283 * You can also use the free size<>() function in operation/size.hpp as size<1>(m) where m is a fixed_matrix
1286 BOOST_CONSTEXPR size_type size1 () const {
1290 /** Return the number of colums of the fixed_matrix
1291 * You can also use the free size<>() function in operation/size.hpp as size<2>(m) where m is a fixed_matrix
1294 BOOST_CONSTEXPR size_type size2 () const {
1298 // Storage accessors
1299 /** Return a constant reference to the internal storage of a dense matrix, i.e. the raw data
1300 * It's type depends on the type used by the matrix to store its data
1303 const array_type &data () const {
1306 /** Return a reference to the internal storage of a dense fixed_matrix, i.e. the raw data
1307 * It's type depends on the type used by the fixed_matrix to store its data
1310 array_type &data () {
1317 /** Access a fixed_matrix element. Here we return a const reference
1318 * \param i the first coordinate of the element. By default it's the row
1319 * \param j the second coordinate of the element. By default it's the column
1320 * \return a const reference to the element
1323 const_reference operator () (size_type i, size_type j) const {
1324 return data () [layout_type::element (i, M, j, N)]; // Fixme: add static lookup for element(...) i.e.: element<M, N>(i,j)
1327 /** Access a fixed_matrix element. Here we return a reference
1328 * \param i the first coordinate of the element. By default it's the row
1329 * \param j the second coordinate of the element. By default it's the column
1330 * \return a reference to the element
1333 reference at_element (size_type i, size_type j) {
1334 return data () [layout_type::element (i, M, j, N)];
1337 /** Access a fixed_matrix element. Here we return a reference
1338 * \param i the first coordinate of the element. By default it's the row
1339 * \param j the second coordinate of the element. By default it's the column
1340 * \return a reference to the element
1343 reference operator () (size_type i, size_type j) {
1344 return at_element (i, j);
1347 // Element assignment
1349 /** Change the value of a fixed_matrix element. Return back a reference to it
1350 * \param i the first coordinate of the element. By default it's the row
1351 * \param j the second coordinate of the element. By default it's the column
1352 * \param t the new value of the element
1353 * \return a reference to the newly changed element
1356 reference insert_element (size_type i, size_type j, const_reference t) {
1357 return (at_element (i, j) = t);
1360 /** Erase the element
1361 * For most types (int, double, etc...) it means setting 0 (zero) the element at zero in fact.
1362 * For user-defined types, it could be another value if you decided it. Your type in that case must
1363 * contain a default null value.
1364 * \param i the first coordinate of the element. By default it's the row
1365 * \param j the second coordinate of the element. By default it's the column
1367 void erase_element (size_type i, size_type j) {
1368 at_element (i, j) = value_type/*zero*/();
1372 /** Erase all elements in the fixed_matrix
1373 * For most types (int, double, etc...) it means writing 0 (zero) everywhere.
1374 * For user-defined types, it could be another value if you decided it. Your type in that case must
1375 * contain a default null value.
1379 std::fill (data ().begin (), data ().end (), value_type/*zero*/());
1383 #ifdef BOOST_UBLAS_MOVE_SEMANTICS
1385 /*! @note "pass by value" the key idea to enable move semantics */
1387 fixed_matrix &operator = (matrix m) {
1388 assign_temporary(m);
1393 fixed_matrix &operator = (const fixed_matrix &m) {
1394 data () = m.data ();
1398 template<class C> // Container assignment without temporary
1400 fixed_matrix &operator = (const matrix_container<C> &m) {
1401 resize (m ().size1 (), m ().size2 (), false);
1406 fixed_matrix &assign_temporary (fixed_matrix &m) {
1412 fixed_matrix &operator = (const matrix_expression<AE> &ae) {
1413 self_type temporary (ae);
1414 return assign_temporary (temporary);
1418 fixed_matrix &assign (const matrix_expression<AE> &ae) {
1419 matrix_assign<scalar_assign> (*this, ae);
1424 fixed_matrix& operator += (const matrix_expression<AE> &ae) {
1425 self_type temporary (*this + ae);
1426 return assign_temporary (temporary);
1428 template<class C> // Container assignment without temporary
1430 fixed_matrix &operator += (const matrix_container<C> &m) {
1436 fixed_matrix &plus_assign (const matrix_expression<AE> &ae) {
1437 matrix_assign<scalar_plus_assign> (*this, ae);
1442 fixed_matrix& operator -= (const matrix_expression<AE> &ae) {
1443 self_type temporary (*this - ae);
1444 return assign_temporary (temporary);
1446 template<class C> // Container assignment without temporary
1448 fixed_matrix &operator -= (const matrix_container<C> &m) {
1454 fixed_matrix &minus_assign (const matrix_expression<AE> &ae) {
1455 matrix_assign<scalar_minus_assign> (*this, ae);
1460 fixed_matrix& operator *= (const AT &at) {
1461 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
1466 fixed_matrix& operator /= (const AT &at) {
1467 matrix_assign_scalar<scalar_divides_assign> (*this, at);
1473 void swap (fixed_matrix &m) {
1475 data ().swap (m.data ());
1479 friend void swap (fixed_matrix &m1, fixed_matrix &m2) {
1485 // Use the storage array iterator
1486 typedef typename A::const_iterator const_subiterator_type;
1487 typedef typename A::iterator subiterator_type;
1490 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1491 typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
1492 typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
1493 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
1494 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
1496 class const_iterator1;
1498 class const_iterator2;
1501 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1502 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
1503 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1504 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
1508 const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
1509 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1510 return const_iterator1 (*this, i, j);
1512 return const_iterator1 (*this, data ().begin () + layout_type::address (i, M, j, N));
1516 iterator1 find1 (int /* rank */, size_type i, size_type j) {
1517 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1518 return iterator1 (*this, i, j);
1520 return iterator1 (*this, data ().begin () + layout_type::address (i, M, j, N));
1524 const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
1525 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1526 return const_iterator2 (*this, i, j);
1528 return const_iterator2 (*this, data ().begin () + layout_type::address (i, M, j, N));
1532 iterator2 find2 (int /* rank */, size_type i, size_type j) {
1533 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1534 return iterator2 (*this, i, j);
1536 return iterator2 (*this, data ().begin () + layout_type::address (i, M, j, N));
1541 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1542 class const_iterator1:
1543 public container_const_reference<fixed_matrix>,
1544 public random_access_iterator_base<dense_random_access_iterator_tag,
1545 const_iterator1, value_type> {
1547 typedef typename fixed_matrix::value_type value_type;
1548 typedef typename fixed_matrix::difference_type difference_type;
1549 typedef typename fixed_matrix::const_reference reference;
1550 typedef const typename fixed_matrix::pointer pointer;
1552 typedef const_iterator2 dual_iterator_type;
1553 typedef const_reverse_iterator2 dual_reverse_iterator_type;
1555 // Construction and destruction
1558 container_const_reference<self_type> (), it_ () {}
1560 const_iterator1 (const self_type &m, const const_subiterator_type &it):
1561 container_const_reference<self_type> (m), it_ (it) {}
1563 const_iterator1 (const iterator1 &it):
1564 container_const_reference<self_type> (it ()), it_ (it.it_) {}
1568 const_iterator1 &operator ++ () {
1569 layout_type::increment_i (it_, (*this) ().size1 (), (*this) ().size2 ());
1573 const_iterator1 &operator -- () {
1574 layout_type::decrement_i (it_, (*this) ().size1 (), (*this) ().size2 ());
1578 const_iterator1 &operator += (difference_type n) {
1579 layout_type::increment_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
1583 const_iterator1 &operator -= (difference_type n) {
1584 layout_type::decrement_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
1588 difference_type operator - (const const_iterator1 &it) const {
1589 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1590 return layout_type::distance_i (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
1595 const_reference operator * () const {
1596 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1597 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1601 const_reference operator [] (difference_type n) const {
1602 return *(*this + n);
1605 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1607 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1608 typename self_type::
1610 const_iterator2 begin () const {
1611 const self_type &m = (*this) ();
1612 return m.find2 (1, index1 (), 0);
1615 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1616 typename self_type::
1618 const_iterator2 cbegin () const {
1622 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1623 typename self_type::
1625 const_iterator2 end () const {
1626 const self_type &m = (*this) ();
1627 return m.find2 (1, index1 (), m.size2 ());
1630 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1631 typename self_type::
1633 const_iterator2 cend () const {
1637 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1638 typename self_type::
1640 const_reverse_iterator2 rbegin () const {
1641 return const_reverse_iterator2 (end ());
1644 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1645 typename self_type::
1647 const_reverse_iterator2 crbegin () const {
1651 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1652 typename self_type::
1654 const_reverse_iterator2 rend () const {
1655 return const_reverse_iterator2 (begin ());
1658 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1659 typename self_type::
1661 const_reverse_iterator2 crend () const {
1668 size_type index1 () const {
1669 const self_type &m = (*this) ();
1670 return layout_type::index_i (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
1673 size_type index2 () const {
1674 const self_type &m = (*this) ();
1675 return layout_type::index_j (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
1680 const_iterator1 &operator = (const const_iterator1 &it) {
1681 container_const_reference<self_type>::assign (&it ());
1688 bool operator == (const const_iterator1 &it) const {
1689 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1690 return it_ == it.it_;
1693 bool operator < (const const_iterator1 &it) const {
1694 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1695 return it_ < it.it_;
1699 const_subiterator_type it_;
1701 friend class iterator1;
1706 const_iterator1 begin1 () const {
1707 return find1 (0, 0, 0);
1710 const_iterator1 cbegin1 () const {
1714 const_iterator1 end1 () const {
1715 return find1 (0, M, 0);
1718 const_iterator1 cend1 () const {
1722 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1724 public container_reference<fixed_matrix>,
1725 public random_access_iterator_base<dense_random_access_iterator_tag,
1726 iterator1, value_type> {
1728 typedef typename fixed_matrix::value_type value_type;
1729 typedef typename fixed_matrix::difference_type difference_type;
1730 typedef typename fixed_matrix::reference reference;
1731 typedef typename fixed_matrix::pointer pointer;
1733 typedef iterator2 dual_iterator_type;
1734 typedef reverse_iterator2 dual_reverse_iterator_type;
1736 // Construction and destruction
1739 container_reference<self_type> (), it_ () {}
1741 iterator1 (self_type &m, const subiterator_type &it):
1742 container_reference<self_type> (m), it_ (it) {}
1746 iterator1 &operator ++ () {
1747 layout_type::increment_i (it_, (*this) ().size1 (), (*this) ().size2 ());
1751 iterator1 &operator -- () {
1752 layout_type::decrement_i (it_, (*this) ().size1 (), (*this) ().size2 ());
1756 iterator1 &operator += (difference_type n) {
1757 layout_type::increment_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
1761 iterator1 &operator -= (difference_type n) {
1762 layout_type::decrement_i (it_, n, (*this) ().size1 (), (*this) ().size2 ());
1766 difference_type operator - (const iterator1 &it) const {
1767 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1768 return layout_type::distance_i (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
1773 reference operator * () const {
1774 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1775 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1779 reference operator [] (difference_type n) const {
1780 return *(*this + n);
1783 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1785 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1786 typename self_type::
1788 iterator2 begin () const {
1789 self_type &m = (*this) ();
1790 return m.find2 (1, index1 (), 0);
1793 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1794 typename self_type::
1796 iterator2 end () const {
1797 self_type &m = (*this) ();
1798 return m.find2 (1, index1 (), m.size2 ());
1801 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1802 typename self_type::
1804 reverse_iterator2 rbegin () const {
1805 return reverse_iterator2 (end ());
1808 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1809 typename self_type::
1811 reverse_iterator2 rend () const {
1812 return reverse_iterator2 (begin ());
1818 size_type index1 () const {
1819 self_type &m = (*this) ();
1820 return layout_type::index_i (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
1823 size_type index2 () const {
1824 self_type &m = (*this) ();
1825 return layout_type::index_j (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
1830 iterator1 &operator = (const iterator1 &it) {
1831 container_reference<self_type>::assign (&it ());
1838 bool operator == (const iterator1 &it) const {
1839 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1840 return it_ == it.it_;
1843 bool operator < (const iterator1 &it) const {
1844 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1845 return it_ < it.it_;
1849 subiterator_type it_;
1851 friend class const_iterator1;
1856 iterator1 begin1 () {
1857 return find1 (0, 0, 0);
1861 return find1 (0, M, 0);
1864 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1865 class const_iterator2:
1866 public container_const_reference<fixed_matrix>,
1867 public random_access_iterator_base<dense_random_access_iterator_tag,
1868 const_iterator2, value_type> {
1870 typedef typename fixed_matrix::value_type value_type;
1871 typedef typename fixed_matrix::difference_type difference_type;
1872 typedef typename fixed_matrix::const_reference reference;
1873 typedef const typename fixed_matrix::pointer pointer;
1875 typedef const_iterator1 dual_iterator_type;
1876 typedef const_reverse_iterator1 dual_reverse_iterator_type;
1878 // Construction and destruction
1881 container_const_reference<self_type> (), it_ () {}
1883 const_iterator2 (const self_type &m, const const_subiterator_type &it):
1884 container_const_reference<self_type> (m), it_ (it) {}
1886 const_iterator2 (const iterator2 &it):
1887 container_const_reference<self_type> (it ()), it_ (it.it_) {}
1891 const_iterator2 &operator ++ () {
1892 layout_type::increment_j (it_, (*this) ().size1 (), (*this) ().size2 ());
1896 const_iterator2 &operator -- () {
1897 layout_type::decrement_j (it_, (*this) ().size1 (), (*this) ().size2 ());
1901 const_iterator2 &operator += (difference_type n) {
1902 layout_type::increment_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
1906 const_iterator2 &operator -= (difference_type n) {
1907 layout_type::decrement_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
1911 difference_type operator - (const const_iterator2 &it) const {
1912 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1913 return layout_type::distance_j (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
1918 const_reference operator * () const {
1919 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1920 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1924 const_reference operator [] (difference_type n) const {
1925 return *(*this + n);
1928 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1930 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1931 typename self_type::
1933 const_iterator1 begin () const {
1934 const self_type &m = (*this) ();
1935 return m.find1 (1, 0, index2 ());
1938 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1939 typename self_type::
1941 const_iterator1 cbegin () const {
1945 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1946 typename self_type::
1948 const_iterator1 end () const {
1949 const self_type &m = (*this) ();
1950 return m.find1 (1, m.size1 (), index2 ());
1953 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1954 typename self_type::
1956 const_iterator1 cend () const {
1960 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1961 typename self_type::
1963 const_reverse_iterator1 rbegin () const {
1964 return const_reverse_iterator1 (end ());
1967 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1968 typename self_type::
1970 const_reverse_iterator1 crbegin () const {
1974 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1975 typename self_type::
1977 const_reverse_iterator1 rend () const {
1978 return const_reverse_iterator1 (begin ());
1981 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1982 typename self_type::
1984 const_reverse_iterator1 crend () const {
1991 size_type index1 () const {
1992 const self_type &m = (*this) ();
1993 return layout_type::index_i (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
1996 size_type index2 () const {
1997 const self_type &m = (*this) ();
1998 return layout_type::index_j (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
2003 const_iterator2 &operator = (const const_iterator2 &it) {
2004 container_const_reference<self_type>::assign (&it ());
2011 bool operator == (const const_iterator2 &it) const {
2012 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2013 return it_ == it.it_;
2016 bool operator < (const const_iterator2 &it) const {
2017 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2018 return it_ < it.it_;
2022 const_subiterator_type it_;
2024 friend class iterator2;
2029 const_iterator2 begin2 () const {
2030 return find2 (0, 0, 0);
2033 const_iterator2 cbegin2 () const {
2037 const_iterator2 end2 () const {
2038 return find2 (0, 0, N);
2041 const_iterator2 cend2 () const {
2045 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2047 public container_reference<fixed_matrix>,
2048 public random_access_iterator_base<dense_random_access_iterator_tag,
2049 iterator2, value_type> {
2051 typedef typename fixed_matrix::value_type value_type;
2052 typedef typename fixed_matrix::difference_type difference_type;
2053 typedef typename fixed_matrix::reference reference;
2054 typedef typename fixed_matrix::pointer pointer;
2056 typedef iterator1 dual_iterator_type;
2057 typedef reverse_iterator1 dual_reverse_iterator_type;
2059 // Construction and destruction
2062 container_reference<self_type> (), it_ () {}
2064 iterator2 (self_type &m, const subiterator_type &it):
2065 container_reference<self_type> (m), it_ (it) {}
2069 iterator2 &operator ++ () {
2070 layout_type::increment_j (it_, (*this) ().size1 (), (*this) ().size2 ());
2074 iterator2 &operator -- () {
2075 layout_type::decrement_j (it_, (*this) ().size1 (), (*this) ().size2 ());
2079 iterator2 &operator += (difference_type n) {
2080 layout_type::increment_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
2084 iterator2 &operator -= (difference_type n) {
2085 layout_type::decrement_j (it_, n, (*this) ().size1 (), (*this) ().size2 ());
2089 difference_type operator - (const iterator2 &it) const {
2090 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2091 return layout_type::distance_j (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
2096 reference operator * () const {
2097 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
2098 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
2102 reference operator [] (difference_type n) const {
2103 return *(*this + n);
2106 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2108 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2109 typename self_type::
2111 iterator1 begin () const {
2112 self_type &m = (*this) ();
2113 return m.find1 (1, 0, index2 ());
2116 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2117 typename self_type::
2119 iterator1 end () const {
2120 self_type &m = (*this) ();
2121 return m.find1 (1, m.size1 (), index2 ());
2124 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2125 typename self_type::
2127 reverse_iterator1 rbegin () const {
2128 return reverse_iterator1 (end ());
2131 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2132 typename self_type::
2134 reverse_iterator1 rend () const {
2135 return reverse_iterator1 (begin ());
2141 size_type index1 () const {
2142 self_type &m = (*this) ();
2143 return layout_type::index_i (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
2146 size_type index2 () const {
2147 self_type &m = (*this) ();
2148 return layout_type::index_j (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
2153 iterator2 &operator = (const iterator2 &it) {
2154 container_reference<self_type>::assign (&it ());
2161 bool operator == (const iterator2 &it) const {
2162 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2163 return it_ == it.it_;
2166 bool operator < (const iterator2 &it) const {
2167 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2168 return it_ < it.it_;
2172 subiterator_type it_;
2174 friend class const_iterator2;
2179 iterator2 begin2 () {
2180 return find2 (0, 0, 0);
2184 return find2 (0, 0, N);
2187 // Reverse iterators
2190 const_reverse_iterator1 rbegin1 () const {
2191 return const_reverse_iterator1 (end1 ());
2194 const_reverse_iterator1 crbegin1 () const {
2198 const_reverse_iterator1 rend1 () const {
2199 return const_reverse_iterator1 (begin1 ());
2202 const_reverse_iterator1 crend1 () const {
2207 reverse_iterator1 rbegin1 () {
2208 return reverse_iterator1 (end1 ());
2211 reverse_iterator1 rend1 () {
2212 return reverse_iterator1 (begin1 ());
2216 const_reverse_iterator2 rbegin2 () const {
2217 return const_reverse_iterator2 (end2 ());
2220 const_reverse_iterator2 crbegin2 () const {
2224 const_reverse_iterator2 rend2 () const {
2225 return const_reverse_iterator2 (begin2 ());
2228 const_reverse_iterator2 crend2 () const {
2233 reverse_iterator2 rbegin2 () {
2234 return reverse_iterator2 (end2 ());
2237 reverse_iterator2 rend2 () {
2238 return reverse_iterator2 (begin2 ());
2242 template<class Archive>
2243 void serialize(Archive & ar, const unsigned int /* file_version */){
2244 ar & serialization::make_nvp("data",data_);
2251 #endif // BOOST_UBLAS_CPP_GE_2011
2253 /** \brief A dense matrix of values of type \c T with a variable size bounded to a maximum of \f$M\f$ by \f$N\f$.
2255 * For a \f$(m \times n)\f$-dimensional matrix and \f$ 0 \leq i < m, 0 \leq j < n\f$, every element \f$m_{i,j}\f$ is mapped
2256 * to the \f$(i.n + j)\f$-th element of the container for row major orientation or the \f$(i + j.m)\f$-th element
2257 * of the container for column major orientation. Finally in a dense matrix all elements are represented in memory
2258 * in a contiguous chunk of memory.
2260 * Orientation can be specified. Default is \c row_major
2261 * The default constructor creates the matrix with size \f$M\f$ by \f$N\f$. Elements are constructed by the storage
2262 * type \c bounded_array, which need not initialise their value.
2264 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
2265 * \tparam M maximum and default number of rows (if not specified at construction)
2266 * \tparam N maximum and default number of columns (if not specified at construction)
2267 * \tparam L the storage organization. It can be either \c row_major or \c column_major. Default is \c row_major
2269 template<class T, std::size_t M, std::size_t N, class L>
2270 class bounded_matrix:
2271 public matrix<T, L, bounded_array<T, M * N> > {
2273 typedef matrix<T, L, bounded_array<T, M * N> > matrix_type;
2275 typedef typename matrix_type::size_type size_type;
2276 static const size_type max_size1 = M;
2277 static const size_type max_size2 = N;
2279 // Construction and destruction
2282 matrix_type (M, N) {}
2284 bounded_matrix (size_type size1, size_type size2):
2285 matrix_type (size1, size2) {}
2287 bounded_matrix (const bounded_matrix &m):
2289 template<class A2> // Allow matrix<T, L, bounded_array<M,N> > construction
2291 bounded_matrix (const matrix<T, L, A2> &m):
2295 bounded_matrix (const matrix_expression<AE> &ae):
2298 ~bounded_matrix () {}
2301 #ifdef BOOST_UBLAS_MOVE_SEMANTICS
2303 /*! @note "pass by value" the key idea to enable move semantics */
2305 bounded_matrix &operator = (bounded_matrix m) {
2306 matrix_type::operator = (m);
2311 bounded_matrix &operator = (const bounded_matrix &m) {
2312 matrix_type::operator = (m);
2316 template<class L2, class A2> // Generic matrix assignment
2318 bounded_matrix &operator = (const matrix<T, L2, A2> &m) {
2319 matrix_type::operator = (m);
2322 template<class C> // Container assignment without temporary
2324 bounded_matrix &operator = (const matrix_container<C> &m) {
2325 matrix_type::operator = (m);
2330 bounded_matrix &operator = (const matrix_expression<AE> &ae) {
2331 matrix_type::operator = (ae);
2337 /** \brief A dense matrix of values of type \c T stored as a vector of vectors.
2339 * Rows or columns are not stored into contiguous chunks of memory but data inside rows (or columns) are.
2340 * Orientation and storage can also be specified, otherwise a row major and unbounded arrays are used.
2341 * The data is stored as a vector of vectors, meaning that rows or columns might not be stored into contiguous chunks
2342 * of memory. Orientation and storage can also be specified, otherwise a row major and unbounded arrays are used.
2343 * The storage type defaults to \c unbounded_array<unbounded_array<T>> and orientation is \c row_major. It is \b not
2344 * required by the storage to initialize elements of the matrix. For a \f$(m \times n)\f$-dimensional matrix and
2345 * \f$ 0 \leq i < m, 0 \leq j < n\f$, every element \f$m_{i,j}\f$ is mapped to the \f$(i.n + j)\f$-th element of the
2346 * container for row major orientation or the \f$(i + j.m)\f$-th element of the container for column major orientation.
2348 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
2349 * \tparam L the storage organization. It can be either \c row_major or \c column_major. By default it is \c row_major
2350 * \tparam A the type of Storage array. By default, it is an \unbounded_array<unbounder_array<T>>
2352 template<class T, class L, class A>
2353 class vector_of_vector:
2354 public matrix_container<vector_of_vector<T, L, A> > {
2357 typedef L layout_type;
2358 typedef vector_of_vector<T, L, A> self_type;
2360 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2361 using matrix_container<self_type>::operator ();
2363 typedef typename A::size_type size_type;
2364 typedef typename A::difference_type difference_type;
2365 typedef T value_type;
2366 typedef const T &const_reference;
2367 typedef T &reference;
2368 typedef A array_type;
2369 typedef const matrix_reference<const self_type> const_closure_type;
2370 typedef matrix_reference<self_type> closure_type;
2371 typedef vector<T, typename A::value_type> vector_temporary_type;
2372 typedef self_type matrix_temporary_type;
2373 typedef dense_tag storage_category;
2374 // This could be better for performance,
2375 // typedef typename unknown_orientation_tag orientation_category;
2376 // but others depend on the orientation information...
2377 typedef typename L::orientation_category orientation_category;
2379 // Construction and destruction
2381 vector_of_vector ():
2382 matrix_container<self_type> (),
2383 size1_ (0), size2_ (0), data_ (1) {}
2385 vector_of_vector (size_type size1, size_type size2):
2386 matrix_container<self_type> (),
2387 size1_ (size1), size2_ (size2), data_ (1) {
2388 resize (size1, size2, true);
2391 vector_of_vector (const vector_of_vector &m):
2392 matrix_container<self_type> (),
2393 size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
2396 vector_of_vector (const matrix_expression<AE> &ae):
2397 matrix_container<self_type> (),
2398 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size_M (size1_, size2_) + 1) {
2399 for (size_type k = 0; k < layout_type::size_M (size1_, size2_); ++ k)
2400 data ()[k].resize (layout_type::size_m (size1_, size2_));
2401 matrix_assign<scalar_assign> (*this, ae);
2406 size_type size1 () const {
2410 size_type size2 () const {
2414 // Storage accessors
2416 const array_type &data () const {
2420 array_type &data () {
2426 void resize (size_type size1, size_type size2, bool preserve = true) {
2430 data ().resize (layout_type::size_M (size1, size2) + 1, typename array_type::value_type ());
2432 data ().resize (layout_type::size_M (size1, size2) + 1);
2433 for (size_type k = 0; k < layout_type::size_M (size1, size2); ++ k) {
2435 data () [k].resize (layout_type::size_m (size1, size2), value_type ());
2437 data () [k].resize (layout_type::size_m (size1, size2));
2443 const_reference operator () (size_type i, size_type j) const {
2444 return data () [layout_type::index_M (i, j)] [layout_type::index_m (i, j)];
2447 reference at_element (size_type i, size_type j) {
2448 return data () [layout_type::index_M (i, j)] [layout_type::index_m (i, j)];
2451 reference operator () (size_type i, size_type j) {
2452 return at_element (i, j);
2455 // Element assignment
2457 reference insert_element (size_type i, size_type j, const_reference t) {
2458 return (at_element (i, j) = t);
2461 void erase_element (size_type i, size_type j) {
2462 at_element (i, j) = value_type/*zero*/();
2468 for (size_type k = 0; k < layout_type::size_M (size1_, size2_); ++ k)
2469 std::fill (data () [k].begin (), data () [k].end (), value_type/*zero*/());
2474 vector_of_vector &operator = (const vector_of_vector &m) {
2477 data () = m.data ();
2481 vector_of_vector &assign_temporary (vector_of_vector &m) {
2487 vector_of_vector &operator = (const matrix_expression<AE> &ae) {
2488 self_type temporary (ae);
2489 return assign_temporary (temporary);
2491 template<class C> // Container assignment without temporary
2493 vector_of_vector &operator = (const matrix_container<C> &m) {
2494 resize (m ().size1 (), m ().size2 (), false);
2500 vector_of_vector &assign (const matrix_expression<AE> &ae) {
2501 matrix_assign<scalar_assign> (*this, ae);
2506 vector_of_vector& operator += (const matrix_expression<AE> &ae) {
2507 self_type temporary (*this + ae);
2508 return assign_temporary (temporary);
2510 template<class C> // Container assignment without temporary
2512 vector_of_vector &operator += (const matrix_container<C> &m) {
2518 vector_of_vector &plus_assign (const matrix_expression<AE> &ae) {
2519 matrix_assign<scalar_plus_assign> (*this, ae);
2524 vector_of_vector& operator -= (const matrix_expression<AE> &ae) {
2525 self_type temporary (*this - ae);
2526 return assign_temporary (temporary);
2528 template<class C> // Container assignment without temporary
2530 vector_of_vector &operator -= (const matrix_container<C> &m) {
2536 vector_of_vector &minus_assign (const matrix_expression<AE> &ae) {
2537 matrix_assign<scalar_minus_assign> (*this, ae);
2542 vector_of_vector& operator *= (const AT &at) {
2543 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
2548 vector_of_vector& operator /= (const AT &at) {
2549 matrix_assign_scalar<scalar_divides_assign> (*this, at);
2555 void swap (vector_of_vector &m) {
2557 std::swap (size1_, m.size1_);
2558 std::swap (size2_, m.size2_);
2559 data ().swap (m.data ());
2563 friend void swap (vector_of_vector &m1, vector_of_vector &m2) {
2569 // Use the vector iterator
2570 typedef typename A::value_type::const_iterator const_subiterator_type;
2571 typedef typename A::value_type::iterator subiterator_type;
2573 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2574 typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
2575 typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
2576 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
2577 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
2579 class const_iterator1;
2581 class const_iterator2;
2584 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2585 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
2586 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2587 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
2591 const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
2592 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2593 return const_iterator1 (*this, i, j);
2595 return const_iterator1 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j));
2599 iterator1 find1 (int /*rank*/, size_type i, size_type j) {
2600 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2601 return iterator1 (*this, i, j);
2603 return iterator1 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j));
2607 const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
2608 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2609 return const_iterator2 (*this, i, j);
2611 return const_iterator2 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j));
2615 iterator2 find2 (int /*rank*/, size_type i, size_type j) {
2616 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2617 return iterator2 (*this, i, j);
2619 return iterator2 (*this, i, j, data () [layout_type::index_M (i, j)].begin () + layout_type::index_m (i, j));
2624 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2625 class const_iterator1:
2626 public container_const_reference<vector_of_vector>,
2627 public random_access_iterator_base<dense_random_access_iterator_tag,
2628 const_iterator1, value_type> {
2630 typedef typename vector_of_vector::value_type value_type;
2631 typedef typename vector_of_vector::difference_type difference_type;
2632 typedef typename vector_of_vector::const_reference reference;
2633 typedef const typename vector_of_vector::pointer pointer;
2635 typedef const_iterator2 dual_iterator_type;
2636 typedef const_reverse_iterator2 dual_reverse_iterator_type;
2638 // Construction and destruction
2641 container_const_reference<self_type> (), i_ (), j_ (), it_ () {}
2643 const_iterator1 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it):
2644 container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
2646 const_iterator1 (const iterator1 &it):
2647 container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
2651 const_iterator1 &operator ++ () {
2653 const self_type &m = (*this) ();
2654 if (layout_type::fast_i ())
2657 it_ = m.find1 (1, i_, j_).it_;
2661 const_iterator1 &operator -- () {
2663 const self_type &m = (*this) ();
2664 if (layout_type::fast_i ())
2667 it_ = m.find1 (1, i_, j_).it_;
2671 const_iterator1 &operator += (difference_type n) {
2673 const self_type &m = (*this) ();
2674 it_ = m.find1 (1, i_, j_).it_;
2678 const_iterator1 &operator -= (difference_type n) {
2680 const self_type &m = (*this) ();
2681 it_ = m.find1 (1, i_, j_).it_;
2685 difference_type operator - (const const_iterator1 &it) const {
2686 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2687 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
2688 return index1 () - it.index1 ();
2693 const_reference operator * () const {
2694 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
2695 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
2699 const_reference operator [] (difference_type n) const {
2700 return *(*this + n);
2703 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2705 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2706 typename self_type::
2708 const_iterator2 begin () const {
2709 const self_type &m = (*this) ();
2710 return m.find2 (1, index1 (), 0);
2713 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2714 typename self_type::
2716 const_iterator2 cbegin () const {
2720 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2721 typename self_type::
2723 const_iterator2 end () const {
2724 const self_type &m = (*this) ();
2725 return m.find2 (1, index1 (), m.size2 ());
2728 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2729 typename self_type::
2731 const_iterator2 cend () const {
2735 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2736 typename self_type::
2738 const_reverse_iterator2 rbegin () const {
2739 return const_reverse_iterator2 (end ());
2742 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2743 typename self_type::
2745 const_reverse_iterator2 crbegin () const {
2749 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2750 typename self_type::
2752 const_reverse_iterator2 rend () const {
2753 return const_reverse_iterator2 (begin ());
2756 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2757 typename self_type::
2759 const_reverse_iterator2 crend () const {
2766 size_type index1 () const {
2770 size_type index2 () const {
2776 const_iterator1 &operator = (const const_iterator1 &it) {
2777 container_const_reference<self_type>::assign (&it ());
2784 bool operator == (const const_iterator1 &it) const {
2785 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2786 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
2787 return it_ == it.it_;
2790 bool operator < (const const_iterator1 &it) const {
2791 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2792 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
2793 return it_ < it.it_;
2799 const_subiterator_type it_;
2801 friend class iterator1;
2806 const_iterator1 begin1 () const {
2807 return find1 (0, 0, 0);
2810 const_iterator1 cbegin1 () const {
2814 const_iterator1 end1 () const {
2815 return find1 (0, size1_, 0);
2818 const_iterator1 cend1 () const {
2822 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2824 public container_reference<vector_of_vector>,
2825 public random_access_iterator_base<dense_random_access_iterator_tag,
2826 iterator1, value_type> {
2828 typedef typename vector_of_vector::value_type value_type;
2829 typedef typename vector_of_vector::difference_type difference_type;
2830 typedef typename vector_of_vector::reference reference;
2831 typedef typename vector_of_vector::pointer pointer;
2833 typedef iterator2 dual_iterator_type;
2834 typedef reverse_iterator2 dual_reverse_iterator_type;
2836 // Construction and destruction
2839 container_reference<self_type> (), i_ (), j_ (), it_ () {}
2841 iterator1 (self_type &m, size_type i, size_type j, const subiterator_type &it):
2842 container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
2846 iterator1 &operator ++ () {
2848 self_type &m = (*this) ();
2849 if (layout_type::fast_i ())
2852 it_ = m.find1 (1, i_, j_).it_;
2856 iterator1 &operator -- () {
2858 self_type &m = (*this) ();
2859 if (layout_type::fast_i ())
2862 it_ = m.find1 (1, i_, j_).it_;
2866 iterator1 &operator += (difference_type n) {
2868 self_type &m = (*this) ();
2869 it_ = m.find1 (1, i_, j_).it_;
2873 iterator1 &operator -= (difference_type n) {
2875 self_type &m = (*this) ();
2876 it_ = m.find1 (1, i_, j_).it_;
2880 difference_type operator - (const iterator1 &it) const {
2881 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2882 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
2883 return index1 () - it.index1 ();
2888 reference operator * () const {
2889 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
2890 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
2894 reference operator [] (difference_type n) const {
2895 return *(*this + n);
2898 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2900 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2901 typename self_type::
2903 iterator2 begin () const {
2904 self_type &m = (*this) ();
2905 return m.find2 (1, index1 (), 0);
2908 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2909 typename self_type::
2911 iterator2 end () const {
2912 self_type &m = (*this) ();
2913 return m.find2 (1, index1 (), m.size2 ());
2916 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2917 typename self_type::
2919 reverse_iterator2 rbegin () const {
2920 return reverse_iterator2 (end ());
2923 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2924 typename self_type::
2926 reverse_iterator2 rend () const {
2927 return reverse_iterator2 (begin ());
2933 size_type index1 () const {
2937 size_type index2 () const {
2943 iterator1 &operator = (const iterator1 &it) {
2944 container_reference<self_type>::assign (&it ());
2951 bool operator == (const iterator1 &it) const {
2952 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2953 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
2954 return it_ == it.it_;
2957 bool operator < (const iterator1 &it) const {
2958 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2959 BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
2960 return it_ < it.it_;
2966 subiterator_type it_;
2968 friend class const_iterator1;
2973 iterator1 begin1 () {
2974 return find1 (0, 0, 0);
2978 return find1 (0, size1_, 0);
2981 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2982 class const_iterator2:
2983 public container_const_reference<vector_of_vector>,
2984 public random_access_iterator_base<dense_random_access_iterator_tag,
2985 const_iterator2, value_type> {
2987 typedef typename vector_of_vector::value_type value_type;
2988 typedef typename vector_of_vector::difference_type difference_type;
2989 typedef typename vector_of_vector::const_reference reference;
2990 typedef const typename vector_of_vector::pointer pointer;
2992 typedef const_iterator1 dual_iterator_type;
2993 typedef const_reverse_iterator1 dual_reverse_iterator_type;
2995 // Construction and destruction
2998 container_const_reference<self_type> (), i_ (), j_ (), it_ () {}
3000 const_iterator2 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it):
3001 container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
3003 const_iterator2 (const iterator2 &it):
3004 container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
3008 const_iterator2 &operator ++ () {
3010 const self_type &m = (*this) ();
3011 if (layout_type::fast_j ())
3014 it_ = m.find2 (1, i_, j_).it_;
3018 const_iterator2 &operator -- () {
3020 const self_type &m = (*this) ();
3021 if (layout_type::fast_j ())
3024 it_ = m.find2 (1, i_, j_).it_;
3028 const_iterator2 &operator += (difference_type n) {
3030 const self_type &m = (*this) ();
3031 it_ = m.find2 (1, i_, j_).it_;
3035 const_iterator2 &operator -= (difference_type n) {
3037 const self_type &m = (*this) ();
3038 it_ = m.find2 (1, i_, j_).it_;
3042 difference_type operator - (const const_iterator2 &it) const {
3043 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3044 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
3045 return index2 () - it.index2 ();
3050 const_reference operator * () const {
3051 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
3052 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
3056 const_reference operator [] (difference_type n) const {
3057 return *(*this + n);
3060 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3062 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3063 typename self_type::
3065 const_iterator1 begin () const {
3066 const self_type &m = (*this) ();
3067 return m.find1 (1, 0, index2 ());
3070 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3071 typename self_type::
3073 const_iterator1 cbegin () const {
3077 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3078 typename self_type::
3080 const_iterator1 end () const {
3081 const self_type &m = (*this) ();
3082 return m.find1 (1, m.size1 (), index2 ());
3085 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3086 typename self_type::
3088 const_iterator1 cend () const {
3092 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3093 typename self_type::
3095 const_reverse_iterator1 rbegin () const {
3096 return const_reverse_iterator1 (end ());
3099 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3100 typename self_type::
3102 const_reverse_iterator1 crbegin () const {
3106 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3107 typename self_type::
3109 const_reverse_iterator1 rend () const {
3110 return const_reverse_iterator1 (begin ());
3113 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3114 typename self_type::
3116 const_reverse_iterator2 crend () const {
3123 size_type index1 () const {
3127 size_type index2 () const {
3133 const_iterator2 &operator = (const const_iterator2 &it) {
3134 container_const_reference<self_type>::assign (&it ());
3141 bool operator == (const const_iterator2 &it) const {
3142 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3143 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
3144 return it_ == it.it_;
3147 bool operator < (const const_iterator2 &it) const {
3148 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3149 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
3150 return it_ < it.it_;
3156 const_subiterator_type it_;
3158 friend class iterator2;
3163 const_iterator2 begin2 () const {
3164 return find2 (0, 0, 0);
3167 const_iterator2 cbegin2 () const {
3171 const_iterator2 end2 () const {
3172 return find2 (0, 0, size2_);
3175 const_iterator2 cend2 () const {
3179 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3181 public container_reference<vector_of_vector>,
3182 public random_access_iterator_base<dense_random_access_iterator_tag,
3183 iterator2, value_type> {
3185 typedef typename vector_of_vector::value_type value_type;
3186 typedef typename vector_of_vector::difference_type difference_type;
3187 typedef typename vector_of_vector::reference reference;
3188 typedef typename vector_of_vector::pointer pointer;
3190 typedef iterator1 dual_iterator_type;
3191 typedef reverse_iterator1 dual_reverse_iterator_type;
3193 // Construction and destruction
3196 container_reference<self_type> (), i_ (), j_ (), it_ () {}
3198 iterator2 (self_type &m, size_type i, size_type j, const subiterator_type &it):
3199 container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
3203 iterator2 &operator ++ () {
3205 self_type &m = (*this) ();
3206 if (layout_type::fast_j ())
3209 it_ = m.find2 (1, i_, j_).it_;
3213 iterator2 &operator -- () {
3215 self_type &m = (*this) ();
3216 if (layout_type::fast_j ())
3219 it_ = m.find2 (1, i_, j_).it_;
3223 iterator2 &operator += (difference_type n) {
3225 self_type &m = (*this) ();
3226 it_ = m.find2 (1, i_, j_).it_;
3230 iterator2 &operator -= (difference_type n) {
3232 self_type &m = (*this) ();
3233 it_ = m.find2 (1, i_, j_).it_;
3237 difference_type operator - (const iterator2 &it) const {
3238 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3239 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
3240 return index2 () - it.index2 ();
3245 reference operator * () const {
3246 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
3247 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
3251 reference operator [] (difference_type n) const {
3252 return *(*this + n);
3255 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3257 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3258 typename self_type::
3260 iterator1 begin () const {
3261 self_type &m = (*this) ();
3262 return m.find1 (1, 0, index2 ());
3265 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3266 typename self_type::
3268 iterator1 end () const {
3269 self_type &m = (*this) ();
3270 return m.find1 (1, m.size1 (), index2 ());
3273 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3274 typename self_type::
3276 reverse_iterator1 rbegin () const {
3277 return reverse_iterator1 (end ());
3280 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3281 typename self_type::
3283 reverse_iterator1 rend () const {
3284 return reverse_iterator1 (begin ());
3290 size_type index1 () const {
3294 size_type index2 () const {
3300 iterator2 &operator = (const iterator2 &it) {
3301 container_reference<self_type>::assign (&it ());
3308 bool operator == (const iterator2 &it) const {
3309 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3310 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
3311 return it_ == it.it_;
3314 bool operator < (const iterator2 &it) const {
3315 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3316 BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
3317 return it_ < it.it_;
3323 subiterator_type it_;
3325 friend class const_iterator2;
3330 iterator2 begin2 () {
3331 return find2 (0, 0, 0);
3335 return find2 (0, 0, size2_);
3338 // Reverse iterators
3341 const_reverse_iterator1 rbegin1 () const {
3342 return const_reverse_iterator1 (end1 ());
3345 const_reverse_iterator1 crbegin1 () const {
3349 const_reverse_iterator1 rend1 () const {
3350 return const_reverse_iterator1 (begin1 ());
3353 const_reverse_iterator1 crend1 () const {
3358 reverse_iterator1 rbegin1 () {
3359 return reverse_iterator1 (end1 ());
3362 reverse_iterator1 rend1 () {
3363 return reverse_iterator1 (begin1 ());
3367 const_reverse_iterator2 rbegin2 () const {
3368 return const_reverse_iterator2 (end2 ());
3371 const_reverse_iterator2 crbegin2 () const {
3375 const_reverse_iterator2 rend2 () const {
3376 return const_reverse_iterator2 (begin2 ());
3379 const_reverse_iterator2 crend2 () const {
3384 reverse_iterator2 rbegin2 () {
3385 return reverse_iterator2 (end2 ());
3388 reverse_iterator2 rend2 () {
3389 return reverse_iterator2 (begin2 ());
3393 template<class Archive>
3394 void serialize(Archive & ar, const unsigned int /* file_version */){
3396 // we need to copy to a collection_size_type to get a portable
3397 // and efficient serialization
3398 serialization::collection_size_type s1 (size1_);
3399 serialization::collection_size_type s2 (size2_);
3401 // serialize the sizes
3402 ar & serialization::make_nvp("size1",s1)
3403 & serialization::make_nvp("size2",s2);
3405 // copy the values back if loading
3406 if (Archive::is_loading::value) {
3410 ar & serialization::make_nvp("data",data_);
3420 /** \brief A matrix with all values of type \c T equal to zero
3422 * Changing values does not affect the matrix, however assigning it to a normal matrix will put zero
3423 * everywhere in the target matrix. All accesses are constant time, due to the trivial value.
3425 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
3426 * \tparam ALLOC an allocator for storing the zero element. By default, a standar allocator is used.
3428 template<class T, class ALLOC>
3430 public matrix_container<zero_matrix<T, ALLOC> > {
3432 typedef const T *const_pointer;
3433 typedef zero_matrix<T, ALLOC> self_type;
3435 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
3436 using matrix_container<self_type>::operator ();
3438 typedef typename ALLOC::size_type size_type;
3439 typedef typename ALLOC::difference_type difference_type;
3440 typedef T value_type;
3441 typedef const T &const_reference;
3442 typedef T &reference;
3443 typedef const matrix_reference<const self_type> const_closure_type;
3444 typedef matrix_reference<self_type> closure_type;
3445 typedef sparse_tag storage_category;
3446 typedef unknown_orientation_tag orientation_category;
3448 // Construction and destruction
3451 matrix_container<self_type> (),
3452 size1_ (0), size2_ (0) {}
3454 zero_matrix (size_type size):
3455 matrix_container<self_type> (),
3456 size1_ (size), size2_ (size) {}
3458 zero_matrix (size_type size1, size_type size2):
3459 matrix_container<self_type> (),
3460 size1_ (size1), size2_ (size2) {}
3462 zero_matrix (const zero_matrix &m):
3463 matrix_container<self_type> (),
3464 size1_ (m.size1_), size2_ (m.size2_) {}
3468 size_type size1 () const {
3472 size_type size2 () const {
3478 void resize (size_type size, bool /*preserve*/ = true) {
3483 void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
3490 const_reference operator () (size_type /* i */, size_type /* j */) const {
3496 zero_matrix &operator = (const zero_matrix &m) {
3502 zero_matrix &assign_temporary (zero_matrix &m) {
3509 void swap (zero_matrix &m) {
3511 std::swap (size1_, m.size1_);
3512 std::swap (size2_, m.size2_);
3516 friend void swap (zero_matrix &m1, zero_matrix &m2) {
3522 class const_iterator1;
3523 class const_iterator2;
3524 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
3525 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
3529 const_iterator1 find1 (int /*rank*/, size_type /*i*/, size_type /*j*/) const {
3530 return const_iterator1 (*this);
3533 const_iterator2 find2 (int /*rank*/, size_type /*i*/, size_type /*j*/) const {
3534 return const_iterator2 (*this);
3537 class const_iterator1:
3538 public container_const_reference<zero_matrix>,
3539 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
3540 const_iterator1, value_type> {
3542 typedef typename zero_matrix::value_type value_type;
3543 typedef typename zero_matrix::difference_type difference_type;
3544 typedef typename zero_matrix::const_reference reference;
3545 typedef typename zero_matrix::const_pointer pointer;
3547 typedef const_iterator2 dual_iterator_type;
3548 typedef const_reverse_iterator2 dual_reverse_iterator_type;
3550 // Construction and destruction
3553 container_const_reference<self_type> () {}
3555 const_iterator1 (const self_type &m):
3556 container_const_reference<self_type> (m) {}
3560 const_iterator1 &operator ++ () {
3561 BOOST_UBLAS_CHECK_FALSE (bad_index ());
3565 const_iterator1 &operator -- () {
3566 BOOST_UBLAS_CHECK_FALSE (bad_index ());
3572 const_reference operator * () const {
3573 BOOST_UBLAS_CHECK_FALSE (bad_index ());
3574 return zero_; // arbitary return value
3577 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3579 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3580 typename self_type::
3582 const_iterator2 begin () const {
3583 return const_iterator2 ((*this) ());
3586 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3587 typename self_type::
3589 const_iterator2 cbegin () const {
3593 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3594 typename self_type::
3596 const_iterator2 end () const {
3597 return const_iterator2 ((*this) ());
3600 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3601 typename self_type::
3603 const_iterator2 cend () const {
3607 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3608 typename self_type::
3610 const_reverse_iterator2 rbegin () const {
3611 return const_reverse_iterator2 (end ());
3614 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3615 typename self_type::
3617 const_reverse_iterator2 crbegin () const {
3621 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3622 typename self_type::
3624 const_reverse_iterator2 rend () const {
3625 return const_reverse_iterator2 (begin ());
3628 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3629 typename self_type::
3631 const_reverse_iterator2 crend () const {
3638 size_type index1 () const {
3639 BOOST_UBLAS_CHECK_FALSE (bad_index ());
3640 return 0; // arbitary return value
3643 size_type index2 () const {
3644 BOOST_UBLAS_CHECK_FALSE (bad_index ());
3645 return 0; // arbitary return value
3650 const_iterator1 &operator = (const const_iterator1 &it) {
3651 container_const_reference<self_type>::assign (&it ());
3657 bool operator == (const const_iterator1 &it) const {
3658 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3659 detail::ignore_unused_variable_warning(it);
3664 typedef const_iterator1 iterator1;
3667 const_iterator1 begin1 () const {
3668 return const_iterator1 (*this);
3671 const_iterator1 cbegin1 () const {
3675 const_iterator1 end1 () const {
3676 return const_iterator1 (*this);
3679 const_iterator1 cend1 () const {
3683 class const_iterator2:
3684 public container_const_reference<zero_matrix>,
3685 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
3686 const_iterator2, value_type> {
3688 typedef typename zero_matrix::value_type value_type;
3689 typedef typename zero_matrix::difference_type difference_type;
3690 typedef typename zero_matrix::const_reference reference;
3691 typedef typename zero_matrix::const_pointer pointer;
3693 typedef const_iterator1 dual_iterator_type;
3694 typedef const_reverse_iterator1 dual_reverse_iterator_type;
3696 // Construction and destruction
3699 container_const_reference<self_type> () {}
3701 const_iterator2 (const self_type &m):
3702 container_const_reference<self_type> (m) {}
3706 const_iterator2 &operator ++ () {
3707 BOOST_UBLAS_CHECK_FALSE (bad_index ());
3711 const_iterator2 &operator -- () {
3712 BOOST_UBLAS_CHECK_FALSE (bad_index ());
3718 const_reference operator * () const {
3719 BOOST_UBLAS_CHECK_FALSE (bad_index ());
3720 return zero_; // arbitary return value
3723 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3725 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3726 typename self_type::
3728 const_iterator1 begin () const {
3729 return const_iterator1 ((*this) ());
3732 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3733 typename self_type::
3735 const_iterator1 cbegin () const {
3739 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3740 typename self_type::
3742 const_iterator1 end () const {
3743 return const_iterator1 ((*this) ());
3746 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3747 typename self_type::
3749 const_iterator1 cend () const {
3753 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3754 typename self_type::
3756 const_reverse_iterator1 rbegin () const {
3757 return const_reverse_iterator1 (end ());
3760 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3761 typename self_type::
3763 const_reverse_iterator1 crbegin () const {
3767 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3768 typename self_type::
3770 const_reverse_iterator1 rend () const {
3771 return const_reverse_iterator1 (begin ());
3774 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3775 typename self_type::
3777 const_reverse_iterator1 crend () const {
3784 size_type index1 () const {
3785 BOOST_UBLAS_CHECK_FALSE (bad_index ());
3786 return 0; // arbitary return value
3789 size_type index2 () const {
3790 BOOST_UBLAS_CHECK_FALSE (bad_index ());
3791 return 0; // arbitary return value
3796 const_iterator2 &operator = (const const_iterator2 &it) {
3797 container_const_reference<self_type>::assign (&it ());
3803 bool operator == (const const_iterator2 &it) const {
3804 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3805 detail::ignore_unused_variable_warning(it);
3810 typedef const_iterator2 iterator2;
3813 const_iterator2 begin2 () const {
3814 return find2 (0, 0, 0);
3817 const_iterator2 cbegin2 () const {
3821 const_iterator2 end2 () const {
3822 return find2 (0, 0, size2_);
3825 const_iterator2 cend2 () const {
3829 // Reverse iterators
3832 const_reverse_iterator1 rbegin1 () const {
3833 return const_reverse_iterator1 (end1 ());
3836 const_reverse_iterator1 crbegin1 () const {
3840 const_reverse_iterator1 rend1 () const {
3841 return const_reverse_iterator1 (begin1 ());
3844 const_reverse_iterator1 crend1 () const {
3849 const_reverse_iterator2 rbegin2 () const {
3850 return const_reverse_iterator2 (end2 ());
3853 const_reverse_iterator2 crbegin2 () const {
3857 const_reverse_iterator2 rend2 () const {
3858 return const_reverse_iterator2 (begin2 ());
3861 const_reverse_iterator2 crend2 () const {
3866 template<class Archive>
3867 void serialize(Archive & ar, const unsigned int /* file_version */){
3869 // we need to copy to a collection_size_type to get a portable
3870 // and efficient serialization
3871 serialization::collection_size_type s1 (size1_);
3872 serialization::collection_size_type s2 (size2_);
3874 // serialize the sizes
3875 ar & serialization::make_nvp("size1",s1)
3876 & serialization::make_nvp("size2",s2);
3878 // copy the values back if loading
3879 if (Archive::is_loading::value) {
3888 static const value_type zero_;
3891 template<class T, class ALLOC>
3892 const typename zero_matrix<T, ALLOC>::value_type zero_matrix<T, ALLOC>::zero_ = T(/*zero*/);
3894 /** \brief An identity matrix with values of type \c T
3896 * Elements or cordinates \f$(i,i)\f$ are equal to 1 (one) and all others to 0 (zero).
3897 * Changing values does not affect the matrix, however assigning it to a normal matrix will
3898 * make the matrix equal to an identity matrix. All accesses are constant du to the trivial values.
3900 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
3901 * \tparam ALLOC an allocator for storing the zeros and one elements. By default, a standar allocator is used.
3903 template<class T, class ALLOC>
3904 class identity_matrix:
3905 public matrix_container<identity_matrix<T, ALLOC> > {
3907 typedef const T *const_pointer;
3908 typedef identity_matrix<T, ALLOC> self_type;
3910 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
3911 using matrix_container<self_type>::operator ();
3913 typedef typename ALLOC::size_type size_type;
3914 typedef typename ALLOC::difference_type difference_type;
3915 typedef T value_type;
3916 typedef const T &const_reference;
3917 typedef T &reference;
3918 typedef const matrix_reference<const self_type> const_closure_type;
3919 typedef matrix_reference<self_type> closure_type;
3920 typedef sparse_tag storage_category;
3921 typedef unknown_orientation_tag orientation_category;
3923 // Construction and destruction
3926 matrix_container<self_type> (),
3927 size1_ (0), size2_ (0), size_common_ (0) {}
3929 identity_matrix (size_type size):
3930 matrix_container<self_type> (),
3931 size1_ (size), size2_ (size), size_common_ ((std::min) (size1_, size2_)) {}
3933 identity_matrix (size_type size1, size_type size2):
3934 matrix_container<self_type> (),
3935 size1_ (size1), size2_ (size2), size_common_ ((std::min) (size1_, size2_)) {}
3937 identity_matrix (const identity_matrix &m):
3938 matrix_container<self_type> (),
3939 size1_ (m.size1_), size2_ (m.size2_), size_common_ ((std::min) (size1_, size2_)) {}
3943 size_type size1 () const {
3947 size_type size2 () const {
3953 void resize (size_type size, bool /*preserve*/ = true) {
3956 size_common_ = ((std::min)(size1_, size2_));
3959 void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
3962 size_common_ = ((std::min)(size1_, size2_));
3967 const_reference operator () (size_type i, size_type j) const {
3976 identity_matrix &operator = (const identity_matrix &m) {
3979 size_common_ = m.size_common_;
3983 identity_matrix &assign_temporary (identity_matrix &m) {
3990 void swap (identity_matrix &m) {
3992 std::swap (size1_, m.size1_);
3993 std::swap (size2_, m.size2_);
3994 std::swap (size_common_, m.size_common_);
3998 friend void swap (identity_matrix &m1, identity_matrix &m2) {
4005 typedef size_type const_subiterator_type;
4008 class const_iterator1;
4009 class const_iterator2;
4010 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
4011 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
4015 const_iterator1 find1 (int rank, size_type i, size_type j) const {
4017 i = (std::max) (i, j);
4018 i = (std::min) (i, j + 1);
4020 return const_iterator1 (*this, i);
4023 const_iterator2 find2 (int rank, size_type i, size_type j) const {
4025 j = (std::max) (j, i);
4026 j = (std::min) (j, i + 1);
4028 return const_iterator2 (*this, j);
4032 class const_iterator1:
4033 public container_const_reference<identity_matrix>,
4034 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
4035 const_iterator1, value_type> {
4037 typedef typename identity_matrix::value_type value_type;
4038 typedef typename identity_matrix::difference_type difference_type;
4039 typedef typename identity_matrix::const_reference reference;
4040 typedef typename identity_matrix::const_pointer pointer;
4042 typedef const_iterator2 dual_iterator_type;
4043 typedef const_reverse_iterator2 dual_reverse_iterator_type;
4045 // Construction and destruction
4048 container_const_reference<self_type> (), it_ () {}
4050 const_iterator1 (const self_type &m, const const_subiterator_type &it):
4051 container_const_reference<self_type> (m), it_ (it) {}
4055 const_iterator1 &operator ++ () {
4056 BOOST_UBLAS_CHECK (it_ < (*this) ().size1 (), bad_index ());
4061 const_iterator1 &operator -- () {
4062 BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
4069 const_reference operator * () const {
4073 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4075 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4076 typename self_type::
4078 const_iterator2 begin () const {
4079 return const_iterator2 ((*this) (), it_);
4082 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4083 typename self_type::
4085 const_iterator2 cbegin () const {
4089 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4090 typename self_type::
4092 const_iterator2 end () const {
4093 return const_iterator2 ((*this) (), it_ + 1);
4096 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4097 typename self_type::
4099 const_iterator2 cend () const {
4103 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4104 typename self_type::
4106 const_reverse_iterator2 rbegin () const {
4107 return const_reverse_iterator2 (end ());
4110 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4111 typename self_type::
4113 const_reverse_iterator2 crbegin () const {
4117 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4118 typename self_type::
4120 const_reverse_iterator2 rend () const {
4121 return const_reverse_iterator2 (begin ());
4124 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4125 typename self_type::
4127 const_reverse_iterator2 crend () const {
4134 size_type index1 () const {
4138 size_type index2 () const {
4144 const_iterator1 &operator = (const const_iterator1 &it) {
4145 container_const_reference<self_type>::assign (&it ());
4152 bool operator == (const const_iterator1 &it) const {
4153 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
4154 return it_ == it.it_;
4158 const_subiterator_type it_;
4161 typedef const_iterator1 iterator1;
4164 const_iterator1 begin1 () const {
4165 return const_iterator1 (*this, 0);
4168 const_iterator1 cbegin1 () const {
4172 const_iterator1 end1 () const {
4173 return const_iterator1 (*this, size_common_);
4176 const_iterator1 cend1 () const {
4180 class const_iterator2:
4181 public container_const_reference<identity_matrix>,
4182 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
4183 const_iterator2, value_type> {
4185 typedef typename identity_matrix::value_type value_type;
4186 typedef typename identity_matrix::difference_type difference_type;
4187 typedef typename identity_matrix::const_reference reference;
4188 typedef typename identity_matrix::const_pointer pointer;
4190 typedef const_iterator1 dual_iterator_type;
4191 typedef const_reverse_iterator1 dual_reverse_iterator_type;
4193 // Construction and destruction
4196 container_const_reference<self_type> (), it_ () {}
4198 const_iterator2 (const self_type &m, const const_subiterator_type &it):
4199 container_const_reference<self_type> (m), it_ (it) {}
4203 const_iterator2 &operator ++ () {
4204 BOOST_UBLAS_CHECK (it_ < (*this) ().size_common_, bad_index ());
4209 const_iterator2 &operator -- () {
4210 BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
4217 const_reference operator * () const {
4221 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4223 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4224 typename self_type::
4226 const_iterator1 begin () const {
4227 return const_iterator1 ((*this) (), it_);
4230 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4231 typename self_type::
4233 const_iterator1 cbegin () const {
4237 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4238 typename self_type::
4240 const_iterator1 end () const {
4241 return const_iterator1 ((*this) (), it_ + 1);
4244 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4245 typename self_type::
4247 const_iterator1 cend () const {
4251 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4252 typename self_type::
4254 const_reverse_iterator1 rbegin () const {
4255 return const_reverse_iterator1 (end ());
4258 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4259 typename self_type::
4261 const_reverse_iterator1 crbegin () const {
4265 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4266 typename self_type::
4268 const_reverse_iterator1 rend () const {
4269 return const_reverse_iterator1 (begin ());
4272 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4273 typename self_type::
4275 const_reverse_iterator1 crend () const {
4282 size_type index1 () const {
4286 size_type index2 () const {
4292 const_iterator2 &operator = (const const_iterator2 &it) {
4293 container_const_reference<self_type>::assign (&it ());
4300 bool operator == (const const_iterator2 &it) const {
4301 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
4302 return it_ == it.it_;
4306 const_subiterator_type it_;
4309 typedef const_iterator2 iterator2;
4312 const_iterator2 begin2 () const {
4313 return const_iterator2 (*this, 0);
4316 const_iterator2 cbegin2 () const {
4320 const_iterator2 end2 () const {
4321 return const_iterator2 (*this, size_common_);
4324 const_iterator2 cend2 () const {
4328 // Reverse iterators
4331 const_reverse_iterator1 rbegin1 () const {
4332 return const_reverse_iterator1 (end1 ());
4335 const_reverse_iterator1 crbegin1 () const {
4339 const_reverse_iterator1 rend1 () const {
4340 return const_reverse_iterator1 (begin1 ());
4343 const_reverse_iterator1 crend1 () const {
4348 const_reverse_iterator2 rbegin2 () const {
4349 return const_reverse_iterator2 (end2 ());
4352 const_reverse_iterator2 crbegin2 () const {
4356 const_reverse_iterator2 rend2 () const {
4357 return const_reverse_iterator2 (begin2 ());
4360 const_reverse_iterator2 crend2 () const {
4365 template<class Archive>
4366 void serialize(Archive & ar, const unsigned int /* file_version */){
4368 // we need to copy to a collection_size_type to get a portable
4369 // and efficient serialization
4370 serialization::collection_size_type s1 (size1_);
4371 serialization::collection_size_type s2 (size2_);
4373 // serialize the sizes
4374 ar & serialization::make_nvp("size1",s1)
4375 & serialization::make_nvp("size2",s2);
4377 // copy the values back if loading
4378 if (Archive::is_loading::value) {
4381 size_common_ = ((std::min)(size1_, size2_));
4388 size_type size_common_;
4389 static const value_type zero_;
4390 static const value_type one_;
4393 template<class T, class ALLOC>
4394 const typename identity_matrix<T, ALLOC>::value_type identity_matrix<T, ALLOC>::zero_ = T(/*zero*/);
4395 template<class T, class ALLOC>
4396 const typename identity_matrix<T, ALLOC>::value_type identity_matrix<T, ALLOC>::one_ (1); // ISSUE: need 'one'-traits here
4399 /** \brief A matrix with all values of type \c T equal to the same value
4401 * Changing one value has the effect of changing all the values. Assigning it to a normal matrix will copy
4402 * the same value everywhere in this matrix. All accesses are constant time, due to the trivial value.
4404 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
4405 * \tparam ALLOC an allocator for storing the unique value. By default, a standar allocator is used.
4407 template<class T, class ALLOC>
4408 class scalar_matrix:
4409 public matrix_container<scalar_matrix<T, ALLOC> > {
4411 typedef const T *const_pointer;
4412 typedef scalar_matrix<T, ALLOC> self_type;
4414 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4415 using matrix_container<self_type>::operator ();
4417 typedef std::size_t size_type;
4418 typedef std::ptrdiff_t difference_type;
4419 typedef T value_type;
4420 typedef const T &const_reference;
4421 typedef T &reference;
4422 typedef const matrix_reference<const self_type> const_closure_type;
4423 typedef matrix_reference<self_type> closure_type;
4424 typedef dense_tag storage_category;
4425 typedef unknown_orientation_tag orientation_category;
4427 // Construction and destruction
4430 matrix_container<self_type> (),
4431 size1_ (0), size2_ (0), value_ () {}
4433 scalar_matrix (size_type size1, size_type size2, const value_type &value = value_type(1)):
4434 matrix_container<self_type> (),
4435 size1_ (size1), size2_ (size2), value_ (value) {}
4437 scalar_matrix (const scalar_matrix &m):
4438 matrix_container<self_type> (),
4439 size1_ (m.size1_), size2_ (m.size2_), value_ (m.value_) {}
4443 size_type size1 () const {
4447 size_type size2 () const {
4453 void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
4460 const_reference operator () (size_type /*i*/, size_type /*j*/) const {
4466 scalar_matrix &operator = (const scalar_matrix &m) {
4473 scalar_matrix &assign_temporary (scalar_matrix &m) {
4480 void swap (scalar_matrix &m) {
4482 std::swap (size1_, m.size1_);
4483 std::swap (size2_, m.size2_);
4484 std::swap (value_, m.value_);
4488 friend void swap (scalar_matrix &m1, scalar_matrix &m2) {
4495 typedef size_type const_subiterator_type;
4498 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4499 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
4500 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
4501 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
4502 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
4504 class const_iterator1;
4505 class const_iterator2;
4507 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
4508 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
4512 const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
4513 return const_iterator1 (*this, i, j);
4516 const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
4517 return const_iterator2 (*this, i, j);
4521 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4522 class const_iterator1:
4523 public container_const_reference<scalar_matrix>,
4524 public random_access_iterator_base<dense_random_access_iterator_tag,
4525 const_iterator1, value_type> {
4527 typedef typename scalar_matrix::value_type value_type;
4528 typedef typename scalar_matrix::difference_type difference_type;
4529 typedef typename scalar_matrix::const_reference reference;
4530 typedef typename scalar_matrix::const_pointer pointer;
4532 typedef const_iterator2 dual_iterator_type;
4533 typedef const_reverse_iterator2 dual_reverse_iterator_type;
4535 // Construction and destruction
4538 container_const_reference<scalar_matrix> (), it1_ (), it2_ () {}
4540 const_iterator1 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2):
4541 container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {}
4545 const_iterator1 &operator ++ () {
4550 const_iterator1 &operator -- () {
4555 const_iterator1 &operator += (difference_type n) {
4560 const_iterator1 &operator -= (difference_type n) {
4565 difference_type operator - (const const_iterator1 &it) const {
4566 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
4567 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4568 return it1_ - it.it1_;
4573 const_reference operator * () const {
4574 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
4575 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
4576 return (*this) () (index1 (), index2 ());
4579 const_reference operator [] (difference_type n) const {
4580 return *(*this + n);
4583 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4585 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4586 typename self_type::
4588 const_iterator2 begin () const {
4589 const scalar_matrix &m = (*this) ();
4590 return m.find2 (1, index1 (), 0);
4593 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4594 typename self_type::
4596 const_iterator2 cbegin () const {
4600 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4601 typename self_type::
4603 const_iterator2 end () const {
4604 const scalar_matrix &m = (*this) ();
4605 return m.find2 (1, index1 (), m.size2 ());
4608 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4609 typename self_type::
4611 const_iterator2 cend () const {
4615 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4616 typename self_type::
4618 const_reverse_iterator2 rbegin () const {
4619 return const_reverse_iterator2 (end ());
4622 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4623 typename self_type::
4625 const_reverse_iterator2 crbegin () const {
4629 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4630 typename self_type::
4632 const_reverse_iterator2 rend () const {
4633 return const_reverse_iterator2 (begin ());
4636 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4637 typename self_type::
4639 const_reverse_iterator2 crend () const {
4646 size_type index1 () const {
4650 size_type index2 () const {
4656 const_iterator1 &operator = (const const_iterator1 &it) {
4657 container_const_reference<scalar_matrix>::assign (&it ());
4665 bool operator == (const const_iterator1 &it) const {
4666 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
4667 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4668 return it1_ == it.it1_;
4671 bool operator < (const const_iterator1 &it) const {
4672 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
4673 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4674 return it1_ < it.it1_;
4678 const_subiterator_type it1_;
4679 const_subiterator_type it2_;
4682 typedef const_iterator1 iterator1;
4686 const_iterator1 begin1 () const {
4687 return find1 (0, 0, 0);
4690 const_iterator1 cbegin1 () const {
4694 const_iterator1 end1 () const {
4695 return find1 (0, size1_, 0);
4698 const_iterator1 cend1 () const {
4702 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4703 class const_iterator2:
4704 public container_const_reference<scalar_matrix>,
4705 public random_access_iterator_base<dense_random_access_iterator_tag,
4706 const_iterator2, value_type> {
4708 typedef typename scalar_matrix::value_type value_type;
4709 typedef typename scalar_matrix::difference_type difference_type;
4710 typedef typename scalar_matrix::const_reference reference;
4711 typedef typename scalar_matrix::const_pointer pointer;
4713 typedef const_iterator1 dual_iterator_type;
4714 typedef const_reverse_iterator1 dual_reverse_iterator_type;
4716 // Construction and destruction
4719 container_const_reference<scalar_matrix> (), it1_ (), it2_ () {}
4721 const_iterator2 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2):
4722 container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {}
4726 const_iterator2 &operator ++ () {
4731 const_iterator2 &operator -- () {
4736 const_iterator2 &operator += (difference_type n) {
4741 const_iterator2 &operator -= (difference_type n) {
4746 difference_type operator - (const const_iterator2 &it) const {
4747 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
4748 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4749 return it2_ - it.it2_;
4754 const_reference operator * () const {
4755 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
4756 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
4757 return (*this) () (index1 (), index2 ());
4760 const_reference operator [] (difference_type n) const {
4761 return *(*this + n);
4764 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4766 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4767 typename self_type::
4769 const_iterator1 begin () const {
4770 const scalar_matrix &m = (*this) ();
4771 return m.find1 (1, 0, index2 ());
4774 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4775 typename self_type::
4777 const_iterator1 cbegin () const {
4781 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4782 typename self_type::
4784 const_iterator1 end () const {
4785 const scalar_matrix &m = (*this) ();
4786 return m.find1 (1, m.size1 (), index2 ());
4789 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4790 typename self_type::
4792 const_iterator1 cend () const {
4796 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4797 typename self_type::
4799 const_reverse_iterator1 rbegin () const {
4800 return const_reverse_iterator1 (end ());
4803 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4804 typename self_type::
4806 const_reverse_iterator1 crbegin () const {
4810 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4811 typename self_type::
4813 const_reverse_iterator1 rend () const {
4814 return const_reverse_iterator1 (begin ());
4817 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4818 typename self_type::
4820 const_reverse_iterator1 crend () const {
4827 size_type index1 () const {
4831 size_type index2 () const {
4837 const_iterator2 &operator = (const const_iterator2 &it) {
4838 container_const_reference<scalar_matrix>::assign (&it ());
4846 bool operator == (const const_iterator2 &it) const {
4847 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
4848 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4849 return it2_ == it.it2_;
4852 bool operator < (const const_iterator2 &it) const {
4853 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
4854 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4855 return it2_ < it.it2_;
4859 const_subiterator_type it1_;
4860 const_subiterator_type it2_;
4863 typedef const_iterator2 iterator2;
4867 const_iterator2 begin2 () const {
4868 return find2 (0, 0, 0);
4871 const_iterator2 cbegin2 () const {
4875 const_iterator2 end2 () const {
4876 return find2 (0, 0, size2_);
4879 const_iterator2 cend2 () const {
4883 // Reverse iterators
4886 const_reverse_iterator1 rbegin1 () const {
4887 return const_reverse_iterator1 (end1 ());
4890 const_reverse_iterator1 crbegin1 () const {
4894 const_reverse_iterator1 rend1 () const {
4895 return const_reverse_iterator1 (begin1 ());
4898 const_reverse_iterator1 crend1 () const {
4903 const_reverse_iterator2 rbegin2 () const {
4904 return const_reverse_iterator2 (end2 ());
4907 const_reverse_iterator2 crbegin2 () const {
4911 const_reverse_iterator2 rend2 () const {
4912 return const_reverse_iterator2 (begin2 ());
4915 const_reverse_iterator2 crend2 () const {
4920 template<class Archive>
4921 void serialize(Archive & ar, const unsigned int /* file_version */){
4923 // we need to copy to a collection_size_type to get a portable
4924 // and efficient serialization
4925 serialization::collection_size_type s1 (size1_);
4926 serialization::collection_size_type s2 (size2_);
4928 // serialize the sizes
4929 ar & serialization::make_nvp("size1",s1)
4930 & serialization::make_nvp("size2",s2);
4932 // copy the values back if loading
4933 if (Archive::is_loading::value) {
4938 ar & serialization::make_nvp("value", value_);
4948 /** \brief An array based matrix class which size is defined at type specification or object instanciation
4950 * This matrix is directly based on a predefined C-style arry of data, thus providing the fastest
4951 * implementation possible. The constraint is that dimensions of the matrix must be specified at
4952 * the instanciation or the type specification.
4954 * For instance, \code typedef c_matrix<double,4,4> my_4by4_matrix \endcode
4955 * defines a 4 by 4 double-precision matrix. You can also instantiate it directly with
4956 * \code c_matrix<int,8,5> my_fast_matrix \endcode. This will make a 8 by 5 integer matrix. The
4957 * price to pay for this speed is that you cannot resize it to a size larger than the one defined
4958 * in the template parameters. In the previous example, a size of 4 by 5 or 3 by 2 is acceptable,
4959 * but a new size of 9 by 5 or even 10 by 10 will raise a bad_size() exception.
4961 * \tparam T the type of object stored in the matrix (like double, float, complex, etc...)
4962 * \tparam N the default maximum number of rows
4963 * \tparam M the default maximum number of columns
4965 template<class T, std::size_t N, std::size_t M>
4967 public matrix_container<c_matrix<T, N, M> > {
4969 typedef c_matrix<T, N, M> self_type;
4971 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4972 using matrix_container<self_type>::operator ();
4974 typedef std::size_t size_type;
4975 typedef std::ptrdiff_t difference_type;
4976 typedef T value_type;
4977 typedef const T &const_reference;
4978 typedef T &reference;
4979 typedef const T *const_pointer;
4981 typedef const matrix_reference<const self_type> const_closure_type;
4982 typedef matrix_reference<self_type> closure_type;
4983 typedef c_vector<T, N * M> vector_temporary_type; // vector able to store all elements of c_matrix
4984 typedef self_type matrix_temporary_type;
4985 typedef dense_tag storage_category;
4986 // This could be better for performance,
4987 // typedef typename unknown_orientation_tag orientation_category;
4988 // but others depend on the orientation information...
4989 typedef row_major_tag orientation_category;
4991 // Construction and destruction
4994 size1_ (N), size2_ (M) /* , data_ () */ {
4997 c_matrix (size_type size1, size_type size2):
4998 size1_ (size1), size2_ (size2) /* , data_ () */ {
4999 if (size1_ > N || size2_ > M)
5000 bad_size ().raise ();
5003 c_matrix (const c_matrix &m):
5004 size1_ (m.size1_), size2_ (m.size2_) /* , data_ () */ {
5005 if (size1_ > N || size2_ > M)
5006 bad_size ().raise ();
5011 c_matrix (const matrix_expression<AE> &ae):
5012 size1_ (ae ().size1 ()), size2_ (ae ().size2 ()) /* , data_ () */ {
5013 if (size1_ > N || size2_ > M)
5014 bad_size ().raise ();
5015 matrix_assign<scalar_assign> (*this, ae);
5020 size_type size1 () const {
5024 size_type size2 () const {
5028 const_pointer data () const {
5029 return reinterpret_cast<const_pointer> (data_);
5033 return reinterpret_cast<pointer> (data_);
5038 void resize (size_type size1, size_type size2, bool preserve = true) {
5039 if (size1 > N || size2 > M)
5040 bad_size ().raise ();
5042 self_type temporary (size1, size2);
5043 // Common elements to preserve
5044 const size_type size1_min = (std::min) (size1, size1_);
5045 const size_type size2_min = (std::min) (size2, size2_);
5046 for (size_type i = 0; i != size1_min; ++i) { // indexing copy over major
5047 for (size_type j = 0; j != size2_min; ++j) {
5048 temporary.data_[i][j] = data_[i][j];
5051 assign_temporary (temporary);
5061 const_reference operator () (size_type i, size_type j) const {
5062 BOOST_UBLAS_CHECK (i < size1_, bad_index ());
5063 BOOST_UBLAS_CHECK (j < size2_, bad_index ());
5064 return data_ [i] [j];
5067 reference at_element (size_type i, size_type j) {
5068 BOOST_UBLAS_CHECK (i < size1_, bad_index ());
5069 BOOST_UBLAS_CHECK (j < size2_, bad_index ());
5070 return data_ [i] [j];
5073 reference operator () (size_type i, size_type j) {
5074 return at_element (i, j);
5077 // Element assignment
5079 reference insert_element (size_type i, size_type j, const_reference t) {
5080 return (at_element (i, j) = t);
5086 for (size_type i = 0; i < size1_; ++ i)
5087 std::fill (data_ [i], data_ [i] + size2_, value_type/*zero*/());
5091 #ifdef BOOST_UBLAS_MOVE_SEMANTICS
5093 /*! @note "pass by value" the key idea to enable move semantics */
5095 c_matrix &operator = (c_matrix m) {
5096 assign_temporary(m);
5101 c_matrix &operator = (const c_matrix &m) {
5104 for (size_type i = 0; i < m.size1_; ++ i)
5105 std::copy (m.data_ [i], m.data_ [i] + m.size2_, data_ [i]);
5109 template<class C> // Container assignment without temporary
5111 c_matrix &operator = (const matrix_container<C> &m) {
5112 resize (m ().size1 (), m ().size2 (), false);
5117 c_matrix &assign_temporary (c_matrix &m) {
5123 c_matrix &operator = (const matrix_expression<AE> &ae) {
5124 self_type temporary (ae);
5125 return assign_temporary (temporary);
5129 c_matrix &assign (const matrix_expression<AE> &ae) {
5130 matrix_assign<scalar_assign> (*this, ae);
5135 c_matrix& operator += (const matrix_expression<AE> &ae) {
5136 self_type temporary (*this + ae);
5137 return assign_temporary (temporary);
5139 template<class C> // Container assignment without temporary
5141 c_matrix &operator += (const matrix_container<C> &m) {
5147 c_matrix &plus_assign (const matrix_expression<AE> &ae) {
5148 matrix_assign<scalar_plus_assign> (*this, ae);
5153 c_matrix& operator -= (const matrix_expression<AE> &ae) {
5154 self_type temporary (*this - ae);
5155 return assign_temporary (temporary);
5157 template<class C> // Container assignment without temporary
5159 c_matrix &operator -= (const matrix_container<C> &m) {
5165 c_matrix &minus_assign (const matrix_expression<AE> &ae) {
5166 matrix_assign<scalar_minus_assign> (*this, ae);
5171 c_matrix& operator *= (const AT &at) {
5172 matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
5177 c_matrix& operator /= (const AT &at) {
5178 matrix_assign_scalar<scalar_divides_assign> (*this, at);
5184 void swap (c_matrix &m) {
5186 BOOST_UBLAS_CHECK (size1_ == m.size1_, bad_size ());
5187 BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ());
5188 std::swap (size1_, m.size1_);
5189 std::swap (size2_, m.size2_);
5190 for (size_type i = 0; i < size1_; ++ i)
5191 std::swap_ranges (data_ [i], data_ [i] + size2_, m.data_ [i]);
5195 friend void swap (c_matrix &m1, c_matrix &m2) {
5201 // Use pointers for iterator
5202 typedef const_pointer const_subiterator_type;
5203 typedef pointer subiterator_type;
5206 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
5207 typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
5208 typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
5209 typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
5210 typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
5212 class const_iterator1;
5214 class const_iterator2;
5217 typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
5218 typedef reverse_iterator_base1<iterator1> reverse_iterator1;
5219 typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
5220 typedef reverse_iterator_base2<iterator2> reverse_iterator2;
5224 const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
5225 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
5226 return const_iterator1 (*this, i, j);
5228 return const_iterator1 (*this, &data_ [i] [j]);
5232 iterator1 find1 (int /*rank*/, size_type i, size_type j) {
5233 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
5234 return iterator1 (*this, i, j);
5236 return iterator1 (*this, &data_ [i] [j]);
5240 const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
5241 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
5242 return const_iterator2 (*this, i, j);
5244 return const_iterator2 (*this, &data_ [i] [j]);
5248 iterator2 find2 (int /*rank*/, size_type i, size_type j) {
5249 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
5250 return iterator2 (*this, i, j);
5252 return iterator2 (*this, &data_ [i] [j]);
5257 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
5258 class const_iterator1:
5259 public container_const_reference<c_matrix>,
5260 public random_access_iterator_base<dense_random_access_iterator_tag,
5261 const_iterator1, value_type> {
5263 typedef typename c_matrix::difference_type difference_type;
5264 typedef typename c_matrix::value_type value_type;
5265 typedef typename c_matrix::const_reference reference;
5266 typedef typename c_matrix::const_pointer pointer;
5268 typedef const_iterator2 dual_iterator_type;
5269 typedef const_reverse_iterator2 dual_reverse_iterator_type;
5271 // Construction and destruction
5274 container_const_reference<self_type> (), it_ () {}
5276 const_iterator1 (const self_type &m, const const_subiterator_type &it):
5277 container_const_reference<self_type> (m), it_ (it) {}
5279 const_iterator1 (const iterator1 &it):
5280 container_const_reference<self_type> (it ()), it_ (it.it_) {}
5284 const_iterator1 &operator ++ () {
5289 const_iterator1 &operator -- () {
5294 const_iterator1 &operator += (difference_type n) {
5299 const_iterator1 &operator -= (difference_type n) {
5304 difference_type operator - (const const_iterator1 &it) const {
5305 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
5306 return (it_ - it.it_) / M;
5311 const_reference operator * () const {
5312 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
5313 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
5317 const_reference operator [] (difference_type n) const {
5318 return *(*this + n);
5321 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5323 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5324 typename self_type::
5326 const_iterator2 begin () const {
5327 const self_type &m = (*this) ();
5328 return m.find2 (1, index1 (), 0);
5331 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5332 typename self_type::
5334 const_iterator2 cbegin () const {
5338 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5339 typename self_type::
5341 const_iterator2 end () const {
5342 const self_type &m = (*this) ();
5343 return m.find2 (1, index1 (), m.size2 ());
5346 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5347 typename self_type::
5349 const_iterator2 cend () const {
5353 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5354 typename self_type::
5356 const_reverse_iterator2 rbegin () const {
5357 return const_reverse_iterator2 (end ());
5360 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5361 typename self_type::
5363 const_reverse_iterator2 crbegin () const {
5367 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5368 typename self_type::
5370 const_reverse_iterator2 rend () const {
5371 return const_reverse_iterator2 (begin ());
5374 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5375 typename self_type::
5377 const_reverse_iterator2 crend () const {
5384 size_type index1 () const {
5385 const self_type &m = (*this) ();
5386 return (it_ - m.begin1 ().it_) / M;
5389 size_type index2 () const {
5390 const self_type &m = (*this) ();
5391 return (it_ - m.begin1 ().it_) % M;
5396 const_iterator1 &operator = (const const_iterator1 &it) {
5397 container_const_reference<self_type>::assign (&it ());
5404 bool operator == (const const_iterator1 &it) const {
5405 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
5406 return it_ == it.it_;
5409 bool operator < (const const_iterator1 &it) const {
5410 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
5411 return it_ < it.it_;
5415 const_subiterator_type it_;
5417 friend class iterator1;
5422 const_iterator1 begin1 () const {
5423 return find1 (0, 0, 0);
5426 const_iterator1 cbegin1 () const {
5430 const_iterator1 end1 () const {
5431 return find1 (0, size1_, 0);
5434 const_iterator1 cend1 () const {
5438 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
5440 public container_reference<c_matrix>,
5441 public random_access_iterator_base<dense_random_access_iterator_tag,
5442 iterator1, value_type> {
5445 typedef typename c_matrix::difference_type difference_type;
5446 typedef typename c_matrix::value_type value_type;
5447 typedef typename c_matrix::reference reference;
5448 typedef typename c_matrix::pointer pointer;
5450 typedef iterator2 dual_iterator_type;
5451 typedef reverse_iterator2 dual_reverse_iterator_type;
5453 // Construction and destruction
5456 container_reference<self_type> (), it_ () {}
5458 iterator1 (self_type &m, const subiterator_type &it):
5459 container_reference<self_type> (m), it_ (it) {}
5463 iterator1 &operator ++ () {
5468 iterator1 &operator -- () {
5473 iterator1 &operator += (difference_type n) {
5478 iterator1 &operator -= (difference_type n) {
5483 difference_type operator - (const iterator1 &it) const {
5484 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
5485 return (it_ - it.it_) / M;
5490 reference operator * () const {
5491 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
5492 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
5496 reference operator [] (difference_type n) const {
5497 return *(*this + n);
5500 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5502 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5503 typename self_type::
5505 iterator2 begin () const {
5506 self_type &m = (*this) ();
5507 return m.find2 (1, index1 (), 0);
5510 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5511 typename self_type::
5513 iterator2 end () const {
5514 self_type &m = (*this) ();
5515 return m.find2 (1, index1 (), m.size2 ());
5518 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5519 typename self_type::
5521 reverse_iterator2 rbegin () const {
5522 return reverse_iterator2 (end ());
5525 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5526 typename self_type::
5528 reverse_iterator2 rend () const {
5529 return reverse_iterator2 (begin ());
5535 size_type index1 () const {
5536 const self_type &m = (*this) ();
5537 return (it_ - m.begin1 ().it_) / M;
5540 size_type index2 () const {
5541 const self_type &m = (*this) ();
5542 return (it_ - m.begin1 ().it_) % M;
5547 iterator1 &operator = (const iterator1 &it) {
5548 container_reference<self_type>::assign (&it ());
5555 bool operator == (const iterator1 &it) const {
5556 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
5557 return it_ == it.it_;
5560 bool operator < (const iterator1 &it) const {
5561 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
5562 return it_ < it.it_;
5566 subiterator_type it_;
5568 friend class const_iterator1;
5573 iterator1 begin1 () {
5574 return find1 (0, 0, 0);
5578 return find1 (0, size1_, 0);
5581 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
5582 class const_iterator2:
5583 public container_const_reference<c_matrix>,
5584 public random_access_iterator_base<dense_random_access_iterator_tag,
5585 const_iterator2, value_type> {
5587 typedef typename c_matrix::difference_type difference_type;
5588 typedef typename c_matrix::value_type value_type;
5589 typedef typename c_matrix::const_reference reference;
5590 typedef typename c_matrix::const_reference pointer;
5592 typedef const_iterator1 dual_iterator_type;
5593 typedef const_reverse_iterator1 dual_reverse_iterator_type;
5595 // Construction and destruction
5598 container_const_reference<self_type> (), it_ () {}
5600 const_iterator2 (const self_type &m, const const_subiterator_type &it):
5601 container_const_reference<self_type> (m), it_ (it) {}
5603 const_iterator2 (const iterator2 &it):
5604 container_const_reference<self_type> (it ()), it_ (it.it_) {}
5608 const_iterator2 &operator ++ () {
5613 const_iterator2 &operator -- () {
5618 const_iterator2 &operator += (difference_type n) {
5623 const_iterator2 &operator -= (difference_type n) {
5628 difference_type operator - (const const_iterator2 &it) const {
5629 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
5630 return it_ - it.it_;
5635 const_reference operator * () const {
5636 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
5637 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
5641 const_reference operator [] (difference_type n) const {
5642 return *(*this + n);
5645 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5647 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5648 typename self_type::
5650 const_iterator1 begin () const {
5651 const self_type &m = (*this) ();
5652 return m.find1 (1, 0, index2 ());
5655 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5656 typename self_type::
5658 const_iterator1 cbegin () const {
5662 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5663 typename self_type::
5665 const_iterator1 end () const {
5666 const self_type &m = (*this) ();
5667 return m.find1 (1, m.size1 (), index2 ());
5670 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5671 typename self_type::
5673 const_iterator1 cend () const {
5677 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5678 typename self_type::
5680 const_reverse_iterator1 rbegin () const {
5681 return const_reverse_iterator1 (end ());
5684 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5685 typename self_type::
5687 const_reverse_iterator1 crbegin () const {
5691 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5692 typename self_type::
5694 const_reverse_iterator1 rend () const {
5695 return const_reverse_iterator1 (begin ());
5698 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5699 typename self_type::
5701 const_reverse_iterator1 crend () const {
5708 size_type index1 () const {
5709 const self_type &m = (*this) ();
5710 return (it_ - m.begin2 ().it_) / M;
5713 size_type index2 () const {
5714 const self_type &m = (*this) ();
5715 return (it_ - m.begin2 ().it_) % M;
5720 const_iterator2 &operator = (const const_iterator2 &it) {
5721 container_const_reference<self_type>::assign (&it ());
5728 bool operator == (const const_iterator2 &it) const {
5729 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
5730 return it_ == it.it_;
5733 bool operator < (const const_iterator2 &it) const {
5734 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
5735 return it_ < it.it_;
5739 const_subiterator_type it_;
5741 friend class iterator2;
5746 const_iterator2 begin2 () const {
5747 return find2 (0, 0, 0);
5750 const_iterator2 cbegin2 () const {
5754 const_iterator2 end2 () const {
5755 return find2 (0, 0, size2_);
5758 const_iterator2 cend2 () const {
5762 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
5764 public container_reference<c_matrix>,
5765 public random_access_iterator_base<dense_random_access_iterator_tag,
5766 iterator2, value_type> {
5768 typedef typename c_matrix::difference_type difference_type;
5769 typedef typename c_matrix::value_type value_type;
5770 typedef typename c_matrix::reference reference;
5771 typedef typename c_matrix::pointer pointer;
5773 typedef iterator1 dual_iterator_type;
5774 typedef reverse_iterator1 dual_reverse_iterator_type;
5776 // Construction and destruction
5779 container_reference<self_type> (), it_ () {}
5781 iterator2 (self_type &m, const subiterator_type &it):
5782 container_reference<self_type> (m), it_ (it) {}
5786 iterator2 &operator ++ () {
5791 iterator2 &operator -- () {
5796 iterator2 &operator += (difference_type n) {
5801 iterator2 &operator -= (difference_type n) {
5806 difference_type operator - (const iterator2 &it) const {
5807 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
5808 return it_ - it.it_;
5813 reference operator * () const {
5814 BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
5815 BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
5819 reference operator [] (difference_type n) const {
5820 return *(*this + n);
5823 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
5825 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5826 typename self_type::
5828 iterator1 begin () const {
5829 self_type &m = (*this) ();
5830 return m.find1 (1, 0, index2 ());
5833 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5834 typename self_type::
5836 iterator1 end () const {
5837 self_type &m = (*this) ();
5838 return m.find1 (1, m.size1 (), index2 ());
5841 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5842 typename self_type::
5844 reverse_iterator1 rbegin () const {
5845 return reverse_iterator1 (end ());
5848 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
5849 typename self_type::
5851 reverse_iterator1 rend () const {
5852 return reverse_iterator1 (begin ());
5858 size_type index1 () const {
5859 const self_type &m = (*this) ();
5860 return (it_ - m.begin2 ().it_) / M;
5863 size_type index2 () const {
5864 const self_type &m = (*this) ();
5865 return (it_ - m.begin2 ().it_) % M;
5870 iterator2 &operator = (const iterator2 &it) {
5871 container_reference<self_type>::assign (&it ());
5878 bool operator == (const iterator2 &it) const {
5879 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
5880 return it_ == it.it_;
5883 bool operator < (const iterator2 &it) const {
5884 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
5885 return it_ < it.it_;
5889 subiterator_type it_;
5891 friend class const_iterator2;
5896 iterator2 begin2 () {
5897 return find2 (0, 0, 0);
5901 return find2 (0, 0, size2_);
5904 // Reverse iterators
5907 const_reverse_iterator1 rbegin1 () const {
5908 return const_reverse_iterator1 (end1 ());
5911 const_reverse_iterator1 crbegin1 () const {
5915 const_reverse_iterator1 rend1 () const {
5916 return const_reverse_iterator1 (begin1 ());
5919 const_reverse_iterator1 crend1 () const {
5924 reverse_iterator1 rbegin1 () {
5925 return reverse_iterator1 (end1 ());
5928 reverse_iterator1 rend1 () {
5929 return reverse_iterator1 (begin1 ());
5933 const_reverse_iterator2 rbegin2 () const {
5934 return const_reverse_iterator2 (end2 ());
5937 const_reverse_iterator2 crbegin2 () const {
5941 const_reverse_iterator2 rend2 () const {
5942 return const_reverse_iterator2 (begin2 ());
5945 const_reverse_iterator2 crend2 () const {
5950 reverse_iterator2 rbegin2 () {
5951 return reverse_iterator2 (end2 ());
5954 reverse_iterator2 rend2 () {
5955 return reverse_iterator2 (begin2 ());
5959 template<class Archive>
5960 void serialize(Archive & ar, const unsigned int /* file_version */){
5962 // we need to copy to a collection_size_type to get a portable
5963 // and efficient serialization
5964 serialization::collection_size_type s1 (size1_);
5965 serialization::collection_size_type s2 (size2_);
5967 // serialize the sizes
5968 ar & serialization::make_nvp("size1",s1)
5969 & serialization::make_nvp("size2",s2);
5971 // copy the values back if loading
5972 if (Archive::is_loading::value) {
5976 // could probably use make_array( &(data[0][0]), N*M )
5977 ar & serialization::make_array(data_, N);
5983 value_type data_ [N] [M];