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 cbegin () const {
192 return begin ();
193 }
194 BOOST_UBLAS_INLINE
195 const_iterator end () const {
196 return expression ().end ();
197 }
198 BOOST_UBLAS_INLINE
199 const_iterator cend () const {
200 return end ();
201 }
202
203 BOOST_UBLAS_INLINE
204 iterator begin () {
205 return expression ().begin ();
206 }
207 BOOST_UBLAS_INLINE
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
217 const_reverse_iterator rbegin () const {
218 return const_reverse_iterator (end ());
219 }
220 BOOST_UBLAS_INLINE
221 const_reverse_iterator crbegin () const {
222 return rbegin ();
223 }
224 BOOST_UBLAS_INLINE
225 const_reverse_iterator rend () const {
226 return const_reverse_iterator (begin ());
227 }
228 BOOST_UBLAS_INLINE
229 const_reverse_iterator crend () const {
230 return rend ();
231 }
232
233 BOOST_UBLAS_INLINE
234 reverse_iterator rbegin () {
235 return reverse_iterator (end ());
236 }
237 BOOST_UBLAS_INLINE
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.
277 explicit vector_unary (expression_type &e):
278 e_ (e) {}
279
280 // Accessors
281 BOOST_UBLAS_INLINE
282 size_type size () const {
283 return e_.size ();
284 }
285
286 public:
287 // Expression accessors
288 BOOST_UBLAS_INLINE
289 const expression_closure_type &expression () const {
290 return e_;
291 }
292
293 public:
294 // Element access
295 BOOST_UBLAS_INLINE
296 const_reference operator () (size_type i) const {
297 return functor_type::apply (e_ (i));
298 }
299 BOOST_UBLAS_INLINE
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
306 const_reference operator [] (size_type i) const {
307 return functor_type::apply (e_ [i]);
308 }
309 BOOST_UBLAS_INLINE
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
317 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
337 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
363 const_iterator ():
364 container_const_reference<self_type> (), it_ () {}
365 BOOST_UBLAS_INLINE
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
371 const_iterator &operator ++ () {
372 ++ it_;
373 return *this;
374 }
375 BOOST_UBLAS_INLINE
376 const_iterator &operator -- () {
377 -- it_;
378 return *this;
379 }
380 BOOST_UBLAS_INLINE
381 const_iterator &operator += (difference_type n) {
382 it_ += n;
383 return *this;
384 }
385 BOOST_UBLAS_INLINE
386 const_iterator &operator -= (difference_type n) {
387 it_ -= n;
388 return *this;
389 }
390 BOOST_UBLAS_INLINE
391 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
398 const_reference operator * () const {
399 return functor_type::apply (*it_);
400 }
401 BOOST_UBLAS_INLINE
402 const_reference operator [] (difference_type n) const {
403 return *(*this + n);
404 }
405
406 // Index
407 BOOST_UBLAS_INLINE
408 size_type index () const {
409 return it_.index ();
410 }
411
412 // Assignment
413 BOOST_UBLAS_INLINE
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
422 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
427 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
438 const_iterator begin () const {
439 return find (i: 0);
440 }
441 BOOST_UBLAS_INLINE
442 const_iterator cbegin () const {
443 return begin ();
444 }
445 BOOST_UBLAS_INLINE
446 const_iterator end () const {
447 return find (i: size ());
448 }
449 BOOST_UBLAS_INLINE
450 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
458 const_reverse_iterator rbegin () const {
459 return const_reverse_iterator (end ());
460 }
461 BOOST_UBLAS_INLINE
462 const_reverse_iterator crbegin () const {
463 return rbegin ();
464 }
465 BOOST_UBLAS_INLINE
466 const_reverse_iterator rend () const {
467 return const_reverse_iterator (begin ());
468 }
469 BOOST_UBLAS_INLINE
470 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
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
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
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
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
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
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
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
575 vector_binary (const expression1_type &e1, const expression2_type &e2):
576 e1_ (e1), e2_ (e2) {}
577
578 // Accessors
579 BOOST_UBLAS_INLINE
580 size_type size () const {
581 return BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
582 }
583
584 private:
585 // Accessors
586 BOOST_UBLAS_INLINE
587 const expression1_closure_type &expression1 () const {
588 return e1_;
589 }
590 BOOST_UBLAS_INLINE
591 const expression2_closure_type &expression2 () const {
592 return e2_;
593 }
594
595 public:
596 // Element access
597 BOOST_UBLAS_INLINE
598 const_reference operator () (size_type i) const {
599 return functor_type::apply (e1_ (i), e2_ (i));
600 }
601
602 BOOST_UBLAS_INLINE
603 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
609 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
633 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
666 const_iterator ():
667 container_const_reference<self_type> (), i_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
668 BOOST_UBLAS_INLINE
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
677 void increment (dense_random_access_iterator_tag) {
678 ++ i_; ++ it1_; ++ it2_;
679 }
680 BOOST_UBLAS_INLINE
681 void decrement (dense_random_access_iterator_tag) {
682 -- i_; -- it1_; -- it2_;
683 }
684 BOOST_UBLAS_INLINE
685 void increment (dense_random_access_iterator_tag, difference_type n) {
686 i_ += n; it1_ += n; it2_ += n;
687 }
688 BOOST_UBLAS_INLINE
689 void decrement (dense_random_access_iterator_tag, difference_type n) {
690 i_ -= n; it1_ -= n; it2_ -= n;
691 }
692 BOOST_UBLAS_INLINE
693 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
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
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
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
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
741 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
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
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
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
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
813 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
828 const_iterator &operator ++ () {
829 increment (iterator_category ());
830 return *this;
831 }
832 BOOST_UBLAS_INLINE
833 const_iterator &operator -- () {
834 decrement (iterator_category ());
835 return *this;
836 }
837 BOOST_UBLAS_INLINE
838 const_iterator &operator += (difference_type n) {
839 increment (iterator_category (), n);
840 return *this;
841 }
842 BOOST_UBLAS_INLINE
843 const_iterator &operator -= (difference_type n) {
844 decrement (iterator_category (), n);
845 return *this;
846 }
847 BOOST_UBLAS_INLINE
848 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
855 const_reference operator * () const {
856 return dereference (iterator_category ());
857 }
858 BOOST_UBLAS_INLINE
859 const_reference operator [] (difference_type n) const {
860 return *(*this + n);
861 }
862
863 // Index
864 BOOST_UBLAS_INLINE
865 size_type index () const {
866 return i_;
867 }
868
869 // Assignment
870 BOOST_UBLAS_INLINE
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
883 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
888 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
903 const_iterator begin () const {
904 return find (i: 0);
905 }
906 BOOST_UBLAS_INLINE
907 const_iterator cbegin () const {
908 return begin ();
909 }
910 BOOST_UBLAS_INLINE
911 const_iterator end () const {
912 return find (i: size ());
913 }
914 BOOST_UBLAS_INLINE
915 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
923 const_reverse_iterator rbegin () const {
924 return const_reverse_iterator (end ());
925 }
926 BOOST_UBLAS_INLINE
927 const_reverse_iterator crbegin () const {
928 return rbegin ();
929 }
930 BOOST_UBLAS_INLINE
931 const_reverse_iterator rend () const {
932 return const_reverse_iterator (begin ());
933 }
934 BOOST_UBLAS_INLINE
935 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
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
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
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
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
1030 vector_binary_scalar1 (const expression1_type &e1, const expression2_type &e2):
1031 e1_ (e1), e2_ (e2) {}
1032
1033 // Accessors
1034 BOOST_UBLAS_INLINE
1035 size_type size () const {
1036 return e2_.size ();
1037 }
1038
1039 public:
1040 // Element access
1041 BOOST_UBLAS_INLINE
1042 const_reference operator () (size_type i) const {
1043 return functor_type::apply (e1_, e2_ (i));
1044 }
1045
1046 BOOST_UBLAS_INLINE
1047 const_reference operator [] (size_type i) const {
1048 return functor_type::apply (e1_, e2_ [i]);
1049 }
1050
1051 // Closure comparison
1052 BOOST_UBLAS_INLINE
1053 bool same_closure (const vector_binary_scalar1 &vbs1) const {
1054 return &e1_ == &(vbs1.e1_) &&
1055 (*this).e2_.same_closure (vbs1.e2_);
1056 }
1057
1058 // Iterator types
1059 private:
1060 typedef expression1_type const_subiterator1_type;
1061 typedef typename expression2_type::const_iterator const_subiterator2_type;
1062 typedef const value_type *const_pointer;
1063
1064 public:
1065#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1066 typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
1067 typedef const_iterator iterator;
1068#else
1069 class const_iterator;
1070 typedef const_iterator iterator;
1071#endif
1072
1073 // Element lookup
1074 BOOST_UBLAS_INLINE
1075 const_iterator find (size_type i) const {
1076#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1077 const_subiterator2_type it (e2_.find (i));
1078 return const_iterator (*this, it.index ());
1079#else
1080 return const_iterator (*this, const_subiterator1_type (e1_), e2_.find (i));
1081#endif
1082 }
1083
1084 // Iterator enhances the iterator of the referenced vector expression
1085 // with the binary functor.
1086
1087#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1088 class const_iterator:
1089 public container_const_reference<vector_binary_scalar1>,
1090 public iterator_base_traits<typename E2::const_iterator::iterator_category>::template
1091 iterator_base<const_iterator, value_type>::type {
1092 public:
1093 typedef typename E2::const_iterator::iterator_category iterator_category;
1094 typedef typename vector_binary_scalar1::difference_type difference_type;
1095 typedef typename vector_binary_scalar1::value_type value_type;
1096 typedef typename vector_binary_scalar1::const_reference reference;
1097 typedef typename vector_binary_scalar1::const_pointer pointer;
1098
1099 // Construction and destruction
1100 BOOST_UBLAS_INLINE
1101 const_iterator ():
1102 container_const_reference<self_type> (), it1_ (), it2_ () {}
1103 BOOST_UBLAS_INLINE
1104 const_iterator (const self_type &vbs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
1105 container_const_reference<self_type> (vbs), it1_ (it1), it2_ (it2) {}
1106
1107 // Arithmetic
1108 BOOST_UBLAS_INLINE
1109 const_iterator &operator ++ () {
1110 ++ it2_;
1111 return *this;
1112 }
1113 BOOST_UBLAS_INLINE
1114 const_iterator &operator -- () {
1115 -- it2_;
1116 return *this;
1117 }
1118 BOOST_UBLAS_INLINE
1119 const_iterator &operator += (difference_type n) {
1120 it2_ += n;
1121 return *this;
1122 }
1123 BOOST_UBLAS_INLINE
1124 const_iterator &operator -= (difference_type n) {
1125 it2_ -= n;
1126 return *this;
1127 }
1128 BOOST_UBLAS_INLINE
1129 difference_type operator - (const const_iterator &it) const {
1130 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1131 // FIXME we shouldn't compare floats
1132 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1133 return it2_ - it.it2_;
1134 }
1135
1136 // Dereference
1137 BOOST_UBLAS_INLINE
1138 const_reference operator * () const {
1139 return functor_type::apply (it1_, *it2_);
1140 }
1141 BOOST_UBLAS_INLINE
1142 const_reference operator [] (difference_type n) const {
1143 return *(*this + n);
1144 }
1145
1146 // Index
1147 BOOST_UBLAS_INLINE
1148 size_type index () const {
1149 return it2_.index ();
1150 }
1151
1152 // Assignment
1153 BOOST_UBLAS_INLINE
1154 const_iterator &operator = (const const_iterator &it) {
1155 container_const_reference<self_type>::assign (&it ());
1156 it1_ = it.it1_;
1157 it2_ = it.it2_;
1158 return *this;
1159 }
1160
1161 // Comparison
1162 BOOST_UBLAS_INLINE
1163 bool operator == (const const_iterator &it) const {
1164 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1165 // FIXME we shouldn't compare floats
1166 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1167 return it2_ == it.it2_;
1168 }
1169 BOOST_UBLAS_INLINE
1170 bool operator < (const const_iterator &it) const {
1171 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1172 // FIXME we shouldn't compare floats
1173 // BOOST_UBLAS_CHECK (it1_ == it.it1_, external_logic ());
1174 return it2_ < it.it2_;
1175 }
1176
1177 private:
1178 const_subiterator1_type it1_;
1179 const_subiterator2_type it2_;
1180 };
1181#endif
1182
1183 BOOST_UBLAS_INLINE
1184 const_iterator begin () const {
1185 return find (i: 0);
1186 }
1187 BOOST_UBLAS_INLINE
1188 const_iterator cbegin () const {
1189 return begin ();
1190 }
1191 BOOST_UBLAS_INLINE
1192 const_iterator end () const {
1193 return find (i: size ());
1194 }
1195 BOOST_UBLAS_INLINE
1196 const_iterator cend () const {
1197 return end ();
1198 }
1199
1200 // Reverse iterator
1201 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1202
1203 BOOST_UBLAS_INLINE
1204 const_reverse_iterator rbegin () const {
1205 return const_reverse_iterator (end ());
1206 }
1207 BOOST_UBLAS_INLINE
1208 const_reverse_iterator crbegin () const {
1209 return rbegin ();
1210 }
1211 BOOST_UBLAS_INLINE
1212 const_reverse_iterator rend () const {
1213 return const_reverse_iterator (begin ());
1214 }
1215 BOOST_UBLAS_INLINE
1216 const_reverse_iterator crend () const {
1217 return end ();
1218 }
1219
1220 private:
1221 expression1_closure_type e1_;
1222 expression2_closure_type e2_;
1223 };
1224
1225 template<class E1, class E2, class F>
1226 struct vector_binary_scalar1_traits {
1227 typedef vector_binary_scalar1<E1, E2, F> expression_type; // allow E1 to be builtin type
1228#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1229 typedef expression_type result_type;
1230#else
1231 typedef typename E2::vector_temporary_type result_type;
1232#endif
1233 };
1234
1235 // (t * v) [i] = t * v [i]
1236 template<class T1, class E2>
1237 BOOST_UBLAS_INLINE
1238 typename boost::enable_if< is_convertible<T1, typename E2::value_type >,
1239 typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::result_type
1240 >::type
1241 operator * (const T1 &e1,
1242 const vector_expression<E2> &e2) {
1243 typedef typename vector_binary_scalar1_traits<const T1, E2, scalar_multiplies<T1, typename E2::value_type> >::expression_type expression_type;
1244 return expression_type (e1, e2 ());
1245 }
1246
1247
1248 template<class E1, class E2, class F>
1249 class vector_binary_scalar2:
1250 public vector_expression<vector_binary_scalar2<E1, E2, F> > {
1251
1252 typedef F functor_type;
1253 typedef E1 expression1_type;
1254 typedef E2 expression2_type;
1255 typedef typename E1::const_closure_type expression1_closure_type;
1256 typedef const E2& expression2_closure_type;
1257 typedef vector_binary_scalar2<E1, E2, F> self_type;
1258 public:
1259#ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1260 using vector_expression<vector_binary_scalar2<E1, E2, F> >::operator ();
1261#endif
1262 typedef typename E1::size_type size_type;
1263 typedef typename E1::difference_type difference_type;
1264 typedef typename F::result_type value_type;
1265 typedef value_type const_reference;
1266 typedef const_reference reference;
1267 typedef const self_type const_closure_type;
1268 typedef const_closure_type closure_type;
1269 typedef unknown_storage_tag storage_category;
1270
1271 // Construction and destruction
1272 BOOST_UBLAS_INLINE
1273 vector_binary_scalar2 (const expression1_type &e1, const expression2_type &e2):
1274 e1_ (e1), e2_ (e2) {}
1275
1276 // Accessors
1277 BOOST_UBLAS_INLINE
1278 size_type size () const {
1279 return e1_.size ();
1280 }
1281
1282 public:
1283 // Element access
1284 BOOST_UBLAS_INLINE
1285 const_reference operator () (size_type i) const {
1286 return functor_type::apply (e1_ (i), e2_);
1287 }
1288
1289 BOOST_UBLAS_INLINE
1290 const_reference operator [] (size_type i) const {
1291 return functor_type::apply (e1_ [i], e2_);
1292 }
1293
1294 // Closure comparison
1295 BOOST_UBLAS_INLINE
1296 bool same_closure (const vector_binary_scalar2 &vbs2) const {
1297 return (*this).e1_.same_closure (vbs2.e1_) &&
1298 &e2_ == &(vbs2.e2_);
1299 }
1300
1301 // Iterator types
1302 private:
1303 typedef typename expression1_type::const_iterator const_subiterator1_type;
1304 typedef expression2_type const_subiterator2_type;
1305 typedef const value_type *const_pointer;
1306
1307 public:
1308#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1309 typedef indexed_const_iterator<const_closure_type, typename const_subiterator2_type::iterator_category> const_iterator;
1310 typedef const_iterator iterator;
1311#else
1312 class const_iterator;
1313 typedef const_iterator iterator;
1314#endif
1315
1316 // Element lookup
1317 BOOST_UBLAS_INLINE
1318 const_iterator find (size_type i) const {
1319#ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1320 const_subiterator1_type it (e1_.find (i));
1321 return const_iterator (*this, it.index ());
1322#else
1323 return const_iterator (*this, e1_.find (i), const_subiterator2_type (e2_));
1324#endif
1325 }
1326
1327 // Iterator enhances the iterator of the referenced vector expression
1328 // with the binary functor.
1329
1330#ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1331 class const_iterator:
1332 public container_const_reference<vector_binary_scalar2>,
1333 public iterator_base_traits<typename E1::const_iterator::iterator_category>::template
1334 iterator_base<const_iterator, value_type>::type {
1335 public:
1336 typedef typename E1::const_iterator::iterator_category iterator_category;
1337 typedef typename vector_binary_scalar2::difference_type difference_type;
1338 typedef typename vector_binary_scalar2::value_type value_type;
1339 typedef typename vector_binary_scalar2::const_reference reference;
1340 typedef typename vector_binary_scalar2::const_pointer pointer;
1341
1342 // Construction and destruction
1343 BOOST_UBLAS_INLINE
1344 const_iterator ():
1345 container_const_reference<self_type> (), it1_ (), it2_ () {}
1346 BOOST_UBLAS_INLINE
1347 const_iterator (const self_type &vbs, const const_subiterator1_type &it1, const const_subiterator2_type &it2):
1348 container_const_reference<self_type> (vbs), it1_ (it1), it2_ (it2) {}
1349
1350 // Arithmetic
1351 BOOST_UBLAS_INLINE
1352 const_iterator &operator ++ () {
1353 ++ it1_;
1354 return *this;
1355 }
1356 BOOST_UBLAS_INLINE
1357 const_iterator &operator -- () {
1358 -- it1_;
1359 return *this;
1360 }
1361 BOOST_UBLAS_INLINE
1362 const_iterator &operator += (difference_type n) {
1363 it1_ += n;
1364 return *this;
1365 }
1366 BOOST_UBLAS_INLINE
1367 const_iterator &operator -= (difference_type n) {
1368 it1_ -= n;
1369 return *this;
1370 }
1371 BOOST_UBLAS_INLINE
1372 difference_type operator - (const const_iterator &it) const {
1373 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1374 // FIXME we shouldn't compare floats
1375 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
1376 return it1_ - it.it1_;
1377 }
1378
1379 // Dereference
1380 BOOST_UBLAS_INLINE
1381 const_reference operator * () const {
1382 return functor_type::apply (*it1_, it2_);
1383 }
1384 BOOST_UBLAS_INLINE
1385 const_reference operator [] (difference_type n) const {
1386 return *(*this + n);
1387 }
1388
1389 // Index
1390 BOOST_UBLAS_INLINE
1391 size_type index () const {
1392 return it1_.index ();
1393 }
1394
1395 // Assignment
1396 BOOST_UBLAS_INLINE
1397 const_iterator &operator = (const const_iterator &it) {
1398 container_const_reference<self_type>::assign (&it ());
1399 it1_ = it.it1_;
1400 it2_ = it.it2_;
1401 return *this;
1402 }
1403
1404 // Comparison
1405 BOOST_UBLAS_INLINE
1406 bool operator == (const const_iterator &it) const {
1407 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1408 // FIXME we shouldn't compare floats
1409 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
1410 return it1_ == it.it1_;
1411 }
1412 BOOST_UBLAS_INLINE
1413 bool operator < (const const_iterator &it) const {
1414 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1415 // FIXME we shouldn't compare floats
1416 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
1417 return it1_ < it.it1_;
1418 }
1419
1420 private:
1421 const_subiterator1_type it1_;
1422 const_subiterator2_type it2_;
1423 };
1424#endif
1425
1426 BOOST_UBLAS_INLINE
1427 const_iterator begin () const {
1428 return find (i: 0);
1429 }
1430 BOOST_UBLAS_INLINE
1431 const_iterator cbegin () const {
1432 return begin ();
1433 }
1434 BOOST_UBLAS_INLINE
1435 const_iterator end () const {
1436 return find (i: size ());
1437 }
1438 BOOST_UBLAS_INLINE
1439 const_iterator cend () const {
1440 return end ();
1441 }
1442
1443 // Reverse iterator
1444 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1445
1446 BOOST_UBLAS_INLINE
1447 const_reverse_iterator rbegin () const {
1448 return const_reverse_iterator (end ());
1449 }
1450 BOOST_UBLAS_INLINE
1451 const_reverse_iterator crbegin () const {
1452 return rbegin ();
1453 }
1454 BOOST_UBLAS_INLINE
1455 const_reverse_iterator rend () const {
1456 return const_reverse_iterator (begin ());
1457 }
1458 BOOST_UBLAS_INLINE
1459 const_reverse_iterator crend () const {
1460 return rend ();
1461 }
1462
1463 private:
1464 expression1_closure_type e1_;
1465 expression2_closure_type e2_;
1466 };
1467
1468 template<class E1, class E2, class F>
1469 struct vector_binary_scalar2_traits {
1470 typedef vector_binary_scalar2<E1, E2, F> expression_type; // allow E2 to be builtin type
1471#ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1472 typedef expression_type result_type;
1473#else
1474 typedef typename E1::vector_temporary_type result_type;
1475#endif
1476 };
1477
1478 // (v * t) [i] = v [i] * t
1479 template<class E1, class T2>
1480 BOOST_UBLAS_INLINE
1481 typename boost::enable_if< is_convertible<T2, typename E1::value_type >,
1482 typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::result_type
1483 >::type
1484 operator * (const vector_expression<E1> &e1,
1485 const T2 &e2) {
1486 typedef typename vector_binary_scalar2_traits<E1, const T2, scalar_multiplies<typename E1::value_type, T2> >::expression_type expression_type;
1487 return expression_type (e1 (), e2);
1488 }
1489
1490 // (v / t) [i] = v [i] / t
1491 template<class E1, class T2>
1492 BOOST_UBLAS_INLINE
1493 typename boost::enable_if< is_convertible<T2, typename E1::value_type >,
1494 typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::result_type
1495 >::type
1496 operator / (const vector_expression<E1> &e1,
1497 const T2 &e2) {
1498 typedef typename vector_binary_scalar2_traits<E1, const T2, scalar_divides<typename E1::value_type, T2> >::expression_type expression_type;
1499 return expression_type (e1 (), e2);
1500 }
1501
1502
1503 template<class E, class F>
1504 class vector_scalar_unary:
1505 public scalar_expression<vector_scalar_unary<E, F> > {
1506
1507 typedef E expression_type;
1508 typedef F functor_type;
1509 typedef typename E::const_closure_type expression_closure_type;
1510 typedef typename E::const_iterator::iterator_category iterator_category;
1511 typedef vector_scalar_unary<E, F> self_type;
1512 public:
1513 typedef typename F::result_type value_type;
1514 typedef typename E::difference_type difference_type;
1515 typedef const self_type const_closure_type;
1516 typedef const_closure_type closure_type;
1517 typedef unknown_storage_tag storage_category;
1518
1519 // Construction and destruction
1520 BOOST_UBLAS_INLINE
1521 explicit vector_scalar_unary (const expression_type &e):
1522 e_ (e) {}
1523
1524 private:
1525 // Expression accessors
1526 BOOST_UBLAS_INLINE
1527 const expression_closure_type &expression () const {
1528 return e_;
1529 }
1530
1531 public:
1532 BOOST_UBLAS_INLINE
1533 operator value_type () const {
1534 return evaluate (iterator_category ());
1535 }
1536
1537 private:
1538 // Dense random access specialization
1539 BOOST_UBLAS_INLINE
1540 value_type evaluate (dense_random_access_iterator_tag) const {
1541#ifdef BOOST_UBLAS_USE_INDEXING
1542 return functor_type::apply (e_);
1543#elif BOOST_UBLAS_USE_ITERATING
1544 difference_type size = e_.size ();
1545 return functor_type::apply (size, e_.begin ());
1546#else
1547 difference_type size = e_.size ();
1548 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
1549 return functor_type::apply (size, e_.begin ());
1550 else
1551 return functor_type::apply (e_);
1552#endif
1553 }
1554
1555 // Packed bidirectional specialization
1556 BOOST_UBLAS_INLINE
1557 value_type evaluate (packed_random_access_iterator_tag) const {
1558 return functor_type::apply (e_.begin (), e_.end ());
1559 }
1560
1561 // Sparse bidirectional specialization
1562 BOOST_UBLAS_INLINE
1563 value_type evaluate (sparse_bidirectional_iterator_tag) const {
1564 return functor_type::apply (e_.begin (), e_.end ());
1565 }
1566
1567 private:
1568 expression_closure_type e_;
1569 };
1570
1571 template<class E, class F>
1572 struct vector_scalar_unary_traits {
1573 typedef vector_scalar_unary<E, F> expression_type;
1574#if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET)
1575// FIXME don't define USE_SCALAR_ET other then for testing
1576// They do not work for complex types
1577 typedef expression_type result_type;
1578#else
1579 typedef typename F::result_type result_type;
1580#endif
1581 };
1582
1583 // sum v = sum (v [i])
1584 template<class E>
1585 BOOST_UBLAS_INLINE
1586 typename vector_scalar_unary_traits<E, vector_sum<E> >::result_type
1587 sum (const vector_expression<E> &e) {
1588 typedef typename vector_scalar_unary_traits<E, vector_sum<E> >::expression_type expression_type;
1589 return expression_type (e ());
1590 }
1591
1592 // real: norm_1 v = sum (abs (v [i]))
1593 // complex: norm_1 v = sum (abs (real (v [i])) + abs (imag (v [i])))
1594 template<class E>
1595 BOOST_UBLAS_INLINE
1596 typename vector_scalar_unary_traits<E, vector_norm_1<E> >::result_type
1597 norm_1 (const vector_expression<E> &e) {
1598 typedef typename vector_scalar_unary_traits<E, vector_norm_1<E> >::expression_type expression_type;
1599 return expression_type (e ());
1600 }
1601
1602 // real: norm_2 v = sqrt (sum (v [i] * v [i]))
1603 // complex: norm_2 v = sqrt (sum (v [i] * conj (v [i])))
1604 template<class E>
1605 BOOST_UBLAS_INLINE
1606 typename vector_scalar_unary_traits<E, vector_norm_2<E> >::result_type
1607 norm_2 (const vector_expression<E> &e) {
1608 typedef typename vector_scalar_unary_traits<E, vector_norm_2<E> >::expression_type expression_type;
1609 return expression_type (e ());
1610 }
1611
1612 // real: norm_2_square v = sum(v [i] * v [i])
1613 // complex: norm_2_square v = sum(v [i] * conj (v [i]))
1614 template<class E>
1615 BOOST_UBLAS_INLINE
1616 typename vector_scalar_unary_traits<E, vector_norm_2_square<E> >::result_type
1617 norm_2_square (const vector_expression<E> &e) {
1618 typedef typename vector_scalar_unary_traits<E, vector_norm_2_square<E> >::expression_type expression_type;
1619 return expression_type (e ());
1620 }
1621
1622 // real: norm_inf v = maximum (abs (v [i]))
1623 // complex: norm_inf v = maximum (maximum (abs (real (v [i])), abs (imag (v [i]))))
1624 template<class E>
1625 BOOST_UBLAS_INLINE
1626 typename vector_scalar_unary_traits<E, vector_norm_inf<E> >::result_type
1627 norm_inf (const vector_expression<E> &e) {
1628 typedef typename vector_scalar_unary_traits<E, vector_norm_inf<E> >::expression_type expression_type;
1629 return expression_type (e ());
1630 }
1631
1632 // real: index_norm_inf v = minimum (i: abs (v [i]) == maximum (abs (v [i])))
1633 template<class E>
1634 BOOST_UBLAS_INLINE
1635 typename vector_scalar_unary_traits<E, vector_index_norm_inf<E> >::result_type
1636 index_norm_inf (const vector_expression<E> &e) {
1637 typedef typename vector_scalar_unary_traits<E, vector_index_norm_inf<E> >::expression_type expression_type;
1638 return expression_type (e ());
1639 }
1640
1641 template<class E1, class E2, class F>
1642 class vector_scalar_binary:
1643 public scalar_expression<vector_scalar_binary<E1, E2, F> > {
1644
1645 typedef E1 expression1_type;
1646 typedef E2 expression2_type;
1647 typedef F functor_type;
1648 typedef typename E1::const_closure_type expression1_closure_type;
1649 typedef typename E2::const_closure_type expression2_closure_type;
1650 typedef typename iterator_restrict_traits<typename E1::const_iterator::iterator_category,
1651 typename E2::const_iterator::iterator_category>::iterator_category iterator_category;
1652 typedef vector_scalar_binary<E1, E2, F> self_type;
1653 public:
1654 static const unsigned complexity = 1;
1655 typedef typename F::result_type value_type;
1656 typedef typename E1::difference_type difference_type;
1657 typedef const self_type const_closure_type;
1658 typedef const_closure_type closure_type;
1659 typedef unknown_storage_tag storage_category;
1660
1661 // Construction and destruction
1662 BOOST_UBLAS_INLINE
1663 vector_scalar_binary (const expression1_type &e1, const expression2_type &e2):
1664 e1_ (e1), e2_ (e2) {}
1665
1666 private:
1667 // Accessors
1668 BOOST_UBLAS_INLINE
1669 const expression1_closure_type &expression1 () const {
1670 return e1_;
1671 }
1672 BOOST_UBLAS_INLINE
1673 const expression2_closure_type &expression2 () const {
1674 return e2_;
1675 }
1676
1677 public:
1678 BOOST_UBLAS_INLINE
1679 operator value_type () const {
1680 return evaluate (iterator_category ());
1681 }
1682
1683 private:
1684 // Dense random access specialization
1685 BOOST_UBLAS_INLINE
1686 value_type evaluate (dense_random_access_iterator_tag) const {
1687 BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
1688#ifdef BOOST_UBLAS_USE_INDEXING
1689 return functor_type::apply (e1_, e2_);
1690#elif BOOST_UBLAS_USE_ITERATING
1691 difference_type size = BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
1692 return functor_type::apply (size, e1_.begin (), e2_.begin ());
1693#else
1694 difference_type size = BOOST_UBLAS_SAME (e1_.size (), e2_.size ());
1695 if (size >= BOOST_UBLAS_ITERATOR_THRESHOLD)
1696 return functor_type::apply (size, e1_.begin (), e2_.begin ());
1697 else
1698 return functor_type::apply (e1_, e2_);
1699#endif
1700 }
1701
1702 // Packed bidirectional specialization
1703 BOOST_UBLAS_INLINE
1704 value_type evaluate (packed_random_access_iterator_tag) const {
1705 BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
1706 return functor_type::apply (e1_.begin (), e1_.end (), e2_.begin (), e2_.end ());
1707 }
1708
1709 // Sparse bidirectional specialization
1710 BOOST_UBLAS_INLINE
1711 value_type evaluate (sparse_bidirectional_iterator_tag) const {
1712 BOOST_UBLAS_CHECK (e1_.size () == e2_.size (), external_logic());
1713 return functor_type::apply (e1_.begin (), e1_.end (), e2_.begin (), e2_.end (), sparse_bidirectional_iterator_tag ());
1714 }
1715
1716 private:
1717 expression1_closure_type e1_;
1718 expression2_closure_type e2_;
1719 };
1720
1721 template<class E1, class E2, class F>
1722 struct vector_scalar_binary_traits {
1723 typedef vector_scalar_binary<E1, E2, F> expression_type;
1724#if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET)
1725// FIXME don't define USE_SCALAR_ET other then for testing
1726// They do not work for complex types
1727 typedef expression_type result_type;
1728#else
1729 typedef typename F::result_type result_type;
1730#endif
1731 };
1732
1733 // inner_prod (v1, v2) = sum (v1 [i] * v2 [i])
1734 template<class E1, class E2>
1735 BOOST_UBLAS_INLINE
1736 typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
1737 typename promote_traits<typename E1::value_type,
1738 typename E2::value_type>::promote_type> >::result_type
1739 inner_prod (const vector_expression<E1> &e1,
1740 const vector_expression<E2> &e2) {
1741 typedef typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
1742 typename promote_traits<typename E1::value_type,
1743 typename E2::value_type>::promote_type> >::expression_type expression_type;
1744 return expression_type (e1 (), e2 ());
1745 }
1746
1747 template<class E1, class E2>
1748 BOOST_UBLAS_INLINE
1749 typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
1750 typename type_traits<typename promote_traits<typename E1::value_type,
1751 typename E2::value_type>::promote_type>::precision_type> >::result_type
1752 prec_inner_prod (const vector_expression<E1> &e1,
1753 const vector_expression<E2> &e2) {
1754 typedef typename vector_scalar_binary_traits<E1, E2, vector_inner_prod<E1, E2,
1755 typename type_traits<typename promote_traits<typename E1::value_type,
1756 typename E2::value_type>::promote_type>::precision_type> >::expression_type expression_type;
1757 return expression_type (e1 (), e2 ());
1758 }
1759
1760}}}
1761
1762#endif
1763

source code of include/boost/numeric/ublas/vector_expression.hpp