]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | /// \file valarray.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_VALARRAY_HPP_EAN_12_12_2005 | |
9 | #define BOOST_NUMERIC_FUNCTIONAL_VALARRAY_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 <valarray> | |
16 | #include <functional> | |
17 | #include <boost/assert.hpp> | |
18 | #include <boost/mpl/and.hpp> | |
19 | #include <boost/mpl/not.hpp> | |
20 | #include <boost/mpl/assert.hpp> | |
21 | #include <boost/utility/enable_if.hpp> | |
22 | #include <boost/type_traits/is_same.hpp> | |
23 | #include <boost/type_traits/is_scalar.hpp> | |
24 | #include <boost/type_traits/remove_const.hpp> | |
25 | #include <boost/typeof/std/valarray.hpp> | |
26 | #include <boost/accumulators/numeric/functional_fwd.hpp> | |
27 | ||
28 | namespace boost { namespace numeric | |
29 | { | |
30 | namespace operators | |
31 | { | |
32 | namespace acc_detail | |
33 | { | |
34 | template<typename Fun> | |
35 | struct make_valarray | |
36 | { | |
37 | typedef std::valarray<typename Fun::result_type> type; | |
38 | }; | |
39 | } | |
40 | ||
41 | /////////////////////////////////////////////////////////////////////////////// | |
42 | // Handle valarray<Left> / Right where Right is a scalar and Right != Left. | |
43 | template<typename Left, typename Right> | |
44 | typename lazy_enable_if< | |
45 | mpl::and_<is_scalar<Right>, mpl::not_<is_same<Left, Right> > > | |
46 | , acc_detail::make_valarray<functional::divides<Left, Right> > | |
47 | >::type | |
48 | operator /(std::valarray<Left> const &left, Right const &right) | |
49 | { | |
50 | typedef typename functional::divides<Left, Right>::result_type value_type; | |
51 | std::valarray<value_type> result(left.size()); | |
52 | for(std::size_t i = 0, size = result.size(); i != size; ++i) | |
53 | { | |
54 | result[i] = numeric::divides(left[i], right); | |
55 | } | |
56 | return result; | |
57 | } | |
58 | ||
59 | /////////////////////////////////////////////////////////////////////////////// | |
60 | // Handle valarray<Left> * Right where Right is a scalar and Right != Left. | |
61 | template<typename Left, typename Right> | |
62 | typename lazy_enable_if< | |
63 | mpl::and_<is_scalar<Right>, mpl::not_<is_same<Left, Right> > > | |
64 | , acc_detail::make_valarray<functional::multiplies<Left, Right> > | |
65 | >::type | |
66 | operator *(std::valarray<Left> const &left, Right const &right) | |
67 | { | |
68 | typedef typename functional::multiplies<Left, Right>::result_type value_type; | |
69 | std::valarray<value_type> result(left.size()); | |
70 | for(std::size_t i = 0, size = result.size(); i != size; ++i) | |
71 | { | |
72 | result[i] = numeric::multiplies(left[i], right); | |
73 | } | |
74 | return result; | |
75 | } | |
76 | ||
77 | /////////////////////////////////////////////////////////////////////////////// | |
78 | // Handle valarray<Left> + valarray<Right> where Right != Left. | |
79 | template<typename Left, typename Right> | |
80 | typename lazy_disable_if< | |
81 | is_same<Left, Right> | |
82 | , acc_detail::make_valarray<functional::plus<Left, Right> > | |
83 | >::type | |
84 | operator +(std::valarray<Left> const &left, std::valarray<Right> const &right) | |
85 | { | |
86 | typedef typename functional::plus<Left, Right>::result_type value_type; | |
87 | std::valarray<value_type> result(left.size()); | |
88 | for(std::size_t i = 0, size = result.size(); i != size; ++i) | |
89 | { | |
90 | result[i] = numeric::plus(left[i], right[i]); | |
91 | } | |
92 | return result; | |
93 | } | |
94 | } | |
95 | ||
96 | namespace functional | |
97 | { | |
98 | struct std_valarray_tag; | |
99 | ||
100 | template<typename T> | |
101 | struct tag<std::valarray<T> > | |
102 | { | |
103 | typedef std_valarray_tag type; | |
104 | }; | |
105 | ||
106 | #ifdef __GLIBCXX__ | |
107 | template<typename T, typename U> | |
108 | struct tag<std::_Expr<T, U> > | |
109 | { | |
110 | typedef std_valarray_tag type; | |
111 | }; | |
112 | #endif | |
113 | ||
114 | /// INTERNAL ONLY | |
115 | /// | |
116 | // This is necessary because the GCC stdlib uses expression templates, and | |
117 | // typeof(som-valarray-expression) is not an instance of std::valarray | |
118 | #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(Name, Op) \ | |
119 | template<typename Left, typename Right> \ | |
120 | struct Name<Left, Right, std_valarray_tag, std_valarray_tag> \ | |
121 | : std::binary_function< \ | |
122 | Left \ | |
123 | , Right \ | |
124 | , std::valarray< \ | |
125 | typename Name< \ | |
126 | typename Left::value_type \ | |
127 | , typename Right::value_type \ | |
128 | >::result_type \ | |
129 | > \ | |
130 | > \ | |
131 | { \ | |
132 | typedef typename Left::value_type left_value_type; \ | |
133 | typedef typename Right::value_type right_value_type; \ | |
134 | typedef \ | |
135 | std::valarray< \ | |
136 | typename Name<left_value_type, right_value_type>::result_type \ | |
137 | > \ | |
138 | result_type; \ | |
139 | result_type \ | |
140 | operator ()(Left &left, Right &right) const \ | |
141 | { \ | |
142 | return numeric::promote<std::valarray<left_value_type> >(left) \ | |
143 | Op numeric::promote<std::valarray<right_value_type> >(right); \ | |
144 | } \ | |
145 | }; \ | |
146 | template<typename Left, typename Right> \ | |
147 | struct Name<Left, Right, std_valarray_tag, void> \ | |
148 | : std::binary_function< \ | |
149 | Left \ | |
150 | , Right \ | |
151 | , std::valarray< \ | |
152 | typename Name<typename Left::value_type, Right>::result_type \ | |
153 | > \ | |
154 | > \ | |
155 | { \ | |
156 | typedef typename Left::value_type left_value_type; \ | |
157 | typedef \ | |
158 | std::valarray< \ | |
159 | typename Name<left_value_type, Right>::result_type \ | |
160 | > \ | |
161 | result_type; \ | |
162 | result_type \ | |
163 | operator ()(Left &left, Right &right) const \ | |
164 | { \ | |
165 | return numeric::promote<std::valarray<left_value_type> >(left) Op right;\ | |
166 | } \ | |
167 | }; \ | |
168 | template<typename Left, typename Right> \ | |
169 | struct Name<Left, Right, void, std_valarray_tag> \ | |
170 | : std::binary_function< \ | |
171 | Left \ | |
172 | , Right \ | |
173 | , std::valarray< \ | |
174 | typename Name<Left, typename Right::value_type>::result_type \ | |
175 | > \ | |
176 | > \ | |
177 | { \ | |
178 | typedef typename Right::value_type right_value_type; \ | |
179 | typedef \ | |
180 | std::valarray< \ | |
181 | typename Name<Left, right_value_type>::result_type \ | |
182 | > \ | |
183 | result_type; \ | |
184 | result_type \ | |
185 | operator ()(Left &left, Right &right) const \ | |
186 | { \ | |
187 | return left Op numeric::promote<std::valarray<right_value_type> >(right);\ | |
188 | } \ | |
189 | }; | |
190 | ||
191 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(plus, +) | |
192 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(minus, -) | |
193 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(multiplies, *) | |
194 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(divides, /) | |
195 | BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(modulus, %) | |
196 | ||
197 | #undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP | |
198 | ||
199 | /////////////////////////////////////////////////////////////////////////////// | |
200 | // element-wise min of std::valarray | |
201 | template<typename Left, typename Right> | |
202 | struct min_assign<Left, Right, std_valarray_tag, std_valarray_tag> | |
203 | : std::binary_function<Left, Right, void> | |
204 | { | |
205 | void operator ()(Left &left, Right &right) const | |
206 | { | |
207 | BOOST_ASSERT(left.size() == right.size()); | |
208 | for(std::size_t i = 0, size = left.size(); i != size; ++i) | |
209 | { | |
210 | if(numeric::less(right[i], left[i])) | |
211 | { | |
212 | left[i] = right[i]; | |
213 | } | |
214 | } | |
215 | } | |
216 | }; | |
217 | ||
218 | /////////////////////////////////////////////////////////////////////////////// | |
219 | // element-wise max of std::valarray | |
220 | template<typename Left, typename Right> | |
221 | struct max_assign<Left, Right, std_valarray_tag, std_valarray_tag> | |
222 | : std::binary_function<Left, Right, void> | |
223 | { | |
224 | void operator ()(Left &left, Right &right) const | |
225 | { | |
226 | BOOST_ASSERT(left.size() == right.size()); | |
227 | for(std::size_t i = 0, size = left.size(); i != size; ++i) | |
228 | { | |
229 | if(numeric::greater(right[i], left[i])) | |
230 | { | |
231 | left[i] = right[i]; | |
232 | } | |
233 | } | |
234 | } | |
235 | }; | |
236 | ||
237 | // partial specialization of numeric::fdiv<> for std::valarray. | |
238 | template<typename Left, typename Right, typename RightTag> | |
239 | struct fdiv<Left, Right, std_valarray_tag, RightTag> | |
240 | : mpl::if_< | |
241 | are_integral<typename Left::value_type, Right> | |
242 | , divides<Left, double const> | |
243 | , divides<Left, Right> | |
244 | >::type | |
245 | {}; | |
246 | ||
247 | // promote | |
248 | template<typename To, typename From> | |
249 | struct promote<To, From, std_valarray_tag, std_valarray_tag> | |
250 | : std::unary_function<From, To> | |
251 | { | |
252 | To operator ()(From &arr) const | |
253 | { | |
254 | typename remove_const<To>::type res(arr.size()); | |
255 | for(std::size_t i = 0, size = arr.size(); i != size; ++i) | |
256 | { | |
257 | res[i] = numeric::promote<typename To::value_type>(arr[i]); | |
258 | } | |
259 | return res; | |
260 | } | |
261 | }; | |
262 | ||
263 | template<typename ToFrom> | |
264 | struct promote<ToFrom, ToFrom, std_valarray_tag, std_valarray_tag> | |
265 | : std::unary_function<ToFrom, ToFrom> | |
266 | { | |
267 | ToFrom &operator ()(ToFrom &tofrom) const | |
268 | { | |
269 | return tofrom; | |
270 | } | |
271 | }; | |
272 | ||
273 | // for "promoting" a std::valarray<bool> to a bool, useful for | |
274 | // comparing 2 valarrays for equality: | |
275 | // if(numeric::promote<bool>(a == b)) | |
276 | template<typename From> | |
277 | struct promote<bool, From, void, std_valarray_tag> | |
278 | : std::unary_function<From, bool> | |
279 | { | |
280 | bool operator ()(From &arr) const | |
281 | { | |
282 | BOOST_MPL_ASSERT((is_same<bool, typename From::value_type>)); | |
283 | for(std::size_t i = 0, size = arr.size(); i != size; ++i) | |
284 | { | |
285 | if(!arr[i]) | |
286 | { | |
287 | return false; | |
288 | } | |
289 | } | |
290 | return true; | |
291 | } | |
292 | }; | |
293 | ||
294 | template<typename From> | |
295 | struct promote<bool const, From, void, std_valarray_tag> | |
296 | : promote<bool, From, void, std_valarray_tag> | |
297 | {}; | |
298 | ||
299 | /////////////////////////////////////////////////////////////////////////////// | |
300 | // functional::as_min | |
301 | template<typename T> | |
302 | struct as_min<T, std_valarray_tag> | |
303 | : std::unary_function<T, typename remove_const<T>::type> | |
304 | { | |
305 | typename remove_const<T>::type operator ()(T &arr) const | |
306 | { | |
307 | return 0 == arr.size() | |
308 | ? T() | |
309 | : T(numeric::as_min(arr[0]), arr.size()); | |
310 | } | |
311 | }; | |
312 | ||
313 | /////////////////////////////////////////////////////////////////////////////// | |
314 | // functional::as_max | |
315 | template<typename T> | |
316 | struct as_max<T, std_valarray_tag> | |
317 | : std::unary_function<T, typename remove_const<T>::type> | |
318 | { | |
319 | typename remove_const<T>::type operator ()(T &arr) const | |
320 | { | |
321 | return 0 == arr.size() | |
322 | ? T() | |
323 | : T(numeric::as_max(arr[0]), arr.size()); | |
324 | } | |
325 | }; | |
326 | ||
327 | /////////////////////////////////////////////////////////////////////////////// | |
328 | // functional::as_zero | |
329 | template<typename T> | |
330 | struct as_zero<T, std_valarray_tag> | |
331 | : std::unary_function<T, typename remove_const<T>::type> | |
332 | { | |
333 | typename remove_const<T>::type operator ()(T &arr) const | |
334 | { | |
335 | return 0 == arr.size() | |
336 | ? T() | |
337 | : T(numeric::as_zero(arr[0]), arr.size()); | |
338 | } | |
339 | }; | |
340 | ||
341 | /////////////////////////////////////////////////////////////////////////////// | |
342 | // functional::as_one | |
343 | template<typename T> | |
344 | struct as_one<T, std_valarray_tag> | |
345 | : std::unary_function<T, typename remove_const<T>::type> | |
346 | { | |
347 | typename remove_const<T>::type operator ()(T &arr) const | |
348 | { | |
349 | return 0 == arr.size() | |
350 | ? T() | |
351 | : T(numeric::as_one(arr[0]), arr.size()); | |
352 | } | |
353 | }; | |
354 | ||
355 | } // namespace functional | |
356 | ||
357 | }} // namespace boost::numeric | |
358 | ||
359 | #endif | |
360 |