File indexing completed on 2025-01-18 09:28:19
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_NUMERIC_FUNCTIONAL_VALARRAY_HPP_EAN_12_12_2005
0009 #define BOOST_NUMERIC_FUNCTIONAL_VALARRAY_HPP_EAN_12_12_2005
0010
0011 #ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED
0012 # error Include this file before boost/accumulators/numeric/functional.hpp
0013 #endif
0014
0015 #include <valarray>
0016 #include <functional>
0017 #include <boost/assert.hpp>
0018 #include <boost/mpl/and.hpp>
0019 #include <boost/mpl/not.hpp>
0020 #include <boost/mpl/assert.hpp>
0021 #include <boost/utility/enable_if.hpp>
0022 #include <boost/type_traits/is_same.hpp>
0023 #include <boost/type_traits/is_scalar.hpp>
0024 #include <boost/type_traits/remove_const.hpp>
0025 #include <boost/typeof/std/valarray.hpp>
0026 #include <boost/accumulators/numeric/functional_fwd.hpp>
0027
0028 namespace boost { namespace numeric
0029 {
0030 namespace operators
0031 {
0032 namespace acc_detail
0033 {
0034 template<typename Fun>
0035 struct make_valarray
0036 {
0037 typedef std::valarray<typename Fun::result_type> type;
0038 };
0039 }
0040
0041
0042
0043 template<typename Left, typename Right>
0044 typename lazy_enable_if<
0045 mpl::and_<is_scalar<Right>, mpl::not_<is_same<Left, Right> > >
0046 , acc_detail::make_valarray<functional::divides<Left, Right> >
0047 >::type
0048 operator /(std::valarray<Left> const &left, Right const &right)
0049 {
0050 typedef typename functional::divides<Left, Right>::result_type value_type;
0051 std::valarray<value_type> result(left.size());
0052 for(std::size_t i = 0, size = result.size(); i != size; ++i)
0053 {
0054 result[i] = numeric::divides(left[i], right);
0055 }
0056 return result;
0057 }
0058
0059
0060
0061 template<typename Left, typename Right>
0062 typename lazy_enable_if<
0063 mpl::and_<is_scalar<Right>, mpl::not_<is_same<Left, Right> > >
0064 , acc_detail::make_valarray<functional::multiplies<Left, Right> >
0065 >::type
0066 operator *(std::valarray<Left> const &left, Right const &right)
0067 {
0068 typedef typename functional::multiplies<Left, Right>::result_type value_type;
0069 std::valarray<value_type> result(left.size());
0070 for(std::size_t i = 0, size = result.size(); i != size; ++i)
0071 {
0072 result[i] = numeric::multiplies(left[i], right);
0073 }
0074 return result;
0075 }
0076
0077
0078
0079 template<typename Left, typename Right>
0080 typename lazy_disable_if<
0081 is_same<Left, Right>
0082 , acc_detail::make_valarray<functional::plus<Left, Right> >
0083 >::type
0084 operator +(std::valarray<Left> const &left, std::valarray<Right> const &right)
0085 {
0086 typedef typename functional::plus<Left, Right>::result_type value_type;
0087 std::valarray<value_type> result(left.size());
0088 for(std::size_t i = 0, size = result.size(); i != size; ++i)
0089 {
0090 result[i] = numeric::plus(left[i], right[i]);
0091 }
0092 return result;
0093 }
0094 }
0095
0096 namespace functional
0097 {
0098 struct std_valarray_tag;
0099
0100 template<typename T>
0101 struct tag<std::valarray<T> >
0102 {
0103 typedef std_valarray_tag type;
0104 };
0105
0106 #ifdef __GLIBCXX__
0107 template<typename T, typename U>
0108 struct tag<std::_Expr<T, U> >
0109 {
0110 typedef std_valarray_tag type;
0111 };
0112 #endif
0113
0114
0115
0116
0117
0118 #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(Name, Op) \
0119 template<typename Left, typename Right> \
0120 struct Name<Left, Right, std_valarray_tag, std_valarray_tag> \
0121 { \
0122 typedef Left first_argument_type; \
0123 typedef Right second_argument_type; \
0124 typedef typename Left::value_type left_value_type; \
0125 typedef typename Right::value_type right_value_type; \
0126 typedef \
0127 std::valarray< \
0128 typename Name<left_value_type, right_value_type>::result_type \
0129 > \
0130 result_type; \
0131 result_type \
0132 operator ()(Left &left, Right &right) const \
0133 { \
0134 return numeric::promote<std::valarray<left_value_type> >(left) \
0135 Op numeric::promote<std::valarray<right_value_type> >(right); \
0136 } \
0137 }; \
0138 template<typename Left, typename Right> \
0139 struct Name<Left, Right, std_valarray_tag, void> \
0140 { \
0141 typedef Left first_argument_type; \
0142 typedef Right second_argument_type; \
0143 typedef typename Left::value_type left_value_type; \
0144 typedef \
0145 std::valarray< \
0146 typename Name<left_value_type, Right>::result_type \
0147 > \
0148 result_type; \
0149 result_type \
0150 operator ()(Left &left, Right &right) const \
0151 { \
0152 return numeric::promote<std::valarray<left_value_type> >(left) Op right;\
0153 } \
0154 }; \
0155 template<typename Left, typename Right> \
0156 struct Name<Left, Right, void, std_valarray_tag> \
0157 { \
0158 typedef Left first_argument_type; \
0159 typedef Right second_argument_type; \
0160 typedef typename Right::value_type right_value_type; \
0161 typedef \
0162 std::valarray< \
0163 typename Name<Left, right_value_type>::result_type \
0164 > \
0165 result_type; \
0166 result_type \
0167 operator ()(Left &left, Right &right) const \
0168 { \
0169 return left Op numeric::promote<std::valarray<right_value_type> >(right);\
0170 } \
0171 };
0172
0173 BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(plus, +)
0174 BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(minus, -)
0175 BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(multiplies, *)
0176 BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(divides, /)
0177 BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(modulus, %)
0178
0179 #undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP
0180
0181
0182
0183 template<typename Left, typename Right>
0184 struct min_assign<Left, Right, std_valarray_tag, std_valarray_tag>
0185 {
0186 typedef Left first_argument_type;
0187 typedef Right second_argument_type;
0188 typedef void result_type;
0189
0190 void operator ()(Left &left, Right &right) const
0191 {
0192 BOOST_ASSERT(left.size() == right.size());
0193 for(std::size_t i = 0, size = left.size(); i != size; ++i)
0194 {
0195 if(numeric::less(right[i], left[i]))
0196 {
0197 left[i] = right[i];
0198 }
0199 }
0200 }
0201 };
0202
0203
0204
0205 template<typename Left, typename Right>
0206 struct max_assign<Left, Right, std_valarray_tag, std_valarray_tag>
0207 {
0208 typedef Left first_argument_type;
0209 typedef Right second_argument_type;
0210 typedef void result_type;
0211
0212 void operator ()(Left &left, Right &right) const
0213 {
0214 BOOST_ASSERT(left.size() == right.size());
0215 for(std::size_t i = 0, size = left.size(); i != size; ++i)
0216 {
0217 if(numeric::greater(right[i], left[i]))
0218 {
0219 left[i] = right[i];
0220 }
0221 }
0222 }
0223 };
0224
0225
0226 template<typename Left, typename Right, typename RightTag>
0227 struct fdiv<Left, Right, std_valarray_tag, RightTag>
0228 : mpl::if_<
0229 are_integral<typename Left::value_type, Right>
0230 , divides<Left, double const>
0231 , divides<Left, Right>
0232 >::type
0233 {};
0234
0235
0236 template<typename To, typename From>
0237 struct promote<To, From, std_valarray_tag, std_valarray_tag>
0238 {
0239 typedef From argument_type;
0240 typedef To result_type;
0241
0242 To operator ()(From &arr) const
0243 {
0244 typename remove_const<To>::type res(arr.size());
0245 for(std::size_t i = 0, size = arr.size(); i != size; ++i)
0246 {
0247 res[i] = numeric::promote<typename To::value_type>(arr[i]);
0248 }
0249 return res;
0250 }
0251 };
0252
0253 template<typename ToFrom>
0254 struct promote<ToFrom, ToFrom, std_valarray_tag, std_valarray_tag>
0255 {
0256 typedef ToFrom argument_type;
0257 typedef ToFrom result_type;
0258
0259 ToFrom &operator ()(ToFrom &tofrom) const
0260 {
0261 return tofrom;
0262 }
0263 };
0264
0265
0266
0267
0268 template<typename From>
0269 struct promote<bool, From, void, std_valarray_tag>
0270 {
0271 typedef From argument_type;
0272 typedef bool result_type;
0273
0274 bool operator ()(From &arr) const
0275 {
0276 BOOST_MPL_ASSERT((is_same<bool, typename From::value_type>));
0277 for(std::size_t i = 0, size = arr.size(); i != size; ++i)
0278 {
0279 if(!arr[i])
0280 {
0281 return false;
0282 }
0283 }
0284 return true;
0285 }
0286 };
0287
0288 template<typename From>
0289 struct promote<bool const, From, void, std_valarray_tag>
0290 : promote<bool, From, void, std_valarray_tag>
0291 {};
0292
0293
0294
0295 template<typename T>
0296 struct as_min<T, std_valarray_tag>
0297 {
0298 typedef T argument_type;
0299 typedef typename remove_const<T>::type result_type;
0300
0301 typename remove_const<T>::type operator ()(T &arr) const
0302 {
0303 return 0 == arr.size()
0304 ? T()
0305 : T(numeric::as_min(arr[0]), arr.size());
0306 }
0307 };
0308
0309
0310
0311 template<typename T>
0312 struct as_max<T, std_valarray_tag>
0313 {
0314 typedef T argument_type;
0315 typedef typename remove_const<T>::type result_type;
0316
0317 typename remove_const<T>::type operator ()(T &arr) const
0318 {
0319 return 0 == arr.size()
0320 ? T()
0321 : T(numeric::as_max(arr[0]), arr.size());
0322 }
0323 };
0324
0325
0326
0327 template<typename T>
0328 struct as_zero<T, std_valarray_tag>
0329 {
0330 typedef T argument_type;
0331 typedef typename remove_const<T>::type result_type;
0332
0333 typename remove_const<T>::type operator ()(T &arr) const
0334 {
0335 return 0 == arr.size()
0336 ? T()
0337 : T(numeric::as_zero(arr[0]), arr.size());
0338 }
0339 };
0340
0341
0342
0343 template<typename T>
0344 struct as_one<T, std_valarray_tag>
0345 {
0346 typedef T argument_type;
0347 typedef typename remove_const<T>::type result_type;
0348
0349 typename remove_const<T>::type operator ()(T &arr) const
0350 {
0351 return 0 == arr.size()
0352 ? T()
0353 : T(numeric::as_one(arr[0]), arr.size());
0354 }
0355 };
0356
0357 }
0358
0359 }}
0360
0361 #endif
0362