1 //
2 //  Copyright (c) 2000-2002
3 //  Joerg Walter, Mathias Koch
4 //
5 //  Distributed under the Boost Software License, Version 1.0. (See
6 //  accompanying file LICENSE_1_0.txt or copy at
7 //  http://www.boost.org/LICENSE_1_0.txt)
8 //
9 //  The authors gratefully acknowledge the support of
10 //  GeNeSys mbH & Co. KG in producing this work.
11 //
12 
13 #ifndef _BOOST_UBLAS_VECTOR_EXPRESSION_
14 #define _BOOST_UBLAS_VECTOR_EXPRESSION_
15 
16 #include <boost/numeric/ublas/expression_types.hpp>
17 
18 
19 // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
20 // Iterators based on ideas of Jeremy Siek
21 //
22 // Classes that model the Vector Expression concept
23 
24 namespace boost { namespace numeric { namespace ublas {
25 
26     template<class E>
27     class vector_reference:
28         public vector_expression<vector_reference<E> > {
29 
30         typedef vector_reference<E> self_type;
31     public:
32 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
33         using vector_expression<vector_reference<E> >::operator ();
34 #endif
35         typedef typename E::size_type size_type;
36         typedef typename E::difference_type difference_type;
37         typedef typename E::value_type value_type;
38         typedef typename E::const_reference const_reference;
39         typedef typename boost::mpl::if_<boost::is_const<E>,
40                                           typename E::const_reference,
41                                           typename E::reference>::type reference;
42         typedef E referred_type;
43         typedef const self_type const_closure_type;
44         typedef self_type closure_type;
45         typedef typename E::storage_category storage_category;
46 
47         // Construction and destruction
48         BOOST_UBLAS_INLINE
vector_reference(referred_type & e)49         explicit vector_reference (referred_type &e):
50             e_ (e) {}
51 
52         // Accessors
53         BOOST_UBLAS_INLINE
size() const54         size_type size () const {
55             return expression ().size ();
56         }
57 
58     public:
59         // Expression accessors - const correct
60         BOOST_UBLAS_INLINE
expression() const61         const referred_type &expression () const {
62             return e_;
63         }
64         BOOST_UBLAS_INLINE
expression()65         referred_type &expression () {
66             return e_;
67         }
68 
69     public:
70         // Element access
71 #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
72         BOOST_UBLAS_INLINE
operator ()(size_type i) const73         const_reference operator () (size_type i) const {
74             return expression () (i);
75         }
76         BOOST_UBLAS_INLINE
operator ()(size_type i)77         reference operator () (size_type i) {
78             return expression () (i);
79         }
80 
81         BOOST_UBLAS_INLINE
operator [](size_type i) const82         const_reference operator [] (size_type i) const {
83             return expression () [i];
84         }
85         BOOST_UBLAS_INLINE
operator [](size_type i)86         reference operator [] (size_type i) {
87             return expression () [i];
88         }
89 #else
90         BOOST_UBLAS_INLINE
91         reference operator () (size_type i) const {
92             return expression () (i);
93         }
94 
95         BOOST_UBLAS_INLINE
96         reference operator [] (size_type i) const {
97             return expression () [i];
98         }
99 #endif
100 
101         // Assignment
102         BOOST_UBLAS_INLINE
operator =(const vector_reference & v)103         vector_reference &operator = (const vector_reference &v) {
104             expression ().operator = (v);
105             return *this;
106         }
107         template<class AE>
108         BOOST_UBLAS_INLINE
operator =(const vector_expression<AE> & ae)109         vector_reference &operator = (const vector_expression<AE> &ae) {
110             expression ().operator = (ae);
111             return *this;
112         }
113         template<class AE>
114         BOOST_UBLAS_INLINE
assign(const vector_expression<AE> & ae)115         vector_reference &assign (const vector_expression<AE> &ae) {
116             expression ().assign (ae);
117             return *this;
118         }
119         template<class AE>
120         BOOST_UBLAS_INLINE
operator +=(const vector_expression<AE> & ae)121         vector_reference &operator += (const vector_expression<AE> &ae) {
122             expression ().operator += (ae);
123             return *this;
124         }
125         template<class AE>
126         BOOST_UBLAS_INLINE
plus_assign(const vector_expression<AE> & ae)127         vector_reference &plus_assign (const vector_expression<AE> &ae) {
128             expression ().plus_assign (ae);
129             return *this;
130         }
131         template<class AE>
132         BOOST_UBLAS_INLINE
operator -=(const vector_expression<AE> & ae)133         vector_reference &operator -= (const vector_expression<AE> &ae) {
134             expression ().operator -= (ae);
135             return *this;
136         }
137         template<class AE>
138         BOOST_UBLAS_INLINE
minus_assign(const vector_expression<AE> & ae)139         vector_reference &minus_assign (const vector_expression<AE> &ae) {
140             expression ().minus_assign (ae);
141             return *this;
142         }
143         template<class AT>
144         BOOST_UBLAS_INLINE
operator *=(const AT & at)145         vector_reference &operator *= (const AT &at) {
146             expression ().operator *= (at);
147             return *this;
148         }
149         template<class AT>
150         BOOST_UBLAS_INLINE
operator /=(const AT & at)151         vector_reference &operator /= (const AT &at) {
152             expression ().operator /= (at);
153             return *this;
154         }
155 
156         // Swapping
157         BOOST_UBLAS_INLINE
swap(vector_reference & v)158         void swap (vector_reference &v) {
159             expression ().swap (v.expression ());
160         }
161 
162         // Closure comparison
163         BOOST_UBLAS_INLINE
same_closure(const vector_reference & vr) const164         bool same_closure (const vector_reference &vr) const {
165             return &(*this).e_ == &vr.e_;
166         }
167 
168         // Iterator types
169         typedef typename E::const_iterator const_iterator;
170         typedef typename boost::mpl::if_<boost::is_const<E>,
171                                           typename E::const_iterator,
172                                           typename E::iterator>::type iterator;
173 
174         // Element lookup
175         BOOST_UBLAS_INLINE
find(size_type i) const176         const_iterator find (size_type i) const {
177             return expression ().find (i);
178         }
179         BOOST_UBLAS_INLINE
find(size_type i)180         iterator find (size_type i) {
181             return expression ().find (i);
182         }
183 
184         // Iterator is the iterator of the referenced expression.
185 
186         BOOST_UBLAS_INLINE
begin() const187         const_iterator begin () const {
188             return expression ().begin ();
189         }
190         BOOST_UBLAS_INLINE
cbegin() const191         const_iterator cbegin () const {
192             return begin ();
193         }
194         BOOST_UBLAS_INLINE
end() const195         const_iterator end () const {
196             return expression ().end ();
197         }
198         BOOST_UBLAS_INLINE
cend() const199         const_iterator cend () const {
200             return end ();
201         }
202 
203         BOOST_UBLAS_INLINE
begin()204         iterator begin () {
205             return expression ().begin ();
206         }
207         BOOST_UBLAS_INLINE
end()208         iterator end () {
209             return expression ().end ();
210         }
211 
212         // Reverse iterator
213         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
214         typedef reverse_iterator_base<iterator> reverse_iterator;
215 
216         BOOST_UBLAS_INLINE
rbegin() const217         const_reverse_iterator rbegin () const {
218             return const_reverse_iterator (end ());
219         }
220         BOOST_UBLAS_INLINE
crbegin() const221         const_reverse_iterator crbegin () const {
222             return rbegin ();
223         }
224         BOOST_UBLAS_INLINE
rend() const225         const_reverse_iterator rend () const {
226             return const_reverse_iterator (begin ());
227         }
228         BOOST_UBLAS_INLINE
crend() const229         const_reverse_iterator crend () const {
230             return rend ();
231         }
232 
233         BOOST_UBLAS_INLINE
rbegin()234         reverse_iterator rbegin () {
235             return reverse_iterator (end ());
236         }
237         BOOST_UBLAS_INLINE
rend()238         reverse_iterator rend () {
239             return reverse_iterator (begin ());
240         }
241 
242     private:
243         referred_type &e_;
244     };
245 
246 
247     template<class E, class F>
248     class vector_unary:
249         public vector_expression<vector_unary<E, F> > {
250 
251         typedef F functor_type;
252         typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
253                                           E,
254                                           const E>::type expression_type;
255         typedef typename boost::mpl::if_<boost::is_const<expression_type>,
256                                           typename E::const_closure_type,
257                                           typename E::closure_type>::type expression_closure_type;
258         typedef vector_unary<E, F> self_type;
259     public:
260 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
261         using vector_expression<vector_unary<E, F> >::operator ();
262 #endif
263         typedef typename E::size_type size_type;
264         typedef typename E::difference_type difference_type;
265         typedef typename F::result_type value_type;
266         typedef value_type const_reference;
267         typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
268                                           typename E::reference,
269                                           value_type>::type reference;
270         typedef const self_type const_closure_type;
271         typedef self_type closure_type;
272         typedef unknown_storage_tag storage_category;
273 
274         // Construction and destruction
275         BOOST_UBLAS_INLINE
276         // May be used as mutable expression.
vector_unary(expression_type & e)277         explicit vector_unary (expression_type &e):
278             e_ (e) {}
279 
280         // Accessors
281         BOOST_UBLAS_INLINE
size() const282         size_type size () const {
283             return e_.size ();
284         }
285 
286     public:
287         // Expression accessors
288         BOOST_UBLAS_INLINE
expression() const289         const expression_closure_type &expression () const {
290             return e_;
291         }
292 
293     public:
294         // Element access
295         BOOST_UBLAS_INLINE
operator ()(size_type i) const296         const_reference operator () (size_type i) const {
297             return functor_type::apply (e_ (i));
298         }
299         BOOST_UBLAS_INLINE
operator ()(size_type i)300         reference operator () (size_type i) {
301             BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
302             return e_ (i);
303         }
304 
305         BOOST_UBLAS_INLINE
operator [](size_type i) const306         const_reference operator [] (size_type i) const {
307             return functor_type::apply (e_ [i]);
308         }
309         BOOST_UBLAS_INLINE
operator [](size_type i)310         reference operator [] (size_type i) {
311             BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
312             return e_ [i];
313         }
314 
315         // Closure comparison
316         BOOST_UBLAS_INLINE
same_closure(const vector_unary & vu) const317         bool same_closure (const vector_unary &vu) const {
318             return (*this).expression ().same_closure (vu.expression ());
319         }
320 
321         // Iterator types
322     private:
323         typedef typename E::const_iterator const_subiterator_type;
324         typedef const value_type *const_pointer;
325 
326     public:
327 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
328         typedef indexed_const_iterator<const_closure_type, typename const_subiterator_type::iterator_category> const_iterator;
329         typedef const_iterator iterator;
330 #else
331         class const_iterator;
332         typedef const_iterator iterator;
333 #endif
334 
335         // Element lookup
336         BOOST_UBLAS_INLINE
find(size_type i) const337         const_iterator find (size_type i) const {
338 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
339             const_subiterator_type it (e_.find (i));
340             return const_iterator (*this, it.index ());
341 #else
342             return const_iterator (*this, e_.find (i));
343 #endif
344         }
345 
346         // Iterator enhances the iterator of the referenced expression
347         // with the unary functor.
348 
349 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
350         class const_iterator:
351             public container_const_reference<vector_unary>,
352             public iterator_base_traits<typename E::const_iterator::iterator_category>::template
353                         iterator_base<const_iterator, value_type>::type {
354         public:
355             typedef typename E::const_iterator::iterator_category iterator_category;
356             typedef typename vector_unary::difference_type difference_type;
357             typedef typename vector_unary::value_type value_type;
358             typedef typename vector_unary::const_reference reference;
359             typedef typename vector_unary::const_pointer pointer;
360 
361             // Construction and destruction
362             BOOST_UBLAS_INLINE
const_iterator()363             const_iterator ():
364                 container_const_reference<self_type> (), it_ () {}
365             BOOST_UBLAS_INLINE
const_iterator(const self_type & vu,const const_subiterator_type & it)366             const_iterator (const self_type &vu, const const_subiterator_type &it):
367                 container_const_reference<self_type> (vu), it_ (it) {}
368 
369             // Arithmetic
370             BOOST_UBLAS_INLINE
operator ++()371             const_iterator &operator ++ () {
372                 ++ it_;
373                 return *this;
374             }
375             BOOST_UBLAS_INLINE
operator --()376             const_iterator &operator -- () {
377                 -- it_;
378                 return *this;
379             }
380             BOOST_UBLAS_INLINE
operator +=(difference_type n)381             const_iterator &operator += (difference_type n) {
382                 it_ += n;
383                 return *this;
384             }
385             BOOST_UBLAS_INLINE
operator -=(difference_type n)386             const_iterator &operator -= (difference_type n) {
387                 it_ -= n;
388                 return *this;
389             }
390             BOOST_UBLAS_INLINE
operator -(const const_iterator & it) const391             difference_type operator - (const const_iterator &it) const {
392                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
393                 return it_ - it.it_;
394             }
395 
396             // Dereference
397             BOOST_UBLAS_INLINE
operator *() const398             const_reference operator * () const {
399                 return functor_type::apply (*it_);
400             }
401             BOOST_UBLAS_INLINE
operator [](difference_type n) const402             const_reference operator [] (difference_type n) const {
403                 return *(*this + n);
404             }
405 
406             // Index
407             BOOST_UBLAS_INLINE
index() const408             size_type index () const {
409                 return it_.index ();
410             }
411 
412             // Assignment
413             BOOST_UBLAS_INLINE
operator =(const const_iterator & it)414             const_iterator &operator = (const const_iterator &it) {
415                 container_const_reference<self_type>::assign (&it ());
416                 it_ = it.it_;
417                 return *this;
418             }
419 
420             // Comparison
421             BOOST_UBLAS_INLINE
operator ==(const const_iterator & it) const422             bool operator == (const const_iterator &it) const {
423                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
424                 return it_ == it.it_;
425             }
426             BOOST_UBLAS_INLINE
operator <(const const_iterator & it) const427             bool operator < (const const_iterator &it) const {
428                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
429                 return it_ < it.it_;
430             }
431 
432         private:
433             const_subiterator_type it_;
434         };
435 #endif
436 
437         BOOST_UBLAS_INLINE
begin() const438         const_iterator begin () const {
439             return find (0);
440         }
441         BOOST_UBLAS_INLINE
cbegin() const442         const_iterator cbegin () const {
443             return begin ();
444         }
445         BOOST_UBLAS_INLINE
end() const446         const_iterator end () const {
447             return find (size ());
448         }
449         BOOST_UBLAS_INLINE
cend() const450         const_iterator cend () const {
451             return end ();
452         }
453 
454         // Reverse iterator
455         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
456 
457         BOOST_UBLAS_INLINE
rbegin() const458         const_reverse_iterator rbegin () const {
459             return const_reverse_iterator (end ());
460         }
461         BOOST_UBLAS_INLINE
crbegin() const462         const_reverse_iterator crbegin () const {
463             return rbegin ();
464         }
465         BOOST_UBLAS_INLINE
rend() const466         const_reverse_iterator rend () const {
467             return const_reverse_iterator (begin ());
468         }
469         BOOST_UBLAS_INLINE
crend() const470         const_reverse_iterator crend () const {
471             return rend ();
472         }
473 
474     private:
475         expression_closure_type e_;
476     };
477 
478     template<class E, class F>
479     struct vector_unary_traits {
480         typedef vector_unary<E, F> expression_type;
481 //FIXME
482 // #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
483         typedef expression_type result_type;
484 // #else
485 //         typedef typename E::vector_temporary_type result_type;
486 // #endif
487     };
488 
489     // (- v) [i] = - v [i]
490     template<class E>
491     BOOST_UBLAS_INLINE
492     typename vector_unary_traits<E, scalar_negate<typename E::value_type> >::result_type
operator -(const vector_expression<E> & e)493     operator - (const vector_expression<E> &e) {
494         typedef typename vector_unary_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
495         return expression_type (e ());
496     }
497 
498     // (conj v) [i] = conj (v [i])
499     template<class E>
500     BOOST_UBLAS_INLINE
501     typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::result_type
conj(const vector_expression<E> & e)502     conj (const vector_expression<E> &e) {
503         typedef typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
504         return expression_type (e ());
505     }
506 
507     // (real v) [i] = real (v [i])
508     template<class E>
509     BOOST_UBLAS_INLINE
510     typename vector_unary_traits<E, scalar_real<typename E::value_type> >::result_type
real(const vector_expression<E> & e)511     real (const vector_expression<E> &e) {
512         typedef typename vector_unary_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
513         return expression_type (e ());
514     }
515 
516     // (imag v) [i] = imag (v [i])
517     template<class E>
518     BOOST_UBLAS_INLINE
519     typename vector_unary_traits<E, scalar_imag<typename E::value_type> >::result_type
imag(const vector_expression<E> & e)520     imag (const vector_expression<E> &e) {
521         typedef typename vector_unary_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
522         return expression_type (e ());
523     }
524 
525     // (trans v) [i] = v [i]
526     template<class E>
527     BOOST_UBLAS_INLINE
528     typename vector_unary_traits<const E, scalar_identity<typename E::value_type> >::result_type
trans(const vector_expression<E> & e)529     trans (const vector_expression<E> &e) {
530         typedef typename vector_unary_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
531         return expression_type (e ());
532     }
533     template<class E>
534     BOOST_UBLAS_INLINE
535     typename vector_unary_traits<E, scalar_identity<typename E::value_type> >::result_type
trans(vector_expression<E> & e)536     trans (vector_expression<E> &e) {
537         typedef typename vector_unary_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
538         return expression_type (e ());
539     }
540 
541     // (herm v) [i] = conj (v [i])
542     template<class E>
543     BOOST_UBLAS_INLINE
544     typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::result_type
herm(const vector_expression<E> & e)545     herm (const vector_expression<E> &e) {
546         typedef typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
547         return expression_type (e ());
548     }
549 
550     template<class E1, class E2, class F>
551     class vector_binary:
552         public vector_expression<vector_binary<E1, E2, F> > {
553 
554         typedef E1 expression1_type;
555         typedef E2 expression2_type;
556         typedef F functor_type;
557         typedef typename E1::const_closure_type expression1_closure_type;
558         typedef typename E2::const_closure_type expression2_closure_type;
559         typedef vector_binary<E1, E2, F> self_type;
560     public:
561 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
562         using vector_expression<vector_binary<E1, E2, F> >::operator ();
563 #endif
564         typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
565         typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
566         typedef typename F::result_type value_type;
567         typedef value_type const_reference;
568         typedef const_reference reference;
569         typedef const self_type const_closure_type;
570         typedef const_closure_type closure_type;
571         typedef unknown_storage_tag storage_category;
572 
573         // Construction and destruction
574         BOOST_UBLAS_INLINE
vector_binary(const expression1_type & e1,const expression2_type & e2)575         vector_binary (const expression1_type &e1, const expression2_type &e2):
576             e1_ (e1), e2_ (e2) {}
577 
578         // Accessors
579         BOOST_UBLAS_INLINE
size() const580         size_type size () const {
581             return BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
582         }
583 
584     private:
585         // Accessors
586         BOOST_UBLAS_INLINE
expression1() const587         const expression1_closure_type &expression1 () const {
588             return e1_;
589         }
590         BOOST_UBLAS_INLINE
expression2() const591         const expression2_closure_type &expression2 () const {
592             return e2_;
593         }
594 
595     public:
596         // Element access
597         BOOST_UBLAS_INLINE
operator ()(size_type i) const598         const_reference operator () (size_type i) const {
599             return functor_type::apply (e1_ (i), e2_ (i));
600         }
601 
602         BOOST_UBLAS_INLINE
operator [](size_type i) const603         const_reference operator [] (size_type i) const {
604             return functor_type::apply (e1_ [i], e2_ [i]);
605         }
606 
607         // Closure comparison
608         BOOST_UBLAS_INLINE
same_closure(const vector_binary & vb) const609         bool same_closure (const vector_binary &vb) const {
610             return (*this).expression1 ().same_closure (vb.expression1 ()) &&
611                    (*this).expression2 ().same_closure (vb.expression2 ());
612         }
613 
614         // Iterator types
615     private:
616         typedef typename E1::const_iterator const_subiterator1_type;
617         typedef typename E2::const_iterator const_subiterator2_type;
618         typedef const value_type *const_pointer;
619 
620     public:
621 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
622         typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
623                                                   typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
624         typedef indexed_const_iterator<const_closure_type, iterator_category> const_iterator;
625         typedef const_iterator iterator;
626 #else
627         class const_iterator;
628         typedef const_iterator iterator;
629 #endif
630 
631         // Element lookup
632         BOOST_UBLAS_INLINE
find(size_type i) const633         const_iterator find (size_type i) const {
634             const_subiterator1_type it1 (e1_.find (i));
635             const_subiterator1_type it1_end (e1_.find (size ()));
636             const_subiterator2_type it2 (e2_.find (i));
637             const_subiterator2_type it2_end (e2_.find (size ()));
638             i = (std::min) (it1 != it1_end ? it1.index () : size (),
639                           it2 != it2_end ? it2.index () : size ());
640 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
641             return const_iterator (*this, i);
642 #else
643             return const_iterator (*this, i, it1, it1_end, it2, it2_end);
644 #endif
645         }
646 
647         // Iterator merges the iterators of the referenced expressions and
648         // enhances them with the binary functor.
649 
650 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
651         class const_iterator:
652             public container_const_reference<vector_binary>,
653             public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
654                                                                           typename E2::const_iterator::iterator_category>::iterator_category>::template
655                         iterator_base<const_iterator, value_type>::type {
656         public:
657             typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
658                                                       typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
659             typedef typename vector_binary::difference_type difference_type;
660             typedef typename vector_binary::value_type value_type;
661             typedef typename vector_binary::const_reference reference;
662             typedef typename vector_binary::const_pointer pointer;
663 
664             // Construction and destruction
665             BOOST_UBLAS_INLINE
const_iterator()666             const_iterator ():
667                 container_const_reference<self_type> (), i_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
668             BOOST_UBLAS_INLINE
const_iterator(const self_type & vb,size_type i,const const_subiterator1_type & it1,const const_subiterator1_type & it1_end,const const_subiterator2_type & it2,const const_subiterator2_type & it2_end)669             const_iterator (const self_type &vb, size_type i,
670                             const const_subiterator1_type &it1, const const_subiterator1_type &it1_end,
671                             const const_subiterator2_type &it2, const const_subiterator2_type &it2_end):
672                 container_const_reference<self_type> (vb), i_ (i), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
673 
674         private:
675             // Dense specializations
676             BOOST_UBLAS_INLINE
increment(dense_random_access_iterator_tag)677             void increment (dense_random_access_iterator_tag) {
678                 ++ i_; ++ it1_; ++ it2_;
679             }
680             BOOST_UBLAS_INLINE
decrement(dense_random_access_iterator_tag)681             void decrement (dense_random_access_iterator_tag) {
682                 -- i_; -- it1_; -- it2_;
683             }
684             BOOST_UBLAS_INLINE
increment(dense_random_access_iterator_tag,difference_type n)685             void increment (dense_random_access_iterator_tag, difference_type n) {
686                 i_ += n; it1_ += n; it2_ += n;
687             }
688             BOOST_UBLAS_INLINE
decrement(dense_random_access_iterator_tag,difference_type n)689             void decrement (dense_random_access_iterator_tag, difference_type n) {
690                 i_ -= n; it1_ -= n; it2_ -= n;
691             }
692             BOOST_UBLAS_INLINE
dereference(dense_random_access_iterator_tag) const693             value_type dereference (dense_random_access_iterator_tag) const {
694                 return functor_type::apply (*it1_, *it2_);
695             }
696 
697             // Packed specializations
698             BOOST_UBLAS_INLINE
increment(packed_random_access_iterator_tag)699             void increment (packed_random_access_iterator_tag) {
700                 if (it1_ != it1_end_)
701                     if (it1_.index () <= i_)
702                         ++ it1_;
703                 if (it2_ != it2_end_)
704                     if (it2_.index () <= i_)
705                         ++ it2_;
706                 ++ i_;
707             }
708             BOOST_UBLAS_INLINE
decrement(packed_random_access_iterator_tag)709             void decrement (packed_random_access_iterator_tag) {
710                 if (it1_ != it1_end_)
711                     if (i_ <= it1_.index ())
712                         -- it1_;
713                 if (it2_ != it2_end_)
714                     if (i_ <= it2_.index ())
715                         -- it2_;
716                 -- i_;
717             }
718             BOOST_UBLAS_INLINE
increment(packed_random_access_iterator_tag,difference_type n)719             void increment (packed_random_access_iterator_tag, difference_type n) {
720                 while (n > 0) {
721                     increment (packed_random_access_iterator_tag ());
722                     --n;
723                 }
724                 while (n < 0) {
725                     decrement (packed_random_access_iterator_tag ());
726                     ++n;
727                 }
728             }
729             BOOST_UBLAS_INLINE
decrement(packed_random_access_iterator_tag,difference_type n)730             void decrement (packed_random_access_iterator_tag, difference_type n) {
731                 while (n > 0) {
732                     decrement (packed_random_access_iterator_tag ());
733                     --n;
734                 }
735                 while (n < 0) {
736                     increment (packed_random_access_iterator_tag ());
737                     ++n;
738                 }
739             }
740             BOOST_UBLAS_INLINE
dereference(packed_random_access_iterator_tag) const741             value_type dereference (packed_random_access_iterator_tag) const {
742                 typename E1::value_type t1 = typename E1::value_type/*zero*/();
743                 if (it1_ != it1_end_)
744                     if (it1_.index () == i_)
745                         t1 = *it1_;
746                 typename E2::value_type t2 = typename E2::value_type/*zero*/();
747                 if (it2_ != it2_end_)
748                     if (it2_.index () == i_)
749                         t2 = *it2_;
750                 return functor_type::apply (t1, t2);
751             }
752 
753             // Sparse specializations
754             BOOST_UBLAS_INLINE
increment(sparse_bidirectional_iterator_tag)755             void increment (sparse_bidirectional_iterator_tag) {
756                 size_type index1 = (*this) ().size ();
757                 if (it1_ != it1_end_) {
758                     if  (it1_.index () <= i_)
759                         ++ it1_;
760                     if (it1_ != it1_end_)
761                         index1 = it1_.index ();
762                 }
763                 size_type index2 = (*this) ().size ();
764                 if (it2_ != it2_end_) {
765                     if (it2_.index () <= i_)
766                         ++ it2_;
767                     if (it2_ != it2_end_)
768                         index2 = it2_.index ();
769                 }
770                 i_ = (std::min) (index1, index2);
771             }
772             BOOST_UBLAS_INLINE
decrement(sparse_bidirectional_iterator_tag)773             void decrement (sparse_bidirectional_iterator_tag) {
774                 size_type index1 = (*this) ().size ();
775                 if (it1_ != it1_end_) {
776                     if (i_ <= it1_.index ())
777                         -- it1_;
778                     if (it1_ != it1_end_)
779                         index1 = it1_.index ();
780                 }
781                 size_type index2 = (*this) ().size ();
782                 if (it2_ != it2_end_) {
783                     if (i_ <= it2_.index ())
784                         -- it2_;
785                     if (it2_ != it2_end_)
786                         index2 = it2_.index ();
787                 }
788                 i_ = (std::max) (index1, index2);
789             }
790             BOOST_UBLAS_INLINE
increment(sparse_bidirectional_iterator_tag,difference_type n)791             void increment (sparse_bidirectional_iterator_tag, difference_type n) {
792                 while (n > 0) {
793                     increment (sparse_bidirectional_iterator_tag ());
794                     --n;
795                 }
796                 while (n < 0) {
797                     decrement (sparse_bidirectional_iterator_tag ());
798                     ++n;
799                 }
800             }
801             BOOST_UBLAS_INLINE
decrement(sparse_bidirectional_iterator_tag,difference_type n)802             void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
803                 while (n > 0) {
804                     decrement (sparse_bidirectional_iterator_tag ());
805                     --n;
806                 }
807                 while (n < 0) {
808                     increment (sparse_bidirectional_iterator_tag ());
809                     ++n;
810                 }
811             }
812             BOOST_UBLAS_INLINE
dereference(sparse_bidirectional_iterator_tag) const813             value_type dereference (sparse_bidirectional_iterator_tag) const {
814                 typename E1::value_type t1 = typename E1::value_type/*zero*/();
815                 if (it1_ != it1_end_)
816                     if (it1_.index () == i_)
817                         t1 = *it1_;
818                 typename E2::value_type t2 = typename E2::value_type/*zero*/();
819                 if (it2_ != it2_end_)
820                     if (it2_.index () == i_)
821                         t2 = *it2_;
822                 return static_cast<value_type>(functor_type::apply (t1, t2));
823             }
824 
825         public:
826             // Arithmetic
827             BOOST_UBLAS_INLINE
operator ++()828             const_iterator &operator ++ () {
829                 increment (iterator_category ());
830                 return *this;
831             }
832             BOOST_UBLAS_INLINE
operator --()833             const_iterator &operator -- () {
834                 decrement (iterator_category ());
835                 return *this;
836             }
837             BOOST_UBLAS_INLINE
operator +=(difference_type n)838             const_iterator &operator += (difference_type n) {
839                 increment (iterator_category (), n);
840                 return *this;
841             }
842             BOOST_UBLAS_INLINE
operator -=(difference_type n)843             const_iterator &operator -= (difference_type n) {
844                 decrement (iterator_category (), n);
845                 return *this;
846             }
847             BOOST_UBLAS_INLINE
operator -(const const_iterator & it) const848             difference_type operator - (const const_iterator &it) const {
849                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
850                 return index () - it.index ();
851             }
852 
853             // Dereference
854             BOOST_UBLAS_INLINE
operator *() const855             const_reference operator * () const {
856                 return dereference (iterator_category ());
857             }
858             BOOST_UBLAS_INLINE
operator [](difference_type n) const859             const_reference operator [] (difference_type n) const {
860                 return *(*this + n);
861             }
862 
863             // Index
864             BOOST_UBLAS_INLINE
index() const865             size_type index () const {
866                 return i_;
867             }
868 
869             // Assignment
870             BOOST_UBLAS_INLINE
operator =(const const_iterator & it)871             const_iterator &operator = (const const_iterator &it) {
872                 container_const_reference<self_type>::assign (&it ());
873                 i_ = it.i_;
874                 it1_ = it.it1_;
875                 it1_end_ = it.it1_end_;
876                 it2_ = it.it2_;
877                 it2_end_ = it.it2_end_;
878                 return *this;
879             }
880 
881             // Comparison
882             BOOST_UBLAS_INLINE
operator ==(const const_iterator & it) const883             bool operator == (const const_iterator &it) const {
884                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
885                 return index () == it.index ();
886             }
887             BOOST_UBLAS_INLINE
operator <(const const_iterator & it) const888             bool operator < (const const_iterator &it) const {
889                 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
890                 return index () < it.index ();
891             }
892 
893         private:
894             size_type i_;
895             const_subiterator1_type it1_;
896             const_subiterator1_type it1_end_;
897             const_subiterator2_type it2_;
898             const_subiterator2_type it2_end_;
899         };
900 #endif
901 
902         BOOST_UBLAS_INLINE
begin() const903         const_iterator begin () const {
904             return find (0);
905         }
906         BOOST_UBLAS_INLINE
cbegin() const907         const_iterator cbegin () const {
908             return begin ();
909         }
910         BOOST_UBLAS_INLINE
end() const911         const_iterator end () const {
912             return find (size ());
913         }
914         BOOST_UBLAS_INLINE
cend() const915         const_iterator cend () const {
916             return end ();
917         }
918 
919         // Reverse iterator
920         typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
921 
922         BOOST_UBLAS_INLINE
rbegin() const923         const_reverse_iterator rbegin () const {
924             return const_reverse_iterator (end ());
925         }
926         BOOST_UBLAS_INLINE
crbegin() const927         const_reverse_iterator crbegin () const {
928             return rbegin ();
929         }
930         BOOST_UBLAS_INLINE
rend() const931         const_reverse_iterator rend () const {
932             return const_reverse_iterator (begin ());
933         }
934         BOOST_UBLAS_INLINE
crend() const935         const_reverse_iterator crend () const {
936             return rend ();
937         }
938 
939     private:
940         expression1_closure_type e1_;
941         expression2_closure_type e2_;
942     };
943 
944     template<class E1, class E2, class F>
945     struct vector_binary_traits {
946         typedef vector_binary<E1, E2, F> expression_type;
947 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
948         typedef expression_type result_type;
949 #else
950         typedef typename E1::vector_temporary_type result_type;
951 #endif
952     };
953 
954     // (v1 + v2) [i] = v1 [i] + v2 [i]
955     template<class E1, class E2>
956     BOOST_UBLAS_INLINE
957     typename vector_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
958                                                       typename E2::value_type> >::result_type
operator +(const vector_expression<E1> & e1,const vector_expression<E2> & e2)959     operator + (const vector_expression<E1> &e1,
960                 const vector_expression<E2> &e2) {
961         typedef typename vector_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
962                                                                               typename E2::value_type> >::expression_type expression_type;
963         return expression_type (e1 (), e2 ());
964     }
965 
966     // (v1 - v2) [i] = v1 [i] - v2 [i]
967     template<class E1, class E2>
968     BOOST_UBLAS_INLINE
969     typename vector_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
970                                                        typename E2::value_type> >::result_type
operator -(const vector_expression<E1> & e1,const vector_expression<E2> & e2)971     operator - (const vector_expression<E1> &e1,
972                 const vector_expression<E2> &e2) {
973         typedef typename vector_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
974                                                                                typename E2::value_type> >::expression_type expression_type;
975         return expression_type (e1 (), e2 ());
976     }
977 
978     // (v1 * v2) [i] = v1 [i] * v2 [i]
979     template<class E1, class E2>
980     BOOST_UBLAS_INLINE
981     typename vector_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
982                                                             typename E2::value_type> >::result_type
element_prod(const vector_expression<E1> & e1,const vector_expression<E2> & e2)983     element_prod (const vector_expression<E1> &e1,
984                   const vector_expression<E2> &e2) {
985         typedef typename vector_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
986                                                                                     typename E2::value_type> >::expression_type expression_type;
987         return expression_type (e1 (), e2 ());
988     }
989 
990     // (v1 / v2) [i] = v1 [i] / v2 [i]
991     template<class E1, class E2>
992     BOOST_UBLAS_INLINE
993     typename vector_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
994                                                          typename E2::value_type> >::result_type
element_div(const vector_expression<E1> & e1,const vector_expression<E2> & e2)995     element_div (const vector_expression<E1> &e1,
996                  const vector_expression<E2> &e2) {
997         typedef typename vector_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
998                                                                                  typename E2::value_type> >::expression_type expression_type;
999         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
vector_binary_scalar1(const expression1_type & e1,const expression2_type & e2)1030         vector_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
1031             e1_ (e1), e2_ (e2) {}
1032 
1033         // Accessors
1034         BOOST_UBLAS_INLINE
size() const1035         size_type size () const {
1036             return e2_.size ();
1037         }
1038 
1039     public:
1040         // Element access
1041         BOOST_UBLAS_INLINE
operator ()(size_type i) const1042         const_reference operator () (size_type i) const {
1043             return functor_type::apply (e1_, e2_ (i));
1044         }
1045 
1046         BOOST_UBLAS_INLINE
operator [](size_type i) const1047         const_reference operator [] (size_type i) const {
1048             return functor_type::apply (e1_, e2_ [i]);
1049         }
1050 
1051         // Closure comparison
1052         BOOST_UBLAS_INLINE
same_closure(const vector_binary_scalar1 & vbs1) const1053         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
find(size_type i) const1075         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
const_iterator()1101             const_iterator ():
1102                 container_const_reference<self_type> (), it1_ (), it2_ () {}
1103             BOOST_UBLAS_INLINE
const_iterator(const self_type & vbs,const const_subiterator1_type & it1,const const_subiterator2_type & it2)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
operator ++()1109             const_iterator &operator ++ () {
1110                 ++ it2_;
1111                 return *this;
1112             }
1113             BOOST_UBLAS_INLINE
operator --()1114             const_iterator &operator -- () {
1115                 -- it2_;
1116                 return *this;
1117             }
1118             BOOST_UBLAS_INLINE
operator +=(difference_type n)1119             const_iterator &operator += (difference_type n) {
1120                 it2_ += n;
1121                 return *this;
1122             }
1123             BOOST_UBLAS_INLINE
operator -=(difference_type n)1124             const_iterator &operator -= (difference_type n) {
1125                 it2_ -= n;
1126                 return *this;
1127             }
1128             BOOST_UBLAS_INLINE
operator -(const const_iterator & it) const1129             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
operator *() const1138             const_reference operator * () const {
1139                 return functor_type::apply (it1_, *it2_);
1140             }
1141             BOOST_UBLAS_INLINE
operator [](difference_type n) const1142             const_reference operator [] (difference_type n) const {
1143                 return *(*this + n);
1144             }
1145 
1146             // Index
1147             BOOST_UBLAS_INLINE
index() const1148             size_type index () const {
1149                 return it2_.index ();
1150             }
1151 
1152             // Assignment
1153             BOOST_UBLAS_INLINE
operator =(const const_iterator & it)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
operator ==(const const_iterator & it) const1163             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
operator <(const const_iterator & it) const1170             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
begin() const1184         const_iterator begin () const {
1185             return find (0);
1186         }
1187         BOOST_UBLAS_INLINE
cbegin() const1188         const_iterator cbegin () const {
1189             return begin ();
1190         }
1191         BOOST_UBLAS_INLINE
end() const1192         const_iterator end () const {
1193             return find (size ());
1194         }
1195         BOOST_UBLAS_INLINE
cend() const1196         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
rbegin() const1204         const_reverse_iterator rbegin () const {
1205             return const_reverse_iterator (end ());
1206         }
1207         BOOST_UBLAS_INLINE
crbegin() const1208         const_reverse_iterator crbegin () const {
1209             return rbegin ();
1210         }
1211         BOOST_UBLAS_INLINE
rend() const1212         const_reverse_iterator rend () const {
1213             return const_reverse_iterator (begin ());
1214         }
1215         BOOST_UBLAS_INLINE
crend() const1216         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
operator *(const T1 & e1,const vector_expression<E2> & e2)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
vector_binary_scalar2(const expression1_type & e1,const expression2_type & e2)1273         vector_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
1274             e1_ (e1), e2_ (e2) {}
1275 
1276         // Accessors
1277         BOOST_UBLAS_INLINE
size() const1278         size_type size () const {
1279             return e1_.size ();
1280         }
1281 
1282     public:
1283         // Element access
1284         BOOST_UBLAS_INLINE
operator ()(size_type i) const1285         const_reference operator () (size_type i) const {
1286             return functor_type::apply (e1_ (i), e2_);
1287         }
1288 
1289         BOOST_UBLAS_INLINE
operator [](size_type i) const1290         const_reference operator [] (size_type i) const {
1291             return functor_type::apply (e1_ [i], e2_);
1292         }
1293 
1294         // Closure comparison
1295         BOOST_UBLAS_INLINE
same_closure(const vector_binary_scalar2 & vbs2) const1296         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
find(size_type i) const1318         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
const_iterator()1344             const_iterator ():
1345                 container_const_reference<self_type> (), it1_ (), it2_ () {}
1346             BOOST_UBLAS_INLINE
const_iterator(const self_type & vbs,const const_subiterator1_type & it1,const const_subiterator2_type & it2)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
operator ++()1352             const_iterator &operator ++ () {
1353                 ++ it1_;
1354                 return *this;
1355             }
1356             BOOST_UBLAS_INLINE
operator --()1357             const_iterator &operator -- () {
1358                 -- it1_;
1359                 return *this;
1360             }
1361             BOOST_UBLAS_INLINE
operator +=(difference_type n)1362             const_iterator &operator += (difference_type n) {
1363                 it1_ += n;
1364                 return *this;
1365             }
1366             BOOST_UBLAS_INLINE
operator -=(difference_type n)1367             const_iterator &operator -= (difference_type n) {
1368                 it1_ -= n;
1369                 return *this;
1370             }
1371             BOOST_UBLAS_INLINE
operator -(const const_iterator & it) const1372             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
operator *() const1381             const_reference operator * () const {
1382                 return functor_type::apply (*it1_, it2_);
1383             }
1384             BOOST_UBLAS_INLINE
operator [](difference_type n) const1385             const_reference operator [] (difference_type n) const {
1386                 return *(*this + n);
1387             }
1388 
1389             // Index
1390             BOOST_UBLAS_INLINE
index() const1391             size_type index () const {
1392                 return it1_.index ();
1393             }
1394 
1395             // Assignment
1396             BOOST_UBLAS_INLINE
operator =(const const_iterator & it)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
operator ==(const const_iterator & it) const1406             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
operator <(const const_iterator & it) const1413             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
begin() const1427         const_iterator begin () const {
1428             return find (0);
1429         }
1430         BOOST_UBLAS_INLINE
cbegin() const1431         const_iterator cbegin () const {
1432             return begin ();
1433         }
1434         BOOST_UBLAS_INLINE
end() const1435         const_iterator end () const {
1436             return find (size ());
1437         }
1438         BOOST_UBLAS_INLINE
cend() const1439         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
rbegin() const1447         const_reverse_iterator rbegin () const {
1448             return const_reverse_iterator (end ());
1449         }
1450         BOOST_UBLAS_INLINE
crbegin() const1451         const_reverse_iterator crbegin () const {
1452             return rbegin ();
1453         }
1454         BOOST_UBLAS_INLINE
rend() const1455         const_reverse_iterator rend () const {
1456             return const_reverse_iterator (begin ());
1457         }
1458         BOOST_UBLAS_INLINE
crend() const1459         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
operator *(const vector_expression<E1> & e1,const T2 & e2)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
operator /(const vector_expression<E1> & e1,const T2 & e2)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
vector_scalar_unary(const expression_type & e)1521         explicit vector_scalar_unary (const expression_type &e):
1522             e_ (e) {}
1523 
1524     private:
1525         // Expression accessors
1526         BOOST_UBLAS_INLINE
expression() const1527         const expression_closure_type &expression () const {
1528             return e_;
1529         }
1530 
1531     public:
1532         BOOST_UBLAS_INLINE
operator value_type() const1533         operator value_type () const {
1534             return evaluate (iterator_category ());
1535         }
1536 
1537     private:
1538         // Dense random access specialization
1539         BOOST_UBLAS_INLINE
evaluate(dense_random_access_iterator_tag) const1540         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
evaluate(packed_random_access_iterator_tag) const1557         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
evaluate(sparse_bidirectional_iterator_tag) const1563         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
sum(const vector_expression<E> & e)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
norm_1(const vector_expression<E> & e)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
norm_2(const vector_expression<E> & e)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
norm_2_square(const vector_expression<E> & e)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
norm_inf(const vector_expression<E> & e)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
index_norm_inf(const vector_expression<E> & e)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
vector_scalar_binary(const expression1_type & e1,const expression2_type & e2)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
expression1() const1669         const expression1_closure_type &expression1 () const {
1670             return e1_;
1671         }
1672         BOOST_UBLAS_INLINE
expression2() const1673         const expression2_closure_type &expression2 () const {
1674             return e2_;
1675         }
1676 
1677     public:
1678         BOOST_UBLAS_INLINE
operator value_type() const1679         operator value_type () const {
1680             return evaluate (iterator_category ());
1681         }
1682 
1683     private:
1684         // Dense random access specialization
1685         BOOST_UBLAS_INLINE
evaluate(dense_random_access_iterator_tag) const1686         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
evaluate(packed_random_access_iterator_tag) const1704         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
evaluate(sparse_bidirectional_iterator_tag) const1711         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
inner_prod(const vector_expression<E1> & e1,const vector_expression<E2> & e2)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
prec_inner_prod(const vector_expression<E1> & e1,const vector_expression<E2> & e2)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
1763