New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
vector_expression.hpp in vendors/XIOS/current/extern/boost/include/boost/numeric/ublas – NEMO

source: vendors/XIOS/current/extern/boost/include/boost/numeric/ublas/vector_expression.hpp @ 3428

Last change on this file since 3428 was 3428, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

File size: 61.5 KB
Line 
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
24namespace 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
49        explicit vector_reference (referred_type &e):
50            e_ (e) {}
51
52        // Accessors
53        BOOST_UBLAS_INLINE
54        size_type size () const {
55            return expression ().size ();
56        }
57
58    public:
59        // Expression accessors - const correct
60        BOOST_UBLAS_INLINE
61        const referred_type &expression () const {
62            return e_;
63        }
64        BOOST_UBLAS_INLINE
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
73        const_reference operator () (size_type i) const {
74            return expression () (i);
75        }
76        BOOST_UBLAS_INLINE
77        reference operator () (size_type i) {
78            return expression () (i);
79        }
80
81        BOOST_UBLAS_INLINE
82        const_reference operator [] (size_type i) const {
83            return expression () [i];
84        }
85        BOOST_UBLAS_INLINE
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
103        vector_reference &operator = (const vector_reference &v) {
104            expression ().operator = (v);
105            return *this;
106        }
107        template<class AE>
108        BOOST_UBLAS_INLINE
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
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
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
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
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
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
145        vector_reference &operator *= (const AT &at) {
146            expression ().operator *= (at);
147            return *this;
148        }
149        template<class AT>
150        BOOST_UBLAS_INLINE
151        vector_reference &operator /= (const AT &at) {
152            expression ().operator /= (at);
153            return *this;
154        }
155
156        // Swapping
157        BOOST_UBLAS_INLINE
158        void swap (vector_reference &v) {
159            expression ().swap (v.expression ());
160        }
161
162        // Closure comparison
163        BOOST_UBLAS_INLINE
164        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
176        const_iterator find (size_type i) const {
177            return expression ().find (i);
178        }
179        BOOST_UBLAS_INLINE
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
187        const_iterator begin () const {
188            return expression ().begin ();
189        }
190        BOOST_UBLAS_INLINE
191        const_iterator end () const {
192            return expression ().end ();
193        }
194
195        BOOST_UBLAS_INLINE
196        iterator begin () {
197            return expression ().begin ();
198        }
199        BOOST_UBLAS_INLINE
200        iterator end () {
201            return expression ().end ();
202        }
203
204        // Reverse iterator
205        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
206        typedef reverse_iterator_base<iterator> reverse_iterator;
207
208        BOOST_UBLAS_INLINE
209        const_reverse_iterator rbegin () const {
210            return const_reverse_iterator (end ());
211        }
212        BOOST_UBLAS_INLINE
213        const_reverse_iterator rend () const {
214            return const_reverse_iterator (begin ());
215        }
216        BOOST_UBLAS_INLINE
217        reverse_iterator rbegin () {
218            return reverse_iterator (end ());
219        }
220        BOOST_UBLAS_INLINE
221        reverse_iterator rend () {
222            return reverse_iterator (begin ());
223        }
224
225    private:
226        referred_type &e_;
227    };
228
229
230    template<class E, class F>
231    class vector_unary:
232        public vector_expression<vector_unary<E, F> > {
233
234        typedef F functor_type;
235        typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<typename E::value_type> >,
236                                          E,
237                                          const E>::type expression_type;
238        typedef typename boost::mpl::if_<boost::is_const<expression_type>,
239                                          typename E::const_closure_type,
240                                          typename E::closure_type>::type expression_closure_type;
241        typedef vector_unary<E, F> self_type;
242    public:
243#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
244        using vector_expression<vector_unary<E, F> >::operator ();
245#endif
246        typedef typename E::size_type size_type;
247        typedef typename E::difference_type difference_type;
248        typedef typename F::result_type value_type;
249        typedef value_type const_reference;
250        typedef typename boost::mpl::if_<boost::is_same<F, scalar_identity<value_type> >,
251                                          typename E::reference,
252                                          value_type>::type reference;
253        typedef const self_type const_closure_type;
254        typedef self_type closure_type;
255        typedef unknown_storage_tag storage_category;
256
257        // Construction and destruction
258        BOOST_UBLAS_INLINE
259        // May be used as mutable expression.
260        explicit vector_unary (expression_type &e):
261            e_ (e) {}
262
263        // Accessors
264        BOOST_UBLAS_INLINE
265        size_type size () const {
266            return e_.size ();
267        }
268
269    public:
270        // Expression accessors
271        BOOST_UBLAS_INLINE
272        const expression_closure_type &expression () const {
273            return e_;
274        }
275
276    public:
277        // Element access
278        BOOST_UBLAS_INLINE
279        const_reference operator () (size_type i) const {
280            return functor_type::apply (e_ (i));
281        }
282        BOOST_UBLAS_INLINE
283        reference operator () (size_type i) {
284            BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
285            return e_ (i);
286        }
287
288        BOOST_UBLAS_INLINE
289        const_reference operator [] (size_type i) const {
290            return functor_type::apply (e_ [i]);
291        }
292        BOOST_UBLAS_INLINE
293        reference operator [] (size_type i) {
294            BOOST_STATIC_ASSERT ((boost::is_same<functor_type, scalar_identity<value_type > >::value));
295            return e_ [i];
296        }
297
298        // Closure comparison
299        BOOST_UBLAS_INLINE
300        bool same_closure (const vector_unary &vu) const {
301            return (*this).expression ().same_closure (vu.expression ());
302        }
303
304        // Iterator types
305    private:
306        typedef typename E::const_iterator const_subiterator_type;
307        typedef const value_type *const_pointer;
308
309    public:
310#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
311        typedef indexed_const_iterator<const_closure_type, typename const_subiterator_type::iterator_category> const_iterator;
312        typedef const_iterator iterator;
313#else
314        class const_iterator;
315        typedef const_iterator iterator;
316#endif
317
318        // Element lookup
319        BOOST_UBLAS_INLINE
320        const_iterator find (size_type i) const {
321#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
322            const_subiterator_type it (e_.find (i));
323            return const_iterator (*this, it.index ());
324#else
325            return const_iterator (*this, e_.find (i));
326#endif
327        }
328
329        // Iterator enhances the iterator of the referenced expression
330        // with the unary functor.
331
332#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
333        class const_iterator:
334            public container_const_reference<vector_unary>,
335            public iterator_base_traits<typename E::const_iterator::iterator_category>::template
336                        iterator_base<const_iterator, value_type>::type {
337        public:
338            typedef typename E::const_iterator::iterator_category iterator_category;
339            typedef typename vector_unary::difference_type difference_type;
340            typedef typename vector_unary::value_type value_type;
341            typedef typename vector_unary::const_reference reference;
342            typedef typename vector_unary::const_pointer pointer;
343
344            // Construction and destruction
345            BOOST_UBLAS_INLINE
346            const_iterator ():
347                container_const_reference<self_type> (), it_ () {}
348            BOOST_UBLAS_INLINE
349            const_iterator (const self_type &vu, const const_subiterator_type &it):
350                container_const_reference<self_type> (vu), it_ (it) {}
351
352            // Arithmetic
353            BOOST_UBLAS_INLINE
354            const_iterator &operator ++ () {
355                ++ it_;
356                return *this;
357            }
358            BOOST_UBLAS_INLINE
359            const_iterator &operator -- () {
360                -- it_;
361                return *this;
362            }
363            BOOST_UBLAS_INLINE
364            const_iterator &operator += (difference_type n) {
365                it_ += n;
366                return *this;
367            }
368            BOOST_UBLAS_INLINE
369            const_iterator &operator -= (difference_type n) {
370                it_ -= n;
371                return *this;
372            }
373            BOOST_UBLAS_INLINE
374            difference_type operator - (const const_iterator &it) const {
375                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
376                return it_ - it.it_;
377            }
378
379            // Dereference
380            BOOST_UBLAS_INLINE
381            const_reference operator * () const {
382                return functor_type::apply (*it_);
383            }
384            BOOST_UBLAS_INLINE
385            const_reference operator [] (difference_type n) const {
386                return *(*this + n);
387            }
388
389            // Index
390            BOOST_UBLAS_INLINE
391            size_type index () const {
392                return it_.index ();
393            }
394
395            // Assignment
396            BOOST_UBLAS_INLINE
397            const_iterator &operator = (const const_iterator &it) {
398                container_const_reference<self_type>::assign (&it ());
399                it_ = it.it_;
400                return *this;
401            }
402
403            // Comparison
404            BOOST_UBLAS_INLINE
405            bool operator == (const const_iterator &it) const {
406                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
407                return it_ == it.it_;
408            }
409            BOOST_UBLAS_INLINE
410            bool operator < (const const_iterator &it) const {
411                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
412                return it_ < it.it_;
413            }
414
415        private:
416            const_subiterator_type it_;
417        };
418#endif
419
420        BOOST_UBLAS_INLINE
421        const_iterator begin () const {
422            return find (0); 
423        }
424        BOOST_UBLAS_INLINE
425        const_iterator end () const {
426            return find (size ());
427        }
428
429        // Reverse iterator
430        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
431
432        BOOST_UBLAS_INLINE
433        const_reverse_iterator rbegin () const {
434            return const_reverse_iterator (end ());
435        }
436        BOOST_UBLAS_INLINE
437        const_reverse_iterator rend () const {
438            return const_reverse_iterator (begin ());
439        }
440
441    private:
442        expression_closure_type e_;
443    };
444
445    template<class E, class F>
446    struct vector_unary_traits {
447        typedef vector_unary<E, F> expression_type;
448//FIXME
449// #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
450        typedef expression_type result_type;
451// #else
452//         typedef typename E::vector_temporary_type result_type;
453// #endif
454    };
455
456    // (- v) [i] = - v [i]
457    template<class E> 
458    BOOST_UBLAS_INLINE
459    typename vector_unary_traits<E, scalar_negate<typename E::value_type> >::result_type
460    operator - (const vector_expression<E> &e) {
461        typedef typename vector_unary_traits<E, scalar_negate<typename E::value_type> >::expression_type expression_type;
462        return expression_type (e ());
463    }
464
465    // (conj v) [i] = conj (v [i])
466    template<class E> 
467    BOOST_UBLAS_INLINE
468    typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::result_type
469    conj (const vector_expression<E> &e) {
470        typedef typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
471        return expression_type (e ());
472    }
473
474    // (real v) [i] = real (v [i])
475    template<class E>
476    BOOST_UBLAS_INLINE
477    typename vector_unary_traits<E, scalar_real<typename E::value_type> >::result_type
478    real (const vector_expression<E> &e) {
479        typedef typename vector_unary_traits<E, scalar_real<typename E::value_type> >::expression_type expression_type;
480        return expression_type (e ());
481    }
482
483    // (imag v) [i] = imag (v [i])
484    template<class E>
485    BOOST_UBLAS_INLINE
486    typename vector_unary_traits<E, scalar_imag<typename E::value_type> >::result_type
487    imag (const vector_expression<E> &e) {
488        typedef typename vector_unary_traits<E, scalar_imag<typename E::value_type> >::expression_type expression_type;
489        return expression_type (e ());
490    }
491
492    // (trans v) [i] = v [i]
493    template<class E>
494    BOOST_UBLAS_INLINE
495    typename vector_unary_traits<const E, scalar_identity<typename E::value_type> >::result_type
496    trans (const vector_expression<E> &e) {
497        typedef typename vector_unary_traits<const E, scalar_identity<typename E::value_type> >::expression_type expression_type;
498        return expression_type (e ());
499    }
500    template<class E>
501    BOOST_UBLAS_INLINE
502    typename vector_unary_traits<E, scalar_identity<typename E::value_type> >::result_type
503    trans (vector_expression<E> &e) {
504        typedef typename vector_unary_traits<E, scalar_identity<typename E::value_type> >::expression_type expression_type;
505        return expression_type (e ());
506    }
507
508    // (herm v) [i] = conj (v [i])
509    template<class E>
510    BOOST_UBLAS_INLINE
511    typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::result_type
512    herm (const vector_expression<E> &e) {
513        typedef typename vector_unary_traits<E, scalar_conj<typename E::value_type> >::expression_type expression_type;
514        return expression_type (e ());
515    }
516
517    template<class E1, class E2, class F>
518    class vector_binary:
519        public vector_expression<vector_binary<E1, E2, F> > {
520
521        typedef E1 expression1_type;
522        typedef E2 expression2_type;
523        typedef F functor_type;
524        typedef typename E1::const_closure_type expression1_closure_type;
525        typedef typename E2::const_closure_type expression2_closure_type;
526        typedef vector_binary<E1, E2, F> self_type;
527    public:
528#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
529        using vector_expression<vector_binary<E1, E2, F> >::operator ();
530#endif
531        typedef typename promote_traits<typename E1::size_type, typename E2::size_type>::promote_type size_type;
532        typedef typename promote_traits<typename E1::difference_type, typename E2::difference_type>::promote_type difference_type;
533        typedef typename F::result_type value_type;
534        typedef value_type const_reference;
535        typedef const_reference reference;
536        typedef const self_type const_closure_type;
537        typedef const_closure_type closure_type;
538        typedef unknown_storage_tag storage_category;
539
540        // Construction and destruction
541        BOOST_UBLAS_INLINE
542        vector_binary (const expression1_type &e1, const expression2_type &e2):
543            e1_ (e1), e2_ (e2) {}
544
545        // Accessors
546        BOOST_UBLAS_INLINE
547        size_type size () const { 
548            return BOOST_UBLAS_SAME (e1_.size (), e2_.size ()); 
549        }
550
551    private:
552        // Accessors
553        BOOST_UBLAS_INLINE
554        const expression1_closure_type &expression1 () const {
555            return e1_;
556        }
557        BOOST_UBLAS_INLINE
558        const expression2_closure_type &expression2 () const {
559            return e2_;
560        }
561
562    public:
563        // Element access
564        BOOST_UBLAS_INLINE
565        const_reference operator () (size_type i) const {
566            return functor_type::apply (e1_ (i), e2_ (i));
567        }
568
569        BOOST_UBLAS_INLINE
570        const_reference operator [] (size_type i) const {
571            return functor_type::apply (e1_ [i], e2_ [i]);
572        }
573
574        // Closure comparison
575        BOOST_UBLAS_INLINE
576        bool same_closure (const vector_binary &vb) const {
577            return (*this).expression1 ().same_closure (vb.expression1 ()) &&
578                   (*this).expression2 ().same_closure (vb.expression2 ());
579        }
580
581        // Iterator types
582    private:
583        typedef typename E1::const_iterator const_subiterator1_type;
584        typedef typename E2::const_iterator const_subiterator2_type;
585        typedef const value_type *const_pointer;
586
587    public:
588#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
589        typedef typename iterator_restrict_traits<typename const_subiterator1_type::iterator_category,
590                                                  typename const_subiterator2_type::iterator_category>::iterator_category iterator_category;
591        typedef indexed_const_iterator<const_closure_type, iterator_category> const_iterator;
592        typedef const_iterator iterator;
593#else
594        class const_iterator;
595        typedef const_iterator iterator;
596#endif
597
598        // Element lookup
599        BOOST_UBLAS_INLINE
600        const_iterator find (size_type i) const {
601            const_subiterator1_type it1 (e1_.find (i));
602            const_subiterator1_type it1_end (e1_.find (size ()));
603            const_subiterator2_type it2 (e2_.find (i));
604            const_subiterator2_type it2_end (e2_.find (size ()));
605            i = (std::min) (it1 != it1_end ? it1.index () : size (),
606                          it2 != it2_end ? it2.index () : size ());
607#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
608            return const_iterator (*this, i);
609#else
610            return const_iterator (*this, i, it1, it1_end, it2, it2_end);
611#endif
612        }
613
614        // Iterator merges the iterators of the referenced expressions and
615        // enhances them with the binary functor.
616
617#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
618        class const_iterator:
619            public container_const_reference<vector_binary>,
620            public iterator_base_traits<typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
621                                                                          typename E2::const_iterator::iterator_category>::iterator_category>::template
622                        iterator_base<const_iterator, value_type>::type {
623        public:
624            typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
625                                                      typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
626            typedef typename vector_binary::difference_type difference_type;
627            typedef typename vector_binary::value_type value_type;
628            typedef typename vector_binary::const_reference reference;
629            typedef typename vector_binary::const_pointer pointer;
630
631            // Construction and destruction
632            BOOST_UBLAS_INLINE
633            const_iterator ():
634                container_const_reference<self_type> (), i_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
635            BOOST_UBLAS_INLINE
636            const_iterator (const self_type &vb, size_type i,
637                            const const_subiterator1_type &it1, const const_subiterator1_type &it1_end,
638                            const const_subiterator2_type &it2, const const_subiterator2_type &it2_end):
639                container_const_reference<self_type> (vb), i_ (i), it1_ (it1), it1_end_ (it1_end), it2_ (it2), it2_end_ (it2_end) {}
640
641        private: 
642            // Dense specializations
643            BOOST_UBLAS_INLINE
644            void increment (dense_random_access_iterator_tag) {
645                ++ i_; ++ it1_; ++ it2_;
646            }
647            BOOST_UBLAS_INLINE
648            void decrement (dense_random_access_iterator_tag) {
649                -- i_; -- it1_; -- it2_;
650            }
651            BOOST_UBLAS_INLINE
652            void increment (dense_random_access_iterator_tag, difference_type n) {
653                i_ += n; it1_ += n; it2_ += n;
654            }
655            BOOST_UBLAS_INLINE
656            void decrement (dense_random_access_iterator_tag, difference_type n) {
657                i_ -= n; it1_ -= n; it2_ -= n;
658            }
659            BOOST_UBLAS_INLINE
660            value_type dereference (dense_random_access_iterator_tag) const {
661                return functor_type::apply (*it1_, *it2_);
662            }
663
664            // Packed specializations
665            BOOST_UBLAS_INLINE
666            void increment (packed_random_access_iterator_tag) {
667                if (it1_ != it1_end_)
668                    if (it1_.index () <= i_)
669                        ++ it1_;
670                if (it2_ != it2_end_)
671                    if (it2_.index () <= i_)
672                        ++ it2_;
673                ++ i_;
674            }
675            BOOST_UBLAS_INLINE
676            void decrement (packed_random_access_iterator_tag) {
677                if (it1_ != it1_end_)
678                    if (i_ <= it1_.index ())
679                        -- it1_;
680                if (it2_ != it2_end_)
681                    if (i_ <= it2_.index ())
682                        -- it2_;
683                -- i_;
684            }
685            BOOST_UBLAS_INLINE
686            void increment (packed_random_access_iterator_tag, difference_type n) {
687                while (n > 0) {
688                    increment (packed_random_access_iterator_tag ());
689                    --n;
690                }
691                while (n < 0) {
692                    decrement (packed_random_access_iterator_tag ());
693                    ++n;
694                }
695            }
696            BOOST_UBLAS_INLINE
697            void decrement (packed_random_access_iterator_tag, difference_type n) {
698                while (n > 0) {
699                    decrement (packed_random_access_iterator_tag ());
700                    --n;
701                }
702                while (n < 0) {
703                    increment (packed_random_access_iterator_tag ());
704                    ++n;
705                }
706            }
707            BOOST_UBLAS_INLINE
708            value_type dereference (packed_random_access_iterator_tag) const {
709                value_type t1 = value_type/*zero*/();
710                if (it1_ != it1_end_)
711                    if (it1_.index () == i_)
712                        t1 = *it1_;
713                value_type t2 = value_type/*zero*/();
714                if (it2_ != it2_end_)
715                    if (it2_.index () == i_)
716                        t2 = *it2_;
717                return functor_type::apply (t1, t2);
718            }
719
720            // Sparse specializations
721            BOOST_UBLAS_INLINE
722            void increment (sparse_bidirectional_iterator_tag) {
723                size_type index1 = (*this) ().size ();
724                if (it1_ != it1_end_) {
725                    if  (it1_.index () <= i_)
726                        ++ it1_;
727                    if (it1_ != it1_end_)
728                        index1 = it1_.index ();
729                }
730                size_type index2 = (*this) ().size ();
731                if (it2_ != it2_end_) {
732                    if (it2_.index () <= i_)
733                        ++ it2_;
734                    if (it2_ != it2_end_)
735                        index2 = it2_.index ();
736                }
737                i_ = (std::min) (index1, index2);
738            }
739            BOOST_UBLAS_INLINE
740            void decrement (sparse_bidirectional_iterator_tag) {
741                size_type index1 = (*this) ().size ();
742                if (it1_ != it1_end_) {
743                    if (i_ <= it1_.index ())
744                        -- it1_;
745                    if (it1_ != it1_end_)
746                        index1 = it1_.index ();
747                }
748                size_type index2 = (*this) ().size ();
749                if (it2_ != it2_end_) {
750                    if (i_ <= it2_.index ())
751                        -- it2_;
752                    if (it2_ != it2_end_)
753                        index2 = it2_.index ();
754                }
755                i_ = (std::max) (index1, index2);
756            }
757            BOOST_UBLAS_INLINE
758            void increment (sparse_bidirectional_iterator_tag, difference_type n) {
759                while (n > 0) {
760                    increment (sparse_bidirectional_iterator_tag ());
761                    --n;
762                }
763                while (n < 0) {
764                    decrement (sparse_bidirectional_iterator_tag ());
765                    ++n;
766                }
767            }
768            BOOST_UBLAS_INLINE
769            void decrement (sparse_bidirectional_iterator_tag, difference_type n) {
770                while (n > 0) {
771                    decrement (sparse_bidirectional_iterator_tag ());
772                    --n;
773                }
774                while (n < 0) {
775                    increment (sparse_bidirectional_iterator_tag ());
776                    ++n;
777                }
778            }
779            BOOST_UBLAS_INLINE
780            value_type dereference (sparse_bidirectional_iterator_tag) const {
781                value_type t1 = value_type/*zero*/();
782                if (it1_ != it1_end_)
783                    if (it1_.index () == i_)
784                        t1 = *it1_;
785                value_type t2 = value_type/*zero*/();
786                if (it2_ != it2_end_)
787                    if (it2_.index () == i_)
788                        t2 = *it2_;
789                return functor_type::apply (t1, t2);
790            }
791
792        public: 
793            // Arithmetic
794            BOOST_UBLAS_INLINE
795            const_iterator &operator ++ () {
796                increment (iterator_category ());
797                return *this;
798            }
799            BOOST_UBLAS_INLINE
800            const_iterator &operator -- () {
801                decrement (iterator_category ());
802                return *this;
803            }
804            BOOST_UBLAS_INLINE
805            const_iterator &operator += (difference_type n) {
806                increment (iterator_category (), n);
807                return *this;
808            }
809            BOOST_UBLAS_INLINE
810            const_iterator &operator -= (difference_type n) {
811                decrement (iterator_category (), n);
812                return *this;
813            }
814            BOOST_UBLAS_INLINE
815            difference_type operator - (const const_iterator &it) const {
816                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
817                return index () - it.index ();
818            }
819
820            // Dereference
821            BOOST_UBLAS_INLINE
822            const_reference operator * () const {
823                return dereference (iterator_category ());
824            }
825            BOOST_UBLAS_INLINE
826            const_reference operator [] (difference_type n) const {
827                return *(*this + n);
828            }
829
830            // Index
831            BOOST_UBLAS_INLINE
832            size_type index () const {
833                return i_;
834            }
835
836            // Assignment
837            BOOST_UBLAS_INLINE
838            const_iterator &operator = (const const_iterator &it) {
839                container_const_reference<self_type>::assign (&it ());
840                i_ = it.i_;
841                it1_ = it.it1_;
842                it1_end_ = it.it1_end_;
843                it2_ = it.it2_;
844                it2_end_ = it.it2_end_;
845                return *this;
846            }
847
848            // Comparison
849            BOOST_UBLAS_INLINE
850            bool operator == (const const_iterator &it) const {
851                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
852                return index () == it.index ();
853            }
854            BOOST_UBLAS_INLINE
855            bool operator < (const const_iterator &it) const {
856                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
857                return index () < it.index ();
858            }
859
860        private:
861            size_type i_;
862            const_subiterator1_type it1_;
863            const_subiterator1_type it1_end_;
864            const_subiterator2_type it2_;
865            const_subiterator2_type it2_end_;
866        };
867#endif
868
869        BOOST_UBLAS_INLINE
870        const_iterator begin () const {
871            return find (0);
872        }
873        BOOST_UBLAS_INLINE
874        const_iterator end () const {
875            return find (size ());
876        }
877
878        // Reverse iterator
879        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
880
881        BOOST_UBLAS_INLINE
882        const_reverse_iterator rbegin () const {
883            return const_reverse_iterator (end ());
884        }
885        BOOST_UBLAS_INLINE
886        const_reverse_iterator rend () const {
887            return const_reverse_iterator (begin ());
888        }
889
890    private:
891        expression1_closure_type e1_;
892        expression2_closure_type e2_;
893    };
894
895    template<class E1, class E2, class F>
896    struct vector_binary_traits {
897        typedef vector_binary<E1, E2, F> expression_type;
898#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
899        typedef expression_type result_type; 
900#else
901        typedef typename E1::vector_temporary_type result_type;
902#endif
903    };
904
905    // (v1 + v2) [i] = v1 [i] + v2 [i]
906    template<class E1, class E2>
907    BOOST_UBLAS_INLINE
908    typename vector_binary_traits<E1, E2, scalar_plus<typename E1::value_type, 
909                                                      typename E2::value_type> >::result_type
910    operator + (const vector_expression<E1> &e1,
911                const vector_expression<E2> &e2) {
912        typedef typename vector_binary_traits<E1, E2, scalar_plus<typename E1::value_type,
913                                                                              typename E2::value_type> >::expression_type expression_type;
914        return expression_type (e1 (), e2 ());
915    }
916
917    // (v1 - v2) [i] = v1 [i] - v2 [i]
918    template<class E1, class E2>
919    BOOST_UBLAS_INLINE
920    typename vector_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
921                                                       typename E2::value_type> >::result_type
922    operator - (const vector_expression<E1> &e1,
923                const vector_expression<E2> &e2) {
924        typedef typename vector_binary_traits<E1, E2, scalar_minus<typename E1::value_type,
925                                                                               typename E2::value_type> >::expression_type expression_type;
926        return expression_type (e1 (), e2 ());
927    }
928
929    // (v1 * v2) [i] = v1 [i] * v2 [i]
930    template<class E1, class E2>
931    BOOST_UBLAS_INLINE
932    typename vector_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
933                                                            typename E2::value_type> >::result_type
934    element_prod (const vector_expression<E1> &e1,
935                  const vector_expression<E2> &e2) {
936        typedef typename vector_binary_traits<E1, E2, scalar_multiplies<typename E1::value_type,
937                                                                                    typename E2::value_type> >::expression_type expression_type;
938        return expression_type (e1 (), e2 ());
939    }
940
941    // (v1 / v2) [i] = v1 [i] / v2 [i]
942    template<class E1, class E2>
943    BOOST_UBLAS_INLINE
944    typename vector_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
945                                                         typename E2::value_type> >::result_type
946    element_div (const vector_expression<E1> &e1,
947                 const vector_expression<E2> &e2) {
948        typedef typename vector_binary_traits<E1, E2, scalar_divides<typename E1::value_type,
949                                                                                 typename E2::value_type> >::expression_type expression_type;
950        return expression_type (e1 (), e2 ());
951    }
952
953
954    template<class E1, class E2, class F>
955    class vector_binary_scalar1:
956        public vector_expression<vector_binary_scalar1<E1, E2, F> > {
957
958        typedef F functor_type;
959        typedef E1 expression1_type;
960        typedef E2 expression2_type;
961    public:
962        typedef const E1& expression1_closure_type;
963        typedef typename E2::const_closure_type expression2_closure_type;
964    private:
965        typedef vector_binary_scalar1<E1, E2, F> self_type;
966    public:
967#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
968        using vector_expression<vector_binary_scalar1<E1, E2, F> >::operator ();
969#endif
970        typedef typename E2::size_type size_type;
971        typedef typename E2::difference_type difference_type;
972        typedef typename F::result_type value_type;
973        typedef value_type const_reference;
974        typedef const_reference reference;
975        typedef const self_type const_closure_type;
976        typedef const_closure_type closure_type;
977        typedef unknown_storage_tag storage_category;
978
979        // Construction and destruction
980        BOOST_UBLAS_INLINE
981        vector_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
982            e1_ (e1), e2_ (e2) {}
983
984        // Accessors
985        BOOST_UBLAS_INLINE
986        size_type size () const {
987            return e2_.size ();
988        }
989
990    public:
991        // Element access
992        BOOST_UBLAS_INLINE
993        const_reference operator () (size_type i) const {
994            return functor_type::apply (e1_, e2_ (i));
995        }
996
997        BOOST_UBLAS_INLINE
998        const_reference operator [] (size_type i) const {
999            return functor_type::apply (e1_, e2_ [i]);
1000        }
1001
1002        // Closure comparison
1003        BOOST_UBLAS_INLINE
1004        bool same_closure (const vector_binary_scalar1 &vbs1) const {
1005            return &e1_ == &(vbs1.e1_) &&
1006                   (*this).e2_.same_closure (vbs1.e2_);
1007        }
1008
1009        // Iterator types
1010    private:
1011        typedef expression1_type const_subiterator1_type;
1012        typedef typename expression2_type::const_iterator const_subiterator2_type;
1013        typedef const value_type *const_pointer;
1014
1015    public:
1016#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1017        typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
1018        typedef const_iterator iterator;
1019#else
1020        class const_iterator;
1021        typedef const_iterator iterator;
1022#endif
1023
1024        // Element lookup
1025        BOOST_UBLAS_INLINE
1026        const_iterator find (size_type i) const {
1027#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1028            const_subiterator2_type it (e2_.find (i));
1029            return const_iterator (*this, it.index ());
1030#else
1031            return const_iterator (*this, const_subiterator1_type (e1_), e2_.find (i));
1032#endif
1033        }
1034
1035        // Iterator enhances the iterator of the referenced vector expression
1036        // with the binary functor.
1037
1038#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1039        class const_iterator:
1040            public container_const_reference<vector_binary_scalar1>,
1041            public iterator_base_traits<typename E2::const_iterator::iterator_category>::template
1042                        iterator_base<const_iterator, value_type>::type {
1043        public:
1044            typedef typename E2::const_iterator::iterator_category iterator_category;
1045            typedef typename vector_binary_scalar1::difference_type difference_type;
1046            typedef typename vector_binary_scalar1::value_type value_type;
1047            typedef typename vector_binary_scalar1::const_reference reference;
1048            typedef typename vector_binary_scalar1::const_pointer pointer;
1049
1050            // Construction and destruction
1051            BOOST_UBLAS_INLINE
1052            const_iterator ():
1053                container_const_reference<self_type> (), it1_ (), it2_ () {}
1054            BOOST_UBLAS_INLINE
1055            const_iterator (const self_type &vbs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
1056                container_const_reference<self_type> (vbs), it1_ (it1), it2_ (it2) {}
1057
1058            // Arithmetic
1059            BOOST_UBLAS_INLINE
1060            const_iterator &operator ++ () {
1061                ++ it2_;
1062                return *this;
1063            }
1064            BOOST_UBLAS_INLINE
1065            const_iterator &operator -- () {
1066                -- it2_;
1067                return *this;
1068            }
1069            BOOST_UBLAS_INLINE
1070            const_iterator &operator += (difference_type n) {
1071                it2_ += n;
1072                return *this;
1073            }
1074            BOOST_UBLAS_INLINE
1075            const_iterator &operator -= (difference_type n) {
1076                it2_ -= n;
1077                return *this;
1078            }
1079            BOOST_UBLAS_INLINE
1080            difference_type operator - (const const_iterator &it) const {
1081                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1082                // FIXME we shouldn't compare floats
1083                // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1084                return it2_ - it.it2_;
1085            }
1086
1087            // Dereference
1088            BOOST_UBLAS_INLINE
1089            const_reference operator * () const {
1090                return functor_type::apply (it1_, *it2_);
1091            }
1092            BOOST_UBLAS_INLINE
1093            const_reference operator [] (difference_type n) const {
1094                return *(*this + n);
1095            }
1096
1097            // Index
1098            BOOST_UBLAS_INLINE
1099            size_type index () const {
1100                return it2_.index ();
1101            }
1102
1103            // Assignment
1104            BOOST_UBLAS_INLINE
1105            const_iterator &operator = (const const_iterator &it) {
1106                container_const_reference<self_type>::assign (&it ());
1107                it1_ = it.it1_;
1108                it2_ = it.it2_;
1109                return *this;
1110            }
1111
1112            // Comparison
1113            BOOST_UBLAS_INLINE
1114            bool operator == (const const_iterator &it) const {
1115                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1116                // FIXME we shouldn't compare floats
1117                // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1118                return it2_ == it.it2_;
1119            }
1120            BOOST_UBLAS_INLINE
1121            bool operator < (const const_iterator &it) const {
1122                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1123                // FIXME we shouldn't compare floats
1124                // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1125                return it2_ < it.it2_;
1126            }
1127
1128        private:
1129            const_subiterator1_type it1_;
1130            const_subiterator2_type it2_;
1131        };
1132#endif
1133
1134        BOOST_UBLAS_INLINE
1135        const_iterator begin () const {
1136            return find (0); 
1137        }
1138        BOOST_UBLAS_INLINE
1139        const_iterator end () const {
1140            return find (size ()); 
1141        }
1142
1143        // Reverse iterator
1144        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1145
1146        BOOST_UBLAS_INLINE
1147        const_reverse_iterator rbegin () const {
1148            return const_reverse_iterator (end ());
1149        }
1150        BOOST_UBLAS_INLINE
1151        const_reverse_iterator rend () const {
1152            return const_reverse_iterator (begin ());
1153        }
1154
1155    private:
1156        expression1_closure_type e1_;
1157        expression2_closure_type e2_;
1158    };
1159
1160    template<class E1, class E2, class F>
1161    struct vector_binary_scalar1_traits {
1162        typedef vector_binary_scalar1<E1, E2, F> expression_type;   // allow E1 to be builtin type
1163#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1164        typedef expression_type result_type;
1165#else
1166        typedef typename E2::vector_temporary_type result_type;
1167#endif
1168    };
1169
1170    // (t * v) [i] = t * v [i]
1171    template<class T1, class E2>
1172    BOOST_UBLAS_INLINE
1173    typename enable_if< is_convertible<T1, typename E2::value_type >,   
1174    typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
1175    >::type
1176    operator * (const T1 &e1,
1177                const vector_expression<E2> &e2) {
1178        typedef typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
1179        return expression_type (e1, e2 ());
1180    }
1181
1182
1183    template<class E1, class E2, class F>
1184    class vector_binary_scalar2:
1185        public vector_expression<vector_binary_scalar2<E1, E2, F> > {
1186
1187        typedef F functor_type;
1188        typedef E1 expression1_type;
1189        typedef E2 expression2_type;
1190        typedef typename E1::const_closure_type expression1_closure_type;
1191        typedef const E2& expression2_closure_type;
1192        typedef vector_binary_scalar2<E1, E2, F> self_type;
1193    public:
1194#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1195        using vector_expression<vector_binary_scalar2<E1, E2, F> >::operator ();
1196#endif
1197        typedef typename E1::size_type size_type;
1198        typedef typename E1::difference_type difference_type;
1199        typedef typename F::result_type value_type;
1200        typedef value_type const_reference;
1201        typedef const_reference reference;
1202        typedef const self_type const_closure_type;
1203        typedef const_closure_type closure_type;
1204        typedef unknown_storage_tag storage_category;
1205
1206        // Construction and destruction
1207        BOOST_UBLAS_INLINE
1208        vector_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
1209            e1_ (e1), e2_ (e2) {}
1210
1211        // Accessors
1212        BOOST_UBLAS_INLINE
1213        size_type size () const {
1214            return e1_.size (); 
1215        }
1216
1217    public:
1218        // Element access
1219        BOOST_UBLAS_INLINE
1220        const_reference operator () (size_type i) const {
1221            return functor_type::apply (e1_ (i), e2_);
1222        }
1223
1224        BOOST_UBLAS_INLINE
1225        const_reference operator [] (size_type i) const {
1226            return functor_type::apply (e1_ [i], e2_);
1227        }
1228
1229        // Closure comparison
1230        BOOST_UBLAS_INLINE
1231        bool same_closure (const vector_binary_scalar2 &vbs2) const {
1232            return (*this).e1_.same_closure (vbs2.e1_) &&
1233                   &e2_ == &(vbs2.e2_);
1234        }
1235
1236        // Iterator types
1237    private:
1238        typedef typename expression1_type::const_iterator const_subiterator1_type;
1239        typedef expression2_type const_subiterator2_type;
1240        typedef const value_type *const_pointer;
1241
1242    public:
1243#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1244        typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
1245        typedef const_iterator iterator;
1246#else
1247        class const_iterator;
1248        typedef const_iterator iterator;
1249#endif
1250
1251        // Element lookup
1252        BOOST_UBLAS_INLINE
1253        const_iterator find (size_type i) const {
1254#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1255            const_subiterator1_type it (e1_.find (i));
1256            return const_iterator (*this, it.index ());
1257#else
1258            return const_iterator (*this, e1_.find (i), const_subiterator2_type (e2_));
1259#endif
1260        }
1261
1262        // Iterator enhances the iterator of the referenced vector expression
1263        // with the binary functor.
1264
1265#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1266        class const_iterator:
1267            public container_const_reference<vector_binary_scalar2>,
1268            public iterator_base_traits<typename E1::const_iterator::iterator_category>::template
1269                        iterator_base<const_iterator, value_type>::type {
1270        public:
1271            typedef typename E1::const_iterator::iterator_category iterator_category;
1272            typedef typename vector_binary_scalar2::difference_type difference_type;
1273            typedef typename vector_binary_scalar2::value_type value_type;
1274            typedef typename vector_binary_scalar2::const_reference reference;
1275            typedef typename vector_binary_scalar2::const_pointer pointer;
1276
1277            // Construction and destruction
1278            BOOST_UBLAS_INLINE
1279            const_iterator ():
1280                container_const_reference<self_type> (), it1_ (), it2_ () {}
1281            BOOST_UBLAS_INLINE
1282            const_iterator (const self_type &vbs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
1283                container_const_reference<self_type> (vbs), it1_ (it1), it2_ (it2) {}
1284
1285            // Arithmetic
1286            BOOST_UBLAS_INLINE
1287            const_iterator &operator ++ () {
1288                ++ it1_;
1289                return *this;
1290            }
1291            BOOST_UBLAS_INLINE
1292            const_iterator &operator -- () {
1293                -- it1_;
1294                return *this;
1295            }
1296            BOOST_UBLAS_INLINE
1297            const_iterator &operator += (difference_type n) {
1298                it1_ += n;
1299                return *this;
1300            }
1301            BOOST_UBLAS_INLINE
1302            const_iterator &operator -= (difference_type n) {
1303                it1_ -= n;
1304                return *this;
1305            }
1306            BOOST_UBLAS_INLINE
1307            difference_type operator - (const const_iterator &it) const {
1308                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1309                // FIXME we shouldn't compare floats
1310                // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
1311                return it1_ - it.it1_;
1312            }
1313
1314            // Dereference
1315            BOOST_UBLAS_INLINE
1316            const_reference operator * () const {
1317                return functor_type::apply (*it1_, it2_);
1318            }
1319            BOOST_UBLAS_INLINE
1320            const_reference operator [] (difference_type n) const {
1321                return *(*this + n);
1322            }
1323
1324            // Index
1325            BOOST_UBLAS_INLINE
1326            size_type index () const {
1327                return it1_.index ();
1328            }
1329
1330            // Assignment
1331            BOOST_UBLAS_INLINE
1332            const_iterator &operator = (const const_iterator &it) {
1333                container_const_reference<self_type>::assign (&it ());
1334                it1_ = it.it1_;
1335                it2_ = it.it2_;
1336                return *this;
1337            }
1338
1339            // Comparison
1340            BOOST_UBLAS_INLINE
1341            bool operator == (const const_iterator &it) const {
1342                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1343                // FIXME we shouldn't compare floats
1344                // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
1345                return it1_ == it.it1_;
1346            }
1347            BOOST_UBLAS_INLINE
1348            bool operator < (const const_iterator &it) const {
1349                BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1350                // FIXME we shouldn't compare floats
1351                // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
1352                return it1_ < it.it1_;
1353            }
1354
1355        private:
1356            const_subiterator1_type it1_;
1357            const_subiterator2_type it2_;
1358        };
1359#endif
1360
1361        BOOST_UBLAS_INLINE
1362        const_iterator begin () const {
1363            return find (0);
1364        }
1365        BOOST_UBLAS_INLINE
1366        const_iterator end () const {
1367            return find (size ());
1368        }
1369
1370        // Reverse iterator
1371        typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1372
1373        BOOST_UBLAS_INLINE
1374        const_reverse_iterator rbegin () const {
1375            return const_reverse_iterator (end ());
1376        }
1377        BOOST_UBLAS_INLINE
1378        const_reverse_iterator rend () const {
1379            return const_reverse_iterator (begin ());
1380        }
1381
1382    private:
1383        expression1_closure_type e1_;
1384        expression2_closure_type e2_;
1385    };
1386
1387    template<class E1, class E2, class F>
1388    struct vector_binary_scalar2_traits {
1389        typedef vector_binary_scalar2<E1, E2, F> expression_type;   // allow E2 to be builtin type
1390#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1391        typedef expression_type result_type;
1392#else
1393        typedef typename E1::vector_temporary_type result_type;
1394#endif
1395    };
1396
1397    // (v * t) [i] = v [i] * t
1398    template<class E1, class T2>
1399    BOOST_UBLAS_INLINE
1400    typename enable_if< is_convertible<T2, typename E1::value_type >,   
1401    typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
1402    >::type
1403    operator * (const vector_expression<E1> &e1,
1404                const T2 &e2) {
1405        typedef typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
1406        return expression_type (e1 (), e2);
1407    }
1408
1409    // (v / t) [i] = v [i] / t
1410    template<class E1, class T2>
1411    BOOST_UBLAS_INLINE
1412    typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
1413    operator / (const vector_expression<E1> &e1,
1414                const T2 &e2) {
1415        typedef typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
1416        return expression_type (e1 (), e2);
1417    }
1418
1419
1420    template<class E, class F>
1421    class vector_scalar_unary:
1422        public scalar_expression<vector_scalar_unary<E, F> > {
1423
1424        typedef E expression_type;
1425        typedef F functor_type;
1426        typedef typename E::const_closure_type expression_closure_type;
1427        typedef typename E::const_iterator::iterator_category iterator_category;
1428        typedef vector_scalar_unary<E, F> self_type;
1429    public:
1430        typedef typename F::result_type value_type;
1431        typedef typename E::difference_type difference_type;
1432        typedef const self_type const_closure_type;
1433        typedef const_closure_type closure_type;
1434        typedef unknown_storage_tag storage_category;
1435
1436        // Construction and destruction
1437        BOOST_UBLAS_INLINE
1438        explicit vector_scalar_unary (const expression_type &e):
1439            e_ (e) {}
1440
1441    private:
1442        // Expression accessors
1443        BOOST_UBLAS_INLINE
1444        const expression_closure_type &expression () const {
1445            return e_;
1446        }
1447
1448    public:
1449        BOOST_UBLAS_INLINE
1450        operator value_type () const {
1451            return evaluate (iterator_category ());
1452        }
1453
1454    private:
1455        // Dense random access specialization
1456        BOOST_UBLAS_INLINE
1457        value_type evaluate (dense_random_access_iterator_tag) const {
1458#ifdef BOOST_UBLAS_USE_INDEXING
1459            return functor_type::apply (e_);
1460#elif BOOST_UBLAS_USE_ITERATING
1461            difference_type size = e_.size ();
1462            return functor_type::apply (size, e_.begin ());
1463#else
1464            difference_type size = e_.size ();
1465            if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
1466                return functor_type::apply (size, e_.begin ());
1467            else
1468                return functor_type::apply (e_);
1469#endif
1470        }
1471
1472        // Packed bidirectional specialization
1473        BOOST_UBLAS_INLINE
1474        value_type evaluate (packed_random_access_iterator_tag) const {
1475            return functor_type::apply (e_.begin (), e_.end ());
1476        }
1477
1478        // Sparse bidirectional specialization
1479        BOOST_UBLAS_INLINE
1480        value_type evaluate (sparse_bidirectional_iterator_tag) const {
1481            return functor_type::apply (e_.begin (), e_.end ());
1482        }
1483
1484    private:
1485        expression_closure_type e_;
1486    };
1487
1488    template<class E, class F>
1489    struct vector_scalar_unary_traits {
1490        typedef vector_scalar_unary<E, F> expression_type;
1491#if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET)
1492// FIXME don't define USE_SCALAR_ET other then for testing
1493// They do not work for complex types
1494         typedef expression_type result_type;
1495#else
1496         typedef typename F::result_type result_type;
1497#endif
1498    };
1499
1500    // sum v = sum (v [i])
1501    template<class E>
1502    BOOST_UBLAS_INLINE
1503    typename vector_scalar_unary_traits<E, vector_sum<E> >::result_type
1504    sum (const vector_expression<E> &e) {
1505        typedef typename vector_scalar_unary_traits<E, vector_sum<E> >::expression_type expression_type;
1506        return expression_type (e ());
1507    }
1508
1509    // real: norm_1 v = sum (abs (v [i]))
1510    // complex: norm_1 v = sum (abs (real (v [i])) + abs (imag (v [i])))
1511    template<class E>
1512    BOOST_UBLAS_INLINE
1513    typename vector_scalar_unary_traits<E, vector_norm_1<E> >::result_type
1514    norm_1 (const vector_expression<E> &e) {
1515        typedef typename vector_scalar_unary_traits<E, vector_norm_1<E> >::expression_type expression_type;
1516        return expression_type (e ());
1517    }
1518
1519    // real: norm_2 v = sqrt (sum (v [i] * v [i]))
1520    // complex: norm_2 v = sqrt (sum (v [i] * conj (v [i])))
1521    template<class E>
1522    BOOST_UBLAS_INLINE
1523    typename vector_scalar_unary_traits<E, vector_norm_2<E> >::result_type
1524    norm_2 (const vector_expression<E> &e) {
1525        typedef typename vector_scalar_unary_traits<E, vector_norm_2<E> >::expression_type expression_type;
1526        return expression_type (e ());
1527    }
1528
1529    // real: norm_inf v = maximum (abs (v [i]))
1530    // complex: norm_inf v = maximum (maximum (abs (real (v [i])), abs (imag (v [i]))))
1531    template<class E>
1532    BOOST_UBLAS_INLINE
1533    typename vector_scalar_unary_traits<E, vector_norm_inf<E> >::result_type
1534    norm_inf (const vector_expression<E> &e) {
1535        typedef typename vector_scalar_unary_traits<E, vector_norm_inf<E> >::expression_type expression_type;
1536        return expression_type (e ());
1537    }
1538
1539    // real: index_norm_inf v = minimum (i: abs (v [i]) == maximum (abs (v [i])))
1540    template<class E>
1541    BOOST_UBLAS_INLINE
1542    typename vector_scalar_unary_traits<E, vector_index_norm_inf<E> >::result_type
1543    index_norm_inf (const vector_expression<E> &e) {
1544        typedef typename vector_scalar_unary_traits<E, vector_index_norm_inf<E> >::expression_type expression_type;
1545        return expression_type (e ());
1546    }
1547
1548    template<class E1, class E2, class F>
1549    class vector_scalar_binary:
1550        public scalar_expression<vector_scalar_binary<E1, E2, F> > {
1551
1552        typedef E1 expression1_type;
1553        typedef E2 expression2_type;
1554        typedef F functor_type;
1555        typedef typename E1::const_closure_type expression1_closure_type;
1556        typedef typename E2::const_closure_type expression2_closure_type;
1557        typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
1558                                                  typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
1559        typedef vector_scalar_binary<E1, E2, F> self_type;
1560    public:
1561        static const unsigned complexity = 1;
1562        typedef typename F::result_type value_type;
1563        typedef typename E1::difference_type difference_type;
1564        typedef const self_type const_closure_type;
1565        typedef const_closure_type closure_type;
1566        typedef unknown_storage_tag storage_category;
1567
1568        // Construction and destruction
1569        BOOST_UBLAS_INLINE
1570        vector_scalar_binary (const expression1_type &e1, const expression2_type  &e2):
1571            e1_ (e1), e2_ (e2) {}
1572
1573    private:
1574        // Accessors
1575        BOOST_UBLAS_INLINE
1576        const expression1_closure_type &expression1 () const {
1577            return e1_;
1578        }
1579        BOOST_UBLAS_INLINE
1580        const expression2_closure_type &expression2 () const {
1581            return e2_;
1582        }
1583
1584    public:
1585        BOOST_UBLAS_INLINE
1586        operator value_type () const {
1587            return evaluate (iterator_category ());
1588        }
1589
1590    private:
1591        // Dense random access specialization
1592        BOOST_UBLAS_INLINE
1593        value_type evaluate (dense_random_access_iterator_tag) const {
1594            BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
1595#ifdef BOOST_UBLAS_USE_INDEXING
1596            return functor_type::apply (e1_, e2_);
1597#elif BOOST_UBLAS_USE_ITERATING
1598            difference_type size = BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
1599            return functor_type::apply (size, e1_.begin (), e2_.begin ());
1600#else
1601            difference_type size = BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
1602            if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
1603                return functor_type::apply (size, e1_.begin (), e2_.begin ());
1604            else
1605                return functor_type::apply (e1_, e2_);
1606#endif
1607        }
1608
1609        // Packed bidirectional specialization
1610        BOOST_UBLAS_INLINE
1611        value_type evaluate (packed_random_access_iterator_tag) const {
1612            BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
1613            return functor_type::apply (e1_.begin (), e1_.end (), e2_.begin (), e2_.end ());
1614        }
1615
1616        // Sparse bidirectional specialization
1617        BOOST_UBLAS_INLINE
1618        value_type evaluate (sparse_bidirectional_iterator_tag) const {
1619            BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
1620            return functor_type::apply (e1_.begin (), e1_.end (), e2_.begin (), e2_.end (), sparse_bidirectional_iterator_tag ());
1621        }
1622
1623    private:
1624        expression1_closure_type e1_;
1625        expression2_closure_type e2_;
1626    };
1627
1628    template<class E1, class E2, class F>
1629    struct vector_scalar_binary_traits {
1630        typedef vector_scalar_binary<E1, E2, F> expression_type;
1631#if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET)
1632// FIXME don't define USE_SCALAR_ET other then for testing
1633// They do not work for complex types
1634        typedef expression_type result_type;
1635#else
1636        typedef typename F::result_type result_type;
1637#endif
1638    };
1639
1640    // inner_prod (v1, v2) = sum (v1 [i] * v2 [i])
1641    template<class E1, class E2>
1642    BOOST_UBLAS_INLINE
1643    typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
1644                                                                   typename promote_traits<typename E1::value_type,
1645                                                                                           typename E2::value_type>::promote_type> >::result_type
1646    inner_prod (const vector_expression<E1> &e1,
1647                const vector_expression<E2> &e2) {
1648        typedef typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
1649                                                                   typename promote_traits<typename E1::value_type,
1650                                                                                           typename E2::value_type>::promote_type> >::expression_type expression_type;
1651        return expression_type (e1 (), e2 ());
1652    }
1653
1654    template<class E1, class E2>
1655    BOOST_UBLAS_INLINE
1656    typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
1657                                                                   typename type_traits<typename promote_traits<typename E1::value_type,
1658                                                                                                                typename E2::value_type>::promote_type>::precision_type> >::result_type
1659    prec_inner_prod (const vector_expression<E1> &e1,
1660                     const vector_expression<E2> &e2) {
1661        typedef typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
1662                                                                   typename type_traits<typename promote_traits<typename E1::value_type,
1663                                                                                                                typename E2::value_type>::promote_type>::precision_type> >::expression_type expression_type;
1664        return expression_type (e1 (), e2 ());
1665    }
1666
1667}}}
1668
1669#endif
Note: See TracBrowser for help on using the repository browser.