Chris@16
|
1 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 /// \file vector.hpp
|
Chris@16
|
3 ///
|
Chris@16
|
4 // Copyright 2005 Eric Niebler. Distributed under the Boost
|
Chris@16
|
5 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7
|
Chris@16
|
8 #ifndef BOOST_NUMERIC_FUNCTIONAL_VECTOR_HPP_EAN_12_12_2005
|
Chris@16
|
9 #define BOOST_NUMERIC_FUNCTIONAL_VECTOR_HPP_EAN_12_12_2005
|
Chris@16
|
10
|
Chris@16
|
11 #ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED
|
Chris@16
|
12 # error Include this file before boost/accumulators/numeric/functional.hpp
|
Chris@16
|
13 #endif
|
Chris@16
|
14
|
Chris@16
|
15 #include <vector>
|
Chris@16
|
16 #include <functional>
|
Chris@16
|
17 #include <boost/assert.hpp>
|
Chris@16
|
18 #include <boost/mpl/and.hpp>
|
Chris@16
|
19 #include <boost/mpl/not.hpp>
|
Chris@16
|
20 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
21 #include <boost/type_traits/is_same.hpp>
|
Chris@16
|
22 #include <boost/type_traits/is_scalar.hpp>
|
Chris@16
|
23 #include <boost/type_traits/remove_const.hpp>
|
Chris@16
|
24 #include <boost/typeof/std/vector.hpp>
|
Chris@16
|
25 #include <boost/accumulators/numeric/functional_fwd.hpp>
|
Chris@16
|
26
|
Chris@16
|
27 namespace boost { namespace numeric
|
Chris@16
|
28 {
|
Chris@16
|
29 namespace operators
|
Chris@16
|
30 {
|
Chris@16
|
31 namespace acc_detail
|
Chris@16
|
32 {
|
Chris@16
|
33 template<typename Fun>
|
Chris@16
|
34 struct make_vector
|
Chris@16
|
35 {
|
Chris@16
|
36 typedef std::vector<typename Fun::result_type> type;
|
Chris@16
|
37 };
|
Chris@16
|
38 }
|
Chris@16
|
39
|
Chris@16
|
40 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
41 // Handle vector<Left> / Right where Right is a scalar.
|
Chris@16
|
42 template<typename Left, typename Right>
|
Chris@16
|
43 typename lazy_enable_if<
|
Chris@16
|
44 is_scalar<Right>
|
Chris@16
|
45 , acc_detail::make_vector<functional::divides<Left, Right> >
|
Chris@16
|
46 >::type
|
Chris@16
|
47 operator /(std::vector<Left> const &left, Right const &right)
|
Chris@16
|
48 {
|
Chris@16
|
49 typedef typename functional::divides<Left, Right>::result_type value_type;
|
Chris@16
|
50 std::vector<value_type> result(left.size());
|
Chris@16
|
51 for(std::size_t i = 0, size = result.size(); i != size; ++i)
|
Chris@16
|
52 {
|
Chris@16
|
53 result[i] = numeric::divides(left[i], right);
|
Chris@16
|
54 }
|
Chris@16
|
55 return result;
|
Chris@16
|
56 }
|
Chris@16
|
57
|
Chris@16
|
58 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
59 // Handle vector<Left> / vector<Right>.
|
Chris@16
|
60 template<typename Left, typename Right>
|
Chris@16
|
61 std::vector<typename functional::divides<Left, Right>::result_type>
|
Chris@16
|
62 operator /(std::vector<Left> const &left, std::vector<Right> const &right)
|
Chris@16
|
63 {
|
Chris@16
|
64 typedef typename functional::divides<Left, Right>::result_type value_type;
|
Chris@16
|
65 std::vector<value_type> result(left.size());
|
Chris@16
|
66 for(std::size_t i = 0, size = result.size(); i != size; ++i)
|
Chris@16
|
67 {
|
Chris@16
|
68 result[i] = numeric::divides(left[i], right[i]);
|
Chris@16
|
69 }
|
Chris@16
|
70 return result;
|
Chris@16
|
71 }
|
Chris@16
|
72
|
Chris@16
|
73 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
74 // Handle vector<Left> * Right where Right is a scalar.
|
Chris@16
|
75 template<typename Left, typename Right>
|
Chris@16
|
76 typename lazy_enable_if<
|
Chris@16
|
77 is_scalar<Right>
|
Chris@16
|
78 , acc_detail::make_vector<functional::multiplies<Left, Right> >
|
Chris@16
|
79 >::type
|
Chris@16
|
80 operator *(std::vector<Left> const &left, Right const &right)
|
Chris@16
|
81 {
|
Chris@16
|
82 typedef typename functional::multiplies<Left, Right>::result_type value_type;
|
Chris@16
|
83 std::vector<value_type> result(left.size());
|
Chris@16
|
84 for(std::size_t i = 0, size = result.size(); i != size; ++i)
|
Chris@16
|
85 {
|
Chris@16
|
86 result[i] = numeric::multiplies(left[i], right);
|
Chris@16
|
87 }
|
Chris@16
|
88 return result;
|
Chris@16
|
89 }
|
Chris@16
|
90
|
Chris@16
|
91 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
92 // Handle Left * vector<Right> where Left is a scalar.
|
Chris@16
|
93 template<typename Left, typename Right>
|
Chris@16
|
94 typename lazy_enable_if<
|
Chris@16
|
95 is_scalar<Left>
|
Chris@16
|
96 , acc_detail::make_vector<functional::multiplies<Left, Right> >
|
Chris@16
|
97 >::type
|
Chris@16
|
98 operator *(Left const &left, std::vector<Right> const &right)
|
Chris@16
|
99 {
|
Chris@16
|
100 typedef typename functional::multiplies<Left, Right>::result_type value_type;
|
Chris@16
|
101 std::vector<value_type> result(right.size());
|
Chris@16
|
102 for(std::size_t i = 0, size = result.size(); i != size; ++i)
|
Chris@16
|
103 {
|
Chris@16
|
104 result[i] = numeric::multiplies(left, right[i]);
|
Chris@16
|
105 }
|
Chris@16
|
106 return result;
|
Chris@16
|
107 }
|
Chris@16
|
108
|
Chris@16
|
109 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
110 // Handle vector<Left> * vector<Right>
|
Chris@16
|
111 template<typename Left, typename Right>
|
Chris@16
|
112 std::vector<typename functional::multiplies<Left, Right>::result_type>
|
Chris@16
|
113 operator *(std::vector<Left> const &left, std::vector<Right> const &right)
|
Chris@16
|
114 {
|
Chris@16
|
115 typedef typename functional::multiplies<Left, Right>::result_type value_type;
|
Chris@16
|
116 std::vector<value_type> result(left.size());
|
Chris@16
|
117 for(std::size_t i = 0, size = result.size(); i != size; ++i)
|
Chris@16
|
118 {
|
Chris@16
|
119 result[i] = numeric::multiplies(left[i], right[i]);
|
Chris@16
|
120 }
|
Chris@16
|
121 return result;
|
Chris@16
|
122 }
|
Chris@16
|
123
|
Chris@16
|
124 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
125 // Handle vector<Left> + vector<Right>
|
Chris@16
|
126 template<typename Left, typename Right>
|
Chris@16
|
127 std::vector<typename functional::plus<Left, Right>::result_type>
|
Chris@16
|
128 operator +(std::vector<Left> const &left, std::vector<Right> const &right)
|
Chris@16
|
129 {
|
Chris@16
|
130 typedef typename functional::plus<Left, Right>::result_type value_type;
|
Chris@16
|
131 std::vector<value_type> result(left.size());
|
Chris@16
|
132 for(std::size_t i = 0, size = result.size(); i != size; ++i)
|
Chris@16
|
133 {
|
Chris@16
|
134 result[i] = numeric::plus(left[i], right[i]);
|
Chris@16
|
135 }
|
Chris@16
|
136 return result;
|
Chris@16
|
137 }
|
Chris@16
|
138
|
Chris@16
|
139 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
140 // Handle vector<Left> - vector<Right>
|
Chris@16
|
141 template<typename Left, typename Right>
|
Chris@16
|
142 std::vector<typename functional::minus<Left, Right>::result_type>
|
Chris@16
|
143 operator -(std::vector<Left> const &left, std::vector<Right> const &right)
|
Chris@16
|
144 {
|
Chris@16
|
145 typedef typename functional::minus<Left, Right>::result_type value_type;
|
Chris@16
|
146 std::vector<value_type> result(left.size());
|
Chris@16
|
147 for(std::size_t i = 0, size = result.size(); i != size; ++i)
|
Chris@16
|
148 {
|
Chris@16
|
149 result[i] = numeric::minus(left[i], right[i]);
|
Chris@16
|
150 }
|
Chris@16
|
151 return result;
|
Chris@16
|
152 }
|
Chris@16
|
153
|
Chris@16
|
154 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
155 // Handle vector<Left> += vector<Left>
|
Chris@16
|
156 template<typename Left>
|
Chris@16
|
157 std::vector<Left> &
|
Chris@16
|
158 operator +=(std::vector<Left> &left, std::vector<Left> const &right)
|
Chris@16
|
159 {
|
Chris@16
|
160 BOOST_ASSERT(left.size() == right.size());
|
Chris@16
|
161 for(std::size_t i = 0, size = left.size(); i != size; ++i)
|
Chris@16
|
162 {
|
Chris@16
|
163 numeric::plus_assign(left[i], right[i]);
|
Chris@16
|
164 }
|
Chris@16
|
165 return left;
|
Chris@16
|
166 }
|
Chris@16
|
167
|
Chris@16
|
168 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
169 // Handle -vector<Arg>
|
Chris@16
|
170 template<typename Arg>
|
Chris@16
|
171 std::vector<typename functional::unary_minus<Arg>::result_type>
|
Chris@16
|
172 operator -(std::vector<Arg> const &arg)
|
Chris@16
|
173 {
|
Chris@16
|
174 typedef typename functional::unary_minus<Arg>::result_type value_type;
|
Chris@16
|
175 std::vector<value_type> result(arg.size());
|
Chris@16
|
176 for(std::size_t i = 0, size = result.size(); i != size; ++i)
|
Chris@16
|
177 {
|
Chris@16
|
178 result[i] = numeric::unary_minus(arg[i]);
|
Chris@16
|
179 }
|
Chris@16
|
180 return result;
|
Chris@16
|
181 }
|
Chris@16
|
182 }
|
Chris@16
|
183
|
Chris@16
|
184 namespace functional
|
Chris@16
|
185 {
|
Chris@16
|
186 struct std_vector_tag;
|
Chris@16
|
187
|
Chris@16
|
188 template<typename T, typename Al>
|
Chris@16
|
189 struct tag<std::vector<T, Al> >
|
Chris@16
|
190 {
|
Chris@16
|
191 typedef std_vector_tag type;
|
Chris@16
|
192 };
|
Chris@16
|
193
|
Chris@16
|
194 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
195 // element-wise min of std::vector
|
Chris@16
|
196 template<typename Left, typename Right>
|
Chris@16
|
197 struct min_assign<Left, Right, std_vector_tag, std_vector_tag>
|
Chris@16
|
198 : std::binary_function<Left, Right, void>
|
Chris@16
|
199 {
|
Chris@16
|
200 void operator ()(Left &left, Right &right) const
|
Chris@16
|
201 {
|
Chris@16
|
202 BOOST_ASSERT(left.size() == right.size());
|
Chris@16
|
203 for(std::size_t i = 0, size = left.size(); i != size; ++i)
|
Chris@16
|
204 {
|
Chris@16
|
205 if(numeric::less(right[i], left[i]))
|
Chris@16
|
206 {
|
Chris@16
|
207 left[i] = right[i];
|
Chris@16
|
208 }
|
Chris@16
|
209 }
|
Chris@16
|
210 }
|
Chris@16
|
211 };
|
Chris@16
|
212
|
Chris@16
|
213 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
214 // element-wise max of std::vector
|
Chris@16
|
215 template<typename Left, typename Right>
|
Chris@16
|
216 struct max_assign<Left, Right, std_vector_tag, std_vector_tag>
|
Chris@16
|
217 : std::binary_function<Left, Right, void>
|
Chris@16
|
218 {
|
Chris@16
|
219 void operator ()(Left &left, Right &right) const
|
Chris@16
|
220 {
|
Chris@16
|
221 BOOST_ASSERT(left.size() == right.size());
|
Chris@16
|
222 for(std::size_t i = 0, size = left.size(); i != size; ++i)
|
Chris@16
|
223 {
|
Chris@16
|
224 if(numeric::greater(right[i], left[i]))
|
Chris@16
|
225 {
|
Chris@16
|
226 left[i] = right[i];
|
Chris@16
|
227 }
|
Chris@16
|
228 }
|
Chris@16
|
229 }
|
Chris@16
|
230 };
|
Chris@16
|
231
|
Chris@16
|
232 // partial specialization for std::vector.
|
Chris@16
|
233 template<typename Left, typename Right>
|
Chris@16
|
234 struct fdiv<Left, Right, std_vector_tag, void>
|
Chris@16
|
235 : mpl::if_<
|
Chris@16
|
236 are_integral<typename Left::value_type, Right>
|
Chris@16
|
237 , divides<Left, double const>
|
Chris@16
|
238 , divides<Left, Right>
|
Chris@16
|
239 >::type
|
Chris@16
|
240 {};
|
Chris@16
|
241
|
Chris@16
|
242 // promote
|
Chris@16
|
243 template<typename To, typename From>
|
Chris@16
|
244 struct promote<To, From, std_vector_tag, std_vector_tag>
|
Chris@16
|
245 : std::unary_function<From, To>
|
Chris@16
|
246 {
|
Chris@16
|
247 To operator ()(From &arr) const
|
Chris@16
|
248 {
|
Chris@16
|
249 typename remove_const<To>::type res(arr.size());
|
Chris@16
|
250 for(std::size_t i = 0, size = arr.size(); i != size; ++i)
|
Chris@16
|
251 {
|
Chris@16
|
252 res[i] = numeric::promote<typename To::value_type>(arr[i]);
|
Chris@16
|
253 }
|
Chris@16
|
254 return res;
|
Chris@16
|
255 }
|
Chris@16
|
256 };
|
Chris@16
|
257
|
Chris@16
|
258 template<typename ToFrom>
|
Chris@16
|
259 struct promote<ToFrom, ToFrom, std_vector_tag, std_vector_tag>
|
Chris@16
|
260 : std::unary_function<ToFrom, ToFrom>
|
Chris@16
|
261 {
|
Chris@16
|
262 ToFrom &operator ()(ToFrom &tofrom) const
|
Chris@16
|
263 {
|
Chris@16
|
264 return tofrom;
|
Chris@16
|
265 }
|
Chris@16
|
266 };
|
Chris@16
|
267
|
Chris@16
|
268 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
269 // functional::as_min
|
Chris@16
|
270 template<typename T>
|
Chris@16
|
271 struct as_min<T, std_vector_tag>
|
Chris@16
|
272 : std::unary_function<T, typename remove_const<T>::type>
|
Chris@16
|
273 {
|
Chris@16
|
274 typename remove_const<T>::type operator ()(T &arr) const
|
Chris@16
|
275 {
|
Chris@16
|
276 return 0 == arr.size()
|
Chris@16
|
277 ? T()
|
Chris@16
|
278 : T(arr.size(), numeric::as_min(arr[0]));
|
Chris@16
|
279 }
|
Chris@16
|
280 };
|
Chris@16
|
281
|
Chris@16
|
282 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
283 // functional::as_max
|
Chris@16
|
284 template<typename T>
|
Chris@16
|
285 struct as_max<T, std_vector_tag>
|
Chris@16
|
286 : std::unary_function<T, typename remove_const<T>::type>
|
Chris@16
|
287 {
|
Chris@16
|
288 typename remove_const<T>::type operator ()(T &arr) const
|
Chris@16
|
289 {
|
Chris@16
|
290 return 0 == arr.size()
|
Chris@16
|
291 ? T()
|
Chris@16
|
292 : T(arr.size(), numeric::as_max(arr[0]));
|
Chris@16
|
293 }
|
Chris@16
|
294 };
|
Chris@16
|
295
|
Chris@16
|
296 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
297 // functional::as_zero
|
Chris@16
|
298 template<typename T>
|
Chris@16
|
299 struct as_zero<T, std_vector_tag>
|
Chris@16
|
300 : std::unary_function<T, typename remove_const<T>::type>
|
Chris@16
|
301 {
|
Chris@16
|
302 typename remove_const<T>::type operator ()(T &arr) const
|
Chris@16
|
303 {
|
Chris@16
|
304 return 0 == arr.size()
|
Chris@16
|
305 ? T()
|
Chris@16
|
306 : T(arr.size(), numeric::as_zero(arr[0]));
|
Chris@16
|
307 }
|
Chris@16
|
308 };
|
Chris@16
|
309
|
Chris@16
|
310 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
311 // functional::as_one
|
Chris@16
|
312 template<typename T>
|
Chris@16
|
313 struct as_one<T, std_vector_tag>
|
Chris@16
|
314 : std::unary_function<T, typename remove_const<T>::type>
|
Chris@16
|
315 {
|
Chris@16
|
316 typename remove_const<T>::type operator ()(T &arr) const
|
Chris@16
|
317 {
|
Chris@16
|
318 return 0 == arr.size()
|
Chris@16
|
319 ? T()
|
Chris@16
|
320 : T(arr.size(), numeric::as_one(arr[0]));
|
Chris@16
|
321 }
|
Chris@16
|
322 };
|
Chris@16
|
323
|
Chris@16
|
324 } // namespace functional
|
Chris@16
|
325
|
Chris@16
|
326 }} // namespace boost::numeric
|
Chris@16
|
327
|
Chris@16
|
328 #endif
|
Chris@16
|
329
|