00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef MTL_VEC_VEC_AOP_EXPR_INCLUDE
00017 #define MTL_VEC_VEC_AOP_EXPR_INCLUDE
00018
00019 #include <boost/mpl/bool.hpp>
00020 #include <boost/numeric/mtl/vector/vec_expr.hpp>
00021 #include <boost/numeric/mtl/operation/static_size.hpp>
00022 #include <boost/numeric/mtl/operation/sfunctor.hpp>
00023 #include <boost/numeric/mtl/utility/exception.hpp>
00024 #include <boost/numeric/mtl/utility/is_static.hpp>
00025
00026 namespace mtl { namespace vector {
00027
00028 namespace impl {
00029
00030 template <unsigned long Index, unsigned long Max, typename SFunctor>
00031 struct assign
00032 {
00033 typedef assign<Index+1, Max, SFunctor> next;
00034
00035 template <class E1, class E2>
00036 static inline void apply(E1& first, const E2& second)
00037 {
00038 SFunctor::apply( first(Index), second(Index) );
00039 next::apply( first, second );
00040 }
00041 };
00042
00043 template <unsigned long Max, typename SFunctor>
00044 struct assign<Max, Max, SFunctor>
00045 {
00046 template <class E1, class E2>
00047 static inline void apply(E1& first, const E2& second)
00048 {
00049 SFunctor::apply( first(Max), second(Max) );
00050 }
00051 };
00052 }
00053
00054
00055
00056 template <class E1, class E2, typename SFunctor>
00057 struct vec_vec_aop_expr
00058 : public vec_expr< vec_vec_aop_expr<E1, E2, SFunctor> >
00059 {
00060 typedef vec_expr< vec_vec_aop_expr<E1, E2, SFunctor> > expr_base;
00061 typedef vec_vec_aop_expr<E1, E2, SFunctor> self;
00062 typedef typename E1::value_type value_type;
00063
00064
00065 typedef typename E1::size_type size_type;
00066
00067
00068 typedef value_type reference_type ;
00069
00070 typedef E1 first_argument_type ;
00071 typedef E2 second_argument_type ;
00072
00073 vec_vec_aop_expr( first_argument_type& v1, second_argument_type const& v2 )
00074 : first( v1 ), second( v2 ), delayed_assign( false )
00075 {
00076 second.delay_assign();
00077 }
00078
00079
00080 void assign(boost::mpl::false_)
00081 {
00082
00083 if (first.size() == 0) first.change_dim(second.size());
00084
00085
00086
00087 MTL_DEBUG_THROW_IF(first.size() != second.size(), incompatible_size());
00088
00089 for (size_type i= 0; i < first.size(); ++i)
00090 SFunctor::apply( first(i), second(i) );
00091 }
00092
00093 void assign(boost::mpl::true_)
00094 {
00095
00096 MTL_DEBUG_THROW_IF(first.size() != second.size(), incompatible_size());
00097 impl::assign<1, static_size<E1>::value, SFunctor>::apply(first, second);
00098 }
00099
00100 ~vec_vec_aop_expr()
00101 {
00102 if (!delayed_assign) {
00103
00104 if (size(first) == 0) first.change_dim(size(second));
00105
00106
00107 MTL_DEBUG_THROW_IF(size(first) != size(second), incompatible_size());
00108
00109 for (size_type i= 0; i < size(first); ++i)
00110 SFunctor::apply( first(i), second(i) );
00111
00112
00113
00114 }
00115 }
00116
00117 void delay_assign() const { delayed_assign= true; }
00118
00119 friend size_type inline size(const self& x)
00120 {
00121 assert( size(x.first) == 0 || size(x.first) == size(x.second) );
00122 return size(x.first);
00123 }
00124
00125
00126 value_type& operator() ( size_type i ) const {
00127 assert( delayed_assign );
00128 return SFunctor::apply( first(i), second(i) );
00129 }
00130
00131 value_type& operator[] ( size_type i ) const{
00132 assert( delayed_assign );
00133 return SFunctor::apply( first(i), second(i) );
00134 }
00135
00136 private:
00137 mutable first_argument_type& first ;
00138 second_argument_type const& second ;
00139 mutable bool delayed_assign;
00140 } ;
00141
00142 } }
00143
00144
00145
00146
00147
00148 #endif
00149
00150