#include #include #include #include "mismatch.H" namespace vec { template struct plus { typedef T1 first_argument_type; typedef T2 second_argument_type; typedef ret_t result_type; ret_t operator() (const T1& x, const T2& y) { return x + y; } }; template struct minus { typedef T1 first_argument_type; typedef T2 second_argument_type; typedef ret_t result_type; ret_t operator() (const T1& x, const T2& y) { return x - y; } }; template struct multiplies { typedef T1 first_argument_type; typedef T2 second_argument_type; typedef ret_t result_type; ret_t operator() (const T1& x, const T2& y) { return x * y; } }; template struct divides { typedef T1 first_argument_type; typedef T2 second_argument_type; typedef ret_t result_type; ret_t operator() (const T1& x, const T2& y) { return x / y; } }; template struct pluseq { typedef T1 first_argument_type; typedef T2 second_argument_type; typedef T1& result_type; T1& operator() (T1& a, const T1& b) { a += b; return a; } }; template struct minuseq { typedef T1 first_argument_type; typedef T2 second_argument_type; typedef T1& result_type; T1& operator() (T1& a, const T1& b) { a -= b; return a; } }; template struct multiplieseq { typedef T1 first_argument_type; typedef T2 second_argument_type; typedef T1& result_type; T1& operator() (T1& a, const T1& b) { a *= b; return a; } }; template struct divideseq { typedef T1 first_argument_type; typedef T2 second_argument_type; typedef T1& result_type; T1& operator() (T1& a, const T1& b) { a /= b; return a; } }; template struct arith_traits; template struct arith_traits,std::vector > { typedef typename boost::numeric::ublas::promote_traits::promote_type ret_type; typedef std::vector vec_ret_type; }; template struct arith_traits,type2> { typedef typename boost::numeric::ublas::promote_traits::promote_type ret_type; typedef std::vector vec_ret_type; }; template class func> struct vec_arith; template class func> struct vec_arith, std::vector, func> { typedef typename arith_traits,std::vector >::vec_ret_type vec_ret_type; typedef typename arith_traits,std::vector >::ret_type ret_type; vec_ret_type operator() (std::vector const& a, std::vector const& b) { if (a.size() != b.size()) throw size_mismatch(); vec_ret_type ret (a.size()); std::transform (a.begin(), a.end(), b.begin(), ret.begin(), func()); return ret; } }; template class func> struct vec_arith, type2, func> { typedef typename arith_traits,type2>::vec_ret_type vec_ret_type; typedef typename arith_traits,type2>::ret_type ret_type; vec_ret_type operator() (std::vectorconst& a, type2 b) { vec_ret_type ret (a.size()); std::transform (a.begin(), a.end(), ret.begin(), boost::bind (func(), _1, b)); return ret; } }; // Dispatch for out-of-place ops template inline typename arith_traits,std::vector >::vec_ret_type operator+ (std::vector const& a, std::vector const& b) { return vec_arith,std::vector,vec::plus>() (a, b); } template inline typename arith_traits,type2>::vec_ret_type operator+ (std::vector const& a, type2 const& b) { return vec_arith,type2,vec::plus>() (a, b); } template inline typename arith_traits,std::vector >::vec_ret_type operator- (std::vector const& a, std::vector const& b) { return vec_arith,std::vector,vec::minus>() (a, b); } template inline typename arith_traits,type2>::vec_ret_type operator- (std::vector const& a, type2 const& b) { return vec_arith,type2,vec::minus>() (a, b); } template inline typename arith_traits,std::vector >::vec_ret_type operator* (std::vector const& a, std::vector const& b) { return vec_arith,std::vector,vec::multiplies>() (a, b); } template inline typename arith_traits,type2>::vec_ret_type operator* (std::vector const& a, type2 const& b) { return vec_arith,type2,vec::multiplies>() (a, b); } template inline typename arith_traits,std::vector >::vec_ret_type operator/ (std::vector const& a, std::vector const& b) { return vec_arith,std::vector,vec::divides>() (a, b); } template inline typename arith_traits,type2>::vec_ret_type operator/ (std::vector const& a, type2 const& b) { return vec_arith,type2,vec::divides>() (a, b); } // Define in-place ops for vectors template class func> struct vector_assign_arith; template class func> struct vector_assign_arith, std::vector, func> { typedef std::vector ret_type; ret_type& operator() (std::vector& a, std::vectorconst& b) { if (a.size() != b.size()) throw size_mismatch(); typename std::vector::iterator i = a.begin(); typename std::vector::const_iterator j = b.begin(); for (; i != a.end(); i++, j++) func() (*i, *j); return a; } }; template class func> struct vector_assign_arith, type2, func> { typedef std::vector ret_type; ret_type& operator() (std::vector& a, type2 const& b) { typename std::vector::iterator i = a.begin(); for (; i != a.end(); i++) func() (*i, b); return a; } }; // Dispatch for in-place ops template inline std::vector& operator+= (std::vector & a, type2 const& b) { return vector_assign_arith,type2,vec::pluseq>() (a, b); } template inline std::vector& operator-= (std::vector & a, type2 const& b) { return vector_assign_arith,type2,vec::minuseq>() (a, b); } template inline std::vector& operator*= (std::vector & a, type2 const& b) { return vector_assign_arith,type2,vec::multiplieseq>() (a, b); } template inline std::vector& operator/= (std::vector & a, type2 const& b) { return vector_assign_arith,type2,vec::divideseq>() (a, b); } }