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