Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/numeric/ublas/matrix.hpp @ 30

Last change on this file since 30 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 139.6 KB
Line 
1//
2//  Copyright (c) 2000-2002
3//  Joerg Walter, Mathias Koch
4//
5//  Permission to use, copy, modify, distribute and sell this software
6//  and its documentation for any purpose is hereby granted without fee,
7//  provided that the above copyright notice appear in all copies and
8//  that both that copyright notice and this permission notice appear
9//  in supporting documentation.  The authors make no representations
10//  about the suitability of this software for any purpose.
11//  It is provided "as is" without express or implied warranty.
12//
13//  The authors gratefully acknowledge the support of
14//  GeNeSys mbH & Co. KG in producing this work.
15//
16
17#ifndef _BOOST_UBLAS_MATRIX_
18#define _BOOST_UBLAS_MATRIX_
19
20#include <boost/numeric/ublas/vector.hpp>
21#include <boost/numeric/ublas/matrix_expression.hpp>
22#include <boost/numeric/ublas/detail/matrix_assign.hpp>
23
24// Iterators based on ideas of Jeremy Siek
25
26namespace boost { namespace numeric { namespace ublas {
27
28    namespace detail {
29        using namespace boost::numeric::ublas;
30
31        // Matrix resizing algorithm
32        template <class L, class M>
33        BOOST_UBLAS_INLINE
34        void matrix_resize_preserve (M& m, M& temporary) {
35            typedef L layout_type;
36            typedef typename M::size_type size_type;
37            const size_type msize1 (m.size1 ());        // original size
38            const size_type msize2 (m.size2 ());
39            const size_type size1 (temporary.size1 ());    // new size is specified by temporary
40            const size_type size2 (temporary.size2 ());
41            // Common elements to preserve
42            const size_type size1_min = (std::min) (size1, msize1);
43            const size_type size2_min = (std::min) (size2, msize2);
44            // Order loop for i-major and j-minor sizes
45            const size_type i_size = layout_type::size1 (size1_min, size2_min);
46            const size_type j_size = layout_type::size2 (size1_min, size2_min);
47            for (size_type i = 0; i != i_size; ++i) {    // indexing copy over major
48                for (size_type j = 0; j != j_size; ++j) {
49                    const size_type element1 = layout_type::element1(i,i_size, j,j_size);
50                    const size_type element2 = layout_type::element2(i,i_size, j,j_size);
51                    temporary.data () [layout_type::element (element1, size1, element2, size2)] =
52                            m.data() [layout_type::element (element1, msize1, element2, msize2)];
53                }
54            }
55            m.assign_temporary (temporary);
56        }
57    }
58
59
60    // Array based matrix class
61    template<class T, class L, class A>
62    class matrix:
63        public matrix_container<matrix<T, L, A> > {
64
65        typedef T *pointer;
66        typedef L layout_type;
67        typedef matrix<T, L, A> self_type;
68    public:
69#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
70        using matrix_container<self_type>::operator ();
71#endif
72        typedef typename A::size_type size_type;
73        typedef typename A::difference_type difference_type;
74        typedef T value_type;
75        typedef const T &const_reference;
76        typedef T &reference;
77        typedef A array_type;
78        typedef const matrix_reference<const self_type> const_closure_type;
79        typedef matrix_reference<self_type> closure_type;
80        typedef vector<T, A> vector_temporary_type;
81        typedef self_type matrix_temporary_type;
82        typedef dense_tag storage_category;
83        // This could be better for performance,
84        // typedef typename unknown_orientation_tag orientation_category;
85        // but others depend on the orientation information...
86        typedef typename L::orientation_category orientation_category;
87
88        // Construction and destruction
89        BOOST_UBLAS_INLINE
90        matrix ():
91            matrix_container<self_type> (),
92            size1_ (0), size2_ (0), data_ () {}
93        BOOST_UBLAS_INLINE
94        matrix (size_type size1, size_type size2):
95            matrix_container<self_type> (),
96            size1_ (size1), size2_ (size2), data_ (layout_type::storage_size (size1, size2)) {
97        }
98        BOOST_UBLAS_INLINE
99        matrix (size_type size1, size_type size2, const array_type &data):
100            matrix_container<self_type> (),
101            size1_ (size1), size2_ (size2), data_ (data) {}
102        BOOST_UBLAS_INLINE
103        matrix (const matrix &m):
104            matrix_container<self_type> (),
105            size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
106        template<class AE>
107        BOOST_UBLAS_INLINE
108        matrix (const matrix_expression<AE> &ae):
109            matrix_container<self_type> (),
110            size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::storage_size (size1_, size2_)) {
111            matrix_assign<scalar_assign> (*this, ae);
112        }
113
114        // Accessors
115        BOOST_UBLAS_INLINE
116        size_type size1 () const {
117            return size1_;
118        }
119        BOOST_UBLAS_INLINE
120        size_type size2 () const {
121            return size2_;
122        }
123
124        // Storage accessors
125        BOOST_UBLAS_INLINE
126        const array_type &data () const {
127            return data_;
128        }
129        BOOST_UBLAS_INLINE
130        array_type &data () {
131            return data_;
132        }
133
134        // Resizing
135        BOOST_UBLAS_INLINE
136        void resize (size_type size1, size_type size2, bool preserve = true) {
137            if (preserve) {
138                self_type temporary (size1, size2);
139                detail::matrix_resize_preserve<layout_type> (*this, temporary);
140            }
141            else {
142                data ().resize (layout_type::storage_size (size1, size2));
143                size1_ = size1;
144                size2_ = size2;
145            }
146        }
147
148        // Element access
149        BOOST_UBLAS_INLINE
150        const_reference operator () (size_type i, size_type j) const {
151            return data () [layout_type::element (i, size1_, j, size2_)];
152        }
153        BOOST_UBLAS_INLINE
154        reference at_element (size_type i, size_type j) {
155            return data () [layout_type::element (i, size1_, j, size2_)];
156        }
157        BOOST_UBLAS_INLINE
158        reference operator () (size_type i, size_type j) {
159            return at_element (i, j);
160        }
161
162        // Element assignment
163        BOOST_UBLAS_INLINE
164        reference insert_element (size_type i, size_type j, const_reference t) {
165            return (at_element (i, j) = t);
166        }
167        void erase_element (size_type i, size_type j) {
168            at_element (i, j) = value_type/*zero*/();
169        }
170
171        // Zeroing
172        BOOST_UBLAS_INLINE
173        void clear () {
174            std::fill (data ().begin (), data ().end (), value_type/*zero*/());
175        }
176
177        // Assignment
178        BOOST_UBLAS_INLINE
179        matrix &operator = (const matrix &m) {
180            size1_ = m.size1_;
181            size2_ = m.size2_;
182            data () = m.data ();
183            return *this;
184        }
185        template<class C>          // Container assignment without temporary
186        BOOST_UBLAS_INLINE
187        matrix &operator = (const matrix_container<C> &m) {
188            resize (m ().size1 (), m ().size2 (), false);
189            assign (m);
190            return *this;
191        }
192        BOOST_UBLAS_INLINE
193        matrix &assign_temporary (matrix &m) {
194            swap (m);
195            return *this;
196        }
197        template<class AE>
198        BOOST_UBLAS_INLINE
199        matrix &operator = (const matrix_expression<AE> &ae) {
200            self_type temporary (ae);
201            return assign_temporary (temporary);
202        }
203        template<class AE>
204        BOOST_UBLAS_INLINE
205        matrix &assign (const matrix_expression<AE> &ae) {
206            matrix_assign<scalar_assign> (*this, ae);
207            return *this;
208        }
209        template<class AE>
210        BOOST_UBLAS_INLINE
211        matrix& operator += (const matrix_expression<AE> &ae) {
212            self_type temporary (*this + ae);
213            return assign_temporary (temporary);
214        }
215        template<class C>          // Container assignment without temporary
216        BOOST_UBLAS_INLINE
217        matrix &operator += (const matrix_container<C> &m) {
218            plus_assign (m);
219            return *this;
220        }
221        template<class AE>
222        BOOST_UBLAS_INLINE
223        matrix &plus_assign (const matrix_expression<AE> &ae) {
224            matrix_assign<scalar_plus_assign> (*this, ae);
225            return *this;
226        }
227        template<class AE>
228        BOOST_UBLAS_INLINE
229        matrix& operator -= (const matrix_expression<AE> &ae) {
230            self_type temporary (*this - ae);
231            return assign_temporary (temporary);
232        }
233        template<class C>          // Container assignment without temporary
234        BOOST_UBLAS_INLINE
235        matrix &operator -= (const matrix_container<C> &m) {
236            minus_assign (m);
237            return *this;
238        }
239        template<class AE>
240        BOOST_UBLAS_INLINE
241        matrix &minus_assign (const matrix_expression<AE> &ae) {
242            matrix_assign<scalar_minus_assign> (*this, ae);
243            return *this;
244        }
245        template<class AT>
246        BOOST_UBLAS_INLINE
247        matrix& operator *= (const AT &at) {
248            matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
249            return *this;
250        }
251        template<class AT>
252        BOOST_UBLAS_INLINE
253        matrix& operator /= (const AT &at) {
254            matrix_assign_scalar<scalar_divides_assign> (*this, at);
255            return *this;
256        }
257
258        // Swapping
259        BOOST_UBLAS_INLINE
260        void swap (matrix &m) {
261            if (this != &m) {
262                std::swap (size1_, m.size1_);
263                std::swap (size2_, m.size2_);
264                data ().swap (m.data ());
265            }
266        }
267        BOOST_UBLAS_INLINE
268        friend void swap (matrix &m1, matrix &m2) {
269            m1.swap (m2);
270        }
271
272        // Iterator types
273    private:
274        // Use the storage array iterator
275        typedef typename A::const_iterator const_subiterator_type;
276        typedef typename A::iterator subiterator_type;
277
278    public:
279#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
280        typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
281        typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
282        typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
283        typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
284#else
285        class const_iterator1;
286        class iterator1;
287        class const_iterator2;
288        class iterator2;
289#endif
290        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
291        typedef reverse_iterator_base1<iterator1> reverse_iterator1;
292        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
293        typedef reverse_iterator_base2<iterator2> reverse_iterator2;
294
295        // Element lookup
296        BOOST_UBLAS_INLINE
297        const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
298#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
299            return const_iterator1 (*this, i, j);
300#else
301            return const_iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
302#endif
303        }
304        BOOST_UBLAS_INLINE
305        iterator1 find1 (int /* rank */, size_type i, size_type j) {
306#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
307            return iterator1 (*this, i, j);
308#else
309            return iterator1 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
310#endif
311        }
312        BOOST_UBLAS_INLINE
313        const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
314#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
315            return const_iterator2 (*this, i, j);
316#else
317            return const_iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
318#endif
319        }
320        BOOST_UBLAS_INLINE
321        iterator2 find2 (int /* rank */, size_type i, size_type j) {
322#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
323            return iterator2 (*this, i, j);
324#else
325            return iterator2 (*this, data ().begin () + layout_type::address (i, size1_, j, size2_));
326#endif
327        }
328
329
330#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
331        class const_iterator1:
332            public container_const_reference<matrix>,
333            public random_access_iterator_base<dense_random_access_iterator_tag,
334                                               const_iterator1, value_type> {
335        public:
336            typedef typename matrix::value_type value_type;
337            typedef typename matrix::difference_type difference_type;
338            typedef typename matrix::const_reference reference;
339            typedef const typename matrix::pointer pointer;
340
341            typedef const_iterator2 dual_iterator_type;
342            typedef const_reverse_iterator2 dual_reverse_iterator_type;
343
344            // Construction and destruction
345            BOOST_UBLAS_INLINE
346            const_iterator1 ():
347                container_const_reference<self_type> (), it_ () {}
348            BOOST_UBLAS_INLINE
349            const_iterator1 (const self_type &m, const const_subiterator_type &it):
350                container_const_reference<self_type> (m), it_ (it) {}
351            BOOST_UBLAS_INLINE
352            const_iterator1 (const iterator1 &it):
353                container_const_reference<self_type> (it ()), it_ (it.it_) {}
354
355            // Arithmetic
356            BOOST_UBLAS_INLINE
357            const_iterator1 &operator ++ () {
358                layout_type::increment1 (it_, (*this) ().size1 (), (*this) ().size2 ());
359                return *this;
360            }
361            BOOST_UBLAS_INLINE
362            const_iterator1 &operator -- () {
363                layout_type::decrement1 (it_, (*this) ().size1 (), (*this) ().size2 ());
364                return *this;
365            }
366            BOOST_UBLAS_INLINE
367            const_iterator1 &operator += (difference_type n) {
368                it_ += n * layout_type::one1 ((*this) ().size1 (), (*this) ().size2 ());
369                return *this;
370            }
371            BOOST_UBLAS_INLINE
372            const_iterator1 &operator -= (difference_type n) {
373                it_ -= n * layout_type::one1 ((*this) ().size1 (), (*this) ().size2 ());
374                return *this;
375            }
376            BOOST_UBLAS_INLINE
377            difference_type operator - (const const_iterator1 &it) const {
378                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
379                return layout_type::distance1 (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
380            }
381
382            // Dereference
383            BOOST_UBLAS_INLINE
384            const_reference operator * () const {
385                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
386                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
387                return *it_;
388            }
389            BOOST_UBLAS_INLINE
390            const_reference operator [] (difference_type n) const {
391                return *(*this + n);
392            }
393
394#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
395            BOOST_UBLAS_INLINE
396#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
397            typename self_type::
398#endif
399            const_iterator2 begin () const {
400                const self_type &m = (*this) ();
401                return m.find2 (1, index1 (), 0);
402            }
403            BOOST_UBLAS_INLINE
404#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
405            typename self_type::
406#endif
407            const_iterator2 end () const {
408                const self_type &m = (*this) ();
409                return m.find2 (1, index1 (), m.size2 ());
410            }
411            BOOST_UBLAS_INLINE
412#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
413            typename self_type::
414#endif
415            const_reverse_iterator2 rbegin () const {
416                return const_reverse_iterator2 (end ());
417            }
418            BOOST_UBLAS_INLINE
419#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
420            typename self_type::
421#endif
422            const_reverse_iterator2 rend () const {
423                return const_reverse_iterator2 (begin ());
424            }
425#endif
426
427            // Indices
428            BOOST_UBLAS_INLINE
429            size_type index1 () const {
430                const self_type &m = (*this) ();
431                return layout_type::index1 (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
432            }
433            BOOST_UBLAS_INLINE
434            size_type index2 () const {
435                const self_type &m = (*this) ();
436                return layout_type::index2 (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
437            }
438
439            // Assignment
440            BOOST_UBLAS_INLINE
441            const_iterator1 &operator = (const const_iterator1 &it) {
442                container_const_reference<self_type>::assign (&it ());
443                it_ = it.it_;
444                return *this;
445            }
446
447            // Comparison
448            BOOST_UBLAS_INLINE
449            bool operator == (const const_iterator1 &it) const {
450                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
451                return it_ == it.it_;
452            }
453            BOOST_UBLAS_INLINE
454            bool operator < (const const_iterator1 &it) const {
455                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
456                return it_ < it.it_;
457            }
458
459        private:
460            const_subiterator_type it_;
461
462            friend class iterator1;
463        };
464#endif
465
466        BOOST_UBLAS_INLINE
467        const_iterator1 begin1 () const {
468            return find1 (0, 0, 0);
469        }
470        BOOST_UBLAS_INLINE
471        const_iterator1 end1 () const {
472            return find1 (0, size1_, 0);
473        }
474
475#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
476        class iterator1:
477            public container_reference<matrix>,
478            public random_access_iterator_base<dense_random_access_iterator_tag,
479                                               iterator1, value_type> {
480        public:
481            typedef typename matrix::value_type value_type;
482            typedef typename matrix::difference_type difference_type;
483            typedef typename matrix::reference reference;
484            typedef typename matrix::pointer pointer;
485
486            typedef iterator2 dual_iterator_type;
487            typedef reverse_iterator2 dual_reverse_iterator_type;
488
489            // Construction and destruction
490            BOOST_UBLAS_INLINE
491            iterator1 ():
492                container_reference<self_type> (), it_ () {}
493            BOOST_UBLAS_INLINE
494            iterator1 (self_type &m, const subiterator_type &it):
495                container_reference<self_type> (m), it_ (it) {}
496
497            // Arithmetic
498            BOOST_UBLAS_INLINE
499            iterator1 &operator ++ () {
500                layout_type::increment1 (it_, (*this) ().size1 (), (*this) ().size2 ());
501                return *this;
502            }
503            BOOST_UBLAS_INLINE
504            iterator1 &operator -- () {
505                layout_type::decrement1 (it_, (*this) ().size1 (), (*this) ().size2 ());
506                return *this;
507            }
508            BOOST_UBLAS_INLINE
509            iterator1 &operator += (difference_type n) {
510                it_ += n * layout_type::one1 ((*this) ().size1 (), (*this) ().size2 ());
511                return *this;
512            }
513            BOOST_UBLAS_INLINE
514            iterator1 &operator -= (difference_type n) {
515                it_ -= n * layout_type::one1 ((*this) ().size1 (), (*this) ().size2 ());
516                return *this;
517            }
518            BOOST_UBLAS_INLINE
519            difference_type operator - (const iterator1 &it) const {
520                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
521                return layout_type::distance1 (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
522            }
523
524            // Dereference
525            BOOST_UBLAS_INLINE
526            reference operator * () const {
527                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
528                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
529                return *it_;
530            }
531            BOOST_UBLAS_INLINE
532            reference operator [] (difference_type n) const {
533                return *(*this + n);
534            }
535
536#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
537            BOOST_UBLAS_INLINE
538#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
539            typename self_type::
540#endif
541            iterator2 begin () const {
542                self_type &m = (*this) ();
543                return m.find2 (1, index1 (), 0);
544            }
545            BOOST_UBLAS_INLINE
546#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
547            typename self_type::
548#endif
549            iterator2 end () const {
550                self_type &m = (*this) ();
551                return m.find2 (1, index1 (), m.size2 ());
552            }
553            BOOST_UBLAS_INLINE
554#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
555            typename self_type::
556#endif
557            reverse_iterator2 rbegin () const {
558                return reverse_iterator2 (end ());
559            }
560            BOOST_UBLAS_INLINE
561#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
562            typename self_type::
563#endif
564            reverse_iterator2 rend () const {
565                return reverse_iterator2 (begin ());
566            }
567#endif
568
569            // Indices
570            BOOST_UBLAS_INLINE
571            size_type index1 () const {
572                self_type &m = (*this) ();
573                return layout_type::index1 (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
574            }
575            BOOST_UBLAS_INLINE
576            size_type index2 () const {
577                self_type &m = (*this) ();
578                return layout_type::index2 (it_ - m.begin1 ().it_, m.size1 (), m.size2 ());
579            }
580
581            // Assignment
582            BOOST_UBLAS_INLINE
583            iterator1 &operator = (const iterator1 &it) {
584                container_reference<self_type>::assign (&it ());
585                it_ = it.it_;
586                return *this;
587            }
588
589            // Comparison
590            BOOST_UBLAS_INLINE
591            bool operator == (const iterator1 &it) const {
592                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
593                return it_ == it.it_;
594            }
595            BOOST_UBLAS_INLINE
596            bool operator < (const iterator1 &it) const {
597                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
598                return it_ < it.it_;
599            }
600
601        private:
602            subiterator_type it_;
603
604            friend class const_iterator1;
605        };
606#endif
607
608        BOOST_UBLAS_INLINE
609        iterator1 begin1 () {
610            return find1 (0, 0, 0);
611        }
612        BOOST_UBLAS_INLINE
613        iterator1 end1 () {
614            return find1 (0, size1_, 0);
615        }
616
617#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
618        class const_iterator2:
619            public container_const_reference<matrix>,
620            public random_access_iterator_base<dense_random_access_iterator_tag,
621                                               const_iterator2, value_type> {
622        public:
623            typedef typename matrix::value_type value_type;
624            typedef typename matrix::difference_type difference_type;
625            typedef typename matrix::const_reference reference;
626            typedef const typename matrix::pointer pointer;
627
628            typedef const_iterator1 dual_iterator_type;
629            typedef const_reverse_iterator1 dual_reverse_iterator_type;
630
631            // Construction and destruction
632            BOOST_UBLAS_INLINE
633            const_iterator2 ():
634                container_const_reference<self_type> (), it_ () {}
635            BOOST_UBLAS_INLINE
636            const_iterator2 (const self_type &m, const const_subiterator_type &it):
637                container_const_reference<self_type> (m), it_ (it) {}
638            BOOST_UBLAS_INLINE
639            const_iterator2 (const iterator2 &it):
640                container_const_reference<self_type> (it ()), it_ (it.it_) {}
641
642            // Arithmetic
643            BOOST_UBLAS_INLINE
644            const_iterator2 &operator ++ () {
645                layout_type::increment2 (it_, (*this) ().size1 (), (*this) ().size2 ());
646                return *this;
647            }
648            BOOST_UBLAS_INLINE
649            const_iterator2 &operator -- () {
650                layout_type::decrement2 (it_, (*this) ().size1 (), (*this) ().size2 ());
651                return *this;
652            }
653            BOOST_UBLAS_INLINE
654            const_iterator2 &operator += (difference_type n) {
655                it_ += n * layout_type::one2 ((*this) ().size1 (), (*this) ().size2 ());
656                return *this;
657            }
658            BOOST_UBLAS_INLINE
659            const_iterator2 &operator -= (difference_type n) {
660                it_ -= n * layout_type::one2 ((*this) ().size1 (), (*this) ().size2 ());
661                return *this;
662            }
663            BOOST_UBLAS_INLINE
664            difference_type operator - (const const_iterator2 &it) const {
665                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
666                return layout_type::distance2 (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
667            }
668
669            // Dereference
670            BOOST_UBLAS_INLINE
671            const_reference operator * () const {
672                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
673                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
674                return *it_;
675            }
676            BOOST_UBLAS_INLINE
677            const_reference operator [] (difference_type n) const {
678                return *(*this + n);
679            }
680
681#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
682            BOOST_UBLAS_INLINE
683#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
684            typename self_type::
685#endif
686            const_iterator1 begin () const {
687                const self_type &m = (*this) ();
688                return m.find1 (1, 0, index2 ());
689            }
690            BOOST_UBLAS_INLINE
691#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
692            typename self_type::
693#endif
694            const_iterator1 end () const {
695                const self_type &m = (*this) ();
696                return m.find1 (1, m.size1 (), index2 ());
697            }
698            BOOST_UBLAS_INLINE
699#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
700            typename self_type::
701#endif
702            const_reverse_iterator1 rbegin () const {
703                return const_reverse_iterator1 (end ());
704            }
705            BOOST_UBLAS_INLINE
706#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
707            typename self_type::
708#endif
709            const_reverse_iterator1 rend () const {
710                return const_reverse_iterator1 (begin ());
711            }
712#endif
713
714            // Indices
715            BOOST_UBLAS_INLINE
716            size_type index1 () const {
717                const self_type &m = (*this) ();
718                return layout_type::index1 (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
719            }
720            BOOST_UBLAS_INLINE
721            size_type index2 () const {
722                const self_type &m = (*this) ();
723                return layout_type::index2 (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
724            }
725
726            // Assignment
727            BOOST_UBLAS_INLINE
728            const_iterator2 &operator = (const const_iterator2 &it) {
729                container_const_reference<self_type>::assign (&it ());
730                it_ = it.it_;
731                return *this;
732            }
733
734            // Comparison
735            BOOST_UBLAS_INLINE
736            bool operator == (const const_iterator2 &it) const {
737                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
738                return it_ == it.it_;
739            }
740            BOOST_UBLAS_INLINE
741            bool operator < (const const_iterator2 &it) const {
742                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
743                return it_ < it.it_;
744            }
745
746        private:
747            const_subiterator_type it_;
748
749            friend class iterator2;
750        };
751#endif
752
753        BOOST_UBLAS_INLINE
754        const_iterator2 begin2 () const {
755            return find2 (0, 0, 0);
756        }
757        BOOST_UBLAS_INLINE
758        const_iterator2 end2 () const {
759            return find2 (0, 0, size2_);
760        }
761
762#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
763        class iterator2:
764            public container_reference<matrix>,
765            public random_access_iterator_base<dense_random_access_iterator_tag,
766                                               iterator2, value_type> {
767        public:
768            typedef typename matrix::value_type value_type;
769            typedef typename matrix::difference_type difference_type;
770            typedef typename matrix::reference reference;
771            typedef typename matrix::pointer pointer;
772
773            typedef iterator1 dual_iterator_type;
774            typedef reverse_iterator1 dual_reverse_iterator_type;
775
776            // Construction and destruction
777            BOOST_UBLAS_INLINE
778            iterator2 ():
779                container_reference<self_type> (), it_ () {}
780            BOOST_UBLAS_INLINE
781            iterator2 (self_type &m, const subiterator_type &it):
782                container_reference<self_type> (m), it_ (it) {}
783
784            // Arithmetic
785            BOOST_UBLAS_INLINE
786            iterator2 &operator ++ () {
787                layout_type::increment2 (it_, (*this) ().size1 (), (*this) ().size2 ());
788                return *this;
789            }
790            BOOST_UBLAS_INLINE
791            iterator2 &operator -- () {
792                layout_type::decrement2 (it_, (*this) ().size1 (), (*this) ().size2 ());
793                return *this;
794            }
795            BOOST_UBLAS_INLINE
796            iterator2 &operator += (difference_type n) {
797                it_ += n * layout_type::one2 ((*this) ().size1 (), (*this) ().size2 ());
798                return *this;
799            }
800            BOOST_UBLAS_INLINE
801            iterator2 &operator -= (difference_type n) {
802                it_ -= n * layout_type::one2 ((*this) ().size1 (), (*this) ().size2 ());
803                return *this;
804            }
805            BOOST_UBLAS_INLINE
806            difference_type operator - (const iterator2 &it) const {
807                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
808                return layout_type::distance2 (it_ - it.it_, (*this) ().size1 (), (*this) ().size2 ());
809            }
810
811            // Dereference
812            BOOST_UBLAS_INLINE
813            reference operator * () const {
814                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
815                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
816                return *it_;
817            }
818            BOOST_UBLAS_INLINE
819            reference operator [] (difference_type n) const {
820                return *(*this + n);
821            }
822
823#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
824            BOOST_UBLAS_INLINE
825#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
826            typename self_type::
827#endif
828            iterator1 begin () const {
829                self_type &m = (*this) ();
830                return m.find1 (1, 0, index2 ());
831            }
832            BOOST_UBLAS_INLINE
833#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
834            typename self_type::
835#endif
836            iterator1 end () const {
837                self_type &m = (*this) ();
838                return m.find1 (1, m.size1 (), index2 ());
839            }
840            BOOST_UBLAS_INLINE
841#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
842            typename self_type::
843#endif
844            reverse_iterator1 rbegin () const {
845                return reverse_iterator1 (end ());
846            }
847            BOOST_UBLAS_INLINE
848#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
849            typename self_type::
850#endif
851            reverse_iterator1 rend () const {
852                return reverse_iterator1 (begin ());
853            }
854#endif
855
856            // Indices
857            BOOST_UBLAS_INLINE
858            size_type index1 () const {
859                self_type &m = (*this) ();
860                return layout_type::index1 (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
861            }
862            BOOST_UBLAS_INLINE
863            size_type index2 () const {
864                self_type &m = (*this) ();
865                return layout_type::index2 (it_ - m.begin2 ().it_, m.size1 (), m.size2 ());
866            }
867
868            // Assignment
869            BOOST_UBLAS_INLINE
870            iterator2 &operator = (const iterator2 &it) {
871                container_reference<self_type>::assign (&it ());
872                it_ = it.it_;
873                return *this;
874            }
875
876            // Comparison
877            BOOST_UBLAS_INLINE
878            bool operator == (const iterator2 &it) const {
879                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
880                return it_ == it.it_;
881            }
882            BOOST_UBLAS_INLINE
883            bool operator < (const iterator2 &it) const {
884                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
885                return it_ < it.it_;
886            }
887
888        private:
889            subiterator_type it_;
890
891            friend class const_iterator2;
892        };
893#endif
894
895        BOOST_UBLAS_INLINE
896        iterator2 begin2 () {
897            return find2 (0, 0, 0);
898        }
899        BOOST_UBLAS_INLINE
900        iterator2 end2 () {
901            return find2 (0, 0, size2_);
902        }
903
904        // Reverse iterators
905
906        BOOST_UBLAS_INLINE
907        const_reverse_iterator1 rbegin1 () const {
908            return const_reverse_iterator1 (end1 ());
909        }
910        BOOST_UBLAS_INLINE
911        const_reverse_iterator1 rend1 () const {
912            return const_reverse_iterator1 (begin1 ());
913        }
914
915        BOOST_UBLAS_INLINE
916        reverse_iterator1 rbegin1 () {
917            return reverse_iterator1 (end1 ());
918        }
919        BOOST_UBLAS_INLINE
920        reverse_iterator1 rend1 () {
921            return reverse_iterator1 (begin1 ());
922        }
923
924        BOOST_UBLAS_INLINE
925        const_reverse_iterator2 rbegin2 () const {
926            return const_reverse_iterator2 (end2 ());
927        }
928        BOOST_UBLAS_INLINE
929        const_reverse_iterator2 rend2 () const {
930            return const_reverse_iterator2 (begin2 ());
931        }
932
933        BOOST_UBLAS_INLINE
934        reverse_iterator2 rbegin2 () {
935            return reverse_iterator2 (end2 ());
936        }
937        BOOST_UBLAS_INLINE
938        reverse_iterator2 rend2 () {
939            return reverse_iterator2 (begin2 ());
940        }
941
942    private:
943        size_type size1_;
944        size_type size2_;
945        array_type data_;
946    };
947
948
949    // Bounded matrix class
950    template<class T, std::size_t M, std::size_t N, class L>
951    class bounded_matrix:
952        public matrix<T, L, bounded_array<T, M * N> > {
953
954        typedef matrix<T, L, bounded_array<T, M * N> > matrix_type;
955    public:
956        typedef typename matrix_type::size_type size_type;
957        static const size_type max_size1 = M;
958        static const size_type max_size2 = N;
959
960        // Construction and destruction
961        BOOST_UBLAS_INLINE
962        bounded_matrix ():
963            matrix_type (M, N) {}
964        BOOST_UBLAS_INLINE
965        bounded_matrix (size_type size1, size_type size2):
966            matrix_type (size1, size2) {}
967        BOOST_UBLAS_INLINE
968        bounded_matrix (const bounded_matrix &m):
969            matrix_type (m) {}
970        template<class A2>              // Allow matrix<T, L, bounded_array<M,N> > construction
971        BOOST_UBLAS_INLINE
972        bounded_matrix (const matrix<T, L, A2> &m):
973            matrix_type (m) {}
974        template<class AE>
975        BOOST_UBLAS_INLINE
976        bounded_matrix (const matrix_expression<AE> &ae):
977            matrix_type (ae) {}
978        BOOST_UBLAS_INLINE
979        ~bounded_matrix () {}
980
981        // Assignment
982        BOOST_UBLAS_INLINE
983        bounded_matrix &operator = (const bounded_matrix &m) {
984            matrix_type::operator = (m);
985            return *this;
986        }
987        template<class L2, class A2>        // Generic matrix assignment
988        BOOST_UBLAS_INLINE
989        bounded_matrix &operator = (const matrix<T, L2, A2> &m) {
990            matrix_type::operator = (m);
991            return *this;
992        }
993        template<class C>          // Container assignment without temporary
994        BOOST_UBLAS_INLINE
995        bounded_matrix &operator = (const matrix_container<C> &m) {
996            matrix_type::operator = (m);
997            return *this;
998        }
999        template<class AE>
1000        BOOST_UBLAS_INLINE
1001        bounded_matrix &operator = (const matrix_expression<AE> &ae) {
1002            matrix_type::operator = (ae);
1003            return *this;
1004        }
1005    };
1006
1007
1008    // Array based matrix class
1009    template<class T, class L, class A>
1010    class vector_of_vector:
1011        public matrix_container<vector_of_vector<T, L, A> > {
1012
1013        typedef T *pointer;
1014        typedef L layout_type;
1015        typedef vector_of_vector<T, L, A> self_type;
1016    public:
1017#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1018        using matrix_container<self_type>::operator ();
1019#endif
1020        typedef typename A::size_type size_type;
1021        typedef typename A::difference_type difference_type;
1022        typedef T value_type;
1023        typedef const T &const_reference;
1024        typedef T &reference;
1025        typedef A array_type;
1026        typedef const matrix_reference<const self_type> const_closure_type;
1027        typedef matrix_reference<self_type> closure_type;
1028        typedef vector<T, typename A::value_type> vector_temporary_type;
1029        typedef self_type matrix_temporary_type;
1030        typedef dense_tag storage_category;
1031        // This could be better for performance,
1032        // typedef typename unknown_orientation_tag orientation_category;
1033        // but others depend on the orientation information...
1034        typedef typename L::orientation_category orientation_category;
1035
1036        // Construction and destruction
1037        BOOST_UBLAS_INLINE
1038        vector_of_vector ():
1039            matrix_container<self_type> (),
1040            size1_ (0), size2_ (0), data_ (1) {}
1041        BOOST_UBLAS_INLINE
1042        vector_of_vector (size_type size1, size_type size2):
1043            matrix_container<self_type> (),
1044            size1_ (size1), size2_ (size2), data_ (1) {
1045            resize (size1, size2, true);
1046        }
1047        BOOST_UBLAS_INLINE
1048        vector_of_vector (const vector_of_vector &m):
1049            matrix_container<self_type> (),
1050            size1_ (m.size1_), size2_ (m.size2_), data_ (m.data_) {}
1051        template<class AE>
1052        BOOST_UBLAS_INLINE
1053        vector_of_vector (const matrix_expression<AE> &ae):
1054            matrix_container<self_type> (),
1055            size1_ (ae ().size1 ()), size2_ (ae ().size2 ()), data_ (layout_type::size1 (size1_, size2_) + 1) {
1056            for (size_type k = 0; k < layout_type::size1 (size1_, size2_); ++ k)
1057                data ()[k].resize (layout_type::size2 (size1_, size2_));
1058            matrix_assign<scalar_assign> (*this, ae);
1059        }
1060
1061        // Accessors
1062        BOOST_UBLAS_INLINE
1063        size_type size1 () const {
1064            return size1_;
1065        }
1066        BOOST_UBLAS_INLINE
1067        size_type size2 () const { 
1068            return size2_;
1069        }
1070
1071        // Storage accessors
1072        BOOST_UBLAS_INLINE
1073        const array_type &data () const {
1074            return data_;
1075        }
1076        BOOST_UBLAS_INLINE
1077        array_type &data () {
1078            return data_;
1079        }
1080
1081        // Resizing
1082        BOOST_UBLAS_INLINE
1083        void resize (size_type size1, size_type size2, bool preserve = true) {
1084            size1_ = size1;
1085            size2_ = size2;
1086            if (preserve)
1087                data ().resize (layout_type::size1 (size1, size2) + 1, typename array_type::value_type ());
1088            else
1089                data ().resize (layout_type::size1 (size1, size2) + 1);
1090            for (size_type k = 0; k < layout_type::size1 (size1, size2); ++ k) {
1091                if (preserve)
1092                    data () [k].resize (layout_type::size2 (size1, size2), value_type ());
1093                else
1094                    data () [k].resize (layout_type::size2 (size1, size2));
1095            }
1096        }
1097
1098        // Element access
1099        BOOST_UBLAS_INLINE
1100        const_reference operator () (size_type i, size_type j) const {
1101            return data () [layout_type::element1 (i, size1_, j, size2_)] [layout_type::element2 (i, size1_, j, size2_)]; 
1102        }
1103        BOOST_UBLAS_INLINE
1104        reference at_element (size_type i, size_type j) {
1105            return data () [layout_type::element1 (i, size1_, j, size2_)] [layout_type::element2 (i, size1_, j, size2_)]; 
1106        }
1107        BOOST_UBLAS_INLINE
1108        reference operator () (size_type i, size_type j) {
1109            return at_element (i, j); 
1110        }
1111
1112        // Element assignment
1113        BOOST_UBLAS_INLINE
1114        reference insert_element (size_type i, size_type j, const_reference t) {
1115            return (at_element (i, j) = t); 
1116        }
1117        BOOST_UBLAS_INLINE
1118        void erase_element (size_type i, size_type j) {
1119            at_element (i, j) = value_type/*zero*/(); 
1120        }
1121       
1122        // Zeroing
1123        BOOST_UBLAS_INLINE
1124        void clear () {
1125            for (size_type k = 0; k < layout_type::size1 (size1_, size2_); ++ k)
1126                std::fill (data () [k].begin (), data () [k].end (), value_type/*zero*/());
1127        }
1128
1129        // Assignment
1130        BOOST_UBLAS_INLINE
1131        vector_of_vector &operator = (const vector_of_vector &m) {
1132            size1_ = m.size1_;
1133            size2_ = m.size2_;
1134            data () = m.data ();
1135            return *this;
1136        }
1137        BOOST_UBLAS_INLINE
1138        vector_of_vector &assign_temporary (vector_of_vector &m) { 
1139            swap (m);
1140            return *this;
1141        }
1142        template<class AE>
1143        BOOST_UBLAS_INLINE
1144        vector_of_vector &operator = (const matrix_expression<AE> &ae) { 
1145            self_type temporary (ae);
1146            return assign_temporary (temporary);
1147        }
1148        template<class C>          // Container assignment without temporary
1149        BOOST_UBLAS_INLINE
1150        vector_of_vector &operator = (const matrix_container<C> &m) {
1151            resize (m ().size1 (), m ().size2 (), false);
1152            assign (m);
1153            return *this;
1154        }
1155        template<class AE>
1156        BOOST_UBLAS_INLINE
1157        vector_of_vector &assign (const matrix_expression<AE> &ae) { 
1158            matrix_assign<scalar_assign> (*this, ae); 
1159            return *this;
1160        }
1161        template<class AE>
1162        BOOST_UBLAS_INLINE
1163        vector_of_vector& operator += (const matrix_expression<AE> &ae) {
1164            self_type temporary (*this + ae);
1165            return assign_temporary (temporary);
1166        }
1167        template<class C>          // Container assignment without temporary
1168        BOOST_UBLAS_INLINE
1169        vector_of_vector &operator += (const matrix_container<C> &m) {
1170            plus_assign (m);
1171            return *this;
1172        }
1173        template<class AE>
1174        BOOST_UBLAS_INLINE
1175        vector_of_vector &plus_assign (const matrix_expression<AE> &ae) { 
1176            matrix_assign<scalar_plus_assign> (*this, ae); 
1177            return *this;
1178        }
1179        template<class AE>
1180        BOOST_UBLAS_INLINE
1181        vector_of_vector& operator -= (const matrix_expression<AE> &ae) {
1182            self_type temporary (*this - ae);
1183            return assign_temporary (temporary);
1184        }
1185        template<class C>          // Container assignment without temporary
1186        BOOST_UBLAS_INLINE
1187        vector_of_vector &operator -= (const matrix_container<C> &m) {
1188            minus_assign (m);
1189            return *this;
1190        }
1191        template<class AE>
1192        BOOST_UBLAS_INLINE
1193        vector_of_vector &minus_assign (const matrix_expression<AE> &ae) {
1194            matrix_assign<scalar_minus_assign> (*this, ae); 
1195            return *this;
1196        }
1197        template<class AT>
1198        BOOST_UBLAS_INLINE
1199        vector_of_vector& operator *= (const AT &at) {
1200            matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
1201            return *this;
1202        }
1203        template<class AT>
1204        BOOST_UBLAS_INLINE
1205        vector_of_vector& operator /= (const AT &at) {
1206            matrix_assign_scalar<scalar_divides_assign> (*this, at);
1207            return *this;
1208        }
1209
1210        // Swapping
1211        BOOST_UBLAS_INLINE
1212        void swap (vector_of_vector &m) {
1213            if (this != &m) {
1214                std::swap (size1_, m.size1_);
1215                std::swap (size2_, m.size2_);
1216                data ().swap (m.data ());
1217            }
1218        }
1219        BOOST_UBLAS_INLINE
1220        friend void swap (vector_of_vector &m1, vector_of_vector &m2) {
1221            m1.swap (m2);
1222        }
1223
1224        // Iterator types
1225    private:
1226        // Use the vector iterator
1227        typedef typename A::value_type::const_iterator const_subiterator_type;
1228        typedef typename A::value_type::iterator subiterator_type;
1229    public:
1230#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1231        typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
1232        typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
1233        typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
1234        typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
1235#else
1236        class const_iterator1;
1237        class iterator1;
1238        class const_iterator2;
1239        class iterator2;
1240#endif
1241        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
1242        typedef reverse_iterator_base1<iterator1> reverse_iterator1;
1243        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
1244        typedef reverse_iterator_base2<iterator2> reverse_iterator2;
1245
1246        // Element lookup
1247        BOOST_UBLAS_INLINE
1248        const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
1249#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1250            return const_iterator1 (*this, i, j);
1251#else
1252            return const_iterator1 (*this, i, j, data () [layout_type::address1 (i, size1_, j, size2_)].begin ()  + layout_type::address2 (i, size1_, j, size2_));
1253#endif
1254        }
1255        BOOST_UBLAS_INLINE
1256        iterator1 find1 (int /*rank*/, size_type i, size_type j) {
1257#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1258            return iterator1 (*this, i, j);
1259#else
1260            return iterator1 (*this, i, j, data () [layout_type::address1 (i, size1_, j, size2_)].begin ()  + layout_type::address2 (i, size1_, j, size2_));
1261#endif
1262        }
1263        BOOST_UBLAS_INLINE
1264        const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
1265#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1266            return const_iterator2 (*this, i, j);
1267#else
1268            return const_iterator2 (*this, i, j, data () [layout_type::address1 (i, size1_, j, size2_)].begin ()  + layout_type::address2 (i, size1_, j, size2_));
1269#endif
1270        }
1271        BOOST_UBLAS_INLINE
1272        iterator2 find2 (int /*rank*/, size_type i, size_type j) {
1273#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1274            return iterator2 (*this, i, j);
1275#else
1276            return iterator2 (*this, i, j, data () [layout_type::address1 (i, size1_, j, size2_)].begin () + layout_type::address2 (i, size1_, j, size2_));
1277#endif
1278        }
1279
1280
1281#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1282        class const_iterator1:
1283            public container_const_reference<vector_of_vector>,
1284            public random_access_iterator_base<dense_random_access_iterator_tag,
1285                                               const_iterator1, value_type> {
1286        public:
1287            typedef typename vector_of_vector::value_type value_type;
1288            typedef typename vector_of_vector::difference_type difference_type;
1289            typedef typename vector_of_vector::const_reference reference;
1290            typedef const typename vector_of_vector::pointer pointer;
1291
1292            typedef const_iterator2 dual_iterator_type;
1293            typedef const_reverse_iterator2 dual_reverse_iterator_type;
1294
1295            // Construction and destruction
1296            BOOST_UBLAS_INLINE
1297            const_iterator1 ():
1298                container_const_reference<self_type> (), i_ (), j_ (), it_ () {}
1299            BOOST_UBLAS_INLINE
1300            const_iterator1 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it):
1301                container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
1302            BOOST_UBLAS_INLINE
1303            const_iterator1 (const iterator1 &it):
1304                container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
1305
1306            // Arithmetic
1307            BOOST_UBLAS_INLINE
1308            const_iterator1 &operator ++ () {
1309                ++ i_;
1310                const self_type &m = (*this) ();
1311                if (layout_type::fast1 ())
1312                    ++ it_;
1313                else 
1314                    it_ = m.find1 (1, i_, j_).it_;
1315                return *this;
1316            }
1317            BOOST_UBLAS_INLINE
1318            const_iterator1 &operator -- () {
1319                -- i_;
1320                const self_type &m = (*this) ();
1321                if (layout_type::fast1 ())
1322                    -- it_;
1323                else
1324                    it_ = m.find1 (1, i_, j_).it_;
1325                return *this;
1326            }
1327            BOOST_UBLAS_INLINE
1328            const_iterator1 &operator += (difference_type n) {
1329                i_ += n;
1330                const self_type &m = (*this) ();
1331                it_ = m.find1 (1, i_, j_).it_;
1332                return *this;
1333            }
1334            BOOST_UBLAS_INLINE
1335            const_iterator1 &operator -= (difference_type n) {
1336                i_ -= n;
1337                const self_type &m = (*this) ();
1338                it_ = m.find1 (1, i_, j_).it_;
1339                return *this;
1340            }
1341            BOOST_UBLAS_INLINE
1342            difference_type operator - (const const_iterator1 &it) const {
1343                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1344                BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
1345                return index1 () - it.index1 ();
1346            }
1347
1348            // Dereference
1349            BOOST_UBLAS_INLINE
1350            const_reference operator * () const {
1351                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1352                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1353                return *it_;
1354            }
1355            BOOST_UBLAS_INLINE
1356            const_reference operator [] (difference_type n) const {
1357                return *(*this + n);
1358            }
1359
1360#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1361            BOOST_UBLAS_INLINE
1362#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1363            typename self_type::
1364#endif
1365            const_iterator2 begin () const {
1366                const self_type &m = (*this) ();
1367                return m.find2 (1, index1 (), 0);
1368            }
1369            BOOST_UBLAS_INLINE
1370#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1371            typename self_type::
1372#endif
1373            const_iterator2 end () const {
1374                const self_type &m = (*this) ();
1375                return m.find2 (1, index1 (), m.size2 ());
1376            }
1377            BOOST_UBLAS_INLINE
1378#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1379            typename self_type::
1380#endif
1381            const_reverse_iterator2 rbegin () const {
1382                return const_reverse_iterator2 (end ());
1383            }
1384            BOOST_UBLAS_INLINE
1385#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1386            typename self_type::
1387#endif
1388            const_reverse_iterator2 rend () const {
1389                return const_reverse_iterator2 (begin ());
1390            }
1391#endif
1392
1393            // Indices
1394            BOOST_UBLAS_INLINE
1395            size_type index1 () const {
1396                return i_;
1397            }
1398            BOOST_UBLAS_INLINE
1399            size_type index2 () const {
1400                return j_;
1401            }
1402
1403            // Assignment
1404            BOOST_UBLAS_INLINE
1405            const_iterator1 &operator = (const const_iterator1 &it) {
1406                container_const_reference<self_type>::assign (&it ());
1407                it_ = it.it_;
1408                return *this;
1409            }
1410
1411            // Comparison
1412            BOOST_UBLAS_INLINE
1413            bool operator == (const const_iterator1 &it) const {
1414                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1415                BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
1416                return it_ == it.it_;
1417            }
1418            BOOST_UBLAS_INLINE
1419            bool operator < (const const_iterator1 &it) const {
1420                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1421                BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
1422                return it_ < it.it_;
1423            }
1424
1425        private:
1426            size_type i_;
1427            size_type j_;
1428            const_subiterator_type it_;
1429
1430            friend class iterator1;
1431        };
1432#endif
1433
1434        BOOST_UBLAS_INLINE
1435        const_iterator1 begin1 () const {
1436            return find1 (0, 0, 0);
1437        }
1438        BOOST_UBLAS_INLINE
1439        const_iterator1 end1 () const {
1440            return find1 (0, size1_, 0);
1441        }
1442
1443#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1444        class iterator1:
1445            public container_reference<vector_of_vector>,
1446            public random_access_iterator_base<dense_random_access_iterator_tag,
1447                                               iterator1, value_type> {
1448        public:
1449            typedef typename vector_of_vector::value_type value_type;
1450            typedef typename vector_of_vector::difference_type difference_type;
1451            typedef typename vector_of_vector::reference reference;
1452            typedef typename vector_of_vector::pointer pointer;
1453
1454            typedef iterator2 dual_iterator_type;
1455            typedef reverse_iterator2 dual_reverse_iterator_type;
1456
1457            // Construction and destruction
1458            BOOST_UBLAS_INLINE
1459            iterator1 ():
1460                container_reference<self_type> (), i_ (), j_ (), it_ () {}
1461            BOOST_UBLAS_INLINE
1462            iterator1 (self_type &m, size_type i, size_type j, const subiterator_type &it):
1463                container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
1464
1465            // Arithmetic
1466            BOOST_UBLAS_INLINE
1467            iterator1 &operator ++ () {
1468                ++ i_;
1469                self_type &m = (*this) ();
1470                if (layout_type::fast1 ())
1471                    ++ it_;
1472                else
1473                    it_ = m.find1 (1, i_, j_).it_;
1474                return *this;
1475            }
1476            BOOST_UBLAS_INLINE
1477            iterator1 &operator -- () {
1478                -- i_;
1479                self_type &m = (*this) ();
1480                if (layout_type::fast1 ())
1481                    -- it_;
1482                else
1483                    it_ = m.find1 (1, i_, j_).it_;
1484                return *this;
1485            }
1486            BOOST_UBLAS_INLINE
1487            iterator1 &operator += (difference_type n) {
1488                i_ += n;
1489                self_type &m = (*this) ();
1490                it_ = m.find1 (1, i_, j_).it_;
1491                return *this;
1492            }
1493            BOOST_UBLAS_INLINE
1494            iterator1 &operator -= (difference_type n) {
1495                i_ -= n;
1496                self_type &m = (*this) ();
1497                it_ = m.find1 (1, i_, j_).it_;
1498                return *this;
1499            }
1500            BOOST_UBLAS_INLINE
1501            difference_type operator - (const iterator1 &it) const {
1502                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1503                BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
1504                return index1 () - it.index1 ();
1505            }
1506
1507            // Dereference
1508            BOOST_UBLAS_INLINE
1509            reference operator * () const {
1510                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1511                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1512                return *it_;
1513            }
1514            BOOST_UBLAS_INLINE
1515            reference operator [] (difference_type n) const {
1516                return *(*this + n);
1517            }
1518
1519#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1520            BOOST_UBLAS_INLINE
1521#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1522            typename self_type::
1523#endif
1524            iterator2 begin () const {
1525                self_type &m = (*this) ();
1526                return m.find2 (1, index1 (), 0);
1527            }
1528            BOOST_UBLAS_INLINE
1529#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1530            typename self_type::
1531#endif
1532            iterator2 end () const {
1533                self_type &m = (*this) ();
1534                return m.find2 (1, index1 (), m.size2 ());
1535            }
1536            BOOST_UBLAS_INLINE
1537#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1538            typename self_type::
1539#endif
1540            reverse_iterator2 rbegin () const {
1541                return reverse_iterator2 (end ());
1542            }
1543            BOOST_UBLAS_INLINE
1544#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1545            typename self_type::
1546#endif
1547            reverse_iterator2 rend () const {
1548                return reverse_iterator2 (begin ());
1549            }
1550#endif
1551
1552            // Indices
1553            BOOST_UBLAS_INLINE
1554            size_type index1 () const {
1555                return i_;
1556            }
1557            BOOST_UBLAS_INLINE
1558            size_type index2 () const {
1559                return j_;
1560            }
1561
1562            // Assignment
1563            BOOST_UBLAS_INLINE
1564            iterator1 &operator = (const iterator1 &it) {
1565                container_reference<self_type>::assign (&it ());
1566                it_ = it.it_;
1567                return *this;
1568            }
1569
1570            // Comparison
1571            BOOST_UBLAS_INLINE
1572            bool operator == (const iterator1 &it) const {
1573                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1574                BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
1575                return it_ == it.it_;
1576            }
1577            BOOST_UBLAS_INLINE
1578            bool operator < (const iterator1 &it) const {
1579                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1580                BOOST_UBLAS_CHECK (index2 () == it.index2 (), bad_index ());
1581                return it_ < it.it_;
1582            }
1583
1584        private:
1585            size_type i_;
1586            size_type j_;
1587            subiterator_type it_;
1588
1589            friend class const_iterator1;
1590        };
1591#endif
1592
1593        BOOST_UBLAS_INLINE
1594        iterator1 begin1 () {
1595            return find1 (0, 0, 0);
1596        }
1597        BOOST_UBLAS_INLINE
1598        iterator1 end1 () {
1599            return find1 (0, size1_, 0);
1600        }
1601
1602#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1603        class const_iterator2:
1604            public container_const_reference<vector_of_vector>,
1605            public random_access_iterator_base<dense_random_access_iterator_tag,
1606                                               const_iterator2, value_type> {
1607        public:
1608            typedef typename vector_of_vector::value_type value_type;
1609            typedef typename vector_of_vector::difference_type difference_type;
1610            typedef typename vector_of_vector::const_reference reference;
1611            typedef const typename vector_of_vector::pointer pointer;
1612
1613            typedef const_iterator1 dual_iterator_type;
1614            typedef const_reverse_iterator1 dual_reverse_iterator_type;
1615
1616            // Construction and destruction
1617            BOOST_UBLAS_INLINE
1618            const_iterator2 ():
1619                container_const_reference<self_type> (), i_ (), j_ (), it_ () {}
1620            BOOST_UBLAS_INLINE
1621            const_iterator2 (const self_type &m, size_type i, size_type j, const const_subiterator_type &it):
1622                container_const_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
1623            BOOST_UBLAS_INLINE
1624            const_iterator2 (const iterator2 &it):
1625                container_const_reference<self_type> (it ()), i_ (it.i_), j_ (it.j_), it_ (it.it_) {}
1626
1627            // Arithmetic
1628            BOOST_UBLAS_INLINE
1629            const_iterator2 &operator ++ () {
1630                ++ j_;
1631                const self_type &m = (*this) ();
1632                if (layout_type::fast2 ())
1633                    ++ it_;
1634                else
1635                    it_ = m.find2 (1, i_, j_).it_;
1636                return *this;
1637            }
1638            BOOST_UBLAS_INLINE
1639            const_iterator2 &operator -- () {
1640                -- j_;
1641                const self_type &m = (*this) ();
1642                if (layout_type::fast2 ())
1643                    -- it_;
1644                else
1645                    it_ = m.find2 (1, i_, j_).it_;
1646                return *this;
1647            }
1648            BOOST_UBLAS_INLINE
1649            const_iterator2 &operator += (difference_type n) {
1650                j_ += n;
1651                const self_type &m = (*this) ();
1652                it_ = m.find2 (1, i_, j_).it_;
1653                return *this;
1654            }
1655            BOOST_UBLAS_INLINE
1656            const_iterator2 &operator -= (difference_type n) {
1657                j_ -= n;
1658                const self_type &m = (*this) ();
1659                it_ = m.find2 (1, i_, j_).it_;
1660                return *this;
1661            }
1662            BOOST_UBLAS_INLINE
1663            difference_type operator - (const const_iterator2 &it) const {
1664                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1665                BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
1666                return index2 () - it.index2 ();
1667            }
1668
1669            // Dereference
1670            BOOST_UBLAS_INLINE
1671            const_reference operator * () const {
1672                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1673                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1674                return *it_;
1675            }
1676            BOOST_UBLAS_INLINE
1677            const_reference operator [] (difference_type n) const {
1678                return *(*this + n);
1679            }
1680
1681#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1682            BOOST_UBLAS_INLINE
1683#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1684            typename self_type::
1685#endif
1686            const_iterator1 begin () const {
1687                const self_type &m = (*this) ();
1688                return m.find1 (1, 0, index2 ());
1689            }
1690            BOOST_UBLAS_INLINE
1691#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1692            typename self_type::
1693#endif
1694            const_iterator1 end () const {
1695                const self_type &m = (*this) ();
1696                return m.find1 (1, m.size1 (), index2 ());
1697            }
1698            BOOST_UBLAS_INLINE
1699#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1700            typename self_type::
1701#endif
1702            const_reverse_iterator1 rbegin () const {
1703                return const_reverse_iterator1 (end ());
1704            }
1705            BOOST_UBLAS_INLINE
1706#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1707            typename self_type::
1708#endif
1709            const_reverse_iterator1 rend () const {
1710                return const_reverse_iterator1 (begin ());
1711            }
1712#endif
1713
1714            // Indices
1715            BOOST_UBLAS_INLINE
1716            size_type index1 () const {
1717                return i_;
1718            }
1719            BOOST_UBLAS_INLINE
1720            size_type index2 () const {
1721                return j_;
1722            }
1723
1724            // Assignment
1725            BOOST_UBLAS_INLINE
1726            const_iterator2 &operator = (const const_iterator2 &it) {
1727                container_const_reference<self_type>::assign (&it ());
1728                it_ = it.it_;
1729                return *this;
1730            }
1731
1732            // Comparison
1733            BOOST_UBLAS_INLINE
1734            bool operator == (const const_iterator2 &it) const {
1735                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1736                BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
1737                return it_ == it.it_;
1738            }
1739            BOOST_UBLAS_INLINE
1740            bool operator < (const const_iterator2 &it) const {
1741                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1742                BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
1743                return it_ < it.it_;
1744            }
1745
1746        private:
1747            size_type i_;
1748            size_type j_;
1749            const_subiterator_type it_;
1750
1751            friend class iterator2;
1752        };
1753#endif
1754
1755        BOOST_UBLAS_INLINE
1756        const_iterator2 begin2 () const {
1757            return find2 (0, 0, 0);
1758        }
1759        BOOST_UBLAS_INLINE
1760        const_iterator2 end2 () const {
1761            return find2 (0, 0, size2_);
1762        }
1763
1764#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1765        class iterator2:
1766            public container_reference<vector_of_vector>,
1767            public random_access_iterator_base<dense_random_access_iterator_tag,
1768                                               iterator2, value_type> {
1769        public:
1770            typedef typename vector_of_vector::value_type value_type;
1771            typedef typename vector_of_vector::difference_type difference_type;
1772            typedef typename vector_of_vector::reference reference;
1773            typedef typename vector_of_vector::pointer pointer;
1774
1775            typedef iterator1 dual_iterator_type;
1776            typedef reverse_iterator1 dual_reverse_iterator_type;
1777
1778            // Construction and destruction
1779            BOOST_UBLAS_INLINE
1780            iterator2 ():
1781                container_reference<self_type> (), i_ (), j_ (), it_ () {}
1782            BOOST_UBLAS_INLINE
1783            iterator2 (self_type &m, size_type i, size_type j, const subiterator_type &it):
1784                container_reference<self_type> (m), i_ (i), j_ (j), it_ (it) {}
1785
1786            // Arithmetic
1787            BOOST_UBLAS_INLINE
1788            iterator2 &operator ++ () {
1789                ++ j_;
1790                self_type &m = (*this) ();
1791                if (layout_type::fast2 ())
1792                    ++ it_;
1793                else
1794                    it_ = m.find2 (1, i_, j_).it_;
1795                return *this;
1796            }
1797            BOOST_UBLAS_INLINE
1798            iterator2 &operator -- () {
1799                -- j_;
1800                self_type &m = (*this) ();
1801                if (layout_type::fast2 ())
1802                    -- it_;
1803                else
1804                    it_ = m.find2 (1, i_, j_).it_;
1805                return *this;
1806            }
1807            BOOST_UBLAS_INLINE
1808            iterator2 &operator += (difference_type n) {
1809                j_ += n;
1810                self_type &m = (*this) ();
1811                it_ = m.find2 (1, i_, j_).it_;
1812                return *this;
1813            }
1814            BOOST_UBLAS_INLINE
1815            iterator2 &operator -= (difference_type n) {
1816                j_ -= n;
1817                self_type &m = (*this) ();
1818                it_ = m.find2 (1, i_, j_).it_;
1819                return *this;
1820            }
1821            BOOST_UBLAS_INLINE
1822            difference_type operator - (const iterator2 &it) const {
1823                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1824                BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
1825                return index2 () - it.index2 ();
1826            }
1827
1828            // Dereference
1829            BOOST_UBLAS_INLINE
1830            reference operator * () const {
1831                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
1832                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
1833                return *it_;
1834            }
1835            BOOST_UBLAS_INLINE
1836            reference operator [] (difference_type n) const {
1837                return *(*this + n);
1838            }
1839
1840#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
1841            BOOST_UBLAS_INLINE
1842#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1843            typename self_type::
1844#endif
1845            iterator1 begin () const {
1846                self_type &m = (*this) ();
1847                return m.find1 (1, 0, index2 ());
1848            }
1849            BOOST_UBLAS_INLINE
1850#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1851            typename self_type::
1852#endif
1853            iterator1 end () const {
1854                self_type &m = (*this) ();
1855                return m.find1 (1, m.size1 (), index2 ());
1856            }
1857            BOOST_UBLAS_INLINE
1858#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1859            typename self_type::
1860#endif
1861            reverse_iterator1 rbegin () const {
1862                return reverse_iterator1 (end ());
1863            }
1864            BOOST_UBLAS_INLINE
1865#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
1866            typename self_type::
1867#endif
1868            reverse_iterator1 rend () const {
1869                return reverse_iterator1 (begin ());
1870            }
1871#endif
1872
1873            // Indices
1874            BOOST_UBLAS_INLINE
1875            size_type index1 () const {
1876                return i_;
1877            }
1878            BOOST_UBLAS_INLINE
1879            size_type index2 () const {
1880                return j_;
1881            }
1882
1883            // Assignment
1884            BOOST_UBLAS_INLINE
1885            iterator2 &operator = (const iterator2 &it) {
1886                container_reference<self_type>::assign (&it ());
1887                it_ = it.it_;
1888                return *this;
1889            }
1890
1891            // Comparison
1892            BOOST_UBLAS_INLINE
1893            bool operator == (const iterator2 &it) const {
1894                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1895                BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
1896                return it_ == it.it_;
1897            }
1898            BOOST_UBLAS_INLINE
1899            bool operator < (const iterator2 &it) const {
1900                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1901                BOOST_UBLAS_CHECK (index1 () == it.index1 (), bad_index ());
1902                return it_ < it.it_;
1903            }
1904
1905        private:
1906            size_type i_;
1907            size_type j_;
1908            subiterator_type it_;
1909
1910            friend class const_iterator2;
1911        };
1912#endif
1913
1914        BOOST_UBLAS_INLINE
1915        iterator2 begin2 () {
1916            return find2 (0, 0, 0);
1917        }
1918        BOOST_UBLAS_INLINE
1919        iterator2 end2 () {
1920            return find2 (0, 0, size2_);
1921        }
1922
1923        // Reverse iterators
1924
1925        BOOST_UBLAS_INLINE
1926        const_reverse_iterator1 rbegin1 () const {
1927            return const_reverse_iterator1 (end1 ());
1928        }
1929        BOOST_UBLAS_INLINE
1930        const_reverse_iterator1 rend1 () const {
1931            return const_reverse_iterator1 (begin1 ());
1932        }
1933
1934        BOOST_UBLAS_INLINE
1935        reverse_iterator1 rbegin1 () {
1936            return reverse_iterator1 (end1 ());
1937        }
1938        BOOST_UBLAS_INLINE
1939        reverse_iterator1 rend1 () {
1940            return reverse_iterator1 (begin1 ());
1941        }
1942
1943        BOOST_UBLAS_INLINE
1944        const_reverse_iterator2 rbegin2 () const {
1945            return const_reverse_iterator2 (end2 ());
1946        }
1947        BOOST_UBLAS_INLINE
1948        const_reverse_iterator2 rend2 () const {
1949            return const_reverse_iterator2 (begin2 ());
1950        }
1951
1952        BOOST_UBLAS_INLINE
1953        reverse_iterator2 rbegin2 () {
1954            return reverse_iterator2 (end2 ());
1955        }
1956        BOOST_UBLAS_INLINE
1957        reverse_iterator2 rend2 () {
1958            return reverse_iterator2 (begin2 ());
1959        }
1960
1961    private:
1962        size_type size1_;
1963        size_type size2_;
1964        array_type data_;
1965    };
1966
1967
1968    // Zero matrix class
1969    template<class T>
1970    class zero_matrix:
1971        public matrix_container<zero_matrix<T> > {
1972
1973        typedef const T *const_pointer;
1974        typedef zero_matrix<T> self_type;
1975    public:
1976#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1977        using matrix_container<self_type>::operator ();
1978#endif
1979        typedef std::size_t size_type;
1980        typedef std::ptrdiff_t difference_type;
1981        typedef T value_type;
1982        typedef const T &const_reference;
1983        typedef T &reference;
1984        typedef const matrix_reference<const self_type> const_closure_type;
1985        typedef matrix_reference<self_type> closure_type;
1986        typedef sparse_tag storage_category;
1987        typedef unknown_orientation_tag orientation_category;
1988
1989        // Construction and destruction
1990        BOOST_UBLAS_INLINE
1991        zero_matrix ():
1992            matrix_container<self_type> (),
1993            size1_ (0), size2_ (0) {}
1994        BOOST_UBLAS_INLINE
1995        zero_matrix (size_type size):
1996            matrix_container<self_type> (),
1997            size1_ (size), size2_ (size) {}
1998        BOOST_UBLAS_INLINE
1999        zero_matrix (size_type size1, size_type size2):
2000            matrix_container<self_type> (),
2001            size1_ (size1), size2_ (size2) {}
2002        BOOST_UBLAS_INLINE
2003        zero_matrix (const zero_matrix &m):
2004            matrix_container<self_type> (),
2005            size1_ (m.size1_), size2_ (m.size2_) {}
2006
2007        // Accessors
2008        BOOST_UBLAS_INLINE
2009        size_type size1 () const {
2010            return size1_;
2011        }
2012        BOOST_UBLAS_INLINE
2013        size_type size2 () const {
2014            return size2_;
2015        }
2016
2017        // Resizing
2018        BOOST_UBLAS_INLINE
2019        void resize (size_type size, bool preserve = true) {
2020            size1_ = size;
2021            size2_ = size;
2022        }
2023        BOOST_UBLAS_INLINE
2024        void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
2025            size1_ = size1;
2026            size2_ = size2;
2027        }
2028
2029        // Element access
2030        BOOST_UBLAS_INLINE
2031        const_reference operator () (size_type /* i */, size_type /* j */) const {
2032            return zero_;
2033        }
2034
2035        // Assignment
2036        BOOST_UBLAS_INLINE
2037        zero_matrix &operator = (const zero_matrix &m) {
2038            size1_ = m.size1_;
2039            size2_ = m.size2_;
2040            return *this;
2041        }
2042        BOOST_UBLAS_INLINE
2043        zero_matrix &assign_temporary (zero_matrix &m) {
2044            swap (m);
2045            return *this;
2046        }
2047
2048        // Swapping
2049        BOOST_UBLAS_INLINE
2050        void swap (zero_matrix &m) {
2051            if (this != &m) {
2052                std::swap (size1_, m.size1_);
2053                std::swap (size2_, m.size2_);
2054            }
2055        }
2056        BOOST_UBLAS_INLINE
2057        friend void swap (zero_matrix &m1, zero_matrix &m2) {
2058            m1.swap (m2);
2059        }
2060
2061        // Iterator types
2062    public:
2063        class const_iterator1;
2064        class const_iterator2;
2065        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2066        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2067
2068        // Element lookup
2069        BOOST_UBLAS_INLINE
2070        const_iterator1 find1 (int /*rank*/, size_type /*i*/, size_type /*j*/) const {
2071            return const_iterator1 (*this);
2072        }
2073        BOOST_UBLAS_INLINE
2074        const_iterator2 find2 (int /*rank*/, size_type /*i*/, size_type /*j*/) const {
2075            return const_iterator2 (*this);
2076        }
2077
2078        class const_iterator1:
2079            public container_const_reference<zero_matrix>,
2080            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
2081                                               const_iterator1, value_type> {
2082        public:
2083            typedef typename zero_matrix::value_type value_type;
2084            typedef typename zero_matrix::difference_type difference_type;
2085            typedef typename zero_matrix::const_reference reference;
2086            typedef typename zero_matrix::const_pointer pointer;
2087
2088            typedef const_iterator2 dual_iterator_type;
2089            typedef const_reverse_iterator2 dual_reverse_iterator_type;
2090
2091            // Construction and destruction
2092            BOOST_UBLAS_INLINE
2093            const_iterator1 ():
2094                container_const_reference<self_type> () {}
2095            BOOST_UBLAS_INLINE
2096            const_iterator1 (const self_type &m):
2097                container_const_reference<self_type> (m) {}
2098
2099            // Arithmetic
2100            BOOST_UBLAS_INLINE
2101            const_iterator1 &operator ++ () {
2102                BOOST_UBLAS_CHECK_FALSE (bad_index ());
2103                return *this;
2104            }
2105            BOOST_UBLAS_INLINE
2106            const_iterator1 &operator -- () {
2107                BOOST_UBLAS_CHECK_FALSE (bad_index ());
2108                return *this;
2109            }
2110
2111            // Dereference
2112            BOOST_UBLAS_INLINE
2113            const_reference operator * () const {
2114                BOOST_UBLAS_CHECK_FALSE (bad_index ());
2115                return zero_;   // arbitary return value
2116            }
2117
2118#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2119            BOOST_UBLAS_INLINE
2120#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2121            typename self_type::
2122#endif
2123            const_iterator2 begin () const {
2124                return const_iterator2 ((*this) ());
2125            }
2126            BOOST_UBLAS_INLINE
2127#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2128            typename self_type::
2129#endif
2130            const_iterator2 end () const {
2131                return const_iterator2 ((*this) ());
2132            }
2133            BOOST_UBLAS_INLINE
2134#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2135            typename self_type::
2136#endif
2137            const_reverse_iterator2 rbegin () const {
2138                return const_reverse_iterator2 (end ());
2139            }
2140            BOOST_UBLAS_INLINE
2141#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2142            typename self_type::
2143#endif
2144            const_reverse_iterator2 rend () const {
2145                return const_reverse_iterator2 (begin ());
2146            }
2147#endif
2148
2149            // Indices
2150            BOOST_UBLAS_INLINE
2151            size_type index1 () const {
2152                BOOST_UBLAS_CHECK_FALSE (bad_index ());
2153                return 0;   // arbitary return value
2154            }
2155            BOOST_UBLAS_INLINE
2156            size_type index2 () const {
2157                BOOST_UBLAS_CHECK_FALSE (bad_index ());
2158                return 0;   // arbitary return value
2159            }
2160
2161            // Assignment
2162            BOOST_UBLAS_INLINE
2163            const_iterator1 &operator = (const const_iterator1 &it) {
2164                container_const_reference<self_type>::assign (&it ());
2165                return *this;
2166            }
2167
2168            // Comparison
2169            BOOST_UBLAS_INLINE
2170            bool operator == (const const_iterator1 &it) const {
2171                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2172                return true;
2173            }
2174        };
2175
2176        typedef const_iterator1 iterator1;
2177
2178        BOOST_UBLAS_INLINE
2179        const_iterator1 begin1 () const {
2180            return const_iterator1 (*this);
2181        }
2182        BOOST_UBLAS_INLINE
2183        const_iterator1 end1 () const {
2184            return const_iterator1 (*this);
2185        }
2186
2187        class const_iterator2:
2188            public container_const_reference<zero_matrix>,
2189            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
2190                                               const_iterator2, value_type> {
2191        public:
2192            typedef typename zero_matrix::value_type value_type;
2193            typedef typename zero_matrix::difference_type difference_type;
2194            typedef typename zero_matrix::const_reference reference;
2195            typedef typename zero_matrix::const_pointer pointer;
2196
2197            typedef const_iterator1 dual_iterator_type;
2198            typedef const_reverse_iterator1 dual_reverse_iterator_type;
2199
2200            // Construction and destruction
2201            BOOST_UBLAS_INLINE
2202            const_iterator2 ():
2203                container_const_reference<self_type> () {}
2204            BOOST_UBLAS_INLINE
2205            const_iterator2 (const self_type &m):
2206                container_const_reference<self_type> (m) {}
2207
2208            // Arithmetic
2209            BOOST_UBLAS_INLINE
2210            const_iterator2 &operator ++ () {
2211                BOOST_UBLAS_CHECK_FALSE (bad_index ());
2212                return *this;
2213            }
2214            BOOST_UBLAS_INLINE
2215            const_iterator2 &operator -- () {
2216                BOOST_UBLAS_CHECK_FALSE (bad_index ());
2217                return *this;
2218            }
2219
2220            // Dereference
2221            BOOST_UBLAS_INLINE
2222            const_reference operator * () const {
2223                BOOST_UBLAS_CHECK_FALSE (bad_index ());
2224                return zero_;   // arbitary return value
2225            }
2226
2227#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2228            BOOST_UBLAS_INLINE
2229#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2230            typename self_type::
2231#endif
2232            const_iterator1 begin () const {
2233                return const_iterator1 ((*this) ());
2234            }
2235            BOOST_UBLAS_INLINE
2236#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2237            typename self_type::
2238#endif
2239            const_iterator1 end () const {
2240                return const_iterator1 ((*this) ());
2241            }
2242            BOOST_UBLAS_INLINE
2243#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2244            typename self_type::
2245#endif
2246            const_reverse_iterator1 rbegin () const {
2247                return const_reverse_iterator1 (end ());
2248            }
2249            BOOST_UBLAS_INLINE
2250#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2251            typename self_type::
2252#endif
2253            const_reverse_iterator1 rend () const {
2254                return const_reverse_iterator1 (begin ());
2255            }
2256#endif
2257
2258            // Indices
2259            BOOST_UBLAS_INLINE
2260            size_type index1 () const {
2261                BOOST_UBLAS_CHECK_FALSE (bad_index ());
2262                return 0;   // arbitary return value
2263            }
2264            BOOST_UBLAS_INLINE
2265            size_type index2 () const {
2266                BOOST_UBLAS_CHECK_FALSE (bad_index ());
2267                return 0;   // arbitary return value
2268            }
2269
2270            // Assignment
2271            BOOST_UBLAS_INLINE
2272            const_iterator2 &operator = (const const_iterator2 &it) {
2273                container_const_reference<self_type>::assign (&it ());
2274                return *this;
2275            }
2276
2277            // Comparison
2278            BOOST_UBLAS_INLINE
2279            bool operator == (const const_iterator2 &it) const {
2280                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2281                return true;
2282            }
2283        };
2284
2285        typedef const_iterator2 iterator2;
2286
2287        BOOST_UBLAS_INLINE
2288        const_iterator2 begin2 () const {
2289            return find2 (0, 0, 0);
2290        }
2291        BOOST_UBLAS_INLINE
2292        const_iterator2 end2 () const {
2293            return find2 (0, 0, size2_);
2294        }
2295
2296        // Reverse iterators
2297
2298        BOOST_UBLAS_INLINE
2299        const_reverse_iterator1 rbegin1 () const {
2300            return const_reverse_iterator1 (end1 ());
2301        }
2302        BOOST_UBLAS_INLINE
2303        const_reverse_iterator1 rend1 () const {
2304            return const_reverse_iterator1 (begin1 ());
2305        }
2306
2307        BOOST_UBLAS_INLINE
2308        const_reverse_iterator2 rbegin2 () const {
2309            return const_reverse_iterator2 (end2 ());
2310        }
2311        BOOST_UBLAS_INLINE
2312        const_reverse_iterator2 rend2 () const {
2313            return const_reverse_iterator2 (begin2 ());
2314        }
2315
2316    private:
2317        size_type size1_;
2318        size_type size2_;
2319        static const value_type zero_;
2320    };
2321
2322    template<class T>
2323    const typename zero_matrix<T>::value_type zero_matrix<T>::zero_ (0);
2324
2325
2326    // Identity matrix class
2327    template<class T>
2328    class identity_matrix:
2329        public matrix_container<identity_matrix<T> > {
2330
2331        typedef const T *const_pointer;
2332        typedef identity_matrix<T> self_type;
2333    public:
2334#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2335        using matrix_container<self_type>::operator ();
2336#endif
2337        typedef std::size_t size_type;
2338        typedef std::ptrdiff_t difference_type;
2339        typedef T value_type;
2340        typedef const T &const_reference;
2341        typedef T &reference;
2342        typedef const matrix_reference<const self_type> const_closure_type;
2343        typedef matrix_reference<self_type> closure_type;
2344        typedef sparse_tag storage_category;
2345        typedef unknown_orientation_tag orientation_category;
2346
2347        // Construction and destruction
2348        BOOST_UBLAS_INLINE
2349        identity_matrix ():
2350            matrix_container<self_type> (),
2351            size1_ (0), size2_ (0), size_common_ (0) {}
2352        BOOST_UBLAS_INLINE
2353        identity_matrix (size_type size):
2354            matrix_container<self_type> (),
2355            size1_ (size), size2_ (size), size_common_ ((std::min) (size1_, size2_)) {}
2356        BOOST_UBLAS_INLINE
2357        identity_matrix (size_type size1, size_type size2):
2358            matrix_container<self_type> (),
2359            size1_ (size1), size2_ (size2), size_common_ ((std::min) (size1_, size2_)) {}
2360        BOOST_UBLAS_INLINE
2361        identity_matrix (const identity_matrix &m):
2362            matrix_container<self_type> (),
2363            size1_ (m.size1_), size2_ (m.size2_), size_common_ ((std::min) (size1_, size2_)) {}
2364
2365        // Accessors
2366        BOOST_UBLAS_INLINE
2367        size_type size1 () const {
2368            return size1_;
2369        }
2370        BOOST_UBLAS_INLINE
2371        size_type size2 () const {
2372            return size2_;
2373        }
2374
2375        // Resizing
2376        BOOST_UBLAS_INLINE
2377        void resize (size_type size, bool preserve = true) {
2378            size1_ = size;
2379            size2_ = size;
2380        }
2381        BOOST_UBLAS_INLINE
2382        void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
2383            size1_ = size1;
2384            size2_ = size2;
2385        }
2386
2387        // Element access
2388        BOOST_UBLAS_INLINE
2389        const_reference operator () (size_type i, size_type j) const {
2390            if (i == j)
2391                return one_;
2392            else
2393                return zero_;
2394        }
2395
2396        // Assignment
2397        BOOST_UBLAS_INLINE
2398        identity_matrix &operator = (const identity_matrix &m) {
2399            size1_ = m.size1_;
2400            size2_ = m.size2_;
2401            return *this;
2402        }
2403        BOOST_UBLAS_INLINE
2404        identity_matrix &assign_temporary (identity_matrix &m) { 
2405            swap (m);
2406            return *this;
2407        }
2408
2409        // Swapping
2410        BOOST_UBLAS_INLINE
2411        void swap (identity_matrix &m) {
2412            if (this != &m) {
2413                std::swap (size1_, m.size1_);
2414                std::swap (size2_, m.size2_);
2415            }
2416        }
2417        BOOST_UBLAS_INLINE
2418        friend void swap (identity_matrix &m1, identity_matrix &m2) {
2419            m1.swap (m2);
2420        }
2421
2422        // Iterator types
2423    private:
2424        // Use an index
2425        typedef size_type const_subiterator_type;
2426
2427    public:
2428        class const_iterator1;
2429        class const_iterator2;
2430        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2431        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2432
2433        // Element lookup
2434        BOOST_UBLAS_INLINE
2435        const_iterator1 find1 (int rank, size_type i, size_type j) const {
2436            if (rank == 1) {
2437                i = (std::max) (i, j);
2438                i = (std::min) (i, j + 1);
2439            }
2440            return const_iterator1 (*this, i);
2441        }
2442        BOOST_UBLAS_INLINE
2443        const_iterator2 find2 (int rank, size_type i, size_type j) const {
2444            if (rank == 1) {
2445                j = (std::max) (j, i);
2446                j = (std::min) (j, i + 1);
2447            }
2448            return const_iterator2 (*this, j);
2449        }
2450
2451
2452        class const_iterator1:
2453            public container_const_reference<identity_matrix>,
2454            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
2455                                               const_iterator1, value_type> {
2456        public:
2457            typedef typename identity_matrix::value_type value_type;
2458            typedef typename identity_matrix::difference_type difference_type;
2459            typedef typename identity_matrix::const_reference reference;
2460            typedef typename identity_matrix::const_pointer pointer;
2461
2462            typedef const_iterator2 dual_iterator_type;
2463            typedef const_reverse_iterator2 dual_reverse_iterator_type;
2464
2465            // Construction and destruction
2466            BOOST_UBLAS_INLINE
2467            const_iterator1 ():
2468                container_const_reference<self_type> (), it_ () {}
2469            BOOST_UBLAS_INLINE
2470            const_iterator1 (const self_type &m, const const_subiterator_type &it):
2471                container_const_reference<self_type> (m), it_ (it) {}
2472
2473            // Arithmetic
2474            BOOST_UBLAS_INLINE
2475            const_iterator1 &operator ++ () {
2476                BOOST_UBLAS_CHECK (it_ < (*this) ().size1 (), bad_index ());
2477                ++it_;
2478                return *this;
2479            }
2480            BOOST_UBLAS_INLINE
2481            const_iterator1 &operator -- () {
2482                BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
2483                --it_;
2484                return *this;
2485            }
2486
2487            // Dereference
2488            BOOST_UBLAS_INLINE
2489            const_reference operator * () const {
2490                return one_;
2491            }
2492
2493#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2494            BOOST_UBLAS_INLINE
2495#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2496            typename self_type::
2497#endif
2498            const_iterator2 begin () const {
2499                return const_iterator2 ((*this) (), it_); 
2500            }
2501            BOOST_UBLAS_INLINE
2502#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2503            typename self_type::
2504#endif
2505            const_iterator2 end () const {
2506                return const_iterator2 ((*this) (), it_ + 1); 
2507            }
2508            BOOST_UBLAS_INLINE
2509#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2510            typename self_type::
2511#endif
2512            const_reverse_iterator2 rbegin () const {
2513                return const_reverse_iterator2 (end ());
2514            }
2515            BOOST_UBLAS_INLINE
2516#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2517            typename self_type::
2518#endif
2519            const_reverse_iterator2 rend () const {
2520                return const_reverse_iterator2 (begin ());
2521            }
2522#endif
2523
2524            // Indices
2525            BOOST_UBLAS_INLINE
2526            size_type index1 () const {
2527                return it_;
2528            }
2529            BOOST_UBLAS_INLINE
2530            size_type index2 () const {
2531                return it_;
2532            }
2533
2534            // Assignment
2535            BOOST_UBLAS_INLINE
2536            const_iterator1 &operator = (const const_iterator1 &it) {
2537                container_const_reference<self_type>::assign (&it ());
2538                it_ = it.it_;
2539                return *this;
2540            }
2541
2542            // Comparison
2543            BOOST_UBLAS_INLINE
2544            bool operator == (const const_iterator1 &it) const {
2545                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2546                return it_ == it.it_;
2547            }
2548
2549        private:
2550            const_subiterator_type it_;
2551        };
2552
2553        typedef const_iterator1 iterator1;
2554
2555        BOOST_UBLAS_INLINE
2556        const_iterator1 begin1 () const {
2557            return const_iterator1 (*this, 0);
2558        }
2559        BOOST_UBLAS_INLINE
2560        const_iterator1 end1 () const {
2561            return const_iterator1 (*this, size_common_);
2562        }
2563
2564        class const_iterator2:
2565            public container_const_reference<identity_matrix>,
2566            public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
2567                                               const_iterator2, value_type> {
2568        public:
2569            typedef typename identity_matrix::value_type value_type;
2570            typedef typename identity_matrix::difference_type difference_type;
2571            typedef typename identity_matrix::const_reference reference;
2572            typedef typename identity_matrix::const_pointer pointer;
2573
2574            typedef const_iterator1 dual_iterator_type;
2575            typedef const_reverse_iterator1 dual_reverse_iterator_type;
2576
2577            // Construction and destruction
2578            BOOST_UBLAS_INLINE
2579            const_iterator2 ():
2580                container_const_reference<self_type> (), it_ () {}
2581            BOOST_UBLAS_INLINE
2582            const_iterator2 (const self_type &m, const const_subiterator_type &it):
2583                container_const_reference<self_type> (m), it_ (it) {}
2584
2585            // Arithmetic
2586            BOOST_UBLAS_INLINE
2587            const_iterator2 &operator ++ () {
2588                BOOST_UBLAS_CHECK (it_ < (*this) ().size_common_, bad_index ());
2589                ++it_;
2590                return *this;
2591            }
2592            BOOST_UBLAS_INLINE
2593            const_iterator2 &operator -- () {
2594                BOOST_UBLAS_CHECK (it_ > 0, bad_index ());
2595                --it_;
2596                return *this;
2597            }
2598
2599            // Dereference
2600            BOOST_UBLAS_INLINE
2601            const_reference operator * () const {
2602                return one_;
2603            }
2604
2605#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2606            BOOST_UBLAS_INLINE
2607#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2608            typename self_type::
2609#endif
2610            const_iterator1 begin () const {
2611                return const_iterator1 ((*this) (), it_); 
2612            }
2613            BOOST_UBLAS_INLINE
2614#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2615            typename self_type::
2616#endif
2617            const_iterator1 end () const {
2618                return const_iterator1 ((*this) (), it_ + 1); 
2619            }
2620            BOOST_UBLAS_INLINE
2621#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2622            typename self_type::
2623#endif
2624            const_reverse_iterator1 rbegin () const {
2625                return const_reverse_iterator1 (end ());
2626            }
2627            BOOST_UBLAS_INLINE
2628#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2629            typename self_type::
2630#endif
2631            const_reverse_iterator1 rend () const {
2632                return const_reverse_iterator1 (begin ());
2633            }
2634#endif
2635
2636            // Indices
2637            BOOST_UBLAS_INLINE
2638            size_type index1 () const {
2639                return it_;
2640            }
2641            BOOST_UBLAS_INLINE
2642            size_type index2 () const {
2643                return it_;
2644            }
2645
2646            // Assignment
2647            BOOST_UBLAS_INLINE
2648            const_iterator2 &operator = (const const_iterator2 &it) {
2649                container_const_reference<self_type>::assign (&it ());
2650                it_ = it.it_;
2651                return *this;
2652            }
2653
2654            // Comparison
2655            BOOST_UBLAS_INLINE
2656            bool operator == (const const_iterator2 &it) const {
2657                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2658                return it_ == it.it_;
2659            }
2660
2661        private:
2662            const_subiterator_type it_;
2663        };
2664
2665        typedef const_iterator2 iterator2;
2666
2667        BOOST_UBLAS_INLINE
2668        const_iterator2 begin2 () const {
2669            return const_iterator2 (*this, 0);
2670        }
2671        BOOST_UBLAS_INLINE
2672        const_iterator2 end2 () const {
2673            return const_iterator2 (*this, size_common_);
2674        }
2675
2676        // Reverse iterators
2677
2678        BOOST_UBLAS_INLINE
2679        const_reverse_iterator1 rbegin1 () const {
2680            return const_reverse_iterator1 (end1 ());
2681        }
2682        BOOST_UBLAS_INLINE
2683        const_reverse_iterator1 rend1 () const {
2684            return const_reverse_iterator1 (begin1 ());
2685        }
2686
2687        BOOST_UBLAS_INLINE
2688        const_reverse_iterator2 rbegin2 () const {
2689            return const_reverse_iterator2 (end2 ());
2690        }
2691        BOOST_UBLAS_INLINE
2692        const_reverse_iterator2 rend2 () const {
2693            return const_reverse_iterator2 (begin2 ());
2694        }
2695
2696    private:
2697        size_type size1_;
2698        size_type size2_;
2699        size_type size_common_;
2700        static const value_type zero_;
2701        static const value_type one_;
2702    };
2703
2704    template<class T>
2705    const typename identity_matrix<T>::value_type identity_matrix<T>::zero_ (0);
2706    template<class T>
2707    const typename identity_matrix<T>::value_type identity_matrix<T>::one_ (1);
2708
2709
2710    // Scalar matrix class
2711    template<class T>
2712    class scalar_matrix:
2713        public matrix_container<scalar_matrix<T> > {
2714
2715        typedef const T *const_pointer;
2716        typedef scalar_matrix<T> self_type;
2717    public:
2718#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2719        using matrix_container<self_type>::operator ();
2720#endif
2721        typedef std::size_t size_type;
2722        typedef std::ptrdiff_t difference_type;
2723        typedef T value_type;
2724        typedef const T &const_reference;
2725        typedef T &reference;
2726        typedef const matrix_reference<const self_type> const_closure_type;
2727        typedef dense_tag storage_category;
2728        typedef unknown_orientation_tag orientation_category;
2729
2730        // Construction and destruction
2731        BOOST_UBLAS_INLINE
2732        scalar_matrix ():
2733            matrix_container<self_type> (),
2734            size1_ (0), size2_ (0), value_ () {}
2735        BOOST_UBLAS_INLINE
2736        scalar_matrix (size_type size1, size_type size2, const value_type &value = value_type(1)):
2737            matrix_container<self_type> (),
2738            size1_ (size1), size2_ (size2), value_ (value) {}
2739        BOOST_UBLAS_INLINE
2740        scalar_matrix (const scalar_matrix &m):
2741            matrix_container<self_type> (),
2742            size1_ (m.size1_), size2_ (m.size2_), value_ (m.value_) {}
2743
2744        // Accessors
2745        BOOST_UBLAS_INLINE
2746        size_type size1 () const {
2747            return size1_;
2748        }
2749        BOOST_UBLAS_INLINE
2750        size_type size2 () const {
2751            return size2_;
2752        }
2753
2754        // Resizing
2755        BOOST_UBLAS_INLINE
2756        void resize (size_type size1, size_type size2, bool /*preserve*/ = true) {
2757            size1_ = size1;
2758            size2_ = size2;
2759        }
2760
2761        // Element access
2762        BOOST_UBLAS_INLINE
2763        const_reference operator () (size_type /*i*/, size_type /*j*/) const {
2764            return value_; 
2765        }
2766
2767        // Assignment
2768        BOOST_UBLAS_INLINE
2769        scalar_matrix &operator = (const scalar_matrix &m) {
2770            size1_ = m.size1_;
2771            size2_ = m.size2_;
2772            value_ = m.value_;
2773            return *this;
2774        }
2775        BOOST_UBLAS_INLINE
2776        scalar_matrix &assign_temporary (scalar_matrix &m) { 
2777            swap (m);
2778            return *this;
2779        }
2780
2781        // Swapping
2782        BOOST_UBLAS_INLINE
2783        void swap (scalar_matrix &m) {
2784            if (this != &m) {
2785                std::swap (size1_, m.size1_);
2786                std::swap (size2_, m.size2_);
2787                std::swap (value_, m.value_);
2788            }
2789        }
2790        BOOST_UBLAS_INLINE
2791        friend void swap (scalar_matrix &m1, scalar_matrix &m2) {
2792            m1.swap (m2);
2793        }
2794
2795        // Iterator types
2796    private:
2797        // Use an index
2798        typedef size_type const_subiterator_type;
2799
2800    public:
2801#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2802        typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
2803        typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
2804        typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
2805        typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
2806#else
2807        class const_iterator1;
2808        class const_iterator2;
2809#endif
2810        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2811        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2812
2813        // Element lookup
2814        BOOST_UBLAS_INLINE
2815        const_iterator1 find1 (int /*rank*/, size_type i, size_type j) const {
2816            return const_iterator1 (*this, i, j);
2817        }
2818        BOOST_UBLAS_INLINE
2819        const_iterator2 find2 (int /*rank*/, size_type i, size_type j) const {
2820            return const_iterator2 (*this, i, j);
2821        }   
2822
2823
2824#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2825        class const_iterator1:
2826            public container_const_reference<scalar_matrix>,
2827            public random_access_iterator_base<dense_random_access_iterator_tag,
2828                                               const_iterator1, value_type> {
2829        public:
2830            typedef typename scalar_matrix::value_type value_type;
2831            typedef typename scalar_matrix::difference_type difference_type;
2832            typedef typename scalar_matrix::const_reference reference;
2833            typedef typename scalar_matrix::const_pointer pointer;
2834
2835            typedef const_iterator2 dual_iterator_type;
2836            typedef const_reverse_iterator2 dual_reverse_iterator_type;
2837
2838            // Construction and destruction
2839            BOOST_UBLAS_INLINE
2840            const_iterator1 ():
2841                container_const_reference<scalar_matrix> (), it1_ (), it2_ () {}
2842            BOOST_UBLAS_INLINE
2843            const_iterator1 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2):
2844                container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {}
2845
2846            // Arithmetic
2847            BOOST_UBLAS_INLINE
2848            const_iterator1 &operator ++ () {
2849                ++ it1_;
2850                return *this;
2851            }
2852            BOOST_UBLAS_INLINE
2853            const_iterator1 &operator -- () {
2854                -- it1_;
2855                return *this;
2856            }
2857            BOOST_UBLAS_INLINE
2858            const_iterator1 &operator += (difference_type n) {
2859                it1_ += n;
2860                return *this;
2861            }
2862            BOOST_UBLAS_INLINE
2863            const_iterator1 &operator -= (difference_type n) {
2864                it1_ -= n;
2865                return *this;
2866            }
2867            BOOST_UBLAS_INLINE
2868            difference_type operator - (const const_iterator1 &it) const {
2869                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2870                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
2871                return it1_ - it.it1_;
2872            }
2873
2874            // Dereference
2875            BOOST_UBLAS_INLINE
2876            const_reference operator * () const {
2877                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
2878                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
2879                return (*this) () (index1 (), index2 ());
2880            }
2881            BOOST_UBLAS_INLINE
2882            const_reference operator [] (difference_type n) const {
2883                return *(*this + n);
2884            }
2885
2886#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2887            BOOST_UBLAS_INLINE
2888#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2889            typename self_type::
2890#endif
2891            const_iterator2 begin () const {
2892                const scalar_matrix &m = (*this) ();
2893                return m.find2 (1, index1 (), 0);
2894            }
2895            BOOST_UBLAS_INLINE
2896#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2897            typename self_type::
2898#endif
2899            const_iterator2 end () const {
2900                const scalar_matrix &m = (*this) ();
2901                return m.find2 (1, index1 (), m.size2 ());
2902            }
2903            BOOST_UBLAS_INLINE
2904#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2905            typename self_type::
2906#endif
2907            const_reverse_iterator2 rbegin () const {
2908                return const_reverse_iterator2 (end ());
2909            }
2910            BOOST_UBLAS_INLINE
2911#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2912            typename self_type::
2913#endif
2914            const_reverse_iterator2 rend () const {
2915                return const_reverse_iterator2 (begin ());
2916            }
2917#endif
2918
2919            // Indices
2920            BOOST_UBLAS_INLINE
2921            size_type index1 () const {
2922                return it1_;
2923            }
2924            BOOST_UBLAS_INLINE
2925            size_type index2 () const {
2926                return it2_;
2927            }
2928
2929            // Assignment
2930            BOOST_UBLAS_INLINE
2931            const_iterator1 &operator = (const const_iterator1 &it) {
2932                container_const_reference<scalar_matrix>::assign (&it ());
2933                it1_ = it.it1_;
2934                it2_ = it.it2_;
2935                return *this;
2936            }
2937
2938            // Comparison
2939            BOOST_UBLAS_INLINE
2940            bool operator == (const const_iterator1 &it) const {
2941                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2942                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
2943                return it1_ == it.it1_;
2944            }
2945            BOOST_UBLAS_INLINE
2946            bool operator < (const const_iterator1 &it) const {
2947                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2948                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
2949                return it1_ < it.it1_;
2950            }
2951
2952        private:
2953            const_subiterator_type it1_;
2954            const_subiterator_type it2_;
2955        };
2956
2957        typedef const_iterator1 iterator1;
2958#endif
2959
2960        BOOST_UBLAS_INLINE
2961        const_iterator1 begin1 () const {
2962            return find1 (0, 0, 0);
2963        }
2964        BOOST_UBLAS_INLINE
2965        const_iterator1 end1 () const {
2966            return find1 (0, size1_, 0);
2967        }
2968
2969#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2970        class const_iterator2:
2971            public container_const_reference<scalar_matrix>,
2972            public random_access_iterator_base<dense_random_access_iterator_tag,
2973                                               const_iterator2, value_type> {
2974        public:
2975            typedef typename scalar_matrix::value_type value_type;
2976            typedef typename scalar_matrix::difference_type difference_type;
2977            typedef typename scalar_matrix::const_reference reference;
2978            typedef typename scalar_matrix::const_pointer pointer;
2979
2980            typedef const_iterator1 dual_iterator_type;
2981            typedef const_reverse_iterator1 dual_reverse_iterator_type;
2982
2983            // Construction and destruction
2984            BOOST_UBLAS_INLINE
2985            const_iterator2 ():
2986                container_const_reference<scalar_matrix> (), it1_ (), it2_ () {}
2987            BOOST_UBLAS_INLINE
2988            const_iterator2 (const scalar_matrix &m, const const_subiterator_type &it1, const const_subiterator_type &it2):
2989                container_const_reference<scalar_matrix> (m), it1_ (it1), it2_ (it2) {}
2990
2991            // Arithmetic
2992            BOOST_UBLAS_INLINE
2993            const_iterator2 &operator ++ () {
2994                ++ it2_;
2995                return *this;
2996            }
2997            BOOST_UBLAS_INLINE
2998            const_iterator2 &operator -- () {
2999                -- it2_;
3000                return *this;
3001            }
3002            BOOST_UBLAS_INLINE
3003            const_iterator2 &operator += (difference_type n) {
3004                it2_ += n;
3005                return *this;
3006            }
3007            BOOST_UBLAS_INLINE
3008            const_iterator2 &operator -= (difference_type n) {
3009                it2_ -= n;
3010                return *this;
3011            }
3012            BOOST_UBLAS_INLINE
3013            difference_type operator - (const const_iterator2 &it) const {
3014                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3015                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3016                return it2_ - it.it2_;
3017            }
3018
3019            // Dereference
3020            BOOST_UBLAS_INLINE
3021            const_reference operator * () const {
3022                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
3023                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
3024                return (*this) () (index1 (), index2 ());
3025            }
3026            BOOST_UBLAS_INLINE
3027            const_reference operator [] (difference_type n) const {
3028                return *(*this + n);
3029            }
3030
3031#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3032            BOOST_UBLAS_INLINE
3033#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3034            typename self_type::
3035#endif
3036            const_iterator1 begin () const {
3037                const scalar_matrix &m = (*this) ();
3038                return m.find1 (1, 0, index2 ());
3039            }
3040            BOOST_UBLAS_INLINE
3041#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3042            typename self_type::
3043#endif
3044            const_iterator1 end () const {
3045                const scalar_matrix &m = (*this) ();
3046                return m.find1 (1, m.size1 (), index2 ());
3047            }
3048            BOOST_UBLAS_INLINE
3049#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3050            typename self_type::
3051#endif
3052            const_reverse_iterator1 rbegin () const {
3053                return const_reverse_iterator1 (end ());
3054            }
3055            BOOST_UBLAS_INLINE
3056#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3057            typename self_type::
3058#endif
3059            const_reverse_iterator1 rend () const {
3060                return const_reverse_iterator1 (begin ());
3061            }
3062#endif
3063
3064            // Indices
3065            BOOST_UBLAS_INLINE
3066            size_type index1 () const {
3067                return it1_;
3068            }
3069            BOOST_UBLAS_INLINE
3070            size_type index2 () const {
3071                return it2_;
3072            }
3073
3074            // Assignment
3075            BOOST_UBLAS_INLINE
3076            const_iterator2 &operator = (const const_iterator2 &it) {
3077                container_const_reference<scalar_matrix>::assign (&it ());
3078                it1_ = it.it1_;
3079                it2_ = it.it2_;
3080                return *this;
3081            }
3082
3083            // Comparison
3084            BOOST_UBLAS_INLINE
3085            bool operator == (const const_iterator2 &it) const {
3086                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3087                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3088                return it2_ == it.it2_;
3089            }
3090            BOOST_UBLAS_INLINE
3091            bool operator < (const const_iterator2 &it) const {
3092                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3093                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3094                return it2_ < it.it2_;
3095            }
3096
3097        private:
3098            const_subiterator_type it1_;
3099            const_subiterator_type it2_;
3100        };
3101
3102        typedef const_iterator2 iterator2;
3103#endif
3104
3105        BOOST_UBLAS_INLINE
3106        const_iterator2 begin2 () const {
3107            return find2 (0, 0, 0);
3108        }
3109        BOOST_UBLAS_INLINE
3110        const_iterator2 end2 () const {
3111            return find2 (0, 0, size2_);
3112        }
3113
3114        // Reverse iterators
3115
3116        BOOST_UBLAS_INLINE
3117        const_reverse_iterator1 rbegin1 () const {
3118            return const_reverse_iterator1 (end1 ());
3119        }
3120        BOOST_UBLAS_INLINE
3121        const_reverse_iterator1 rend1 () const {
3122            return const_reverse_iterator1 (begin1 ());
3123        }
3124
3125        BOOST_UBLAS_INLINE
3126        const_reverse_iterator2 rbegin2 () const {
3127            return const_reverse_iterator2 (end2 ());
3128        }
3129        BOOST_UBLAS_INLINE
3130        const_reverse_iterator2 rend2 () const {
3131            return const_reverse_iterator2 (begin2 ());
3132        }
3133
3134    private:
3135        size_type size1_;
3136        size_type size2_;
3137        value_type value_;
3138    };
3139
3140
3141    // Array based matrix class
3142    template<class T, std::size_t N, std::size_t M>
3143    class c_matrix:
3144        public matrix_container<c_matrix<T, N, M> > {
3145
3146        typedef c_matrix<T, N, M> self_type;
3147    public:
3148#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
3149        using matrix_container<self_type>::operator ();
3150#endif
3151        typedef std::size_t size_type;
3152        typedef std::ptrdiff_t difference_type;
3153        typedef T value_type;
3154        typedef const T &const_reference;
3155        typedef T &reference;
3156        typedef const T *const_pointer;
3157        typedef T *pointer;
3158        typedef const matrix_reference<const self_type> const_closure_type;
3159        typedef matrix_reference<self_type> closure_type;
3160        typedef c_vector<T, N * M> vector_temporary_type;     // vector able to store all elements of c_matrix
3161        typedef self_type matrix_temporary_type;
3162        typedef dense_tag storage_category;
3163        // This could be better for performance,
3164        // typedef typename unknown_orientation_tag orientation_category;
3165        // but others depend on the orientation information...
3166        typedef row_major_tag orientation_category;
3167
3168        // Construction and destruction
3169        BOOST_UBLAS_INLINE
3170        c_matrix ():
3171            size1_ (N), size2_ (M) /* , data_ () */ {
3172        }
3173        BOOST_UBLAS_INLINE
3174        c_matrix (size_type size1, size_type size2):
3175            size1_ (size1), size2_ (size2) /* , data_ () */ {
3176            if (size1_ > N || size2_ > M)
3177                bad_size ().raise ();
3178        }
3179        BOOST_UBLAS_INLINE
3180        c_matrix (const c_matrix &m):
3181            size1_ (m.size1_), size2_ (m.size2_) /* , data_ () */ {
3182            if (size1_ > N || size2_ > M)
3183                bad_size ().raise ();
3184            *this = m;
3185        }
3186        template<class AE>
3187        BOOST_UBLAS_INLINE
3188        c_matrix (const matrix_expression<AE> &ae):
3189            size1_ (ae ().size1 ()), size2_ (ae ().size2 ()) /* , data_ () */ {
3190            if (size1_ > N || size2_ > M)
3191                bad_size ().raise ();
3192            matrix_assign<scalar_assign> (*this, ae);
3193        }
3194
3195        // Accessors
3196        BOOST_UBLAS_INLINE
3197        size_type size1 () const {
3198            return size1_;
3199        }
3200        BOOST_UBLAS_INLINE
3201        size_type size2 () const {
3202            return size2_;
3203        }
3204        BOOST_UBLAS_INLINE
3205        const_pointer data () const {
3206            return reinterpret_cast<const_pointer> (data_);
3207        }
3208        BOOST_UBLAS_INLINE
3209        pointer data () {
3210            return reinterpret_cast<pointer> (data_);
3211        }
3212
3213        // Resizing
3214        BOOST_UBLAS_INLINE
3215        void resize (size_type size1, size_type size2, bool preserve = true) {
3216            if (size1 > N || size2 > M)
3217                bad_size ().raise ();
3218            if (preserve) {
3219                self_type temporary (size1, size2);
3220                // Common elements to preserve
3221                const size_type size1_min = (std::min) (size1, size1_);
3222                const size_type size2_min = (std::min) (size2, size2_);
3223                for (size_type i = 0; i != size1_min; ++i) {    // indexing copy over major
3224                    for (size_type j = 0; j != size2_min; ++j) {
3225                        temporary.data_[i][j] = data_[i][j];
3226                    }
3227                }
3228                assign_temporary (temporary);
3229            }
3230            else {
3231                size1_ = size1;
3232                size2_ = size2;
3233            }
3234        }
3235
3236        // Element access
3237        BOOST_UBLAS_INLINE
3238        const_reference operator () (size_type i, size_type j) const {
3239            BOOST_UBLAS_CHECK (i < size1_, bad_index ());
3240            BOOST_UBLAS_CHECK (j < size2_, bad_index ());
3241            return data_ [i] [j];
3242        }
3243        BOOST_UBLAS_INLINE
3244        reference at_element (size_type i, size_type j) {
3245            BOOST_UBLAS_CHECK (i < size1_, bad_index ());
3246            BOOST_UBLAS_CHECK (j < size2_, bad_index ());
3247            return data_ [i] [j];
3248        }
3249        BOOST_UBLAS_INLINE
3250        reference operator () (size_type i, size_type j) {
3251            return at_element (i, j);
3252        }
3253
3254        // Element assignment
3255        BOOST_UBLAS_INLINE
3256        reference insert_element (size_type i, size_type j, const_reference t) {
3257            return (at_element (i, j) = t);
3258        }
3259       
3260        // Zeroing
3261        BOOST_UBLAS_INLINE
3262        void clear () {
3263            for (size_type i = 0; i < size1_; ++ i)
3264                std::fill (data_ [i], data_ [i] + size2_, value_type/*zero*/());
3265        }
3266
3267        // Assignment
3268        BOOST_UBLAS_INLINE
3269        c_matrix &operator = (const c_matrix &m) {
3270            size1_ = m.size1_;
3271            size2_ = m.size2_;
3272            for (size_type i = 0; i < m.size1_; ++ i)
3273                std::copy (m.data_ [i], m.data_ [i] + m.size2_, data_ [i]);
3274            return *this;
3275        }
3276        template<class C>          // Container assignment without temporary
3277        BOOST_UBLAS_INLINE
3278        c_matrix &operator = (const matrix_container<C> &m) {
3279            resize (m ().size1 (), m ().size2 (), false);
3280            assign (m);
3281            return *this;
3282        }
3283        BOOST_UBLAS_INLINE
3284        c_matrix &assign_temporary (c_matrix &m) {
3285            swap (m);
3286            return *this;
3287        }
3288        template<class AE>
3289        BOOST_UBLAS_INLINE
3290        c_matrix &operator = (const matrix_expression<AE> &ae) { 
3291            self_type temporary (ae);
3292            return assign_temporary (temporary);
3293        }
3294        template<class AE>
3295        BOOST_UBLAS_INLINE
3296        c_matrix &assign (const matrix_expression<AE> &ae) { 
3297            matrix_assign<scalar_assign> (*this, ae); 
3298            return *this;
3299        }
3300        template<class AE>
3301        BOOST_UBLAS_INLINE
3302        c_matrix& operator += (const matrix_expression<AE> &ae) {
3303            self_type temporary (*this + ae);
3304            return assign_temporary (temporary);
3305        }
3306        template<class C>          // Container assignment without temporary
3307        BOOST_UBLAS_INLINE
3308        c_matrix &operator += (const matrix_container<C> &m) {
3309            plus_assign (m);
3310            return *this;
3311        }
3312        template<class AE>
3313        BOOST_UBLAS_INLINE
3314        c_matrix &plus_assign (const matrix_expression<AE> &ae) { 
3315            matrix_assign<scalar_plus_assign> (*this, ae); 
3316            return *this;
3317        }
3318        template<class AE>
3319        BOOST_UBLAS_INLINE
3320        c_matrix& operator -= (const matrix_expression<AE> &ae) {
3321            self_type temporary (*this - ae);
3322            return assign_temporary (temporary);
3323        }
3324        template<class C>          // Container assignment without temporary
3325        BOOST_UBLAS_INLINE
3326        c_matrix &operator -= (const matrix_container<C> &m) {
3327            minus_assign (m);
3328            return *this;
3329        }
3330        template<class AE>
3331        BOOST_UBLAS_INLINE
3332        c_matrix &minus_assign (const matrix_expression<AE> &ae) { 
3333            matrix_assign<scalar_minus_assign> (*this, ae); 
3334            return *this;
3335        }
3336        template<class AT>
3337        BOOST_UBLAS_INLINE
3338        c_matrix& operator *= (const AT &at) {
3339            matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
3340            return *this;
3341        }
3342        template<class AT>
3343        BOOST_UBLAS_INLINE
3344        c_matrix& operator /= (const AT &at) {
3345            matrix_assign_scalar<scalar_divides_assign> (*this, at);
3346            return *this;
3347        }
3348
3349        // Swapping
3350        BOOST_UBLAS_INLINE
3351        void swap (c_matrix &m) {
3352            if (this != &m) {
3353                BOOST_UBLAS_CHECK (size1_ == m.size1_, bad_size ());
3354                BOOST_UBLAS_CHECK (size2_ == m.size2_, bad_size ());
3355                std::swap (size1_, m.size1_);
3356                std::swap (size2_, m.size2_);
3357                for (size_type i = 0; i < size1_; ++ i)
3358                    std::swap_ranges (data_ [i], data_ [i] + size2_, m.data_ [i]);
3359            }
3360        }
3361        BOOST_UBLAS_INLINE
3362        friend void swap (c_matrix &m1, c_matrix &m2) {
3363            m1.swap (m2);
3364        }
3365
3366        // Iterator types
3367    private:
3368        // Use pointers for iterator
3369        typedef const_pointer const_subiterator_type;
3370        typedef pointer subiterator_type;
3371
3372    public:
3373#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3374        typedef indexed_iterator1<self_type, dense_random_access_iterator_tag> iterator1;
3375        typedef indexed_iterator2<self_type, dense_random_access_iterator_tag> iterator2;
3376        typedef indexed_const_iterator1<self_type, dense_random_access_iterator_tag> const_iterator1;
3377        typedef indexed_const_iterator2<self_type, dense_random_access_iterator_tag> const_iterator2;
3378#else
3379        class const_iterator1;
3380        class iterator1;
3381        class const_iterator2;
3382        class iterator2;
3383#endif
3384        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
3385        typedef reverse_iterator_base1<iterator1> reverse_iterator1;
3386        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
3387        typedef reverse_iterator_base2<iterator2> reverse_iterator2;
3388
3389        // Element lookup
3390        BOOST_UBLAS_INLINE
3391        const_iterator1 find1 (int rank, size_type i, size_type j) const {
3392#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3393            return const_iterator1 (*this, i, j);
3394#else
3395            return const_iterator1 (*this, &data_ [i] [j]);
3396#endif
3397        }
3398        BOOST_UBLAS_INLINE
3399        iterator1 find1 (int rank, size_type i, size_type j) {
3400#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3401            return iterator1 (*this, i, j);
3402#else
3403            return iterator1 (*this, &data_ [i] [j]);
3404#endif
3405        }
3406        BOOST_UBLAS_INLINE
3407        const_iterator2 find2 (int rank, size_type i, size_type j) const {
3408#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3409            return const_iterator2 (*this, i, j);
3410#else
3411            return const_iterator2 (*this, &data_ [i] [j]);
3412#endif
3413        }
3414        BOOST_UBLAS_INLINE
3415        iterator2 find2 (int rank, size_type i, size_type j) {
3416#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3417            return iterator2 (*this, i, j);
3418#else
3419            return iterator2 (*this, &data_ [i] [j]);
3420#endif
3421        }
3422
3423
3424#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3425        class const_iterator1:
3426            public container_const_reference<c_matrix>,
3427            public random_access_iterator_base<dense_random_access_iterator_tag,
3428                                               const_iterator1, value_type> {
3429        public:
3430            typedef typename c_matrix::difference_type difference_type;
3431            typedef typename c_matrix::value_type value_type;
3432            typedef typename c_matrix::const_reference reference;
3433            typedef typename c_matrix::const_pointer pointer;
3434
3435            typedef const_iterator2 dual_iterator_type;
3436            typedef const_reverse_iterator2 dual_reverse_iterator_type;
3437
3438            // Construction and destruction
3439            BOOST_UBLAS_INLINE
3440            const_iterator1 ():
3441                container_const_reference<self_type> (), it_ () {}
3442            BOOST_UBLAS_INLINE
3443            const_iterator1 (const self_type &m, const const_subiterator_type &it):
3444                container_const_reference<self_type> (m), it_ (it) {}
3445            BOOST_UBLAS_INLINE
3446            const_iterator1 (const iterator1 &it):
3447                container_const_reference<self_type> (it ()), it_ (it.it_) {}
3448
3449            // Arithmetic
3450            BOOST_UBLAS_INLINE
3451            const_iterator1 &operator ++ () {
3452                it_ += M;
3453                return *this;
3454            }
3455            BOOST_UBLAS_INLINE
3456            const_iterator1 &operator -- () {
3457                it_ -= M;
3458                return *this;
3459            }
3460            BOOST_UBLAS_INLINE
3461            const_iterator1 &operator += (difference_type n) {
3462                it_ += n * M;
3463                return *this;
3464            }
3465            BOOST_UBLAS_INLINE
3466            const_iterator1 &operator -= (difference_type n) {
3467                it_ -= n * M;
3468                return *this;
3469            }
3470            BOOST_UBLAS_INLINE
3471            difference_type operator - (const const_iterator1 &it) const {
3472                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3473                return (it_ - it.it_) / M;
3474            }
3475
3476            // Dereference
3477            BOOST_UBLAS_INLINE
3478            const_reference operator * () const {
3479                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
3480                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
3481                return *it_;
3482            }
3483            BOOST_UBLAS_INLINE
3484            const_reference operator [] (difference_type n) const {
3485                return *(*this + n);
3486            }
3487
3488#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3489            BOOST_UBLAS_INLINE
3490#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3491            typename self_type::
3492#endif
3493            const_iterator2 begin () const {
3494                const self_type &m = (*this) ();
3495                return m.find2 (1, index1 (), 0);
3496            }
3497            BOOST_UBLAS_INLINE
3498#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3499            typename self_type::
3500#endif
3501            const_iterator2 end () const {
3502                const self_type &m = (*this) ();
3503                return m.find2 (1, index1 (), m.size2 ());
3504            }
3505            BOOST_UBLAS_INLINE
3506#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3507            typename self_type::
3508#endif
3509            const_reverse_iterator2 rbegin () const {
3510                return const_reverse_iterator2 (end ());
3511            }
3512            BOOST_UBLAS_INLINE
3513#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3514            typename self_type::
3515#endif
3516            const_reverse_iterator2 rend () const {
3517                return const_reverse_iterator2 (begin ());
3518            }
3519#endif
3520
3521            // Indices
3522            BOOST_UBLAS_INLINE
3523            size_type index1 () const {
3524                const self_type &m = (*this) ();
3525                return (it_ - m.begin1 ().it_) / M;
3526            }
3527            BOOST_UBLAS_INLINE
3528            size_type index2 () const {
3529                const self_type &m = (*this) ();
3530                return (it_ - m.begin1 ().it_) % M;
3531            }
3532
3533            // Assignment
3534            BOOST_UBLAS_INLINE
3535            const_iterator1 &operator = (const const_iterator1 &it) {
3536                container_const_reference<self_type>::assign (&it ());
3537                it_ = it.it_;
3538                return *this;
3539            }
3540
3541            // Comparison
3542            BOOST_UBLAS_INLINE
3543            bool operator == (const const_iterator1 &it) const {
3544                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3545                return it_ == it.it_;
3546            }
3547            BOOST_UBLAS_INLINE
3548            bool operator < (const const_iterator1 &it) const {
3549                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3550                return it_ < it.it_;
3551            }
3552
3553        private:
3554            const_subiterator_type it_;
3555
3556            friend class iterator1;
3557        };
3558#endif
3559
3560        BOOST_UBLAS_INLINE
3561        const_iterator1 begin1 () const {
3562            return find1 (0, 0, 0);
3563        }
3564        BOOST_UBLAS_INLINE
3565        const_iterator1 end1 () const {
3566            return find1 (0, size1_, 0);
3567        }
3568
3569#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3570        class iterator1:
3571            public container_reference<c_matrix>,
3572            public random_access_iterator_base<dense_random_access_iterator_tag,
3573                                               iterator1, value_type> {
3574        public:
3575
3576            typedef typename c_matrix::difference_type difference_type;
3577            typedef typename c_matrix::value_type value_type;
3578            typedef typename c_matrix::reference reference;
3579            typedef typename c_matrix::pointer pointer;
3580
3581            typedef iterator2 dual_iterator_type;
3582            typedef reverse_iterator2 dual_reverse_iterator_type;
3583
3584            // Construction and destruction
3585            BOOST_UBLAS_INLINE
3586            iterator1 ():
3587                container_reference<self_type> (), it_ () {}
3588            BOOST_UBLAS_INLINE
3589            iterator1 (self_type &m, const subiterator_type &it):
3590                container_reference<self_type> (m), it_ (it) {}
3591
3592            // Arithmetic
3593            BOOST_UBLAS_INLINE
3594            iterator1 &operator ++ () {
3595                it_ += M;
3596                return *this;
3597            }
3598            BOOST_UBLAS_INLINE
3599            iterator1 &operator -- () {
3600                it_ -= M;
3601                return *this;
3602            }
3603            BOOST_UBLAS_INLINE
3604            iterator1 &operator += (difference_type n) {
3605                it_ += n * M;
3606                return *this;
3607            }
3608            BOOST_UBLAS_INLINE
3609            iterator1 &operator -= (difference_type n) {
3610                it_ -= n * M;
3611                return *this;
3612            }
3613            BOOST_UBLAS_INLINE
3614            difference_type operator - (const iterator1 &it) const {
3615                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3616                return (it_ - it.it_) / M;
3617            }
3618
3619            // Dereference
3620            BOOST_UBLAS_INLINE
3621            reference operator * () const {
3622                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
3623                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
3624                return *it_;
3625            }
3626            BOOST_UBLAS_INLINE
3627            reference operator [] (difference_type n) const {
3628                return *(*this + n);
3629            }
3630
3631#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3632            BOOST_UBLAS_INLINE
3633#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3634            typename self_type::
3635#endif
3636            iterator2 begin () const {
3637                self_type &m = (*this) ();
3638                return m.find2 (1, index1 (), 0);
3639            }
3640            BOOST_UBLAS_INLINE
3641#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3642            typename self_type::
3643#endif
3644            iterator2 end () const {
3645                self_type &m = (*this) ();
3646                return m.find2 (1, index1 (), m.size2 ());
3647            }
3648            BOOST_UBLAS_INLINE
3649#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3650            typename self_type::
3651#endif
3652            reverse_iterator2 rbegin () const {
3653                return reverse_iterator2 (end ());
3654            }
3655            BOOST_UBLAS_INLINE
3656#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3657            typename self_type::
3658#endif
3659            reverse_iterator2 rend () const {
3660                return reverse_iterator2 (begin ());
3661            }
3662#endif
3663
3664            // Indices
3665            BOOST_UBLAS_INLINE
3666            size_type index1 () const {
3667                const self_type &m = (*this) ();
3668                return (it_ - m.begin1 ().it_) / M;
3669            }
3670            BOOST_UBLAS_INLINE
3671            size_type index2 () const {
3672                const self_type &m = (*this) ();
3673                return (it_ - m.begin1 ().it_) % M;
3674            }
3675
3676            // Assignment
3677            BOOST_UBLAS_INLINE
3678            iterator1 &operator = (const iterator1 &it) {
3679                container_reference<self_type>::assign (&it ());
3680                it_ = it.it_;
3681                return *this;
3682            }
3683
3684            // Comparison
3685            BOOST_UBLAS_INLINE
3686            bool operator == (const iterator1 &it) const {
3687                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3688                return it_ == it.it_;
3689            }
3690            BOOST_UBLAS_INLINE
3691            bool operator < (const iterator1 &it) const {
3692                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3693                return it_ < it.it_;
3694            }
3695
3696        private:
3697            subiterator_type it_;
3698
3699            friend class const_iterator1;
3700        };
3701#endif
3702
3703        BOOST_UBLAS_INLINE
3704        iterator1 begin1 () {
3705            return find1 (0, 0, 0);
3706        }
3707        BOOST_UBLAS_INLINE
3708        iterator1 end1 () {
3709            return find1 (0, size1_, 0);
3710        }
3711
3712#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3713        class const_iterator2:
3714            public container_const_reference<c_matrix>,
3715            public random_access_iterator_base<dense_random_access_iterator_tag,
3716                                               const_iterator2, value_type> {
3717        public:
3718            typedef typename c_matrix::difference_type difference_type;
3719            typedef typename c_matrix::value_type value_type;
3720            typedef typename c_matrix::const_reference reference;
3721            typedef typename c_matrix::const_reference pointer;
3722
3723            typedef const_iterator1 dual_iterator_type;
3724            typedef const_reverse_iterator1 dual_reverse_iterator_type;
3725
3726            // Construction and destruction
3727            BOOST_UBLAS_INLINE
3728            const_iterator2 ():
3729                container_const_reference<self_type> (), it_ () {}
3730            BOOST_UBLAS_INLINE
3731            const_iterator2 (const self_type &m, const const_subiterator_type &it):
3732                container_const_reference<self_type> (m), it_ (it) {}
3733            BOOST_UBLAS_INLINE
3734            const_iterator2 (const iterator2 &it):
3735                container_const_reference<self_type> (it ()), it_ (it.it_) {}
3736
3737            // Arithmetic
3738            BOOST_UBLAS_INLINE
3739            const_iterator2 &operator ++ () {
3740                ++ it_;
3741                return *this;
3742            }
3743            BOOST_UBLAS_INLINE
3744            const_iterator2 &operator -- () {
3745                -- it_;
3746                return *this;
3747            }
3748            BOOST_UBLAS_INLINE
3749            const_iterator2 &operator += (difference_type n) {
3750                it_ += n;
3751                return *this;
3752            }
3753            BOOST_UBLAS_INLINE
3754            const_iterator2 &operator -= (difference_type n) {
3755                it_ -= n;
3756                return *this;
3757            }
3758            BOOST_UBLAS_INLINE
3759            difference_type operator - (const const_iterator2 &it) const {
3760                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3761                return it_ - it.it_;
3762            }
3763
3764            // Dereference
3765            BOOST_UBLAS_INLINE
3766            const_reference operator * () const {
3767                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
3768                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
3769                return *it_;
3770            }
3771            BOOST_UBLAS_INLINE
3772            const_reference operator [] (difference_type n) const {
3773                return *(*this + n);
3774            }
3775
3776#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3777            BOOST_UBLAS_INLINE
3778#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3779            typename self_type::
3780#endif
3781            const_iterator1 begin () const {
3782                const self_type &m = (*this) ();
3783                return m.find1 (1, 0, index2 ());
3784            }
3785            BOOST_UBLAS_INLINE
3786#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3787            typename self_type::
3788#endif
3789            const_iterator1 end () const {
3790                const self_type &m = (*this) ();
3791                return m.find1 (1, m.size1 (), index2 ());
3792            }
3793            BOOST_UBLAS_INLINE
3794#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3795            typename self_type::
3796#endif
3797            const_reverse_iterator1 rbegin () const {
3798                return const_reverse_iterator1 (end ());
3799            }
3800            BOOST_UBLAS_INLINE
3801#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3802            typename self_type::
3803#endif
3804            const_reverse_iterator1 rend () const {
3805                return const_reverse_iterator1 (begin ());
3806            }
3807#endif
3808
3809            // Indices
3810            BOOST_UBLAS_INLINE
3811            size_type index1 () const {
3812                const self_type &m = (*this) ();
3813                return (it_ - m.begin2 ().it_) / M;
3814            }
3815            BOOST_UBLAS_INLINE
3816            size_type index2 () const {
3817                const self_type &m = (*this) ();
3818                return (it_ - m.begin2 ().it_) % M;
3819            }
3820
3821            // Assignment
3822            BOOST_UBLAS_INLINE
3823            const_iterator2 &operator = (const const_iterator2 &it) {
3824                container_const_reference<self_type>::assign (&it ());
3825                it_ = it.it_;
3826                return *this;
3827            }
3828
3829            // Comparison
3830            BOOST_UBLAS_INLINE
3831            bool operator == (const const_iterator2 &it) const {
3832                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3833                return it_ == it.it_;
3834            }
3835            BOOST_UBLAS_INLINE
3836            bool operator < (const const_iterator2 &it) const {
3837                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3838                return it_ < it.it_;
3839            }
3840
3841        private:
3842            const_subiterator_type it_;
3843
3844            friend class iterator2;
3845        };
3846#endif
3847
3848        BOOST_UBLAS_INLINE
3849        const_iterator2 begin2 () const {
3850            return find2 (0, 0, 0);
3851        }
3852        BOOST_UBLAS_INLINE
3853        const_iterator2 end2 () const {
3854            return find2 (0, 0, size2_);
3855        }
3856
3857#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3858        class iterator2:
3859            public container_reference<c_matrix>,
3860            public random_access_iterator_base<dense_random_access_iterator_tag,
3861                                               iterator2, value_type> {
3862        public:
3863            typedef typename c_matrix::difference_type difference_type;
3864            typedef typename c_matrix::value_type value_type;
3865            typedef typename c_matrix::reference reference;
3866            typedef typename c_matrix::pointer pointer;
3867
3868            typedef iterator1 dual_iterator_type;
3869            typedef reverse_iterator1 dual_reverse_iterator_type;
3870
3871            // Construction and destruction
3872            BOOST_UBLAS_INLINE
3873            iterator2 ():
3874                container_reference<self_type> (), it_ () {}
3875            BOOST_UBLAS_INLINE
3876            iterator2 (self_type &m, const subiterator_type &it):
3877                container_reference<self_type> (m), it_ (it) {}
3878
3879            // Arithmetic
3880            BOOST_UBLAS_INLINE
3881            iterator2 &operator ++ () {
3882                ++ it_;
3883                return *this;
3884            }
3885            BOOST_UBLAS_INLINE
3886            iterator2 &operator -- () {
3887                -- it_;
3888                return *this;
3889            }
3890            BOOST_UBLAS_INLINE
3891            iterator2 &operator += (difference_type n) {
3892                it_ += n;
3893                return *this;
3894            }
3895            BOOST_UBLAS_INLINE
3896            iterator2 &operator -= (difference_type n) {
3897                it_ -= n;
3898                return *this;
3899            }
3900            BOOST_UBLAS_INLINE
3901            difference_type operator - (const iterator2 &it) const {
3902                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3903                return it_ - it.it_;
3904            }
3905
3906            // Dereference
3907            BOOST_UBLAS_INLINE
3908            reference operator * () const {
3909                BOOST_UBLAS_CHECK (index1 () < (*this) ().size1 (), bad_index ());
3910                BOOST_UBLAS_CHECK (index2 () < (*this) ().size2 (), bad_index ());
3911                return *it_;
3912            }
3913            BOOST_UBLAS_INLINE
3914            reference operator [] (difference_type n) const {
3915                return *(*this + n);
3916            }
3917
3918#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3919            BOOST_UBLAS_INLINE
3920#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3921            typename self_type::
3922#endif
3923            iterator1 begin () const {
3924                self_type &m = (*this) ();
3925                return m.find1 (1, 0, index2 ());
3926            }
3927            BOOST_UBLAS_INLINE
3928#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3929            typename self_type::
3930#endif
3931            iterator1 end () const {
3932                self_type &m = (*this) ();
3933                return m.find1 (1, m.size1 (), index2 ());
3934            }
3935            BOOST_UBLAS_INLINE
3936#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3937            typename self_type::
3938#endif
3939            reverse_iterator1 rbegin () const {
3940                return reverse_iterator1 (end ());
3941            }
3942            BOOST_UBLAS_INLINE
3943#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3944            typename self_type::
3945#endif
3946            reverse_iterator1 rend () const {
3947                return reverse_iterator1 (begin ());
3948            }
3949#endif
3950
3951            // Indices
3952            BOOST_UBLAS_INLINE
3953            size_type index1 () const {
3954                const self_type &m = (*this) ();
3955                return (it_ - m.begin2 ().it_) / M;
3956            }
3957            BOOST_UBLAS_INLINE
3958            size_type index2 () const {
3959                const self_type &m = (*this) ();
3960                return (it_ - m.begin2 ().it_) % M;
3961            }
3962
3963            // Assignment
3964            BOOST_UBLAS_INLINE
3965            iterator2 &operator = (const iterator2 &it) {
3966                container_reference<self_type>::assign (&it ());
3967                it_ = it.it_;
3968                return *this;
3969            }
3970
3971            // Comparison
3972            BOOST_UBLAS_INLINE
3973            bool operator == (const iterator2 &it) const {
3974                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3975                return it_ == it.it_;
3976            }
3977            BOOST_UBLAS_INLINE
3978            bool operator < (const iterator2 &it) const {
3979                BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
3980                return it_ < it.it_;
3981            }
3982
3983        private:
3984            subiterator_type it_;
3985
3986            friend class const_iterator2;
3987        };
3988#endif
3989
3990        BOOST_UBLAS_INLINE
3991        iterator2 begin2 () {
3992            return find2 (0, 0, 0);
3993        }
3994        BOOST_UBLAS_INLINE
3995        iterator2 end2 () {
3996            return find2 (0, 0, size2_);
3997        }
3998
3999        // Reverse iterators
4000
4001        BOOST_UBLAS_INLINE
4002        const_reverse_iterator1 rbegin1 () const {
4003            return const_reverse_iterator1 (end1 ());
4004        }
4005        BOOST_UBLAS_INLINE
4006        const_reverse_iterator1 rend1 () const {
4007            return const_reverse_iterator1 (begin1 ());
4008        }
4009
4010        BOOST_UBLAS_INLINE
4011        reverse_iterator1 rbegin1 () {
4012            return reverse_iterator1 (end1 ());
4013        }
4014        BOOST_UBLAS_INLINE
4015        reverse_iterator1 rend1 () {
4016            return reverse_iterator1 (begin1 ());
4017        }
4018
4019        BOOST_UBLAS_INLINE
4020        const_reverse_iterator2 rbegin2 () const {
4021            return const_reverse_iterator2 (end2 ());
4022        }
4023        BOOST_UBLAS_INLINE
4024        const_reverse_iterator2 rend2 () const {
4025            return const_reverse_iterator2 (begin2 ());
4026        }
4027
4028        BOOST_UBLAS_INLINE
4029        reverse_iterator2 rbegin2 () {
4030            return reverse_iterator2 (end2 ());
4031        }
4032        BOOST_UBLAS_INLINE
4033        reverse_iterator2 rend2 () {
4034            return reverse_iterator2 (begin2 ());
4035        }
4036
4037    private:
4038        size_type size1_;
4039        size_type size2_;
4040        value_type data_ [N] [M];
4041    };
4042
4043}}}
4044
4045#endif
Note: See TracBrowser for help on using the repository browser.