Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:17

0001 //
0002 //  Copyright (c) 2000-2002
0003 //  Joerg Walter, Mathias Koch
0004 //
0005 //  Distributed under the Boost Software License, Version 1.0. (See
0006 //  accompanying file LICENSE_1_0.txt or copy at
0007 //  http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 //  The authors gratefully acknowledge the support of
0010 //  GeNeSys mbH & Co. KG in producing this work.
0011 //
0012 
0013 #ifndef _BOOST_UBLAS_VECTOR_EXPRESSION_
0014 #define _BOOST_UBLAS_VECTOR_EXPRESSION_
0015 
0016 #include <boost/numeric/ublas/expression_types.hpp>
0017 
0018 
0019 // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
0020 // Iterators based on ideas of Jeremy Siek
0021 //
0022 // Classes that model the Vector Expression concept
0023 
0024 namespace boost { namespace numeric { namespace ublas {
0025 
0026     template<class E>
0027     class vector_reference:
0028         public vector_expression<vector_reference<E> > {
0029 
0030         typedef vector_reference<E> self_type;
0031     public:
0032 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
0033         using vector_expression<vector_reference<E> >::operator ();
0034 #endif
0035         typedef typename E::size_type size_type;
0036         typedef typename E::difference_type difference_type;
0037         typedef typename E::value_type value_type;
0038         typedef typename E::const_reference const_reference;
0039         typedef typename boost::mpl::if_<boost::is_const<E>,
0040                                           typename E::const_reference,
0041                                           typename E::reference>::type reference;
0042         typedef E referred_type;
0043         typedef const self_type const_closure_type;
0044         typedef self_type closure_type;
0045         typedef typename E::storage_category storage_category;
0046 
0047         // Construction and destruction
0048         BOOST_UBLAS_INLINE
0049         explicit vector_reference (referred_type &e):
0050             e_ (e) {}
0051 
0052         // Accessors
0053         BOOST_UBLAS_INLINE
0054         size_type size () const {
0055             return expression ().size ();
0056         }
0057 
0058     public:
0059         // Expression accessors - const correct
0060         BOOST_UBLAS_INLINE
0061         const referred_type &expression () const {
0062             return e_;
0063         }
0064         BOOST_UBLAS_INLINE
0065         referred_type &expression () {
0066             return e_;
0067         }
0068 
0069     public:
0070         // Element access
0071 #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
0072         BOOST_UBLAS_INLINE
0073         const_reference operator () (size_type i) const {
0074             return expression () (i);
0075         }
0076         BOOST_UBLAS_INLINE
0077         reference operator () (size_type i) {
0078             return expression () (i);
0079         }
0080 
0081         BOOST_UBLAS_INLINE
0082         const_reference operator [] (size_type i) const {
0083             return expression () [i];
0084         }
0085         BOOST_UBLAS_INLINE
0086         reference operator [] (size_type i) {
0087             return expression () [i];
0088         }
0089 #else
0090         BOOST_UBLAS_INLINE
0091         reference operator () (size_type i) const {
0092             return expression () (i);
0093         }
0094 
0095         BOOST_UBLAS_INLINE
0096         reference operator [] (size_type i) const {
0097             return expression () [i];
0098         }
0099 #endif
0100 
0101         // Assignment
0102         BOOST_UBLAS_INLINE
0103         vector_reference &operator = (const vector_reference &v) {
0104             expression ().operator = (v);
0105             return *this;
0106         }
0107         template<class AE>
0108         BOOST_UBLAS_INLINE
0109         vector_reference &operator = (const vector_expression<AE> &ae) {
0110             expression ().operator = (ae);
0111             return *this;
0112         }
0113         template<class AE>
0114         BOOST_UBLAS_INLINE
0115         vector_reference &assign (const vector_expression<AE> &ae) {
0116             expression ().assign (ae);
0117             return *this;
0118         }
0119         template<class AE>
0120         BOOST_UBLAS_INLINE
0121         vector_reference &operator += (const vector_expression<AE> &ae) {
0122             expression ().operator += (ae);
0123             return *this;
0124         }
0125         template<class AE>
0126         BOOST_UBLAS_INLINE
0127         vector_reference &plus_assign (const vector_expression<AE> &ae) {
0128             expression ().plus_assign (ae);
0129             return *this;
0130         }
0131         template<class AE>
0132         BOOST_UBLAS_INLINE
0133         vector_reference &operator -= (const vector_expression<AE> &ae) {
0134             expression ().operator -= (ae);
0135             return *this;
0136         }
0137         template<class AE>
0138         BOOST_UBLAS_INLINE
0139         vector_reference &minus_assign (const vector_expression<AE> &ae) {
0140             expression ().minus_assign (ae);
0141             return *this;
0142         }
0143         template<class AT>
0144         BOOST_UBLAS_INLINE
0145         vector_reference &operator *= (const AT &at) {
0146             expression ().operator *= (at);
0147             return *this;
0148         }
0149         template<class AT>
0150         BOOST_UBLAS_INLINE
0151         vector_reference &operator /= (const AT &at) {
0152             expression ().operator /= (at);
0153             return *this;
0154         }
0155 
0156         // Swapping
0157         BOOST_UBLAS_INLINE
0158         void swap (vector_reference &v) {
0159             expression ().swap (v.expression ());
0160         }
0161 
0162         // Closure comparison
0163         BOOST_UBLAS_INLINE
0164         bool same_closure (const vector_reference &vr) const {
0165             return &(*this).e_ == &vr.e_;
0166         }
0167 
0168         // Iterator types
0169         typedef typename E::const_iterator const_iterator;
0170         typedef typename boost::mpl::if_<boost::is_const<E>,
0171                                           typename E::const_iterator,
0172                                           typename E::iterator>::type iterator;
0173 
0174         // Element lookup
0175         BOOST_UBLAS_INLINE
0176         const_iterator find (size_type i) const {
0177             return expression ().find (i);
0178         }
0179         BOOST_UBLAS_INLINE
0180         iterator find (size_type i) {
0181             return expression ().find (i);
0182         }
0183 
0184         // Iterator is the iterator of the referenced expression.
0185 
0186         BOOST_UBLAS_INLINE
0187         const_iterator begin () const {
0188             return expression ().begin ();
0189         }
0190         BOOST_UBLAS_INLINE
0191         const_iterator cbegin () const {
0192             return begin ();
0193         }
0194         BOOST_UBLAS_INLINE
0195         const_iterator end () const {
0196             return expression ().end ();
0197         }
0198         BOOST_UBLAS_INLINE
0199         const_iterator cend () const {
0200             return end ();
0201         }
0202 
0203         BOOST_UBLAS_INLINE
0204         iterator begin () {
0205             return expression ().begin ();
0206         }
0207         BOOST_UBLAS_INLINE
0208         iterator end () {
0209             return expression ().end ();
0210         }
0211 
0212         // Reverse iterator
0213         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
0214         typedef reverse_iterator_base<iterator> reverse_iterator;
0215 
0216         BOOST_UBLAS_INLINE
0217         const_reverse_iterator rbegin () const {
0218             return const_reverse_iterator (end ());
0219         }
0220         BOOST_UBLAS_INLINE
0221         const_reverse_iterator crbegin () const {
0222             return rbegin ();
0223         }
0224         BOOST_UBLAS_INLINE
0225         const_reverse_iterator rend () const {
0226             return const_reverse_iterator (begin ());
0227         }
0228         BOOST_UBLAS_INLINE
0229         const_reverse_iterator crend () const {
0230             return rend ();
0231         }
0232 
0233         BOOST_UBLAS_INLINE
0234         reverse_iterator rbegin () {
0235             return reverse_iterator (end ());
0236         }
0237         BOOST_UBLAS_INLINE
0238         reverse_iterator rend () {
0239             return reverse_iterator (begin ());
0240         }
0241 
0242     private:
0243         referred_type &e_;
0244     };
0245 
0246 
0247     template<class E, class F>
0248     class vector_unary:
0249         public vector_expression<vector_unary<E, F> > {
0250 
0251         typedef F functor_type;
0252         typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
0253                                           E,
0254                                           const E>::type expression_type;
0255         typedef typename boost::mpl::if_<boost::is_const<expression_type>,
0256                                           typename E::const_closure_type,
0257                                           typename E::closure_type>::type expression_closure_type;
0258         typedef vector_unary<E, F> self_type;
0259     public:
0260 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
0261         using vector_expression<vector_unary<E, F> >::operator ();
0262 #endif
0263         typedef typename E::size_type size_type;
0264         typedef typename E::difference_type difference_type;
0265         typedef typename F::result_type value_type;
0266         typedef value_type const_reference;
0267         typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
0268                                           typename E::reference,
0269                                           value_type>::type reference;
0270         typedef const self_type const_closure_type;
0271         typedef self_type closure_type;
0272         typedef unknown_storage_tag storage_category;
0273 
0274         // Construction and destruction
0275         BOOST_UBLAS_INLINE
0276         // May be used as mutable expression.
0277         explicit vector_unary (expression_type &e):
0278             e_ (e) {}
0279 
0280         // Accessors
0281         BOOST_UBLAS_INLINE
0282         size_type size () const {
0283             return e_.size ();
0284         }
0285 
0286     public:
0287         // Expression accessors
0288         BOOST_UBLAS_INLINE
0289         const expression_closure_type &expression () const {
0290             return e_;
0291         }
0292 
0293     public:
0294         // Element access
0295         BOOST_UBLAS_INLINE
0296         const_reference operator () (size_type i) const {
0297             return functor_type::apply (e_ (i));
0298         }
0299         BOOST_UBLAS_INLINE
0300         reference operator () (size_type i) {
0301             BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
0302             return e_ (i);
0303         }
0304 
0305         BOOST_UBLAS_INLINE
0306         const_reference operator [] (size_type i) const {
0307             return functor_type::apply (e_ [i]);
0308         }
0309         BOOST_UBLAS_INLINE
0310         reference operator [] (size_type i) {
0311             BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
0312             return e_ [i];
0313         }
0314 
0315         // Closure comparison
0316         BOOST_UBLAS_INLINE
0317         bool same_closure (const vector_unary &vu) const {
0318             return (*this).expression ().same_closure (vu.expression ());
0319         }
0320 
0321         // Iterator types
0322     private:
0323         typedef typename E::const_iterator const_subiterator_type;
0324         typedef const value_type *const_pointer;
0325 
0326     public:
0327 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
0328         typedef indexed_const_iterator<const_closure_type, typename const_subiterator_type::iterator_category> const_iterator;
0329         typedef const_iterator iterator;
0330 #else
0331         class const_iterator;
0332         typedef const_iterator iterator;
0333 #endif
0334 
0335         // Element lookup
0336         BOOST_UBLAS_INLINE
0337         const_iterator find (size_type i) const {
0338 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
0339             const_subiterator_type it (e_.find (i));
0340             return const_iterator (*this, it.index ());
0341 #else
0342             return const_iterator (*this, e_.find (i));
0343 #endif
0344         }
0345 
0346         // Iterator enhances the iterator of the referenced expression
0347         // with the unary functor.
0348 
0349 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
0350         class const_iterator:
0351             public container_const_reference<vector_unary>,
0352             public iterator_base_traits<typename E::const_iterator::iterator_category>::template
0353                         iterator_base<const_iterator, value_type>::type {
0354         public:
0355             typedef typename E::const_iterator::iterator_category iterator_category;
0356             typedef typename vector_unary::difference_type difference_type;
0357             typedef typename vector_unary::value_type value_type;
0358             typedef typename vector_unary::const_reference reference;
0359             typedef typename vector_unary::const_pointer pointer;
0360 
0361             // Construction and destruction
0362             BOOST_UBLAS_INLINE
0363             const_iterator ():
0364                 container_const_reference<self_type> (), it_ () {}
0365             BOOST_UBLAS_INLINE
0366             const_iterator (const self_type &vu, const const_subiterator_type &it):
0367                 container_const_reference<self_type> (vu), it_ (it) {}
0368 
0369             // Arithmetic
0370             BOOST_UBLAS_INLINE
0371             const_iterator &operator ++ () {
0372                 ++ it_;
0373                 return *this;
0374             }
0375             BOOST_UBLAS_INLINE
0376             const_iterator &operator -- () {
0377                 -- it_;
0378                 return *this;
0379             }
0380             BOOST_UBLAS_INLINE
0381             const_iterator &operator += (difference_type n) {
0382                 it_ += n;
0383                 return *this;
0384             }
0385             BOOST_UBLAS_INLINE
0386             const_iterator &operator -= (difference_type n) {
0387                 it_ -= n;
0388                 return *this;
0389             }
0390             BOOST_UBLAS_INLINE
0391             difference_type operator - (const const_iterator &it) const {
0392                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0393                 return it_ - it.it_;
0394             }
0395 
0396             // Dereference
0397             BOOST_UBLAS_INLINE
0398             const_reference operator * () const {
0399                 return functor_type::apply (*it_);
0400             }
0401             BOOST_UBLAS_INLINE
0402             const_reference operator [] (difference_type n) const {
0403                 return *(*this + n);
0404             }
0405 
0406             // Index
0407             BOOST_UBLAS_INLINE
0408             size_type index () const {
0409                 return it_.index ();
0410             }
0411 
0412             // Assignment
0413             BOOST_UBLAS_INLINE
0414             const_iterator &operator = (const const_iterator &it) {
0415                 container_const_reference<self_type>::assign (&it ());
0416                 it_ = it.it_;
0417                 return *this;
0418             }
0419 
0420             // Comparison
0421             BOOST_UBLAS_INLINE
0422             bool operator == (const const_iterator &it) const {
0423                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0424                 return it_ == it.it_;
0425             }
0426             BOOST_UBLAS_INLINE
0427             bool operator < (const const_iterator &it) const {
0428                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0429                 return it_ < it.it_;
0430             }
0431 
0432         private:
0433             const_subiterator_type it_;
0434         };
0435 #endif
0436 
0437         BOOST_UBLAS_INLINE
0438         const_iterator begin () const {
0439             return find (0); 
0440         }
0441         BOOST_UBLAS_INLINE
0442         const_iterator cbegin () const {
0443             return begin ();
0444         }
0445         BOOST_UBLAS_INLINE
0446         const_iterator end () const {
0447             return find (size ());
0448         }
0449         BOOST_UBLAS_INLINE
0450         const_iterator cend () const {
0451             return end ();
0452         }
0453 
0454         // Reverse iterator
0455         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
0456 
0457         BOOST_UBLAS_INLINE
0458         const_reverse_iterator rbegin () const {
0459             return const_reverse_iterator (end ());
0460         }
0461         BOOST_UBLAS_INLINE
0462         const_reverse_iterator crbegin () const {
0463             return rbegin ();
0464         }
0465         BOOST_UBLAS_INLINE
0466         const_reverse_iterator rend () const {
0467             return const_reverse_iterator (begin ());
0468         }
0469         BOOST_UBLAS_INLINE
0470         const_reverse_iterator crend () const {
0471             return rend ();
0472         }
0473 
0474     private:
0475         expression_closure_type e_;
0476     };
0477 
0478     template<class E, class F>
0479     struct vector_unary_traits {
0480         typedef vector_unary<E, F> expression_type;
0481 //FIXME
0482 // #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
0483         typedef expression_type result_type;
0484 // #else
0485 //         typedef typename E::vector_temporary_type result_type;
0486 // #endif
0487     };
0488 
0489     // (- v) [i] = - v [i]
0490     template<class E> 
0491     BOOST_UBLAS_INLINE
0492     typename vector_unary_traits<E, scalar_negate<typename E::value_type> >::result_type
0493     operator - (const vector_expression<E> &e) {
0494         typedef typename vector_unary_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
0495         return expression_type (e ());
0496     }
0497 
0498     // (conj v) [i] = conj (v [i])
0499     template<class E> 
0500     BOOST_UBLAS_INLINE
0501     typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::result_type
0502     conj (const vector_expression<E> &e) {
0503         typedef typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
0504         return expression_type (e ());
0505     }
0506 
0507     // (real v) [i] = real (v [i])
0508     template<class E>
0509     BOOST_UBLAS_INLINE
0510     typename vector_unary_traits<E, scalar_real<typename E::value_type> >::result_type
0511     real (const vector_expression<E> &e) {
0512         typedef typename vector_unary_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
0513         return expression_type (e ());
0514     }
0515 
0516     // (imag v) [i] = imag (v [i])
0517     template<class E>
0518     BOOST_UBLAS_INLINE
0519     typename vector_unary_traits<E, scalar_imag<typename E::value_type> >::result_type
0520     imag (const vector_expression<E> &e) {
0521         typedef typename vector_unary_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
0522         return expression_type (e ());
0523     }
0524 
0525     // (trans v) [i] = v [i]
0526     template<class E>
0527     BOOST_UBLAS_INLINE
0528     typename vector_unary_traits<const E, scalar_identity<typename E::value_type> >::result_type
0529     trans (const vector_expression<E> &e) {
0530         typedef typename vector_unary_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
0531         return expression_type (e ());
0532     }
0533     template<class E>
0534     BOOST_UBLAS_INLINE
0535     typename vector_unary_traits<E, scalar_identity<typename E::value_type> >::result_type
0536     trans (vector_expression<E> &e) {
0537         typedef typename vector_unary_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
0538         return expression_type (e ());
0539     }
0540 
0541     // (herm v) [i] = conj (v [i])
0542     template<class E>
0543     BOOST_UBLAS_INLINE
0544     typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::result_type
0545     herm (const vector_expression<E> &e) {
0546         typedef typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
0547         return expression_type (e ());
0548     }
0549 
0550     template<class E1, class E2, class F>
0551     class vector_binary:
0552         public vector_expression<vector_binary<E1, E2, F> > {
0553 
0554         typedef E1 expression1_type;
0555         typedef E2 expression2_type;
0556         typedef F functor_type;
0557         typedef typename E1::const_closure_type expression1_closure_type;
0558         typedef typename E2::const_closure_type expression2_closure_type;
0559         typedef vector_binary<E1, E2, F> self_type;
0560     public:
0561 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
0562         using vector_expression<vector_binary<E1, E2, F> >::operator ();
0563 #endif
0564         typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
0565         typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
0566         typedef typename F::result_type value_type;
0567         typedef value_type const_reference;
0568         typedef const_reference reference;
0569         typedef const self_type const_closure_type;
0570         typedef const_closure_type closure_type;
0571         typedef unknown_storage_tag storage_category;
0572 
0573         // Construction and destruction
0574         BOOST_UBLAS_INLINE
0575         vector_binary (const expression1_type &e1, const expression2_type &e2):
0576             e1_ (e1), e2_ (e2) {}
0577 
0578         // Accessors
0579         BOOST_UBLAS_INLINE
0580         size_type size () const { 
0581             return BOOST_UBLAS_SAME (e1_.size (), e2_.size ()); 
0582         }
0583 
0584     private:
0585         // Accessors
0586         BOOST_UBLAS_INLINE
0587         const expression1_closure_type &expression1 () const {
0588             return e1_;
0589         }
0590         BOOST_UBLAS_INLINE
0591         const expression2_closure_type &expression2 () const {
0592             return e2_;
0593         }
0594 
0595     public:
0596         // Element access
0597         BOOST_UBLAS_INLINE
0598         const_reference operator () (size_type i) const {
0599             return functor_type::apply (e1_ (i), e2_ (i));
0600         }
0601 
0602         BOOST_UBLAS_INLINE
0603         const_reference operator [] (size_type i) const {
0604             return functor_type::apply (e1_ [i], e2_ [i]);
0605         }
0606 
0607         // Closure comparison
0608         BOOST_UBLAS_INLINE
0609         bool same_closure (const vector_binary &vb) const {
0610             return (*this).expression1 ().same_closure (vb.expression1 ()) &&
0611                    (*this).expression2 ().same_closure (vb.expression2 ());
0612         }
0613 
0614         // Iterator types
0615     private:
0616         typedef typename E1::const_iterator const_subiterator1_type;
0617         typedef typename E2::const_iterator const_subiterator2_type;
0618         typedef const value_type *const_pointer;
0619 
0620     public:
0621 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
0622         typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
0623                                                   typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
0624         typedef indexed_const_iterator<const_closure_type, iterator_category> const_iterator;
0625         typedef const_iterator iterator;
0626 #else
0627         class const_iterator;
0628         typedef const_iterator iterator;
0629 #endif
0630 
0631         // Element lookup
0632         BOOST_UBLAS_INLINE
0633         const_iterator find (size_type i) const {
0634             const_subiterator1_type it1 (e1_.find (i));
0635             const_subiterator1_type it1_end (e1_.find (size ()));
0636             const_subiterator2_type it2 (e2_.find (i));
0637             const_subiterator2_type it2_end (e2_.find (size ()));
0638             i = (std::min) (it1 != it1_end ? it1.index () : size (),
0639                           it2 != it2_end ? it2.index () : size ());
0640 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
0641             return const_iterator (*this, i);
0642 #else
0643             return const_iterator (*this, i, it1, it1_end, it2, it2_end);
0644 #endif
0645         }
0646 
0647         // Iterator merges the iterators of the referenced expressions and
0648         // enhances them with the binary functor.
0649 
0650 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
0651         class const_iterator:
0652             public container_const_reference<vector_binary>,
0653             public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
0654                                                                           typename E2::const_iterator::iterator_category>::iterator_category>::template
0655                         iterator_base<const_iterator, value_type>::type {
0656         public:
0657             typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
0658                                                       typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
0659             typedef typename vector_binary::difference_type difference_type;
0660             typedef typename vector_binary::value_type value_type;
0661             typedef typename vector_binary::const_reference reference;
0662             typedef typename vector_binary::const_pointer pointer;
0663 
0664             // Construction and destruction
0665             BOOST_UBLAS_INLINE
0666             const_iterator ():
0667                 container_const_reference<self_type> (), i_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
0668             BOOST_UBLAS_INLINE
0669             const_iterator (const self_type &vb, size_type i,
0670                             const const_subiterator1_type &it1, const const_subiterator1_type &it1_end,
0671                             const const_subiterator2_type &it2, const const_subiterator2_type &it2_end):
0672                 container_const_reference<self_type> (vb), i_ (i), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
0673 
0674         private: 
0675             // Dense specializations
0676             BOOST_UBLAS_INLINE
0677             void increment (dense_random_access_iterator_tag) {
0678                 ++ i_; ++ it1_; ++ it2_;
0679             }
0680             BOOST_UBLAS_INLINE
0681             void decrement (dense_random_access_iterator_tag) {
0682                 -- i_; -- it1_; -- it2_;
0683             }
0684             BOOST_UBLAS_INLINE
0685             void increment (dense_random_access_iterator_tag, difference_type n) {
0686                 i_ += n; it1_ += n; it2_ += n;
0687             }
0688             BOOST_UBLAS_INLINE
0689             void decrement (dense_random_access_iterator_tag, difference_type n) {
0690                 i_ -= n; it1_ -= n; it2_ -= n;
0691             }
0692             BOOST_UBLAS_INLINE
0693             value_type dereference (dense_random_access_iterator_tag) const {
0694                 return functor_type::apply (*it1_, *it2_);
0695             }
0696 
0697             // Packed specializations
0698             BOOST_UBLAS_INLINE
0699             void increment (packed_random_access_iterator_tag) {
0700                 if (it1_ != it1_end_)
0701                     if (it1_.index () <= i_)
0702                         ++ it1_;
0703                 if (it2_ != it2_end_)
0704                     if (it2_.index () <= i_)
0705                         ++ it2_;
0706                 ++ i_;
0707             }
0708             BOOST_UBLAS_INLINE
0709             void decrement (packed_random_access_iterator_tag) {
0710                 if (it1_ != it1_end_)
0711                     if (i_ <= it1_.index ())
0712                         -- it1_;
0713                 if (it2_ != it2_end_)
0714                     if (i_ <= it2_.index ())
0715                         -- it2_;
0716                 -- i_;
0717             }
0718             BOOST_UBLAS_INLINE
0719             void increment (packed_random_access_iterator_tag, difference_type n) {
0720                 while (n > 0) {
0721                     increment (packed_random_access_iterator_tag ());
0722                     --n;
0723                 }
0724                 while (n < 0) {
0725                     decrement (packed_random_access_iterator_tag ());
0726                     ++n;
0727                 }
0728             }
0729             BOOST_UBLAS_INLINE
0730             void decrement (packed_random_access_iterator_tag, difference_type n) {
0731                 while (n > 0) {
0732                     decrement (packed_random_access_iterator_tag ());
0733                     --n;
0734                 }
0735                 while (n < 0) {
0736                     increment (packed_random_access_iterator_tag ());
0737                     ++n;
0738                 }
0739             }
0740             BOOST_UBLAS_INLINE
0741             value_type dereference (packed_random_access_iterator_tag) const {
0742                 typename E1::value_type t1 = typename E1::value_type/*zero*/();
0743                 if (it1_ != it1_end_)
0744                     if (it1_.index () == i_)
0745                         t1 = *it1_;
0746                 typename E2::value_type t2 = typename E2::value_type/*zero*/();
0747                 if (it2_ != it2_end_)
0748                     if (it2_.index () == i_)
0749                         t2 = *it2_;
0750                 return functor_type::apply (t1, t2);
0751             }
0752 
0753             // Sparse specializations
0754             BOOST_UBLAS_INLINE
0755             void increment (sparse_bidirectional_iterator_tag) {
0756                 size_type index1 = (*this) ().size ();
0757                 if (it1_ != it1_end_) {
0758                     if  (it1_.index () <= i_)
0759                         ++ it1_;
0760                     if (it1_ != it1_end_)
0761                         index1 = it1_.index ();
0762                 }
0763                 size_type index2 = (*this) ().size ();
0764                 if (it2_ != it2_end_) {
0765                     if (it2_.index () <= i_)
0766                         ++ it2_;
0767                     if (it2_ != it2_end_)
0768                         index2 = it2_.index ();
0769                 }
0770                 i_ = (std::min) (index1, index2);
0771             }
0772             BOOST_UBLAS_INLINE
0773             void decrement (sparse_bidirectional_iterator_tag) {
0774                 size_type index1 = (*this) ().size ();
0775                 if (it1_ != it1_end_) {
0776                     if (i_ <= it1_.index ())
0777                         -- it1_;
0778                     if (it1_ != it1_end_)
0779                         index1 = it1_.index ();
0780                 }
0781                 size_type index2 = (*this) ().size ();
0782                 if (it2_ != it2_end_) {
0783                     if (i_ <= it2_.index ())
0784                         -- it2_;
0785                     if (it2_ != it2_end_)
0786                         index2 = it2_.index ();
0787                 }
0788                 i_ = (std::max) (index1, index2);
0789             }
0790             BOOST_UBLAS_INLINE
0791             void increment (sparse_bidirectional_iterator_tag, difference_type n) {
0792                 while (n > 0) {
0793                     increment (sparse_bidirectional_iterator_tag ());
0794                     --n;
0795                 }
0796                 while (n < 0) {
0797                     decrement (sparse_bidirectional_iterator_tag ());
0798                     ++n;
0799                 }
0800             }
0801             BOOST_UBLAS_INLINE
0802             void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
0803                 while (n > 0) {
0804                     decrement (sparse_bidirectional_iterator_tag ());
0805                     --n;
0806                 }
0807                 while (n < 0) {
0808                     increment (sparse_bidirectional_iterator_tag ());
0809                     ++n;
0810                 }
0811             }
0812             BOOST_UBLAS_INLINE
0813             value_type dereference (sparse_bidirectional_iterator_tag) const {
0814                 typename E1::value_type t1 = typename E1::value_type/*zero*/();
0815                 if (it1_ != it1_end_)
0816                     if (it1_.index () == i_)
0817                         t1 = *it1_;
0818                 typename E2::value_type t2 = typename E2::value_type/*zero*/();
0819                 if (it2_ != it2_end_)
0820                     if (it2_.index () == i_)
0821                         t2 = *it2_;
0822                 return static_cast<value_type>(functor_type::apply (t1, t2));
0823             }
0824 
0825         public: 
0826             // Arithmetic
0827             BOOST_UBLAS_INLINE
0828             const_iterator &operator ++ () {
0829                 increment (iterator_category ());
0830                 return *this;
0831             }
0832             BOOST_UBLAS_INLINE
0833             const_iterator &operator -- () {
0834                 decrement (iterator_category ());
0835                 return *this;
0836             }
0837             BOOST_UBLAS_INLINE
0838             const_iterator &operator += (difference_type n) {
0839                 increment (iterator_category (), n);
0840                 return *this;
0841             }
0842             BOOST_UBLAS_INLINE
0843             const_iterator &operator -= (difference_type n) {
0844                 decrement (iterator_category (), n);
0845                 return *this;
0846             }
0847             BOOST_UBLAS_INLINE
0848             difference_type operator - (const const_iterator &it) const {
0849                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0850                 return index () - it.index ();
0851             }
0852 
0853             // Dereference
0854             BOOST_UBLAS_INLINE
0855             const_reference operator * () const {
0856                 return dereference (iterator_category ());
0857             }
0858             BOOST_UBLAS_INLINE
0859             const_reference operator [] (difference_type n) const {
0860                 return *(*this + n);
0861             }
0862 
0863             // Index
0864             BOOST_UBLAS_INLINE
0865             size_type index () const {
0866                 return i_;
0867             }
0868 
0869             // Assignment
0870             BOOST_UBLAS_INLINE
0871             const_iterator &operator = (const const_iterator &it) {
0872                 container_const_reference<self_type>::assign (&it ());
0873                 i_ = it.i_;
0874                 it1_ = it.it1_;
0875                 it1_end_ = it.it1_end_;
0876                 it2_ = it.it2_;
0877                 it2_end_ = it.it2_end_;
0878                 return *this;
0879             }
0880 
0881             // Comparison
0882             BOOST_UBLAS_INLINE
0883             bool operator == (const const_iterator &it) const {
0884                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0885                 return index () == it.index ();
0886             }
0887             BOOST_UBLAS_INLINE
0888             bool operator < (const const_iterator &it) const {
0889                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
0890                 return index () < it.index ();
0891             }
0892 
0893         private:
0894             size_type i_;
0895             const_subiterator1_type it1_;
0896             const_subiterator1_type it1_end_;
0897             const_subiterator2_type it2_;
0898             const_subiterator2_type it2_end_;
0899         };
0900 #endif
0901 
0902         BOOST_UBLAS_INLINE
0903         const_iterator begin () const {
0904             return find (0);
0905         }
0906         BOOST_UBLAS_INLINE
0907         const_iterator cbegin () const {
0908             return begin ();
0909         }
0910         BOOST_UBLAS_INLINE
0911         const_iterator end () const {
0912             return find (size ());
0913         }
0914         BOOST_UBLAS_INLINE
0915         const_iterator cend () const {
0916             return end ();
0917         }
0918 
0919         // Reverse iterator
0920         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
0921 
0922         BOOST_UBLAS_INLINE
0923         const_reverse_iterator rbegin () const {
0924             return const_reverse_iterator (end ());
0925         }
0926         BOOST_UBLAS_INLINE
0927         const_reverse_iterator crbegin () const {
0928             return rbegin ();
0929         }
0930         BOOST_UBLAS_INLINE
0931         const_reverse_iterator rend () const {
0932             return const_reverse_iterator (begin ());
0933         }
0934         BOOST_UBLAS_INLINE
0935         const_reverse_iterator crend () const {
0936             return rend ();
0937         }
0938 
0939     private:
0940         expression1_closure_type e1_;
0941         expression2_closure_type e2_;
0942     };
0943 
0944     template<class E1, class E2, class F>
0945     struct vector_binary_traits {
0946         typedef vector_binary<E1, E2, F> expression_type;
0947 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
0948         typedef expression_type result_type; 
0949 #else
0950         typedef typename E1::vector_temporary_type result_type;
0951 #endif
0952     };
0953 
0954     // (v1 + v2) [i] = v1 [i] + v2 [i]
0955     template<class E1, class E2>
0956     BOOST_UBLAS_INLINE
0957     typename vector_binary_traits<E1, E2, scalar_plus<typename E1::value_type, 
0958                                                       typename E2::value_type> >::result_type
0959     operator + (const vector_expression<E1> &e1,
0960                 const vector_expression<E2> &e2) {
0961         typedef typename vector_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
0962                                                                               typename E2::value_type> >::expression_type expression_type;
0963         return expression_type (e1 (), e2 ());
0964     }
0965 
0966     // (v1 - v2) [i] = v1 [i] - v2 [i]
0967     template<class E1, class E2>
0968     BOOST_UBLAS_INLINE
0969     typename vector_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
0970                                                        typename E2::value_type> >::result_type
0971     operator - (const vector_expression<E1> &e1,
0972                 const vector_expression<E2> &e2) {
0973         typedef typename vector_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
0974                                                                                typename E2::value_type> >::expression_type expression_type;
0975         return expression_type (e1 (), e2 ());
0976     }
0977 
0978     // (v1 * v2) [i] = v1 [i] * v2 [i]
0979     template<class E1, class E2>
0980     BOOST_UBLAS_INLINE
0981     typename vector_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
0982                                                             typename E2::value_type> >::result_type
0983     element_prod (const vector_expression<E1> &e1,
0984                   const vector_expression<E2> &e2) {
0985         typedef typename vector_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
0986                                                                                     typename E2::value_type> >::expression_type expression_type;
0987         return expression_type (e1 (), e2 ());
0988     }
0989 
0990     // (v1 / v2) [i] = v1 [i] / v2 [i]
0991     template<class E1, class E2>
0992     BOOST_UBLAS_INLINE
0993     typename vector_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
0994                                                          typename E2::value_type> >::result_type
0995     element_div (const vector_expression<E1> &e1,
0996                  const vector_expression<E2> &e2) {
0997         typedef typename vector_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
0998                                                                                  typename E2::value_type> >::expression_type expression_type;
0999         return expression_type (e1 (), e2 ());
1000     }
1001 
1002 
1003     template<class E1, class E2, class F>
1004     class vector_binary_scalar1:
1005         public vector_expression<vector_binary_scalar1<E1, E2, F> > {
1006 
1007         typedef F functor_type;
1008         typedef E1 expression1_type;
1009         typedef E2 expression2_type;
1010     public:
1011         typedef const E1& expression1_closure_type;
1012         typedef typename E2::const_closure_type expression2_closure_type;
1013     private:
1014         typedef vector_binary_scalar1<E1, E2, F> self_type;
1015     public:
1016 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1017         using vector_expression<vector_binary_scalar1<E1, E2, F> >::operator ();
1018 #endif
1019         typedef typename E2::size_type size_type;
1020         typedef typename E2::difference_type difference_type;
1021         typedef typename F::result_type value_type;
1022         typedef value_type const_reference;
1023         typedef const_reference reference;
1024         typedef const self_type const_closure_type;
1025         typedef const_closure_type closure_type;
1026         typedef unknown_storage_tag storage_category;
1027 
1028         // Construction and destruction
1029         BOOST_UBLAS_INLINE
1030         vector_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
1031             e1_ (e1), e2_ (e2) {}
1032 
1033         // Accessors
1034         BOOST_UBLAS_INLINE
1035         size_type size () const {
1036             return e2_.size ();
1037         }
1038 
1039     public:
1040         // Element access
1041         BOOST_UBLAS_INLINE
1042         const_reference operator () (size_type i) const {
1043             return functor_type::apply (e1_, e2_ (i));
1044         }
1045 
1046         BOOST_UBLAS_INLINE
1047         const_reference operator [] (size_type i) const {
1048             return functor_type::apply (e1_, e2_ [i]);
1049         }
1050 
1051         // Closure comparison
1052         BOOST_UBLAS_INLINE
1053         bool same_closure (const vector_binary_scalar1 &vbs1) const {
1054             return &e1_ == &(vbs1.e1_) &&
1055                    (*this).e2_.same_closure (vbs1.e2_);
1056         }
1057 
1058         // Iterator types
1059     private:
1060         typedef expression1_type const_subiterator1_type;
1061         typedef typename expression2_type::const_iterator const_subiterator2_type;
1062         typedef const value_type *const_pointer;
1063 
1064     public:
1065 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1066         typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
1067         typedef const_iterator iterator;
1068 #else
1069         class const_iterator;
1070         typedef const_iterator iterator;
1071 #endif
1072 
1073         // Element lookup
1074         BOOST_UBLAS_INLINE
1075         const_iterator find (size_type i) const {
1076 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1077             const_subiterator2_type it (e2_.find (i));
1078             return const_iterator (*this, it.index ());
1079 #else
1080             return const_iterator (*this, const_subiterator1_type (e1_), e2_.find (i));
1081 #endif
1082         }
1083 
1084         // Iterator enhances the iterator of the referenced vector expression
1085         // with the binary functor.
1086 
1087 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1088         class const_iterator:
1089             public container_const_reference<vector_binary_scalar1>,
1090             public iterator_base_traits<typename E2::const_iterator::iterator_category>::template
1091                         iterator_base<const_iterator, value_type>::type {
1092         public:
1093             typedef typename E2::const_iterator::iterator_category iterator_category;
1094             typedef typename vector_binary_scalar1::difference_type difference_type;
1095             typedef typename vector_binary_scalar1::value_type value_type;
1096             typedef typename vector_binary_scalar1::const_reference reference;
1097             typedef typename vector_binary_scalar1::const_pointer pointer;
1098 
1099             // Construction and destruction
1100             BOOST_UBLAS_INLINE
1101             const_iterator ():
1102                 container_const_reference<self_type> (), it1_ (), it2_ () {}
1103             BOOST_UBLAS_INLINE
1104             const_iterator (const self_type &vbs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
1105                 container_const_reference<self_type> (vbs), it1_ (it1), it2_ (it2) {}
1106 
1107             // Arithmetic
1108             BOOST_UBLAS_INLINE
1109             const_iterator &operator ++ () {
1110                 ++ it2_;
1111                 return *this;
1112             }
1113             BOOST_UBLAS_INLINE
1114             const_iterator &operator -- () {
1115                 -- it2_;
1116                 return *this;
1117             }
1118             BOOST_UBLAS_INLINE
1119             const_iterator &operator += (difference_type n) {
1120                 it2_ += n;
1121                 return *this;
1122             }
1123             BOOST_UBLAS_INLINE
1124             const_iterator &operator -= (difference_type n) {
1125                 it2_ -= n;
1126                 return *this;
1127             }
1128             BOOST_UBLAS_INLINE
1129             difference_type operator - (const const_iterator &it) const {
1130                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1131                 // FIXME we shouldn't compare floats
1132                 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1133                 return it2_ - it.it2_;
1134             }
1135 
1136             // Dereference
1137             BOOST_UBLAS_INLINE
1138             const_reference operator * () const {
1139                 return functor_type::apply (it1_, *it2_);
1140             }
1141             BOOST_UBLAS_INLINE
1142             const_reference operator [] (difference_type n) const {
1143                 return *(*this + n);
1144             }
1145 
1146             // Index
1147             BOOST_UBLAS_INLINE
1148             size_type index () const {
1149                 return it2_.index ();
1150             }
1151 
1152             // Assignment 
1153             BOOST_UBLAS_INLINE
1154             const_iterator &operator = (const const_iterator &it) {
1155                 container_const_reference<self_type>::assign (&it ());
1156                 it1_ = it.it1_;
1157                 it2_ = it.it2_;
1158                 return *this;
1159             }
1160 
1161             // Comparison
1162             BOOST_UBLAS_INLINE
1163             bool operator == (const const_iterator &it) const {
1164                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1165                 // FIXME we shouldn't compare floats
1166                 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1167                 return it2_ == it.it2_;
1168             }
1169             BOOST_UBLAS_INLINE
1170             bool operator < (const const_iterator &it) const {
1171                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1172                 // FIXME we shouldn't compare floats
1173                 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1174                 return it2_ < it.it2_;
1175             }
1176 
1177         private:
1178             const_subiterator1_type it1_;
1179             const_subiterator2_type it2_;
1180         };
1181 #endif
1182 
1183         BOOST_UBLAS_INLINE
1184         const_iterator begin () const {
1185             return find (0); 
1186         }
1187         BOOST_UBLAS_INLINE
1188         const_iterator cbegin () const {
1189             return begin ();
1190         }
1191         BOOST_UBLAS_INLINE
1192         const_iterator end () const {
1193             return find (size ()); 
1194         }
1195         BOOST_UBLAS_INLINE
1196         const_iterator cend () const {
1197             return end ();
1198         }
1199 
1200         // Reverse iterator
1201         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1202 
1203         BOOST_UBLAS_INLINE
1204         const_reverse_iterator rbegin () const {
1205             return const_reverse_iterator (end ());
1206         }
1207         BOOST_UBLAS_INLINE
1208         const_reverse_iterator crbegin () const {
1209             return rbegin ();
1210         }
1211         BOOST_UBLAS_INLINE
1212         const_reverse_iterator rend () const {
1213             return const_reverse_iterator (begin ());
1214         }
1215         BOOST_UBLAS_INLINE
1216         const_reverse_iterator crend () const {
1217             return end ();
1218         }
1219 
1220     private:
1221         expression1_closure_type e1_;
1222         expression2_closure_type e2_;
1223     };
1224 
1225     template<class E1, class E2, class F>
1226     struct vector_binary_scalar1_traits {
1227         typedef vector_binary_scalar1<E1, E2, F> expression_type;   // allow E1 to be builtin type
1228 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1229         typedef expression_type result_type;
1230 #else
1231         typedef typename E2::vector_temporary_type result_type;
1232 #endif
1233     };
1234 
1235     // (t * v) [i] = t * v [i]
1236     template<class T1, class E2>
1237     BOOST_UBLAS_INLINE
1238     typename boost::enable_if< is_convertible<T1, typename E2::value_type >,
1239     typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
1240     >::type
1241     operator * (const T1 &e1,
1242                 const vector_expression<E2> &e2) {
1243         typedef typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
1244         return expression_type (e1, e2 ());
1245     }
1246 
1247 
1248     template<class E1, class E2, class F>
1249     class vector_binary_scalar2:
1250         public vector_expression<vector_binary_scalar2<E1, E2, F> > {
1251 
1252         typedef F functor_type;
1253         typedef E1 expression1_type;
1254         typedef E2 expression2_type;
1255         typedef typename E1::const_closure_type expression1_closure_type;
1256         typedef const E2& expression2_closure_type;
1257         typedef vector_binary_scalar2<E1, E2, F> self_type;
1258     public:
1259 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1260         using vector_expression<vector_binary_scalar2<E1, E2, F> >::operator ();
1261 #endif
1262         typedef typename E1::size_type size_type;
1263         typedef typename E1::difference_type difference_type;
1264         typedef typename F::result_type value_type;
1265         typedef value_type const_reference;
1266         typedef const_reference reference;
1267         typedef const self_type const_closure_type;
1268         typedef const_closure_type closure_type;
1269         typedef unknown_storage_tag storage_category;
1270 
1271         // Construction and destruction
1272         BOOST_UBLAS_INLINE
1273         vector_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
1274             e1_ (e1), e2_ (e2) {}
1275 
1276         // Accessors
1277         BOOST_UBLAS_INLINE
1278         size_type size () const {
1279             return e1_.size (); 
1280         }
1281 
1282     public:
1283         // Element access
1284         BOOST_UBLAS_INLINE
1285         const_reference operator () (size_type i) const {
1286             return functor_type::apply (e1_ (i), e2_);
1287         }
1288 
1289         BOOST_UBLAS_INLINE
1290         const_reference operator [] (size_type i) const {
1291             return functor_type::apply (e1_ [i], e2_);
1292         }
1293 
1294         // Closure comparison
1295         BOOST_UBLAS_INLINE
1296         bool same_closure (const vector_binary_scalar2 &vbs2) const {
1297             return (*this).e1_.same_closure (vbs2.e1_) &&
1298                    &e2_ == &(vbs2.e2_);
1299         }
1300 
1301         // Iterator types
1302     private:
1303         typedef typename expression1_type::const_iterator const_subiterator1_type;
1304         typedef expression2_type const_subiterator2_type;
1305         typedef const value_type *const_pointer;
1306 
1307     public:
1308 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1309         typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
1310         typedef const_iterator iterator;
1311 #else
1312         class const_iterator;
1313         typedef const_iterator iterator;
1314 #endif
1315 
1316         // Element lookup
1317         BOOST_UBLAS_INLINE
1318         const_iterator find (size_type i) const {
1319 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1320             const_subiterator1_type it (e1_.find (i));
1321             return const_iterator (*this, it.index ());
1322 #else
1323             return const_iterator (*this, e1_.find (i), const_subiterator2_type (e2_));
1324 #endif
1325         }
1326 
1327         // Iterator enhances the iterator of the referenced vector expression
1328         // with the binary functor.
1329 
1330 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1331         class const_iterator:
1332             public container_const_reference<vector_binary_scalar2>,
1333             public iterator_base_traits<typename E1::const_iterator::iterator_category>::template
1334                         iterator_base<const_iterator, value_type>::type {
1335         public:
1336             typedef typename E1::const_iterator::iterator_category iterator_category;
1337             typedef typename vector_binary_scalar2::difference_type difference_type;
1338             typedef typename vector_binary_scalar2::value_type value_type;
1339             typedef typename vector_binary_scalar2::const_reference reference;
1340             typedef typename vector_binary_scalar2::const_pointer pointer;
1341 
1342             // Construction and destruction
1343             BOOST_UBLAS_INLINE
1344             const_iterator ():
1345                 container_const_reference<self_type> (), it1_ (), it2_ () {}
1346             BOOST_UBLAS_INLINE
1347             const_iterator (const self_type &vbs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
1348                 container_const_reference<self_type> (vbs), it1_ (it1), it2_ (it2) {}
1349 
1350             // Arithmetic
1351             BOOST_UBLAS_INLINE
1352             const_iterator &operator ++ () {
1353                 ++ it1_;
1354                 return *this;
1355             }
1356             BOOST_UBLAS_INLINE
1357             const_iterator &operator -- () {
1358                 -- it1_;
1359                 return *this;
1360             }
1361             BOOST_UBLAS_INLINE
1362             const_iterator &operator += (difference_type n) {
1363                 it1_ += n;
1364                 return *this;
1365             }
1366             BOOST_UBLAS_INLINE
1367             const_iterator &operator -= (difference_type n) {
1368                 it1_ -= n;
1369                 return *this;
1370             }
1371             BOOST_UBLAS_INLINE
1372             difference_type operator - (const const_iterator &it) const {
1373                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1374                 // FIXME we shouldn't compare floats
1375                 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
1376                 return it1_ - it.it1_;
1377             }
1378 
1379             // Dereference
1380             BOOST_UBLAS_INLINE
1381             const_reference operator * () const {
1382                 return functor_type::apply (*it1_, it2_);
1383             }
1384             BOOST_UBLAS_INLINE
1385             const_reference operator [] (difference_type n) const {
1386                 return *(*this + n);
1387             }
1388 
1389             // Index
1390             BOOST_UBLAS_INLINE
1391             size_type index () const {
1392                 return it1_.index ();
1393             }
1394 
1395             // Assignment
1396             BOOST_UBLAS_INLINE
1397             const_iterator &operator = (const const_iterator &it) {
1398                 container_const_reference<self_type>::assign (&it ());
1399                 it1_ = it.it1_;
1400                 it2_ = it.it2_;
1401                 return *this;
1402             }
1403 
1404             // Comparison
1405             BOOST_UBLAS_INLINE
1406             bool operator == (const const_iterator &it) const {
1407                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1408                 // FIXME we shouldn't compare floats
1409                 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
1410                 return it1_ == it.it1_;
1411             }
1412             BOOST_UBLAS_INLINE
1413             bool operator < (const const_iterator &it) const {
1414                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1415                 // FIXME we shouldn't compare floats
1416                 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
1417                 return it1_ < it.it1_;
1418             }
1419 
1420         private:
1421             const_subiterator1_type it1_;
1422             const_subiterator2_type it2_;
1423         };
1424 #endif
1425 
1426         BOOST_UBLAS_INLINE
1427         const_iterator begin () const {
1428             return find (0);
1429         }
1430         BOOST_UBLAS_INLINE
1431         const_iterator cbegin () const {
1432             return begin ();
1433         }
1434         BOOST_UBLAS_INLINE
1435         const_iterator end () const {
1436             return find (size ());
1437         }
1438         BOOST_UBLAS_INLINE
1439         const_iterator cend () const {
1440             return end ();
1441         }
1442 
1443         // Reverse iterator
1444         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1445 
1446         BOOST_UBLAS_INLINE
1447         const_reverse_iterator rbegin () const {
1448             return const_reverse_iterator (end ());
1449         }
1450         BOOST_UBLAS_INLINE
1451         const_reverse_iterator crbegin () const {
1452             return rbegin ();
1453         }
1454         BOOST_UBLAS_INLINE
1455         const_reverse_iterator rend () const {
1456             return const_reverse_iterator (begin ());
1457         }
1458         BOOST_UBLAS_INLINE
1459         const_reverse_iterator crend () const {
1460             return rend ();
1461         }
1462 
1463     private:
1464         expression1_closure_type e1_;
1465         expression2_closure_type e2_;
1466     };
1467 
1468     template<class E1, class E2, class F>
1469     struct vector_binary_scalar2_traits {
1470         typedef vector_binary_scalar2<E1, E2, F> expression_type;   // allow E2 to be builtin type
1471 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1472         typedef expression_type result_type;
1473 #else
1474         typedef typename E1::vector_temporary_type result_type;
1475 #endif
1476     };
1477 
1478     // (v * t) [i] = v [i] * t
1479     template<class E1, class T2>
1480     BOOST_UBLAS_INLINE
1481     typename boost::enable_if< is_convertible<T2, typename E1::value_type >,
1482     typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
1483     >::type
1484     operator * (const vector_expression<E1> &e1,
1485                 const T2 &e2) {
1486         typedef typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
1487         return expression_type (e1 (), e2);
1488     }
1489 
1490     // (v / t) [i] = v [i] / t
1491     template<class E1, class T2>
1492     BOOST_UBLAS_INLINE
1493     typename boost::enable_if< is_convertible<T2, typename E1::value_type >,
1494     typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
1495     >::type
1496     operator / (const vector_expression<E1> &e1,
1497                 const T2 &e2) {
1498         typedef typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
1499         return expression_type (e1 (), e2);
1500     }
1501 
1502 
1503     template<class E, class F>
1504     class vector_scalar_unary:
1505         public scalar_expression<vector_scalar_unary<E, F> > {
1506 
1507         typedef E expression_type;
1508         typedef F functor_type;
1509         typedef typename E::const_closure_type expression_closure_type;
1510         typedef typename E::const_iterator::iterator_category iterator_category;
1511         typedef vector_scalar_unary<E, F> self_type;
1512     public:
1513         typedef typename F::result_type value_type;
1514         typedef typename E::difference_type difference_type;
1515         typedef const self_type const_closure_type;
1516         typedef const_closure_type closure_type;
1517         typedef unknown_storage_tag storage_category;
1518 
1519         // Construction and destruction
1520         BOOST_UBLAS_INLINE
1521         explicit vector_scalar_unary (const expression_type &e):
1522             e_ (e) {}
1523 
1524     private:
1525         // Expression accessors
1526         BOOST_UBLAS_INLINE
1527         const expression_closure_type &expression () const {
1528             return e_;
1529         }
1530 
1531     public:
1532         BOOST_UBLAS_INLINE
1533         operator value_type () const {
1534             return evaluate (iterator_category ());
1535         }
1536 
1537     private:
1538         // Dense random access specialization
1539         BOOST_UBLAS_INLINE
1540         value_type evaluate (dense_random_access_iterator_tag) const {
1541 #ifdef BOOST_UBLAS_USE_INDEXING
1542             return functor_type::apply (e_);
1543 #elif BOOST_UBLAS_USE_ITERATING
1544             difference_type size = e_.size ();
1545             return functor_type::apply (size, e_.begin ());
1546 #else
1547             difference_type size = e_.size ();
1548             if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
1549                 return functor_type::apply (size, e_.begin ());
1550             else
1551                 return functor_type::apply (e_);
1552 #endif
1553         }
1554 
1555         // Packed bidirectional specialization
1556         BOOST_UBLAS_INLINE
1557         value_type evaluate (packed_random_access_iterator_tag) const {
1558             return functor_type::apply (e_.begin (), e_.end ());
1559         }
1560 
1561         // Sparse bidirectional specialization
1562         BOOST_UBLAS_INLINE
1563         value_type evaluate (sparse_bidirectional_iterator_tag) const {
1564             return functor_type::apply (e_.begin (), e_.end ());
1565         }
1566 
1567     private:
1568         expression_closure_type e_;
1569     };
1570 
1571     template<class E, class F>
1572     struct vector_scalar_unary_traits {
1573         typedef vector_scalar_unary<E, F> expression_type;
1574 #if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET)
1575 // FIXME don't define USE_SCALAR_ET other then for testing
1576 // They do not work for complex types
1577          typedef expression_type result_type;
1578 #else
1579          typedef typename F::result_type result_type;
1580 #endif
1581     };
1582 
1583     // sum v = sum (v [i])
1584     template<class E>
1585     BOOST_UBLAS_INLINE
1586     typename vector_scalar_unary_traits<E, vector_sum<E> >::result_type
1587     sum (const vector_expression<E> &e) {
1588         typedef typename vector_scalar_unary_traits<E, vector_sum<E> >::expression_type expression_type;
1589         return expression_type (e ());
1590     }
1591 
1592     // real: norm_1 v = sum (abs (v [i]))
1593     // complex: norm_1 v = sum (abs (real (v [i])) + abs (imag (v [i])))
1594     template<class E>
1595     BOOST_UBLAS_INLINE
1596     typename vector_scalar_unary_traits<E, vector_norm_1<E> >::result_type
1597     norm_1 (const vector_expression<E> &e) {
1598         typedef typename vector_scalar_unary_traits<E, vector_norm_1<E> >::expression_type expression_type;
1599         return expression_type (e ());
1600     }
1601 
1602     // real: norm_2 v = sqrt (sum (v [i] * v [i]))
1603     // complex: norm_2 v = sqrt (sum (v [i] * conj (v [i])))
1604     template<class E>
1605     BOOST_UBLAS_INLINE
1606     typename vector_scalar_unary_traits<E, vector_norm_2<E> >::result_type
1607     norm_2 (const vector_expression<E> &e) {
1608         typedef typename vector_scalar_unary_traits<E, vector_norm_2<E> >::expression_type expression_type;
1609         return expression_type (e ());
1610     }
1611 
1612     // real: norm_2_square v = sum(v [i] * v [i])
1613     // complex: norm_2_square v = sum(v [i] * conj (v [i]))
1614     template<class E>
1615     BOOST_UBLAS_INLINE
1616     typename vector_scalar_unary_traits<E, vector_norm_2_square<E> >::result_type
1617     norm_2_square (const vector_expression<E> &e) {
1618         typedef typename vector_scalar_unary_traits<E, vector_norm_2_square<E> >::expression_type expression_type;
1619         return expression_type (e ());
1620     }
1621 
1622     // real: norm_inf v = maximum (abs (v [i]))
1623     // complex: norm_inf v = maximum (maximum (abs (real (v [i])), abs (imag (v [i]))))
1624     template<class E>
1625     BOOST_UBLAS_INLINE
1626     typename vector_scalar_unary_traits<E, vector_norm_inf<E> >::result_type
1627     norm_inf (const vector_expression<E> &e) {
1628         typedef typename vector_scalar_unary_traits<E, vector_norm_inf<E> >::expression_type expression_type;
1629         return expression_type (e ());
1630     }
1631 
1632     // real: index_norm_inf v = minimum (i: abs (v [i]) == maximum (abs (v [i])))
1633     template<class E>
1634     BOOST_UBLAS_INLINE
1635     typename vector_scalar_unary_traits<E, vector_index_norm_inf<E> >::result_type
1636     index_norm_inf (const vector_expression<E> &e) {
1637         typedef typename vector_scalar_unary_traits<E, vector_index_norm_inf<E> >::expression_type expression_type;
1638         return expression_type (e ());
1639     }
1640 
1641     template<class E1, class E2, class F>
1642     class vector_scalar_binary:
1643         public scalar_expression<vector_scalar_binary<E1, E2, F> > {
1644 
1645         typedef E1 expression1_type;
1646         typedef E2 expression2_type;
1647         typedef F functor_type;
1648         typedef typename E1::const_closure_type expression1_closure_type;
1649         typedef typename E2::const_closure_type expression2_closure_type;
1650         typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
1651                                                   typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
1652         typedef vector_scalar_binary<E1, E2, F> self_type;
1653     public:
1654         static const unsigned complexity = 1;
1655         typedef typename F::result_type value_type;
1656         typedef typename E1::difference_type difference_type;
1657         typedef const self_type const_closure_type;
1658         typedef const_closure_type closure_type;
1659         typedef unknown_storage_tag storage_category;
1660 
1661         // Construction and destruction
1662         BOOST_UBLAS_INLINE
1663         vector_scalar_binary (const expression1_type &e1, const expression2_type  &e2):
1664             e1_ (e1), e2_ (e2) {}
1665 
1666     private:
1667         // Accessors
1668         BOOST_UBLAS_INLINE
1669         const expression1_closure_type &expression1 () const {
1670             return e1_;
1671         }
1672         BOOST_UBLAS_INLINE
1673         const expression2_closure_type &expression2 () const {
1674             return e2_;
1675         }
1676 
1677     public:
1678         BOOST_UBLAS_INLINE
1679         operator value_type () const {
1680             return evaluate (iterator_category ());
1681         }
1682 
1683     private:
1684         // Dense random access specialization
1685         BOOST_UBLAS_INLINE
1686         value_type evaluate (dense_random_access_iterator_tag) const {
1687             BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
1688 #ifdef BOOST_UBLAS_USE_INDEXING
1689             return functor_type::apply (e1_, e2_);
1690 #elif BOOST_UBLAS_USE_ITERATING
1691             difference_type size = BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
1692             return functor_type::apply (size, e1_.begin (), e2_.begin ());
1693 #else
1694             difference_type size = BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
1695             if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
1696                 return functor_type::apply (size, e1_.begin (), e2_.begin ());
1697             else
1698                 return functor_type::apply (e1_, e2_);
1699 #endif
1700         }
1701 
1702         // Packed bidirectional specialization
1703         BOOST_UBLAS_INLINE
1704         value_type evaluate (packed_random_access_iterator_tag) const {
1705             BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
1706             return functor_type::apply (e1_.begin (), e1_.end (), e2_.begin (), e2_.end ());
1707         }
1708 
1709         // Sparse bidirectional specialization
1710         BOOST_UBLAS_INLINE
1711         value_type evaluate (sparse_bidirectional_iterator_tag) const {
1712             BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
1713             return functor_type::apply (e1_.begin (), e1_.end (), e2_.begin (), e2_.end (), sparse_bidirectional_iterator_tag ());
1714         }
1715 
1716     private:
1717         expression1_closure_type e1_;
1718         expression2_closure_type e2_;
1719     };
1720 
1721     template<class E1, class E2, class F>
1722     struct vector_scalar_binary_traits {
1723         typedef vector_scalar_binary<E1, E2, F> expression_type;
1724 #if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET)
1725 // FIXME don't define USE_SCALAR_ET other then for testing
1726 // They do not work for complex types
1727         typedef expression_type result_type;
1728 #else
1729         typedef typename F::result_type result_type;
1730 #endif
1731     };
1732 
1733     // inner_prod (v1, v2) = sum (v1 [i] * v2 [i])
1734     template<class E1, class E2>
1735     BOOST_UBLAS_INLINE
1736     typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
1737                                                                    typename promote_traits<typename E1::value_type,
1738                                                                                            typename E2::value_type>::promote_type> >::result_type
1739     inner_prod (const vector_expression<E1> &e1,
1740                 const vector_expression<E2> &e2) {
1741         typedef typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
1742                                                                    typename promote_traits<typename E1::value_type,
1743                                                                                            typename E2::value_type>::promote_type> >::expression_type expression_type;
1744         return expression_type (e1 (), e2 ());
1745     }
1746 
1747     template<class E1, class E2>
1748     BOOST_UBLAS_INLINE
1749     typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
1750                                                                    typename type_traits<typename promote_traits<typename E1::value_type,
1751                                                                                                                 typename E2::value_type>::promote_type>::precision_type> >::result_type
1752     prec_inner_prod (const vector_expression<E1> &e1,
1753                      const vector_expression<E2> &e2) {
1754         typedef typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
1755                                                                    typename type_traits<typename promote_traits<typename E1::value_type,
1756                                                                                                                 typename E2::value_type>::promote_type>::precision_type> >::expression_type expression_type;
1757         return expression_type (e1 (), e2 ());
1758     }
1759 
1760 }}}
1761 
1762 #endif