1 ///////////////////////////////////////////////////////////////////////////////
4 // Copyright 2005 Eric Niebler. Distributed under the Boost
5 // Software License, Version 1.0. (See accompanying file
6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 #ifndef BOOST_NUMERIC_FUNCTIONAL_VECTOR_HPP_EAN_12_12_2005
9 #define BOOST_NUMERIC_FUNCTIONAL_VECTOR_HPP_EAN_12_12_2005
11 #ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED
12 # error Include this file before boost/accumulators/numeric/functional.hpp
17 #include <boost/assert.hpp>
18 #include <boost/mpl/and.hpp>
19 #include <boost/mpl/not.hpp>
20 #include <boost/utility/enable_if.hpp>
21 #include <boost/type_traits/is_same.hpp>
22 #include <boost/type_traits/is_scalar.hpp>
23 #include <boost/type_traits/remove_const.hpp>
24 #include <boost/typeof/std/vector.hpp>
25 #include <boost/accumulators/numeric/functional_fwd.hpp>
27 namespace boost { namespace numeric
33 template<typename Fun>
36 typedef std::vector<typename Fun::result_type> type;
40 ///////////////////////////////////////////////////////////////////////////////
41 // Handle vector<Left> / Right where Right is a scalar.
42 template<typename Left, typename Right>
43 typename lazy_enable_if<
45 , acc_detail::make_vector<functional::divides<Left, Right> >
47 operator /(std::vector<Left> const &left, Right const &right)
49 typedef typename functional::divides<Left, Right>::result_type value_type;
50 std::vector<value_type> result(left.size());
51 for(std::size_t i = 0, size = result.size(); i != size; ++i)
53 result[i] = numeric::divides(left[i], right);
58 ///////////////////////////////////////////////////////////////////////////////
59 // Handle vector<Left> / vector<Right>.
60 template<typename Left, typename Right>
61 std::vector<typename functional::divides<Left, Right>::result_type>
62 operator /(std::vector<Left> const &left, std::vector<Right> const &right)
64 typedef typename functional::divides<Left, Right>::result_type value_type;
65 std::vector<value_type> result(left.size());
66 for(std::size_t i = 0, size = result.size(); i != size; ++i)
68 result[i] = numeric::divides(left[i], right[i]);
73 ///////////////////////////////////////////////////////////////////////////////
74 // Handle vector<Left> * Right where Right is a scalar.
75 template<typename Left, typename Right>
76 typename lazy_enable_if<
78 , acc_detail::make_vector<functional::multiplies<Left, Right> >
80 operator *(std::vector<Left> const &left, Right const &right)
82 typedef typename functional::multiplies<Left, Right>::result_type value_type;
83 std::vector<value_type> result(left.size());
84 for(std::size_t i = 0, size = result.size(); i != size; ++i)
86 result[i] = numeric::multiplies(left[i], right);
91 ///////////////////////////////////////////////////////////////////////////////
92 // Handle Left * vector<Right> where Left is a scalar.
93 template<typename Left, typename Right>
94 typename lazy_enable_if<
96 , acc_detail::make_vector<functional::multiplies<Left, Right> >
98 operator *(Left const &left, std::vector<Right> const &right)
100 typedef typename functional::multiplies<Left, Right>::result_type value_type;
101 std::vector<value_type> result(right.size());
102 for(std::size_t i = 0, size = result.size(); i != size; ++i)
104 result[i] = numeric::multiplies(left, right[i]);
109 ///////////////////////////////////////////////////////////////////////////////
110 // Handle vector<Left> * vector<Right>
111 template<typename Left, typename Right>
112 std::vector<typename functional::multiplies<Left, Right>::result_type>
113 operator *(std::vector<Left> const &left, std::vector<Right> const &right)
115 typedef typename functional::multiplies<Left, Right>::result_type value_type;
116 std::vector<value_type> result(left.size());
117 for(std::size_t i = 0, size = result.size(); i != size; ++i)
119 result[i] = numeric::multiplies(left[i], right[i]);
124 ///////////////////////////////////////////////////////////////////////////////
125 // Handle vector<Left> + vector<Right>
126 template<typename Left, typename Right>
127 std::vector<typename functional::plus<Left, Right>::result_type>
128 operator +(std::vector<Left> const &left, std::vector<Right> const &right)
130 typedef typename functional::plus<Left, Right>::result_type value_type;
131 std::vector<value_type> result(left.size());
132 for(std::size_t i = 0, size = result.size(); i != size; ++i)
134 result[i] = numeric::plus(left[i], right[i]);
139 ///////////////////////////////////////////////////////////////////////////////
140 // Handle vector<Left> - vector<Right>
141 template<typename Left, typename Right>
142 std::vector<typename functional::minus<Left, Right>::result_type>
143 operator -(std::vector<Left> const &left, std::vector<Right> const &right)
145 typedef typename functional::minus<Left, Right>::result_type value_type;
146 std::vector<value_type> result(left.size());
147 for(std::size_t i = 0, size = result.size(); i != size; ++i)
149 result[i] = numeric::minus(left[i], right[i]);
154 ///////////////////////////////////////////////////////////////////////////////
155 // Handle vector<Left> += vector<Left>
156 template<typename Left>
158 operator +=(std::vector<Left> &left, std::vector<Left> const &right)
160 BOOST_ASSERT(left.size() == right.size());
161 for(std::size_t i = 0, size = left.size(); i != size; ++i)
163 numeric::plus_assign(left[i], right[i]);
168 ///////////////////////////////////////////////////////////////////////////////
169 // Handle -vector<Arg>
170 template<typename Arg>
171 std::vector<typename functional::unary_minus<Arg>::result_type>
172 operator -(std::vector<Arg> const &arg)
174 typedef typename functional::unary_minus<Arg>::result_type value_type;
175 std::vector<value_type> result(arg.size());
176 for(std::size_t i = 0, size = result.size(); i != size; ++i)
178 result[i] = numeric::unary_minus(arg[i]);
186 struct std_vector_tag;
188 template<typename T, typename Al>
189 struct tag<std::vector<T, Al> >
191 typedef std_vector_tag type;
194 ///////////////////////////////////////////////////////////////////////////////
195 // element-wise min of std::vector
196 template<typename Left, typename Right>
197 struct min_assign<Left, Right, std_vector_tag, std_vector_tag>
198 : std::binary_function<Left, Right, void>
200 void operator ()(Left &left, Right &right) const
202 BOOST_ASSERT(left.size() == right.size());
203 for(std::size_t i = 0, size = left.size(); i != size; ++i)
205 if(numeric::less(right[i], left[i]))
213 ///////////////////////////////////////////////////////////////////////////////
214 // element-wise max of std::vector
215 template<typename Left, typename Right>
216 struct max_assign<Left, Right, std_vector_tag, std_vector_tag>
217 : std::binary_function<Left, Right, void>
219 void operator ()(Left &left, Right &right) const
221 BOOST_ASSERT(left.size() == right.size());
222 for(std::size_t i = 0, size = left.size(); i != size; ++i)
224 if(numeric::greater(right[i], left[i]))
232 // partial specialization for std::vector.
233 template<typename Left, typename Right>
234 struct fdiv<Left, Right, std_vector_tag, void>
236 are_integral<typename Left::value_type, Right>
237 , divides<Left, double const>
238 , divides<Left, Right>
243 template<typename To, typename From>
244 struct promote<To, From, std_vector_tag, std_vector_tag>
245 : std::unary_function<From, To>
247 To operator ()(From &arr) const
249 typename remove_const<To>::type res(arr.size());
250 for(std::size_t i = 0, size = arr.size(); i != size; ++i)
252 res[i] = numeric::promote<typename To::value_type>(arr[i]);
258 template<typename ToFrom>
259 struct promote<ToFrom, ToFrom, std_vector_tag, std_vector_tag>
260 : std::unary_function<ToFrom, ToFrom>
262 ToFrom &operator ()(ToFrom &tofrom) const
268 ///////////////////////////////////////////////////////////////////////////////
269 // functional::as_min
271 struct as_min<T, std_vector_tag>
272 : std::unary_function<T, typename remove_const<T>::type>
274 typename remove_const<T>::type operator ()(T &arr) const
276 return 0 == arr.size()
278 : T(arr.size(), numeric::as_min(arr[0]));
282 ///////////////////////////////////////////////////////////////////////////////
283 // functional::as_max
285 struct as_max<T, std_vector_tag>
286 : std::unary_function<T, typename remove_const<T>::type>
288 typename remove_const<T>::type operator ()(T &arr) const
290 return 0 == arr.size()
292 : T(arr.size(), numeric::as_max(arr[0]));
296 ///////////////////////////////////////////////////////////////////////////////
297 // functional::as_zero
299 struct as_zero<T, std_vector_tag>
300 : std::unary_function<T, typename remove_const<T>::type>
302 typename remove_const<T>::type operator ()(T &arr) const
304 return 0 == arr.size()
306 : T(arr.size(), numeric::as_zero(arr[0]));
310 ///////////////////////////////////////////////////////////////////////////////
311 // functional::as_one
313 struct as_one<T, std_vector_tag>
314 : std::unary_function<T, typename remove_const<T>::type>
316 typename remove_const<T>::type operator ()(T &arr) const
318 return 0 == arr.size()
320 : T(arr.size(), numeric::as_one(arr[0]));
324 } // namespace functional
326 }} // namespace boost::numeric