ublas: matrix_expression.hpp Source File

- Main Page
- Related Pages
- Classes
- Files

- File List

# matrix_expression.hpp

    00001 //
    00002 //  Copyright (c) 2000-2002
    00003 //  Joerg Walter, Mathias Koch
    00004 //
    00005 //  Distributed under the Boost Software License, Version 1.0. (See
    00006 //  accompanying file LICENSE_1_0.txt or copy at
    00007 //  http://www.boost.org/LICENSE_1_0.txt)
    00008 //
    00009 //  The authors gratefully acknowledge the support of
    00010 //  GeNeSys mbH & Co. KG in producing this work.
    00011 //
    00012
    00013 #ifndef _BOOST_UBLAS_MATRIX_EXPRESSION_
    00014 #define _BOOST_UBLAS_MATRIX_EXPRESSION_
    00015
    00016 #include <boost/numeric/ublas/vector_expression.hpp>
    00017
    00018 // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
    00019 // Iterators based on ideas of Jeremy Siek
    00020 //
    00021 // Classes that model the Matrix Expression concept
    00022
    00023 namespace boost { namespace numeric { namespace ublas {
    00024
    00025     template<class E>
    00026     class matrix_reference:
    00027         public matrix_expression<matrix_reference<E> > {
    00028
    00029         typedef matrix_reference<E> self_type;
    00030     public:
    00031 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    00032         using matrix_expression<self_type>::operator ();
    00033 #endif
    00034         typedef typename E::size_type size_type;
    00035         typedef typename E::difference_type difference_type;
    00036         typedef typename E::value_type value_type;
    00037         typedef typename E::const_reference const_reference;
    00038         typedef typename boost::mpl::if_<boost::is_const<E>,
    00039                                           typename E::const_reference,
    00040                                           typename E::reference>::type reference;
    00041         typedef E referred_type;
    00042         typedef const self_type const_closure_type;
    00043         typedef self_type closure_type;
    00044         typedef typename E::orientation_category orientation_category;
    00045         typedef typename E::storage_category storage_category;
    00046
    00047         // Construction and destruction
    00048         BOOST_UBLAS_INLINE
    00049         explicit matrix_reference (referred_type &e):
    00050               e_ (e) {}
    00051
    00052         // Accessors
    00053         BOOST_UBLAS_INLINE
    00054         size_type size1 () const {
    00055             return e_.size1 ();
    00056         }
    00057         BOOST_UBLAS_INLINE
    00058         size_type size2 () const {
    00059             return e_.size2 ();
    00060         }
    00061
    00062     public:
    00063         // Expression accessors - const correct
    00064         BOOST_UBLAS_INLINE
    00065         const referred_type &expression () const {
    00066             return e_;
    00067         }
    00068         BOOST_UBLAS_INLINE
    00069         referred_type &expression () {
    00070             return e_;
    00071         }
    00072
    00073     public:
    00074         // Element access
    00075 #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
    00076         BOOST_UBLAS_INLINE
    00077         const_reference operator () (size_type i, size_type j) const {
    00078             return expression () (i, j);
    00079         }
    00080         BOOST_UBLAS_INLINE
    00081         reference operator () (size_type i, size_type j) {
    00082             return expression () (i, j);
    00083         }
    00084 #else
    00085         BOOST_UBLAS_INLINE
    00086         reference operator () (size_type i, size_type j) const {
    00087             return expression () (i, j);
    00088         }
    00089 #endif
    00090
    00091         // Assignment
    00092         BOOST_UBLAS_INLINE
    00093         matrix_reference &operator = (const matrix_reference &m) {
    00094             expression ().operator = (m);
    00095             return *this;
    00096         }
    00097         template<class AE>
    00098         BOOST_UBLAS_INLINE
    00099         matrix_reference &operator = (const matrix_expression<AE> &ae) {
    00100             expression ().operator = (ae);
    00101             return *this;
    00102         }
    00103         template<class AE>
    00104         BOOST_UBLAS_INLINE
    00105         matrix_reference &assign (const matrix_expression<AE> &ae) {
    00106             expression ().assign (ae);
    00107             return *this;
    00108         }
    00109         template<class AE>
    00110         BOOST_UBLAS_INLINE
    00111         matrix_reference &operator += (const matrix_expression<AE> &ae) {
    00112             expression ().operator += (ae);
    00113             return *this;
    00114         }
    00115         template<class AE>
    00116         BOOST_UBLAS_INLINE
    00117         matrix_reference &plus_assign (const matrix_expression<AE> &ae) {
    00118             expression ().plus_assign (ae);
    00119             return *this;
    00120         }
    00121         template<class AE>
    00122         BOOST_UBLAS_INLINE
    00123         matrix_reference &operator -= (const matrix_expression<AE> &ae) {
    00124             expression ().operator -= (ae);
    00125             return *this;
    00126         }
    00127         template<class AE>
    00128         BOOST_UBLAS_INLINE
    00129         matrix_reference &minus_assign (const matrix_expression<AE> &ae) {
    00130             expression ().minus_assign (ae);
    00131             return *this;
    00132         }
    00133         template<class AT>
    00134         BOOST_UBLAS_INLINE
    00135         matrix_reference &operator *= (const AT &at) {
    00136             expression ().operator *= (at);
    00137             return *this;
    00138         }
    00139         template<class AT>
    00140         BOOST_UBLAS_INLINE
    00141         matrix_reference &operator /= (const AT &at) {
    00142             expression ().operator /= (at);
    00143             return *this;
    00144         }
    00145
    00146          // Swapping
    00147         BOOST_UBLAS_INLINE
    00148         void swap (matrix_reference &m) {
    00149             expression ().swap (m.expression ());
    00150         }
    00151
    00152         // Closure comparison
    00153         BOOST_UBLAS_INLINE
    00154         bool same_closure (const matrix_reference &mr) const {
    00155             return &(*this).e_ == &mr.e_;
    00156         }
    00157
    00158         // Iterator types
    00159         typedef typename E::const_iterator1 const_iterator1;
    00160         typedef typename boost::mpl::if_<boost::is_const<E>,
    00161                                           typename E::const_iterator1,
    00162                                           typename E::iterator1>::type iterator1;
    00163         typedef typename E::const_iterator2 const_iterator2;
    00164         typedef typename boost::mpl::if_<boost::is_const<E>,
    00165                                           typename E::const_iterator2,
    00166                                           typename E::iterator2>::type iterator2;
    00167
    00168         // Element lookup
    00169         BOOST_UBLAS_INLINE
    00170         const_iterator1 find1 (int rank, size_type i, size_type j) const {
    00171             return expression ().find1 (rank, i, j);
    00172         }
    00173         BOOST_UBLAS_INLINE
    00174         iterator1 find1 (int rank, size_type i, size_type j) {
    00175             return expression ().find1 (rank, i, j);
    00176         }
    00177         BOOST_UBLAS_INLINE
    00178         const_iterator2 find2 (int rank, size_type i, size_type j) const {
    00179             return expression ().find2 (rank, i, j);
    00180         }
    00181         BOOST_UBLAS_INLINE
    00182         iterator2 find2 (int rank, size_type i, size_type j) {
    00183             return expression ().find2 (rank, i, j);
    00184         }
    00185
    00186         // Iterators are the iterators of the referenced expression.
    00187
    00188         BOOST_UBLAS_INLINE
    00189         const_iterator1 begin1 () const {
    00190             return expression ().begin1 ();
    00191         }
    00192         BOOST_UBLAS_INLINE
    00193         const_iterator1 end1 () const {
    00194             return expression ().end1 ();
    00195         }
    00196
    00197         BOOST_UBLAS_INLINE
    00198         iterator1 begin1 () {
    00199             return expression ().begin1 ();
    00200         }
    00201         BOOST_UBLAS_INLINE
    00202         iterator1 end1 () {
    00203             return expression ().end1 ();
    00204         }
    00205
    00206         BOOST_UBLAS_INLINE
    00207         const_iterator2 begin2 () const {
    00208             return expression ().begin2 ();
    00209         }
    00210         BOOST_UBLAS_INLINE
    00211         const_iterator2 end2 () const {
    00212             return expression ().end2 ();
    00213         }
    00214
    00215         BOOST_UBLAS_INLINE
    00216         iterator2 begin2 () {
    00217             return expression ().begin2 ();
    00218         }
    00219         BOOST_UBLAS_INLINE
    00220         iterator2 end2 () {
    00221             return expression ().end2 ();
    00222         }
    00223
    00224         // Reverse iterators
    00225         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    00226         typedef reverse_iterator_base1<iterator1> reverse_iterator1;
    00227
    00228         BOOST_UBLAS_INLINE
    00229         const_reverse_iterator1 rbegin1 () const {
    00230             return const_reverse_iterator1 (end1 ());
    00231         }
    00232         BOOST_UBLAS_INLINE
    00233         const_reverse_iterator1 rend1 () const {
    00234             return const_reverse_iterator1 (begin1 ());
    00235         }
    00236
    00237         BOOST_UBLAS_INLINE
    00238         reverse_iterator1 rbegin1 () {
    00239             return reverse_iterator1 (end1 ());
    00240         }
    00241         BOOST_UBLAS_INLINE
    00242         reverse_iterator1 rend1 () {
    00243             return reverse_iterator1 (begin1 ());
    00244         }
    00245
    00246         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    00247         typedef reverse_iterator_base2<iterator2> reverse_iterator2;
    00248
    00249         BOOST_UBLAS_INLINE
    00250         const_reverse_iterator2 rbegin2 () const {
    00251             return const_reverse_iterator2 (end2 ());
    00252         }
    00253         BOOST_UBLAS_INLINE
    00254         const_reverse_iterator2 rend2 () const {
    00255             return const_reverse_iterator2 (begin2 ());
    00256         }
    00257
    00258         BOOST_UBLAS_INLINE
    00259         reverse_iterator2 rbegin2 () {
    00260             return reverse_iterator2 (end2 ());
    00261         }
    00262         BOOST_UBLAS_INLINE
    00263         reverse_iterator2 rend2 () {
    00264             return reverse_iterator2 (begin2 ());
    00265         }
    00266
    00267     private:
    00268         referred_type &e_;
    00269     };
    00270
    00271
    00272     template<class E1, class E2, class F>
    00273     class vector_matrix_binary:
    00274         public matrix_expression<vector_matrix_binary<E1, E2, F> > {
    00275
    00276         typedef E1 expression1_type;
    00277         typedef E2 expression2_type;
    00278     public:
    00279         typedef typename E1::const_closure_type expression1_closure_type;
    00280         typedef typename E2::const_closure_type expression2_closure_type;
    00281     private:
    00282         typedef vector_matrix_binary<E1, E2, F> self_type;
    00283     public:
    00284 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    00285         using matrix_expression<self_type>::operator ();
    00286 #endif
    00287         typedef F functor_type;
    00288         typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
    00289         typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
    00290         typedef typename F::result_type value_type;
    00291         typedef value_type const_reference;
    00292         typedef const_reference reference;
    00293         typedef const self_type const_closure_type;
    00294         typedef const_closure_type closure_type;
    00295         typedef unknown_orientation_tag orientation_category;
    00296         typedef unknown_storage_tag storage_category;
    00297
    00298         // Construction and destruction
    00299         BOOST_UBLAS_INLINE
    00300         vector_matrix_binary (const expression1_type &e1, const expression2_type &e2):
    00301             e1_ (e1), e2_ (e2) {}
    00302
    00303         // Accessors
    00304         BOOST_UBLAS_INLINE
    00305         size_type size1 () const {
    00306             return e1_.size ();
    00307         }
    00308         BOOST_UBLAS_INLINE
    00309         size_type size2 () const {
    00310             return e2_.size ();
    00311         }
    00312
    00313     public:
    00314         // Expression accessors
    00315         BOOST_UBLAS_INLINE
    00316         const expression1_closure_type &expression1 () const {
    00317             return e1_;
    00318         }
    00319         BOOST_UBLAS_INLINE
    00320         const expression2_closure_type &expression2 () const {
    00321             return e2_;
    00322         }
    00323
    00324     public:
    00325         // Element access
    00326         BOOST_UBLAS_INLINE
    00327         const_reference operator () (size_type i, size_type j) const {
    00328             return functor_type::apply (e1_ (i), e2_ (j));
    00329         }
    00330
    00331         // Closure comparison
    00332         BOOST_UBLAS_INLINE
    00333         bool same_closure (const vector_matrix_binary &vmb) const {
    00334             return (*this).expression1 ().same_closure (vmb.expression1 ()) &&
    00335                    (*this).expression2 ().same_closure (vmb.expression2 ());
    00336         }
    00337
    00338         // Iterator types
    00339     private:
    00340         typedef typename E1::const_iterator const_subiterator1_type;
    00341         typedef typename E2::const_iterator const_subiterator2_type;
    00342         typedef const value_type *const_pointer;
    00343
    00344     public:
    00345 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00346         typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
    00347                                                   typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
    00348         typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
    00349         typedef const_iterator1 iterator1;
    00350         typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
    00351         typedef const_iterator2 iterator2;
    00352 #else
    00353         class const_iterator1;
    00354         typedef const_iterator1 iterator1;
    00355         class const_iterator2;
    00356         typedef const_iterator2 iterator2;
    00357 #endif
    00358         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    00359         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    00360
    00361         // Element lookup
    00362         BOOST_UBLAS_INLINE
    00363         const_iterator1 find1 (int rank, size_type i, size_type j) const {
    00364             const_subiterator1_type it1 (e1_.find (i));
    00365             const_subiterator1_type it1_end (e1_.find (size1 ()));
    00366             const_subiterator2_type it2 (e2_.find (j));
    00367             const_subiterator2_type it2_end (e2_.find (size2 ()));
    00368             if (it2 == it2_end || (rank == 1 && (it2.index () != j || *it2 == value_type/*zero*/()))) {
    00369                 it1 = it1_end;
    00370                 it2 = it2_end;
    00371             }
    00372 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00373             return const_iterator1 (*this, it1.index (), it2.index ());
    00374 #else
    00375 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    00376             return const_iterator1 (*this, it1, it2, it2 != it2_end ? *it2 : value_type/*zero*/());
    00377 #else
    00378             return const_iterator1 (*this, it1, it2);
    00379 #endif
    00380 #endif
    00381         }
    00382         BOOST_UBLAS_INLINE
    00383         const_iterator2 find2 (int rank, size_type i, size_type j) const {
    00384             const_subiterator2_type it2 (e2_.find (j));
    00385             const_subiterator2_type it2_end (e2_.find (size2 ()));
    00386             const_subiterator1_type it1 (e1_.find (i));
    00387             const_subiterator1_type it1_end (e1_.find (size1 ()));
    00388             if (it1 == it1_end || (rank == 1 && (it1.index () != i || *it1 == value_type/*zero*/()))) {
    00389                 it2 = it2_end;
    00390                 it1 = it1_end;
    00391             }
    00392 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00393             return const_iterator2 (*this, it1.index (), it2.index ());
    00394 #else
    00395 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    00396             return const_iterator2 (*this, it1, it2, it1 != it1_end ? *it1 : value_type/*zero*/());
    00397 #else
    00398             return const_iterator2 (*this, it1, it2);
    00399 #endif
    00400 #endif
    00401         }
    00402
    00403         // Iterators enhance the iterators of the referenced expressions
    00404         // with the binary functor.
    00405
    00406 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00407         class const_iterator1:
    00408             public container_const_reference<vector_matrix_binary>,
    00409             public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
    00410                                                                           typename E2::const_iterator::iterator_category>::iterator_category>::template
    00411                 iterator_base<const_iterator1, value_type>::type {
    00412         public:
    00413             typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
    00414                                                       typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
    00415             typedef typename vector_matrix_binary::difference_type difference_type;
    00416             typedef typename vector_matrix_binary::value_type value_type;
    00417             typedef typename vector_matrix_binary::const_reference reference;
    00418             typedef typename vector_matrix_binary::const_pointer pointer;
    00419
    00420             typedef const_iterator2 dual_iterator_type;
    00421             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    00422
    00423             // Construction and destruction
    00424 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    00425             BOOST_UBLAS_INLINE
    00426             const_iterator1 ():
    00427                 container_const_reference<self_type> (), it1_ (), it2_ (), t2_ () {}
    00428             BOOST_UBLAS_INLINE
    00429             const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t2):
    00430                 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t2_ (t2) {}
    00431 #else
    00432             BOOST_UBLAS_INLINE
    00433             const_iterator1 ():
    00434                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    00435             BOOST_UBLAS_INLINE
    00436             const_iterator1 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
    00437                 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
    00438 #endif
    00439
    00440             // Arithmetic
    00441             BOOST_UBLAS_INLINE
    00442             const_iterator1 &operator ++ () {
    00443                 ++ it1_;
    00444                 return *this;
    00445             }
    00446             BOOST_UBLAS_INLINE
    00447             const_iterator1 &operator -- () {
    00448                 -- it1_;
    00449                 return *this;
    00450             }
    00451             BOOST_UBLAS_INLINE
    00452             const_iterator1 &operator += (difference_type n) {
    00453                 it1_ += n;
    00454                 return *this;
    00455             }
    00456             BOOST_UBLAS_INLINE
    00457             const_iterator1 &operator -= (difference_type n) {
    00458                 it1_ -= n;
    00459                 return *this;
    00460             }
    00461             BOOST_UBLAS_INLINE
    00462             difference_type operator - (const const_iterator1 &it) const {
    00463                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00464                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    00465                 return it1_ - it.it1_;
    00466             }
    00467
    00468             // Dereference
    00469             BOOST_UBLAS_INLINE
    00470             const_reference operator * () const {
    00471 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    00472                 return functor_type::apply (*it1_, t2_);
    00473 #else
    00474                 return functor_type::apply (*it1_, *it2_);
    00475 #endif
    00476             }
    00477             BOOST_UBLAS_INLINE
    00478             const_reference operator [] (difference_type n) const {
    00479                 return *(*this + n);
    00480             }
    00481
    00482 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00483             BOOST_UBLAS_INLINE
    00484 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00485             typename self_type::
    00486 #endif
    00487             const_iterator2 begin () const {
    00488                 return (*this) ().find2 (1, index1 (), 0);
    00489             }
    00490             BOOST_UBLAS_INLINE
    00491 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00492             typename self_type::
    00493 #endif
    00494             const_iterator2 end () const {
    00495                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
    00496             }
    00497             BOOST_UBLAS_INLINE
    00498 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00499             typename self_type::
    00500 #endif
    00501             const_reverse_iterator2 rbegin () const {
    00502                 return const_reverse_iterator2 (end ());
    00503             }
    00504             BOOST_UBLAS_INLINE
    00505 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00506             typename self_type::
    00507 #endif
    00508             const_reverse_iterator2 rend () const {
    00509                 return const_reverse_iterator2 (begin ());
    00510             }
    00511 #endif
    00512
    00513             // Indices
    00514             BOOST_UBLAS_INLINE
    00515             size_type index1 () const {
    00516                 return it1_.index ();
    00517             }
    00518             BOOST_UBLAS_INLINE
    00519             size_type  index2 () const {
    00520                 return it2_.index ();
    00521             }
    00522
    00523             // Assignment
    00524             BOOST_UBLAS_INLINE
    00525             const_iterator1 &operator = (const const_iterator1 &it) {
    00526                 container_const_reference<self_type>::assign (&it ());
    00527                 it1_ = it.it1_;
    00528                 it2_ = it.it2_;
    00529 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    00530                 t2_ = it.t2_;
    00531 #endif
    00532                 return *this;
    00533             }
    00534
    00535             // Comparison
    00536             BOOST_UBLAS_INLINE
    00537             bool operator == (const const_iterator1 &it) const {
    00538                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00539                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    00540                 return it1_ == it.it1_;
    00541             }
    00542             BOOST_UBLAS_INLINE
    00543             bool operator < (const const_iterator1 &it) const {
    00544                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00545                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    00546                 return it1_ < it.it1_;
    00547             }
    00548
    00549         private:
    00550 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    00551             const_subiterator1_type it1_;
    00552             // Mutable due to assignment
    00553             /* const */ const_subiterator2_type it2_;
    00554             value_type t2_;
    00555 #else
    00556             const_subiterator1_type it1_;
    00557             const_subiterator2_type it2_;
    00558 #endif
    00559         };
    00560 #endif
    00561
    00562         BOOST_UBLAS_INLINE
    00563         const_iterator1 begin1 () const {
    00564             return find1 (0, 0, 0);
    00565         }
    00566         BOOST_UBLAS_INLINE
    00567         const_iterator1 end1 () const {
    00568             return find1 (0, size1 (), 0);
    00569         }
    00570
    00571 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00572         class const_iterator2:
    00573             public container_const_reference<vector_matrix_binary>,
    00574             public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
    00575                                                                           typename E2::const_iterator::iterator_category>::iterator_category>::template
    00576                 iterator_base<const_iterator2, value_type>::type {
    00577         public:
    00578             typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
    00579                                                       typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
    00580             typedef typename vector_matrix_binary::difference_type difference_type;
    00581             typedef typename vector_matrix_binary::value_type value_type;
    00582             typedef typename vector_matrix_binary::const_reference reference;
    00583             typedef typename vector_matrix_binary::const_pointer pointer;
    00584
    00585             typedef const_iterator1 dual_iterator_type;
    00586             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    00587
    00588             // Construction and destruction
    00589 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    00590             BOOST_UBLAS_INLINE
    00591             const_iterator2 ():
    00592                 container_const_reference<self_type> (), it1_ (), it2_ (), t1_ () {}
    00593             BOOST_UBLAS_INLINE
    00594             const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2, value_type t1):
    00595                 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2), t1_ (t1) {}
    00596 #else
    00597             BOOST_UBLAS_INLINE
    00598             const_iterator2 ():
    00599                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    00600             BOOST_UBLAS_INLINE
    00601             const_iterator2 (const self_type &vmb, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
    00602                 container_const_reference<self_type> (vmb), it1_ (it1), it2_ (it2) {}
    00603 #endif
    00604
    00605             // Arithmetic
    00606             BOOST_UBLAS_INLINE
    00607             const_iterator2 &operator ++ () {
    00608                 ++ it2_;
    00609                 return *this;
    00610             }
    00611             BOOST_UBLAS_INLINE
    00612             const_iterator2 &operator -- () {
    00613                 -- it2_;
    00614                 return *this;
    00615             }
    00616             BOOST_UBLAS_INLINE
    00617             const_iterator2 &operator += (difference_type n) {
    00618                 it2_ += n;
    00619                 return *this;
    00620             }
    00621             BOOST_UBLAS_INLINE
    00622             const_iterator2 &operator -= (difference_type n) {
    00623                 it2_ -= n;
    00624                 return *this;
    00625             }
    00626             BOOST_UBLAS_INLINE
    00627             difference_type operator - (const const_iterator2 &it) const {
    00628                 BOOST_UBLAS_CHECK ((*this) ().same_closure(it ()), external_logic ());
    00629                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    00630                 return it2_ - it.it2_;
    00631             }
    00632
    00633             // Dereference
    00634             BOOST_UBLAS_INLINE
    00635             const_reference operator * () const {
    00636 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    00637                 return functor_type::apply (t1_, *it2_);
    00638 #else
    00639                 return functor_type::apply (*it1_, *it2_);
    00640 #endif
    00641             }
    00642             BOOST_UBLAS_INLINE
    00643             const_reference operator [] (difference_type n) const {
    00644                 return *(*this + n);
    00645             }
    00646
    00647 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00648             BOOST_UBLAS_INLINE
    00649 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00650             typename self_type::
    00651 #endif
    00652             const_iterator1 begin () const {
    00653                 return (*this) ().find1 (1, 0, index2 ());
    00654             }
    00655             BOOST_UBLAS_INLINE
    00656 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00657             typename self_type::
    00658 #endif
    00659             const_iterator1 end () const {
    00660                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
    00661             }
    00662             BOOST_UBLAS_INLINE
    00663 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00664             typename self_type::
    00665 #endif
    00666             const_reverse_iterator1 rbegin () const {
    00667                 return const_reverse_iterator1 (end ());
    00668             }
    00669             BOOST_UBLAS_INLINE
    00670 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00671             typename self_type::
    00672 #endif
    00673             const_reverse_iterator1 rend () const {
    00674                 return const_reverse_iterator1 (begin ());
    00675             }
    00676 #endif
    00677
    00678             // Indices
    00679             BOOST_UBLAS_INLINE
    00680             size_type index1 () const {
    00681                 return it1_.index ();
    00682             }
    00683             BOOST_UBLAS_INLINE
    00684             size_type  index2 () const {
    00685                 return it2_.index ();
    00686             }
    00687
    00688             // Assignment
    00689             BOOST_UBLAS_INLINE
    00690             const_iterator2 &operator = (const const_iterator2 &it) {
    00691                 container_const_reference<self_type>::assign (&it ());
    00692                 it1_ = it.it1_;
    00693                 it2_ = it.it2_;
    00694 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    00695                 t1_ = it.t1_;
    00696 #endif
    00697                 return *this;
    00698             }
    00699
    00700             // Comparison
    00701             BOOST_UBLAS_INLINE
    00702             bool operator == (const const_iterator2 &it) const {
    00703                 BOOST_UBLAS_CHECK ((*this) ().same_closure( it ()), external_logic ());
    00704                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    00705                 return it2_ == it.it2_;
    00706             }
    00707             BOOST_UBLAS_INLINE
    00708             bool operator < (const const_iterator2 &it) const {
    00709                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00710                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    00711                 return it2_ < it.it2_;
    00712             }
    00713
    00714         private:
    00715 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    00716             // Mutable due to assignment
    00717             /* const */ const_subiterator1_type it1_;
    00718             const_subiterator2_type it2_;
    00719             value_type t1_;
    00720 #else
    00721             const_subiterator1_type it1_;
    00722             const_subiterator2_type it2_;
    00723 #endif
    00724         };
    00725 #endif
    00726
    00727         BOOST_UBLAS_INLINE
    00728         const_iterator2 begin2 () const {
    00729             return find2 (0, 0, 0);
    00730         }
    00731         BOOST_UBLAS_INLINE
    00732         const_iterator2 end2 () const {
    00733             return find2 (0, 0, size2 ());
    00734         }
    00735
    00736         // Reverse iterators
    00737
    00738         BOOST_UBLAS_INLINE
    00739         const_reverse_iterator1 rbegin1 () const {
    00740             return const_reverse_iterator1 (end1 ());
    00741         }
    00742         BOOST_UBLAS_INLINE
    00743         const_reverse_iterator1 rend1 () const {
    00744             return const_reverse_iterator1 (begin1 ());
    00745         }
    00746
    00747         BOOST_UBLAS_INLINE
    00748         const_reverse_iterator2 rbegin2 () const {
    00749             return const_reverse_iterator2 (end2 ());
    00750         }
    00751         BOOST_UBLAS_INLINE
    00752         const_reverse_iterator2 rend2 () const {
    00753             return const_reverse_iterator2 (begin2 ());
    00754         }
    00755
    00756     private:
    00757         expression1_closure_type e1_;
    00758         expression2_closure_type e2_;
    00759     };
    00760
    00761     template<class E1, class E2, class F>
    00762     struct vector_matrix_binary_traits {
    00763         typedef vector_matrix_binary<E1, E2, F> expression_type;
    00764 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
    00765         typedef expression_type result_type;
    00766 #else
    00767         // ISSUE matrix is arbitary temporary type
    00768         typedef matrix<typename F::value_type> result_type;
    00769 #endif
    00770     };
    00771
    00772     // (outer_prod (v1, v2)) [i] [j] = v1 [i] * v2 [j]
    00773     template<class E1, class E2>
    00774     BOOST_UBLAS_INLINE
    00775     typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::result_type
    00776     outer_prod (const vector_expression<E1> &e1,
    00777                 const vector_expression<E2> &e2) {
    00778         BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
    00779         typedef typename vector_matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type, typename E2::value_type> >::expression_type expression_type;
    00780         return expression_type (e1 (), e2 ());
    00781     }
    00782
    00783     template<class E, class F>
    00784     class matrix_unary1:
    00785         public matrix_expression<matrix_unary1<E, F> > {
    00786
    00787         typedef E expression_type;
    00788         typedef F functor_type;
    00789     public:
    00790         typedef typename E::const_closure_type expression_closure_type;
    00791     private:
    00792         typedef matrix_unary1<E, F> self_type;
    00793     public:
    00794 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    00795         using matrix_expression<self_type>::operator ();
    00796 #endif
    00797         typedef typename E::size_type size_type;
    00798         typedef typename E::difference_type difference_type;
    00799         typedef typename F::result_type value_type;
    00800         typedef value_type const_reference;
    00801         typedef const_reference reference;
    00802         typedef const self_type const_closure_type;
    00803         typedef const_closure_type closure_type;
    00804         typedef typename E::orientation_category orientation_category;
    00805         typedef unknown_storage_tag storage_category;
    00806
    00807         // Construction and destruction
    00808         BOOST_UBLAS_INLINE
    00809         explicit matrix_unary1 (const expression_type &e):
    00810             e_ (e) {}
    00811
    00812         // Accessors
    00813         BOOST_UBLAS_INLINE
    00814         size_type size1 () const {
    00815             return e_.size1 ();
    00816         }
    00817         BOOST_UBLAS_INLINE
    00818         size_type size2 () const {
    00819             return e_.size2 ();
    00820         }
    00821
    00822     public:
    00823         // Expression accessors
    00824         BOOST_UBLAS_INLINE
    00825         const expression_closure_type &expression () const {
    00826             return e_;
    00827         }
    00828
    00829     public:
    00830         // Element access
    00831         BOOST_UBLAS_INLINE
    00832         const_reference operator () (size_type i, size_type j) const {
    00833             return functor_type::apply (e_ (i, j));
    00834         }
    00835
    00836         // Closure comparison
    00837         BOOST_UBLAS_INLINE
    00838         bool same_closure (const matrix_unary1 &mu1) const {
    00839             return (*this).expression ().same_closure (mu1.expression ());
    00840         }
    00841
    00842         // Iterator types
    00843     private:
    00844         typedef typename E::const_iterator1 const_subiterator1_type;
    00845         typedef typename E::const_iterator2 const_subiterator2_type;
    00846         typedef const value_type *const_pointer;
    00847
    00848     public:
    00849 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00850         typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
    00851         typedef const_iterator1 iterator1;
    00852         typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
    00853         typedef const_iterator2 iterator2;
    00854 #else
    00855         class const_iterator1;
    00856         typedef const_iterator1 iterator1;
    00857         class const_iterator2;
    00858         typedef const_iterator2 iterator2;
    00859 #endif
    00860         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    00861         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    00862
    00863         // Element lookup
    00864         BOOST_UBLAS_INLINE
    00865         const_iterator1 find1 (int rank, size_type i, size_type j) const {
    00866             const_subiterator1_type it1 (e_.find1 (rank, i, j));
    00867 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00868             return const_iterator1 (*this, it1.index1 (), it1.index2 ());
    00869 #else
    00870             return const_iterator1 (*this, it1);
    00871 #endif
    00872         }
    00873         BOOST_UBLAS_INLINE
    00874         const_iterator2 find2 (int rank, size_type i, size_type j) const {
    00875             const_subiterator2_type it2 (e_.find2 (rank, i, j));
    00876 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00877             return const_iterator2 (*this, it2.index1 (), it2.index2 ());
    00878 #else
    00879             return const_iterator2 (*this, it2);
    00880 #endif
    00881         }
    00882
    00883         // Iterators enhance the iterators of the referenced expression
    00884         // with the unary functor.
    00885
    00886 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    00887         class const_iterator1:
    00888             public container_const_reference<matrix_unary1>,
    00889             public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
    00890                 iterator_base<const_iterator1, value_type>::type {
    00891         public:
    00892             typedef typename E::const_iterator1::iterator_category iterator_category;
    00893             typedef typename matrix_unary1::difference_type difference_type;
    00894             typedef typename matrix_unary1::value_type value_type;
    00895             typedef typename matrix_unary1::const_reference reference;
    00896             typedef typename matrix_unary1::const_pointer pointer;
    00897
    00898             typedef const_iterator2 dual_iterator_type;
    00899             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    00900
    00901             // Construction and destruction
    00902             BOOST_UBLAS_INLINE
    00903             const_iterator1 ():
    00904                 container_const_reference<self_type> (), it_ () {}
    00905             BOOST_UBLAS_INLINE
    00906             const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
    00907                 container_const_reference<self_type> (mu), it_ (it) {}
    00908
    00909             // Arithmetic
    00910             BOOST_UBLAS_INLINE
    00911             const_iterator1 &operator ++ () {
    00912                 ++ it_;
    00913                 return *this;
    00914             }
    00915             BOOST_UBLAS_INLINE
    00916             const_iterator1 &operator -- () {
    00917                 -- it_;
    00918                 return *this;
    00919             }
    00920             BOOST_UBLAS_INLINE
    00921             const_iterator1 &operator += (difference_type n) {
    00922                 it_ += n;
    00923                 return *this;
    00924             }
    00925             BOOST_UBLAS_INLINE
    00926             const_iterator1 &operator -= (difference_type n) {
    00927                 it_ -= n;
    00928                 return *this;
    00929             }
    00930             BOOST_UBLAS_INLINE
    00931             difference_type operator - (const const_iterator1 &it) const {
    00932                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00933                 return it_ - it.it_;
    00934             }
    00935
    00936             // Dereference
    00937             BOOST_UBLAS_INLINE
    00938             const_reference operator * () const {
    00939                 return functor_type::apply (*it_);
    00940             }
    00941             BOOST_UBLAS_INLINE
    00942             const_reference operator [] (difference_type n) const {
    00943                 return *(*this + n);
    00944             }
    00945
    00946 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    00947             BOOST_UBLAS_INLINE
    00948 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00949             typename self_type::
    00950 #endif
    00951             const_iterator2 begin () const {
    00952                 return (*this) ().find2 (1, index1 (), 0);
    00953             }
    00954             BOOST_UBLAS_INLINE
    00955 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00956             typename self_type::
    00957 #endif
    00958             const_iterator2 end () const {
    00959                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
    00960             }
    00961             BOOST_UBLAS_INLINE
    00962 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00963             typename self_type::
    00964 #endif
    00965             const_reverse_iterator2 rbegin () const {
    00966                 return const_reverse_iterator2 (end ());
    00967             }
    00968             BOOST_UBLAS_INLINE
    00969 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    00970             typename self_type::
    00971 #endif
    00972             const_reverse_iterator2 rend () const {
    00973                 return const_reverse_iterator2 (begin ());
    00974             }
    00975 #endif
    00976
    00977             // Indices
    00978             BOOST_UBLAS_INLINE
    00979             size_type index1 () const {
    00980                 return it_.index1 ();
    00981             }
    00982             BOOST_UBLAS_INLINE
    00983             size_type index2 () const {
    00984                 return it_.index2 ();
    00985             }
    00986
    00987             // Assignment
    00988             BOOST_UBLAS_INLINE
    00989             const_iterator1 &operator = (const const_iterator1 &it) {
    00990                 container_const_reference<self_type>::assign (&it ());
    00991                 it_ = it.it_;
    00992                 return *this;
    00993             }
    00994
    00995             // Comparison
    00996             BOOST_UBLAS_INLINE
    00997             bool operator == (const const_iterator1 &it) const {
    00998                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    00999                 return it_ == it.it_;
    01000             }
    01001             BOOST_UBLAS_INLINE
    01002             bool operator < (const const_iterator1 &it) const {
    01003                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01004                 return it_ < it.it_;
    01005             }
    01006
    01007         private:
    01008             const_subiterator1_type it_;
    01009         };
    01010 #endif
    01011
    01012         BOOST_UBLAS_INLINE
    01013         const_iterator1 begin1 () const {
    01014             return find1 (0, 0, 0);
    01015         }
    01016         BOOST_UBLAS_INLINE
    01017         const_iterator1 end1 () const {
    01018             return find1 (0, size1 (), 0);
    01019         }
    01020
    01021 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01022         class const_iterator2:
    01023             public container_const_reference<matrix_unary1>,
    01024             public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
    01025                 iterator_base<const_iterator2, value_type>::type {
    01026         public:
    01027             typedef typename E::const_iterator2::iterator_category iterator_category;
    01028             typedef typename matrix_unary1::difference_type difference_type;
    01029             typedef typename matrix_unary1::value_type value_type;
    01030             typedef typename matrix_unary1::const_reference reference;
    01031             typedef typename matrix_unary1::const_pointer pointer;
    01032
    01033             typedef const_iterator1 dual_iterator_type;
    01034             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    01035
    01036             // Construction and destruction
    01037             BOOST_UBLAS_INLINE
    01038             const_iterator2 ():
    01039                 container_const_reference<self_type> (), it_ () {}
    01040             BOOST_UBLAS_INLINE
    01041             const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
    01042                 container_const_reference<self_type> (mu), it_ (it) {}
    01043
    01044             // Arithmetic
    01045             BOOST_UBLAS_INLINE
    01046             const_iterator2 &operator ++ () {
    01047                 ++ it_;
    01048                 return *this;
    01049             }
    01050             BOOST_UBLAS_INLINE
    01051             const_iterator2 &operator -- () {
    01052                 -- it_;
    01053                 return *this;
    01054             }
    01055             BOOST_UBLAS_INLINE
    01056             const_iterator2 &operator += (difference_type n) {
    01057                 it_ += n;
    01058                 return *this;
    01059             }
    01060             BOOST_UBLAS_INLINE
    01061             const_iterator2 &operator -= (difference_type n) {
    01062                 it_ -= n;
    01063                 return *this;
    01064             }
    01065             BOOST_UBLAS_INLINE
    01066             difference_type operator - (const const_iterator2 &it) const {
    01067                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01068                 return it_ - it.it_;
    01069             }
    01070
    01071             // Dereference
    01072             BOOST_UBLAS_INLINE
    01073             const_reference operator * () const {
    01074                 return functor_type::apply (*it_);
    01075             }
    01076             BOOST_UBLAS_INLINE
    01077             const_reference operator [] (difference_type n) const {
    01078                 return *(*this + n);
    01079             }
    01080
    01081 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    01082             BOOST_UBLAS_INLINE
    01083 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01084             typename self_type::
    01085 #endif
    01086             const_iterator1 begin () const {
    01087                 return (*this) ().find1 (1, 0, index2 ());
    01088             }
    01089             BOOST_UBLAS_INLINE
    01090 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01091             typename self_type::
    01092 #endif
    01093             const_iterator1 end () const {
    01094                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
    01095             }
    01096             BOOST_UBLAS_INLINE
    01097 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01098             typename self_type::
    01099 #endif
    01100             const_reverse_iterator1 rbegin () const {
    01101                 return const_reverse_iterator1 (end ());
    01102             }
    01103             BOOST_UBLAS_INLINE
    01104 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01105             typename self_type::
    01106 #endif
    01107             const_reverse_iterator1 rend () const {
    01108                 return const_reverse_iterator1 (begin ());
    01109             }
    01110 #endif
    01111
    01112             // Indices
    01113             BOOST_UBLAS_INLINE
    01114             size_type index1 () const {
    01115                 return it_.index1 ();
    01116             }
    01117             BOOST_UBLAS_INLINE
    01118             size_type index2 () const {
    01119                 return it_.index2 ();
    01120             }
    01121
    01122             // Assignment
    01123             BOOST_UBLAS_INLINE
    01124             const_iterator2 &operator = (const const_iterator2 &it) {
    01125                 container_const_reference<self_type>::assign (&it ());
    01126                 it_ = it.it_;
    01127                 return *this;
    01128             }
    01129
    01130             // Comparison
    01131             BOOST_UBLAS_INLINE
    01132             bool operator == (const const_iterator2 &it) const {
    01133                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01134                 return it_ == it.it_;
    01135             }
    01136             BOOST_UBLAS_INLINE
    01137             bool operator < (const const_iterator2 &it) const {
    01138                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01139                 return it_ < it.it_;
    01140             }
    01141
    01142         private:
    01143             const_subiterator2_type it_;
    01144         };
    01145 #endif
    01146
    01147         BOOST_UBLAS_INLINE
    01148         const_iterator2 begin2 () const {
    01149             return find2 (0, 0, 0);
    01150         }
    01151         BOOST_UBLAS_INLINE
    01152         const_iterator2 end2 () const {
    01153             return find2 (0, 0, size2 ());
    01154         }
    01155
    01156         // Reverse iterators
    01157
    01158         BOOST_UBLAS_INLINE
    01159         const_reverse_iterator1 rbegin1 () const {
    01160             return const_reverse_iterator1 (end1 ());
    01161         }
    01162         BOOST_UBLAS_INLINE
    01163         const_reverse_iterator1 rend1 () const {
    01164             return const_reverse_iterator1 (begin1 ());
    01165         }
    01166
    01167         BOOST_UBLAS_INLINE
    01168         const_reverse_iterator2 rbegin2 () const {
    01169             return const_reverse_iterator2 (end2 ());
    01170         }
    01171         BOOST_UBLAS_INLINE
    01172         const_reverse_iterator2 rend2 () const {
    01173             return const_reverse_iterator2 (begin2 ());
    01174         }
    01175
    01176     private:
    01177         expression_closure_type e_;
    01178     };
    01179
    01180     template<class E, class F>
    01181     struct matrix_unary1_traits {
    01182         typedef matrix_unary1<E, F> expression_type;
    01183 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
    01184         typedef expression_type result_type;
    01185 #else
    01186         typedef typename E::matrix_temporary_type result_type;
    01187 #endif
    01188     };
    01189
    01190     // (- m) [i] [j] = - m [i] [j]
    01191     template<class E>
    01192     BOOST_UBLAS_INLINE
    01193     typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::result_type
    01194     operator - (const matrix_expression<E> &e) {
    01195         typedef typename matrix_unary1_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
    01196         return expression_type (e ());
    01197     }
    01198
    01199     // (conj m) [i] [j] = conj (m [i] [j])
    01200     template<class E>
    01201     BOOST_UBLAS_INLINE
    01202     typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::result_type
    01203     conj (const matrix_expression<E> &e) {
    01204         typedef typename matrix_unary1_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
    01205         return expression_type (e ());
    01206     }
    01207
    01208     // (real m) [i] [j] = real (m [i] [j])
    01209     template<class E>
    01210     BOOST_UBLAS_INLINE
    01211     typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::result_type
    01212     real (const matrix_expression<E> &e) {
    01213         typedef typename matrix_unary1_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
    01214         return expression_type (e ());
    01215     }
    01216
    01217     // (imag m) [i] [j] = imag (m [i] [j])
    01218     template<class E>
    01219     BOOST_UBLAS_INLINE
    01220     typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::result_type
    01221     imag (const matrix_expression<E> &e) {
    01222         typedef typename matrix_unary1_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
    01223         return expression_type (e ());
    01224     }
    01225
    01226     template<class E, class F>
    01227     class matrix_unary2:
    01228         public matrix_expression<matrix_unary2<E, F> > {
    01229
    01230         typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
    01231                                           E,
    01232                                           const E>::type expression_type;
    01233         typedef F functor_type;
    01234     public:
    01235         typedef typename boost::mpl::if_<boost::is_const<expression_type>,
    01236                                           typename E::const_closure_type,
    01237                                           typename E::closure_type>::type expression_closure_type;
    01238     private:
    01239         typedef matrix_unary2<E, F> self_type;
    01240     public:
    01241 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    01242         using matrix_expression<self_type>::operator ();
    01243 #endif
    01244         typedef typename E::size_type size_type;
    01245         typedef typename E::difference_type difference_type;
    01246         typedef typename F::result_type value_type;
    01247         typedef value_type const_reference;
    01248         typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
    01249                                           typename E::reference,
    01250                                           value_type>::type reference;
    01251
    01252         typedef const self_type const_closure_type;
    01253         typedef self_type closure_type;
    01254         typedef typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
    01255                                                          row_major_tag>,
    01256                                           column_major_tag,
    01257                 typename boost::mpl::if_<boost::is_same<typename E::orientation_category,
    01258                                                          column_major_tag>,
    01259                                           row_major_tag,
    01260                                           typename E::orientation_category>::type>::type orientation_category;
    01261         typedef typename E::storage_category storage_category;
    01262
    01263         // Construction and destruction
    01264         BOOST_UBLAS_INLINE
    01265         // matrix_unary2 may be used as mutable expression -
    01266         // this is the only non const expression constructor
    01267         explicit matrix_unary2 (expression_type &e):
    01268             e_ (e) {}
    01269
    01270         // Accessors
    01271         BOOST_UBLAS_INLINE
    01272         size_type size1 () const {
    01273             return e_.size2 ();
    01274         }
    01275         BOOST_UBLAS_INLINE
    01276         size_type size2 () const {
    01277             return e_.size1 ();
    01278         }
    01279
    01280     public:
    01281         // Expression accessors
    01282         BOOST_UBLAS_INLINE
    01283         const expression_closure_type &expression () const {
    01284             return e_;
    01285         }
    01286
    01287     public:
    01288         // Element access
    01289         BOOST_UBLAS_INLINE
    01290         const_reference operator () (size_type i, size_type j) const {
    01291             return functor_type::apply (e_ (j, i));
    01292         }
    01293         BOOST_UBLAS_INLINE
    01294         reference operator () (size_type i, size_type j) {
    01295             BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
    01296             return e_ (j, i);
    01297         }
    01298
    01299         // Closure comparison
    01300         BOOST_UBLAS_INLINE
    01301         bool same_closure (const matrix_unary2 &mu2) const {
    01302             return (*this).expression ().same_closure (mu2.expression ());
    01303         }
    01304
    01305         // Iterator types
    01306     private:
    01307         typedef typename E::const_iterator1 const_subiterator2_type;
    01308         typedef typename E::const_iterator2 const_subiterator1_type;
    01309         typedef const value_type *const_pointer;
    01310
    01311     public:
    01312 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01313         typedef indexed_const_iterator1<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator1;
    01314         typedef const_iterator1 iterator1;
    01315         typedef indexed_const_iterator2<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator2;
    01316         typedef const_iterator2 iterator2;
    01317 #else
    01318         class const_iterator1;
    01319         typedef const_iterator1 iterator1;
    01320         class const_iterator2;
    01321         typedef const_iterator2 iterator2;
    01322 #endif
    01323         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    01324         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    01325
    01326         // Element lookup
    01327         BOOST_UBLAS_INLINE
    01328         const_iterator1 find1 (int rank, size_type i, size_type j) const {
    01329             const_subiterator1_type it1 (e_.find2 (rank, j, i));
    01330 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01331             return const_iterator1 (*this, it1.index2 (), it1.index1 ());
    01332 #else
    01333             return const_iterator1 (*this, it1);
    01334 #endif
    01335         }
    01336         BOOST_UBLAS_INLINE
    01337         const_iterator2 find2 (int rank, size_type i, size_type j) const {
    01338             const_subiterator2_type it2 (e_.find1 (rank, j, i));
    01339 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01340             return const_iterator2 (*this, it2.index2 (), it2.index1 ());
    01341 #else
    01342             return const_iterator2 (*this, it2);
    01343 #endif
    01344         }
    01345
    01346         // Iterators enhance the iterators of the referenced expression
    01347         // with the unary functor.
    01348
    01349 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01350         class const_iterator1:
    01351             public container_const_reference<matrix_unary2>,
    01352             public iterator_base_traits<typename E::const_iterator2::iterator_category>::template
    01353                 iterator_base<const_iterator1, value_type>::type {
    01354         public:
    01355             typedef typename E::const_iterator2::iterator_category iterator_category;
    01356             typedef typename matrix_unary2::difference_type difference_type;
    01357             typedef typename matrix_unary2::value_type value_type;
    01358             typedef typename matrix_unary2::const_reference reference;
    01359             typedef typename matrix_unary2::const_pointer pointer;
    01360
    01361             typedef const_iterator2 dual_iterator_type;
    01362             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    01363
    01364             // Construction and destruction
    01365             BOOST_UBLAS_INLINE
    01366             const_iterator1 ():
    01367                 container_const_reference<self_type> (), it_ () {}
    01368             BOOST_UBLAS_INLINE
    01369             const_iterator1 (const self_type &mu, const const_subiterator1_type &it):
    01370                 container_const_reference<self_type> (mu), it_ (it) {}
    01371
    01372             // Arithmetic
    01373             BOOST_UBLAS_INLINE
    01374             const_iterator1 &operator ++ () {
    01375                 ++ it_;
    01376                 return *this;
    01377             }
    01378             BOOST_UBLAS_INLINE
    01379             const_iterator1 &operator -- () {
    01380                 -- it_;
    01381                 return *this;
    01382             }
    01383             BOOST_UBLAS_INLINE
    01384             const_iterator1 &operator += (difference_type n) {
    01385                 it_ += n;
    01386                 return *this;
    01387             }
    01388             BOOST_UBLAS_INLINE
    01389             const_iterator1 &operator -= (difference_type n) {
    01390                 it_ -= n;
    01391                 return *this;
    01392             }
    01393             BOOST_UBLAS_INLINE
    01394             difference_type operator - (const const_iterator1 &it) const {
    01395                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01396                 return it_ - it.it_;
    01397             }
    01398
    01399             // Dereference
    01400             BOOST_UBLAS_INLINE
    01401             const_reference operator * () const {
    01402                 return functor_type::apply (*it_);
    01403             }
    01404             BOOST_UBLAS_INLINE
    01405             const_reference operator [] (difference_type n) const {
    01406                 return *(*this + n);
    01407             }
    01408
    01409 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    01410             BOOST_UBLAS_INLINE
    01411 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01412             typename self_type::
    01413 #endif
    01414             const_iterator2 begin () const {
    01415                 return (*this) ().find2 (1, index1 (), 0);
    01416             }
    01417             BOOST_UBLAS_INLINE
    01418 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01419             typename self_type::
    01420 #endif
    01421             const_iterator2 end () const {
    01422                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
    01423             }
    01424             BOOST_UBLAS_INLINE
    01425 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01426             typename self_type::
    01427 #endif
    01428             const_reverse_iterator2 rbegin () const {
    01429                 return const_reverse_iterator2 (end ());
    01430             }
    01431             BOOST_UBLAS_INLINE
    01432 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01433             typename self_type::
    01434 #endif
    01435             const_reverse_iterator2 rend () const {
    01436                 return const_reverse_iterator2 (begin ());
    01437             }
    01438 #endif
    01439
    01440             // Indices
    01441             BOOST_UBLAS_INLINE
    01442             size_type index1 () const {
    01443                 return it_.index2 ();
    01444             }
    01445             BOOST_UBLAS_INLINE
    01446             size_type index2 () const {
    01447                 return it_.index1 ();
    01448             }
    01449
    01450             // Assignment
    01451             BOOST_UBLAS_INLINE
    01452             const_iterator1 &operator = (const const_iterator1 &it) {
    01453                 container_const_reference<self_type>::assign (&it ());
    01454                 it_ = it.it_;
    01455                 return *this;
    01456             }
    01457
    01458             // Comparison
    01459             BOOST_UBLAS_INLINE
    01460             bool operator == (const const_iterator1 &it) const {
    01461                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01462                 return it_ == it.it_;
    01463             }
    01464             BOOST_UBLAS_INLINE
    01465             bool operator < (const const_iterator1 &it) const {
    01466                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01467                 return it_ < it.it_;
    01468             }
    01469
    01470         private:
    01471             const_subiterator1_type it_;
    01472         };
    01473 #endif
    01474
    01475         BOOST_UBLAS_INLINE
    01476         const_iterator1 begin1 () const {
    01477             return find1 (0, 0, 0);
    01478         }
    01479         BOOST_UBLAS_INLINE
    01480         const_iterator1 end1 () const {
    01481             return find1 (0, size1 (), 0);
    01482         }
    01483
    01484 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01485         class const_iterator2:
    01486             public container_const_reference<matrix_unary2>,
    01487             public iterator_base_traits<typename E::const_iterator1::iterator_category>::template
    01488                 iterator_base<const_iterator2, value_type>::type {
    01489         public:
    01490             typedef typename E::const_iterator1::iterator_category iterator_category;
    01491             typedef typename matrix_unary2::difference_type difference_type;
    01492             typedef typename matrix_unary2::value_type value_type;
    01493             typedef typename matrix_unary2::const_reference reference;
    01494             typedef typename matrix_unary2::const_pointer pointer;
    01495
    01496             typedef const_iterator1 dual_iterator_type;
    01497             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    01498
    01499             // Construction and destruction
    01500             BOOST_UBLAS_INLINE
    01501             const_iterator2 ():
    01502                 container_const_reference<self_type> (), it_ () {}
    01503             BOOST_UBLAS_INLINE
    01504             const_iterator2 (const self_type &mu, const const_subiterator2_type &it):
    01505                 container_const_reference<self_type> (mu), it_ (it) {}
    01506
    01507             // Arithmetic
    01508             BOOST_UBLAS_INLINE
    01509             const_iterator2 &operator ++ () {
    01510                 ++ it_;
    01511                 return *this;
    01512             }
    01513             BOOST_UBLAS_INLINE
    01514             const_iterator2 &operator -- () {
    01515                 -- it_;
    01516                 return *this;
    01517             }
    01518             BOOST_UBLAS_INLINE
    01519             const_iterator2 &operator += (difference_type n) {
    01520                 it_ += n;
    01521                 return *this;
    01522             }
    01523             BOOST_UBLAS_INLINE
    01524             const_iterator2 &operator -= (difference_type n) {
    01525                 it_ -= n;
    01526                 return *this;
    01527             }
    01528             BOOST_UBLAS_INLINE
    01529             difference_type operator - (const const_iterator2 &it) const {
    01530                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01531                 return it_ - it.it_;
    01532             }
    01533
    01534             // Dereference
    01535             BOOST_UBLAS_INLINE
    01536             const_reference operator * () const {
    01537                 return functor_type::apply (*it_);
    01538             }
    01539             BOOST_UBLAS_INLINE
    01540             const_reference operator [] (difference_type n) const {
    01541                 return *(*this + n);
    01542             }
    01543
    01544 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    01545             BOOST_UBLAS_INLINE
    01546 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01547             typename self_type::
    01548 #endif
    01549             const_iterator1 begin () const {
    01550                 return (*this) ().find1 (1, 0, index2 ());
    01551             }
    01552             BOOST_UBLAS_INLINE
    01553 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01554             typename self_type::
    01555 #endif
    01556             const_iterator1 end () const {
    01557                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
    01558             }
    01559             BOOST_UBLAS_INLINE
    01560 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01561             typename self_type::
    01562 #endif
    01563             const_reverse_iterator1 rbegin () const {
    01564                 return const_reverse_iterator1 (end ());
    01565             }
    01566             BOOST_UBLAS_INLINE
    01567 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    01568             typename self_type::
    01569 #endif
    01570             const_reverse_iterator1 rend () const {
    01571                 return const_reverse_iterator1 (begin ());
    01572             }
    01573 #endif
    01574
    01575             // Indices
    01576             BOOST_UBLAS_INLINE
    01577             size_type index1 () const {
    01578                 return it_.index2 ();
    01579             }
    01580             BOOST_UBLAS_INLINE
    01581             size_type index2 () const {
    01582                 return it_.index1 ();
    01583             }
    01584
    01585             // Assignment
    01586             BOOST_UBLAS_INLINE
    01587             const_iterator2 &operator = (const const_iterator2 &it) {
    01588                 container_const_reference<self_type>::assign (&it ());
    01589                 it_ = it.it_;
    01590                 return *this;
    01591             }
    01592
    01593             // Comparison
    01594             BOOST_UBLAS_INLINE
    01595             bool operator == (const const_iterator2 &it) const {
    01596                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01597                 return it_ == it.it_;
    01598             }
    01599             BOOST_UBLAS_INLINE
    01600             bool operator < (const const_iterator2 &it) const {
    01601                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    01602                 return it_ < it.it_;
    01603             }
    01604
    01605         private:
    01606             const_subiterator2_type it_;
    01607         };
    01608 #endif
    01609
    01610         BOOST_UBLAS_INLINE
    01611         const_iterator2 begin2 () const {
    01612             return find2 (0, 0, 0);
    01613         }
    01614         BOOST_UBLAS_INLINE
    01615         const_iterator2 end2 () const {
    01616             return find2 (0, 0, size2 ());
    01617         }
    01618
    01619         // Reverse iterators
    01620
    01621         BOOST_UBLAS_INLINE
    01622         const_reverse_iterator1 rbegin1 () const {
    01623             return const_reverse_iterator1 (end1 ());
    01624         }
    01625         BOOST_UBLAS_INLINE
    01626         const_reverse_iterator1 rend1 () const {
    01627             return const_reverse_iterator1 (begin1 ());
    01628         }
    01629
    01630         BOOST_UBLAS_INLINE
    01631         const_reverse_iterator2 rbegin2 () const {
    01632             return const_reverse_iterator2 (end2 ());
    01633         }
    01634         BOOST_UBLAS_INLINE
    01635         const_reverse_iterator2 rend2 () const {
    01636             return const_reverse_iterator2 (begin2 ());
    01637         }
    01638
    01639     private:
    01640         expression_closure_type e_;
    01641     };
    01642
    01643     template<class E, class F>
    01644     struct matrix_unary2_traits {
    01645         typedef matrix_unary2<E, F> expression_type;
    01646 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
    01647         typedef expression_type result_type;
    01648 #else
    01649         typedef typename E::matrix_temporary_type result_type;
    01650 #endif
    01651     };
    01652
    01653     // (trans m) [i] [j] = m [j] [i]
    01654     template<class E>
    01655     BOOST_UBLAS_INLINE
    01656     typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::result_type
    01657     trans (const matrix_expression<E> &e) {
    01658         typedef typename matrix_unary2_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
    01659         return expression_type (e ());
    01660     }
    01661     template<class E>
    01662     BOOST_UBLAS_INLINE
    01663     typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::result_type
    01664     trans (matrix_expression<E> &e) {
    01665         typedef typename matrix_unary2_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
    01666         return expression_type (e ());
    01667     }
    01668
    01669     // (herm m) [i] [j] = conj (m [j] [i])
    01670     template<class E>
    01671     BOOST_UBLAS_INLINE
    01672     typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::result_type
    01673     herm (const matrix_expression<E> &e) {
    01674         typedef typename matrix_unary2_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
    01675         return expression_type (e ());
    01676     }
    01677
    01678     template<class E1, class E2, class F>
    01679     class matrix_binary:
    01680         public matrix_expression<matrix_binary<E1, E2, F> > {
    01681
    01682         typedef E1 expression1_type;
    01683         typedef E2 expression2_type;
    01684         typedef F functor_type;
    01685     public:
    01686         typedef typename E1::const_closure_type expression1_closure_type;
    01687         typedef typename E2::const_closure_type expression2_closure_type;
    01688     private:
    01689         typedef matrix_binary<E1, E2, F> self_type;
    01690     public:
    01691 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    01692         using matrix_expression<self_type>::operator ();
    01693 #endif
    01694         typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
    01695         typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
    01696         typedef typename F::result_type value_type;
    01697         typedef value_type const_reference;
    01698         typedef const_reference reference;
    01699         typedef const self_type const_closure_type;
    01700         typedef const_closure_type closure_type;
    01701         typedef unknown_orientation_tag orientation_category;
    01702         typedef unknown_storage_tag storage_category;
    01703
    01704         // Construction and destruction
    01705         BOOST_UBLAS_INLINE
    01706         matrix_binary (const E1 &e1, const E2 &e2):
    01707             e1_ (e1), e2_ (e2) {}
    01708
    01709         // Accessors
    01710         BOOST_UBLAS_INLINE
    01711         size_type size1 () const {
    01712             return BOOST_UBLAS_SAME (e1_.size1 (), e2_.size1 ());
    01713         }
    01714         BOOST_UBLAS_INLINE
    01715         size_type size2 () const {
    01716             return BOOST_UBLAS_SAME (e1_.size2 (), e2_.size2 ());
    01717         }
    01718
    01719     public:
    01720         // Expression accessors
    01721         BOOST_UBLAS_INLINE
    01722         const expression1_closure_type &expression1 () const {
    01723             return e1_;
    01724         }
    01725         BOOST_UBLAS_INLINE
    01726         const expression2_closure_type &expression2 () const {
    01727             return e2_;
    01728         }
    01729
    01730     public:
    01731         // Element access
    01732         BOOST_UBLAS_INLINE
    01733         const_reference operator () (size_type i, size_type j) const {
    01734             return functor_type::apply (e1_ (i, j), e2_ (i, j));
    01735         }
    01736
    01737         // Closure comparison
    01738         BOOST_UBLAS_INLINE
    01739         bool same_closure (const matrix_binary &mb) const {
    01740             return (*this).expression1 ().same_closure (mb.expression1 ()) &&
    01741                    (*this).expression2 ().same_closure (mb.expression2 ());
    01742         }
    01743
    01744         // Iterator types
    01745     private:
    01746         typedef typename E1::const_iterator1 const_iterator11_type;
    01747         typedef typename E1::const_iterator2 const_iterator12_type;
    01748         typedef typename E2::const_iterator1 const_iterator21_type;
    01749         typedef typename E2::const_iterator2 const_iterator22_type;
    01750         typedef const value_type *const_pointer;
    01751
    01752     public:
    01753 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01754         typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
    01755                                                   typename const_iterator21_type::iterator_category>::iterator_category iterator_category1;
    01756         typedef indexed_const_iterator1<const_closure_type, iterator_category1> const_iterator1;
    01757         typedef const_iterator1 iterator1;
    01758         typedef typename iterator_restrict_traits<typename const_iterator12_type::iterator_category,
    01759                                                   typename const_iterator22_type::iterator_category>::iterator_category iterator_category2;
    01760         typedef indexed_const_iterator2<const_closure_type, iterator_category2> const_iterator2;
    01761         typedef const_iterator2 iterator2;
    01762 #else
    01763         class const_iterator1;
    01764         typedef const_iterator1 iterator1;
    01765         class const_iterator2;
    01766         typedef const_iterator2 iterator2;
    01767 #endif
    01768         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    01769         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    01770
    01771         // Element lookup
    01772         BOOST_UBLAS_INLINE
    01773         const_iterator1 find1 (int rank, size_type i, size_type j) const {
    01774             const_iterator11_type it11 (e1_.find1 (rank, i, j));
    01775             const_iterator11_type it11_end (e1_.find1 (rank, size1 (), j));
    01776             const_iterator21_type it21 (e2_.find1 (rank, i, j));
    01777             const_iterator21_type it21_end (e2_.find1 (rank, size1 (), j));
    01778             BOOST_UBLAS_CHECK (rank == 0 || it11 == it11_end || it11.index2 () == j, internal_logic ())
    01779             BOOST_UBLAS_CHECK (rank == 0 || it21 == it21_end || it21.index2 () == j, internal_logic ())
    01780             i = (std::min) (it11 != it11_end ? it11.index1 () : size1 (),
    01781                           it21 != it21_end ? it21.index1 () : size1 ());
    01782 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01783             return const_iterator1 (*this, i, j);
    01784 #else
    01785             return const_iterator1 (*this, i, j, it11, it11_end, it21, it21_end);
    01786 #endif
    01787         }
    01788         BOOST_UBLAS_INLINE
    01789         const_iterator2 find2 (int rank, size_type i, size_type j) const {
    01790             const_iterator12_type it12 (e1_.find2 (rank, i, j));
    01791             const_iterator12_type it12_end (e1_.find2 (rank, i, size2 ()));
    01792             const_iterator22_type it22 (e2_.find2 (rank, i, j));
    01793             const_iterator22_type it22_end (e2_.find2 (rank, i, size2 ()));
    01794             BOOST_UBLAS_CHECK (rank == 0 || it12 == it12_end || it12.index1 () == i, internal_logic ())
    01795             BOOST_UBLAS_CHECK (rank == 0 || it22 == it22_end || it22.index1 () == i, internal_logic ())
    01796             j = (std::min) (it12 != it12_end ? it12.index2 () : size2 (),
    01797                           it22 != it22_end ? it22.index2 () : size2 ());
    01798 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01799             return const_iterator2 (*this, i, j);
    01800 #else
    01801             return const_iterator2 (*this, i, j, it12, it12_end, it22, it22_end);
    01802 #endif
    01803         }
    01804
    01805         // Iterators enhance the iterators of the referenced expression
    01806         // with the binary functor.
    01807
    01808 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    01809         class const_iterator1:
    01810             public container_const_reference<matrix_binary>,
    01811             public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
    01812                                                                           typename E2::const_iterator1::iterator_category>::iterator_category>::template
    01813                 iterator_base<const_iterator1, value_type>::type {
    01814         public:
    01815             typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
    01816                                                       typename E2::const_iterator1::iterator_category>::iterator_category iterator_category;
    01817             typedef typename matrix_binary::difference_type difference_type;
    01818             typedef typename matrix_binary::value_type value_type;
    01819             typedef typename matrix_binary::const_reference reference;
    01820             typedef typename matrix_binary::const_pointer pointer;
    01821
    01822             typedef const_iterator2 dual_iterator_type;
    01823             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    01824
    01825             // Construction and destruction
    01826             BOOST_UBLAS_INLINE
    01827             const_iterator1 ():
    01828                 container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
    01829             BOOST_UBLAS_INLINE
    01830             const_iterator1 (const self_type &mb, size_type i, size_type j,
    01831                              const const_iterator11_type &it1, const const_iterator11_type &it1_end,
    01832                              const const_iterator21_type &it2, const const_iterator21_type &it2_end):
    01833                 container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
    01834
    01835         private:
    01836             // Dense specializations
    01837             BOOST_UBLAS_INLINE
    01838             void increment (dense_random_access_iterator_tag) {
    01839                 ++ i_; ++ it1_; ++ it2_;
    01840             }
    01841             BOOST_UBLAS_INLINE
    01842             void decrement (dense_random_access_iterator_tag) {
    01843                 -- i_; -- it1_; -- it2_;
    01844             }
    01845             BOOST_UBLAS_INLINE
    01846             void increment (dense_random_access_iterator_tag, difference_type n) {
    01847                  i_ += n; it1_ += n; it2_ += n;
    01848             }
    01849             BOOST_UBLAS_INLINE
    01850             void decrement (dense_random_access_iterator_tag, difference_type n) {
    01851                 i_ -= n; it1_ -= n; it2_ -= n;
    01852             }
    01853             BOOST_UBLAS_INLINE
    01854             value_type dereference (dense_random_access_iterator_tag) const {
    01855                 return functor_type::apply (*it1_, *it2_);
    01856             }
    01857
    01858             // Packed specializations
    01859             BOOST_UBLAS_INLINE
    01860             void increment (packed_random_access_iterator_tag) {
    01861                 if (it1_ != it1_end_)
    01862                     if (it1_.index1 () <= i_)
    01863                         ++ it1_;
    01864                 if (it2_ != it2_end_)
    01865                     if (it2_.index1 () <= i_)
    01866                         ++ it2_;
    01867                 ++ i_;
    01868             }
    01869             BOOST_UBLAS_INLINE
    01870             void decrement (packed_random_access_iterator_tag) {
    01871                 if (it1_ != it1_end_)
    01872                     if (i_ <= it1_.index1 ())
    01873                         -- it1_;
    01874                 if (it2_ != it2_end_)
    01875                     if (i_ <= it2_.index1 ())
    01876                         -- it2_;
    01877                 -- i_;
    01878             }
    01879             BOOST_UBLAS_INLINE
    01880             void increment (packed_random_access_iterator_tag, difference_type n) {
    01881                 while (n > 0) {
    01882                     increment (packed_random_access_iterator_tag ());
    01883                     --n;
    01884                 }
    01885                 while (n < 0) {
    01886                     decrement (packed_random_access_iterator_tag ());
    01887                     ++n;
    01888                 }
    01889             }
    01890             BOOST_UBLAS_INLINE
    01891             void decrement (packed_random_access_iterator_tag, difference_type n) {
    01892                 while (n > 0) {
    01893                     decrement (packed_random_access_iterator_tag ());
    01894                     --n;
    01895                 }
    01896                 while (n < 0) {
    01897                     increment (packed_random_access_iterator_tag ());
    01898                     ++n;
    01899                 }
    01900             }
    01901             BOOST_UBLAS_INLINE
    01902             value_type dereference (packed_random_access_iterator_tag) const {
    01903                 value_type t1 = value_type/*zero*/();
    01904                 if (it1_ != it1_end_) {
    01905                     BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
    01906                     if (it1_.index1 () == i_)
    01907                         t1 = *it1_;
    01908                 }
    01909                 value_type t2 = value_type/*zero*/();
    01910                 if (it2_ != it2_end_) {
    01911                     BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
    01912                     if (it2_.index1 () == i_)
    01913                         t2 = *it2_;
    01914                 }
    01915                 return functor_type::apply (t1, t2);
    01916             }
    01917
    01918             // Sparse specializations
    01919             BOOST_UBLAS_INLINE
    01920             void increment (sparse_bidirectional_iterator_tag) {
    01921                 size_type index1 = (*this) ().size1 ();
    01922                 if (it1_ != it1_end_) {
    01923                     if (it1_.index1 () <= i_)
    01924                         ++ it1_;
    01925                     if (it1_ != it1_end_)
    01926                         index1 = it1_.index1 ();
    01927                 }
    01928                 size_type index2 = (*this) ().size1 ();
    01929                 if (it2_ != it2_end_)
    01930                     if (it2_.index1 () <= i_)
    01931                         ++ it2_;
    01932                     if (it2_ != it2_end_) {
    01933                         index2 = it2_.index1 ();
    01934                 }
    01935                 i_ = (std::min) (index1, index2);
    01936             }
    01937             BOOST_UBLAS_INLINE
    01938             void decrement (sparse_bidirectional_iterator_tag) {
    01939                 size_type index1 = (*this) ().size1 ();
    01940                 if (it1_ != it1_end_) {
    01941                     if (i_ <= it1_.index1 ())
    01942                         -- it1_;
    01943                     if (it1_ != it1_end_)
    01944                         index1 = it1_.index1 ();
    01945                 }
    01946                 size_type index2 = (*this) ().size1 ();
    01947                 if (it2_ != it2_end_) {
    01948                     if (i_ <= it2_.index1 ())
    01949                         -- it2_;
    01950                     if (it2_ != it2_end_)
    01951                         index2 = it2_.index1 ();
    01952                 }
    01953                 i_ = (std::max) (index1, index2);
    01954             }
    01955             BOOST_UBLAS_INLINE
    01956             void increment (sparse_bidirectional_iterator_tag, difference_type n) {
    01957                 while (n > 0) {
    01958                     increment (sparse_bidirectional_iterator_tag ());
    01959                     --n;
    01960                 }
    01961                 while (n < 0) {
    01962                     decrement (sparse_bidirectional_iterator_tag ());
    01963                     ++n;
    01964                 }
    01965             }
    01966             BOOST_UBLAS_INLINE
    01967             void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
    01968                 while (n > 0) {
    01969                     decrement (sparse_bidirectional_iterator_tag ());
    01970                     --n;
    01971                 }
    01972                 while (n < 0) {
    01973                     increment (sparse_bidirectional_iterator_tag ());
    01974                     ++n;
    01975                 }
    01976             }
    01977             BOOST_UBLAS_INLINE
    01978             value_type dereference (sparse_bidirectional_iterator_tag) const {
    01979                 value_type t1 = value_type/*zero*/();
    01980                 if (it1_ != it1_end_) {
    01981                     BOOST_UBLAS_CHECK (it1_.index2 () == j_, internal_logic ());
    01982                     if (it1_.index1 () == i_)
    01983                         t1 = *it1_;
    01984                 }
    01985                 value_type t2 = value_type/*zero*/();
    01986                 if (it2_ != it2_end_) {
    01987                     BOOST_UBLAS_CHECK (it2_.index2 () == j_, internal_logic ());
    01988                     if (it2_.index1 () == i_)
    01989                         t2 = *it2_;
    01990                 }
    01991                 return functor_type::apply (t1, t2);
    01992             }
    01993
    01994         public:
    01995             // Arithmetic
    01996             BOOST_UBLAS_INLINE
    01997             const_iterator1 &operator ++ () {
    01998                 increment (iterator_category ());
    01999                 return *this;
    02000             }
    02001             BOOST_UBLAS_INLINE
    02002             const_iterator1 &operator -- () {
    02003                 decrement (iterator_category ());
    02004                 return *this;
    02005             }
    02006             BOOST_UBLAS_INLINE
    02007             const_iterator1 &operator += (difference_type n) {
    02008                 increment (iterator_category (), n);
    02009                 return *this;
    02010             }
    02011             BOOST_UBLAS_INLINE
    02012             const_iterator1 &operator -= (difference_type n) {
    02013                 decrement (iterator_category (), n);
    02014                 return *this;
    02015             }
    02016             BOOST_UBLAS_INLINE
    02017             difference_type operator - (const const_iterator1 &it) const {
    02018                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02019                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
    02020                 return index1 () - it.index1 ();
    02021             }
    02022
    02023             // Dereference
    02024             BOOST_UBLAS_INLINE
    02025             const_reference operator * () const {
    02026                 return dereference (iterator_category ());
    02027             }
    02028             BOOST_UBLAS_INLINE
    02029             const_reference operator [] (difference_type n) const {
    02030                 return *(*this + n);
    02031             }
    02032
    02033 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02034             BOOST_UBLAS_INLINE
    02035 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02036             typename self_type::
    02037 #endif
    02038             const_iterator2 begin () const {
    02039                 return (*this) ().find2 (1, index1 (), 0);
    02040             }
    02041             BOOST_UBLAS_INLINE
    02042 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02043             typename self_type::
    02044 #endif
    02045             const_iterator2 end () const {
    02046                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
    02047             }
    02048             BOOST_UBLAS_INLINE
    02049 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02050             typename self_type::
    02051 #endif
    02052             const_reverse_iterator2 rbegin () const {
    02053                 return const_reverse_iterator2 (end ());
    02054             }
    02055             BOOST_UBLAS_INLINE
    02056 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02057             typename self_type::
    02058 #endif
    02059             const_reverse_iterator2 rend () const {
    02060                 return const_reverse_iterator2 (begin ());
    02061             }
    02062 #endif
    02063
    02064             // Indices
    02065             BOOST_UBLAS_INLINE
    02066             size_type index1 () const {
    02067                 return i_;
    02068             }
    02069             BOOST_UBLAS_INLINE
    02070             size_type index2 () const {
    02071                 // if (it1_ != it1_end_ && it2_ != it2_end_)
    02072                 //    return BOOST_UBLAS_SAME (it1_.index2 (), it2_.index2 ());
    02073                 // else
    02074                     return j_;
    02075             }
    02076
    02077             // Assignment
    02078             BOOST_UBLAS_INLINE
    02079             const_iterator1 &operator = (const const_iterator1 &it) {
    02080                 container_const_reference<self_type>::assign (&it ());
    02081                 i_ = it.i_;
    02082                 j_ = it.j_;
    02083                 it1_ = it.it1_;
    02084                 it1_end_ = it.it1_end_;
    02085                 it2_ = it.it2_;
    02086                 it2_end_ = it.it2_end_;
    02087                 return *this;
    02088             }
    02089
    02090             // Comparison
    02091             BOOST_UBLAS_INLINE
    02092             bool operator == (const const_iterator1 &it) const {
    02093                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02094                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
    02095                 return index1 () == it.index1 ();
    02096             }
    02097             BOOST_UBLAS_INLINE
    02098             bool operator < (const const_iterator1 &it) const {
    02099                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02100                 BOOST_UBLAS_CHECK (index2 () == it.index2 (), external_logic ());
    02101                 return index1 () < it.index1 ();
    02102             }
    02103
    02104         private:
    02105             size_type i_;
    02106             size_type j_;
    02107             const_iterator11_type it1_;
    02108             const_iterator11_type it1_end_;
    02109             const_iterator21_type it2_;
    02110             const_iterator21_type it2_end_;
    02111         };
    02112 #endif
    02113
    02114         BOOST_UBLAS_INLINE
    02115         const_iterator1 begin1 () const {
    02116             return find1 (0, 0, 0);
    02117         }
    02118         BOOST_UBLAS_INLINE
    02119         const_iterator1 end1 () const {
    02120             return find1 (0, size1 (), 0);
    02121         }
    02122
    02123 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02124         class const_iterator2:
    02125             public container_const_reference<matrix_binary>,
    02126             public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
    02127                                                                           typename E2::const_iterator2::iterator_category>::iterator_category>::template
    02128                 iterator_base<const_iterator2, value_type>::type {
    02129         public:
    02130             typedef typename iterator_restrict_traits<typename E1::const_iterator2::iterator_category,
    02131                                                       typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
    02132             typedef typename matrix_binary::difference_type difference_type;
    02133             typedef typename matrix_binary::value_type value_type;
    02134             typedef typename matrix_binary::const_reference reference;
    02135             typedef typename matrix_binary::const_pointer pointer;
    02136
    02137             typedef const_iterator1 dual_iterator_type;
    02138             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    02139
    02140             // Construction and destruction
    02141             BOOST_UBLAS_INLINE
    02142             const_iterator2 ():
    02143                 container_const_reference<self_type> (), i_ (), j_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
    02144             BOOST_UBLAS_INLINE
    02145             const_iterator2 (const self_type &mb, size_type i, size_type j,
    02146                              const const_iterator12_type &it1, const const_iterator12_type &it1_end,
    02147                              const const_iterator22_type &it2, const const_iterator22_type &it2_end):
    02148                 container_const_reference<self_type> (mb), i_ (i), j_ (j), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
    02149
    02150         private:
    02151             // Dense access specializations
    02152             BOOST_UBLAS_INLINE
    02153             void increment (dense_random_access_iterator_tag) {
    02154                 ++ j_; ++ it1_; ++ it2_;
    02155             }
    02156             BOOST_UBLAS_INLINE
    02157             void decrement (dense_random_access_iterator_tag) {
    02158                 -- j_; -- it1_; -- it2_;
    02159             }
    02160             BOOST_UBLAS_INLINE
    02161             void increment (dense_random_access_iterator_tag, difference_type n) {
    02162                 j_ += n; it1_ += n; it2_ += n;
    02163             }
    02164             BOOST_UBLAS_INLINE
    02165             void decrement (dense_random_access_iterator_tag, difference_type n) {
    02166                 j_ -= n; it1_ -= n; it2_ -= n;
    02167             }
    02168             BOOST_UBLAS_INLINE
    02169             value_type dereference (dense_random_access_iterator_tag) const {
    02170                 return functor_type::apply (*it1_, *it2_);
    02171             }
    02172
    02173             // Packed specializations
    02174             BOOST_UBLAS_INLINE
    02175             void increment (packed_random_access_iterator_tag) {
    02176                 if (it1_ != it1_end_)
    02177                     if (it1_.index2 () <= j_)
    02178                         ++ it1_;
    02179                 if (it2_ != it2_end_)
    02180                     if (it2_.index2 () <= j_)
    02181                         ++ it2_;
    02182                 ++ j_;
    02183             }
    02184             BOOST_UBLAS_INLINE
    02185             void decrement (packed_random_access_iterator_tag) {
    02186                 if (it1_ != it1_end_)
    02187                     if (j_ <= it1_.index2 ())
    02188                         -- it1_;
    02189                 if (it2_ != it2_end_)
    02190                     if (j_ <= it2_.index2 ())
    02191                         -- it2_;
    02192                 -- j_;
    02193             }
    02194             BOOST_UBLAS_INLINE
    02195             void increment (packed_random_access_iterator_tag, difference_type n) {
    02196                 while (n > 0) {
    02197                     increment (packed_random_access_iterator_tag ());
    02198                     --n;
    02199                 }
    02200                 while (n < 0) {
    02201                     decrement (packed_random_access_iterator_tag ());
    02202                     ++n;
    02203                 }
    02204             }
    02205             BOOST_UBLAS_INLINE
    02206             void decrement (packed_random_access_iterator_tag, difference_type n) {
    02207                 while (n > 0) {
    02208                     decrement (packed_random_access_iterator_tag ());
    02209                     --n;
    02210                 }
    02211                 while (n < 0) {
    02212                     increment (packed_random_access_iterator_tag ());
    02213                     ++n;
    02214                 }
    02215             }
    02216             BOOST_UBLAS_INLINE
    02217             value_type dereference (packed_random_access_iterator_tag) const {
    02218                 value_type t1 = value_type/*zero*/();
    02219                 if (it1_ != it1_end_) {
    02220                     BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
    02221                     if (it1_.index2 () == j_)
    02222                         t1 = *it1_;
    02223                 }
    02224                 value_type t2 = value_type/*zero*/();
    02225                 if (it2_ != it2_end_) {
    02226                     BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
    02227                     if (it2_.index2 () == j_)
    02228                         t2 = *it2_;
    02229                 }
    02230                 return functor_type::apply (t1, t2);
    02231             }
    02232
    02233             // Sparse specializations
    02234             BOOST_UBLAS_INLINE
    02235             void increment (sparse_bidirectional_iterator_tag) {
    02236                 size_type index1 = (*this) ().size2 ();
    02237                 if (it1_ != it1_end_) {
    02238                     if (it1_.index2 () <= j_)
    02239                         ++ it1_;
    02240                     if (it1_ != it1_end_)
    02241                         index1 = it1_.index2 ();
    02242                 }
    02243                 size_type index2 = (*this) ().size2 ();
    02244                 if (it2_ != it2_end_) {
    02245                     if (it2_.index2 () <= j_)
    02246                         ++ it2_;
    02247                     if (it2_ != it2_end_)
    02248                         index2 = it2_.index2 ();
    02249                 }
    02250                 j_ = (std::min) (index1, index2);
    02251             }
    02252             BOOST_UBLAS_INLINE
    02253             void decrement (sparse_bidirectional_iterator_tag) {
    02254                 size_type index1 = (*this) ().size2 ();
    02255                 if (it1_ != it1_end_) {
    02256                     if (j_ <= it1_.index2 ())
    02257                         -- it1_;
    02258                     if (it1_ != it1_end_)
    02259                         index1 = it1_.index2 ();
    02260                 }
    02261                 size_type index2 = (*this) ().size2 ();
    02262                 if (it2_ != it2_end_) {
    02263                     if (j_ <= it2_.index2 ())
    02264                         -- it2_;
    02265                     if (it2_ != it2_end_)
    02266                         index2 = it2_.index2 ();
    02267                 }
    02268                 j_ = (std::max) (index1, index2);
    02269             }
    02270             BOOST_UBLAS_INLINE
    02271             void increment (sparse_bidirectional_iterator_tag, difference_type n) {
    02272                 while (n > 0) {
    02273                     increment (sparse_bidirectional_iterator_tag ());
    02274                     --n;
    02275                 }
    02276                 while (n < 0) {
    02277                     decrement (sparse_bidirectional_iterator_tag ());
    02278                     ++n;
    02279                 }
    02280             }
    02281             BOOST_UBLAS_INLINE
    02282             void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
    02283                 while (n > 0) {
    02284                     decrement (sparse_bidirectional_iterator_tag ());
    02285                     --n;
    02286                 }
    02287                 while (n < 0) {
    02288                     increment (sparse_bidirectional_iterator_tag ());
    02289                     ++n;
    02290                 }
    02291             }
    02292             BOOST_UBLAS_INLINE
    02293             value_type dereference (sparse_bidirectional_iterator_tag) const {
    02294                 value_type t1 = value_type/*zero*/();
    02295                 if (it1_ != it1_end_) {
    02296                     BOOST_UBLAS_CHECK (it1_.index1 () == i_, internal_logic ());
    02297                     if (it1_.index2 () == j_)
    02298                         t1 = *it1_;
    02299                 }
    02300                 value_type t2 = value_type/*zero*/();
    02301                 if (it2_ != it2_end_) {
    02302                     BOOST_UBLAS_CHECK (it2_.index1 () == i_, internal_logic ());
    02303                     if (it2_.index2 () == j_)
    02304                         t2 = *it2_;
    02305                 }
    02306                 return functor_type::apply (t1, t2);
    02307             }
    02308
    02309         public:
    02310             // Arithmetic
    02311             BOOST_UBLAS_INLINE
    02312             const_iterator2 &operator ++ () {
    02313                 increment (iterator_category ());
    02314                 return *this;
    02315             }
    02316             BOOST_UBLAS_INLINE
    02317             const_iterator2 &operator -- () {
    02318                 decrement (iterator_category ());
    02319                 return *this;
    02320             }
    02321             BOOST_UBLAS_INLINE
    02322             const_iterator2 &operator += (difference_type n) {
    02323                 increment (iterator_category (), n);
    02324                 return *this;
    02325             }
    02326             BOOST_UBLAS_INLINE
    02327             const_iterator2 &operator -= (difference_type n) {
    02328                 decrement (iterator_category (), n);
    02329                 return *this;
    02330             }
    02331             BOOST_UBLAS_INLINE
    02332             difference_type operator - (const const_iterator2 &it) const {
    02333                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02334                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
    02335                 return index2 () - it.index2 ();
    02336             }
    02337
    02338             // Dereference
    02339             BOOST_UBLAS_INLINE
    02340             const_reference operator * () const {
    02341                 return dereference (iterator_category ());
    02342             }
    02343             BOOST_UBLAS_INLINE
    02344             const_reference operator [] (difference_type n) const {
    02345                 return *(*this + n);
    02346             }
    02347
    02348 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02349             BOOST_UBLAS_INLINE
    02350 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02351             typename self_type::
    02352 #endif
    02353             const_iterator1 begin () const {
    02354                 return (*this) ().find1 (1, 0, index2 ());
    02355             }
    02356             BOOST_UBLAS_INLINE
    02357 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02358             typename self_type::
    02359 #endif
    02360             const_iterator1 end () const {
    02361                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
    02362             }
    02363             BOOST_UBLAS_INLINE
    02364 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02365             typename self_type::
    02366 #endif
    02367             const_reverse_iterator1 rbegin () const {
    02368                 return const_reverse_iterator1 (end ());
    02369             }
    02370             BOOST_UBLAS_INLINE
    02371 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02372             typename self_type::
    02373 #endif
    02374             const_reverse_iterator1 rend () const {
    02375                 return const_reverse_iterator1 (begin ());
    02376             }
    02377 #endif
    02378
    02379             // Indices
    02380             BOOST_UBLAS_INLINE
    02381             size_type index1 () const {
    02382                 // if (it1_ != it1_end_ && it2_ != it2_end_)
    02383                 //    return BOOST_UBLAS_SAME (it1_.index1 (), it2_.index1 ());
    02384                 // else
    02385                     return i_;
    02386             }
    02387             BOOST_UBLAS_INLINE
    02388             size_type index2 () const {
    02389                 return j_;
    02390             }
    02391
    02392             // Assignment
    02393             BOOST_UBLAS_INLINE
    02394             const_iterator2 &operator = (const const_iterator2 &it) {
    02395                 container_const_reference<self_type>::assign (&it ());
    02396                 i_ = it.i_;
    02397                 j_ = it.j_;
    02398                 it1_ = it.it1_;
    02399                 it1_end_ = it.it1_end_;
    02400                 it2_ = it.it2_;
    02401                 it2_end_ = it.it2_end_;
    02402                 return *this;
    02403             }
    02404
    02405             // Comparison
    02406             BOOST_UBLAS_INLINE
    02407             bool operator == (const const_iterator2 &it) const {
    02408                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02409                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
    02410                 return index2 () == it.index2 ();
    02411             }
    02412             BOOST_UBLAS_INLINE
    02413             bool operator < (const const_iterator2 &it) const {
    02414                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02415                 BOOST_UBLAS_CHECK (index1 () == it.index1 (), external_logic ());
    02416                 return index2 () < it.index2 ();
    02417             }
    02418
    02419         private:
    02420             size_type i_;
    02421             size_type j_;
    02422             const_iterator12_type it1_;
    02423             const_iterator12_type it1_end_;
    02424             const_iterator22_type it2_;
    02425             const_iterator22_type it2_end_;
    02426         };
    02427 #endif
    02428
    02429         BOOST_UBLAS_INLINE
    02430         const_iterator2 begin2 () const {
    02431             return find2 (0, 0, 0);
    02432         }
    02433         BOOST_UBLAS_INLINE
    02434         const_iterator2 end2 () const {
    02435             return find2 (0, 0, size2 ());
    02436         }
    02437
    02438         // Reverse iterators
    02439
    02440         BOOST_UBLAS_INLINE
    02441         const_reverse_iterator1 rbegin1 () const {
    02442             return const_reverse_iterator1 (end1 ());
    02443         }
    02444         BOOST_UBLAS_INLINE
    02445         const_reverse_iterator1 rend1 () const {
    02446             return const_reverse_iterator1 (begin1 ());
    02447         }
    02448
    02449         BOOST_UBLAS_INLINE
    02450         const_reverse_iterator2 rbegin2 () const {
    02451             return const_reverse_iterator2 (end2 ());
    02452         }
    02453         BOOST_UBLAS_INLINE
    02454         const_reverse_iterator2 rend2 () const {
    02455             return const_reverse_iterator2 (begin2 ());
    02456         }
    02457
    02458     private:
    02459         expression1_closure_type e1_;
    02460         expression2_closure_type e2_;
    02461     };
    02462
    02463     template<class E1, class E2, class F>
    02464     struct matrix_binary_traits {
    02465         typedef matrix_binary<E1, E2, F> expression_type;
    02466 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
    02467         typedef expression_type result_type;
    02468 #else
    02469         typedef typename E1::matrix_temporary_type result_type;
    02470 #endif
    02471     };
    02472
    02473     // (m1 + m2) [i] [j] = m1 [i] [j] + m2 [i] [j]
    02474     template<class E1, class E2>
    02475     BOOST_UBLAS_INLINE
    02476     typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
    02477                                                       typename E2::value_type> >::result_type
    02478     operator + (const matrix_expression<E1> &e1,
    02479                 const matrix_expression<E2> &e2) {
    02480         typedef typename matrix_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
    02481                                                                   typename E2::value_type> >::expression_type expression_type;
    02482         return expression_type (e1 (), e2 ());
    02483     }
    02484
    02485     // (m1 - m2) [i] [j] = m1 [i] [j] - m2 [i] [j]
    02486     template<class E1, class E2>
    02487     BOOST_UBLAS_INLINE
    02488     typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
    02489                                                        typename E2::value_type> >::result_type
    02490     operator - (const matrix_expression<E1> &e1,
    02491                 const matrix_expression<E2> &e2) {
    02492         typedef typename matrix_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
    02493                                                                    typename E2::value_type> >::expression_type expression_type;
    02494         return expression_type (e1 (), e2 ());
    02495     }
    02496
    02497     // (m1 * m2) [i] [j] = m1 [i] [j] * m2 [i] [j]
    02498     template<class E1, class E2>
    02499     BOOST_UBLAS_INLINE
    02500     typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
    02501                                                             typename E2::value_type> >::result_type
    02502     element_prod (const matrix_expression<E1> &e1,
    02503                   const matrix_expression<E2> &e2) {
    02504         typedef typename matrix_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
    02505                                                                         typename E2::value_type> >::expression_type expression_type;
    02506         return expression_type (e1 (), e2 ());
    02507     }
    02508
    02509     // (m1 / m2) [i] [j] = m1 [i] [j] / m2 [i] [j]
    02510     template<class E1, class E2>
    02511     BOOST_UBLAS_INLINE
    02512     typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
    02513                                                          typename E2::value_type> >::result_type
    02514     element_div (const matrix_expression<E1> &e1,
    02515                  const matrix_expression<E2> &e2) {
    02516         typedef typename matrix_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
    02517                                                                      typename E2::value_type> >::expression_type expression_type;
    02518         return expression_type (e1 (), e2 ());
    02519     }
    02520
    02521     template<class E1, class E2, class F>
    02522     class matrix_binary_scalar1:
    02523         public matrix_expression<matrix_binary_scalar1<E1, E2, F> > {
    02524
    02525         typedef E1 expression1_type;
    02526         typedef E2 expression2_type;
    02527         typedef F functor_type;
    02528         typedef const E1& expression1_closure_type;
    02529         typedef typename E2::const_closure_type expression2_closure_type;
    02530         typedef matrix_binary_scalar1<E1, E2, F> self_type;
    02531     public:
    02532 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    02533         using matrix_expression<self_type>::operator ();
    02534 #endif
    02535         typedef typename E2::size_type size_type;
    02536         typedef typename E2::difference_type difference_type;
    02537         typedef typename F::result_type value_type;
    02538         typedef value_type const_reference;
    02539         typedef const_reference reference;
    02540         typedef const self_type const_closure_type;
    02541         typedef const_closure_type closure_type;
    02542         typedef typename E2::orientation_category orientation_category;
    02543         typedef unknown_storage_tag storage_category;
    02544
    02545         // Construction and destruction
    02546         BOOST_UBLAS_INLINE
    02547         matrix_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
    02548             e1_ (e1), e2_ (e2) {}
    02549
    02550         // Accessors
    02551         BOOST_UBLAS_INLINE
    02552         size_type size1 () const {
    02553             return e2_.size1 ();
    02554         }
    02555         BOOST_UBLAS_INLINE
    02556         size_type size2 () const {
    02557             return e2_.size2 ();
    02558         }
    02559
    02560     public:
    02561         // Element access
    02562         BOOST_UBLAS_INLINE
    02563         const_reference operator () (size_type i, size_type j) const {
    02564             return functor_type::apply (expression1_type (e1_), e2_ (i, j));
    02565         }
    02566
    02567         // Closure comparison
    02568         BOOST_UBLAS_INLINE
    02569         bool same_closure (const matrix_binary_scalar1 &mbs1) const {
    02570             return &e1_ == &(mbs1.e1_) &&
    02571                    (*this).e2_.same_closure (mbs1.e2_);
    02572         }
    02573
    02574         // Iterator types
    02575     private:
    02576         typedef expression1_type const_subiterator1_type;
    02577         typedef typename E2::const_iterator1 const_iterator21_type;
    02578         typedef typename E2::const_iterator2 const_iterator22_type;
    02579         typedef const value_type *const_pointer;
    02580
    02581     public:
    02582 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02583         typedef indexed_const_iterator1<const_closure_type, typename const_iterator21_type::iterator_category> const_iterator1;
    02584         typedef const_iterator1 iterator1;
    02585         typedef indexed_const_iterator2<const_closure_type, typename const_iterator22_type::iterator_category> const_iterator2;
    02586         typedef const_iterator2 iterator2;
    02587 #else
    02588         class const_iterator1;
    02589         typedef const_iterator1 iterator1;
    02590         class const_iterator2;
    02591         typedef const_iterator2 iterator2;
    02592 #endif
    02593         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    02594         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    02595
    02596         // Element lookup
    02597         BOOST_UBLAS_INLINE
    02598         const_iterator1 find1 (int rank, size_type i, size_type j) const {
    02599             const_iterator21_type it21 (e2_.find1 (rank, i, j));
    02600 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02601             return const_iterator1 (*this, it21.index1 (), it21.index2 ());
    02602 #else
    02603             return const_iterator1 (*this, const_subiterator1_type (e1_), it21);
    02604 #endif
    02605         }
    02606         BOOST_UBLAS_INLINE
    02607         const_iterator2 find2 (int rank, size_type i, size_type j) const {
    02608             const_iterator22_type it22 (e2_.find2 (rank, i, j));
    02609 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02610             return const_iterator2 (*this, it22.index1 (), it22.index2 ());
    02611 #else
    02612             return const_iterator2 (*this, const_subiterator1_type (e1_), it22);
    02613 #endif
    02614         }
    02615
    02616         // Iterators enhance the iterators of the referenced expression
    02617         // with the binary functor.
    02618
    02619 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02620         class const_iterator1:
    02621             public container_const_reference<matrix_binary_scalar1>,
    02622             public iterator_base_traits<typename E2::const_iterator1::iterator_category>::template
    02623                 iterator_base<const_iterator1, value_type>::type {
    02624         public:
    02625             typedef typename E2::const_iterator1::iterator_category iterator_category;
    02626             typedef typename matrix_binary_scalar1::difference_type difference_type;
    02627             typedef typename matrix_binary_scalar1::value_type value_type;
    02628             typedef typename matrix_binary_scalar1::const_reference reference;
    02629             typedef typename matrix_binary_scalar1::const_pointer pointer;
    02630
    02631             typedef const_iterator2 dual_iterator_type;
    02632             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    02633
    02634             // Construction and destruction
    02635             BOOST_UBLAS_INLINE
    02636             const_iterator1 ():
    02637                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    02638             BOOST_UBLAS_INLINE
    02639             const_iterator1 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator21_type &it2):
    02640                 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
    02641
    02642             // Arithmetic
    02643             BOOST_UBLAS_INLINE
    02644             const_iterator1 &operator ++ () {
    02645                 ++ it2_;
    02646                 return *this;
    02647             }
    02648             BOOST_UBLAS_INLINE
    02649             const_iterator1 &operator -- () {
    02650                 -- it2_ ;
    02651                 return *this;
    02652             }
    02653             BOOST_UBLAS_INLINE
    02654             const_iterator1 &operator += (difference_type n) {
    02655                 it2_ += n;
    02656                 return *this;
    02657             }
    02658             BOOST_UBLAS_INLINE
    02659             const_iterator1 &operator -= (difference_type n) {
    02660                 it2_ -= n;
    02661                 return *this;
    02662             }
    02663             BOOST_UBLAS_INLINE
    02664             difference_type operator - (const const_iterator1 &it) const {
    02665                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02666                 // FIXME we shouldn't compare floats
    02667                 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    02668                 return it2_ - it.it2_;
    02669             }
    02670
    02671             // Dereference
    02672             BOOST_UBLAS_INLINE
    02673             const_reference operator * () const {
    02674                 return functor_type::apply (it1_, *it2_);
    02675             }
    02676             BOOST_UBLAS_INLINE
    02677             const_reference operator [] (difference_type n) const {
    02678                 return *(*this + n);
    02679             }
    02680
    02681 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02682             BOOST_UBLAS_INLINE
    02683 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02684             typename self_type::
    02685 #endif
    02686             const_iterator2 begin () const {
    02687                 return (*this) ().find2 (1, index1 (), 0);
    02688             }
    02689             BOOST_UBLAS_INLINE
    02690 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02691             typename self_type::
    02692 #endif
    02693             const_iterator2 end () const {
    02694                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
    02695             }
    02696             BOOST_UBLAS_INLINE
    02697 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02698             typename self_type::
    02699 #endif
    02700             const_reverse_iterator2 rbegin () const {
    02701                 return const_reverse_iterator2 (end ());
    02702             }
    02703             BOOST_UBLAS_INLINE
    02704 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02705             typename self_type::
    02706 #endif
    02707             const_reverse_iterator2 rend () const {
    02708                 return const_reverse_iterator2 (begin ());
    02709             }
    02710 #endif
    02711
    02712             // Indices
    02713             BOOST_UBLAS_INLINE
    02714             size_type index1 () const {
    02715                 return it2_.index1 ();
    02716             }
    02717             BOOST_UBLAS_INLINE
    02718             size_type index2 () const {
    02719                 return it2_.index2 ();
    02720             }
    02721
    02722             // Assignment
    02723             BOOST_UBLAS_INLINE
    02724             const_iterator1 &operator = (const const_iterator1 &it) {
    02725                 container_const_reference<self_type>::assign (&it ());
    02726                 it1_ = it.it1_;
    02727                 it2_ = it.it2_;
    02728                 return *this;
    02729             }
    02730
    02731             // Comparison
    02732             BOOST_UBLAS_INLINE
    02733             bool operator == (const const_iterator1 &it) const {
    02734                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02735                 // FIXME we shouldn't compare floats
    02736                 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    02737                 return it2_ == it.it2_;
    02738             }
    02739             BOOST_UBLAS_INLINE
    02740             bool operator < (const const_iterator1 &it) const {
    02741                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02742                 // FIXME we shouldn't compare floats
    02743                 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    02744                 return it2_ < it.it2_;
    02745             }
    02746
    02747         private:
    02748             const_subiterator1_type it1_;
    02749             const_iterator21_type it2_;
    02750         };
    02751 #endif
    02752
    02753         BOOST_UBLAS_INLINE
    02754         const_iterator1 begin1 () const {
    02755             return find1 (0, 0, 0);
    02756         }
    02757         BOOST_UBLAS_INLINE
    02758         const_iterator1 end1 () const {
    02759             return find1 (0, size1 (), 0);
    02760         }
    02761
    02762 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    02763         class const_iterator2:
    02764             public container_const_reference<matrix_binary_scalar1>,
    02765             public iterator_base_traits<typename E2::const_iterator2::iterator_category>::template
    02766                 iterator_base<const_iterator2, value_type>::type {
    02767         public:
    02768             typedef typename E2::const_iterator2::iterator_category iterator_category;
    02769             typedef typename matrix_binary_scalar1::difference_type difference_type;
    02770             typedef typename matrix_binary_scalar1::value_type value_type;
    02771             typedef typename matrix_binary_scalar1::const_reference reference;
    02772             typedef typename matrix_binary_scalar1::const_pointer pointer;
    02773
    02774             typedef const_iterator1 dual_iterator_type;
    02775             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    02776
    02777             // Construction and destruction
    02778             BOOST_UBLAS_INLINE
    02779             const_iterator2 ():
    02780                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    02781             BOOST_UBLAS_INLINE
    02782             const_iterator2 (const self_type &mbs, const const_subiterator1_type &it1, const const_iterator22_type &it2):
    02783                 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
    02784
    02785             // Arithmetic
    02786             BOOST_UBLAS_INLINE
    02787             const_iterator2 &operator ++ () {
    02788                 ++ it2_;
    02789                 return *this;
    02790             }
    02791             BOOST_UBLAS_INLINE
    02792             const_iterator2 &operator -- () {
    02793                 -- it2_;
    02794                 return *this;
    02795             }
    02796             BOOST_UBLAS_INLINE
    02797             const_iterator2 &operator += (difference_type n) {
    02798                 it2_ += n;
    02799                 return *this;
    02800             }
    02801             BOOST_UBLAS_INLINE
    02802             const_iterator2 &operator -= (difference_type n) {
    02803                 it2_ -= n;
    02804                 return *this;
    02805             }
    02806             BOOST_UBLAS_INLINE
    02807             difference_type operator - (const const_iterator2 &it) const {
    02808                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02809                 // FIXME we shouldn't compare floats
    02810                 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    02811                 return it2_ - it.it2_;
    02812             }
    02813
    02814             // Dereference
    02815             BOOST_UBLAS_INLINE
    02816             const_reference operator * () const {
    02817                 return functor_type::apply (it1_, *it2_);
    02818             }
    02819             BOOST_UBLAS_INLINE
    02820             const_reference operator [] (difference_type n) const {
    02821                 return *(*this + n);
    02822             }
    02823
    02824 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    02825             BOOST_UBLAS_INLINE
    02826 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02827             typename self_type::
    02828 #endif
    02829             const_iterator1 begin () const {
    02830                 return (*this) ().find1 (1, 0, index2 ());
    02831             }
    02832             BOOST_UBLAS_INLINE
    02833 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02834             typename self_type::
    02835 #endif
    02836             const_iterator1 end () const {
    02837                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
    02838             }
    02839             BOOST_UBLAS_INLINE
    02840 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02841             typename self_type::
    02842 #endif
    02843             const_reverse_iterator1 rbegin () const {
    02844                 return const_reverse_iterator1 (end ());
    02845             }
    02846             BOOST_UBLAS_INLINE
    02847 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    02848             typename self_type::
    02849 #endif
    02850             const_reverse_iterator1 rend () const {
    02851                 return const_reverse_iterator1 (begin ());
    02852             }
    02853 #endif
    02854
    02855             // Indices
    02856             BOOST_UBLAS_INLINE
    02857             size_type index1 () const {
    02858                 return it2_.index1 ();
    02859             }
    02860             BOOST_UBLAS_INLINE
    02861             size_type index2 () const {
    02862                 return it2_.index2 ();
    02863             }
    02864
    02865             // Assignment
    02866             BOOST_UBLAS_INLINE
    02867             const_iterator2 &operator = (const const_iterator2 &it) {
    02868                 container_const_reference<self_type>::assign (&it ());
    02869                 it1_ = it.it1_;
    02870                 it2_ = it.it2_;
    02871                 return *this;
    02872             }
    02873
    02874             // Comparison
    02875             BOOST_UBLAS_INLINE
    02876             bool operator == (const const_iterator2 &it) const {
    02877                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02878                 // FIXME we shouldn't compare floats
    02879                 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    02880                 return it2_ == it.it2_;
    02881             }
    02882             BOOST_UBLAS_INLINE
    02883             bool operator < (const const_iterator2 &it) const {
    02884                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    02885                 // FIXME we shouldn't compare floats
    02886                 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    02887                 return it2_ < it.it2_;
    02888             }
    02889
    02890         private:
    02891             const_subiterator1_type it1_;
    02892             const_iterator22_type it2_;
    02893         };
    02894 #endif
    02895
    02896         BOOST_UBLAS_INLINE
    02897         const_iterator2 begin2 () const {
    02898             return find2 (0, 0, 0);
    02899         }
    02900         BOOST_UBLAS_INLINE
    02901         const_iterator2 end2 () const {
    02902             return find2 (0, 0, size2 ());
    02903         }
    02904
    02905         // Reverse iterators
    02906
    02907         BOOST_UBLAS_INLINE
    02908         const_reverse_iterator1 rbegin1 () const {
    02909             return const_reverse_iterator1 (end1 ());
    02910         }
    02911         BOOST_UBLAS_INLINE
    02912         const_reverse_iterator1 rend1 () const {
    02913             return const_reverse_iterator1 (begin1 ());
    02914         }
    02915
    02916         BOOST_UBLAS_INLINE
    02917         const_reverse_iterator2 rbegin2 () const {
    02918             return const_reverse_iterator2 (end2 ());
    02919         }
    02920         BOOST_UBLAS_INLINE
    02921         const_reverse_iterator2 rend2 () const {
    02922             return const_reverse_iterator2 (begin2 ());
    02923         }
    02924
    02925     private:
    02926         expression1_closure_type e1_;
    02927         expression2_closure_type e2_;
    02928     };
    02929
    02930     template<class E1, class E2, class F>
    02931     struct matrix_binary_scalar1_traits {
    02932         typedef matrix_binary_scalar1<E1, E2, F> expression_type;   // allow E1 to be builtin type
    02933 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
    02934         typedef expression_type result_type;
    02935 #else
    02936         typedef typename E2::matrix_temporary_type result_type;
    02937 #endif
    02938     };
    02939
    02940     // (t * m) [i] [j] = t * m [i] [j]
    02941     template<class T1, class E2>
    02942     BOOST_UBLAS_INLINE
    02943     typename enable_if< is_convertible<T1, typename E2::value_type >,
    02944     typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
    02945     >::type
    02946     operator * (const T1 &e1,
    02947                 const matrix_expression<E2> &e2) {
    02948         typedef typename matrix_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
    02949         return expression_type (e1, e2 ());
    02950     }
    02951
    02952
    02953     template<class E1, class E2, class F>
    02954     class matrix_binary_scalar2:
    02955         public matrix_expression<matrix_binary_scalar2<E1, E2, F> > {
    02956
    02957         typedef E1 expression1_type;
    02958         typedef E2 expression2_type;
    02959         typedef F functor_type;
    02960     public:
    02961         typedef typename E1::const_closure_type expression1_closure_type;
    02962         typedef const E2& expression2_closure_type;
    02963     private:
    02964         typedef matrix_binary_scalar2<E1, E2, F> self_type;
    02965     public:
    02966 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    02967         using matrix_expression<self_type>::operator ();
    02968 #endif
    02969         typedef typename E1::size_type size_type;
    02970         typedef typename E1::difference_type difference_type;
    02971         typedef typename F::result_type value_type;
    02972         typedef value_type const_reference;
    02973         typedef const_reference reference;
    02974
    02975         typedef const self_type const_closure_type;
    02976         typedef const_closure_type closure_type;
    02977         typedef typename E1::orientation_category orientation_category;
    02978         typedef unknown_storage_tag storage_category;
    02979
    02980         // Construction and destruction
    02981         BOOST_UBLAS_INLINE
    02982         matrix_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
    02983             e1_ (e1), e2_ (e2) {}
    02984
    02985         // Accessors
    02986         BOOST_UBLAS_INLINE
    02987         size_type size1 () const {
    02988             return e1_.size1 ();
    02989         }
    02990         BOOST_UBLAS_INLINE
    02991         size_type size2 () const {
    02992             return e1_.size2 ();
    02993         }
    02994
    02995     public:
    02996         // Element access
    02997         BOOST_UBLAS_INLINE
    02998         const_reference operator () (size_type i, size_type j) const {
    02999             return functor_type::apply (e1_ (i, j), expression2_type (e2_));
    03000         }
    03001
    03002         // Closure comparison
    03003         BOOST_UBLAS_INLINE
    03004         bool same_closure (const matrix_binary_scalar2 &mbs2) const {
    03005             return (*this).e1_.same_closure (mbs2.e1_) &&
    03006                    &e2_ == &(mbs2.e2_);
    03007         }
    03008
    03009         // Iterator types
    03010     private:
    03011         typedef typename E1::const_iterator1 const_iterator11_type;
    03012         typedef typename E1::const_iterator2 const_iterator12_type;
    03013         typedef expression2_type const_subiterator2_type;
    03014         typedef const value_type *const_pointer;
    03015
    03016     public:
    03017 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03018         typedef indexed_const_iterator1<const_closure_type, typename const_iterator11_type::iterator_category> const_iterator1;
    03019         typedef const_iterator1 iterator1;
    03020         typedef indexed_const_iterator2<const_closure_type, typename const_iterator12_type::iterator_category> const_iterator2;
    03021         typedef const_iterator2 iterator2;
    03022 #else
    03023         class const_iterator1;
    03024         typedef const_iterator1 iterator1;
    03025         class const_iterator2;
    03026         typedef const_iterator2 iterator2;
    03027 #endif
    03028         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    03029         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    03030
    03031         // Element lookup
    03032         BOOST_UBLAS_INLINE
    03033         const_iterator1 find1 (int rank, size_type i, size_type j) const {
    03034             const_iterator11_type it11 (e1_.find1 (rank, i, j));
    03035 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03036             return const_iterator1 (*this, it11.index1 (), it11.index2 ());
    03037 #else
    03038             return const_iterator1 (*this, it11, const_subiterator2_type (e2_));
    03039 #endif
    03040         }
    03041         BOOST_UBLAS_INLINE
    03042         const_iterator2 find2 (int rank, size_type i, size_type j) const {
    03043             const_iterator12_type it12 (e1_.find2 (rank, i, j));
    03044 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03045             return const_iterator2 (*this, it12.index1 (), it12.index2 ());
    03046 #else
    03047             return const_iterator2 (*this, it12, const_subiterator2_type (e2_));
    03048 #endif
    03049         }
    03050
    03051         // Iterators enhance the iterators of the referenced expression
    03052         // with the binary functor.
    03053
    03054 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03055         class const_iterator1:
    03056             public container_const_reference<matrix_binary_scalar2>,
    03057             public iterator_base_traits<typename E1::const_iterator1::iterator_category>::template
    03058                 iterator_base<const_iterator1, value_type>::type {
    03059         public:
    03060             typedef typename E1::const_iterator1::iterator_category iterator_category;
    03061             typedef typename matrix_binary_scalar2::difference_type difference_type;
    03062             typedef typename matrix_binary_scalar2::value_type value_type;
    03063             typedef typename matrix_binary_scalar2::const_reference reference;
    03064             typedef typename matrix_binary_scalar2::const_pointer pointer;
    03065
    03066             typedef const_iterator2 dual_iterator_type;
    03067             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    03068
    03069             // Construction and destruction
    03070             BOOST_UBLAS_INLINE
    03071             const_iterator1 ():
    03072                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    03073             BOOST_UBLAS_INLINE
    03074             const_iterator1 (const self_type &mbs, const const_iterator11_type &it1, const const_subiterator2_type &it2):
    03075                 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
    03076
    03077             // Arithmetic
    03078             BOOST_UBLAS_INLINE
    03079             const_iterator1 &operator ++ () {
    03080                 ++ it1_;
    03081                 return *this;
    03082             }
    03083             BOOST_UBLAS_INLINE
    03084             const_iterator1 &operator -- () {
    03085                 -- it1_ ;
    03086                 return *this;
    03087             }
    03088             BOOST_UBLAS_INLINE
    03089             const_iterator1 &operator += (difference_type n) {
    03090                 it1_ += n;
    03091                 return *this;
    03092             }
    03093             BOOST_UBLAS_INLINE
    03094             const_iterator1 &operator -= (difference_type n) {
    03095                 it1_ -= n;
    03096                 return *this;
    03097             }
    03098             BOOST_UBLAS_INLINE
    03099             difference_type operator - (const const_iterator1 &it) const {
    03100                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    03101                 // FIXME we shouldn't compare floats
    03102                 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03103                 return it1_ - it.it1_;
    03104             }
    03105
    03106             // Dereference
    03107             BOOST_UBLAS_INLINE
    03108             const_reference operator * () const {
    03109                 return functor_type::apply (*it1_, it2_);
    03110             }
    03111             BOOST_UBLAS_INLINE
    03112             const_reference operator [] (difference_type n) const {
    03113                 return *(*this + n);
    03114             }
    03115
    03116 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03117             BOOST_UBLAS_INLINE
    03118 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03119             typename self_type::
    03120 #endif
    03121             const_iterator2 begin () const {
    03122                 return (*this) ().find2 (1, index1 (), 0);
    03123             }
    03124             BOOST_UBLAS_INLINE
    03125 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03126             typename self_type::
    03127 #endif
    03128             const_iterator2 end () const {
    03129                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
    03130             }
    03131             BOOST_UBLAS_INLINE
    03132 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03133             typename self_type::
    03134 #endif
    03135             const_reverse_iterator2 rbegin () const {
    03136                 return const_reverse_iterator2 (end ());
    03137             }
    03138             BOOST_UBLAS_INLINE
    03139 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03140             typename self_type::
    03141 #endif
    03142             const_reverse_iterator2 rend () const {
    03143                 return const_reverse_iterator2 (begin ());
    03144             }
    03145 #endif
    03146
    03147             // Indices
    03148             BOOST_UBLAS_INLINE
    03149             size_type index1 () const {
    03150                 return it1_.index1 ();
    03151             }
    03152             BOOST_UBLAS_INLINE
    03153             size_type index2 () const {
    03154                 return it1_.index2 ();
    03155             }
    03156
    03157             // Assignment
    03158             BOOST_UBLAS_INLINE
    03159             const_iterator1 &operator = (const const_iterator1 &it) {
    03160                 container_const_reference<self_type>::assign (&it ());
    03161                 it1_ = it.it1_;
    03162                 it2_ = it.it2_;
    03163                 return *this;
    03164             }
    03165
    03166             // Comparison
    03167             BOOST_UBLAS_INLINE
    03168             bool operator == (const const_iterator1 &it) const {
    03169                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    03170                 // FIXME we shouldn't compare floats
    03171                 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03172                 return it1_ == it.it1_;
    03173             }
    03174             BOOST_UBLAS_INLINE
    03175             bool operator < (const const_iterator1 &it) const {
    03176                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    03177                 // FIXME we shouldn't compare floats
    03178                 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03179                 return it1_ < it.it1_;
    03180             }
    03181
    03182         private:
    03183             const_iterator11_type it1_;
    03184             const_subiterator2_type it2_;
    03185         };
    03186 #endif
    03187
    03188         BOOST_UBLAS_INLINE
    03189         const_iterator1 begin1 () const {
    03190             return find1 (0, 0, 0);
    03191         }
    03192         BOOST_UBLAS_INLINE
    03193         const_iterator1 end1 () const {
    03194             return find1 (0, size1 (), 0);
    03195         }
    03196
    03197 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03198         class const_iterator2:
    03199             public container_const_reference<matrix_binary_scalar2>,
    03200             public iterator_base_traits<typename E1::const_iterator2::iterator_category>::template
    03201                 iterator_base<const_iterator2, value_type>::type {
    03202         public:
    03203             typedef typename E1::const_iterator2::iterator_category iterator_category;
    03204             typedef typename matrix_binary_scalar2::difference_type difference_type;
    03205             typedef typename matrix_binary_scalar2::value_type value_type;
    03206             typedef typename matrix_binary_scalar2::const_reference reference;
    03207             typedef typename matrix_binary_scalar2::const_pointer pointer;
    03208
    03209             typedef const_iterator1 dual_iterator_type;
    03210             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    03211
    03212             // Construction and destruction
    03213             BOOST_UBLAS_INLINE
    03214             const_iterator2 ():
    03215                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    03216             BOOST_UBLAS_INLINE
    03217             const_iterator2 (const self_type &mbs, const const_iterator12_type &it1, const const_subiterator2_type &it2):
    03218                 container_const_reference<self_type> (mbs), it1_ (it1), it2_ (it2) {}
    03219
    03220             // Arithmetic
    03221             BOOST_UBLAS_INLINE
    03222             const_iterator2 &operator ++ () {
    03223                 ++ it1_;
    03224                 return *this;
    03225             }
    03226             BOOST_UBLAS_INLINE
    03227             const_iterator2 &operator -- () {
    03228                 -- it1_;
    03229                 return *this;
    03230             }
    03231             BOOST_UBLAS_INLINE
    03232             const_iterator2 &operator += (difference_type n) {
    03233                 it1_ += n;
    03234                 return *this;
    03235             }
    03236             BOOST_UBLAS_INLINE
    03237             const_iterator2 &operator -= (difference_type n) {
    03238                 it1_ -= n;
    03239                 return *this;
    03240             }
    03241             BOOST_UBLAS_INLINE
    03242             difference_type operator - (const const_iterator2 &it) const {
    03243                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    03244                 // FIXME we shouldn't compare floats
    03245                 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03246                 return it1_ - it.it1_;
    03247             }
    03248
    03249             // Dereference
    03250             BOOST_UBLAS_INLINE
    03251             const_reference operator * () const {
    03252                 return functor_type::apply (*it1_, it2_);
    03253             }
    03254             BOOST_UBLAS_INLINE
    03255             const_reference operator [] (difference_type n) const {
    03256                 return *(*this + n);
    03257             }
    03258
    03259 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03260             BOOST_UBLAS_INLINE
    03261 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03262             typename self_type::
    03263 #endif
    03264             const_iterator1 begin () const {
    03265                 return (*this) ().find1 (1, 0, index2 ());
    03266             }
    03267             BOOST_UBLAS_INLINE
    03268 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03269             typename self_type::
    03270 #endif
    03271             const_iterator1 end () const {
    03272                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
    03273             }
    03274             BOOST_UBLAS_INLINE
    03275 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03276             typename self_type::
    03277 #endif
    03278             const_reverse_iterator1 rbegin () const {
    03279                 return const_reverse_iterator1 (end ());
    03280             }
    03281             BOOST_UBLAS_INLINE
    03282 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    03283             typename self_type::
    03284 #endif
    03285             const_reverse_iterator1 rend () const {
    03286                 return const_reverse_iterator1 (begin ());
    03287             }
    03288 #endif
    03289
    03290             // Indices
    03291             BOOST_UBLAS_INLINE
    03292             size_type index1 () const {
    03293                 return it1_.index1 ();
    03294             }
    03295             BOOST_UBLAS_INLINE
    03296             size_type index2 () const {
    03297                 return it1_.index2 ();
    03298             }
    03299
    03300             // Assignment
    03301             BOOST_UBLAS_INLINE
    03302             const_iterator2 &operator = (const const_iterator2 &it) {
    03303                 container_const_reference<self_type>::assign (&it ());
    03304                 it1_ = it.it1_;
    03305                 it2_ = it.it2_;
    03306                 return *this;
    03307             }
    03308
    03309             // Comparison
    03310             BOOST_UBLAS_INLINE
    03311             bool operator == (const const_iterator2 &it) const {
    03312                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    03313                 // FIXME we shouldn't compare floats
    03314                 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03315                 return it1_ == it.it1_;
    03316             }
    03317             BOOST_UBLAS_INLINE
    03318             bool operator < (const const_iterator2 &it) const {
    03319                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    03320                 // FIXME we shouldn't compare floats
    03321                 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    03322                 return it1_ < it.it1_;
    03323             }
    03324
    03325         private:
    03326             const_iterator12_type it1_;
    03327             const_subiterator2_type it2_;
    03328         };
    03329 #endif
    03330
    03331         BOOST_UBLAS_INLINE
    03332         const_iterator2 begin2 () const {
    03333             return find2 (0, 0, 0);
    03334         }
    03335         BOOST_UBLAS_INLINE
    03336         const_iterator2 end2 () const {
    03337             return find2 (0, 0, size2 ());
    03338         }
    03339
    03340         // Reverse iterators
    03341
    03342         BOOST_UBLAS_INLINE
    03343         const_reverse_iterator1 rbegin1 () const {
    03344             return const_reverse_iterator1 (end1 ());
    03345         }
    03346         BOOST_UBLAS_INLINE
    03347         const_reverse_iterator1 rend1 () const {
    03348             return const_reverse_iterator1 (begin1 ());
    03349         }
    03350
    03351         BOOST_UBLAS_INLINE
    03352         const_reverse_iterator2 rbegin2 () const {
    03353             return const_reverse_iterator2 (end2 ());
    03354         }
    03355         BOOST_UBLAS_INLINE
    03356         const_reverse_iterator2 rend2 () const {
    03357             return const_reverse_iterator2 (begin2 ());
    03358         }
    03359
    03360     private:
    03361         expression1_closure_type e1_;
    03362         expression2_closure_type e2_;
    03363     };
    03364
    03365     template<class E1, class E2, class F>
    03366     struct matrix_binary_scalar2_traits {
    03367         typedef matrix_binary_scalar2<E1, E2, F> expression_type;   // allow E2 to be builtin type
    03368 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
    03369         typedef expression_type result_type;
    03370 #else
    03371         typedef typename E1::matrix_temporary_type result_type;
    03372 #endif
    03373     };
    03374
    03375     // (m * t) [i] [j] = m [i] [j] * t
    03376     template<class E1, class T2>
    03377     BOOST_UBLAS_INLINE
    03378     typename enable_if< is_convertible<T2, typename E1::value_type>,
    03379     typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
    03380     >::type
    03381     operator * (const matrix_expression<E1> &e1,
    03382                 const T2 &e2) {
    03383         typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
    03384         return expression_type (e1 (), e2);
    03385     }
    03386
    03387     // (m / t) [i] [j] = m [i] [j] / t
    03388     template<class E1, class T2>
    03389     BOOST_UBLAS_INLINE
    03390     typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
    03391     operator / (const matrix_expression<E1> &e1,
    03392                 const T2 &e2) {
    03393         typedef typename matrix_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
    03394         return expression_type (e1 (), e2);
    03395     }
    03396
    03397
    03398     template<class E1, class E2, class F>
    03399     class matrix_vector_binary1:
    03400         public vector_expression<matrix_vector_binary1<E1, E2, F> > {
    03401
    03402     public:
    03403         typedef E1 expression1_type;
    03404         typedef E2 expression2_type;
    03405     private:
    03406         typedef F functor_type;
    03407     public:
    03408         typedef typename E1::const_closure_type expression1_closure_type;
    03409         typedef typename E2::const_closure_type expression2_closure_type;
    03410     private:
    03411         typedef matrix_vector_binary1<E1, E2, F> self_type;
    03412     public:
    03413 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    03414         using vector_expression<self_type>::operator ();
    03415 #endif
    03416         static const unsigned complexity = 1;
    03417         typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
    03418         typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
    03419         typedef typename F::result_type value_type;
    03420         typedef value_type const_reference;
    03421         typedef const_reference reference;
    03422         typedef const self_type const_closure_type;
    03423         typedef const_closure_type closure_type;
    03424         typedef unknown_storage_tag storage_category;
    03425
    03426         // Construction and destruction
    03427         BOOST_UBLAS_INLINE
    03428         matrix_vector_binary1 (const expression1_type &e1, const expression2_type &e2):
    03429             e1_ (e1), e2_ (e2) {}
    03430
    03431         // Accessors
    03432         BOOST_UBLAS_INLINE
    03433         size_type size () const {
    03434             return e1_.size1 ();
    03435         }
    03436
    03437     public:
    03438         // Expression accessors
    03439         BOOST_UBLAS_INLINE
    03440         const expression1_closure_type &expression1 () const {
    03441             return e1_;
    03442         }
    03443         BOOST_UBLAS_INLINE
    03444         const expression2_closure_type &expression2 () const {
    03445             return e2_;
    03446         }
    03447
    03448     public:
    03449         // Element access
    03450         BOOST_UBLAS_INLINE
    03451         const_reference operator () (size_type i) const {
    03452             return functor_type::apply (e1_, e2_, i);
    03453         }
    03454
    03455         // Closure comparison
    03456         BOOST_UBLAS_INLINE
    03457         bool same_closure (const matrix_vector_binary1 &mvb1) const {
    03458             return (*this).expression1 ().same_closure (mvb1.expression1 ()) &&
    03459                    (*this).expression2 ().same_closure (mvb1.expression2 ());
    03460         }
    03461
    03462         // Iterator types
    03463     private:
    03464         typedef typename E1::const_iterator1 const_subiterator1_type;
    03465         typedef typename E2::const_iterator const_subiterator2_type;
    03466         typedef const value_type *const_pointer;
    03467
    03468     public:
    03469 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03470         typedef indexed_const_iterator<const_closure_type, typename const_subiterator1_type::iterator_category> const_iterator;
    03471         typedef const_iterator iterator;
    03472 #else
    03473         class const_iterator;
    03474         typedef const_iterator iterator;
    03475 #endif
    03476
    03477         // Element lookup
    03478         BOOST_UBLAS_INLINE
    03479         const_iterator find (size_type i) const {
    03480 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03481             const_subiterator1_type it1 (e1_.find1 (0, i, 0));
    03482             return const_iterator (*this, it1.index1 ());
    03483 #else
    03484             return const_iterator (*this, e1_.find1 (0, i, 0));
    03485 #endif
    03486         }
    03487
    03488
    03489 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03490         class const_iterator:
    03491             public container_const_reference<matrix_vector_binary1>,
    03492             public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
    03493                                                                           typename E2::const_iterator::iterator_category>::iterator_category>::template
    03494                 iterator_base<const_iterator, value_type>::type {
    03495         public:
    03496             typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
    03497                                                       typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
    03498             typedef typename matrix_vector_binary1::difference_type difference_type;
    03499             typedef typename matrix_vector_binary1::value_type value_type;
    03500             typedef typename matrix_vector_binary1::const_reference reference;
    03501             typedef typename matrix_vector_binary1::const_pointer pointer;
    03502
    03503             // Construction and destruction
    03504 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    03505             BOOST_UBLAS_INLINE
    03506             const_iterator ():
    03507                 container_const_reference<self_type> (), it1_ (), e2_begin_ (), e2_end_ () {}
    03508             BOOST_UBLAS_INLINE
    03509             const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
    03510                 container_const_reference<self_type> (mvb), it1_ (it1), e2_begin_ (mvb.expression2 ().begin ()), e2_end_ (mvb.expression2 ().end ()) {}
    03511 #else
    03512             BOOST_UBLAS_INLINE
    03513             const_iterator ():
    03514                 container_const_reference<self_type> (), it1_ () {}
    03515             BOOST_UBLAS_INLINE
    03516             const_iterator (const self_type &mvb, const const_subiterator1_type &it1):
    03517                 container_const_reference<self_type> (mvb), it1_ (it1) {}
    03518 #endif
    03519
    03520         private:
    03521             // Dense random access specialization
    03522             BOOST_UBLAS_INLINE
    03523             value_type dereference (dense_random_access_iterator_tag) const {
    03524                 const self_type &mvb = (*this) ();
    03525 #ifdef BOOST_UBLAS_USE_INDEXING
    03526                 return mvb (index ());
    03527 #elif BOOST_UBLAS_USE_ITERATING
    03528                 difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
    03529 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    03530                 return functor_type::apply (size, it1_.begin (), e2_begin_);
    03531 #else
    03532                 return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
    03533 #endif
    03534 #else
    03535                 difference_type size = BOOST_UBLAS_SAME (mvb.expression1 ().size2 (), mvb.expression2 ().size ());
    03536                 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
    03537 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    03538                     return functor_type::apply (size, it1_.begin (), e2_begin_);
    03539 #else
    03540                     return functor_type::apply (size, it1_.begin (), mvb.expression2 ().begin ());
    03541 #endif
    03542                 else
    03543                     return mvb (index ());
    03544 #endif
    03545             }
    03546
    03547             // Packed bidirectional specialization
    03548             BOOST_UBLAS_INLINE
    03549             value_type dereference (packed_random_access_iterator_tag) const {
    03550 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    03551                 return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_);
    03552 #else
    03553                 const self_type &mvb = (*this) ();
    03554 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03555                 return functor_type::apply (it1_.begin (), it1_.end (),
    03556                                         mvb.expression2 ().begin (), mvb.expression2 ().end ());
    03557 #else
    03558                 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
    03559                                         boost::numeric::ublas::end (it1_, iterator1_tag ()),
    03560                                         mvb.expression2 ().begin (), mvb.expression2 ().end ());
    03561 #endif
    03562 #endif
    03563             }
    03564
    03565             // Sparse bidirectional specialization
    03566             BOOST_UBLAS_INLINE
    03567             value_type dereference (sparse_bidirectional_iterator_tag) const {
    03568 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    03569                 return functor_type::apply (it1_.begin (), it1_.end (), e2_begin_, e2_end_, sparse_bidirectional_iterator_tag ());
    03570 #else
    03571                 const self_type &mvb = (*this) ();
    03572 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03573                 return functor_type::apply (it1_.begin (), it1_.end (),
    03574                                         mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
    03575 #else
    03576                 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
    03577                                         boost::numeric::ublas::end (it1_, iterator1_tag ()),
    03578                                         mvb.expression2 ().begin (), mvb.expression2 ().end (), sparse_bidirectional_iterator_tag ());
    03579 #endif
    03580 #endif
    03581             }
    03582
    03583         public:
    03584             // Arithmetic
    03585             BOOST_UBLAS_INLINE
    03586             const_iterator &operator ++ () {
    03587                 ++ it1_;
    03588                 return *this;
    03589             }
    03590             BOOST_UBLAS_INLINE
    03591             const_iterator &operator -- () {
    03592                 -- it1_;
    03593                 return *this;
    03594             }
    03595             BOOST_UBLAS_INLINE
    03596             const_iterator &operator += (difference_type n) {
    03597                 it1_ += n;
    03598                 return *this;
    03599             }
    03600             BOOST_UBLAS_INLINE
    03601             const_iterator &operator -= (difference_type n) {
    03602                 it1_ -= n;
    03603                 return *this;
    03604             }
    03605             BOOST_UBLAS_INLINE
    03606             difference_type operator - (const const_iterator &it) const {
    03607                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    03608                 return it1_ - it.it1_;
    03609             }
    03610
    03611             // Dereference
    03612             BOOST_UBLAS_INLINE
    03613             const_reference operator * () const {
    03614                 return dereference (iterator_category ());
    03615             }
    03616             BOOST_UBLAS_INLINE
    03617             const_reference operator [] (difference_type n) const {
    03618                 return *(*this + n);
    03619             }
    03620
    03621             // Index
    03622             BOOST_UBLAS_INLINE
    03623             size_type index () const {
    03624                 return it1_.index1 ();
    03625             }
    03626
    03627             // Assignment
    03628             BOOST_UBLAS_INLINE
    03629             const_iterator &operator = (const const_iterator &it) {
    03630                 container_const_reference<self_type>::assign (&it ());
    03631                 it1_ = it.it1_;
    03632 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    03633                 e2_begin_ = it.e2_begin_;
    03634                 e2_end_ = it.e2_end_;
    03635 #endif
    03636                 return *this;
    03637             }
    03638
    03639             // Comparison
    03640             BOOST_UBLAS_INLINE
    03641             bool operator == (const const_iterator &it) const {
    03642                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    03643                 return it1_ == it.it1_;
    03644             }
    03645             BOOST_UBLAS_INLINE
    03646             bool operator < (const const_iterator &it) const {
    03647                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    03648                 return it1_ < it.it1_;
    03649             }
    03650
    03651         private:
    03652             const_subiterator1_type it1_;
    03653 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    03654             // Mutable due to assignment
    03655             /* const */ const_subiterator2_type e2_begin_;
    03656             /* const */ const_subiterator2_type e2_end_;
    03657 #endif
    03658         };
    03659 #endif
    03660
    03661         BOOST_UBLAS_INLINE
    03662         const_iterator begin () const {
    03663             return find (0);
    03664         }
    03665         BOOST_UBLAS_INLINE
    03666         const_iterator end () const {
    03667             return find (size ());
    03668         }
    03669
    03670         // Reverse iterator
    03671         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
    03672
    03673         BOOST_UBLAS_INLINE
    03674         const_reverse_iterator rbegin () const {
    03675             return const_reverse_iterator (end ());
    03676         }
    03677         BOOST_UBLAS_INLINE
    03678         const_reverse_iterator rend () const {
    03679             return const_reverse_iterator (begin ());
    03680         }
    03681
    03682     private:
    03683         expression1_closure_type e1_;
    03684         expression2_closure_type e2_;
    03685     };
    03686
    03687     template<class T1, class E1, class T2, class E2>
    03688     struct matrix_vector_binary1_traits {
    03689         typedef unknown_storage_tag storage_category;
    03690         typedef row_major_tag orientation_category;
    03691         typedef typename promote_traits<T1, T2>::promote_type promote_type;
    03692         typedef matrix_vector_binary1<E1, E2, matrix_vector_prod1<E1, E2, promote_type> > expression_type;
    03693 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
    03694         typedef expression_type result_type;
    03695 #else
    03696         typedef typename E1::vector_temporary_type result_type;
    03697 #endif
    03698     };
    03699
    03700     template<class E1, class E2>
    03701     BOOST_UBLAS_INLINE
    03702     typename matrix_vector_binary1_traits<typename E1::value_type, E1,
    03703                                           typename E2::value_type, E2>::result_type
    03704     prod (const matrix_expression<E1> &e1,
    03705           const vector_expression<E2> &e2,
    03706           unknown_storage_tag,
    03707           row_major_tag) {
    03708         typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
    03709                                                       typename E2::value_type, E2>::expression_type expression_type;
    03710         return expression_type (e1 (), e2 ());
    03711     }
    03712
    03713     // Dispatcher
    03714     template<class E1, class E2>
    03715     BOOST_UBLAS_INLINE
    03716     typename matrix_vector_binary1_traits<typename E1::value_type, E1,
    03717                                           typename E2::value_type, E2>::result_type
    03718     prod (const matrix_expression<E1> &e1,
    03719           const vector_expression<E2> &e2) {
    03720         BOOST_STATIC_ASSERT (E2::complexity == 0);
    03721         typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
    03722                                                       typename E2::value_type, E2>::storage_category storage_category;
    03723         typedef typename matrix_vector_binary1_traits<typename E1::value_type, E1,
    03724                                                       typename E2::value_type, E2>::orientation_category orientation_category;
    03725         return prod (e1, e2, storage_category (), orientation_category ());
    03726     }
    03727
    03728     template<class E1, class E2>
    03729     BOOST_UBLAS_INLINE
    03730     typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    03731                                           typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
    03732     prec_prod (const matrix_expression<E1> &e1,
    03733                const vector_expression<E2> &e2,
    03734                unknown_storage_tag,
    03735                row_major_tag) {
    03736         typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    03737                                                       typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
    03738         return expression_type (e1 (), e2 ());
    03739     }
    03740
    03741     // Dispatcher
    03742     template<class E1, class E2>
    03743     BOOST_UBLAS_INLINE
    03744     typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    03745                                           typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
    03746     prec_prod (const matrix_expression<E1> &e1,
    03747                const vector_expression<E2> &e2) {
    03748         BOOST_STATIC_ASSERT (E2::complexity == 0);
    03749         typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    03750                                                       typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
    03751         typedef typename matrix_vector_binary1_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    03752                                                       typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
    03753         return prec_prod (e1, e2, storage_category (), orientation_category ());
    03754     }
    03755
    03756     template<class V, class E1, class E2>
    03757     BOOST_UBLAS_INLINE
    03758     V &
    03759     prod (const matrix_expression<E1> &e1,
    03760           const vector_expression<E2> &e2,
    03761           V &v) {
    03762         return v.assign (prod (e1, e2));
    03763     }
    03764
    03765     template<class V, class E1, class E2>
    03766     BOOST_UBLAS_INLINE
    03767     V &
    03768     prec_prod (const matrix_expression<E1> &e1,
    03769                const vector_expression<E2> &e2,
    03770                V &v) {
    03771         return v.assign (prec_prod (e1, e2));
    03772     }
    03773
    03774     template<class V, class E1, class E2>
    03775     BOOST_UBLAS_INLINE
    03776     V
    03777     prod (const matrix_expression<E1> &e1,
    03778           const vector_expression<E2> &e2) {
    03779         return V (prod (e1, e2));
    03780     }
    03781
    03782     template<class V, class E1, class E2>
    03783     BOOST_UBLAS_INLINE
    03784     V
    03785     prec_prod (const matrix_expression<E1> &e1,
    03786                const vector_expression<E2> &e2) {
    03787         return V (prec_prod (e1, e2));
    03788     }
    03789
    03790     template<class E1, class E2, class F>
    03791     class matrix_vector_binary2:
    03792         public vector_expression<matrix_vector_binary2<E1, E2, F> > {
    03793
    03794         typedef E1 expression1_type;
    03795         typedef E2 expression2_type;
    03796         typedef F functor_type;
    03797     public:
    03798         typedef typename E1::const_closure_type expression1_closure_type;
    03799         typedef typename E2::const_closure_type expression2_closure_type;
    03800     private:
    03801         typedef matrix_vector_binary2<E1, E2, F> self_type;
    03802     public:
    03803 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    03804         using vector_expression<self_type>::operator ();
    03805 #endif
    03806         static const unsigned complexity = 1;
    03807         typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
    03808         typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
    03809         typedef typename F::result_type value_type;
    03810         typedef value_type const_reference;
    03811         typedef const_reference reference;
    03812         typedef const self_type const_closure_type;
    03813         typedef const_closure_type closure_type;
    03814         typedef unknown_storage_tag storage_category;
    03815
    03816         // Construction and destruction
    03817         BOOST_UBLAS_INLINE
    03818         matrix_vector_binary2 (const expression1_type &e1, const expression2_type &e2):
    03819             e1_ (e1), e2_ (e2) {}
    03820
    03821         // Accessors
    03822         BOOST_UBLAS_INLINE
    03823         size_type size () const {
    03824             return e2_.size2 ();
    03825         }
    03826
    03827     public:
    03828         // Expression accessors
    03829         BOOST_UBLAS_INLINE
    03830         const expression1_closure_type &expression1 () const {
    03831             return e1_;
    03832         }
    03833         BOOST_UBLAS_INLINE
    03834         const expression2_closure_type &expression2 () const {
    03835             return e2_;
    03836         }
    03837     public:
    03838
    03839         // Element access
    03840         BOOST_UBLAS_INLINE
    03841         const_reference operator () (size_type j) const {
    03842             return functor_type::apply (e1_, e2_, j);
    03843         }
    03844
    03845         // Closure comparison
    03846         BOOST_UBLAS_INLINE
    03847         bool same_closure (const matrix_vector_binary2 &mvb2) const {
    03848             return (*this).expression1 ().same_closure (mvb2.expression1 ()) &&
    03849                    (*this).expression2 ().same_closure (mvb2.expression2 ());
    03850         }
    03851
    03852         // Iterator types
    03853     private:
    03854         typedef typename E1::const_iterator const_subiterator1_type;
    03855         typedef typename E2::const_iterator2 const_subiterator2_type;
    03856         typedef const value_type *const_pointer;
    03857
    03858     public:
    03859 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03860         typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
    03861         typedef const_iterator iterator;
    03862 #else
    03863         class const_iterator;
    03864         typedef const_iterator iterator;
    03865 #endif
    03866
    03867         // Element lookup
    03868         BOOST_UBLAS_INLINE
    03869         const_iterator find (size_type j) const {
    03870 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03871             const_subiterator2_type it2 (e2_.find2 (0, 0, j));
    03872             return const_iterator (*this, it2.index2 ());
    03873 #else
    03874             return const_iterator (*this, e2_.find2 (0, 0, j));
    03875 #endif
    03876         }
    03877
    03878
    03879 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    03880         class const_iterator:
    03881             public container_const_reference<matrix_vector_binary2>,
    03882             public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
    03883                                                                           typename E2::const_iterator2::iterator_category>::iterator_category>::template
    03884                 iterator_base<const_iterator, value_type>::type {
    03885         public:
    03886             typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
    03887                                                       typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
    03888             typedef typename matrix_vector_binary2::difference_type difference_type;
    03889             typedef typename matrix_vector_binary2::value_type value_type;
    03890             typedef typename matrix_vector_binary2::const_reference reference;
    03891             typedef typename matrix_vector_binary2::const_pointer pointer;
    03892
    03893             // Construction and destruction
    03894 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    03895             BOOST_UBLAS_INLINE
    03896             const_iterator ():
    03897                 container_const_reference<self_type> (), it2_ (), e1_begin_ (), e1_end_ () {}
    03898             BOOST_UBLAS_INLINE
    03899             const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
    03900                 container_const_reference<self_type> (mvb), it2_ (it2), e1_begin_ (mvb.expression1 ().begin ()), e1_end_ (mvb.expression1 ().end ()) {}
    03901 #else
    03902             BOOST_UBLAS_INLINE
    03903             const_iterator ():
    03904                 container_const_reference<self_type> (), it2_ () {}
    03905             BOOST_UBLAS_INLINE
    03906             const_iterator (const self_type &mvb, const const_subiterator2_type &it2):
    03907                 container_const_reference<self_type> (mvb), it2_ (it2) {}
    03908 #endif
    03909
    03910         private:
    03911             // Dense random access specialization
    03912             BOOST_UBLAS_INLINE
    03913             value_type dereference (dense_random_access_iterator_tag) const {
    03914                 const self_type &mvb = (*this) ();
    03915 #ifdef BOOST_UBLAS_USE_INDEXING
    03916                 return mvb (index ());
    03917 #elif BOOST_UBLAS_USE_ITERATING
    03918                 difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
    03919 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    03920                 return functor_type::apply (size, e1_begin_, it2_.begin ());
    03921 #else
    03922                 return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
    03923 #endif
    03924 #else
    03925                 difference_type size = BOOST_UBLAS_SAME (mvb.expression2 ().size1 (), mvb.expression1 ().size ());
    03926                 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
    03927 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    03928                     return functor_type::apply (size, e1_begin_, it2_.begin ());
    03929 #else
    03930                     return functor_type::apply (size, mvb.expression1 ().begin (), it2_.begin ());
    03931 #endif
    03932                 else
    03933                     return mvb (index ());
    03934 #endif
    03935             }
    03936
    03937             // Packed bidirectional specialization
    03938             BOOST_UBLAS_INLINE
    03939             value_type dereference (packed_random_access_iterator_tag) const {
    03940 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    03941                 return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end ());
    03942 #else
    03943                 const self_type &mvb = (*this) ();
    03944 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03945                 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
    03946                                         it2_.begin (), it2_.end ());
    03947 #else
    03948                 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
    03949                                         boost::numeric::ublas::begin (it2_, iterator2_tag ()),
    03950                                         boost::numeric::ublas::end (it2_, iterator2_tag ()));
    03951 #endif
    03952 #endif
    03953             }
    03954
    03955             // Sparse bidirectional specialization
    03956             BOOST_UBLAS_INLINE
    03957             value_type dereference (sparse_bidirectional_iterator_tag) const {
    03958 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    03959                 return functor_type::apply (e1_begin_, e1_end_, it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
    03960 #else
    03961                 const self_type &mvb = (*this) ();
    03962 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    03963                 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
    03964                                         it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
    03965 #else
    03966                 return functor_type::apply (mvb.expression1 ().begin (), mvb.expression1 ().end (),
    03967                                         boost::numeric::ublas::begin (it2_, iterator2_tag ()),
    03968                                         boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
    03969 #endif
    03970 #endif
    03971             }
    03972
    03973         public:
    03974             // Arithmetic
    03975             BOOST_UBLAS_INLINE
    03976             const_iterator &operator ++ () {
    03977                 ++ it2_;
    03978                 return *this;
    03979             }
    03980             BOOST_UBLAS_INLINE
    03981             const_iterator &operator -- () {
    03982                 -- it2_;
    03983                 return *this;
    03984             }
    03985             BOOST_UBLAS_INLINE
    03986             const_iterator &operator += (difference_type n) {
    03987                 it2_ += n;
    03988                 return *this;
    03989             }
    03990             BOOST_UBLAS_INLINE
    03991             const_iterator &operator -= (difference_type n) {
    03992                 it2_ -= n;
    03993                 return *this;
    03994             }
    03995             BOOST_UBLAS_INLINE
    03996             difference_type operator - (const const_iterator &it) const {
    03997                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    03998                 return it2_ - it.it2_;
    03999             }
    04000
    04001             // Dereference
    04002             BOOST_UBLAS_INLINE
    04003             const_reference operator * () const {
    04004                 return dereference (iterator_category ());
    04005             }
    04006             BOOST_UBLAS_INLINE
    04007             const_reference operator [] (difference_type n) const {
    04008                 return *(*this + n);
    04009             }
    04010
    04011             // Index
    04012             BOOST_UBLAS_INLINE
    04013             size_type index () const {
    04014                 return it2_.index2 ();
    04015             }
    04016
    04017             // Assignment
    04018             BOOST_UBLAS_INLINE
    04019             const_iterator &operator = (const const_iterator &it) {
    04020                 container_const_reference<self_type>::assign (&it ());
    04021                 it2_ = it.it2_;
    04022 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04023                 e1_begin_ = it.e1_begin_;
    04024                 e1_end_ = it.e1_end_;
    04025 #endif
    04026                 return *this;
    04027             }
    04028
    04029             // Comparison
    04030             BOOST_UBLAS_INLINE
    04031             bool operator == (const const_iterator &it) const {
    04032                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    04033                 return it2_ == it.it2_;
    04034             }
    04035             BOOST_UBLAS_INLINE
    04036             bool operator < (const const_iterator &it) const {
    04037                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    04038                 return it2_ < it.it2_;
    04039             }
    04040
    04041         private:
    04042             const_subiterator2_type it2_;
    04043 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04044             // Mutable due to assignment
    04045             /* const */ const_subiterator1_type e1_begin_;
    04046             /* const */ const_subiterator1_type e1_end_;
    04047 #endif
    04048         };
    04049 #endif
    04050
    04051         BOOST_UBLAS_INLINE
    04052         const_iterator begin () const {
    04053             return find (0);
    04054         }
    04055         BOOST_UBLAS_INLINE
    04056         const_iterator end () const {
    04057             return find (size ());
    04058         }
    04059
    04060         // Reverse iterator
    04061         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
    04062
    04063         BOOST_UBLAS_INLINE
    04064         const_reverse_iterator rbegin () const {
    04065             return const_reverse_iterator (end ());
    04066         }
    04067         BOOST_UBLAS_INLINE
    04068         const_reverse_iterator rend () const {
    04069             return const_reverse_iterator (begin ());
    04070         }
    04071
    04072     private:
    04073         expression1_closure_type e1_;
    04074         expression2_closure_type e2_;
    04075     };
    04076
    04077     template<class T1, class E1, class T2, class E2>
    04078     struct matrix_vector_binary2_traits {
    04079         typedef unknown_storage_tag storage_category;
    04080         typedef column_major_tag orientation_category;
    04081         typedef typename promote_traits<T1, T2>::promote_type promote_type;
    04082         typedef matrix_vector_binary2<E1, E2, matrix_vector_prod2<E1, E2, promote_type> > expression_type;
    04083 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
    04084         typedef expression_type result_type;
    04085 #else
    04086         typedef typename E2::vector_temporary_type result_type;
    04087 #endif
    04088     };
    04089
    04090     template<class E1, class E2>
    04091     BOOST_UBLAS_INLINE
    04092     typename matrix_vector_binary2_traits<typename E1::value_type, E1,
    04093                                           typename E2::value_type, E2>::result_type
    04094     prod (const vector_expression<E1> &e1,
    04095           const matrix_expression<E2> &e2,
    04096           unknown_storage_tag,
    04097           column_major_tag) {
    04098         typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
    04099                                                       typename E2::value_type, E2>::expression_type expression_type;
    04100         return expression_type (e1 (), e2 ());
    04101     }
    04102
    04103     // Dispatcher
    04104     template<class E1, class E2>
    04105     BOOST_UBLAS_INLINE
    04106     typename matrix_vector_binary2_traits<typename E1::value_type, E1,
    04107                                           typename E2::value_type, E2>::result_type
    04108     prod (const vector_expression<E1> &e1,
    04109           const matrix_expression<E2> &e2) {
    04110         BOOST_STATIC_ASSERT (E1::complexity == 0);
    04111         typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
    04112                                                       typename E2::value_type, E2>::storage_category storage_category;
    04113         typedef typename matrix_vector_binary2_traits<typename E1::value_type, E1,
    04114                                                       typename E2::value_type, E2>::orientation_category orientation_category;
    04115         return prod (e1, e2, storage_category (), orientation_category ());
    04116     }
    04117
    04118     template<class E1, class E2>
    04119     BOOST_UBLAS_INLINE
    04120     typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    04121                                           typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
    04122     prec_prod (const vector_expression<E1> &e1,
    04123                const matrix_expression<E2> &e2,
    04124                unknown_storage_tag,
    04125                column_major_tag) {
    04126         typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    04127                                                       typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
    04128         return expression_type (e1 (), e2 ());
    04129     }
    04130
    04131     // Dispatcher
    04132     template<class E1, class E2>
    04133     BOOST_UBLAS_INLINE
    04134     typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    04135                                           typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
    04136     prec_prod (const vector_expression<E1> &e1,
    04137                const matrix_expression<E2> &e2) {
    04138         BOOST_STATIC_ASSERT (E1::complexity == 0);
    04139         typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    04140                                                       typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
    04141         typedef typename matrix_vector_binary2_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    04142                                                       typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
    04143         return prec_prod (e1, e2, storage_category (), orientation_category ());
    04144     }
    04145
    04146     template<class V, class E1, class E2>
    04147     BOOST_UBLAS_INLINE
    04148     V &
    04149     prod (const vector_expression<E1> &e1,
    04150           const matrix_expression<E2> &e2,
    04151           V &v) {
    04152         return v.assign (prod (e1, e2));
    04153     }
    04154
    04155     template<class V, class E1, class E2>
    04156     BOOST_UBLAS_INLINE
    04157     V &
    04158     prec_prod (const vector_expression<E1> &e1,
    04159                const matrix_expression<E2> &e2,
    04160                V &v) {
    04161         return v.assign (prec_prod (e1, e2));
    04162     }
    04163
    04164     template<class V, class E1, class E2>
    04165     BOOST_UBLAS_INLINE
    04166     V
    04167     prod (const vector_expression<E1> &e1,
    04168           const matrix_expression<E2> &e2) {
    04169         return V (prod (e1, e2));
    04170     }
    04171
    04172     template<class V, class E1, class E2>
    04173     BOOST_UBLAS_INLINE
    04174     V
    04175     prec_prod (const vector_expression<E1> &e1,
    04176                const matrix_expression<E2> &e2) {
    04177         return V (prec_prod (e1, e2));
    04178     }
    04179
    04180     template<class E1, class E2, class F>
    04181     class matrix_matrix_binary:
    04182         public matrix_expression<matrix_matrix_binary<E1, E2, F> > {
    04183
    04184     public:
    04185         typedef E1 expression1_type;
    04186         typedef E2 expression2_type;
    04187     private:
    04188         typedef F functor_type;
    04189     public:
    04190         typedef typename E1::const_closure_type expression1_closure_type;
    04191         typedef typename E2::const_closure_type expression2_closure_type;
    04192     private:
    04193         typedef matrix_matrix_binary<E1, E2, F> self_type;
    04194     public:
    04195 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
    04196         using matrix_expression<self_type>::operator ();
    04197 #endif
    04198         static const unsigned complexity = 1;
    04199         typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
    04200         typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
    04201         typedef typename F::result_type value_type;
    04202         typedef value_type const_reference;
    04203         typedef const_reference reference;
    04204         typedef const self_type const_closure_type;
    04205         typedef const_closure_type closure_type;
    04206         typedef unknown_orientation_tag orientation_category;
    04207         typedef unknown_storage_tag storage_category;
    04208
    04209         // Construction and destruction
    04210         BOOST_UBLAS_INLINE
    04211         matrix_matrix_binary (const expression1_type &e1, const expression2_type &e2):
    04212             e1_ (e1), e2_ (e2) {}
    04213
    04214         // Accessors
    04215         BOOST_UBLAS_INLINE
    04216         size_type size1 () const {
    04217             return e1_.size1 ();
    04218         }
    04219         BOOST_UBLAS_INLINE
    04220         size_type size2 () const {
    04221             return e2_.size2 ();
    04222         }
    04223
    04224     public:
    04225         // Expression accessors
    04226         BOOST_UBLAS_INLINE
    04227         const expression1_closure_type &expression1 () const {
    04228             return e1_;
    04229         }
    04230         BOOST_UBLAS_INLINE
    04231         const expression2_closure_type &expression2 () const {
    04232             return e2_;
    04233         }
    04234
    04235     public:
    04236         // Element access
    04237         BOOST_UBLAS_INLINE
    04238         const_reference operator () (size_type i, size_type j) const {
    04239             return functor_type::apply (e1_, e2_, i, j);
    04240         }
    04241
    04242         // Closure comparison
    04243         BOOST_UBLAS_INLINE
    04244         bool same_closure (const matrix_matrix_binary &mmb) const {
    04245             return (*this).expression1 ().same_closure (mmb.expression1 ()) &&
    04246                    (*this).expression2 ().same_closure (mmb.expression2 ());
    04247         }
    04248
    04249         // Iterator types
    04250     private:
    04251         typedef typename E1::const_iterator1 const_iterator11_type;
    04252         typedef typename E1::const_iterator2 const_iterator12_type;
    04253         typedef typename E2::const_iterator1 const_iterator21_type;
    04254         typedef typename E2::const_iterator2 const_iterator22_type;
    04255         typedef const value_type *const_pointer;
    04256
    04257     public:
    04258 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04259         typedef typename iterator_restrict_traits<typename const_iterator11_type::iterator_category,
    04260                                                   typename const_iterator22_type::iterator_category>::iterator_category iterator_category;
    04261         typedef indexed_const_iterator1<const_closure_type, iterator_category> const_iterator1;
    04262         typedef const_iterator1 iterator1;
    04263         typedef indexed_const_iterator2<const_closure_type, iterator_category> const_iterator2;
    04264         typedef const_iterator2 iterator2;
    04265 #else
    04266         class const_iterator1;
    04267         typedef const_iterator1 iterator1;
    04268         class const_iterator2;
    04269         typedef const_iterator2 iterator2;
    04270 #endif
    04271         typedef reverse_iterator_base1<const_iterator1> const_reverse_iterator1;
    04272         typedef reverse_iterator_base2<const_iterator2> const_reverse_iterator2;
    04273
    04274         // Element lookup
    04275         BOOST_UBLAS_INLINE
    04276         const_iterator1 find1 (int /* rank */, size_type i, size_type j) const {
    04277             // FIXME sparse matrix tests fail!
    04278             // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
    04279             const_iterator11_type it11 (e1_.find1 (0, i, 0));
    04280 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04281             return const_iterator1 (*this, it11.index1 (), j);
    04282 #else
    04283             // FIXME sparse matrix tests fail!
    04284             // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
    04285             const_iterator22_type it22 (e2_.find2 (0, 0, j));
    04286             return const_iterator1 (*this, it11, it22);
    04287 #endif
    04288         }
    04289         BOOST_UBLAS_INLINE
    04290         const_iterator2 find2 (int /* rank */, size_type i, size_type j) const {
    04291             // FIXME sparse matrix tests fail!
    04292             // const_iterator22_type it22 (e2_.find2 (rank, 0, j));
    04293             const_iterator22_type it22 (e2_.find2 (0, 0, j));
    04294 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04295             return const_iterator2 (*this, i, it22.index2 ());
    04296 #else
    04297             // FIXME sparse matrix tests fail!
    04298             // const_iterator11_type it11 (e1_.find1 (rank, i, 0));
    04299             const_iterator11_type it11 (e1_.find1 (0, i, 0));
    04300             return const_iterator2 (*this, it11, it22);
    04301 #endif
    04302         }
    04303
    04304
    04305 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04306         class const_iterator1:
    04307             public container_const_reference<matrix_matrix_binary>,
    04308             public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
    04309                                                                           typename E2::const_iterator2::iterator_category>::iterator_category>::template
    04310                 iterator_base<const_iterator1, value_type>::type {
    04311         public:
    04312             typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
    04313                                                       typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
    04314             typedef typename matrix_matrix_binary::difference_type difference_type;
    04315             typedef typename matrix_matrix_binary::value_type value_type;
    04316             typedef typename matrix_matrix_binary::const_reference reference;
    04317             typedef typename matrix_matrix_binary::const_pointer pointer;
    04318
    04319             typedef const_iterator2 dual_iterator_type;
    04320             typedef const_reverse_iterator2 dual_reverse_iterator_type;
    04321
    04322             // Construction and destruction
    04323 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04324             BOOST_UBLAS_INLINE
    04325             const_iterator1 ():
    04326                 container_const_reference<self_type> (), it1_ (), it2_ (), it2_begin_ (), it2_end_ () {}
    04327             BOOST_UBLAS_INLINE
    04328             const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
    04329                 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it2_begin_ (it2.begin ()), it2_end_ (it2.end ()) {}
    04330 #else
    04331             BOOST_UBLAS_INLINE
    04332             const_iterator1 ():
    04333                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    04334             BOOST_UBLAS_INLINE
    04335             const_iterator1 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
    04336                 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
    04337 #endif
    04338
    04339         private:
    04340             // Random access specialization
    04341             BOOST_UBLAS_INLINE
    04342             value_type dereference (dense_random_access_iterator_tag) const {
    04343                 const self_type &mmb = (*this) ();
    04344 #ifdef BOOST_UBLAS_USE_INDEXING
    04345                 return mmb (index1 (), index2 ());
    04346 #elif BOOST_UBLAS_USE_ITERATING
    04347                 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
    04348 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04349                 return functor_type::apply (size, it1_.begin (), it2_begin_);
    04350 #else
    04351                 return functor_type::apply (size, it1_.begin (), it2_.begin ());
    04352 #endif
    04353 #else
    04354                 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
    04355                 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
    04356 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04357                     return functor_type::apply (size, it1_.begin (), it2_begin_);
    04358 #else
    04359                     return functor_type::apply (size, it1_.begin (), it2_.begin ());
    04360 #endif
    04361                 else
    04362                     return mmb (index1 (), index2 ());
    04363 #endif
    04364             }
    04365
    04366             // Packed bidirectional specialization
    04367             BOOST_UBLAS_INLINE
    04368             value_type dereference (packed_random_access_iterator_tag) const {
    04369 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04370                 return functor_type::apply (it1_.begin (), it1_.end (),
    04371                                         it2_begin_, it2_end_, packed_random_access_iterator_tag ());
    04372 #else
    04373 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    04374                 return functor_type::apply (it1_.begin (), it1_.end (),
    04375                                         it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
    04376 #else
    04377                 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
    04378                                         boost::numeric::ublas::end (it1_, iterator1_tag ()),
    04379                                         boost::numeric::ublas::begin (it2_, iterator2_tag ()),
    04380                                         boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
    04381 #endif
    04382 #endif
    04383             }
    04384
    04385             // Sparse bidirectional specialization
    04386             BOOST_UBLAS_INLINE
    04387             value_type dereference (sparse_bidirectional_iterator_tag) const {
    04388 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04389                 return functor_type::apply (it1_.begin (), it1_.end (),
    04390                                         it2_begin_, it2_end_, sparse_bidirectional_iterator_tag ());
    04391 #else
    04392 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    04393                 return functor_type::apply (it1_.begin (), it1_.end (),
    04394                                         it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
    04395 #else
    04396                 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
    04397                                         boost::numeric::ublas::end (it1_, iterator1_tag ()),
    04398                                         boost::numeric::ublas::begin (it2_, iterator2_tag ()),
    04399                                         boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
    04400 #endif
    04401 #endif
    04402             }
    04403
    04404         public:
    04405             // Arithmetic
    04406             BOOST_UBLAS_INLINE
    04407             const_iterator1 &operator ++ () {
    04408                 ++ it1_;
    04409                 return *this;
    04410             }
    04411             BOOST_UBLAS_INLINE
    04412             const_iterator1 &operator -- () {
    04413                 -- it1_;
    04414                 return *this;
    04415             }
    04416             BOOST_UBLAS_INLINE
    04417             const_iterator1 &operator += (difference_type n) {
    04418                 it1_ += n;
    04419                 return *this;
    04420             }
    04421             BOOST_UBLAS_INLINE
    04422             const_iterator1 &operator -= (difference_type n) {
    04423                 it1_ -= n;
    04424                 return *this;
    04425             }
    04426             BOOST_UBLAS_INLINE
    04427             difference_type operator - (const const_iterator1 &it) const {
    04428                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    04429                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    04430                 return it1_ - it.it1_;
    04431             }
    04432
    04433             // Dereference
    04434             BOOST_UBLAS_INLINE
    04435             const_reference operator * () const {
    04436                 return dereference (iterator_category ());
    04437             }
    04438             BOOST_UBLAS_INLINE
    04439             const_reference operator [] (difference_type n) const {
    04440                 return *(*this + n);
    04441             }
    04442
    04443 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    04444             BOOST_UBLAS_INLINE
    04445 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04446             typename self_type::
    04447 #endif
    04448             const_iterator2 begin () const {
    04449                 return (*this) ().find2 (1, index1 (), 0);
    04450             }
    04451             BOOST_UBLAS_INLINE
    04452 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04453             typename self_type::
    04454 #endif
    04455             const_iterator2 end () const {
    04456                 return (*this) ().find2 (1, index1 (), (*this) ().size2 ());
    04457             }
    04458             BOOST_UBLAS_INLINE
    04459 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04460             typename self_type::
    04461 #endif
    04462             const_reverse_iterator2 rbegin () const {
    04463                 return const_reverse_iterator2 (end ());
    04464             }
    04465             BOOST_UBLAS_INLINE
    04466 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04467             typename self_type::
    04468 #endif
    04469             const_reverse_iterator2 rend () const {
    04470                 return const_reverse_iterator2 (begin ());
    04471             }
    04472 #endif
    04473
    04474             // Indices
    04475             BOOST_UBLAS_INLINE
    04476             size_type index1 () const {
    04477                 return it1_.index1 ();
    04478             }
    04479             BOOST_UBLAS_INLINE
    04480             size_type index2 () const {
    04481                 return it2_.index2 ();
    04482             }
    04483
    04484             // Assignment
    04485             BOOST_UBLAS_INLINE
    04486             const_iterator1 &operator = (const const_iterator1 &it) {
    04487                 container_const_reference<self_type>::assign (&it ());
    04488                 it1_ = it.it1_;
    04489                 it2_ = it.it2_;
    04490 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04491                 it2_begin_ = it.it2_begin_;
    04492                 it2_end_ = it.it2_end_;
    04493 #endif
    04494                 return *this;
    04495             }
    04496
    04497             // Comparison
    04498             BOOST_UBLAS_INLINE
    04499             bool operator == (const const_iterator1 &it) const {
    04500                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    04501                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    04502                 return it1_ == it.it1_;
    04503             }
    04504             BOOST_UBLAS_INLINE
    04505             bool operator < (const const_iterator1 &it) const {
    04506                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    04507                 BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
    04508                 return it1_ < it.it1_;
    04509             }
    04510
    04511         private:
    04512             const_iterator11_type it1_;
    04513             // Mutable due to assignment
    04514             /* const */ const_iterator22_type it2_;
    04515 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04516             /* const */ const_iterator21_type it2_begin_;
    04517             /* const */ const_iterator21_type it2_end_;
    04518 #endif
    04519         };
    04520 #endif
    04521
    04522         BOOST_UBLAS_INLINE
    04523         const_iterator1 begin1 () const {
    04524             return find1 (0, 0, 0);
    04525         }
    04526         BOOST_UBLAS_INLINE
    04527         const_iterator1 end1 () const {
    04528             return find1 (0, size1 (), 0);
    04529         }
    04530
    04531 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
    04532         class const_iterator2:
    04533             public container_const_reference<matrix_matrix_binary>,
    04534             public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
    04535                                                                           typename E2::const_iterator2::iterator_category>::iterator_category>::template
    04536                 iterator_base<const_iterator2, value_type>::type {
    04537         public:
    04538             typedef typename iterator_restrict_traits<typename E1::const_iterator1::iterator_category,
    04539                                                       typename E2::const_iterator2::iterator_category>::iterator_category iterator_category;
    04540             typedef typename matrix_matrix_binary::difference_type difference_type;
    04541             typedef typename matrix_matrix_binary::value_type value_type;
    04542             typedef typename matrix_matrix_binary::const_reference reference;
    04543             typedef typename matrix_matrix_binary::const_pointer pointer;
    04544
    04545             typedef const_iterator1 dual_iterator_type;
    04546             typedef const_reverse_iterator1 dual_reverse_iterator_type;
    04547
    04548             // Construction and destruction
    04549 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04550             BOOST_UBLAS_INLINE
    04551             const_iterator2 ():
    04552                 container_const_reference<self_type> (), it1_ (), it2_ (), it1_begin_ (), it1_end_ () {}
    04553             BOOST_UBLAS_INLINE
    04554             const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
    04555                 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2), it1_begin_ (it1.begin ()), it1_end_ (it1.end ()) {}
    04556 #else
    04557             BOOST_UBLAS_INLINE
    04558             const_iterator2 ():
    04559                 container_const_reference<self_type> (), it1_ (), it2_ () {}
    04560             BOOST_UBLAS_INLINE
    04561             const_iterator2 (const self_type &mmb, const const_iterator11_type &it1, const const_iterator22_type &it2):
    04562                 container_const_reference<self_type> (mmb), it1_ (it1), it2_ (it2) {}
    04563 #endif
    04564
    04565         private:
    04566             // Random access specialization
    04567             BOOST_UBLAS_INLINE
    04568             value_type dereference (dense_random_access_iterator_tag) const {
    04569                 const self_type &mmb = (*this) ();
    04570 #ifdef BOOST_UBLAS_USE_INDEXING
    04571                 return mmb (index1 (), index2 ());
    04572 #elif BOOST_UBLAS_USE_ITERATING
    04573                 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
    04574 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04575                 return functor_type::apply (size, it1_begin_, it2_.begin ());
    04576 #else
    04577                 return functor_type::apply (size, it1_.begin (), it2_.begin ());
    04578 #endif
    04579 #else
    04580                 difference_type size = BOOST_UBLAS_SAME (mmb.expression1 ().size2 (), mmb.expression2 ().size1 ());
    04581                 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
    04582 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04583                     return functor_type::apply (size, it1_begin_, it2_.begin ());
    04584 #else
    04585                     return functor_type::apply (size, it1_.begin (), it2_.begin ());
    04586 #endif
    04587                 else
    04588                     return mmb (index1 (), index2 ());
    04589 #endif
    04590             }
    04591
    04592             // Packed bidirectional specialization
    04593             BOOST_UBLAS_INLINE
    04594             value_type dereference (packed_random_access_iterator_tag) const {
    04595 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04596                 return functor_type::apply (it1_begin_, it1_end_,
    04597                                         it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
    04598 #else
    04599 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    04600                 return functor_type::apply (it1_.begin (), it1_.end (),
    04601                                         it2_.begin (), it2_.end (), packed_random_access_iterator_tag ());
    04602 #else
    04603                 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
    04604                                         boost::numeric::ublas::end (it1_, iterator1_tag ()),
    04605                                         boost::numeric::ublas::begin (it2_, iterator2_tag ()),
    04606                                         boost::numeric::ublas::end (it2_, iterator2_tag ()), packed_random_access_iterator_tag ());
    04607 #endif
    04608 #endif
    04609             }
    04610
    04611             // Sparse bidirectional specialization
    04612             BOOST_UBLAS_INLINE
    04613             value_type dereference (sparse_bidirectional_iterator_tag) const {
    04614 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04615                 return functor_type::apply (it1_begin_, it1_end_,
    04616                                         it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
    04617 #else
    04618 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    04619                 return functor_type::apply (it1_.begin (), it1_.end (),
    04620                                         it2_.begin (), it2_.end (), sparse_bidirectional_iterator_tag ());
    04621 #else
    04622                 return functor_type::apply (boost::numeric::ublas::begin (it1_, iterator1_tag ()),
    04623                                         boost::numeric::ublas::end (it1_, iterator1_tag ()),
    04624                                         boost::numeric::ublas::begin (it2_, iterator2_tag ()),
    04625                                         boost::numeric::ublas::end (it2_, iterator2_tag ()), sparse_bidirectional_iterator_tag ());
    04626 #endif
    04627 #endif
    04628             }
    04629
    04630         public:
    04631             // Arithmetic
    04632             BOOST_UBLAS_INLINE
    04633             const_iterator2 &operator ++ () {
    04634                 ++ it2_;
    04635                 return *this;
    04636             }
    04637             BOOST_UBLAS_INLINE
    04638             const_iterator2 &operator -- () {
    04639                 -- it2_;
    04640                 return *this;
    04641             }
    04642             BOOST_UBLAS_INLINE
    04643             const_iterator2 &operator += (difference_type n) {
    04644                 it2_ += n;
    04645                 return *this;
    04646             }
    04647             BOOST_UBLAS_INLINE
    04648             const_iterator2 &operator -= (difference_type n) {
    04649                 it2_ -= n;
    04650                 return *this;
    04651             }
    04652             BOOST_UBLAS_INLINE
    04653             difference_type operator - (const const_iterator2 &it) const {
    04654                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    04655                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    04656                 return it2_ - it.it2_;
    04657             }
    04658
    04659             // Dereference
    04660             BOOST_UBLAS_INLINE
    04661             const_reference operator * () const {
    04662                 return dereference (iterator_category ());
    04663             }
    04664             BOOST_UBLAS_INLINE
    04665             const_reference operator [] (difference_type n) const {
    04666                 return *(*this + n);
    04667             }
    04668
    04669 #ifndef BOOST_UBLAS_NO_NESTED_CLASS_RELATION
    04670             BOOST_UBLAS_INLINE
    04671 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04672             typename self_type::
    04673 #endif
    04674             const_iterator1 begin () const {
    04675                 return (*this) ().find1 (1, 0, index2 ());
    04676             }
    04677             BOOST_UBLAS_INLINE
    04678 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04679             typename self_type::
    04680 #endif
    04681             const_iterator1 end () const {
    04682                 return (*this) ().find1 (1, (*this) ().size1 (), index2 ());
    04683             }
    04684             BOOST_UBLAS_INLINE
    04685 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04686             typename self_type::
    04687 #endif
    04688             const_reverse_iterator1 rbegin () const {
    04689                 return const_reverse_iterator1 (end ());
    04690             }
    04691             BOOST_UBLAS_INLINE
    04692 #ifdef BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION
    04693             typename self_type::
    04694 #endif
    04695             const_reverse_iterator1 rend () const {
    04696                 return const_reverse_iterator1 (begin ());
    04697             }
    04698 #endif
    04699
    04700             // Indices
    04701             BOOST_UBLAS_INLINE
    04702             size_type index1 () const {
    04703                 return it1_.index1 ();
    04704             }
    04705             BOOST_UBLAS_INLINE
    04706             size_type index2 () const {
    04707                 return it2_.index2 ();
    04708             }
    04709
    04710             // Assignment
    04711             BOOST_UBLAS_INLINE
    04712             const_iterator2 &operator = (const const_iterator2 &it) {
    04713                 container_const_reference<self_type>::assign (&it ());
    04714                 it1_ = it.it1_;
    04715                 it2_ = it.it2_;
    04716 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04717                 it1_begin_ = it.it1_begin_;
    04718                 it1_end_ = it.it1_end_;
    04719 #endif
    04720                 return *this;
    04721             }
    04722
    04723             // Comparison
    04724             BOOST_UBLAS_INLINE
    04725             bool operator == (const const_iterator2 &it) const {
    04726                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    04727                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    04728                 return it2_ == it.it2_;
    04729             }
    04730             BOOST_UBLAS_INLINE
    04731             bool operator < (const const_iterator2 &it) const {
    04732                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
    04733                 BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
    04734                 return it2_ < it.it2_;
    04735             }
    04736
    04737         private:
    04738             // Mutable due to assignment
    04739             /* const */ const_iterator11_type it1_;
    04740             const_iterator22_type it2_;
    04741 #ifdef BOOST_UBLAS_USE_INVARIANT_HOISTING
    04742             /* const */ const_iterator12_type it1_begin_;
    04743             /* const */ const_iterator12_type it1_end_;
    04744 #endif
    04745         };
    04746 #endif
    04747
    04748         BOOST_UBLAS_INLINE
    04749         const_iterator2 begin2 () const {
    04750             return find2 (0, 0, 0);
    04751         }
    04752         BOOST_UBLAS_INLINE
    04753         const_iterator2 end2 () const {
    04754             return find2 (0, 0, size2 ());
    04755         }
    04756
    04757         // Reverse iterators
    04758
    04759         BOOST_UBLAS_INLINE
    04760         const_reverse_iterator1 rbegin1 () const {
    04761             return const_reverse_iterator1 (end1 ());
    04762         }
    04763         BOOST_UBLAS_INLINE
    04764         const_reverse_iterator1 rend1 () const {
    04765             return const_reverse_iterator1 (begin1 ());
    04766         }
    04767
    04768         BOOST_UBLAS_INLINE
    04769         const_reverse_iterator2 rbegin2 () const {
    04770             return const_reverse_iterator2 (end2 ());
    04771         }
    04772         BOOST_UBLAS_INLINE
    04773         const_reverse_iterator2 rend2 () const {
    04774             return const_reverse_iterator2 (begin2 ());
    04775         }
    04776
    04777     private:
    04778         expression1_closure_type e1_;
    04779         expression2_closure_type e2_;
    04780     };
    04781
    04782     template<class T1, class E1, class T2, class E2>
    04783     struct matrix_matrix_binary_traits {
    04784         typedef unknown_storage_tag storage_category;
    04785         typedef unknown_orientation_tag orientation_category;
    04786         typedef typename promote_traits<T1, T2>::promote_type promote_type;
    04787         typedef matrix_matrix_binary<E1, E2, matrix_matrix_prod<E1, E2, promote_type> > expression_type;
    04788 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
    04789         typedef expression_type result_type;
    04790 #else
    04791         typedef typename E1::matrix_temporary_type result_type;
    04792 #endif
    04793     };
    04794
    04795     template<class E1, class E2>
    04796     BOOST_UBLAS_INLINE
    04797     typename matrix_matrix_binary_traits<typename E1::value_type, E1,
    04798                                          typename E2::value_type, E2>::result_type
    04799     prod (const matrix_expression<E1> &e1,
    04800           const matrix_expression<E2> &e2,
    04801           unknown_storage_tag,
    04802           unknown_orientation_tag) {
    04803         typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
    04804                                                      typename E2::value_type, E2>::expression_type expression_type;
    04805         return expression_type (e1 (), e2 ());
    04806     }
    04807
    04808     // Dispatcher
    04809     template<class E1, class E2>
    04810     BOOST_UBLAS_INLINE
    04811     typename matrix_matrix_binary_traits<typename E1::value_type, E1,
    04812                                          typename E2::value_type, E2>::result_type
    04813     prod (const matrix_expression<E1> &e1,
    04814           const matrix_expression<E2> &e2) {
    04815         BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
    04816         typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
    04817                                                      typename E2::value_type, E2>::storage_category storage_category;
    04818         typedef typename matrix_matrix_binary_traits<typename E1::value_type, E1,
    04819                                                      typename E2::value_type, E2>::orientation_category orientation_category;
    04820         return prod (e1, e2, storage_category (), orientation_category ());
    04821     }
    04822
    04823     template<class E1, class E2>
    04824     BOOST_UBLAS_INLINE
    04825     typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    04826                                          typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
    04827     prec_prod (const matrix_expression<E1> &e1,
    04828                const matrix_expression<E2> &e2,
    04829                unknown_storage_tag,
    04830                unknown_orientation_tag) {
    04831         typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    04832                                                      typename type_traits<typename E2::value_type>::precision_type, E2>::expression_type expression_type;
    04833         return expression_type (e1 (), e2 ());
    04834     }
    04835
    04836     // Dispatcher
    04837     template<class E1, class E2>
    04838     BOOST_UBLAS_INLINE
    04839     typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    04840                                          typename type_traits<typename E2::value_type>::precision_type, E2>::result_type
    04841     prec_prod (const matrix_expression<E1> &e1,
    04842                const matrix_expression<E2> &e2) {
    04843         BOOST_STATIC_ASSERT (E1::complexity == 0 && E2::complexity == 0);
    04844         typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    04845                                                      typename type_traits<typename E2::value_type>::precision_type, E2>::storage_category storage_category;
    04846         typedef typename matrix_matrix_binary_traits<typename type_traits<typename E1::value_type>::precision_type, E1,
    04847                                                      typename type_traits<typename E2::value_type>::precision_type, E2>::orientation_category orientation_category;
    04848         return prec_prod (e1, e2, storage_category (), orientation_category ());
    04849     }
    04850
    04851     template<class M, class E1, class E2>
    04852     BOOST_UBLAS_INLINE
    04853     M &
    04854     prod (const matrix_expression<E1> &e1,
    04855           const matrix_expression<E2> &e2,
    04856           M &m) {
    04857         return m.assign (prod (e1, e2));
    04858     }
    04859
    04860     template<class M, class E1, class E2>
    04861     BOOST_UBLAS_INLINE
    04862     M &
    04863     prec_prod (const matrix_expression<E1> &e1,
    04864                const matrix_expression<E2> &e2,
    04865                M &m) {
    04866         return m.assign (prec_prod (e1, e2));
    04867     }
    04868
    04869     template<class M, class E1, class E2>
    04870     BOOST_UBLAS_INLINE
    04871     M
    04872     prod (const matrix_expression<E1> &e1,
    04873           const matrix_expression<E2> &e2) {
    04874         return M (prod (e1, e2));
    04875     }
    04876
    04877     template<class M, class E1, class E2>
    04878     BOOST_UBLAS_INLINE
    04879     M
    04880     prec_prod (const matrix_expression<E1> &e1,
    04881                const matrix_expression<E2> &e2) {
    04882         return M (prec_prod (e1, e2));
    04883     }
    04884
    04885     template<class E, class F>
    04886     class matrix_scalar_unary:
    04887         public scalar_expression<matrix_scalar_unary<E, F> > {
    04888     public:
    04889         typedef E expression_type;
    04890         typedef F functor_type;
    04891         typedef typename F::result_type value_type;
    04892         typedef typename E::const_closure_type expression_closure_type;
    04893
    04894         // Construction and destruction
    04895         BOOST_UBLAS_INLINE
    04896         explicit matrix_scalar_unary (const expression_type &e):
    04897             e_ (e) {}
    04898
    04899     private:
    04900         // Expression accessors
    04901         BOOST_UBLAS_INLINE
    04902         const expression_closure_type &expression () const {
    04903             return e_;
    04904         }
    04905
    04906     public:
    04907         BOOST_UBLAS_INLINE
    04908         operator value_type () const {
    04909             return functor_type::apply (e_);
    04910         }
    04911
    04912     private:
    04913         expression_closure_type e_;
    04914     };
    04915
    04916     template<class E, class F>
    04917     struct matrix_scalar_unary_traits {
    04918         typedef matrix_scalar_unary<E, F> expression_type;
    04919 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
    04920          typedef expression_type result_type;
    04921 #else
    04922          typedef typename F::result_type result_type;
    04923 #endif
    04924     };
    04925
    04926     template<class E>
    04927     BOOST_UBLAS_INLINE
    04928     typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::result_type
    04929     norm_1 (const matrix_expression<E> &e) {
    04930         typedef typename matrix_scalar_unary_traits<E, matrix_norm_1<E> >::expression_type expression_type;
    04931         return expression_type (e ());
    04932     }
    04933
    04934     template<class E>
    04935     BOOST_UBLAS_INLINE
    04936     typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::result_type
    04937     norm_frobenius (const matrix_expression<E> &e) {
    04938         typedef typename matrix_scalar_unary_traits<E, matrix_norm_frobenius<E> >::expression_type expression_type;
    04939         return expression_type (e ());
    04940     }
    04941
    04942     template<class E>
    04943     BOOST_UBLAS_INLINE
    04944     typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::result_type
    04945     norm_inf (const matrix_expression<E> &e) {
    04946         typedef typename matrix_scalar_unary_traits<E, matrix_norm_inf<E> >::expression_type expression_type;
    04947         return expression_type (e ());
    04948     }
    04949
    04950 }}}
    04951
    04952 #endif