]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | /// \file vector.hpp | |
3 | /// | |
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) | |
7 | ||
8 | #ifndef BOOST_NUMERIC_FUNCTIONAL_VECTOR_HPP_EAN_12_12_2005 | |
9 | #define BOOST_NUMERIC_FUNCTIONAL_VECTOR_HPP_EAN_12_12_2005 | |
10 | ||
11 | #ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED | |
12 | # error Include this file before boost/accumulators/numeric/functional.hpp | |
13 | #endif | |
14 | ||
15 | #include <vector> | |
16 | #include <functional> | |
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> | |
26 | ||
27 | namespace boost { namespace numeric | |
28 | { | |
29 | namespace operators | |
30 | { | |
31 | namespace acc_detail | |
32 | { | |
33 | template<typename Fun> | |
34 | struct make_vector | |
35 | { | |
36 | typedef std::vector<typename Fun::result_type> type; | |
37 | }; | |
38 | } | |
39 | ||
40 | /////////////////////////////////////////////////////////////////////////////// | |
41 | // Handle vector<Left> / Right where Right is a scalar. | |
42 | template<typename Left, typename Right> | |
43 | typename lazy_enable_if< | |
44 | is_scalar<Right> | |
45 | , acc_detail::make_vector<functional::divides<Left, Right> > | |
46 | >::type | |
47 | operator /(std::vector<Left> const &left, Right const &right) | |
48 | { | |
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) | |
52 | { | |
53 | result[i] = numeric::divides(left[i], right); | |
54 | } | |
55 | return result; | |
56 | } | |
57 | ||
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) | |
63 | { | |
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) | |
67 | { | |
68 | result[i] = numeric::divides(left[i], right[i]); | |
69 | } | |
70 | return result; | |
71 | } | |
72 | ||
73 | /////////////////////////////////////////////////////////////////////////////// | |
74 | // Handle vector<Left> * Right where Right is a scalar. | |
75 | template<typename Left, typename Right> | |
76 | typename lazy_enable_if< | |
77 | is_scalar<Right> | |
78 | , acc_detail::make_vector<functional::multiplies<Left, Right> > | |
79 | >::type | |
80 | operator *(std::vector<Left> const &left, Right const &right) | |
81 | { | |
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) | |
85 | { | |
86 | result[i] = numeric::multiplies(left[i], right); | |
87 | } | |
88 | return result; | |
89 | } | |
90 | ||
91 | /////////////////////////////////////////////////////////////////////////////// | |
92 | // Handle Left * vector<Right> where Left is a scalar. | |
93 | template<typename Left, typename Right> | |
94 | typename lazy_enable_if< | |
95 | is_scalar<Left> | |
96 | , acc_detail::make_vector<functional::multiplies<Left, Right> > | |
97 | >::type | |
98 | operator *(Left const &left, std::vector<Right> const &right) | |
99 | { | |
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) | |
103 | { | |
104 | result[i] = numeric::multiplies(left, right[i]); | |
105 | } | |
106 | return result; | |
107 | } | |
108 | ||
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) | |
114 | { | |
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) | |
118 | { | |
119 | result[i] = numeric::multiplies(left[i], right[i]); | |
120 | } | |
121 | return result; | |
122 | } | |
123 | ||
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) | |
129 | { | |
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) | |
133 | { | |
134 | result[i] = numeric::plus(left[i], right[i]); | |
135 | } | |
136 | return result; | |
137 | } | |
138 | ||
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) | |
144 | { | |
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) | |
148 | { | |
149 | result[i] = numeric::minus(left[i], right[i]); | |
150 | } | |
151 | return result; | |
152 | } | |
153 | ||
154 | /////////////////////////////////////////////////////////////////////////////// | |
155 | // Handle vector<Left> += vector<Left> | |
156 | template<typename Left> | |
157 | std::vector<Left> & | |
158 | operator +=(std::vector<Left> &left, std::vector<Left> const &right) | |
159 | { | |
160 | BOOST_ASSERT(left.size() == right.size()); | |
161 | for(std::size_t i = 0, size = left.size(); i != size; ++i) | |
162 | { | |
163 | numeric::plus_assign(left[i], right[i]); | |
164 | } | |
165 | return left; | |
166 | } | |
167 | ||
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) | |
173 | { | |
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) | |
177 | { | |
178 | result[i] = numeric::unary_minus(arg[i]); | |
179 | } | |
180 | return result; | |
181 | } | |
182 | } | |
183 | ||
184 | namespace functional | |
185 | { | |
186 | struct std_vector_tag; | |
187 | ||
188 | template<typename T, typename Al> | |
189 | struct tag<std::vector<T, Al> > | |
190 | { | |
191 | typedef std_vector_tag type; | |
192 | }; | |
193 | ||
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> | |
199 | { | |
200 | void operator ()(Left &left, Right &right) const | |
201 | { | |
202 | BOOST_ASSERT(left.size() == right.size()); | |
203 | for(std::size_t i = 0, size = left.size(); i != size; ++i) | |
204 | { | |
205 | if(numeric::less(right[i], left[i])) | |
206 | { | |
207 | left[i] = right[i]; | |
208 | } | |
209 | } | |
210 | } | |
211 | }; | |
212 | ||
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> | |
218 | { | |
219 | void operator ()(Left &left, Right &right) const | |
220 | { | |
221 | BOOST_ASSERT(left.size() == right.size()); | |
222 | for(std::size_t i = 0, size = left.size(); i != size; ++i) | |
223 | { | |
224 | if(numeric::greater(right[i], left[i])) | |
225 | { | |
226 | left[i] = right[i]; | |
227 | } | |
228 | } | |
229 | } | |
230 | }; | |
231 | ||
232 | // partial specialization for std::vector. | |
233 | template<typename Left, typename Right> | |
234 | struct fdiv<Left, Right, std_vector_tag, void> | |
235 | : mpl::if_< | |
236 | are_integral<typename Left::value_type, Right> | |
237 | , divides<Left, double const> | |
238 | , divides<Left, Right> | |
239 | >::type | |
240 | {}; | |
241 | ||
242 | // promote | |
243 | template<typename To, typename From> | |
244 | struct promote<To, From, std_vector_tag, std_vector_tag> | |
245 | : std::unary_function<From, To> | |
246 | { | |
247 | To operator ()(From &arr) const | |
248 | { | |
249 | typename remove_const<To>::type res(arr.size()); | |
250 | for(std::size_t i = 0, size = arr.size(); i != size; ++i) | |
251 | { | |
252 | res[i] = numeric::promote<typename To::value_type>(arr[i]); | |
253 | } | |
254 | return res; | |
255 | } | |
256 | }; | |
257 | ||
258 | template<typename ToFrom> | |
259 | struct promote<ToFrom, ToFrom, std_vector_tag, std_vector_tag> | |
260 | : std::unary_function<ToFrom, ToFrom> | |
261 | { | |
262 | ToFrom &operator ()(ToFrom &tofrom) const | |
263 | { | |
264 | return tofrom; | |
265 | } | |
266 | }; | |
267 | ||
268 | /////////////////////////////////////////////////////////////////////////////// | |
269 | // functional::as_min | |
270 | template<typename T> | |
271 | struct as_min<T, std_vector_tag> | |
272 | : std::unary_function<T, typename remove_const<T>::type> | |
273 | { | |
274 | typename remove_const<T>::type operator ()(T &arr) const | |
275 | { | |
276 | return 0 == arr.size() | |
277 | ? T() | |
278 | : T(arr.size(), numeric::as_min(arr[0])); | |
279 | } | |
280 | }; | |
281 | ||
282 | /////////////////////////////////////////////////////////////////////////////// | |
283 | // functional::as_max | |
284 | template<typename T> | |
285 | struct as_max<T, std_vector_tag> | |
286 | : std::unary_function<T, typename remove_const<T>::type> | |
287 | { | |
288 | typename remove_const<T>::type operator ()(T &arr) const | |
289 | { | |
290 | return 0 == arr.size() | |
291 | ? T() | |
292 | : T(arr.size(), numeric::as_max(arr[0])); | |
293 | } | |
294 | }; | |
295 | ||
296 | /////////////////////////////////////////////////////////////////////////////// | |
297 | // functional::as_zero | |
298 | template<typename T> | |
299 | struct as_zero<T, std_vector_tag> | |
300 | : std::unary_function<T, typename remove_const<T>::type> | |
301 | { | |
302 | typename remove_const<T>::type operator ()(T &arr) const | |
303 | { | |
304 | return 0 == arr.size() | |
305 | ? T() | |
306 | : T(arr.size(), numeric::as_zero(arr[0])); | |
307 | } | |
308 | }; | |
309 | ||
310 | /////////////////////////////////////////////////////////////////////////////// | |
311 | // functional::as_one | |
312 | template<typename T> | |
313 | struct as_one<T, std_vector_tag> | |
314 | : std::unary_function<T, typename remove_const<T>::type> | |
315 | { | |
316 | typename remove_const<T>::type operator ()(T &arr) const | |
317 | { | |
318 | return 0 == arr.size() | |
319 | ? T() | |
320 | : T(arr.size(), numeric::as_one(arr[0])); | |
321 | } | |
322 | }; | |
323 | ||
324 | } // namespace functional | |
325 | ||
326 | }} // namespace boost::numeric | |
327 | ||
328 | #endif | |
329 |