Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/numeric/ublas/matrix_proxy.hpp @ 44

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

updated boost from 1_33_1 to 1_34_1

File size: 186.1 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_PROXY_
18#define _BOOST_UBLAS_MATRIX_PROXY_
19
20#include <boost/numeric/ublas/matrix_expression.hpp>
21#include <boost/numeric/ublas/detail/vector_assign.hpp>
22#include <boost/numeric/ublas/detail/matrix_assign.hpp>
23#include <boost/numeric/ublas/detail/temporary.hpp>
24
25// Iterators based on ideas of Jeremy Siek
26
27namespace boost { namespace numeric { namespace ublas {
28
29    // Matrix based row vector class
30    template<class M>
31    class matrix_row:
32        public vector_expression<matrix_row<M> > {
33
34        typedef matrix_row<M> self_type;
35    public:
36#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
37        using vector_expression<self_type>::operator ();
38#endif
39        typedef M matrix_type;
40        typedef typename M::size_type size_type;
41        typedef typename M::difference_type difference_type;
42        typedef typename M::value_type value_type;
43        typedef typename M::const_reference const_reference;
44        typedef typename boost::mpl::if_<boost::is_const<M>,
45                                          typename M::const_reference,
46                                          typename M::reference>::type reference;
47        typedef typename boost::mpl::if_<boost::is_const<M>,
48                                          typename M::const_closure_type,
49                                          typename M::closure_type>::type matrix_closure_type;
50        typedef const self_type const_closure_type;
51        typedef self_type closure_type;
52        typedef typename storage_restrict_traits<typename M::storage_category,
53                                                 dense_proxy_tag>::storage_category storage_category;
54
55        // Construction and destruction
56        BOOST_UBLAS_INLINE
57        matrix_row (matrix_type &data, size_type i):
58            data_ (data), i_ (i) {
59            // Early checking of preconditions here.
60            // BOOST_UBLAS_CHECK (i_ < data_.size1 (), bad_index ());
61        }
62
63        // Accessors
64        BOOST_UBLAS_INLINE
65        size_type size () const {
66            return data_.size2 ();
67        }
68        BOOST_UBLAS_INLINE
69        size_type index () const {
70            return i_;
71        }
72
73        // Storage accessors
74        BOOST_UBLAS_INLINE
75        const matrix_closure_type &data () const {
76            return data_;
77        }
78        BOOST_UBLAS_INLINE
79        matrix_closure_type &data () {
80            return data_;
81        }
82
83        // Element access
84#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
85        BOOST_UBLAS_INLINE
86        const_reference operator () (size_type j) const {
87            return data_ (i_, j);
88        }
89        BOOST_UBLAS_INLINE
90        reference operator () (size_type j) {
91            return data_ (i_, j);
92        }
93
94        BOOST_UBLAS_INLINE
95        const_reference operator [] (size_type j) const {
96            return (*this) (j);
97        }
98        BOOST_UBLAS_INLINE
99        reference operator [] (size_type j) {
100            return (*this) (j);
101        }
102#else
103        BOOST_UBLAS_INLINE
104        reference operator () (size_type j) const {
105            return data_ (i_, j);
106        }
107
108        BOOST_UBLAS_INLINE
109        reference operator [] (size_type j) const {
110            return (*this) (j);
111        }
112#endif
113
114        // Assignment
115        BOOST_UBLAS_INLINE
116        matrix_row &operator = (const matrix_row &mr) {
117            // ISSUE need a temporary, proxy can be overlaping alias
118            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mr));
119            return *this;
120        }
121        BOOST_UBLAS_INLINE
122        matrix_row &assign_temporary (matrix_row &mr) {
123            // assign elements, proxied container remains the same
124            vector_assign<scalar_assign> (*this, mr);
125            return *this;
126        }
127        template<class AE>
128        BOOST_UBLAS_INLINE
129        matrix_row &operator = (const vector_expression<AE> &ae) {
130            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
131            return *this;
132        }
133        template<class AE>
134        BOOST_UBLAS_INLINE
135        matrix_row &assign (const vector_expression<AE> &ae) {
136            vector_assign<scalar_assign> (*this, ae);
137            return *this;
138        }
139        template<class AE>
140        BOOST_UBLAS_INLINE
141        matrix_row &operator += (const vector_expression<AE> &ae) {
142            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
143            return *this;
144        }
145        template<class AE>
146        BOOST_UBLAS_INLINE
147        matrix_row &plus_assign (const vector_expression<AE> &ae) {
148            vector_assign<scalar_plus_assign> (*this, ae);
149            return *this;
150        }
151        template<class AE>
152        BOOST_UBLAS_INLINE
153        matrix_row &operator -= (const vector_expression<AE> &ae) {
154            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
155            return *this;
156        }
157        template<class AE>
158        BOOST_UBLAS_INLINE
159        matrix_row &minus_assign (const vector_expression<AE> &ae) {
160            vector_assign<scalar_minus_assign> (*this, ae);
161            return *this;
162        }
163        template<class AT>
164        BOOST_UBLAS_INLINE
165        matrix_row &operator *= (const AT &at) {
166            vector_assign_scalar<scalar_multiplies_assign> (*this, at);
167            return *this;
168        }
169        template<class AT>
170        BOOST_UBLAS_INLINE
171        matrix_row &operator /= (const AT &at) {
172            vector_assign_scalar<scalar_divides_assign> (*this, at);
173            return *this;
174        }
175
176        // Closure comparison
177        BOOST_UBLAS_INLINE
178        bool same_closure (const matrix_row &mr) const {
179            return (*this).data_.same_closure (mr.data_);
180        }
181
182        // Comparison
183        BOOST_UBLAS_INLINE
184        bool operator == (const matrix_row &mr) const {
185            return (*this).data_ == mr.data_ && index () == mr.index ();
186        }
187
188        // Swapping
189        BOOST_UBLAS_INLINE
190        void swap (matrix_row mr) {
191            if (this != &mr) {
192                BOOST_UBLAS_CHECK (size () == mr.size (), bad_size ());
193                // Sparse ranges may be nonconformant now.
194                // std::swap_ranges (begin (), end (), mr.begin ());
195                vector_swap<scalar_swap> (*this, mr);
196            }
197        }
198        BOOST_UBLAS_INLINE
199        friend void swap (matrix_row mr1, matrix_row mr2) {
200            mr1.swap (mr2);
201        }
202
203        // Iterator types
204    private:
205        typedef typename M::const_iterator2 const_subiterator_type;
206        typedef typename boost::mpl::if_<boost::is_const<M>,
207                                          typename M::const_iterator2,
208                                          typename M::iterator2>::type subiterator_type;
209
210    public:
211#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
212        typedef indexed_iterator<matrix_row<matrix_type>,
213                                 typename subiterator_type::iterator_category> iterator;
214        typedef indexed_const_iterator<matrix_row<matrix_type>,
215                                       typename const_subiterator_type::iterator_category> const_iterator;
216#else
217        class const_iterator;
218        class iterator;
219#endif
220
221        // Element lookup
222        BOOST_UBLAS_INLINE
223        const_iterator find (size_type j) const {
224            const_subiterator_type it2 (data_.find2 (1, i_, j));
225#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
226            return const_iterator (*this, it2.index2 ());
227#else
228            return const_iterator (*this, it2);
229#endif
230        }
231        BOOST_UBLAS_INLINE
232        iterator find (size_type j) {
233            subiterator_type it2 (data_.find2 (1, i_, j));
234#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
235            return iterator (*this, it2.index2 ());
236#else
237            return iterator (*this, it2);
238#endif
239        }
240
241#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
242        class const_iterator:
243            public container_const_reference<matrix_row>,
244            public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
245                        iterator_base<const_iterator, value_type>::type {
246        public:
247            typedef typename const_subiterator_type::value_type value_type;
248            typedef typename const_subiterator_type::difference_type difference_type;
249            typedef typename const_subiterator_type::reference reference;
250            typedef typename const_subiterator_type::pointer pointer;
251
252            // Construction and destruction
253            BOOST_UBLAS_INLINE
254            const_iterator ():
255                container_const_reference<self_type> (), it_ () {}
256            BOOST_UBLAS_INLINE
257            const_iterator (const self_type &mr, const const_subiterator_type &it):
258                container_const_reference<self_type> (mr), it_ (it) {}
259            BOOST_UBLAS_INLINE
260            const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
261                container_const_reference<self_type> (it ()), it_ (it.it_) {}
262
263            // Arithmetic
264            BOOST_UBLAS_INLINE
265            const_iterator &operator ++ () {
266                ++ it_;
267                return *this;
268            }
269            BOOST_UBLAS_INLINE
270            const_iterator &operator -- () {
271                -- it_;
272                return *this;
273            }
274            BOOST_UBLAS_INLINE
275            const_iterator &operator += (difference_type n) {
276                it_ += n;
277                return *this;
278            }
279            BOOST_UBLAS_INLINE
280            const_iterator &operator -= (difference_type n) {
281                it_ -= n;
282                return *this;
283            }
284            BOOST_UBLAS_INLINE
285            difference_type operator - (const const_iterator &it) const {
286                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
287                return it_ - it.it_;
288            }
289
290            // Dereference
291            BOOST_UBLAS_INLINE
292            const_reference operator * () const {
293                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
294                return *it_;
295            }
296            BOOST_UBLAS_INLINE
297            const_reference operator [] (difference_type n) const {
298                return *(*this + n);
299            }
300
301            // Index
302            BOOST_UBLAS_INLINE
303            size_type index () const {
304                return it_.index2 ();
305            }
306
307            // Assignment
308            BOOST_UBLAS_INLINE
309            const_iterator &operator = (const const_iterator &it) {
310                container_const_reference<self_type>::assign (&it ());
311                it_ = it.it_;
312                return *this;
313            }
314
315            // Comparison
316            BOOST_UBLAS_INLINE
317            bool operator == (const const_iterator &it) const {
318                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
319                return it_ == it.it_;
320            }
321            BOOST_UBLAS_INLINE
322            bool operator < (const const_iterator &it) const {
323                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
324                return it_ < it.it_;
325            }
326
327        private:
328            const_subiterator_type it_;
329        };
330#endif
331
332        BOOST_UBLAS_INLINE
333        const_iterator begin () const {
334            return find (0);
335        }
336        BOOST_UBLAS_INLINE
337        const_iterator end () const {
338            return find (size ());
339        }
340
341#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
342        class iterator:
343            public container_reference<matrix_row>,
344            public iterator_base_traits<typename subiterator_type::iterator_category>::template
345                        iterator_base<iterator, value_type>::type {
346        public:
347            typedef typename subiterator_type::value_type value_type;
348            typedef typename subiterator_type::difference_type difference_type;
349            typedef typename subiterator_type::reference reference;
350            typedef typename subiterator_type::pointer pointer;
351
352            // Construction and destruction
353            BOOST_UBLAS_INLINE
354            iterator ():
355                container_reference<self_type> (), it_ () {}
356            BOOST_UBLAS_INLINE
357            iterator (self_type &mr, const subiterator_type &it):
358                container_reference<self_type> (mr), it_ (it) {}
359
360            // Arithmetic
361            BOOST_UBLAS_INLINE
362            iterator &operator ++ () {
363                ++ it_;
364                return *this;
365            }
366            BOOST_UBLAS_INLINE
367            iterator &operator -- () {
368                -- it_;
369                return *this;
370            }
371            BOOST_UBLAS_INLINE
372            iterator &operator += (difference_type n) {
373                it_ += n;
374                return *this;
375            }
376            BOOST_UBLAS_INLINE
377            iterator &operator -= (difference_type n) {
378                it_ -= n;
379                return *this;
380            }
381            BOOST_UBLAS_INLINE
382            difference_type operator - (const iterator &it) const {
383                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
384                return it_ - it.it_;
385            }
386
387            // Dereference
388            BOOST_UBLAS_INLINE
389            reference operator * () const {
390                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
391                return *it_;
392            }
393            BOOST_UBLAS_INLINE
394            reference operator [] (difference_type n) const {
395                return *(*this + n);
396            }
397
398            // Index
399            BOOST_UBLAS_INLINE
400            size_type index () const {
401                return it_.index2 ();
402            }
403
404            // Assignment
405            BOOST_UBLAS_INLINE
406            iterator &operator = (const iterator &it) {
407                container_reference<self_type>::assign (&it ());
408                it_ = it.it_;
409                return *this;
410            }
411
412            // Comparison
413            BOOST_UBLAS_INLINE
414            bool operator == (const iterator &it) const {
415                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
416                return it_ == it.it_;
417            }
418            BOOST_UBLAS_INLINE
419            bool operator < (const iterator &it) const {
420                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
421                return it_ < it.it_;
422            }
423
424        private:
425            subiterator_type it_;
426
427            friend class const_iterator;
428        };
429#endif
430
431        BOOST_UBLAS_INLINE
432        iterator begin () {
433            return find (0);
434        }
435        BOOST_UBLAS_INLINE
436        iterator end () {
437            return find (size ());
438        }
439
440        // Reverse iterator
441        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
442        typedef reverse_iterator_base<iterator> reverse_iterator;
443
444        BOOST_UBLAS_INLINE
445        const_reverse_iterator rbegin () const {
446            return const_reverse_iterator (end ());
447        }
448        BOOST_UBLAS_INLINE
449        const_reverse_iterator rend () const {
450            return const_reverse_iterator (begin ());
451        }
452        BOOST_UBLAS_INLINE
453        reverse_iterator rbegin () {
454            return reverse_iterator (end ());
455        }
456        BOOST_UBLAS_INLINE
457        reverse_iterator rend () {
458            return reverse_iterator (begin ());
459        }
460
461    private:
462        matrix_closure_type data_;
463        size_type i_;
464    };
465
466    // Projections
467    template<class M>
468    BOOST_UBLAS_INLINE
469    matrix_row<M> row (M &data, typename M::size_type i) {
470        return matrix_row<M> (data, i);
471    }
472    template<class M>
473    BOOST_UBLAS_INLINE
474    const matrix_row<const M> row (const M &data, typename M::size_type i) {
475        return matrix_row<const M> (data, i);
476    }
477
478    // Specialize temporary
479    template <class M>
480    struct vector_temporary_traits< matrix_row<M> >
481    : vector_temporary_traits< M > {} ;
482    template <class M>
483    struct vector_temporary_traits< const matrix_row<M> >
484    : vector_temporary_traits< M > {} ;
485
486    // Matrix based column vector class
487    template<class M>
488    class matrix_column:
489        public vector_expression<matrix_column<M> > {
490
491        typedef matrix_column<M> self_type;
492    public:
493#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
494        using vector_expression<self_type>::operator ();
495#endif
496        typedef M matrix_type;
497        typedef typename M::size_type size_type;
498        typedef typename M::difference_type difference_type;
499        typedef typename M::value_type value_type;
500        typedef typename M::const_reference const_reference;
501        typedef typename boost::mpl::if_<boost::is_const<M>,
502                                          typename M::const_reference,
503                                          typename M::reference>::type reference;
504        typedef typename boost::mpl::if_<boost::is_const<M>,
505                                          typename M::const_closure_type,
506                                          typename M::closure_type>::type matrix_closure_type;
507        typedef const self_type const_closure_type;
508        typedef self_type closure_type;
509        typedef typename storage_restrict_traits<typename M::storage_category,
510                                                 dense_proxy_tag>::storage_category storage_category;
511
512        // Construction and destruction
513        BOOST_UBLAS_INLINE
514        matrix_column (matrix_type &data, size_type j):
515            data_ (data), j_ (j) {
516            // Early checking of preconditions here.
517            // BOOST_UBLAS_CHECK (j_ < data_.size2 (), bad_index ());
518        }
519
520        // Accessors
521        BOOST_UBLAS_INLINE
522        size_type size () const {
523            return data_.size1 ();
524        }
525        BOOST_UBLAS_INLINE
526        size_type index () const {
527            return j_;
528        }
529
530        // Storage accessors
531        BOOST_UBLAS_INLINE
532        const matrix_closure_type &data () const {
533            return data_;
534        }
535        BOOST_UBLAS_INLINE
536        matrix_closure_type &data () {
537            return data_;
538        }
539
540        // Element access
541#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
542        BOOST_UBLAS_INLINE
543        const_reference operator () (size_type i) const {
544            return data_ (i, j_);
545        }
546        BOOST_UBLAS_INLINE
547        reference operator () (size_type i) {
548            return data_ (i, j_);
549        }
550
551        BOOST_UBLAS_INLINE
552        const_reference operator [] (size_type i) const {
553            return (*this) (i);
554        }
555        BOOST_UBLAS_INLINE
556        reference operator [] (size_type i) {
557            return (*this) (i);
558        }
559#else
560        BOOST_UBLAS_INLINE
561        reference operator () (size_type i) const {
562            return data_ (i, j_);
563        }
564
565        BOOST_UBLAS_INLINE
566        reference operator [] (size_type i) const {
567            return (*this) (i);
568        }
569#endif
570
571        // Assignment
572        BOOST_UBLAS_INLINE
573        matrix_column &operator = (const matrix_column &mc) {
574            // ISSUE need a temporary, proxy can be overlaping alias
575            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mc));
576            return *this;
577        }
578        BOOST_UBLAS_INLINE
579        matrix_column &assign_temporary (matrix_column &mc) {
580            // assign elements, proxied container remains the same
581            vector_assign<scalar_assign> (*this, mc);
582            return *this;
583        }
584        template<class AE>
585        BOOST_UBLAS_INLINE
586        matrix_column &operator = (const vector_expression<AE> &ae) {
587            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
588            return *this;
589        }
590        template<class AE>
591        BOOST_UBLAS_INLINE
592        matrix_column &assign (const vector_expression<AE> &ae) {
593            vector_assign<scalar_assign> (*this, ae);
594            return *this;
595        }
596        template<class AE>
597        BOOST_UBLAS_INLINE
598        matrix_column &operator += (const vector_expression<AE> &ae) {
599            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
600            return *this;
601        }
602        template<class AE>
603        BOOST_UBLAS_INLINE
604        matrix_column &plus_assign (const vector_expression<AE> &ae) {
605            vector_assign<scalar_plus_assign> (*this, ae);
606            return *this;
607        }
608        template<class AE>
609        BOOST_UBLAS_INLINE
610        matrix_column &operator -= (const vector_expression<AE> &ae) {
611            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
612            return *this;
613        }
614        template<class AE>
615        BOOST_UBLAS_INLINE
616        matrix_column &minus_assign (const vector_expression<AE> &ae) {
617            vector_assign<scalar_minus_assign> (*this, ae);
618            return *this;
619        }
620        template<class AT>
621        BOOST_UBLAS_INLINE
622        matrix_column &operator *= (const AT &at) {
623            vector_assign_scalar<scalar_multiplies_assign> (*this, at);
624            return *this;
625        }
626        template<class AT>
627        BOOST_UBLAS_INLINE
628        matrix_column &operator /= (const AT &at) {
629            vector_assign_scalar<scalar_divides_assign> (*this, at);
630            return *this;
631        }
632
633        // Closure comparison
634        BOOST_UBLAS_INLINE
635        bool same_closure (const matrix_column &mc) const {
636            return (*this).data_.same_closure (mc.data_);
637        }
638
639        // Comparison
640        BOOST_UBLAS_INLINE
641        bool operator == (const matrix_column &mc) const {
642            return (*this).data_ == mc.data_ && index () == mc.index ();
643        }
644
645        // Swapping
646        BOOST_UBLAS_INLINE
647        void swap (matrix_column mc) {
648            if (this != &mc) {
649                BOOST_UBLAS_CHECK (size () == mc.size (), bad_size ());
650                // Sparse ranges may be nonconformant now.
651                // std::swap_ranges (begin (), end (), mc.begin ());
652                vector_swap<scalar_swap> (*this, mc);
653            }
654        }
655        BOOST_UBLAS_INLINE
656        friend void swap (matrix_column mc1, matrix_column mc2) {
657            mc1.swap (mc2);
658        }
659
660        // Iterator types
661    private:
662        typedef typename M::const_iterator1 const_subiterator_type;
663        typedef typename boost::mpl::if_<boost::is_const<M>,
664                                          typename M::const_iterator1,
665                                          typename M::iterator1>::type subiterator_type;
666
667    public:
668#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
669        typedef indexed_iterator<matrix_column<matrix_type>,
670                                 typename subiterator_type::iterator_category> iterator;
671        typedef indexed_const_iterator<matrix_column<matrix_type>,
672                                       typename const_subiterator_type::iterator_category> const_iterator;
673#else
674        class const_iterator;
675        class iterator;
676#endif
677
678        // Element lookup
679        BOOST_UBLAS_INLINE
680        const_iterator find (size_type i) const {
681            const_subiterator_type it1 (data_.find1 (1, i, j_));
682#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
683            return const_iterator (*this, it1.index1 ());
684#else
685            return const_iterator (*this, it1);
686#endif
687        }
688        BOOST_UBLAS_INLINE
689        iterator find (size_type i) {
690            subiterator_type it1 (data_.find1 (1, i, j_));
691#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
692            return iterator (*this, it1.index1 ());
693#else
694            return iterator (*this, it1);
695#endif
696        }
697
698#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
699        class const_iterator:
700            public container_const_reference<matrix_column>,
701            public iterator_base_traits<typename const_subiterator_type::iterator_category>::template
702                        iterator_base<const_iterator, value_type>::type {
703        public:
704            typedef typename const_subiterator_type::value_type value_type;
705            typedef typename const_subiterator_type::difference_type difference_type;
706            typedef typename const_subiterator_type::reference reference;
707            typedef typename const_subiterator_type::pointer pointer;
708
709            // Construction and destruction
710            BOOST_UBLAS_INLINE
711            const_iterator ():
712                container_const_reference<self_type> (), it_ () {}
713            BOOST_UBLAS_INLINE
714            const_iterator (const self_type &mc, const const_subiterator_type &it):
715                container_const_reference<self_type> (mc), it_ (it) {}
716            BOOST_UBLAS_INLINE
717            const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
718                container_const_reference<self_type> (it ()), it_ (it.it_) {}
719
720            // Arithmetic
721            BOOST_UBLAS_INLINE
722            const_iterator &operator ++ () {
723                ++ it_;
724                return *this;
725            }
726            BOOST_UBLAS_INLINE
727            const_iterator &operator -- () {
728                -- it_;
729                return *this;
730            }
731            BOOST_UBLAS_INLINE
732            const_iterator &operator += (difference_type n) {
733                it_ += n;
734                return *this;
735            }
736            BOOST_UBLAS_INLINE
737            const_iterator &operator -= (difference_type n) {
738                it_ -= n;
739                return *this;
740            }
741            BOOST_UBLAS_INLINE
742            difference_type operator - (const const_iterator &it) const {
743                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
744                return it_ - it.it_;
745            }
746
747            // Dereference
748            BOOST_UBLAS_INLINE
749            const_reference operator * () const {
750                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
751                return *it_;
752            }
753            BOOST_UBLAS_INLINE
754            const_reference operator [] (difference_type n) const {
755                return *(*this + n);
756            }
757
758            // Index
759            BOOST_UBLAS_INLINE
760            size_type index () const {
761                return it_.index1 ();
762            }
763
764            // Assignment
765            BOOST_UBLAS_INLINE
766            const_iterator &operator = (const const_iterator &it) {
767                container_const_reference<self_type>::assign (&it ());
768                it_ = it.it_;
769                return *this;
770            }
771
772            // Comparison
773            BOOST_UBLAS_INLINE
774            bool operator == (const const_iterator &it) const {
775                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
776                return it_ == it.it_;
777            }
778            BOOST_UBLAS_INLINE
779            bool operator < (const const_iterator &it) const {
780                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
781                return it_ < it.it_;
782            }
783
784        private:
785            const_subiterator_type it_;
786        };
787#endif
788
789        BOOST_UBLAS_INLINE
790        const_iterator begin () const {
791            return find (0);
792        }
793        BOOST_UBLAS_INLINE
794        const_iterator end () const {
795            return find (size ());
796        }
797
798#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
799        class iterator:
800            public container_reference<matrix_column>,
801            public iterator_base_traits<typename subiterator_type::iterator_category>::template
802                        iterator_base<iterator, value_type>::type {
803        public:
804            typedef typename subiterator_type::value_type value_type;
805            typedef typename subiterator_type::difference_type difference_type;
806            typedef typename subiterator_type::reference reference;
807            typedef typename subiterator_type::pointer pointer;
808
809            // Construction and destruction
810            BOOST_UBLAS_INLINE
811            iterator ():
812                container_reference<self_type> (), it_ () {}
813            BOOST_UBLAS_INLINE
814            iterator (self_type &mc, const subiterator_type &it):
815                container_reference<self_type> (mc), it_ (it) {}
816
817            // Arithmetic
818            BOOST_UBLAS_INLINE
819            iterator &operator ++ () {
820                ++ it_;
821                return *this;
822            }
823            BOOST_UBLAS_INLINE
824            iterator &operator -- () {
825                -- it_;
826                return *this;
827            }
828            BOOST_UBLAS_INLINE
829            iterator &operator += (difference_type n) {
830                it_ += n;
831                return *this;
832            }
833            BOOST_UBLAS_INLINE
834            iterator &operator -= (difference_type n) {
835                it_ -= n;
836                return *this;
837            }
838            BOOST_UBLAS_INLINE
839            difference_type operator - (const iterator &it) const {
840                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
841                return it_ - it.it_;
842            }
843
844            // Dereference
845            BOOST_UBLAS_INLINE
846            reference operator * () const {
847                BOOST_UBLAS_CHECK (index () < (*this) ().size (), bad_index ());
848                return *it_;
849            }
850            BOOST_UBLAS_INLINE
851            reference operator [] (difference_type n) const {
852                return *(*this + n);
853            }
854
855            // Index
856            BOOST_UBLAS_INLINE
857            size_type index () const {
858                return it_.index1 ();
859            }
860
861            // Assignment
862            BOOST_UBLAS_INLINE
863            iterator &operator = (const iterator &it) {
864                container_reference<self_type>::assign (&it ());
865                it_ = it.it_;
866                return *this;
867            }
868
869            // Comparison
870            BOOST_UBLAS_INLINE
871            bool operator == (const iterator &it) const {
872                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
873                return it_ == it.it_;
874            }
875            BOOST_UBLAS_INLINE
876            bool operator < (const iterator &it) const {
877                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
878                return it_ < it.it_;
879            }
880
881        private:
882            subiterator_type it_;
883
884            friend class const_iterator;
885        };
886#endif
887
888        BOOST_UBLAS_INLINE
889        iterator begin () {
890            return find (0);
891        }
892        BOOST_UBLAS_INLINE
893        iterator end () {
894            return find (size ());
895        }
896
897        // Reverse iterator
898        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
899        typedef reverse_iterator_base<iterator> reverse_iterator;
900
901        BOOST_UBLAS_INLINE
902        const_reverse_iterator rbegin () const {
903            return const_reverse_iterator (end ());
904        }
905        BOOST_UBLAS_INLINE
906        const_reverse_iterator rend () const {
907            return const_reverse_iterator (begin ());
908        }
909        reverse_iterator rbegin () {
910            return reverse_iterator (end ());
911        }
912        BOOST_UBLAS_INLINE
913        reverse_iterator rend () {
914            return reverse_iterator (begin ());
915        }
916
917    private:
918        matrix_closure_type data_;
919        size_type j_;
920    };
921
922    // Projections
923    template<class M>
924    BOOST_UBLAS_INLINE
925    matrix_column<M> column (M &data, typename M::size_type j) {
926        return matrix_column<M> (data, j);
927    }
928    template<class M>
929    BOOST_UBLAS_INLINE
930    const matrix_column<const M> column (const M &data, typename M::size_type j) {
931        return matrix_column<const M> (data, j);
932    }
933
934    // Specialize temporary
935    template <class M>
936    struct vector_temporary_traits< matrix_column<M> >
937    : vector_temporary_traits< M > {} ;
938    template <class M>
939    struct vector_temporary_traits< const matrix_column<M> >
940    : vector_temporary_traits< M > {} ;
941
942    // Matrix based vector range class
943    template<class M>
944    class matrix_vector_range:
945        public vector_expression<matrix_vector_range<M> > {
946
947        typedef matrix_vector_range<M> self_type;
948    public:
949#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
950        using vector_expression<self_type>::operator ();
951#endif
952        typedef M matrix_type;
953        typedef typename M::size_type size_type;
954        typedef typename M::difference_type difference_type;
955        typedef typename M::value_type value_type;
956        typedef typename M::const_reference const_reference;
957        typedef typename boost::mpl::if_<boost::is_const<M>,
958                                          typename M::const_reference,
959                                          typename M::reference>::type reference;
960        typedef typename boost::mpl::if_<boost::is_const<M>,
961                                          typename M::const_closure_type,
962                                          typename M::closure_type>::type matrix_closure_type;
963        typedef basic_range<size_type, difference_type> range_type;
964        typedef const self_type const_closure_type;
965        typedef self_type closure_type;
966        typedef typename storage_restrict_traits<typename M::storage_category,
967                                                 dense_proxy_tag>::storage_category storage_category;
968
969        // Construction and destruction
970        BOOST_UBLAS_INLINE
971        matrix_vector_range (matrix_type &data, const range_type &r1, const range_type &r2):
972            data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {
973            // Early checking of preconditions here.
974            // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
975            //                     r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
976            // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
977            //                   r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
978            // BOOST_UBLAS_CHECK (r1_.size () == r2_.size (), bad_size ());
979        }
980
981        // Accessors
982        BOOST_UBLAS_INLINE
983        size_type start1 () const {
984            return r1_.start ();
985        }
986        BOOST_UBLAS_INLINE
987        size_type start2 () const {
988            return r2_.start ();
989        }
990        BOOST_UBLAS_INLINE
991        size_type size () const {
992            return BOOST_UBLAS_SAME (r1_.size (), r2_.size ());
993        }
994
995        // Storage accessors
996        BOOST_UBLAS_INLINE
997        const matrix_closure_type &data () const {
998            return data_;
999        }
1000        BOOST_UBLAS_INLINE
1001        matrix_closure_type &data () {
1002            return data_;
1003        }
1004
1005        // Element access
1006#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1007        BOOST_UBLAS_INLINE
1008        const_reference operator () (size_type i) const {
1009            return data_ (r1_ (i), r2_ (i));
1010        }
1011        BOOST_UBLAS_INLINE
1012        reference operator () (size_type i) {
1013            return data_ (r1_ (i), r2_ (i));
1014        }
1015
1016        BOOST_UBLAS_INLINE
1017        const_reference operator [] (size_type i) const {
1018            return (*this) (i);
1019        }
1020        BOOST_UBLAS_INLINE
1021        reference operator [] (size_type i) {
1022            return (*this) (i);
1023        }
1024#else
1025        BOOST_UBLAS_INLINE
1026        reference operator () (size_type i) const {
1027            return data_ (r1_ (i), r2_ (i));
1028        }
1029
1030        BOOST_UBLAS_INLINE
1031        reference operator [] (size_type i) const {
1032            return (*this) (i);
1033        }
1034#endif
1035
1036        // Assignment
1037        BOOST_UBLAS_INLINE
1038        matrix_vector_range &operator = (const matrix_vector_range &mvr) {
1039            // ISSUE need a temporary, proxy can be overlaping alias
1040            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvr));
1041            return *this;
1042        }
1043        BOOST_UBLAS_INLINE
1044        matrix_vector_range &assign_temporary (matrix_vector_range &mvr) {
1045            // assign elements, proxied container remains the same
1046            vector_assign<scalar_assign> (*this, mvr);
1047            return *this;
1048        }
1049        template<class AE>
1050        BOOST_UBLAS_INLINE
1051        matrix_vector_range &operator = (const vector_expression<AE> &ae) {
1052            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
1053            return *this;
1054        }
1055        template<class AE>
1056        BOOST_UBLAS_INLINE
1057        matrix_vector_range &assign (const vector_expression<AE> &ae) {
1058            vector_assign<scalar_assign> (*this, ae);
1059            return *this;
1060        }
1061        template<class AE>
1062        BOOST_UBLAS_INLINE
1063        matrix_vector_range &operator += (const vector_expression<AE> &ae) {
1064            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
1065            return *this;
1066        }
1067        template<class AE>
1068        BOOST_UBLAS_INLINE
1069        matrix_vector_range &plus_assign (const vector_expression<AE> &ae) {
1070            vector_assign<scalar_plus_assign> (*this, ae);
1071            return *this;
1072        }
1073        template<class AE>
1074        BOOST_UBLAS_INLINE
1075        matrix_vector_range &operator -= (const vector_expression<AE> &ae) {
1076            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
1077            return *this;
1078        }
1079        template<class AE>
1080        BOOST_UBLAS_INLINE
1081        matrix_vector_range &minus_assign (const vector_expression<AE> &ae) {
1082            vector_assign<scalar_minus_assign> (*this, ae);
1083            return *this;
1084        }
1085        template<class AT>
1086        BOOST_UBLAS_INLINE
1087        matrix_vector_range &operator *= (const AT &at) {
1088            vector_assign_scalar<scalar_multiplies_assign> (*this, at);
1089            return *this;
1090        }
1091        template<class AT>
1092        BOOST_UBLAS_INLINE
1093        matrix_vector_range &operator /= (const AT &at) {
1094            vector_assign_scalar<scalar_divides_assign> (*this, at);
1095            return *this;
1096        }
1097
1098        // Closure comparison
1099        BOOST_UBLAS_INLINE
1100        bool same_closure (const matrix_vector_range &mvr) const {
1101            return (*this).data_.same_closure (mvr.data_);
1102        }
1103
1104        // Comparison
1105        BOOST_UBLAS_INLINE
1106        bool operator == (const matrix_vector_range &mvr) const {
1107            return (*this).data_ == mvr.data_ && r1_ == mvr.r1_ && r2_ == mvr.r2_;
1108        }
1109
1110        // Swapping
1111        BOOST_UBLAS_INLINE
1112        void swap (matrix_vector_range mvr) {
1113            if (this != &mvr) {
1114                BOOST_UBLAS_CHECK (size () == mvr.size (), bad_size ());
1115                // Sparse ranges may be nonconformant now.
1116                // std::swap_ranges (begin (), end (), mvr.begin ());
1117                vector_swap<scalar_swap> (*this, mvr);
1118            }
1119        }
1120        BOOST_UBLAS_INLINE
1121        friend void swap (matrix_vector_range mvr1, matrix_vector_range mvr2) {
1122            mvr1.swap (mvr2);
1123        }
1124
1125        // Iterator types
1126    private:
1127        // Use range as an index - FIXME this fails for packed assignment
1128        typedef typename range_type::const_iterator const_subiterator1_type;
1129        typedef typename range_type::const_iterator subiterator1_type;
1130        typedef typename range_type::const_iterator const_subiterator2_type;
1131        typedef typename range_type::const_iterator subiterator2_type;
1132
1133    public:
1134        class const_iterator;
1135        class iterator;
1136
1137        // Element lookup
1138        BOOST_UBLAS_INLINE
1139        const_iterator find (size_type i) const {
1140            return const_iterator (*this, r1_.begin () + i, r2_.begin () + i);
1141        }
1142        BOOST_UBLAS_INLINE
1143        iterator find (size_type i) {
1144            return iterator (*this, r1_.begin () + i, r2_.begin () + i);
1145        }
1146
1147        class const_iterator:
1148            public container_const_reference<matrix_vector_range>,
1149            public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
1150                        iterator_base<const_iterator, value_type>::type {
1151        public:
1152            // FIXME Iterator can never be different code was:
1153            // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
1154            BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
1155
1156            typedef typename matrix_vector_range::value_type value_type;
1157            typedef typename matrix_vector_range::difference_type difference_type;
1158            typedef typename matrix_vector_range::const_reference reference;
1159            typedef const typename matrix_vector_range::value_type *pointer;
1160
1161            // Construction and destruction
1162            BOOST_UBLAS_INLINE
1163            const_iterator ():
1164                container_const_reference<self_type> (), it1_ (), it2_ () {}
1165            BOOST_UBLAS_INLINE
1166            const_iterator (const self_type &mvr, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
1167                container_const_reference<self_type> (mvr), it1_ (it1), it2_ (it2) {}
1168            BOOST_UBLAS_INLINE
1169            const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
1170                container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
1171
1172            // Arithmetic
1173            BOOST_UBLAS_INLINE
1174            const_iterator &operator ++ () {
1175                ++ it1_;
1176                ++ it2_;
1177                return *this;
1178            }
1179            BOOST_UBLAS_INLINE
1180            const_iterator &operator -- () {
1181                -- it1_;
1182                -- it2_;
1183                return *this;
1184            }
1185            BOOST_UBLAS_INLINE
1186            const_iterator &operator += (difference_type n) {
1187                it1_ += n;
1188                it2_ += n;
1189                return *this;
1190            }
1191            BOOST_UBLAS_INLINE
1192            const_iterator &operator -= (difference_type n) {
1193                it1_ -= n;
1194                it2_ -= n;
1195                return *this;
1196            }
1197            BOOST_UBLAS_INLINE
1198            difference_type operator - (const const_iterator &it) const {
1199                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
1200                return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
1201            }
1202
1203            // Dereference
1204            BOOST_UBLAS_INLINE
1205            const_reference operator * () const {
1206                // FIXME replace find with at_element
1207                return (*this) ().data_ (*it1_, *it2_);
1208            }
1209            BOOST_UBLAS_INLINE
1210            const_reference operator [] (difference_type n) const {
1211                return *(*this + n);
1212            }
1213
1214            // Index
1215            BOOST_UBLAS_INLINE
1216            size_type  index () const {
1217                return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
1218            }
1219
1220            // Assignment
1221            BOOST_UBLAS_INLINE
1222            const_iterator &operator = (const const_iterator &it) {
1223                container_const_reference<self_type>::assign (&it ());
1224                it1_ = it.it1_;
1225                it2_ = it.it2_;
1226                return *this;
1227            }
1228
1229            // Comparison
1230            BOOST_UBLAS_INLINE
1231            bool operator == (const const_iterator &it) const {
1232                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1233                return it1_ == it.it1_ && it2_ == it.it2_;
1234            }
1235            BOOST_UBLAS_INLINE
1236            bool operator < (const const_iterator &it) const {
1237                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1238                return it1_ < it.it1_ && it2_ < it.it2_;
1239            }
1240
1241        private:
1242            const_subiterator1_type it1_;
1243            const_subiterator2_type it2_;
1244        };
1245
1246        BOOST_UBLAS_INLINE
1247        const_iterator begin () const {
1248            return find (0);
1249        }
1250        BOOST_UBLAS_INLINE
1251        const_iterator end () const {
1252            return find (size ());
1253        }
1254
1255        class iterator:
1256            public container_reference<matrix_vector_range>,
1257            public iterator_base_traits<typename M::iterator1::iterator_category>::template
1258                        iterator_base<iterator, value_type>::type {
1259        public:
1260            // FIXME Iterator can never be different code was:
1261            // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
1262            BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
1263
1264            typedef typename matrix_vector_range::value_type value_type;
1265            typedef typename matrix_vector_range::difference_type difference_type;
1266            typedef typename matrix_vector_range::reference reference;
1267            typedef typename matrix_vector_range::value_type *pointer;
1268
1269            // Construction and destruction
1270            BOOST_UBLAS_INLINE
1271            iterator ():
1272                container_reference<self_type> (), it1_ (), it2_ () {}
1273            BOOST_UBLAS_INLINE
1274            iterator (self_type &mvr, const subiterator1_type &it1, const subiterator2_type &it2):
1275                container_reference<self_type> (mvr), it1_ (it1), it2_ (it2) {}
1276
1277            // Arithmetic
1278            BOOST_UBLAS_INLINE
1279            iterator &operator ++ () {
1280                ++ it1_;
1281                ++ it2_;
1282                return *this;
1283            }
1284            BOOST_UBLAS_INLINE
1285            iterator &operator -- () {
1286                -- it1_;
1287                -- it2_;
1288                return *this;
1289            }
1290            BOOST_UBLAS_INLINE
1291            iterator &operator += (difference_type n) {
1292                it1_ += n;
1293                it2_ += n;
1294                return *this;
1295            }
1296            BOOST_UBLAS_INLINE
1297            iterator &operator -= (difference_type n) {
1298                it1_ -= n;
1299                it2_ -= n;
1300                return *this;
1301            }
1302            BOOST_UBLAS_INLINE
1303            difference_type operator - (const iterator &it) const {
1304                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
1305                return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
1306            }
1307
1308            // Dereference
1309            BOOST_UBLAS_INLINE
1310            reference operator * () const {
1311                // FIXME replace find with at_element
1312                return (*this) ().data_ (*it1_, *it2_);
1313            }
1314            BOOST_UBLAS_INLINE
1315            reference operator [] (difference_type n) const {
1316                return *(*this + n);
1317            }
1318
1319            // Index
1320            BOOST_UBLAS_INLINE
1321            size_type index () const {
1322                return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
1323            }
1324
1325            // Assignment
1326            BOOST_UBLAS_INLINE
1327            iterator &operator = (const iterator &it) {
1328                container_reference<self_type>::assign (&it ());
1329                it1_ = it.it1_;
1330                it2_ = it.it2_;
1331                return *this;
1332            }
1333
1334            // Comparison
1335            BOOST_UBLAS_INLINE
1336            bool operator == (const iterator &it) const {
1337                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1338                return it1_ == it.it1_ && it2_ == it.it2_;
1339            }
1340            BOOST_UBLAS_INLINE
1341            bool operator < (const iterator &it) const {
1342                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1343                return it1_ < it.it1_ && it2_ < it.it2_;
1344            }
1345
1346        private:
1347            subiterator1_type it1_;
1348            subiterator2_type it2_;
1349
1350            friend class const_iterator;
1351        };
1352
1353        BOOST_UBLAS_INLINE
1354        iterator begin () {
1355            return find (0);
1356        }
1357        BOOST_UBLAS_INLINE
1358        iterator end () {
1359            return find (size ());
1360        }
1361
1362        // Reverse iterator
1363        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1364        typedef reverse_iterator_base<iterator> reverse_iterator;
1365
1366        BOOST_UBLAS_INLINE
1367        const_reverse_iterator rbegin () const {
1368            return const_reverse_iterator (end ());
1369        }
1370        BOOST_UBLAS_INLINE
1371        const_reverse_iterator rend () const {
1372            return const_reverse_iterator (begin ());
1373        }
1374        BOOST_UBLAS_INLINE
1375        reverse_iterator rbegin () {
1376            return reverse_iterator (end ());
1377        }
1378        BOOST_UBLAS_INLINE
1379        reverse_iterator rend () {
1380            return reverse_iterator (begin ());
1381        }
1382
1383    private:
1384        matrix_closure_type data_;
1385        range_type r1_;
1386        range_type r2_;
1387    };
1388
1389    // Specialize temporary
1390    template <class M>
1391    struct vector_temporary_traits< matrix_vector_range<M> >
1392    : vector_temporary_traits< M > {} ;
1393    template <class M>
1394    struct vector_temporary_traits< const matrix_vector_range<M> >
1395    : vector_temporary_traits< M > {} ;
1396
1397    // Matrix based vector slice class
1398    template<class M>
1399    class matrix_vector_slice:
1400        public vector_expression<matrix_vector_slice<M> > {
1401
1402        typedef matrix_vector_slice<M> self_type;
1403    public:
1404#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1405        using vector_expression<self_type>::operator ();
1406#endif
1407        typedef M matrix_type;
1408        typedef typename M::size_type size_type;
1409        typedef typename M::difference_type difference_type;
1410        typedef typename M::value_type value_type;
1411        typedef typename M::const_reference const_reference;
1412        typedef typename boost::mpl::if_<boost::is_const<M>,
1413                                          typename M::const_reference,
1414                                          typename M::reference>::type reference;
1415        typedef typename boost::mpl::if_<boost::is_const<M>,
1416                                          typename M::const_closure_type,
1417                                          typename M::closure_type>::type matrix_closure_type;
1418        typedef basic_range<size_type, difference_type> range_type;
1419        typedef basic_slice<size_type, difference_type> slice_type;
1420        typedef const self_type const_closure_type;
1421        typedef self_type closure_type;
1422        typedef typename storage_restrict_traits<typename M::storage_category,
1423                                                 dense_proxy_tag>::storage_category storage_category;
1424
1425        // Construction and destruction
1426        BOOST_UBLAS_INLINE
1427        matrix_vector_slice (matrix_type &data, const slice_type &s1, const slice_type &s2):
1428            data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {
1429            // Early checking of preconditions here.
1430            // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
1431            //                    s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
1432            // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
1433            //                    s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
1434        }
1435
1436        // Accessors
1437        BOOST_UBLAS_INLINE
1438        size_type start1 () const {
1439            return s1_.start ();
1440        }
1441        BOOST_UBLAS_INLINE
1442        size_type start2 () const {
1443            return s2_.start ();
1444        }
1445        BOOST_UBLAS_INLINE
1446        difference_type stride1 () const {
1447            return s1_.stride ();
1448        }
1449        BOOST_UBLAS_INLINE
1450        difference_type stride2 () const {
1451            return s2_.stride ();
1452        }
1453        BOOST_UBLAS_INLINE
1454        size_type size () const {
1455            return BOOST_UBLAS_SAME (s1_.size (), s2_.size ());
1456        }
1457
1458        // Storage accessors
1459        BOOST_UBLAS_INLINE
1460        const matrix_closure_type &data () const {
1461            return data_;
1462        }
1463        BOOST_UBLAS_INLINE
1464        matrix_closure_type &data () {
1465            return data_;
1466        }
1467
1468        // Element access
1469#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1470        BOOST_UBLAS_INLINE
1471        const_reference operator () (size_type i) const {
1472            return data_ (s1_ (i), s2_ (i));
1473        }
1474        BOOST_UBLAS_INLINE
1475        reference operator () (size_type i) {
1476            return data_ (s1_ (i), s2_ (i));
1477        }
1478
1479        BOOST_UBLAS_INLINE
1480        const_reference operator [] (size_type i) const {
1481            return (*this) (i);
1482        }
1483        BOOST_UBLAS_INLINE
1484        reference operator [] (size_type i) {
1485            return (*this) (i);
1486        }
1487#else
1488        BOOST_UBLAS_INLINE
1489        reference operator () (size_type i) const {
1490            return data_ (s1_ (i), s2_ (i));
1491        }
1492
1493        BOOST_UBLAS_INLINE
1494        reference operator [] (size_type i) const {
1495            return (*this) (i);
1496        }
1497#endif
1498
1499        // Assignment
1500        BOOST_UBLAS_INLINE
1501        matrix_vector_slice &operator = (const matrix_vector_slice &mvs) {
1502            // ISSUE need a temporary, proxy can be overlaping alias
1503            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvs));
1504            return *this;
1505        }
1506        BOOST_UBLAS_INLINE
1507        matrix_vector_slice &assign_temporary (matrix_vector_slice &mvs) {
1508            // assign elements, proxied container remains the same
1509            vector_assign<scalar_assign> (*this, mvs);
1510            return *this;
1511        }
1512        template<class AE>
1513        BOOST_UBLAS_INLINE
1514        matrix_vector_slice &operator = (const vector_expression<AE> &ae) {
1515            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
1516            return *this;
1517        }
1518        template<class AE>
1519        BOOST_UBLAS_INLINE
1520        matrix_vector_slice &assign (const vector_expression<AE> &ae) {
1521            vector_assign<scalar_assign> (*this, ae);
1522            return *this;
1523        }
1524        template<class AE>
1525        BOOST_UBLAS_INLINE
1526        matrix_vector_slice &operator += (const vector_expression<AE> &ae) {
1527            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
1528            return *this;
1529        }
1530        template<class AE>
1531        BOOST_UBLAS_INLINE
1532        matrix_vector_slice &plus_assign (const vector_expression<AE> &ae) {
1533            vector_assign<scalar_plus_assign> (*this, ae);
1534            return *this;
1535        }
1536        template<class AE>
1537        BOOST_UBLAS_INLINE
1538        matrix_vector_slice &operator -= (const vector_expression<AE> &ae) {
1539            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
1540            return *this;
1541        }
1542        template<class AE>
1543        BOOST_UBLAS_INLINE
1544        matrix_vector_slice &minus_assign (const vector_expression<AE> &ae) {
1545            vector_assign<scalar_minus_assign> (*this, ae);
1546            return *this;
1547        }
1548        template<class AT>
1549        BOOST_UBLAS_INLINE
1550        matrix_vector_slice &operator *= (const AT &at) {
1551            vector_assign_scalar<scalar_multiplies_assign> (*this, at);
1552            return *this;
1553        }
1554        template<class AT>
1555        BOOST_UBLAS_INLINE
1556        matrix_vector_slice &operator /= (const AT &at) {
1557            vector_assign_scalar<scalar_divides_assign> (*this, at);
1558            return *this;
1559        }
1560
1561        // Closure comparison
1562        BOOST_UBLAS_INLINE
1563        bool same_closure (const matrix_vector_slice &mvs) const {
1564            return (*this).data_.same_closure (mvs.data_);
1565        }
1566
1567        // Comparison
1568        BOOST_UBLAS_INLINE
1569        bool operator == (const matrix_vector_slice &mvs) const {
1570            return (*this).data_ == mvs.data_ && s1_ == mvs.s1_ && s2_ == mvs.s2_;
1571        }
1572
1573        // Swapping
1574        BOOST_UBLAS_INLINE
1575        void swap (matrix_vector_slice mvs) {
1576            if (this != &mvs) {
1577                BOOST_UBLAS_CHECK (size () == mvs.size (), bad_size ());
1578                // Sparse ranges may be nonconformant now.
1579                // std::swap_ranges (begin (), end (), mvs.begin ());
1580                vector_swap<scalar_swap> (*this, mvs);
1581            }
1582        }
1583        BOOST_UBLAS_INLINE
1584        friend void swap (matrix_vector_slice mvs1, matrix_vector_slice mvs2) {
1585            mvs1.swap (mvs2);
1586        }
1587
1588        // Iterator types
1589    private:
1590        // Use slice as an index - FIXME this fails for packed assignment
1591        typedef typename slice_type::const_iterator const_subiterator1_type;
1592        typedef typename slice_type::const_iterator subiterator1_type;
1593        typedef typename slice_type::const_iterator const_subiterator2_type;
1594        typedef typename slice_type::const_iterator subiterator2_type;
1595
1596    public:
1597        class const_iterator;
1598        class iterator;
1599
1600        // Element lookup
1601        BOOST_UBLAS_INLINE
1602        const_iterator find (size_type i) const {
1603            return const_iterator (*this, s1_.begin () + i, s2_.begin () + i);
1604        }
1605        BOOST_UBLAS_INLINE
1606        iterator find (size_type i) {
1607            return iterator (*this, s1_.begin () + i, s2_.begin () + i);
1608        }
1609
1610        // Iterators simply are indices.
1611
1612        class const_iterator:
1613            public container_const_reference<matrix_vector_slice>,
1614            public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
1615                        iterator_base<const_iterator, value_type>::type {
1616        public:
1617            // FIXME Iterator can never be different code was:
1618            // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
1619            BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
1620
1621            typedef typename matrix_vector_slice::value_type value_type;
1622            typedef typename matrix_vector_slice::difference_type difference_type;
1623            typedef typename matrix_vector_slice::const_reference reference;
1624            typedef const typename matrix_vector_slice::value_type *pointer;
1625
1626            // Construction and destruction
1627            BOOST_UBLAS_INLINE
1628            const_iterator ():
1629                container_const_reference<self_type> (), it1_ (), it2_ () {}
1630            BOOST_UBLAS_INLINE
1631            const_iterator (const self_type &mvs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
1632                container_const_reference<self_type> (mvs), it1_ (it1), it2_ (it2) {}
1633            BOOST_UBLAS_INLINE
1634            const_iterator (const typename self_type::iterator &it):  // ISSUE vector:: stops VC8 using std::iterator here
1635                container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
1636
1637            // Arithmetic
1638            BOOST_UBLAS_INLINE
1639            const_iterator &operator ++ () {
1640                ++ it1_;
1641                ++ it2_;
1642                return *this;
1643            }
1644            BOOST_UBLAS_INLINE
1645            const_iterator &operator -- () {
1646                -- it1_;
1647                -- it2_;
1648                return *this;
1649            }
1650            BOOST_UBLAS_INLINE
1651            const_iterator &operator += (difference_type n) {
1652                it1_ += n;
1653                it2_ += n;
1654                return *this;
1655            }
1656            BOOST_UBLAS_INLINE
1657            const_iterator &operator -= (difference_type n) {
1658                it1_ -= n;
1659                it2_ -= n;
1660                return *this;
1661            }
1662            BOOST_UBLAS_INLINE
1663            difference_type operator - (const const_iterator &it) const {
1664                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
1665                return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
1666            }
1667
1668            // Dereference
1669            BOOST_UBLAS_INLINE
1670            const_reference operator * () const {
1671                // FIXME replace find with at_element
1672                return (*this) ().data_ (*it1_, *it2_);
1673            }
1674            BOOST_UBLAS_INLINE
1675            const_reference operator [] (difference_type n) const {
1676                return *(*this + n);
1677            }
1678
1679            // Index
1680            BOOST_UBLAS_INLINE
1681            size_type  index () const {
1682                return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
1683            }
1684
1685            // Assignment
1686            BOOST_UBLAS_INLINE
1687            const_iterator &operator = (const const_iterator &it) {
1688                container_const_reference<self_type>::assign (&it ());
1689                it1_ = it.it1_;
1690                it2_ = it.it2_;
1691                return *this;
1692            }
1693
1694            // Comparison
1695            BOOST_UBLAS_INLINE
1696            bool operator == (const const_iterator &it) const {
1697                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1698                return it1_ == it.it1_ && it2_ == it.it2_;
1699            }
1700            BOOST_UBLAS_INLINE
1701            bool operator < (const const_iterator &it) const {
1702                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1703                return it1_ < it.it1_ && it2_ < it.it2_;
1704            }
1705
1706        private:
1707            const_subiterator1_type it1_;
1708            const_subiterator2_type it2_;
1709        };
1710
1711        BOOST_UBLAS_INLINE
1712        const_iterator begin () const {
1713            return find (0);
1714        }
1715        BOOST_UBLAS_INLINE
1716        const_iterator end () const {
1717            return find (size ());
1718        }
1719
1720        class iterator:
1721            public container_reference<matrix_vector_slice>,
1722            public iterator_base_traits<typename M::iterator1::iterator_category>::template
1723                        iterator_base<iterator, value_type>::type {
1724        public:
1725            // FIXME Iterator can never be different code was:
1726            // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
1727            BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
1728
1729            typedef typename matrix_vector_slice::value_type value_type;
1730            typedef typename matrix_vector_slice::difference_type difference_type;
1731            typedef typename matrix_vector_slice::reference reference;
1732            typedef typename matrix_vector_slice::value_type *pointer;
1733
1734            // Construction and destruction
1735            BOOST_UBLAS_INLINE
1736            iterator ():
1737                container_reference<self_type> (), it1_ (), it2_ () {}
1738            BOOST_UBLAS_INLINE
1739            iterator (self_type &mvs, const subiterator1_type &it1, const subiterator2_type &it2):
1740                container_reference<self_type> (mvs), it1_ (it1), it2_ (it2) {}
1741
1742            // Arithmetic
1743            BOOST_UBLAS_INLINE
1744            iterator &operator ++ () {
1745                ++ it1_;
1746                ++ it2_;
1747                return *this;
1748            }
1749            BOOST_UBLAS_INLINE
1750            iterator &operator -- () {
1751                -- it1_;
1752                -- it2_;
1753                return *this;
1754            }
1755            BOOST_UBLAS_INLINE
1756            iterator &operator += (difference_type n) {
1757                it1_ += n;
1758                it2_ += n;
1759                return *this;
1760            }
1761            BOOST_UBLAS_INLINE
1762            iterator &operator -= (difference_type n) {
1763                it1_ -= n;
1764                it2_ -= n;
1765                return *this;
1766            }
1767            BOOST_UBLAS_INLINE
1768            difference_type operator - (const iterator &it) const {
1769                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
1770                return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
1771            }
1772
1773            // Dereference
1774            BOOST_UBLAS_INLINE
1775            reference operator * () const {
1776                // FIXME replace find with at_element
1777                return (*this) ().data_ (*it1_, *it2_);
1778            }
1779            BOOST_UBLAS_INLINE
1780            reference operator [] (difference_type n) const {
1781                return *(*this + n);
1782            }
1783
1784            // Index
1785            BOOST_UBLAS_INLINE
1786            size_type index () const {
1787                return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
1788            }
1789
1790            // Assignment
1791            BOOST_UBLAS_INLINE
1792            iterator &operator = (const iterator &it) {
1793                container_reference<self_type>::assign (&it ());
1794                it1_ = it.it1_;
1795                it2_ = it.it2_;
1796                return *this;
1797            }
1798
1799            // Comparison
1800            BOOST_UBLAS_INLINE
1801            bool operator == (const iterator &it) const {
1802                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1803                return it1_ == it.it1_ && it2_ == it.it2_;
1804            }
1805            BOOST_UBLAS_INLINE
1806            bool operator < (const iterator &it) const {
1807                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1808                return it1_ < it.it1_ && it2_ < it.it2_;
1809            }
1810
1811        private:
1812            subiterator1_type it1_;
1813            subiterator2_type it2_;
1814
1815            friend class const_iterator;
1816        };
1817
1818        BOOST_UBLAS_INLINE
1819        iterator begin () {
1820            return find (0);
1821        }
1822        BOOST_UBLAS_INLINE
1823        iterator end () {
1824            return find (size ());
1825        }
1826
1827        // Reverse iterator
1828        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1829        typedef reverse_iterator_base<iterator> reverse_iterator;
1830
1831        BOOST_UBLAS_INLINE
1832        const_reverse_iterator rbegin () const {
1833            return const_reverse_iterator (end ());
1834        }
1835        BOOST_UBLAS_INLINE
1836        const_reverse_iterator rend () const {
1837            return const_reverse_iterator (begin ());
1838        }
1839        BOOST_UBLAS_INLINE
1840        reverse_iterator rbegin () {
1841            return reverse_iterator (end ());
1842        }
1843        BOOST_UBLAS_INLINE
1844        reverse_iterator rend () {
1845            return reverse_iterator (begin ());
1846        }
1847
1848    private:
1849        matrix_closure_type data_;
1850        slice_type s1_;
1851        slice_type s2_;
1852    };
1853
1854    // Specialize temporary
1855    template <class M>
1856    struct vector_temporary_traits< matrix_vector_slice<M> >
1857    : vector_temporary_traits< M > {} ;
1858    template <class M>
1859    struct vector_temporary_traits< const matrix_vector_slice<M> >
1860    : vector_temporary_traits< M > {} ;
1861
1862    // Matrix based vector indirection class
1863    template<class M, class IA>
1864    class matrix_vector_indirect:
1865        public vector_expression<matrix_vector_indirect<M, IA> > {
1866
1867        typedef matrix_vector_indirect<M, IA> self_type;
1868    public:
1869#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1870        using vector_expression<self_type>::operator ();
1871#endif
1872        typedef M matrix_type;
1873        typedef IA indirect_array_type;
1874        typedef typename M::size_type size_type;
1875        typedef typename M::difference_type difference_type;
1876        typedef typename M::value_type value_type;
1877        typedef typename M::const_reference const_reference;
1878        typedef typename boost::mpl::if_<boost::is_const<M>,
1879                                          typename M::const_reference,
1880                                          typename M::reference>::type reference;
1881        typedef typename boost::mpl::if_<boost::is_const<M>,
1882                                          typename M::const_closure_type,
1883                                          typename M::closure_type>::type matrix_closure_type;
1884        typedef const self_type const_closure_type;
1885        typedef self_type closure_type;
1886        typedef typename storage_restrict_traits<typename M::storage_category,
1887                                                 dense_proxy_tag>::storage_category storage_category;
1888
1889        // Construction and destruction
1890        BOOST_UBLAS_INLINE
1891        matrix_vector_indirect (matrix_type &data, size_type size):
1892            data_ (data), ia1_ (size), ia2_ (size) {}
1893        BOOST_UBLAS_INLINE
1894        matrix_vector_indirect (matrix_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2):
1895            data_ (data), ia1_ (ia1), ia2_ (ia2) {
1896            // Early checking of preconditions here.
1897            // BOOST_UBLAS_CHECK (ia1_.size () == ia2_.size (), bad_size ());
1898        }
1899
1900        // Accessors
1901        BOOST_UBLAS_INLINE
1902        size_type size () const {
1903            return BOOST_UBLAS_SAME (ia1_.size (), ia2_.size ());
1904        }
1905        BOOST_UBLAS_INLINE
1906        const indirect_array_type &indirect1 () const {
1907            return ia1_;
1908        }
1909        BOOST_UBLAS_INLINE
1910        indirect_array_type &indirect1 () {
1911            return ia1_;
1912        }
1913        BOOST_UBLAS_INLINE
1914        const indirect_array_type &indirect2 () const {
1915            return ia2_;
1916        }
1917        BOOST_UBLAS_INLINE
1918        indirect_array_type &indirect2 () {
1919            return ia2_;
1920        }
1921
1922        // Storage accessors
1923        BOOST_UBLAS_INLINE
1924        const matrix_closure_type &data () const {
1925            return data_;
1926        }
1927        BOOST_UBLAS_INLINE
1928        matrix_closure_type &data () {
1929            return data_;
1930        }
1931
1932        // Element access
1933#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
1934        BOOST_UBLAS_INLINE
1935        const_reference operator () (size_type i) const {
1936            return data_ (ia1_ (i), ia2_ (i));
1937        }
1938        BOOST_UBLAS_INLINE
1939        reference operator () (size_type i) {
1940            return data_ (ia1_ (i), ia2_ (i));
1941        }
1942
1943        BOOST_UBLAS_INLINE
1944        const_reference operator [] (size_type i) const {
1945            return (*this) (i);
1946        }
1947        BOOST_UBLAS_INLINE
1948        reference operator [] (size_type i) {
1949            return (*this) (i);
1950        }
1951#else
1952        BOOST_UBLAS_INLINE
1953        reference operator () (size_type i) const {
1954            return data_ (ia1_ (i), ia2_ (i));
1955        }
1956
1957        BOOST_UBLAS_INLINE
1958        reference operator [] (size_type i) const {
1959            return (*this) (i);
1960        }
1961#endif
1962
1963        // Assignment
1964        BOOST_UBLAS_INLINE
1965        matrix_vector_indirect &operator = (const matrix_vector_indirect &mvi) {
1966            // ISSUE need a temporary, proxy can be overlaping alias
1967            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (mvi));
1968            return *this;
1969        }
1970        BOOST_UBLAS_INLINE
1971        matrix_vector_indirect &assign_temporary (matrix_vector_indirect &mvi) {
1972            // assign elements, proxied container remains the same
1973            vector_assign<scalar_assign> (*this, mvi);
1974            return *this;
1975        }
1976        template<class AE>
1977        BOOST_UBLAS_INLINE
1978        matrix_vector_indirect &operator = (const vector_expression<AE> &ae) {
1979            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (ae));
1980            return *this;
1981        }
1982        template<class AE>
1983        BOOST_UBLAS_INLINE
1984        matrix_vector_indirect &assign (const vector_expression<AE> &ae) {
1985            vector_assign<scalar_assign> (*this, ae);
1986            return *this;
1987        }
1988        template<class AE>
1989        BOOST_UBLAS_INLINE
1990        matrix_vector_indirect &operator += (const vector_expression<AE> &ae) {
1991            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this + ae));
1992            return *this;
1993        }
1994        template<class AE>
1995        BOOST_UBLAS_INLINE
1996        matrix_vector_indirect &plus_assign (const vector_expression<AE> &ae) {
1997            vector_assign<scalar_plus_assign> (*this, ae);
1998            return *this;
1999        }
2000        template<class AE>
2001        BOOST_UBLAS_INLINE
2002        matrix_vector_indirect &operator -= (const vector_expression<AE> &ae) {
2003            vector_assign<scalar_assign> (*this, typename vector_temporary_traits<M>::type (*this - ae));
2004            return *this;
2005        }
2006        template<class AE>
2007        BOOST_UBLAS_INLINE
2008        matrix_vector_indirect &minus_assign (const vector_expression<AE> &ae) {
2009            vector_assign<scalar_minus_assign> (*this, ae);
2010            return *this;
2011        }
2012        template<class AT>
2013        BOOST_UBLAS_INLINE
2014        matrix_vector_indirect &operator *= (const AT &at) {
2015            vector_assign_scalar<scalar_multiplies_assign> (*this, at);
2016            return *this;
2017        }
2018        template<class AT>
2019        BOOST_UBLAS_INLINE
2020        matrix_vector_indirect &operator /= (const AT &at) {
2021            vector_assign_scalar<scalar_divides_assign> (*this, at);
2022            return *this;
2023        }
2024
2025        // Closure comparison
2026        BOOST_UBLAS_INLINE
2027        bool same_closure (const matrix_vector_indirect &mvi) const {
2028            return (*this).data_.same_closure (mvi.data_);
2029        }
2030
2031        // Comparison
2032        BOOST_UBLAS_INLINE
2033        bool operator == (const matrix_vector_indirect &mvi) const {
2034            return (*this).data_ == mvi.data_ && ia1_ == mvi.ia1_ && ia2_ == mvi.ia2_;
2035        }
2036
2037        // Swapping
2038        BOOST_UBLAS_INLINE
2039        void swap (matrix_vector_indirect mvi) {
2040            if (this != &mvi) {
2041                BOOST_UBLAS_CHECK (size () == mvi.size (), bad_size ());
2042                // Sparse ranges may be nonconformant now.
2043                // std::swap_ranges (begin (), end (), mvi.begin ());
2044                vector_swap<scalar_swap> (*this, mvi);
2045            }
2046        }
2047        BOOST_UBLAS_INLINE
2048        friend void swap (matrix_vector_indirect mvi1, matrix_vector_indirect mvi2) {
2049            mvi1.swap (mvi2);
2050        }
2051
2052        // Iterator types
2053    private:
2054        // Use indirect array as an index - FIXME this fails for packed assignment
2055        typedef typename IA::const_iterator const_subiterator1_type;
2056        typedef typename IA::const_iterator subiterator1_type;
2057        typedef typename IA::const_iterator const_subiterator2_type;
2058        typedef typename IA::const_iterator subiterator2_type;
2059
2060    public:
2061        class const_iterator;
2062        class iterator;
2063
2064        // Element lookup
2065        BOOST_UBLAS_INLINE
2066        const_iterator find (size_type i) const {
2067            return const_iterator (*this, ia1_.begin () + i, ia2_.begin () + i);
2068        }
2069        BOOST_UBLAS_INLINE
2070        iterator find (size_type i) {
2071            return iterator (*this, ia1_.begin () + i, ia2_.begin () + i);
2072        }
2073
2074        // Iterators simply are indices.
2075
2076        class const_iterator:
2077            public container_const_reference<matrix_vector_indirect>,
2078            public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
2079                        iterator_base<const_iterator, value_type>::type {
2080        public:
2081            // FIXME Iterator can never be different code was:
2082            // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
2083            BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
2084
2085            typedef typename matrix_vector_indirect::value_type value_type;
2086            typedef typename matrix_vector_indirect::difference_type difference_type;
2087            typedef typename matrix_vector_indirect::const_reference reference;
2088            typedef const typename matrix_vector_indirect::value_type *pointer;
2089
2090            // Construction and destruction
2091            BOOST_UBLAS_INLINE
2092            const_iterator ():
2093                container_const_reference<self_type> (), it1_ (), it2_ () {}
2094            BOOST_UBLAS_INLINE
2095            const_iterator (const self_type &mvi, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
2096                container_const_reference<self_type> (mvi), it1_ (it1), it2_ (it2) {}
2097            BOOST_UBLAS_INLINE
2098            const_iterator (const typename self_type::iterator &it):  // ISSUE self_type:: stops VC8 using std::iterator here
2099                container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
2100
2101            // Arithmetic
2102            BOOST_UBLAS_INLINE
2103            const_iterator &operator ++ () {
2104                ++ it1_;
2105                ++ it2_;
2106                return *this;
2107            }
2108            BOOST_UBLAS_INLINE
2109            const_iterator &operator -- () {
2110                -- it1_;
2111                -- it2_;
2112                return *this;
2113            }
2114            BOOST_UBLAS_INLINE
2115            const_iterator &operator += (difference_type n) {
2116                it1_ += n;
2117                it2_ += n;
2118                return *this;
2119            }
2120            BOOST_UBLAS_INLINE
2121            const_iterator &operator -= (difference_type n) {
2122                it1_ -= n;
2123                it2_ -= n;
2124                return *this;
2125            }
2126            BOOST_UBLAS_INLINE
2127            difference_type operator - (const const_iterator &it) const {
2128                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
2129                return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
2130            }
2131
2132            // Dereference
2133            BOOST_UBLAS_INLINE
2134            const_reference operator * () const {
2135                // FIXME replace find with at_element
2136                return (*this) ().data_ (*it1_, *it2_);
2137            }
2138            BOOST_UBLAS_INLINE
2139            const_reference operator [] (difference_type n) const {
2140                return *(*this + n);
2141            }
2142
2143            // Index
2144            BOOST_UBLAS_INLINE
2145            size_type  index () const {
2146                return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
2147            }
2148
2149            // Assignment
2150            BOOST_UBLAS_INLINE
2151            const_iterator &operator = (const const_iterator &it) {
2152                container_const_reference<self_type>::assign (&it ());
2153                it1_ = it.it1_;
2154                it2_ = it.it2_;
2155                return *this;
2156            }
2157
2158            // Comparison
2159            BOOST_UBLAS_INLINE
2160            bool operator == (const const_iterator &it) const {
2161                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2162                return it1_ == it.it1_ && it2_ == it.it2_;
2163            }
2164            BOOST_UBLAS_INLINE
2165            bool operator < (const const_iterator &it) const {
2166                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2167                return it1_ < it.it1_ && it2_ < it.it2_;
2168            }
2169
2170        private:
2171            const_subiterator1_type it1_;
2172            const_subiterator2_type it2_;
2173        };
2174
2175        BOOST_UBLAS_INLINE
2176        const_iterator begin () const {
2177            return find (0);
2178        }
2179        BOOST_UBLAS_INLINE
2180        const_iterator end () const {
2181            return find (size ());
2182        }
2183
2184        class iterator:
2185            public container_reference<matrix_vector_indirect>,
2186            public iterator_base_traits<typename M::iterator1::iterator_category>::template
2187                        iterator_base<iterator, value_type>::type {
2188        public:
2189            // FIXME Iterator can never be different code was:
2190            // typename iterator_restrict_traits<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::iterator_category>
2191            BOOST_STATIC_ASSERT ((boost::is_same<typename M::const_iterator1::iterator_category, typename M::const_iterator2::iterator_category>::value ));
2192
2193            typedef typename matrix_vector_indirect::value_type value_type;
2194            typedef typename matrix_vector_indirect::difference_type difference_type;
2195            typedef typename matrix_vector_indirect::reference reference;
2196            typedef typename matrix_vector_indirect::value_type *pointer;
2197
2198            // Construction and destruction
2199            BOOST_UBLAS_INLINE
2200            iterator ():
2201                container_reference<self_type> (), it1_ (), it2_ () {}
2202            BOOST_UBLAS_INLINE
2203            iterator (self_type &mvi, const subiterator1_type &it1, const subiterator2_type &it2):
2204                container_reference<self_type> (mvi), it1_ (it1), it2_ (it2) {}
2205
2206            // Arithmetic
2207            BOOST_UBLAS_INLINE
2208            iterator &operator ++ () {
2209                ++ it1_;
2210                ++ it2_;
2211                return *this;
2212            }
2213            BOOST_UBLAS_INLINE
2214            iterator &operator -- () {
2215                -- it1_;
2216                -- it2_;
2217                return *this;
2218            }
2219            BOOST_UBLAS_INLINE
2220            iterator &operator += (difference_type n) {
2221                it1_ += n;
2222                it2_ += n;
2223                return *this;
2224            }
2225            BOOST_UBLAS_INLINE
2226            iterator &operator -= (difference_type n) {
2227                it1_ -= n;
2228                it2_ -= n;
2229                return *this;
2230            }
2231            BOOST_UBLAS_INLINE
2232            difference_type operator - (const iterator &it) const {
2233                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
2234                return BOOST_UBLAS_SAME (it1_ - it.it1_, it2_ - it.it2_);
2235            }
2236
2237            // Dereference
2238            BOOST_UBLAS_INLINE
2239            reference operator * () const {
2240                // FIXME replace find with at_element
2241                return (*this) ().data_ (*it1_, *it2_);
2242            }
2243            BOOST_UBLAS_INLINE
2244            reference operator [] (difference_type n) const {
2245                return *(*this + n);
2246            }
2247
2248            // Index
2249            BOOST_UBLAS_INLINE
2250            size_type index () const {
2251                return BOOST_UBLAS_SAME (it1_.index (), it2_.index ());
2252            }
2253
2254            // Assignment
2255            BOOST_UBLAS_INLINE
2256            iterator &operator = (const iterator &it) {
2257                container_reference<self_type>::assign (&it ());
2258                it1_ = it.it1_;
2259                it2_ = it.it2_;
2260                return *this;
2261            }
2262
2263            // Comparison
2264            BOOST_UBLAS_INLINE
2265            bool operator == (const iterator &it) const {
2266                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2267                return it1_ == it.it1_ && it2_ == it.it2_;
2268            }
2269            BOOST_UBLAS_INLINE
2270            bool operator < (const iterator &it) const {
2271                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2272                return it1_ < it.it1_ && it2_ < it.it2_;
2273            }
2274
2275        private:
2276            subiterator1_type it1_;
2277            subiterator2_type it2_;
2278
2279            friend class const_iterator;
2280        };
2281
2282        BOOST_UBLAS_INLINE
2283        iterator begin () {
2284            return find (0);
2285        }
2286        BOOST_UBLAS_INLINE
2287        iterator end () {
2288            return find (size ());
2289        }
2290
2291        // Reverse iterator
2292        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
2293        typedef reverse_iterator_base<iterator> reverse_iterator;
2294
2295        BOOST_UBLAS_INLINE
2296        const_reverse_iterator rbegin () const {
2297            return const_reverse_iterator (end ());
2298        }
2299        BOOST_UBLAS_INLINE
2300        const_reverse_iterator rend () const {
2301            return const_reverse_iterator (begin ());
2302        }
2303        BOOST_UBLAS_INLINE
2304        reverse_iterator rbegin () {
2305            return reverse_iterator (end ());
2306        }
2307        BOOST_UBLAS_INLINE
2308        reverse_iterator rend () {
2309            return reverse_iterator (begin ());
2310        }
2311
2312    private:
2313        matrix_closure_type data_;
2314        indirect_array_type ia1_;
2315        indirect_array_type ia2_;
2316    };
2317
2318    // Specialize temporary
2319    template <class M, class IA>
2320    struct vector_temporary_traits< matrix_vector_indirect<M,IA> >
2321    : vector_temporary_traits< M > {} ;
2322    template <class M, class IA>
2323    struct vector_temporary_traits< const matrix_vector_indirect<M,IA> >
2324    : vector_temporary_traits< M > {} ;
2325
2326    // Matrix based range class
2327    template<class M>
2328    class matrix_range:
2329        public matrix_expression<matrix_range<M> > {
2330
2331        typedef matrix_range<M> self_type;
2332    public:
2333#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2334        using matrix_expression<self_type>::operator ();
2335#endif
2336        typedef M matrix_type;
2337        typedef typename M::size_type size_type;
2338        typedef typename M::difference_type difference_type;
2339        typedef typename M::value_type value_type;
2340        typedef typename M::const_reference const_reference;
2341        typedef typename boost::mpl::if_<boost::is_const<M>,
2342                                          typename M::const_reference,
2343                                          typename M::reference>::type reference;
2344        typedef typename boost::mpl::if_<boost::is_const<M>,
2345                                          typename M::const_closure_type,
2346                                          typename M::closure_type>::type matrix_closure_type;
2347        typedef basic_range<size_type, difference_type> range_type;
2348        typedef const self_type const_closure_type;
2349        typedef self_type closure_type;
2350        typedef typename storage_restrict_traits<typename M::storage_category,
2351                                                 dense_proxy_tag>::storage_category storage_category;
2352        typedef typename M::orientation_category orientation_category;
2353
2354        // Construction and destruction
2355        BOOST_UBLAS_INLINE
2356        matrix_range (matrix_type &data, const range_type &r1, const range_type &r2):
2357            data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {
2358            // Early checking of preconditions here.
2359            // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
2360            //                    r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
2361            // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
2362            //                    r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
2363        }
2364        BOOST_UBLAS_INLINE
2365        matrix_range (const matrix_closure_type &data, const range_type &r1, const range_type &r2, int):
2366            data_ (data), r1_ (r1.preprocess (data.size1 ())), r2_ (r2.preprocess (data.size2 ())) {
2367            // Early checking of preconditions here.
2368            // BOOST_UBLAS_CHECK (r1_.start () <= data_.size1 () &&
2369            //                    r1_.start () + r1_.size () <= data_.size1 (), bad_index ());
2370            // BOOST_UBLAS_CHECK (r2_.start () <= data_.size2 () &&
2371            //                    r2_.start () + r2_.size () <= data_.size2 (), bad_index ());
2372        }
2373
2374        // Accessors
2375        BOOST_UBLAS_INLINE
2376        size_type start1 () const {
2377            return r1_.start ();
2378        }
2379        BOOST_UBLAS_INLINE
2380        size_type size1 () const {
2381            return r1_.size ();
2382        }
2383        BOOST_UBLAS_INLINE
2384        size_type start2() const {
2385            return r2_.start ();
2386        }
2387        BOOST_UBLAS_INLINE
2388        size_type size2 () const {
2389            return r2_.size ();
2390        }
2391
2392        // Storage accessors
2393        BOOST_UBLAS_INLINE
2394        const matrix_closure_type &data () const {
2395            return data_;
2396        }
2397        BOOST_UBLAS_INLINE
2398        matrix_closure_type &data () {
2399            return data_;
2400        }
2401
2402        // Element access
2403#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
2404        BOOST_UBLAS_INLINE
2405        const_reference operator () (size_type i, size_type j) const {
2406            return data_ (r1_ (i), r2_ (j));
2407        }
2408        BOOST_UBLAS_INLINE
2409        reference operator () (size_type i, size_type j) {
2410            return data_ (r1_ (i), r2_ (j));
2411        }
2412#else
2413        BOOST_UBLAS_INLINE
2414        reference operator () (size_type i, size_type j) const {
2415            return data_ (r1_ (i), r2_ (j));
2416        }
2417#endif
2418
2419        // ISSUE can this be done in free project function?
2420        // Although a const function can create a non-const proxy to a non-const object
2421        // Critical is that matrix_type and data_ (vector_closure_type) are const correct
2422        BOOST_UBLAS_INLINE
2423        matrix_range<matrix_type> project (const range_type &r1, const range_type &r2) const {
2424            return matrix_range<matrix_type>  (data_, r1_.compose (r1.preprocess (data_.size1 ())), r2_.compose (r2.preprocess (data_.size2 ())), 0);
2425        }
2426
2427        // Assignment
2428        BOOST_UBLAS_INLINE
2429        matrix_range &operator = (const matrix_range &mr) {
2430            matrix_assign<scalar_assign> (*this, mr);
2431            return *this;
2432        }
2433        BOOST_UBLAS_INLINE
2434        matrix_range &assign_temporary (matrix_range &mr) {
2435            return *this = mr;
2436        }
2437        template<class AE>
2438        BOOST_UBLAS_INLINE
2439        matrix_range &operator = (const matrix_expression<AE> &ae) {
2440            matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae));
2441            return *this;
2442        }
2443        template<class AE>
2444        BOOST_UBLAS_INLINE
2445        matrix_range &assign (const matrix_expression<AE> &ae) {
2446            matrix_assign<scalar_assign> (*this, ae);
2447            return *this;
2448        }
2449        template<class AE>
2450        BOOST_UBLAS_INLINE
2451        matrix_range& operator += (const matrix_expression<AE> &ae) {
2452            matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae));
2453            return *this;
2454        }
2455        template<class AE>
2456        BOOST_UBLAS_INLINE
2457        matrix_range &plus_assign (const matrix_expression<AE> &ae) {
2458            matrix_assign<scalar_plus_assign> (*this, ae);
2459            return *this;
2460        }
2461        template<class AE>
2462        BOOST_UBLAS_INLINE
2463        matrix_range& operator -= (const matrix_expression<AE> &ae) {
2464            matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae));
2465            return *this;
2466        }
2467        template<class AE>
2468        BOOST_UBLAS_INLINE
2469        matrix_range &minus_assign (const matrix_expression<AE> &ae) {
2470            matrix_assign<scalar_minus_assign> (*this, ae);
2471            return *this;
2472        }
2473        template<class AT>
2474        BOOST_UBLAS_INLINE
2475        matrix_range& operator *= (const AT &at) {
2476            matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
2477            return *this;
2478        }
2479        template<class AT>
2480        BOOST_UBLAS_INLINE
2481        matrix_range& operator /= (const AT &at) {
2482            matrix_assign_scalar<scalar_divides_assign> (*this, at);
2483            return *this;
2484        }
2485
2486        // Closure comparison
2487        BOOST_UBLAS_INLINE
2488        bool same_closure (const matrix_range &mr) const {
2489            return (*this).data_.same_closure (mr.data_);
2490        }
2491
2492        // Comparison
2493        BOOST_UBLAS_INLINE
2494        bool operator == (const matrix_range &mr) const {
2495            return (*this).data_ == (mr.data_) && r1_ == mr.r1_ && r2_ == mr.r2_;
2496        }
2497
2498        // Swapping
2499        BOOST_UBLAS_INLINE
2500        void swap (matrix_range mr) {
2501            if (this != &mr) {
2502                BOOST_UBLAS_CHECK (size1 () == mr.size1 (), bad_size ());
2503                BOOST_UBLAS_CHECK (size2 () == mr.size2 (), bad_size ());
2504                matrix_swap<scalar_swap> (*this, mr);
2505            }
2506        }
2507        BOOST_UBLAS_INLINE
2508        friend void swap (matrix_range mr1, matrix_range mr2) {
2509            mr1.swap (mr2);
2510        }
2511
2512        // Iterator types
2513    private:
2514        typedef typename M::const_iterator1 const_subiterator1_type;
2515        typedef typename boost::mpl::if_<boost::is_const<M>,
2516                                          typename M::const_iterator1,
2517                                          typename M::iterator1>::type subiterator1_type;
2518        typedef typename M::const_iterator2 const_subiterator2_type;
2519        typedef typename boost::mpl::if_<boost::is_const<M>,
2520                                          typename M::const_iterator2,
2521                                          typename M::iterator2>::type subiterator2_type;
2522
2523    public:
2524#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2525        typedef indexed_iterator1<matrix_range<matrix_type>,
2526                                  typename subiterator1_type::iterator_category> iterator1;
2527        typedef indexed_iterator2<matrix_range<matrix_type>,
2528                                  typename subiterator2_type::iterator_category> iterator2;
2529        typedef indexed_const_iterator1<matrix_range<matrix_type>,
2530                                        typename const_subiterator1_type::iterator_category> const_iterator1;
2531        typedef indexed_const_iterator2<matrix_range<matrix_type>,
2532                                        typename const_subiterator2_type::iterator_category> const_iterator2;
2533#else
2534        class const_iterator1;
2535        class iterator1;
2536        class const_iterator2;
2537        class iterator2;
2538#endif
2539        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
2540        typedef reverse_iterator_base1<iterator1> reverse_iterator1;
2541        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
2542        typedef reverse_iterator_base2<iterator2> reverse_iterator2;
2543
2544        // Element lookup
2545        BOOST_UBLAS_INLINE
2546        const_iterator1 find1 (int rank, size_type i, size_type j) const {
2547            const_subiterator1_type it1 (data_.find1 (rank, start1 () + i, start2 () + j));
2548#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2549            return const_iterator1 (*this, it1.index1 (), it1.index2 ());
2550#else
2551            return const_iterator1 (*this, it1);
2552#endif
2553        }
2554        BOOST_UBLAS_INLINE
2555        iterator1 find1 (int rank, size_type i, size_type j) {
2556            subiterator1_type it1 (data_.find1 (rank, start1 () + i, start2 () + j));
2557#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2558            return iterator1 (*this, it1.index1 (), it1.index2 ());
2559#else
2560            return iterator1 (*this, it1);
2561#endif
2562        }
2563        BOOST_UBLAS_INLINE
2564        const_iterator2 find2 (int rank, size_type i, size_type j) const {
2565            const_subiterator2_type it2 (data_.find2 (rank, start1 () + i, start2 () + j));
2566#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2567            return const_iterator2 (*this, it2.index1 (), it2.index2 ());
2568#else
2569            return const_iterator2 (*this, it2);
2570#endif
2571        }
2572        BOOST_UBLAS_INLINE
2573        iterator2 find2 (int rank, size_type i, size_type j) {
2574            subiterator2_type it2 (data_.find2 (rank, start1 () + i, start2 () + j));
2575#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2576            return iterator2 (*this, it2.index1 (), it2.index2 ());
2577#else
2578            return iterator2 (*this, it2);
2579#endif
2580        }
2581
2582
2583#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2584        class const_iterator1:
2585            public container_const_reference<matrix_range>,
2586            public iterator_base_traits<typename const_subiterator1_type::iterator_category>::template
2587                        iterator_base<const_iterator1, value_type>::type {
2588        public:
2589            typedef typename const_subiterator1_type::value_type value_type;
2590            typedef typename const_subiterator1_type::difference_type difference_type;
2591            typedef typename const_subiterator1_type::reference reference;
2592            typedef typename const_subiterator1_type::pointer pointer;
2593            typedef const_iterator2 dual_iterator_type;
2594            typedef const_reverse_iterator2 dual_reverse_iterator_type;
2595
2596            // Construction and destruction
2597            BOOST_UBLAS_INLINE
2598            const_iterator1 ():
2599                container_const_reference<self_type> (), it_ () {}
2600            BOOST_UBLAS_INLINE
2601            const_iterator1 (const self_type &mr, const const_subiterator1_type &it):
2602                container_const_reference<self_type> (mr), it_ (it) {}
2603            BOOST_UBLAS_INLINE
2604            const_iterator1 (const iterator1 &it):
2605                container_const_reference<self_type> (it ()), it_ (it.it_) {}
2606
2607            // Arithmetic
2608            BOOST_UBLAS_INLINE
2609            const_iterator1 &operator ++ () {
2610                ++ it_;
2611                return *this;
2612            }
2613            BOOST_UBLAS_INLINE
2614            const_iterator1 &operator -- () {
2615                -- it_;
2616                return *this;
2617            }
2618            BOOST_UBLAS_INLINE
2619            const_iterator1 &operator += (difference_type n) {
2620                it_ += n;
2621                return *this;
2622            }
2623            BOOST_UBLAS_INLINE
2624            const_iterator1 &operator -= (difference_type n) {
2625                it_ -= n;
2626                return *this;
2627            }
2628            BOOST_UBLAS_INLINE
2629            difference_type operator - (const const_iterator1 &it) const {
2630                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2631                return it_ - it.it_;
2632            }
2633
2634            // Dereference
2635            BOOST_UBLAS_INLINE
2636            const_reference operator * () const {
2637                return *it_;
2638            }
2639            BOOST_UBLAS_INLINE
2640            const_reference operator [] (difference_type n) const {
2641                return *(*this + n);
2642            }
2643
2644#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2645            BOOST_UBLAS_INLINE
2646#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2647            typename self_type::
2648#endif
2649            const_iterator2 begin () const {
2650                const self_type &mr = (*this) ();
2651                return mr.find2 (1, index1 (), 0);
2652            }
2653            BOOST_UBLAS_INLINE
2654#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2655            typename self_type::
2656#endif
2657            const_iterator2 end () const {
2658                const self_type &mr = (*this) ();
2659                return mr.find2 (1, index1 (), mr.size2 ());
2660            }
2661            BOOST_UBLAS_INLINE
2662#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2663            typename self_type::
2664#endif
2665            const_reverse_iterator2 rbegin () const {
2666                return const_reverse_iterator2 (end ());
2667            }
2668            BOOST_UBLAS_INLINE
2669#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2670            typename self_type::
2671#endif
2672            const_reverse_iterator2 rend () const {
2673                return const_reverse_iterator2 (begin ());
2674            }
2675#endif
2676
2677            // Indices
2678            BOOST_UBLAS_INLINE
2679            size_type index1 () const {
2680                return it_.index1 () - (*this) ().start1 ();
2681            }
2682            BOOST_UBLAS_INLINE
2683            size_type index2 () const {
2684                return it_.index2 () - (*this) ().start2 ();
2685            }
2686
2687            // Assignment
2688            BOOST_UBLAS_INLINE
2689            const_iterator1 &operator = (const const_iterator1 &it) {
2690                container_const_reference<self_type>::assign (&it ());
2691                it_ = it.it_;
2692                return *this;
2693            }
2694
2695            // Comparison
2696            BOOST_UBLAS_INLINE
2697            bool operator == (const const_iterator1 &it) const {
2698                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2699                return it_ == it.it_;
2700            }
2701            BOOST_UBLAS_INLINE
2702            bool operator < (const const_iterator1 &it) const {
2703                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2704                return it_ < it.it_;
2705            }
2706
2707        private:
2708            const_subiterator1_type it_;
2709        };
2710#endif
2711
2712        BOOST_UBLAS_INLINE
2713        const_iterator1 begin1 () const {
2714            return find1 (0, 0, 0);
2715        }
2716        BOOST_UBLAS_INLINE
2717        const_iterator1 end1 () const {
2718            return find1 (0, size1 (), 0);
2719        }
2720
2721#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2722        class iterator1:
2723            public container_reference<matrix_range>,
2724            public iterator_base_traits<typename subiterator1_type::iterator_category>::template
2725                        iterator_base<iterator1, value_type>::type {
2726        public:
2727            typedef typename subiterator1_type::value_type value_type;
2728            typedef typename subiterator1_type::difference_type difference_type;
2729            typedef typename subiterator1_type::reference reference;
2730            typedef typename subiterator1_type::pointer pointer;
2731            typedef iterator2 dual_iterator_type;
2732            typedef reverse_iterator2 dual_reverse_iterator_type;
2733
2734            // Construction and destruction
2735            BOOST_UBLAS_INLINE
2736            iterator1 ():
2737                container_reference<self_type> (), it_ () {}
2738            BOOST_UBLAS_INLINE
2739            iterator1 (self_type &mr, const subiterator1_type &it):
2740                container_reference<self_type> (mr), it_ (it) {}
2741
2742            // Arithmetic
2743            BOOST_UBLAS_INLINE
2744            iterator1 &operator ++ () {
2745                ++ it_;
2746                return *this;
2747            }
2748            BOOST_UBLAS_INLINE
2749            iterator1 &operator -- () {
2750                -- it_;
2751                return *this;
2752            }
2753            BOOST_UBLAS_INLINE
2754            iterator1 &operator += (difference_type n) {
2755                it_ += n;
2756                return *this;
2757            }
2758            BOOST_UBLAS_INLINE
2759            iterator1 &operator -= (difference_type n) {
2760                it_ -= n;
2761                return *this;
2762            }
2763            BOOST_UBLAS_INLINE
2764            difference_type operator - (const iterator1 &it) const {
2765                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
2766                return it_ - it.it_;
2767            }
2768
2769            // Dereference
2770            BOOST_UBLAS_INLINE
2771            reference operator * () const {
2772                return *it_;
2773            }
2774            BOOST_UBLAS_INLINE
2775            reference operator [] (difference_type n) const {
2776                return *(*this + n);
2777            }
2778
2779#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2780            BOOST_UBLAS_INLINE
2781#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2782            typename self_type::
2783#endif
2784            iterator2 begin () const {
2785                self_type &mr = (*this) ();
2786                return mr.find2 (1, index1 (), 0);
2787            }
2788            BOOST_UBLAS_INLINE
2789#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2790            typename self_type::
2791#endif
2792            iterator2 end () const {
2793                self_type &mr = (*this) ();
2794                return mr.find2 (1, index1 (), mr.size2 ());
2795            }
2796            BOOST_UBLAS_INLINE
2797#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2798            typename self_type::
2799#endif
2800            reverse_iterator2 rbegin () const {
2801                return reverse_iterator2 (end ());
2802            }
2803            BOOST_UBLAS_INLINE
2804#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2805            typename self_type::
2806#endif
2807            reverse_iterator2 rend () const {
2808                return reverse_iterator2 (begin ());
2809            }
2810#endif
2811
2812            // Indices
2813            BOOST_UBLAS_INLINE
2814            size_type index1 () const {
2815                return it_.index1 () - (*this) ().start1 ();
2816            }
2817            BOOST_UBLAS_INLINE
2818            size_type index2 () const {
2819                return it_.index2 () - (*this) ().start2 ();
2820            }
2821
2822            // Assignment
2823            BOOST_UBLAS_INLINE
2824            iterator1 &operator = (const iterator1 &it) {
2825                container_reference<self_type>::assign (&it ());
2826                it_ = it.it_;
2827                return *this;
2828            }
2829
2830            // Comparison
2831            BOOST_UBLAS_INLINE
2832            bool operator == (const iterator1 &it) const {
2833                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2834                return it_ == it.it_;
2835            }
2836            BOOST_UBLAS_INLINE
2837            bool operator < (const iterator1 &it) const {
2838                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2839                return it_ < it.it_;
2840            }
2841
2842        private:
2843            subiterator1_type it_;
2844
2845            friend class const_iterator1;
2846        };
2847#endif
2848
2849        BOOST_UBLAS_INLINE
2850        iterator1 begin1 () {
2851            return find1 (0, 0, 0);
2852        }
2853        BOOST_UBLAS_INLINE
2854        iterator1 end1 () {
2855            return find1 (0, size1 (), 0);
2856        }
2857
2858#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2859        class const_iterator2:
2860            public container_const_reference<matrix_range>,
2861            public iterator_base_traits<typename const_subiterator2_type::iterator_category>::template
2862                        iterator_base<const_iterator2, value_type>::type {
2863        public:
2864            typedef typename const_subiterator2_type::value_type value_type;
2865            typedef typename const_subiterator2_type::difference_type difference_type;
2866            typedef typename const_subiterator2_type::reference reference;
2867            typedef typename const_subiterator2_type::pointer pointer;
2868            typedef const_iterator1 dual_iterator_type;
2869            typedef const_reverse_iterator1 dual_reverse_iterator_type;
2870
2871            // Construction and destruction
2872            BOOST_UBLAS_INLINE
2873            const_iterator2 ():
2874                container_const_reference<self_type> (), it_ () {}
2875            BOOST_UBLAS_INLINE
2876            const_iterator2 (const self_type &mr, const const_subiterator2_type &it):
2877                container_const_reference<self_type> (mr), it_ (it) {}
2878            BOOST_UBLAS_INLINE
2879            const_iterator2 (const iterator2 &it):
2880                container_const_reference<self_type> (it ()), it_ (it.it_) {}
2881
2882            // Arithmetic
2883            BOOST_UBLAS_INLINE
2884            const_iterator2 &operator ++ () {
2885                ++ it_;
2886                return *this;
2887            }
2888            BOOST_UBLAS_INLINE
2889            const_iterator2 &operator -- () {
2890                -- it_;
2891                return *this;
2892            }
2893            BOOST_UBLAS_INLINE
2894            const_iterator2 &operator += (difference_type n) {
2895                it_ += n;
2896                return *this;
2897            }
2898            BOOST_UBLAS_INLINE
2899            const_iterator2 &operator -= (difference_type n) {
2900                it_ -= n;
2901                return *this;
2902            }
2903            BOOST_UBLAS_INLINE
2904            difference_type operator - (const const_iterator2 &it) const {
2905                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
2906                return it_ - it.it_;
2907            }
2908
2909            // Dereference
2910            BOOST_UBLAS_INLINE
2911            const_reference operator * () const {
2912                return *it_;
2913            }
2914            BOOST_UBLAS_INLINE
2915            const_reference operator [] (difference_type n) const {
2916                return *(*this + n);
2917            }
2918
2919#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
2920            BOOST_UBLAS_INLINE
2921#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2922            typename self_type::
2923#endif
2924            const_iterator1 begin () const {
2925                const self_type &mr = (*this) ();
2926                return mr.find1 (1, 0, index2 ());
2927            }
2928            BOOST_UBLAS_INLINE
2929#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2930            typename self_type::
2931#endif
2932            const_iterator1 end () const {
2933                const self_type &mr = (*this) ();
2934                return mr.find1 (1, mr.size1 (), index2 ());
2935            }
2936            BOOST_UBLAS_INLINE
2937#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2938            typename self_type::
2939#endif
2940            const_reverse_iterator1 rbegin () const {
2941                return const_reverse_iterator1 (end ());
2942            }
2943            BOOST_UBLAS_INLINE
2944#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
2945            typename self_type::
2946#endif
2947            const_reverse_iterator1 rend () const {
2948                return const_reverse_iterator1 (begin ());
2949            }
2950#endif
2951
2952            // Indices
2953            BOOST_UBLAS_INLINE
2954            size_type index1 () const {
2955                return it_.index1 () - (*this) ().start1 ();
2956            }
2957            BOOST_UBLAS_INLINE
2958            size_type index2 () const {
2959                return it_.index2 () - (*this) ().start2 ();
2960            }
2961
2962            // Assignment
2963            BOOST_UBLAS_INLINE
2964            const_iterator2 &operator = (const const_iterator2 &it) {
2965                container_const_reference<self_type>::assign (&it ());
2966                it_ = it.it_;
2967                return *this;
2968            }
2969
2970            // Comparison
2971            BOOST_UBLAS_INLINE
2972            bool operator == (const const_iterator2 &it) const {
2973                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
2974                return it_ == it.it_;
2975            }
2976            BOOST_UBLAS_INLINE
2977            bool operator < (const const_iterator2 &it) const {
2978                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
2979                return it_ < it.it_;
2980            }
2981
2982        private:
2983            const_subiterator2_type it_;
2984        };
2985#endif
2986
2987        BOOST_UBLAS_INLINE
2988        const_iterator2 begin2 () const {
2989            return find2 (0, 0, 0);
2990        }
2991        BOOST_UBLAS_INLINE
2992        const_iterator2 end2 () const {
2993            return find2 (0, 0, size2 ());
2994        }
2995
2996#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2997        class iterator2:
2998            public container_reference<matrix_range>,
2999            public iterator_base_traits<typename subiterator2_type::iterator_category>::template
3000                        iterator_base<iterator2, value_type>::type {
3001        public:
3002            typedef typename subiterator2_type::value_type value_type;
3003            typedef typename subiterator2_type::difference_type difference_type;
3004            typedef typename subiterator2_type::reference reference;
3005            typedef typename subiterator2_type::pointer pointer;
3006            typedef iterator1 dual_iterator_type;
3007            typedef reverse_iterator1 dual_reverse_iterator_type;
3008
3009            // Construction and destruction
3010            BOOST_UBLAS_INLINE
3011            iterator2 ():
3012                container_reference<self_type> (), it_ () {}
3013            BOOST_UBLAS_INLINE
3014            iterator2 (self_type &mr, const subiterator2_type &it):
3015                container_reference<self_type> (mr), it_ (it) {}
3016
3017            // Arithmetic
3018            BOOST_UBLAS_INLINE
3019            iterator2 &operator ++ () {
3020                ++ it_;
3021                return *this;
3022            }
3023            BOOST_UBLAS_INLINE
3024            iterator2 &operator -- () {
3025                -- it_;
3026                return *this;
3027            }
3028            BOOST_UBLAS_INLINE
3029            iterator2 &operator += (difference_type n) {
3030                it_ += n;
3031                return *this;
3032            }
3033            BOOST_UBLAS_INLINE
3034            iterator2 &operator -= (difference_type n) {
3035                it_ -= n;
3036                return *this;
3037            }
3038            BOOST_UBLAS_INLINE
3039            difference_type operator - (const iterator2 &it) const {
3040               BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3041                return it_ - it.it_;
3042            }
3043
3044            // Dereference
3045            BOOST_UBLAS_INLINE
3046            reference operator * () const {
3047                return *it_;
3048            }
3049            BOOST_UBLAS_INLINE
3050            reference operator [] (difference_type n) const {
3051                return *(*this + n);
3052            }
3053
3054#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3055            BOOST_UBLAS_INLINE
3056#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3057            typename self_type::
3058#endif
3059            iterator1 begin () const {
3060                self_type &mr = (*this) ();
3061                return mr.find1 (1, 0, index2 ());
3062            }
3063            BOOST_UBLAS_INLINE
3064#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3065            typename self_type::
3066#endif
3067            iterator1 end () const {
3068                self_type &mr = (*this) ();
3069                return mr.find1 (1, mr.size1 (), index2 ());
3070            }
3071            BOOST_UBLAS_INLINE
3072#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3073            typename self_type::
3074#endif
3075            reverse_iterator1 rbegin () const {
3076                return reverse_iterator1 (end ());
3077            }
3078            BOOST_UBLAS_INLINE
3079#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3080            typename self_type::
3081#endif
3082            reverse_iterator1 rend () const {
3083                return reverse_iterator1 (begin ());
3084            }
3085#endif
3086
3087            // Indices
3088            BOOST_UBLAS_INLINE
3089            size_type index1 () const {
3090                return it_.index1 () - (*this) ().start1 ();
3091            }
3092            BOOST_UBLAS_INLINE
3093            size_type index2 () const {
3094                return it_.index2 () - (*this) ().start2 ();
3095            }
3096
3097            // Assignment
3098            BOOST_UBLAS_INLINE
3099            iterator2 &operator = (const iterator2 &it) {
3100                container_reference<self_type>::assign (&it ());
3101                it_ = it.it_;
3102                return *this;
3103            }
3104
3105            // Comparison
3106            BOOST_UBLAS_INLINE
3107            bool operator == (const iterator2 &it) const {
3108                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3109                return it_ == it.it_;
3110            }
3111            BOOST_UBLAS_INLINE
3112            bool operator < (const iterator2 &it) const {
3113                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3114                return it_ < it.it_;
3115            }
3116
3117        private:
3118            subiterator2_type it_;
3119
3120            friend class const_iterator2;
3121        };
3122#endif
3123
3124        BOOST_UBLAS_INLINE
3125        iterator2 begin2 () {
3126            return find2 (0, 0, 0);
3127        }
3128        BOOST_UBLAS_INLINE
3129        iterator2 end2 () {
3130            return find2 (0, 0, size2 ());
3131        }
3132
3133        // Reverse iterators
3134
3135        BOOST_UBLAS_INLINE
3136        const_reverse_iterator1 rbegin1 () const {
3137            return const_reverse_iterator1 (end1 ());
3138        }
3139        BOOST_UBLAS_INLINE
3140        const_reverse_iterator1 rend1 () const {
3141            return const_reverse_iterator1 (begin1 ());
3142        }
3143
3144        BOOST_UBLAS_INLINE
3145        reverse_iterator1 rbegin1 () {
3146            return reverse_iterator1 (end1 ());
3147        }
3148        BOOST_UBLAS_INLINE
3149        reverse_iterator1 rend1 () {
3150            return reverse_iterator1 (begin1 ());
3151        }
3152
3153        BOOST_UBLAS_INLINE
3154        const_reverse_iterator2 rbegin2 () const {
3155            return const_reverse_iterator2 (end2 ());
3156        }
3157        BOOST_UBLAS_INLINE
3158        const_reverse_iterator2 rend2 () const {
3159            return const_reverse_iterator2 (begin2 ());
3160        }
3161
3162        BOOST_UBLAS_INLINE
3163        reverse_iterator2 rbegin2 () {
3164            return reverse_iterator2 (end2 ());
3165        }
3166        BOOST_UBLAS_INLINE
3167        reverse_iterator2 rend2 () {
3168            return reverse_iterator2 (begin2 ());
3169        }
3170
3171    private:
3172        matrix_closure_type data_;
3173        range_type r1_;
3174        range_type r2_;
3175    };
3176
3177    // Simple Projections
3178    template<class M>
3179    BOOST_UBLAS_INLINE
3180    matrix_range<M> subrange (M &data, typename M::size_type start1, typename M::size_type stop1, typename M::size_type start2, typename M::size_type stop2) {
3181        typedef basic_range<typename M::size_type, typename M::difference_type> range_type;
3182        return matrix_range<M> (data, range_type (start1, stop1), range_type (start2, stop2));
3183    }
3184    template<class M>
3185    BOOST_UBLAS_INLINE
3186    matrix_range<const M> subrange (const M &data, typename M::size_type start1, typename M::size_type stop1, typename M::size_type start2, typename M::size_type stop2) {
3187        typedef basic_range<typename M::size_type, typename M::difference_type> range_type;
3188        return matrix_range<const M> (data, range_type (start1, stop1), range_type (start2, stop2));
3189    }
3190
3191    // Generic Projections
3192    template<class M>
3193    BOOST_UBLAS_INLINE
3194    matrix_range<M> project (M &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
3195        return matrix_range<M> (data, r1, r2);
3196    }
3197    template<class M>
3198    BOOST_UBLAS_INLINE
3199    const matrix_range<const M> project (const M &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
3200        // ISSUE was: return matrix_range<M> (const_cast<M &> (data), r1, r2);
3201        return matrix_range<const M> (data, r1, r2);
3202    }
3203    template<class M>
3204    BOOST_UBLAS_INLINE
3205    matrix_range<M> project (matrix_range<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
3206        return data.project (r1, r2);
3207    }
3208    template<class M>
3209    BOOST_UBLAS_INLINE
3210    const matrix_range<M> project (const matrix_range<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
3211        return data.project (r1, r2);
3212    }
3213
3214    // Specialization of temporary_traits
3215    template <class M>
3216    struct matrix_temporary_traits< matrix_range<M> >
3217    : matrix_temporary_traits< M > {} ;
3218    template <class M>
3219    struct matrix_temporary_traits< const matrix_range<M> >
3220    : matrix_temporary_traits< M > {} ;
3221
3222    template <class M>
3223    struct vector_temporary_traits< matrix_range<M> >
3224    : vector_temporary_traits< M > {} ;
3225    template <class M>
3226    struct vector_temporary_traits< const matrix_range<M> >
3227    : vector_temporary_traits< M > {} ;
3228
3229    // Matrix based slice class
3230    template<class M>
3231    class matrix_slice:
3232        public matrix_expression<matrix_slice<M> > {
3233
3234        typedef matrix_slice<M> self_type;
3235    public:
3236#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
3237        using matrix_expression<self_type>::operator ();
3238#endif
3239        typedef M matrix_type;
3240        typedef typename M::size_type size_type;
3241        typedef typename M::difference_type difference_type;
3242        typedef typename M::value_type value_type;
3243        typedef typename M::const_reference const_reference;
3244        typedef typename boost::mpl::if_<boost::is_const<M>,
3245                                          typename M::const_reference,
3246                                          typename M::reference>::type reference;
3247        typedef typename boost::mpl::if_<boost::is_const<M>,
3248                                          typename M::const_closure_type,
3249                                          typename M::closure_type>::type matrix_closure_type;
3250        typedef basic_range<size_type, difference_type> range_type;
3251        typedef basic_slice<size_type, difference_type> slice_type;
3252        typedef const self_type const_closure_type;
3253        typedef self_type closure_type;
3254        typedef typename storage_restrict_traits<typename M::storage_category,
3255                                                 dense_proxy_tag>::storage_category storage_category;
3256        typedef typename M::orientation_category orientation_category;
3257
3258        // Construction and destruction
3259        BOOST_UBLAS_INLINE
3260        matrix_slice (matrix_type &data, const slice_type &s1, const slice_type &s2):
3261            data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {
3262            // Early checking of preconditions here.
3263            // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
3264            //                    s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
3265            // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
3266            //                    s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
3267        }
3268        BOOST_UBLAS_INLINE
3269        matrix_slice (const matrix_closure_type &data, const slice_type &s1, const slice_type &s2, int):
3270            data_ (data), s1_ (s1.preprocess (data.size1 ())), s2_ (s2.preprocess (data.size2 ())) {
3271            // Early checking of preconditions.
3272            // BOOST_UBLAS_CHECK (s1_.start () <= data_.size1 () &&
3273            //                    s1_.start () + s1_.stride () * (s1_.size () - (s1_.size () > 0)) <= data_.size1 (), bad_index ());
3274            // BOOST_UBLAS_CHECK (s2_.start () <= data_.size2 () &&
3275            //                    s2_.start () + s2_.stride () * (s2_.size () - (s2_.size () > 0)) <= data_.size2 (), bad_index ());
3276        }
3277
3278        // Accessors
3279        BOOST_UBLAS_INLINE
3280        size_type start1 () const {
3281            return s1_.start ();
3282        }
3283        BOOST_UBLAS_INLINE
3284        size_type start2 () const {
3285            return s2_.start ();
3286        }
3287        BOOST_UBLAS_INLINE
3288        difference_type stride1 () const {
3289            return s1_.stride ();
3290        }
3291        BOOST_UBLAS_INLINE
3292        difference_type stride2 () const {
3293            return s2_.stride ();
3294        }
3295        BOOST_UBLAS_INLINE
3296        size_type size1 () const {
3297            return s1_.size ();
3298        }
3299        BOOST_UBLAS_INLINE
3300        size_type size2 () const {
3301            return s2_.size ();
3302        }
3303
3304        // Storage accessors
3305        BOOST_UBLAS_INLINE
3306        const matrix_closure_type &data () const {
3307            return data_;
3308        }
3309        BOOST_UBLAS_INLINE
3310        matrix_closure_type &data () {
3311            return data_;
3312        }
3313
3314        // Element access
3315#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
3316        BOOST_UBLAS_INLINE
3317        const_reference operator () (size_type i, size_type j) const {
3318            return data_ (s1_ (i), s2_ (j));
3319        }
3320        BOOST_UBLAS_INLINE
3321        reference operator () (size_type i, size_type j) {
3322            return data_ (s1_ (i), s2_ (j));
3323        }
3324#else
3325        BOOST_UBLAS_INLINE
3326        reference operator () (size_type i, size_type j) const {
3327            return data_ (s1_ (i), s2_ (j));
3328        }
3329#endif
3330
3331        // ISSUE can this be done in free project function?
3332        // Although a const function can create a non-const proxy to a non-const object
3333        // Critical is that matrix_type and data_ (vector_closure_type) are const correct
3334        BOOST_UBLAS_INLINE
3335        matrix_slice<matrix_type> project (const range_type &r1, const range_type &r2) const {
3336            return matrix_slice<matrix_type>  (data_, s1_.compose (r1.preprocess (data_.size1 ())), s2_.compose (r2.preprocess (data_.size2 ())), 0);
3337        }
3338        BOOST_UBLAS_INLINE
3339        matrix_slice<matrix_type> project (const slice_type &s1, const slice_type &s2) const {
3340            return matrix_slice<matrix_type>  (data_, s1_.compose (s1.preprocess (data_.size1 ())), s2_.compose (s2.preprocess (data_.size2 ())), 0);
3341        }
3342
3343        // Assignment
3344        BOOST_UBLAS_INLINE
3345        matrix_slice &operator = (const matrix_slice &ms) {
3346            matrix_assign<scalar_assign> (*this, ms);
3347            return *this;
3348        }
3349        BOOST_UBLAS_INLINE
3350        matrix_slice &assign_temporary (matrix_slice &ms) {
3351            return *this = ms;
3352        }
3353        template<class AE>
3354        BOOST_UBLAS_INLINE
3355        matrix_slice &operator = (const matrix_expression<AE> &ae) {
3356            matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae));
3357            return *this;
3358        }
3359        template<class AE>
3360        BOOST_UBLAS_INLINE
3361        matrix_slice &assign (const matrix_expression<AE> &ae) {
3362            matrix_assign<scalar_assign> (*this, ae);
3363            return *this;
3364        }
3365        template<class AE>
3366        BOOST_UBLAS_INLINE
3367        matrix_slice& operator += (const matrix_expression<AE> &ae) {
3368            matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae));
3369            return *this;
3370        }
3371        template<class AE>
3372        BOOST_UBLAS_INLINE
3373        matrix_slice &plus_assign (const matrix_expression<AE> &ae) {
3374            matrix_assign<scalar_plus_assign> (*this, ae);
3375            return *this;
3376        }
3377        template<class AE>
3378        BOOST_UBLAS_INLINE
3379        matrix_slice& operator -= (const matrix_expression<AE> &ae) {
3380            matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae));
3381            return *this;
3382        }
3383        template<class AE>
3384        BOOST_UBLAS_INLINE
3385        matrix_slice &minus_assign (const matrix_expression<AE> &ae) {
3386            matrix_assign<scalar_minus_assign> (*this, ae);
3387            return *this;
3388        }
3389        template<class AT>
3390        BOOST_UBLAS_INLINE
3391        matrix_slice& operator *= (const AT &at) {
3392            matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
3393            return *this;
3394        }
3395        template<class AT>
3396        BOOST_UBLAS_INLINE
3397        matrix_slice& operator /= (const AT &at) {
3398            matrix_assign_scalar<scalar_divides_assign> (*this, at);
3399            return *this;
3400        }
3401
3402        // Closure comparison
3403        BOOST_UBLAS_INLINE
3404        bool same_closure (const matrix_slice &ms) const {
3405            return (*this).data_.same_closure (ms.data_);
3406        }
3407
3408        // Comparison
3409        BOOST_UBLAS_INLINE
3410        bool operator == (const matrix_slice &ms) const {
3411            return (*this).data_ == ms.data_ && s1_ == ms.s1_ && s2_ == ms.s2_;
3412        }
3413
3414        // Swapping
3415        BOOST_UBLAS_INLINE
3416        void swap (matrix_slice ms) {
3417            if (this != &ms) {
3418                BOOST_UBLAS_CHECK (size1 () == ms.size1 (), bad_size ());
3419                BOOST_UBLAS_CHECK (size2 () == ms.size2 (), bad_size ());
3420                matrix_swap<scalar_swap> (*this, ms);
3421            }
3422        }
3423        BOOST_UBLAS_INLINE
3424        friend void swap (matrix_slice ms1, matrix_slice ms2) {
3425            ms1.swap (ms2);
3426        }
3427
3428        // Iterator types
3429    private:
3430        // Use slice as an index - FIXME this fails for packed assignment
3431        typedef typename slice_type::const_iterator const_subiterator1_type;
3432        typedef typename slice_type::const_iterator subiterator1_type;
3433        typedef typename slice_type::const_iterator const_subiterator2_type;
3434        typedef typename slice_type::const_iterator subiterator2_type;
3435
3436    public:
3437#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3438        typedef indexed_iterator1<matrix_slice<matrix_type>,
3439                                  typename matrix_type::iterator1::iterator_category> iterator1;
3440        typedef indexed_iterator2<matrix_slice<matrix_type>,
3441                                  typename matrix_type::iterator2::iterator_category> iterator2;
3442        typedef indexed_const_iterator1<matrix_slice<matrix_type>,
3443                                        typename matrix_type::const_iterator1::iterator_category> const_iterator1;
3444        typedef indexed_const_iterator2<matrix_slice<matrix_type>,
3445                                        typename matrix_type::const_iterator2::iterator_category> const_iterator2;
3446#else
3447        class const_iterator1;
3448        class iterator1;
3449        class const_iterator2;
3450        class iterator2;
3451#endif
3452        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
3453        typedef reverse_iterator_base1<iterator1> reverse_iterator1;
3454        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
3455        typedef reverse_iterator_base2<iterator2> reverse_iterator2;
3456
3457        // Element lookup
3458        BOOST_UBLAS_INLINE
3459        const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
3460#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3461            return const_iterator1 (*this, i, j);
3462#else
3463            return const_iterator1 (*this, s1_.begin () + i, s2_.begin () + j);
3464#endif
3465        }
3466        BOOST_UBLAS_INLINE
3467        iterator1 find1 (int /* rank */, size_type i, size_type j) {
3468#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3469            return iterator1 (*this, i, j);
3470#else
3471            return iterator1 (*this, s1_.begin () + i, s2_.begin () + j);
3472#endif
3473        }
3474        BOOST_UBLAS_INLINE
3475        const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
3476#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3477            return const_iterator2 (*this, i, j);
3478#else
3479            return const_iterator2 (*this, s1_.begin () + i, s2_.begin () + j);
3480#endif
3481        }
3482        BOOST_UBLAS_INLINE
3483        iterator2 find2 (int /* rank */, size_type i, size_type j) {
3484#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
3485            return iterator2 (*this, i, j);
3486#else
3487            return iterator2 (*this, s1_.begin () + i, s2_.begin () + j);
3488#endif
3489        }
3490
3491        // Iterators simply are indices.
3492
3493#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3494        class const_iterator1:
3495            public container_const_reference<matrix_slice>,
3496            public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
3497                        iterator_base<const_iterator1, value_type>::type {
3498        public:
3499            typedef typename M::const_iterator1::value_type value_type;
3500            typedef typename M::const_iterator1::difference_type difference_type;
3501            typedef typename M::const_reference reference;    //FIXME due to indexing access
3502            typedef typename M::const_iterator1::pointer pointer;
3503            typedef const_iterator2 dual_iterator_type;
3504            typedef const_reverse_iterator2 dual_reverse_iterator_type;
3505
3506            // Construction and destruction
3507            BOOST_UBLAS_INLINE
3508            const_iterator1 ():
3509                container_const_reference<self_type> (), it1_ (), it2_ () {}
3510            BOOST_UBLAS_INLINE
3511            const_iterator1 (const self_type &ms, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
3512                container_const_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
3513            BOOST_UBLAS_INLINE
3514            const_iterator1 (const iterator1 &it):
3515                container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
3516
3517            // Arithmetic
3518            BOOST_UBLAS_INLINE
3519            const_iterator1 &operator ++ () {
3520                ++ it1_;
3521                return *this;
3522            }
3523            BOOST_UBLAS_INLINE
3524            const_iterator1 &operator -- () {
3525                -- it1_;
3526                return *this;
3527            }
3528            BOOST_UBLAS_INLINE
3529            const_iterator1 &operator += (difference_type n) {
3530                it1_ += n;
3531                return *this;
3532            }
3533            BOOST_UBLAS_INLINE
3534            const_iterator1 &operator -= (difference_type n) {
3535                it1_ -= n;
3536                return *this;
3537            }
3538            BOOST_UBLAS_INLINE
3539            difference_type operator - (const const_iterator1 &it) const {
3540                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3541                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3542                return it1_ - it.it1_;
3543            }
3544
3545            // Dereference
3546            BOOST_UBLAS_INLINE
3547            const_reference operator * () const {
3548                // FIXME replace find with at_element
3549                return (*this) ().data_ (*it1_, *it2_);
3550            }
3551            BOOST_UBLAS_INLINE
3552            const_reference operator [] (difference_type n) const {
3553                return *(*this + n);
3554            }
3555
3556#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3557            BOOST_UBLAS_INLINE
3558#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3559            typename self_type::
3560#endif
3561            const_iterator2 begin () const {
3562                return const_iterator2 ((*this) (), it1_, it2_ ().begin ());
3563            }
3564            BOOST_UBLAS_INLINE
3565#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3566            typename self_type::
3567#endif
3568            const_iterator2 end () const {
3569                return const_iterator2 ((*this) (), it1_, it2_ ().end ());
3570            }
3571            BOOST_UBLAS_INLINE
3572#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3573            typename self_type::
3574#endif
3575            const_reverse_iterator2 rbegin () const {
3576                return const_reverse_iterator2 (end ());
3577            }
3578            BOOST_UBLAS_INLINE
3579#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3580            typename self_type::
3581#endif
3582            const_reverse_iterator2 rend () const {
3583                return const_reverse_iterator2 (begin ());
3584            }
3585#endif
3586
3587            // Indices
3588            BOOST_UBLAS_INLINE
3589            size_type index1 () const {
3590                return it1_.index ();
3591            }
3592            BOOST_UBLAS_INLINE
3593            size_type index2 () const {
3594                return it2_.index ();
3595            }
3596
3597            // Assignment
3598            BOOST_UBLAS_INLINE
3599            const_iterator1 &operator = (const const_iterator1 &it) {
3600                container_const_reference<self_type>::assign (&it ());
3601                it1_ = it.it1_;
3602                it2_ = it.it2_;
3603                return *this;
3604            }
3605
3606            // Comparison
3607            BOOST_UBLAS_INLINE
3608            bool operator == (const const_iterator1 &it) const {
3609                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3610                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3611                return it1_ == it.it1_;
3612            }
3613            BOOST_UBLAS_INLINE
3614            bool operator < (const const_iterator1 &it) const {
3615                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3616                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3617                return it1_ < it.it1_;
3618            }
3619
3620        private:
3621            const_subiterator1_type it1_;
3622            const_subiterator2_type it2_;
3623        };
3624#endif
3625
3626        BOOST_UBLAS_INLINE
3627        const_iterator1 begin1 () const {
3628            return find1 (0, 0, 0);
3629        }
3630        BOOST_UBLAS_INLINE
3631        const_iterator1 end1 () const {
3632            return find1 (0, size1 (), 0);
3633        }
3634
3635#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3636        class iterator1:
3637            public container_reference<matrix_slice>,
3638            public iterator_base_traits<typename M::iterator1::iterator_category>::template
3639                        iterator_base<iterator1, value_type>::type {
3640        public:
3641            typedef typename M::iterator1::value_type value_type;
3642            typedef typename M::iterator1::difference_type difference_type;
3643            typedef typename M::reference reference;    //FIXME due to indexing access
3644            typedef typename M::iterator1::pointer pointer;
3645            typedef iterator2 dual_iterator_type;
3646            typedef reverse_iterator2 dual_reverse_iterator_type;
3647
3648            // Construction and destruction
3649            BOOST_UBLAS_INLINE
3650            iterator1 ():
3651                container_reference<self_type> (), it1_ (), it2_ () {}
3652            BOOST_UBLAS_INLINE
3653            iterator1 (self_type &ms, const subiterator1_type &it1, const subiterator2_type &it2):
3654                container_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
3655
3656            // Arithmetic
3657            BOOST_UBLAS_INLINE
3658            iterator1 &operator ++ () {
3659                ++ it1_;
3660                return *this;
3661            }
3662            BOOST_UBLAS_INLINE
3663            iterator1 &operator -- () {
3664                -- it1_;
3665                return *this;
3666            }
3667            BOOST_UBLAS_INLINE
3668            iterator1 &operator += (difference_type n) {
3669                it1_ += n;
3670                return *this;
3671            }
3672            BOOST_UBLAS_INLINE
3673            iterator1 &operator -= (difference_type n) {
3674                it1_ -= n;
3675                return *this;
3676            }
3677            BOOST_UBLAS_INLINE
3678            difference_type operator - (const iterator1 &it) const {
3679                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3680                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3681                return it1_ - it.it1_;
3682            }
3683
3684            // Dereference
3685            BOOST_UBLAS_INLINE
3686            reference operator * () const {
3687                // FIXME replace find with at_element
3688                return (*this) ().data_ (*it1_, *it2_);
3689            }
3690            BOOST_UBLAS_INLINE
3691            reference operator [] (difference_type n) const {
3692                return *(*this + n);
3693            }
3694
3695#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3696            BOOST_UBLAS_INLINE
3697#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3698            typename self_type::
3699#endif
3700            iterator2 begin () const {
3701                return iterator2 ((*this) (), it1_, it2_ ().begin ());
3702            }
3703            BOOST_UBLAS_INLINE
3704#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3705            typename self_type::
3706#endif
3707            iterator2 end () const {
3708                return iterator2 ((*this) (), it1_, it2_ ().end ());
3709            }
3710            BOOST_UBLAS_INLINE
3711#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3712            typename self_type::
3713#endif
3714            reverse_iterator2 rbegin () const {
3715                return reverse_iterator2 (end ());
3716            }
3717            BOOST_UBLAS_INLINE
3718#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3719            typename self_type::
3720#endif
3721            reverse_iterator2 rend () const {
3722                return reverse_iterator2 (begin ());
3723            }
3724#endif
3725
3726            // Indices
3727            BOOST_UBLAS_INLINE
3728            size_type index1 () const {
3729                return it1_.index ();
3730            }
3731            BOOST_UBLAS_INLINE
3732            size_type index2 () const {
3733                return it2_.index ();
3734            }
3735
3736            // Assignment
3737            BOOST_UBLAS_INLINE
3738            iterator1 &operator = (const iterator1 &it) {
3739                container_reference<self_type>::assign (&it ());
3740                it1_ = it.it1_;
3741                it2_ = it.it2_;
3742                return *this;
3743            }
3744
3745            // Comparison
3746            BOOST_UBLAS_INLINE
3747            bool operator == (const iterator1 &it) const {
3748                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3749                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3750                return it1_ == it.it1_;
3751            }
3752            BOOST_UBLAS_INLINE
3753            bool operator < (const iterator1 &it) const {
3754                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3755                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
3756                return it1_ < it.it1_;
3757            }
3758
3759        private:
3760            subiterator1_type it1_;
3761            subiterator2_type it2_;
3762
3763            friend class const_iterator1;
3764        };
3765#endif
3766
3767        BOOST_UBLAS_INLINE
3768        iterator1 begin1 () {
3769            return find1 (0, 0, 0);
3770        }
3771        BOOST_UBLAS_INLINE
3772        iterator1 end1 () {
3773            return find1 (0, size1 (), 0);
3774        }
3775
3776#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3777        class const_iterator2:
3778            public container_const_reference<matrix_slice>,
3779            public iterator_base_traits<typename M::const_iterator2::iterator_category>::template
3780                        iterator_base<const_iterator2, value_type>::type {
3781        public:
3782            typedef typename M::const_iterator2::value_type value_type;
3783            typedef typename M::const_iterator2::difference_type difference_type;
3784            typedef typename M::const_reference reference;    //FIXME due to indexing access
3785            typedef typename M::const_iterator2::pointer pointer;
3786            typedef const_iterator1 dual_iterator_type;
3787            typedef const_reverse_iterator1 dual_reverse_iterator_type;
3788
3789            // Construction and destruction
3790            BOOST_UBLAS_INLINE
3791            const_iterator2 ():
3792                container_const_reference<self_type> (), it1_ (), it2_ () {}
3793            BOOST_UBLAS_INLINE
3794            const_iterator2 (const self_type &ms, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
3795                container_const_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
3796            BOOST_UBLAS_INLINE
3797            const_iterator2 (const iterator2 &it):
3798                container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
3799
3800            // Arithmetic
3801            BOOST_UBLAS_INLINE
3802            const_iterator2 &operator ++ () {
3803                ++ it2_;
3804                return *this;
3805            }
3806            BOOST_UBLAS_INLINE
3807            const_iterator2 &operator -- () {
3808                -- it2_;
3809                return *this;
3810            }
3811            BOOST_UBLAS_INLINE
3812            const_iterator2 &operator += (difference_type n) {
3813                it2_ += n;
3814                return *this;
3815            }
3816            BOOST_UBLAS_INLINE
3817            const_iterator2 &operator -= (difference_type n) {
3818                it2_ -= n;
3819                return *this;
3820            }
3821            BOOST_UBLAS_INLINE
3822            difference_type operator - (const const_iterator2 &it) const {
3823                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3824                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3825                return it2_ - it.it2_;
3826            }
3827
3828            // Dereference
3829            BOOST_UBLAS_INLINE
3830            const_reference operator * () const {
3831                // FIXME replace find with at_element
3832                return (*this) ().data_ (*it1_, *it2_);
3833            }
3834            BOOST_UBLAS_INLINE
3835            const_reference operator [] (difference_type n) const {
3836                return *(*this + n);
3837            }
3838
3839#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3840            BOOST_UBLAS_INLINE
3841#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3842            typename self_type::
3843#endif
3844            const_iterator1 begin () const {
3845                return const_iterator1 ((*this) (), it1_ ().begin (), it2_);
3846            }
3847            BOOST_UBLAS_INLINE
3848#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3849            typename self_type::
3850#endif
3851            const_iterator1 end () const {
3852                return const_iterator1 ((*this) (), it1_ ().end (), it2_);
3853            }
3854            BOOST_UBLAS_INLINE
3855#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3856            typename self_type::
3857#endif
3858            const_reverse_iterator1 rbegin () const {
3859                return const_reverse_iterator1 (end ());
3860            }
3861            BOOST_UBLAS_INLINE
3862#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3863            typename self_type::
3864#endif
3865            const_reverse_iterator1 rend () const {
3866                return const_reverse_iterator1 (begin ());
3867            }
3868#endif
3869
3870            // Indices
3871            BOOST_UBLAS_INLINE
3872            size_type index1 () const {
3873                return it1_.index ();
3874            }
3875            BOOST_UBLAS_INLINE
3876            size_type index2 () const {
3877                return it2_.index ();
3878            }
3879
3880            // Assignment
3881            BOOST_UBLAS_INLINE
3882            const_iterator2 &operator = (const const_iterator2 &it) {
3883                container_const_reference<self_type>::assign (&it ());
3884                it1_ = it.it1_;
3885                it2_ = it.it2_;
3886                return *this;
3887            }
3888
3889            // Comparison
3890            BOOST_UBLAS_INLINE
3891            bool operator == (const const_iterator2 &it) const {
3892                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3893                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3894                return it2_ == it.it2_;
3895            }
3896            BOOST_UBLAS_INLINE
3897            bool operator < (const const_iterator2 &it) const {
3898                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3899                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3900                return it2_ < it.it2_;
3901            }
3902
3903        private:
3904            const_subiterator1_type it1_;
3905            const_subiterator2_type it2_;
3906        };
3907#endif
3908
3909        BOOST_UBLAS_INLINE
3910        const_iterator2 begin2 () const {
3911            return find2 (0, 0, 0);
3912        }
3913        BOOST_UBLAS_INLINE
3914        const_iterator2 end2 () const {
3915            return find2 (0, 0, size2 ());
3916        }
3917
3918#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
3919        class iterator2:
3920            public container_reference<matrix_slice>,
3921            public iterator_base_traits<typename M::iterator2::iterator_category>::template
3922                        iterator_base<iterator2, value_type>::type {
3923        public:
3924            typedef typename M::iterator2::value_type value_type;
3925            typedef typename M::iterator2::difference_type difference_type;
3926            typedef typename M::reference reference;    //FIXME due to indexing access
3927            typedef typename M::iterator2::pointer pointer;
3928            typedef iterator1 dual_iterator_type;
3929            typedef reverse_iterator1 dual_reverse_iterator_type;
3930
3931            // Construction and destruction
3932            BOOST_UBLAS_INLINE
3933            iterator2 ():
3934                container_reference<self_type> (), it1_ (), it2_ () {}
3935            BOOST_UBLAS_INLINE
3936            iterator2 (self_type &ms, const subiterator1_type &it1, const subiterator2_type &it2):
3937                container_reference<self_type> (ms), it1_ (it1), it2_ (it2) {}
3938
3939            // Arithmetic
3940            BOOST_UBLAS_INLINE
3941            iterator2 &operator ++ () {
3942                ++ it2_;
3943                return *this;
3944            }
3945            BOOST_UBLAS_INLINE
3946            iterator2 &operator -- () {
3947                -- it2_;
3948                return *this;
3949            }
3950            BOOST_UBLAS_INLINE
3951            iterator2 &operator += (difference_type n) {
3952                it2_ += n;
3953                return *this;
3954            }
3955            BOOST_UBLAS_INLINE
3956            iterator2 &operator -= (difference_type n) {
3957                it2_ -= n;
3958                return *this;
3959            }
3960            BOOST_UBLAS_INLINE
3961            difference_type operator - (const iterator2 &it) const {
3962                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
3963                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
3964                return it2_ - it.it2_;
3965            }
3966
3967            // Dereference
3968            BOOST_UBLAS_INLINE
3969            reference operator * () const {
3970                // FIXME replace find with at_element
3971                return (*this) ().data_ (*it1_, *it2_);
3972            }
3973            BOOST_UBLAS_INLINE
3974            reference operator [] (difference_type n) const {
3975                return *(*this + n);
3976            }
3977
3978#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
3979            BOOST_UBLAS_INLINE
3980#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3981            typename self_type::
3982#endif
3983            iterator1 begin () const {
3984                return iterator1 ((*this) (), it1_ ().begin (), it2_);
3985            }
3986            BOOST_UBLAS_INLINE
3987#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3988            typename self_type::
3989#endif
3990            iterator1 end () const {
3991                return iterator1 ((*this) (), it1_ ().end (), it2_);
3992            }
3993            BOOST_UBLAS_INLINE
3994#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
3995            typename self_type::
3996#endif
3997            reverse_iterator1 rbegin () const {
3998                return reverse_iterator1 (end ());
3999            }
4000            BOOST_UBLAS_INLINE
4001#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4002            typename self_type::
4003#endif
4004            reverse_iterator1 rend () const {
4005                return reverse_iterator1 (begin ());
4006            }
4007#endif
4008
4009            // Indices
4010            BOOST_UBLAS_INLINE
4011            size_type index1 () const {
4012                return it1_.index ();
4013            }
4014            BOOST_UBLAS_INLINE
4015            size_type index2 () const {
4016                return it2_.index ();
4017            }
4018
4019            // Assignment
4020            BOOST_UBLAS_INLINE
4021            iterator2 &operator = (const iterator2 &it) {
4022                container_reference<self_type>::assign (&it ());
4023                it1_ = it.it1_;
4024                it2_ = it.it2_;
4025                return *this;
4026            }
4027
4028            // Comparison
4029            BOOST_UBLAS_INLINE
4030            bool operator == (const iterator2 &it) const {
4031                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4032                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4033                return it2_ == it.it2_;
4034            }
4035            BOOST_UBLAS_INLINE
4036            bool operator < (const iterator2 &it) const {
4037                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4038                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4039                return it2_ < it.it2_;
4040            }
4041
4042        private:
4043            subiterator1_type it1_;
4044            subiterator2_type it2_;
4045
4046            friend class const_iterator2;
4047        };
4048#endif
4049
4050        BOOST_UBLAS_INLINE
4051        iterator2 begin2 () {
4052            return find2 (0, 0, 0);
4053        }
4054        BOOST_UBLAS_INLINE
4055        iterator2 end2 () {
4056            return find2 (0, 0, size2 ());
4057        }
4058
4059        // Reverse iterators
4060
4061        BOOST_UBLAS_INLINE
4062        const_reverse_iterator1 rbegin1 () const {
4063            return const_reverse_iterator1 (end1 ());
4064        }
4065        BOOST_UBLAS_INLINE
4066        const_reverse_iterator1 rend1 () const {
4067            return const_reverse_iterator1 (begin1 ());
4068        }
4069
4070        BOOST_UBLAS_INLINE
4071        reverse_iterator1 rbegin1 () {
4072            return reverse_iterator1 (end1 ());
4073        }
4074        BOOST_UBLAS_INLINE
4075        reverse_iterator1 rend1 () {
4076            return reverse_iterator1 (begin1 ());
4077        }
4078
4079        BOOST_UBLAS_INLINE
4080        const_reverse_iterator2 rbegin2 () const {
4081            return const_reverse_iterator2 (end2 ());
4082        }
4083        BOOST_UBLAS_INLINE
4084        const_reverse_iterator2 rend2 () const {
4085            return const_reverse_iterator2 (begin2 ());
4086        }
4087
4088        BOOST_UBLAS_INLINE
4089        reverse_iterator2 rbegin2 () {
4090            return reverse_iterator2 (end2 ());
4091        }
4092        BOOST_UBLAS_INLINE
4093        reverse_iterator2 rend2 () {
4094            return reverse_iterator2 (begin2 ());
4095        }
4096
4097    private:
4098        matrix_closure_type data_;
4099        slice_type s1_;
4100        slice_type s2_;
4101    };
4102
4103    // Simple Projections
4104    template<class M>
4105    BOOST_UBLAS_INLINE
4106    matrix_slice<M> subslice (M &data, typename M::size_type start1, typename M::difference_type stride1, typename M::size_type size1, typename M::size_type start2, typename M::difference_type stride2, typename M::size_type size2) {
4107        typedef basic_slice<typename M::size_type, typename M::difference_type> slice_type;
4108        return matrix_slice<M> (data, slice_type (start1, stride1, size1), slice_type (start2, stride2, size2));
4109    }
4110    template<class M>
4111    BOOST_UBLAS_INLINE
4112    matrix_slice<const M> subslice (const M &data, typename M::size_type start1, typename M::difference_type stride1, typename M::size_type size1, typename M::size_type start2, typename M::difference_type stride2, typename M::size_type size2) {
4113        typedef basic_slice<typename M::size_type, typename M::difference_type> slice_type;
4114        return matrix_slice<const M> (data (), slice_type (start1, stride1, size1), slice_type (start2, stride2, size2));
4115    }
4116
4117    // Generic Projections
4118    template<class M>
4119    BOOST_UBLAS_INLINE
4120    matrix_slice<M> project (M &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
4121        return matrix_slice<M> (data, s1, s2);
4122    }
4123    template<class M>
4124    BOOST_UBLAS_INLINE
4125    const matrix_slice<const M> project (const M &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
4126        // ISSUE was: return matrix_slice<M> (const_cast<M &> (data), s1, s2);
4127        return matrix_slice<const M> (data, s1, s2);
4128    }
4129    // ISSUE in the following two functions it would be logical to use matrix_slice<V>::range_type but this confuses VC7.1 and 8.0
4130    template<class M>
4131    BOOST_UBLAS_INLINE
4132    matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
4133        return data.project (r1, r2);
4134    }
4135    template<class M>
4136    BOOST_UBLAS_INLINE
4137    const matrix_slice<M> project (const matrix_slice<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
4138        return data.project (r1, r2);
4139    }
4140    template<class M>
4141    BOOST_UBLAS_INLINE
4142    matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
4143        return data.project (s1, s2);
4144    }
4145    template<class M>
4146    BOOST_UBLAS_INLINE
4147    const matrix_slice<M> project (const matrix_slice<M> &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
4148        return data.project (s1, s2);
4149    }
4150
4151    // Specialization of temporary_traits
4152    template <class M>
4153    struct matrix_temporary_traits< matrix_slice<M> >
4154    : matrix_temporary_traits< M > {};
4155    template <class M>
4156    struct matrix_temporary_traits< const matrix_slice<M> >
4157    : matrix_temporary_traits< M > {};
4158
4159    template <class M>
4160    struct vector_temporary_traits< matrix_slice<M> >
4161    : vector_temporary_traits< M > {};
4162    template <class M>
4163    struct vector_temporary_traits< const matrix_slice<M> >
4164    : vector_temporary_traits< M > {};
4165
4166    // Matrix based indirection class
4167    // Contributed by Toon Knapen.
4168    // Extended and optimized by Kresimir Fresl.
4169    template<class M, class IA>
4170    class matrix_indirect:
4171        public matrix_expression<matrix_indirect<M, IA> > {
4172
4173        typedef matrix_indirect<M, IA> self_type;
4174    public:
4175#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
4176        using matrix_expression<self_type>::operator ();
4177#endif
4178        typedef M matrix_type;
4179        typedef IA indirect_array_type;
4180        typedef typename M::size_type size_type;
4181        typedef typename M::difference_type difference_type;
4182        typedef typename M::value_type value_type;
4183        typedef typename M::const_reference const_reference;
4184        typedef typename boost::mpl::if_<boost::is_const<M>,
4185                                          typename M::const_reference,
4186                                          typename M::reference>::type reference;
4187        typedef typename boost::mpl::if_<boost::is_const<M>,
4188                                          typename M::const_closure_type,
4189                                          typename M::closure_type>::type matrix_closure_type;
4190        typedef basic_range<size_type, difference_type> range_type;
4191        typedef basic_slice<size_type, difference_type> slice_type;
4192        typedef const self_type const_closure_type;
4193        typedef self_type closure_type;
4194        typedef typename storage_restrict_traits<typename M::storage_category,
4195                                                 dense_proxy_tag>::storage_category storage_category;
4196        typedef typename M::orientation_category orientation_category;
4197
4198        // Construction and destruction
4199        BOOST_UBLAS_INLINE
4200        matrix_indirect (matrix_type &data, size_type size1, size_type size2):
4201            data_ (data), ia1_ (size1), ia2_ (size2) {}
4202        BOOST_UBLAS_INLINE
4203        matrix_indirect (matrix_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2):
4204            data_ (data), ia1_ (ia1.preprocess (data.size1 ())), ia2_ (ia2.preprocess (data.size2 ())) {}
4205        BOOST_UBLAS_INLINE
4206        matrix_indirect (const matrix_closure_type &data, const indirect_array_type &ia1, const indirect_array_type &ia2, int):
4207            data_ (data), ia1_ (ia1.preprocess (data.size1 ())), ia2_ (ia2.preprocess (data.size2 ())) {}
4208
4209        // Accessors
4210        BOOST_UBLAS_INLINE
4211        size_type size1 () const {
4212            return ia1_.size ();
4213        }
4214        BOOST_UBLAS_INLINE
4215        size_type size2 () const {
4216            return ia2_.size ();
4217        }
4218        BOOST_UBLAS_INLINE
4219        const indirect_array_type &indirect1 () const {
4220            return ia1_;
4221        }
4222        BOOST_UBLAS_INLINE
4223        indirect_array_type &indirect1 () {
4224            return ia1_;
4225        }
4226        BOOST_UBLAS_INLINE
4227        const indirect_array_type &indirect2 () const {
4228            return ia2_;
4229        }
4230        BOOST_UBLAS_INLINE
4231        indirect_array_type &indirect2 () {
4232            return ia2_;
4233        }
4234
4235        // Storage accessors
4236        BOOST_UBLAS_INLINE
4237        const matrix_closure_type &data () const {
4238            return data_;
4239        }
4240        BOOST_UBLAS_INLINE
4241        matrix_closure_type &data () {
4242            return data_;
4243        }
4244
4245        // Element access
4246#ifndef BOOST_UBLAS_PROXY_CONST_MEMBER
4247        BOOST_UBLAS_INLINE
4248        const_reference operator () (size_type i, size_type j) const {
4249            return data_ (ia1_ (i), ia2_ (j));
4250        }
4251        BOOST_UBLAS_INLINE
4252        reference operator () (size_type i, size_type j) {
4253            return data_ (ia1_ (i), ia2_ (j));
4254        }
4255#else
4256        BOOST_UBLAS_INLINE
4257        reference operator () (size_type i, size_type j) const {
4258            return data_ (ia1_ (i), ia2_ (j));
4259        }
4260#endif
4261
4262        // ISSUE can this be done in free project function?
4263        // Although a const function can create a non-const proxy to a non-const object
4264        // Critical is that matrix_type and data_ (vector_closure_type) are const correct
4265        BOOST_UBLAS_INLINE
4266        matrix_indirect<matrix_type, indirect_array_type> project (const range_type &r1, const range_type &r2) const {
4267            return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (r1.preprocess (data_.size1 ())), ia2_.compose (r2.preprocess (data_.size2 ())), 0);
4268        }
4269        BOOST_UBLAS_INLINE
4270        matrix_indirect<matrix_type, indirect_array_type> project (const slice_type &s1, const slice_type &s2) const {
4271            return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (s1.preprocess (data_.size1 ())), ia2_.compose (s2.preprocess (data_.size2 ())), 0);
4272        }
4273        BOOST_UBLAS_INLINE
4274        matrix_indirect<matrix_type, indirect_array_type> project (const indirect_array_type &ia1, const indirect_array_type &ia2) const {
4275            return matrix_indirect<matrix_type, indirect_array_type> (data_, ia1_.compose (ia1.preprocess (data_.size1 ())), ia2_.compose (ia2.preprocess (data_.size2 ())), 0);
4276        }
4277
4278        // Assignment
4279        BOOST_UBLAS_INLINE
4280        matrix_indirect &operator = (const matrix_indirect &mi) {
4281            matrix_assign<scalar_assign> (*this, mi);
4282            return *this;
4283        }
4284        BOOST_UBLAS_INLINE
4285        matrix_indirect &assign_temporary (matrix_indirect &mi) {
4286            return *this = mi;
4287        }
4288        template<class AE>
4289        BOOST_UBLAS_INLINE
4290        matrix_indirect &operator = (const matrix_expression<AE> &ae) {
4291            matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (ae));
4292            return *this;
4293        }
4294        template<class AE>
4295        BOOST_UBLAS_INLINE
4296        matrix_indirect &assign (const matrix_expression<AE> &ae) {
4297            matrix_assign<scalar_assign> (*this, ae);
4298            return *this;
4299        }
4300        template<class AE>
4301        BOOST_UBLAS_INLINE
4302        matrix_indirect& operator += (const matrix_expression<AE> &ae) {
4303            matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this + ae));
4304            return *this;
4305        }
4306        template<class AE>
4307        BOOST_UBLAS_INLINE
4308        matrix_indirect &plus_assign (const matrix_expression<AE> &ae) {
4309            matrix_assign<scalar_plus_assign> (*this, ae);
4310            return *this;
4311        }
4312        template<class AE>
4313        BOOST_UBLAS_INLINE
4314        matrix_indirect& operator -= (const matrix_expression<AE> &ae) {
4315            matrix_assign<scalar_assign> (*this, typename matrix_temporary_traits<M>::type (*this - ae));
4316            return *this;
4317        }
4318        template<class AE>
4319        BOOST_UBLAS_INLINE
4320        matrix_indirect &minus_assign (const matrix_expression<AE> &ae) {
4321            matrix_assign<scalar_minus_assign> (*this, ae);
4322            return *this;
4323        }
4324        template<class AT>
4325        BOOST_UBLAS_INLINE
4326        matrix_indirect& operator *= (const AT &at) {
4327            matrix_assign_scalar<scalar_multiplies_assign> (*this, at);
4328            return *this;
4329        }
4330        template<class AT>
4331        BOOST_UBLAS_INLINE
4332        matrix_indirect& operator /= (const AT &at) {
4333            matrix_assign_scalar<scalar_divides_assign> (*this, at);
4334            return *this;
4335        }
4336
4337        // Closure comparison
4338        BOOST_UBLAS_INLINE
4339        bool same_closure (const matrix_indirect &mi) const {
4340            return (*this).data_.same_closure (mi.data_);
4341        }
4342
4343        // Comparison
4344        BOOST_UBLAS_INLINE
4345        bool operator == (const matrix_indirect &mi) const {
4346            return (*this).data_ == mi.data_ && ia1_ == mi.ia1_ && ia2_ == mi.ia2_;
4347        }
4348
4349        // Swapping
4350        BOOST_UBLAS_INLINE
4351        void swap (matrix_indirect mi) {
4352            if (this != &mi) {
4353                BOOST_UBLAS_CHECK (size1 () == mi.size1 (), bad_size ());
4354                BOOST_UBLAS_CHECK (size2 () == mi.size2 (), bad_size ());
4355                matrix_swap<scalar_swap> (*this, mi);
4356            }
4357        }
4358        BOOST_UBLAS_INLINE
4359        friend void swap (matrix_indirect mi1, matrix_indirect mi2) {
4360            mi1.swap (mi2);
4361        }
4362
4363        // Iterator types
4364    private:
4365        typedef typename IA::const_iterator const_subiterator1_type;
4366        typedef typename IA::const_iterator subiterator1_type;
4367        typedef typename IA::const_iterator const_subiterator2_type;
4368        typedef typename IA::const_iterator subiterator2_type;
4369
4370    public:
4371#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4372        typedef indexed_iterator1<matrix_indirect<matrix_type, indirect_array_type>,
4373                                  typename matrix_type::iterator1::iterator_category> iterator1;
4374        typedef indexed_iterator2<matrix_indirect<matrix_type, indirect_array_type>,
4375                                  typename matrix_type::iterator2::iterator_category> iterator2;
4376        typedef indexed_const_iterator1<matrix_indirect<matrix_type, indirect_array_type>,
4377                                        typename matrix_type::const_iterator1::iterator_category> const_iterator1;
4378        typedef indexed_const_iterator2<matrix_indirect<matrix_type, indirect_array_type>,
4379                                        typename matrix_type::const_iterator2::iterator_category> const_iterator2;
4380#else
4381        class const_iterator1;
4382        class iterator1;
4383        class const_iterator2;
4384        class iterator2;
4385#endif
4386        typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
4387        typedef reverse_iterator_base1<iterator1> reverse_iterator1;
4388        typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
4389        typedef reverse_iterator_base2<iterator2> reverse_iterator2;
4390
4391        // Element lookup
4392        BOOST_UBLAS_INLINE
4393        const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
4394#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4395            return const_iterator1 (*this, i, j);
4396#else
4397            return const_iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j);
4398#endif
4399        }
4400        BOOST_UBLAS_INLINE
4401        iterator1 find1 (int /* rank */, size_type i, size_type j) {
4402#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4403            return iterator1 (*this, i, j);
4404#else
4405            return iterator1 (*this, ia1_.begin () + i, ia2_.begin () + j);
4406#endif
4407        }
4408        BOOST_UBLAS_INLINE
4409        const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
4410#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4411            return const_iterator2 (*this, i, j);
4412#else
4413            return const_iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j);
4414#endif
4415        }
4416        BOOST_UBLAS_INLINE
4417        iterator2 find2 (int /* rank */, size_type i, size_type j) {
4418#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
4419            return iterator2 (*this, i, j);
4420#else
4421            return iterator2 (*this, ia1_.begin () + i, ia2_.begin () + j);
4422#endif
4423        }
4424
4425        // Iterators simply are indices.
4426
4427#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4428        class const_iterator1:
4429            public container_const_reference<matrix_indirect>,
4430            public iterator_base_traits<typename M::const_iterator1::iterator_category>::template
4431                        iterator_base<const_iterator1, value_type>::type {
4432        public:
4433            typedef typename M::const_iterator1::value_type value_type;
4434            typedef typename M::const_iterator1::difference_type difference_type;
4435            typedef typename M::const_reference reference;    //FIXME due to indexing access
4436            typedef typename M::const_iterator1::pointer pointer;
4437            typedef const_iterator2 dual_iterator_type;
4438            typedef const_reverse_iterator2 dual_reverse_iterator_type;
4439
4440            // Construction and destruction
4441            BOOST_UBLAS_INLINE
4442            const_iterator1 ():
4443                container_const_reference<self_type> (), it1_ (), it2_ () {}
4444            BOOST_UBLAS_INLINE
4445            const_iterator1 (const self_type &mi, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
4446                container_const_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
4447            BOOST_UBLAS_INLINE
4448            const_iterator1 (const iterator1 &it):
4449                container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
4450
4451            // Arithmetic
4452            BOOST_UBLAS_INLINE
4453            const_iterator1 &operator ++ () {
4454                ++ it1_;
4455                return *this;
4456            }
4457            BOOST_UBLAS_INLINE
4458            const_iterator1 &operator -- () {
4459                -- it1_;
4460                return *this;
4461            }
4462            BOOST_UBLAS_INLINE
4463            const_iterator1 &operator += (difference_type n) {
4464                it1_ += n;
4465                return *this;
4466            }
4467            BOOST_UBLAS_INLINE
4468            const_iterator1 &operator -= (difference_type n) {
4469                it1_ -= n;
4470                return *this;
4471            }
4472            BOOST_UBLAS_INLINE
4473            difference_type operator - (const const_iterator1 &it) const {
4474                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4475                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4476                return it1_ - it.it1_;
4477            }
4478
4479            // Dereference
4480            BOOST_UBLAS_INLINE
4481            const_reference operator * () const {
4482                // FIXME replace find with at_element
4483                return (*this) ().data_ (*it1_, *it2_);
4484            }
4485            BOOST_UBLAS_INLINE
4486            const_reference operator [] (difference_type n) const {
4487                return *(*this + n);
4488            }
4489
4490#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4491            BOOST_UBLAS_INLINE
4492#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4493            typename self_type::
4494#endif
4495            const_iterator2 begin () const {
4496                return const_iterator2 ((*this) (), it1_, it2_ ().begin ());
4497            }
4498            BOOST_UBLAS_INLINE
4499#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4500            typename self_type::
4501#endif
4502            const_iterator2 end () const {
4503                return const_iterator2 ((*this) (), it1_, it2_ ().end ());
4504            }
4505            BOOST_UBLAS_INLINE
4506#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4507            typename self_type::
4508#endif
4509            const_reverse_iterator2 rbegin () const {
4510                return const_reverse_iterator2 (end ());
4511            }
4512            BOOST_UBLAS_INLINE
4513#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4514            typename self_type::
4515#endif
4516            const_reverse_iterator2 rend () const {
4517                return const_reverse_iterator2 (begin ());
4518            }
4519#endif
4520
4521            // Indices
4522            BOOST_UBLAS_INLINE
4523            size_type index1 () const {
4524                return it1_.index ();
4525            }
4526            BOOST_UBLAS_INLINE
4527            size_type index2 () const {
4528                return it2_.index ();
4529            }
4530
4531            // Assignment
4532            BOOST_UBLAS_INLINE
4533            const_iterator1 &operator = (const const_iterator1 &it) {
4534                container_const_reference<self_type>::assign (&it ());
4535                it1_ = it.it1_;
4536                it2_ = it.it2_;
4537                return *this;
4538            }
4539
4540            // Comparison
4541            BOOST_UBLAS_INLINE
4542            bool operator == (const const_iterator1 &it) const {
4543                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4544                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4545                return it1_ == it.it1_;
4546            }
4547            BOOST_UBLAS_INLINE
4548            bool operator < (const const_iterator1 &it) const {
4549                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4550                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4551                return it1_ < it.it1_;
4552            }
4553
4554        private:
4555            const_subiterator1_type it1_;
4556            const_subiterator2_type it2_;
4557        };
4558#endif
4559
4560        BOOST_UBLAS_INLINE
4561        const_iterator1 begin1 () const {
4562            return find1 (0, 0, 0);
4563        }
4564        BOOST_UBLAS_INLINE
4565        const_iterator1 end1 () const {
4566            return find1 (0, size1 (), 0);
4567        }
4568
4569#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4570        class iterator1:
4571            public container_reference<matrix_indirect>,
4572            public iterator_base_traits<typename M::iterator1::iterator_category>::template
4573                        iterator_base<iterator1, value_type>::type {
4574        public:
4575            typedef typename M::iterator1::value_type value_type;
4576            typedef typename M::iterator1::difference_type difference_type;
4577            typedef typename M::reference reference;    //FIXME due to indexing access
4578            typedef typename M::iterator1::pointer pointer;
4579            typedef iterator2 dual_iterator_type;
4580            typedef reverse_iterator2 dual_reverse_iterator_type;
4581
4582            // Construction and destruction
4583            BOOST_UBLAS_INLINE
4584            iterator1 ():
4585                container_reference<self_type> (), it1_ (), it2_ () {}
4586            BOOST_UBLAS_INLINE
4587            iterator1 (self_type &mi, const subiterator1_type &it1, const subiterator2_type &it2):
4588                container_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
4589
4590            // Arithmetic
4591            BOOST_UBLAS_INLINE
4592            iterator1 &operator ++ () {
4593                ++ it1_;
4594                return *this;
4595            }
4596            BOOST_UBLAS_INLINE
4597            iterator1 &operator -- () {
4598                -- it1_;
4599                return *this;
4600            }
4601            BOOST_UBLAS_INLINE
4602            iterator1 &operator += (difference_type n) {
4603                it1_ += n;
4604                return *this;
4605            }
4606            BOOST_UBLAS_INLINE
4607            iterator1 &operator -= (difference_type n) {
4608                it1_ -= n;
4609                return *this;
4610            }
4611            BOOST_UBLAS_INLINE
4612            difference_type operator - (const iterator1 &it) const {
4613                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4614                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4615                return it1_ - it.it1_;
4616            }
4617
4618            // Dereference
4619            BOOST_UBLAS_INLINE
4620            reference operator * () const {
4621                // FIXME replace find with at_element
4622                return (*this) ().data_ (*it1_, *it2_);
4623            }
4624            BOOST_UBLAS_INLINE
4625            reference operator [] (difference_type n) const {
4626                return *(*this + n);
4627            }
4628
4629#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4630            BOOST_UBLAS_INLINE
4631#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4632            typename self_type::
4633#endif
4634            iterator2 begin () const {
4635                return iterator2 ((*this) (), it1_, it2_ ().begin ());
4636            }
4637            BOOST_UBLAS_INLINE
4638#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4639            typename self_type::
4640#endif
4641            iterator2 end () const {
4642                return iterator2 ((*this) (), it1_, it2_ ().end ());
4643            }
4644            BOOST_UBLAS_INLINE
4645#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4646            typename self_type::
4647#endif
4648            reverse_iterator2 rbegin () const {
4649                return reverse_iterator2 (end ());
4650            }
4651            BOOST_UBLAS_INLINE
4652#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4653            typename self_type::
4654#endif
4655            reverse_iterator2 rend () const {
4656                return reverse_iterator2 (begin ());
4657            }
4658#endif
4659
4660            // Indices
4661            BOOST_UBLAS_INLINE
4662            size_type index1 () const {
4663                return it1_.index ();
4664            }
4665            BOOST_UBLAS_INLINE
4666            size_type index2 () const {
4667                return it2_.index ();
4668            }
4669
4670            // Assignment
4671            BOOST_UBLAS_INLINE
4672            iterator1 &operator = (const iterator1 &it) {
4673                container_reference<self_type>::assign (&it ());
4674                it1_ = it.it1_;
4675                it2_ = it.it2_;
4676                return *this;
4677            }
4678
4679            // Comparison
4680            BOOST_UBLAS_INLINE
4681            bool operator == (const iterator1 &it) const {
4682                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4683                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4684                return it1_ == it.it1_;
4685            }
4686            BOOST_UBLAS_INLINE
4687            bool operator < (const iterator1 &it) const {
4688                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4689                BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
4690                return it1_ < it.it1_;
4691            }
4692
4693        private:
4694            subiterator1_type it1_;
4695            subiterator2_type it2_;
4696
4697            friend class const_iterator1;
4698        };
4699#endif
4700
4701        BOOST_UBLAS_INLINE
4702        iterator1 begin1 () {
4703            return find1 (0, 0, 0);
4704        }
4705        BOOST_UBLAS_INLINE
4706        iterator1 end1 () {
4707            return find1 (0, size1 (), 0);
4708        }
4709
4710#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4711        class const_iterator2:
4712            public container_const_reference<matrix_indirect>,
4713            public iterator_base_traits<typename M::const_iterator2::iterator_category>::template
4714                        iterator_base<const_iterator2, value_type>::type {
4715        public:
4716            typedef typename M::const_iterator2::value_type value_type;
4717            typedef typename M::const_iterator2::difference_type difference_type;
4718            typedef typename M::const_reference reference;    //FIXME due to indexing access
4719            typedef typename M::const_iterator2::pointer pointer;
4720            typedef const_iterator1 dual_iterator_type;
4721            typedef const_reverse_iterator1 dual_reverse_iterator_type;
4722
4723            // Construction and destruction
4724            BOOST_UBLAS_INLINE
4725            const_iterator2 ():
4726                container_const_reference<self_type> (), it1_ (), it2_ () {}
4727            BOOST_UBLAS_INLINE
4728            const_iterator2 (const self_type &mi, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
4729                container_const_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
4730            BOOST_UBLAS_INLINE
4731            const_iterator2 (const iterator2 &it):
4732                container_const_reference<self_type> (it ()), it1_ (it.it1_), it2_ (it.it2_) {}
4733
4734            // Arithmetic
4735            BOOST_UBLAS_INLINE
4736            const_iterator2 &operator ++ () {
4737                ++ it2_;
4738                return *this;
4739            }
4740            BOOST_UBLAS_INLINE
4741            const_iterator2 &operator -- () {
4742                -- it2_;
4743                return *this;
4744            }
4745            BOOST_UBLAS_INLINE
4746            const_iterator2 &operator += (difference_type n) {
4747                it2_ += n;
4748                return *this;
4749            }
4750            BOOST_UBLAS_INLINE
4751            const_iterator2 &operator -= (difference_type n) {
4752                it2_ -= n;
4753                return *this;
4754            }
4755            BOOST_UBLAS_INLINE
4756            difference_type operator - (const const_iterator2 &it) const {
4757                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4758                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4759                return it2_ - it.it2_;
4760            }
4761
4762            // Dereference
4763            BOOST_UBLAS_INLINE
4764            const_reference operator * () const {
4765                // FIXME replace find with at_element
4766                return (*this) ().data_ (*it1_, *it2_);
4767            }
4768            BOOST_UBLAS_INLINE
4769            const_reference operator [] (difference_type n) const {
4770                return *(*this + n);
4771            }
4772
4773#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4774            BOOST_UBLAS_INLINE
4775#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4776            typename self_type::
4777#endif
4778            const_iterator1 begin () const {
4779                return const_iterator1 ((*this) (), it1_ ().begin (), it2_);
4780            }
4781            BOOST_UBLAS_INLINE
4782#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4783            typename self_type::
4784#endif
4785            const_iterator1 end () const {
4786                return const_iterator1 ((*this) (), it1_ ().end (), it2_);
4787            }
4788            BOOST_UBLAS_INLINE
4789#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4790            typename self_type::
4791#endif
4792            const_reverse_iterator1 rbegin () const {
4793                return const_reverse_iterator1 (end ());
4794            }
4795            BOOST_UBLAS_INLINE
4796#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4797            typename self_type::
4798#endif
4799            const_reverse_iterator1 rend () const {
4800                return const_reverse_iterator1 (begin ());
4801            }
4802#endif
4803
4804            // Indices
4805            BOOST_UBLAS_INLINE
4806            size_type index1 () const {
4807                return it1_.index ();
4808            }
4809            BOOST_UBLAS_INLINE
4810            size_type index2 () const {
4811                return it2_.index ();
4812            }
4813
4814            // Assignment
4815            BOOST_UBLAS_INLINE
4816            const_iterator2 &operator = (const const_iterator2 &it) {
4817                container_const_reference<self_type>::assign (&it ());
4818                it1_ = it.it1_;
4819                it2_ = it.it2_;
4820                return *this;
4821            }
4822
4823            // Comparison
4824            BOOST_UBLAS_INLINE
4825            bool operator == (const const_iterator2 &it) const {
4826                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4827                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4828                return it2_ == it.it2_;
4829            }
4830            BOOST_UBLAS_INLINE
4831            bool operator < (const const_iterator2 &it) const {
4832                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4833                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4834                return it2_ < it.it2_;
4835            }
4836
4837        private:
4838            const_subiterator1_type it1_;
4839            const_subiterator2_type it2_;
4840        };
4841#endif
4842
4843        BOOST_UBLAS_INLINE
4844        const_iterator2 begin2 () const {
4845            return find2 (0, 0, 0);
4846        }
4847        BOOST_UBLAS_INLINE
4848        const_iterator2 end2 () const {
4849            return find2 (0, 0, size2 ());
4850        }
4851
4852#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
4853        class iterator2:
4854            public container_reference<matrix_indirect>,
4855            public iterator_base_traits<typename M::iterator2::iterator_category>::template
4856                        iterator_base<iterator2, value_type>::type {
4857        public:
4858            typedef typename M::iterator2::value_type value_type;
4859            typedef typename M::iterator2::difference_type difference_type;
4860            typedef typename M::reference reference;    //FIXME due to indexing access
4861            typedef typename M::iterator2::pointer pointer;
4862            typedef iterator1 dual_iterator_type;
4863            typedef reverse_iterator1 dual_reverse_iterator_type;
4864
4865            // Construction and destruction
4866            BOOST_UBLAS_INLINE
4867            iterator2 ():
4868                container_reference<self_type> (), it1_ (), it2_ () {}
4869            BOOST_UBLAS_INLINE
4870            iterator2 (self_type &mi, const subiterator1_type &it1, const subiterator2_type &it2):
4871                container_reference<self_type> (mi), it1_ (it1), it2_ (it2) {}
4872
4873            // Arithmetic
4874            BOOST_UBLAS_INLINE
4875            iterator2 &operator ++ () {
4876                ++ it2_;
4877                return *this;
4878            }
4879            BOOST_UBLAS_INLINE
4880            iterator2 &operator -- () {
4881                -- it2_;
4882                return *this;
4883            }
4884            BOOST_UBLAS_INLINE
4885            iterator2 &operator += (difference_type n) {
4886                it2_ += n;
4887                return *this;
4888            }
4889            BOOST_UBLAS_INLINE
4890            iterator2 &operator -= (difference_type n) {
4891                it2_ -= n;
4892                return *this;
4893            }
4894            BOOST_UBLAS_INLINE
4895            difference_type operator - (const iterator2 &it) const {
4896                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4897                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4898                return it2_ - it.it2_;
4899            }
4900
4901            // Dereference
4902            BOOST_UBLAS_INLINE
4903            reference operator * () const {
4904                // FIXME replace find with at_element
4905                return (*this) ().data_ (*it1_, *it2_);
4906            }
4907            BOOST_UBLAS_INLINE
4908            reference operator [] (difference_type n) const {
4909                return *(*this + n);
4910            }
4911
4912#ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
4913            BOOST_UBLAS_INLINE
4914#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4915            typename self_type::
4916#endif
4917            iterator1 begin () const {
4918                return iterator1 ((*this) (), it1_ ().begin (), it2_);
4919            }
4920            BOOST_UBLAS_INLINE
4921#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4922            typename self_type::
4923#endif
4924            iterator1 end () const {
4925                return iterator1 ((*this) (), it1_ ().end (), it2_);
4926            }
4927            BOOST_UBLAS_INLINE
4928#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4929            typename self_type::
4930#endif
4931            reverse_iterator1 rbegin () const {
4932                return reverse_iterator1 (end ());
4933            }
4934            BOOST_UBLAS_INLINE
4935#ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
4936            typename self_type::
4937#endif
4938            reverse_iterator1 rend () const {
4939                return reverse_iterator1 (begin ());
4940            }
4941#endif
4942
4943            // Indices
4944            BOOST_UBLAS_INLINE
4945            size_type index1 () const {
4946                return it1_.index ();
4947            }
4948            BOOST_UBLAS_INLINE
4949            size_type index2 () const {
4950                return it2_.index ();
4951            }
4952
4953            // Assignment
4954            BOOST_UBLAS_INLINE
4955            iterator2 &operator = (const iterator2 &it) {
4956                container_reference<self_type>::assign (&it ());
4957                it1_ = it.it1_;
4958                it2_ = it.it2_;
4959                return *this;
4960            }
4961
4962            // Comparison
4963            BOOST_UBLAS_INLINE
4964            bool operator == (const iterator2 &it) const {
4965                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4966                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4967                return it2_ == it.it2_;
4968            }
4969            BOOST_UBLAS_INLINE
4970            bool operator < (const iterator2 &it) const {
4971                BOOST_UBLAS_CHECK ((*this) ().same_closure  (it ()), external_logic ());
4972                BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
4973                return it2_ < it.it2_;
4974            }
4975
4976        private:
4977            subiterator1_type it1_;
4978            subiterator2_type it2_;
4979
4980            friend class const_iterator2;
4981        };
4982#endif
4983
4984        BOOST_UBLAS_INLINE
4985        iterator2 begin2 () {
4986            return find2 (0, 0, 0);
4987        }
4988        BOOST_UBLAS_INLINE
4989        iterator2 end2 () {
4990            return find2 (0, 0, size2 ());
4991        }
4992
4993        // Reverse iterators
4994
4995        BOOST_UBLAS_INLINE
4996        const_reverse_iterator1 rbegin1 () const {
4997            return const_reverse_iterator1 (end1 ());
4998        }
4999        BOOST_UBLAS_INLINE
5000        const_reverse_iterator1 rend1 () const {
5001            return const_reverse_iterator1 (begin1 ());
5002        }
5003
5004        BOOST_UBLAS_INLINE
5005        reverse_iterator1 rbegin1 () {
5006            return reverse_iterator1 (end1 ());
5007        }
5008        BOOST_UBLAS_INLINE
5009        reverse_iterator1 rend1 () {
5010            return reverse_iterator1 (begin1 ());
5011        }
5012
5013        BOOST_UBLAS_INLINE
5014        const_reverse_iterator2 rbegin2 () const {
5015            return const_reverse_iterator2 (end2 ());
5016        }
5017        BOOST_UBLAS_INLINE
5018        const_reverse_iterator2 rend2 () const {
5019            return const_reverse_iterator2 (begin2 ());
5020        }
5021
5022        BOOST_UBLAS_INLINE
5023        reverse_iterator2 rbegin2 () {
5024            return reverse_iterator2 (end2 ());
5025        }
5026        BOOST_UBLAS_INLINE
5027        reverse_iterator2 rend2 () {
5028            return reverse_iterator2 (begin2 ());
5029        }
5030
5031    private:
5032        matrix_closure_type data_;
5033        indirect_array_type ia1_;
5034        indirect_array_type ia2_;
5035    };
5036
5037    // Projections
5038    template<class M, class A>
5039    BOOST_UBLAS_INLINE
5040    matrix_indirect<M, indirect_array<A> > project (M &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
5041        return matrix_indirect<M, indirect_array<A> > (data, ia1, ia2);
5042    }
5043    template<class M, class A>
5044    BOOST_UBLAS_INLINE
5045    const matrix_indirect<const M, indirect_array<A> > project (const M &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
5046        // ISSUE was: return matrix_indirect<M, indirect_array<A> > (const_cast<M &> (data), ia1, ia2);
5047        return matrix_indirect<const M, indirect_array<A> > (data, ia1, ia2);
5048    }
5049    template<class M, class IA>
5050    BOOST_UBLAS_INLINE
5051    matrix_indirect<M, IA> project (matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::range_type &r1, const typename matrix_indirect<M, IA>::range_type &r2) {
5052        return data.project (r1, r2);
5053    }
5054    template<class M, class IA>
5055    BOOST_UBLAS_INLINE
5056    const matrix_indirect<M, IA> project (const matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::range_type &r1, const typename matrix_indirect<M, IA>::range_type &r2) {
5057        return data.project (r1, r2);
5058    }
5059    template<class M, class IA>
5060    BOOST_UBLAS_INLINE
5061    matrix_indirect<M, IA> project (matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::slice_type &s1, const typename matrix_indirect<M, IA>::slice_type &s2) {
5062        return data.project (s1, s2);
5063    }
5064    template<class M, class IA>
5065    BOOST_UBLAS_INLINE
5066    const matrix_indirect<M, IA> project (const matrix_indirect<M, IA> &data, const typename matrix_indirect<M, IA>::slice_type &s1, const typename matrix_indirect<M, IA>::slice_type &s2) {
5067        return data.project (s1, s2);
5068    }
5069    template<class M, class A>
5070    BOOST_UBLAS_INLINE
5071    matrix_indirect<M, indirect_array<A> > project (matrix_indirect<M, indirect_array<A> > &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
5072        return data.project (ia1, ia2);
5073    }
5074    template<class M, class A>
5075    BOOST_UBLAS_INLINE
5076    const matrix_indirect<M, indirect_array<A> > project (const matrix_indirect<M, indirect_array<A> > &data, const indirect_array<A> &ia1, const indirect_array<A> &ia2) {
5077        return data.project (ia1, ia2);
5078    }
5079
5080    /// Specialization of temporary_traits
5081    template <class M>
5082    struct matrix_temporary_traits< matrix_indirect<M> >
5083    : matrix_temporary_traits< M > {};
5084    template <class M>
5085    struct matrix_temporary_traits< const matrix_indirect<M> >
5086    : matrix_temporary_traits< M > {};
5087
5088    template <class M>
5089    struct vector_temporary_traits< matrix_indirect<M> >
5090    : vector_temporary_traits< M > {};
5091    template <class M>
5092    struct vector_temporary_traits< const matrix_indirect<M> >
5093    : vector_temporary_traits< M > {};
5094
5095}}}
5096
5097#endif
Note: See TracBrowser for help on using the repository browser.