• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
operator /(std::vector<Left> const & left,Right const & right)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>
operator /(std::vector<Left> const & left,std::vector<Right> const & right)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
operator *(std::vector<Left> const & left,Right const & right)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
operator *(Left const & left,std::vector<Right> const & right)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>
operator *(std::vector<Left> const & left,std::vector<Right> const & right)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>
operator +(std::vector<Left> const & left,std::vector<Right> const & right)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>
operator -(std::vector<Left> const & left,std::vector<Right> const & right)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> &
operator +=(std::vector<Left> & left,std::vector<Left> const & right)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>
operator -(std::vector<Arg> const & arg)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         {
199             typedef Left first_argument_type;
200             typedef Right second_argument_type;
201             typedef void result_type;
202 
operator ()boost::numeric::functional::min_assign203             void operator ()(Left &left, Right &right) const
204             {
205                 BOOST_ASSERT(left.size() == right.size());
206                 for(std::size_t i = 0, size = left.size(); i != size; ++i)
207                 {
208                     if(numeric::less(right[i], left[i]))
209                     {
210                         left[i] = right[i];
211                     }
212                 }
213             }
214         };
215 
216         ///////////////////////////////////////////////////////////////////////////////
217         // element-wise max of std::vector
218         template<typename Left, typename Right>
219         struct max_assign<Left, Right, std_vector_tag, std_vector_tag>
220         {
221             typedef Left first_argument_type;
222             typedef Right second_argument_type;
223             typedef void result_type;
224 
operator ()boost::numeric::functional::max_assign225             void operator ()(Left &left, Right &right) const
226             {
227                 BOOST_ASSERT(left.size() == right.size());
228                 for(std::size_t i = 0, size = left.size(); i != size; ++i)
229                 {
230                     if(numeric::greater(right[i], left[i]))
231                     {
232                         left[i] = right[i];
233                     }
234                 }
235             }
236         };
237 
238         // partial specialization for std::vector.
239         template<typename Left, typename Right>
240         struct fdiv<Left, Right, std_vector_tag, void>
241           : mpl::if_<
242                 are_integral<typename Left::value_type, Right>
243               , divides<Left, double const>
244               , divides<Left, Right>
245             >::type
246         {};
247 
248         // promote
249         template<typename To, typename From>
250         struct promote<To, From, std_vector_tag, std_vector_tag>
251         {
252             typedef From argument_type;
253             typedef To result_type;
254 
operator ()boost::numeric::functional::promote255             To operator ()(From &arr) const
256             {
257                 typename remove_const<To>::type res(arr.size());
258                 for(std::size_t i = 0, size = arr.size(); i != size; ++i)
259                 {
260                     res[i] = numeric::promote<typename To::value_type>(arr[i]);
261                 }
262                 return res;
263             }
264         };
265 
266         template<typename ToFrom>
267         struct promote<ToFrom, ToFrom, std_vector_tag, std_vector_tag>
268         {
269             typedef ToFrom argument_type;
270             typedef ToFrom result_type;
271 
operator ()boost::numeric::functional::promote272             ToFrom &operator ()(ToFrom &tofrom) const
273             {
274                 return tofrom;
275             }
276         };
277 
278         ///////////////////////////////////////////////////////////////////////////////
279         // functional::as_min
280         template<typename T>
281         struct as_min<T, std_vector_tag>
282         {
283             typedef T argument_type;
284             typedef typename remove_const<T>::type result_type;
285 
operator ()boost::numeric::functional::as_min286             typename remove_const<T>::type operator ()(T &arr) const
287             {
288                 return 0 == arr.size()
289                   ? T()
290                   : T(arr.size(), numeric::as_min(arr[0]));
291             }
292         };
293 
294         ///////////////////////////////////////////////////////////////////////////////
295         // functional::as_max
296         template<typename T>
297         struct as_max<T, std_vector_tag>
298         {
299             typedef T argument_type;
300             typedef typename remove_const<T>::type result_type;
301 
operator ()boost::numeric::functional::as_max302             typename remove_const<T>::type operator ()(T &arr) const
303             {
304                 return 0 == arr.size()
305                   ? T()
306                   : T(arr.size(), numeric::as_max(arr[0]));
307             }
308         };
309 
310         ///////////////////////////////////////////////////////////////////////////////
311         // functional::as_zero
312         template<typename T>
313         struct as_zero<T, std_vector_tag>
314         {
315             typedef T argument_type;
316             typedef typename remove_const<T>::type result_type;
317 
operator ()boost::numeric::functional::as_zero318             typename remove_const<T>::type operator ()(T &arr) const
319             {
320                 return 0 == arr.size()
321                   ? T()
322                   : T(arr.size(), numeric::as_zero(arr[0]));
323             }
324         };
325 
326         ///////////////////////////////////////////////////////////////////////////////
327         // functional::as_one
328         template<typename T>
329         struct as_one<T, std_vector_tag>
330         {
331             typedef T argument_type;
332             typedef typename remove_const<T>::type result_type;
333 
operator ()boost::numeric::functional::as_one334             typename remove_const<T>::type operator ()(T &arr) const
335             {
336                 return 0 == arr.size()
337                   ? T()
338                   : T(arr.size(), numeric::as_one(arr[0]));
339             }
340         };
341 
342     } // namespace functional
343 
344 }} // namespace boost::numeric
345 
346 #endif
347 
348