2 // Copyright (c) 2000-2002
3 // Joerg Walter, Mathias Koch
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)
9 // The authors gratefully acknowledge the support of
10 // GeNeSys mbH & Co. KG in producing this work.
13 #ifndef _BOOST_UBLAS_VECTOR_EXPRESSION_
14 #define _BOOST_UBLAS_VECTOR_EXPRESSION_
16 #include <boost/numeric/ublas/expression_types.hpp>
19 // Expression templates based on ideas of Todd Veldhuizen and Geoffrey Furnish
20 // Iterators based on ideas of Jeremy Siek
22 // Classes that model the Vector Expression concept
24 namespace boost
{ namespace numeric
{ namespace ublas
{
27 class vector_reference
:
28 public vector_expression
<vector_reference
<E
> > {
30 typedef vector_reference
<E
> self_type
;
32 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
33 using vector_expression
<vector_reference
<E
> >::operator ();
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
;
47 // Construction and destruction
49 explicit vector_reference (referred_type
&e
):
54 size_type
size () const {
55 return expression ().size ();
59 // Expression accessors - const correct
61 const referred_type
&expression () const {
65 referred_type
&expression () {
71 #ifndef BOOST_UBLAS_REFERENCE_CONST_MEMBER
73 const_reference
operator () (size_type i
) const {
74 return expression () (i
);
77 reference
operator () (size_type i
) {
78 return expression () (i
);
82 const_reference
operator [] (size_type i
) const {
83 return expression () [i
];
86 reference
operator [] (size_type i
) {
87 return expression () [i
];
91 reference
operator () (size_type i
) const {
92 return expression () (i
);
96 reference
operator [] (size_type i
) const {
97 return expression () [i
];
103 vector_reference
&operator = (const vector_reference
&v
) {
104 expression ().operator = (v
);
109 vector_reference
&operator = (const vector_expression
<AE
> &ae
) {
110 expression ().operator = (ae
);
115 vector_reference
&assign (const vector_expression
<AE
> &ae
) {
116 expression ().assign (ae
);
121 vector_reference
&operator += (const vector_expression
<AE
> &ae
) {
122 expression ().operator += (ae
);
127 vector_reference
&plus_assign (const vector_expression
<AE
> &ae
) {
128 expression ().plus_assign (ae
);
133 vector_reference
&operator -= (const vector_expression
<AE
> &ae
) {
134 expression ().operator -= (ae
);
139 vector_reference
&minus_assign (const vector_expression
<AE
> &ae
) {
140 expression ().minus_assign (ae
);
145 vector_reference
&operator *= (const AT
&at
) {
146 expression ().operator *= (at
);
151 vector_reference
&operator /= (const AT
&at
) {
152 expression ().operator /= (at
);
158 void swap (vector_reference
&v
) {
159 expression ().swap (v
.expression ());
162 // Closure comparison
164 bool same_closure (const vector_reference
&vr
) const {
165 return &(*this).e_
== &vr
.e_
;
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
;
176 const_iterator
find (size_type i
) const {
177 return expression ().find (i
);
180 iterator
find (size_type i
) {
181 return expression ().find (i
);
184 // Iterator is the iterator of the referenced expression.
187 const_iterator
begin () const {
188 return expression ().begin ();
191 const_iterator
end () const {
192 return expression ().end ();
197 return expression ().begin ();
201 return expression ().end ();
205 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
206 typedef reverse_iterator_base
<iterator
> reverse_iterator
;
209 const_reverse_iterator
rbegin () const {
210 return const_reverse_iterator (end ());
213 const_reverse_iterator
rend () const {
214 return const_reverse_iterator (begin ());
217 reverse_iterator
rbegin () {
218 return reverse_iterator (end ());
221 reverse_iterator
rend () {
222 return reverse_iterator (begin ());
230 template<class E
, class F
>
232 public vector_expression
<vector_unary
<E
, F
> > {
234 typedef F functor_type
;
235 typedef typename
boost::mpl::if_
<boost::is_same
<F
, scalar_identity
<typename
E::value_type
> >,
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
;
243 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
244 using vector_expression
<vector_unary
<E
, F
> >::operator ();
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
;
257 // Construction and destruction
259 // May be used as mutable expression.
260 explicit vector_unary (expression_type
&e
):
265 size_type
size () const {
270 // Expression accessors
272 const expression_closure_type
&expression () const {
279 const_reference
operator () (size_type i
) const {
280 return functor_type::apply (e_ (i
));
283 reference
operator () (size_type i
) {
284 BOOST_STATIC_ASSERT ((boost::is_same
<functor_type
, scalar_identity
<value_type
> >::value
));
289 const_reference
operator [] (size_type i
) const {
290 return functor_type::apply (e_
[i
]);
293 reference
operator [] (size_type i
) {
294 BOOST_STATIC_ASSERT ((boost::is_same
<functor_type
, scalar_identity
<value_type
> >::value
));
298 // Closure comparison
300 bool same_closure (const vector_unary
&vu
) const {
301 return (*this).expression ().same_closure (vu
.expression ());
306 typedef typename
E::const_iterator const_subiterator_type
;
307 typedef const value_type
*const_pointer
;
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
;
314 class const_iterator
;
315 typedef const_iterator iterator
;
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 ());
325 return const_iterator (*this, e_
.find (i
));
329 // Iterator enhances the iterator of the referenced expression
330 // with the unary functor.
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
{
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
;
344 // Construction and destruction
347 container_const_reference
<self_type
> (), it_ () {}
349 const_iterator (const self_type
&vu
, const const_subiterator_type
&it
):
350 container_const_reference
<self_type
> (vu
), it_ (it
) {}
354 const_iterator
&operator ++ () {
359 const_iterator
&operator -- () {
364 const_iterator
&operator += (difference_type n
) {
369 const_iterator
&operator -= (difference_type n
) {
374 difference_type
operator - (const const_iterator
&it
) const {
375 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
381 const_reference
operator * () const {
382 return functor_type::apply (*it_
);
385 const_reference
operator [] (difference_type n
) const {
391 size_type
index () const {
397 const_iterator
&operator = (const const_iterator
&it
) {
398 container_const_reference
<self_type
>::assign (&it ());
405 bool operator == (const const_iterator
&it
) const {
406 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
407 return it_
== it
.it_
;
410 bool operator < (const const_iterator
&it
) const {
411 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
416 const_subiterator_type it_
;
421 const_iterator
begin () const {
425 const_iterator
end () const {
426 return find (size ());
430 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
433 const_reverse_iterator
rbegin () const {
434 return const_reverse_iterator (end ());
437 const_reverse_iterator
rend () const {
438 return const_reverse_iterator (begin ());
442 expression_closure_type e_
;
445 template<class E
, class F
>
446 struct vector_unary_traits
{
447 typedef vector_unary
<E
, F
> expression_type
;
449 // #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
450 typedef expression_type result_type
;
452 // typedef typename E::vector_temporary_type result_type;
456 // (- v) [i] = - v [i]
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 ());
465 // (conj v) [i] = conj (v [i])
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 ());
474 // (real v) [i] = real (v [i])
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 ());
483 // (imag v) [i] = imag (v [i])
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 ());
492 // (trans v) [i] = v [i]
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 ());
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 ());
508 // (herm v) [i] = conj (v [i])
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 ());
517 template<class E1
, class E2
, class F
>
519 public vector_expression
<vector_binary
<E1
, E2
, F
> > {
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
;
528 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
529 using vector_expression
<vector_binary
<E1
, E2
, F
> >::operator ();
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
;
540 // Construction and destruction
542 vector_binary (const expression1_type
&e1
, const expression2_type
&e2
):
543 e1_ (e1
), e2_ (e2
) {}
547 size_type
size () const {
548 return BOOST_UBLAS_SAME (e1_
.size (), e2_
.size ());
554 const expression1_closure_type
&expression1 () const {
558 const expression2_closure_type
&expression2 () const {
565 const_reference
operator () (size_type i
) const {
566 return functor_type::apply (e1_ (i
), e2_ (i
));
570 const_reference
operator [] (size_type i
) const {
571 return functor_type::apply (e1_
[i
], e2_
[i
]);
574 // Closure comparison
576 bool same_closure (const vector_binary
&vb
) const {
577 return (*this).expression1 ().same_closure (vb
.expression1 ()) &&
578 (*this).expression2 ().same_closure (vb
.expression2 ());
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
;
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
;
594 class const_iterator
;
595 typedef const_iterator iterator
;
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
);
610 return const_iterator (*this, i
, it1
, it1_end
, it2
, it2_end
);
614 // Iterator merges the iterators of the referenced expressions and
615 // enhances them with the binary functor.
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
{
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
;
631 // Construction and destruction
634 container_const_reference
<self_type
> (), i_ (), it1_ (), it1_end_ (), it2_ (), it2_end_ () {}
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
) {}
642 // Dense specializations
644 void increment (dense_random_access_iterator_tag
) {
645 ++ i_
; ++ it1_
; ++ it2_
;
648 void decrement (dense_random_access_iterator_tag
) {
649 -- i_
; -- it1_
; -- it2_
;
652 void increment (dense_random_access_iterator_tag
, difference_type n
) {
653 i_
+= n
; it1_
+= n
; it2_
+= n
;
656 void decrement (dense_random_access_iterator_tag
, difference_type n
) {
657 i_
-= n
; it1_
-= n
; it2_
-= n
;
660 value_type
dereference (dense_random_access_iterator_tag
) const {
661 return functor_type::apply (*it1_
, *it2_
);
664 // Packed specializations
666 void increment (packed_random_access_iterator_tag
) {
667 if (it1_
!= it1_end_
)
668 if (it1_
.index () <= i_
)
670 if (it2_
!= it2_end_
)
671 if (it2_
.index () <= i_
)
676 void decrement (packed_random_access_iterator_tag
) {
677 if (it1_
!= it1_end_
)
678 if (i_
<= it1_
.index ())
680 if (it2_
!= it2_end_
)
681 if (i_
<= it2_
.index ())
686 void increment (packed_random_access_iterator_tag
, difference_type n
) {
688 increment (packed_random_access_iterator_tag ());
692 decrement (packed_random_access_iterator_tag ());
697 void decrement (packed_random_access_iterator_tag
, difference_type n
) {
699 decrement (packed_random_access_iterator_tag ());
703 increment (packed_random_access_iterator_tag ());
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_
)
713 value_type t2
= value_type
/*zero*/();
714 if (it2_
!= it2_end_
)
715 if (it2_
.index () == i_
)
717 return functor_type::apply (t1
, t2
);
720 // Sparse specializations
722 void increment (sparse_bidirectional_iterator_tag
) {
723 size_type index1
= (*this) ().size ();
724 if (it1_
!= it1_end_
) {
725 if (it1_
.index () <= i_
)
727 if (it1_
!= it1_end_
)
728 index1
= it1_
.index ();
730 size_type index2
= (*this) ().size ();
731 if (it2_
!= it2_end_
) {
732 if (it2_
.index () <= i_
)
734 if (it2_
!= it2_end_
)
735 index2
= it2_
.index ();
737 i_
= (std::min
) (index1
, index2
);
740 void decrement (sparse_bidirectional_iterator_tag
) {
741 size_type index1
= (*this) ().size ();
742 if (it1_
!= it1_end_
) {
743 if (i_
<= it1_
.index ())
745 if (it1_
!= it1_end_
)
746 index1
= it1_
.index ();
748 size_type index2
= (*this) ().size ();
749 if (it2_
!= it2_end_
) {
750 if (i_
<= it2_
.index ())
752 if (it2_
!= it2_end_
)
753 index2
= it2_
.index ();
755 i_
= (std::max
) (index1
, index2
);
758 void increment (sparse_bidirectional_iterator_tag
, difference_type n
) {
760 increment (sparse_bidirectional_iterator_tag ());
764 decrement (sparse_bidirectional_iterator_tag ());
769 void decrement (sparse_bidirectional_iterator_tag
, difference_type n
) {
771 decrement (sparse_bidirectional_iterator_tag ());
775 increment (sparse_bidirectional_iterator_tag ());
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_
)
785 value_type t2
= value_type
/*zero*/();
786 if (it2_
!= it2_end_
)
787 if (it2_
.index () == i_
)
789 return functor_type::apply (t1
, t2
);
795 const_iterator
&operator ++ () {
796 increment (iterator_category ());
800 const_iterator
&operator -- () {
801 decrement (iterator_category ());
805 const_iterator
&operator += (difference_type n
) {
806 increment (iterator_category (), n
);
810 const_iterator
&operator -= (difference_type n
) {
811 decrement (iterator_category (), n
);
815 difference_type
operator - (const const_iterator
&it
) const {
816 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
817 return index () - it
.index ();
822 const_reference
operator * () const {
823 return dereference (iterator_category ());
826 const_reference
operator [] (difference_type n
) const {
832 size_type
index () const {
838 const_iterator
&operator = (const const_iterator
&it
) {
839 container_const_reference
<self_type
>::assign (&it ());
842 it1_end_
= it
.it1_end_
;
844 it2_end_
= it
.it2_end_
;
850 bool operator == (const const_iterator
&it
) const {
851 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
852 return index () == it
.index ();
855 bool operator < (const const_iterator
&it
) const {
856 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
857 return index () < it
.index ();
862 const_subiterator1_type it1_
;
863 const_subiterator1_type it1_end_
;
864 const_subiterator2_type it2_
;
865 const_subiterator2_type it2_end_
;
870 const_iterator
begin () const {
874 const_iterator
end () const {
875 return find (size ());
879 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
882 const_reverse_iterator
rbegin () const {
883 return const_reverse_iterator (end ());
886 const_reverse_iterator
rend () const {
887 return const_reverse_iterator (begin ());
891 expression1_closure_type e1_
;
892 expression2_closure_type e2_
;
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
;
901 typedef typename
E1::vector_temporary_type result_type
;
905 // (v1 + v2) [i] = v1 [i] + v2 [i]
906 template<class E1
, class E2
>
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 ());
917 // (v1 - v2) [i] = v1 [i] - v2 [i]
918 template<class E1
, class E2
>
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 ());
929 // (v1 * v2) [i] = v1 [i] * v2 [i]
930 template<class E1
, class E2
>
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 ());
941 // (v1 / v2) [i] = v1 [i] / v2 [i]
942 template<class E1
, class E2
>
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 ());
954 template<class E1
, class E2
, class F
>
955 class vector_binary_scalar1
:
956 public vector_expression
<vector_binary_scalar1
<E1
, E2
, F
> > {
958 typedef F functor_type
;
959 typedef E1 expression1_type
;
960 typedef E2 expression2_type
;
962 typedef const E1
& expression1_closure_type
;
963 typedef typename
E2::const_closure_type expression2_closure_type
;
965 typedef vector_binary_scalar1
<E1
, E2
, F
> self_type
;
967 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
968 using vector_expression
<vector_binary_scalar1
<E1
, E2
, F
> >::operator ();
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
;
979 // Construction and destruction
981 vector_binary_scalar1 (const expression1_type
&e1
, const expression2_type
&e2
):
982 e1_ (e1
), e2_ (e2
) {}
986 size_type
size () const {
993 const_reference
operator () (size_type i
) const {
994 return functor_type::apply (e1_
, e2_ (i
));
998 const_reference
operator [] (size_type i
) const {
999 return functor_type::apply (e1_
, e2_
[i
]);
1002 // Closure comparison
1004 bool same_closure (const vector_binary_scalar1
&vbs1
) const {
1005 return &e1_
== &(vbs1
.e1_
) &&
1006 (*this).e2_
.same_closure (vbs1
.e2_
);
1011 typedef expression1_type const_subiterator1_type
;
1012 typedef typename
expression2_type::const_iterator const_subiterator2_type
;
1013 typedef const value_type
*const_pointer
;
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
;
1020 class const_iterator
;
1021 typedef const_iterator iterator
;
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 ());
1031 return const_iterator (*this, const_subiterator1_type (e1_
), e2_
.find (i
));
1035 // Iterator enhances the iterator of the referenced vector expression
1036 // with the binary functor.
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
{
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
;
1050 // Construction and destruction
1053 container_const_reference
<self_type
> (), it1_ (), it2_ () {}
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
) {}
1060 const_iterator
&operator ++ () {
1065 const_iterator
&operator -- () {
1070 const_iterator
&operator += (difference_type n
) {
1075 const_iterator
&operator -= (difference_type n
) {
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_
;
1089 const_reference
operator * () const {
1090 return functor_type::apply (it1_
, *it2_
);
1093 const_reference
operator [] (difference_type n
) const {
1094 return *(*this + n
);
1099 size_type
index () const {
1100 return it2_
.index ();
1105 const_iterator
&operator = (const const_iterator
&it
) {
1106 container_const_reference
<self_type
>::assign (&it ());
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_
;
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_
;
1129 const_subiterator1_type it1_
;
1130 const_subiterator2_type it2_
;
1135 const_iterator
begin () const {
1139 const_iterator
end () const {
1140 return find (size ());
1144 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
1147 const_reverse_iterator
rbegin () const {
1148 return const_reverse_iterator (end ());
1151 const_reverse_iterator
rend () const {
1152 return const_reverse_iterator (begin ());
1156 expression1_closure_type e1_
;
1157 expression2_closure_type e2_
;
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
;
1166 typedef typename
E2::vector_temporary_type result_type
;
1170 // (t * v) [i] = t * v [i]
1171 template<class T1
, class E2
>
1173 typename vector_binary_scalar1_traits
<const T1
, E2
, scalar_multiplies
<T1
, typename
E2::value_type
> >::result_type
1174 operator * (const T1
&e1
,
1175 const vector_expression
<E2
> &e2
) {
1176 typedef typename vector_binary_scalar1_traits
<const T1
, E2
, scalar_multiplies
<T1
, typename
E2::value_type
> >::expression_type expression_type
;
1177 return expression_type (e1
, e2 ());
1181 template<class E1
, class E2
, class F
>
1182 class vector_binary_scalar2
:
1183 public vector_expression
<vector_binary_scalar2
<E1
, E2
, F
> > {
1185 typedef F functor_type
;
1186 typedef E1 expression1_type
;
1187 typedef E2 expression2_type
;
1188 typedef typename
E1::const_closure_type expression1_closure_type
;
1189 typedef const E2
& expression2_closure_type
;
1190 typedef vector_binary_scalar2
<E1
, E2
, F
> self_type
;
1192 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1193 using vector_expression
<vector_binary_scalar2
<E1
, E2
, F
> >::operator ();
1195 typedef typename
E1::size_type size_type
;
1196 typedef typename
E1::difference_type difference_type
;
1197 typedef typename
F::result_type value_type
;
1198 typedef value_type const_reference
;
1199 typedef const_reference reference
;
1200 typedef const self_type const_closure_type
;
1201 typedef const_closure_type closure_type
;
1202 typedef unknown_storage_tag storage_category
;
1204 // Construction and destruction
1206 vector_binary_scalar2 (const expression1_type
&e1
, const expression2_type
&e2
):
1207 e1_ (e1
), e2_ (e2
) {}
1211 size_type
size () const {
1218 const_reference
operator () (size_type i
) const {
1219 return functor_type::apply (e1_ (i
), e2_
);
1223 const_reference
operator [] (size_type i
) const {
1224 return functor_type::apply (e1_
[i
], e2_
);
1227 // Closure comparison
1229 bool same_closure (const vector_binary_scalar2
&vbs2
) const {
1230 return (*this).e1_
.same_closure (vbs2
.e1_
) &&
1231 &e2_
== &(vbs2
.e2_
);
1236 typedef typename
expression1_type::const_iterator const_subiterator1_type
;
1237 typedef expression2_type const_subiterator2_type
;
1238 typedef const value_type
*const_pointer
;
1241 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1242 typedef indexed_const_iterator
<const_closure_type
, typename
const_subiterator2_type::iterator_category
> const_iterator
;
1243 typedef const_iterator iterator
;
1245 class const_iterator
;
1246 typedef const_iterator iterator
;
1251 const_iterator
find (size_type i
) const {
1252 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1253 const_subiterator1_type
it (e1_
.find (i
));
1254 return const_iterator (*this, it
.index ());
1256 return const_iterator (*this, e1_
.find (i
), const_subiterator2_type (e2_
));
1260 // Iterator enhances the iterator of the referenced vector expression
1261 // with the binary functor.
1263 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1264 class const_iterator
:
1265 public container_const_reference
<vector_binary_scalar2
>,
1266 public iterator_base_traits
<typename
E1::const_iterator::iterator_category
>::template
1267 iterator_base
<const_iterator
, value_type
>::type
{
1269 typedef typename
E1::const_iterator::iterator_category iterator_category
;
1270 typedef typename
vector_binary_scalar2::difference_type difference_type
;
1271 typedef typename
vector_binary_scalar2::value_type value_type
;
1272 typedef typename
vector_binary_scalar2::const_reference reference
;
1273 typedef typename
vector_binary_scalar2::const_pointer pointer
;
1275 // Construction and destruction
1278 container_const_reference
<self_type
> (), it1_ (), it2_ () {}
1280 const_iterator (const self_type
&vbs
, const const_subiterator1_type
&it1
, const const_subiterator2_type
&it2
):
1281 container_const_reference
<self_type
> (vbs
), it1_ (it1
), it2_ (it2
) {}
1285 const_iterator
&operator ++ () {
1290 const_iterator
&operator -- () {
1295 const_iterator
&operator += (difference_type n
) {
1300 const_iterator
&operator -= (difference_type n
) {
1305 difference_type
operator - (const const_iterator
&it
) const {
1306 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1307 // FIXME we shouldn't compare floats
1308 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
1309 return it1_
- it
.it1_
;
1314 const_reference
operator * () const {
1315 return functor_type::apply (*it1_
, it2_
);
1318 const_reference
operator [] (difference_type n
) const {
1319 return *(*this + n
);
1324 size_type
index () const {
1325 return it1_
.index ();
1330 const_iterator
&operator = (const const_iterator
&it
) {
1331 container_const_reference
<self_type
>::assign (&it ());
1339 bool operator == (const const_iterator
&it
) const {
1340 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1341 // FIXME we shouldn't compare floats
1342 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
1343 return it1_
== it
.it1_
;
1346 bool operator < (const const_iterator
&it
) const {
1347 BOOST_UBLAS_CHECK ((*this) ().same_closure (it ()), external_logic ());
1348 // FIXME we shouldn't compare floats
1349 // BOOST_UBLAS_CHECK (it2_ == it.it2_, external_logic ());
1350 return it1_
< it
.it1_
;
1354 const_subiterator1_type it1_
;
1355 const_subiterator2_type it2_
;
1360 const_iterator
begin () const {
1364 const_iterator
end () const {
1365 return find (size ());
1369 typedef reverse_iterator_base
<const_iterator
> const_reverse_iterator
;
1372 const_reverse_iterator
rbegin () const {
1373 return const_reverse_iterator (end ());
1376 const_reverse_iterator
rend () const {
1377 return const_reverse_iterator (begin ());
1381 expression1_closure_type e1_
;
1382 expression2_closure_type e2_
;
1385 template<class E1
, class E2
, class F
>
1386 struct vector_binary_scalar2_traits
{
1387 typedef vector_binary_scalar2
<E1
, E2
, F
> expression_type
; // allow E2 to be builtin type
1388 #ifndef BOOST_UBLAS_SIMPLE_ET_DEBUG
1389 typedef expression_type result_type
;
1391 typedef typename
E1::vector_temporary_type result_type
;
1395 // (v * t) [i] = v [i] * t
1396 template<class E1
, class T2
>
1398 typename vector_binary_scalar2_traits
<E1
, const T2
, scalar_multiplies
<typename
E1::value_type
, T2
> >::result_type
1399 operator * (const vector_expression
<E1
> &e1
,
1401 typedef typename vector_binary_scalar2_traits
<E1
, const T2
, scalar_multiplies
<typename
E1::value_type
, T2
> >::expression_type expression_type
;
1402 return expression_type (e1 (), e2
);
1405 // (v / t) [i] = v [i] / t
1406 template<class E1
, class T2
>
1408 typename vector_binary_scalar2_traits
<E1
, const T2
, scalar_divides
<typename
E1::value_type
, T2
> >::result_type
1409 operator / (const vector_expression
<E1
> &e1
,
1411 typedef typename vector_binary_scalar2_traits
<E1
, const T2
, scalar_divides
<typename
E1::value_type
, T2
> >::expression_type expression_type
;
1412 return expression_type (e1 (), e2
);
1416 template<class E
, class F
>
1417 class vector_scalar_unary
:
1418 public scalar_expression
<vector_scalar_unary
<E
, F
> > {
1420 typedef E expression_type
;
1421 typedef F functor_type
;
1422 typedef typename
E::const_closure_type expression_closure_type
;
1423 typedef typename
E::const_iterator::iterator_category iterator_category
;
1424 typedef vector_scalar_unary
<E
, F
> self_type
;
1426 typedef typename
F::result_type value_type
;
1427 typedef typename
E::difference_type difference_type
;
1428 typedef const self_type const_closure_type
;
1429 typedef const_closure_type closure_type
;
1430 typedef unknown_storage_tag storage_category
;
1432 // Construction and destruction
1434 explicit vector_scalar_unary (const expression_type
&e
):
1438 // Expression accessors
1440 const expression_closure_type
&expression () const {
1446 operator value_type () const {
1447 return evaluate (iterator_category ());
1451 // Dense random access specialization
1453 value_type
evaluate (dense_random_access_iterator_tag
) const {
1454 #ifdef BOOST_UBLAS_USE_INDEXING
1455 return functor_type::apply (e_
);
1456 #elif BOOST_UBLAS_USE_ITERATING
1457 difference_type size
= e_
.size ();
1458 return functor_type::apply (size
, e_
.begin ());
1460 difference_type size
= e_
.size ();
1461 if (size
>= BOOST_UBLAS_ITERATOR_THRESHOLD
)
1462 return functor_type::apply (size
, e_
.begin ());
1464 return functor_type::apply (e_
);
1468 // Packed bidirectional specialization
1470 value_type
evaluate (packed_random_access_iterator_tag
) const {
1471 return functor_type::apply (e_
.begin (), e_
.end ());
1474 // Sparse bidirectional specialization
1476 value_type
evaluate (sparse_bidirectional_iterator_tag
) const {
1477 return functor_type::apply (e_
.begin (), e_
.end ());
1481 expression_closure_type e_
;
1484 template<class E
, class F
>
1485 struct vector_scalar_unary_traits
{
1486 typedef vector_scalar_unary
<E
, F
> expression_type
;
1487 #if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET)
1488 // FIXME don't define USE_SCALAR_ET other then for testing
1489 // They do not work for complex types
1490 typedef expression_type result_type
;
1492 typedef typename
F::result_type result_type
;
1496 // sum v = sum (v [i])
1499 typename vector_scalar_unary_traits
<E
, vector_sum
<E
> >::result_type
1500 sum (const vector_expression
<E
> &e
) {
1501 typedef typename vector_scalar_unary_traits
<E
, vector_sum
<E
> >::expression_type expression_type
;
1502 return expression_type (e ());
1505 // real: norm_1 v = sum (abs (v [i]))
1506 // complex: norm_1 v = sum (abs (real (v [i])) + abs (imag (v [i])))
1509 typename vector_scalar_unary_traits
<E
, vector_norm_1
<E
> >::result_type
1510 norm_1 (const vector_expression
<E
> &e
) {
1511 typedef typename vector_scalar_unary_traits
<E
, vector_norm_1
<E
> >::expression_type expression_type
;
1512 return expression_type (e ());
1515 // real: norm_2 v = sqrt (sum (v [i] * v [i]))
1516 // complex: norm_2 v = sqrt (sum (v [i] * conj (v [i])))
1519 typename vector_scalar_unary_traits
<E
, vector_norm_2
<E
> >::result_type
1520 norm_2 (const vector_expression
<E
> &e
) {
1521 typedef typename vector_scalar_unary_traits
<E
, vector_norm_2
<E
> >::expression_type expression_type
;
1522 return expression_type (e ());
1525 // real: norm_inf v = maximum (abs (v [i]))
1526 // complex: norm_inf v = maximum (maximum (abs (real (v [i])), abs (imag (v [i]))))
1529 typename vector_scalar_unary_traits
<E
, vector_norm_inf
<E
> >::result_type
1530 norm_inf (const vector_expression
<E
> &e
) {
1531 typedef typename vector_scalar_unary_traits
<E
, vector_norm_inf
<E
> >::expression_type expression_type
;
1532 return expression_type (e ());
1535 // real: index_norm_inf v = minimum (i: abs (v [i]) == maximum (abs (v [i])))
1538 typename vector_scalar_unary_traits
<E
, vector_index_norm_inf
<E
> >::result_type
1539 index_norm_inf (const vector_expression
<E
> &e
) {
1540 typedef typename vector_scalar_unary_traits
<E
, vector_index_norm_inf
<E
> >::expression_type expression_type
;
1541 return expression_type (e ());
1544 template<class E1
, class E2
, class F
>
1545 class vector_scalar_binary
:
1546 public scalar_expression
<vector_scalar_binary
<E1
, E2
, F
> > {
1548 typedef E1 expression1_type
;
1549 typedef E2 expression2_type
;
1550 typedef F functor_type
;
1551 typedef typename
E1::const_closure_type expression1_closure_type
;
1552 typedef typename
E2::const_closure_type expression2_closure_type
;
1553 typedef typename iterator_restrict_traits
<typename
E1::const_iterator::iterator_category
,
1554 typename
E2::const_iterator::iterator_category
>::iterator_category iterator_category
;
1555 typedef vector_scalar_binary
<E1
, E2
, F
> self_type
;
1557 static const unsigned complexity
= 1;
1558 typedef typename
F::result_type value_type
;
1559 typedef typename
E1::difference_type difference_type
;
1560 typedef const self_type const_closure_type
;
1561 typedef const_closure_type closure_type
;
1562 typedef unknown_storage_tag storage_category
;
1564 // Construction and destruction
1566 vector_scalar_binary (const expression1_type
&e1
, const expression2_type
&e2
):
1567 e1_ (e1
), e2_ (e2
) {}
1572 const expression1_closure_type
&expression1 () const {
1576 const expression2_closure_type
&expression2 () const {
1582 operator value_type () const {
1583 return evaluate (iterator_category ());
1587 // Dense random access specialization
1589 value_type
evaluate (dense_random_access_iterator_tag
) const {
1590 BOOST_UBLAS_CHECK (e1_
.size () == e2_
.size (), external_logic());
1591 #ifdef BOOST_UBLAS_USE_INDEXING
1592 return functor_type::apply (e1_
, e2_
);
1593 #elif BOOST_UBLAS_USE_ITERATING
1594 difference_type size
= BOOST_UBLAS_SAME (e1_
.size (), e2_
.size ());
1595 return functor_type::apply (size
, e1_
.begin (), e2_
.begin ());
1597 difference_type size
= BOOST_UBLAS_SAME (e1_
.size (), e2_
.size ());
1598 if (size
>= BOOST_UBLAS_ITERATOR_THRESHOLD
)
1599 return functor_type::apply (size
, e1_
.begin (), e2_
.begin ());
1601 return functor_type::apply (e1_
, e2_
);
1605 // Packed bidirectional specialization
1607 value_type
evaluate (packed_random_access_iterator_tag
) const {
1608 BOOST_UBLAS_CHECK (e1_
.size () == e2_
.size (), external_logic());
1609 return functor_type::apply (e1_
.begin (), e1_
.end (), e2_
.begin (), e2_
.end ());
1612 // Sparse bidirectional specialization
1614 value_type
evaluate (sparse_bidirectional_iterator_tag
) const {
1615 BOOST_UBLAS_CHECK (e1_
.size () == e2_
.size (), external_logic());
1616 return functor_type::apply (e1_
.begin (), e1_
.end (), e2_
.begin (), e2_
.end (), sparse_bidirectional_iterator_tag ());
1620 expression1_closure_type e1_
;
1621 expression2_closure_type e2_
;
1624 template<class E1
, class E2
, class F
>
1625 struct vector_scalar_binary_traits
{
1626 typedef vector_scalar_binary
<E1
, E2
, F
> expression_type
;
1627 #if !defined (BOOST_UBLAS_SIMPLE_ET_DEBUG) && defined (BOOST_UBLAS_USE_SCALAR_ET)
1628 // FIXME don't define USE_SCALAR_ET other then for testing
1629 // They do not work for complex types
1630 typedef expression_type result_type
;
1632 typedef typename
F::result_type result_type
;
1636 // inner_prod (v1, v2) = sum (v1 [i] * v2 [i])
1637 template<class E1
, class E2
>
1639 typename vector_scalar_binary_traits
<E1
, E2
, vector_inner_prod
<E1
, E2
,
1640 typename promote_traits
<typename
E1::value_type
,
1641 typename
E2::value_type
>::promote_type
> >::result_type
1642 inner_prod (const vector_expression
<E1
> &e1
,
1643 const vector_expression
<E2
> &e2
) {
1644 typedef typename vector_scalar_binary_traits
<E1
, E2
, vector_inner_prod
<E1
, E2
,
1645 typename promote_traits
<typename
E1::value_type
,
1646 typename
E2::value_type
>::promote_type
> >::expression_type expression_type
;
1647 return expression_type (e1 (), e2 ());
1650 template<class E1
, class E2
>
1652 typename vector_scalar_binary_traits
<E1
, E2
, vector_inner_prod
<E1
, E2
,
1653 typename type_traits
<typename promote_traits
<typename
E1::value_type
,
1654 typename
E2::value_type
>::promote_type
>::precision_type
> >::result_type
1655 prec_inner_prod (const vector_expression
<E1
> &e1
,
1656 const vector_expression
<E2
> &e2
) {
1657 typedef typename vector_scalar_binary_traits
<E1
, E2
, vector_inner_prod
<E1
, E2
,
1658 typename type_traits
<typename promote_traits
<typename
E1::value_type
,
1659 typename
E2::value_type
>::promote_type
>::precision_type
> >::expression_type expression_type
;
1660 return expression_type (e1 (), e2 ());