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