File indexing completed on 2025-01-18 09:29:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
0012 #define BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
0013
0014 #include <cstddef>
0015 #include <valarray>
0016
0017 #include <boost/static_assert.hpp>
0018 #include <boost/type_traits.hpp>
0019
0020 #include <boost/compute/buffer.hpp>
0021 #include <boost/compute/algorithm/copy.hpp>
0022 #include <boost/compute/algorithm/fill.hpp>
0023 #include <boost/compute/algorithm/max_element.hpp>
0024 #include <boost/compute/algorithm/min_element.hpp>
0025 #include <boost/compute/algorithm/transform.hpp>
0026 #include <boost/compute/algorithm/accumulate.hpp>
0027 #include <boost/compute/detail/buffer_value.hpp>
0028 #include <boost/compute/functional.hpp>
0029 #include <boost/compute/functional/bind.hpp>
0030 #include <boost/compute/iterator/buffer_iterator.hpp>
0031 #include <boost/compute/type_traits.hpp>
0032
0033 namespace boost {
0034 namespace compute {
0035
0036 template<class T>
0037 class valarray
0038 {
0039 public:
0040 explicit valarray(const context &context = system::default_context())
0041 : m_buffer(context, 0)
0042 {
0043 }
0044
0045 explicit valarray(size_t size,
0046 const context &context = system::default_context())
0047 : m_buffer(context, size * sizeof(T))
0048 {
0049 }
0050
0051 valarray(const T &value,
0052 size_t size,
0053 const context &context = system::default_context())
0054 : m_buffer(context, size * sizeof(T))
0055 {
0056 fill(begin(), end(), value);
0057 }
0058
0059 valarray(const T *values,
0060 size_t size,
0061 const context &context = system::default_context())
0062 : m_buffer(context, size * sizeof(T))
0063 {
0064 copy(values, values + size, begin());
0065 }
0066
0067 valarray(const valarray<T> &other)
0068 : m_buffer(other.m_buffer.get_context(), other.size() * sizeof(T))
0069 {
0070 copy(other.begin(), other.end(), begin());
0071 }
0072
0073 valarray(const std::valarray<T> &valarray,
0074 const context &context = system::default_context())
0075 : m_buffer(context, valarray.size() * sizeof(T))
0076 {
0077 copy(&valarray[0], &valarray[valarray.size()], begin());
0078 }
0079
0080 valarray<T>& operator=(const valarray<T> &other)
0081 {
0082 if(this != &other){
0083
0084 m_buffer = buffer(other.m_buffer.get_context(), other.size() * sizeof(T));
0085 copy(other.begin(), other.end(), begin());
0086 }
0087
0088 return *this;
0089 }
0090
0091 valarray<T>& operator=(const std::valarray<T> &valarray)
0092 {
0093 m_buffer = buffer(m_buffer.get_context(), valarray.size() * sizeof(T));
0094 copy(&valarray[0], &valarray[valarray.size()], begin());
0095
0096 return *this;
0097 }
0098
0099 valarray<T>& operator*=(const T&);
0100
0101 valarray<T>& operator/=(const T&);
0102
0103 valarray<T>& operator%=(const T& val);
0104
0105 valarray<T> operator+() const
0106 {
0107
0108 valarray<T> result(size());
0109 copy(begin(), end(), result.begin());
0110 return result;
0111 }
0112
0113 valarray<T> operator-() const
0114 {
0115 BOOST_STATIC_ASSERT_MSG(
0116 is_fundamental<T>::value,
0117 "This operator can be used with all OpenCL built-in scalar"
0118 " and vector types"
0119 );
0120 valarray<T> result(size());
0121 BOOST_COMPUTE_FUNCTION(T, unary_minus, (T x),
0122 {
0123 return -x;
0124 });
0125 transform(begin(), end(), result.begin(), unary_minus);
0126 return result;
0127 }
0128
0129 valarray<T> operator~() const
0130 {
0131 BOOST_STATIC_ASSERT_MSG(
0132 is_fundamental<T>::value &&
0133 !is_floating_point<typename scalar_type<T>::type>::value,
0134 "This operator can be used with all OpenCL built-in scalar"
0135 " and vector types except the built-in scalar and vector float types"
0136 );
0137 valarray<T> result(size());
0138 BOOST_COMPUTE_FUNCTION(T, bitwise_not, (T x),
0139 {
0140 return ~x;
0141 });
0142 transform(begin(), end(), result.begin(), bitwise_not);
0143 return result;
0144 }
0145
0146
0147
0148
0149 valarray<char> operator!() const
0150 {
0151 BOOST_STATIC_ASSERT_MSG(
0152 is_fundamental<T>::value,
0153 "This operator can be used with all OpenCL built-in scalar"
0154 " and vector types"
0155 );
0156 valarray<char> result(size());
0157 BOOST_COMPUTE_FUNCTION(char, logical_not, (T x),
0158 {
0159 return !x;
0160 });
0161 transform(begin(), end(), &result[0], logical_not);
0162 return result;
0163 }
0164
0165 valarray<T>& operator+=(const T&);
0166
0167 valarray<T>& operator-=(const T&);
0168
0169 valarray<T>& operator^=(const T&);
0170
0171 valarray<T>& operator&=(const T&);
0172
0173 valarray<T>& operator|=(const T&);
0174
0175 valarray<T>& operator<<=(const T&);
0176
0177 valarray<T>& operator>>=(const T&);
0178
0179 valarray<T>& operator*=(const valarray<T>&);
0180
0181 valarray<T>& operator/=(const valarray<T>&);
0182
0183 valarray<T>& operator%=(const valarray<T>&);
0184
0185 valarray<T>& operator+=(const valarray<T>&);
0186
0187 valarray<T>& operator-=(const valarray<T>&);
0188
0189 valarray<T>& operator^=(const valarray<T>&);
0190
0191 valarray<T>& operator&=(const valarray<T>&);
0192
0193 valarray<T>& operator|=(const valarray<T>&);
0194
0195 valarray<T>& operator<<=(const valarray<T>&);
0196
0197 valarray<T>& operator>>=(const valarray<T>&);
0198
0199 ~valarray()
0200 {
0201
0202 }
0203
0204 size_t size() const
0205 {
0206 return m_buffer.size() / sizeof(T);
0207 }
0208
0209 void resize(size_t size, T value = T())
0210 {
0211 m_buffer = buffer(m_buffer.get_context(), size * sizeof(T));
0212 fill(begin(), end(), value);
0213 }
0214
0215 detail::buffer_value<T> operator[](size_t index)
0216 {
0217 return *(begin() + static_cast<ptrdiff_t>(index));
0218 }
0219
0220 const detail::buffer_value<T> operator[](size_t index) const
0221 {
0222 return *(begin() + static_cast<ptrdiff_t>(index));
0223 }
0224
0225 T (min)() const
0226 {
0227 return *(boost::compute::min_element(begin(), end()));
0228 }
0229
0230 T (max)() const
0231 {
0232 return *(boost::compute::max_element(begin(), end()));
0233 }
0234
0235 T sum() const
0236 {
0237 return boost::compute::accumulate(begin(), end(), T(0));
0238 }
0239
0240 template<class UnaryFunction>
0241 valarray<T> apply(UnaryFunction function) const
0242 {
0243 valarray<T> result(size());
0244 transform(begin(), end(), result.begin(), function);
0245 return result;
0246 }
0247
0248 const buffer& get_buffer() const
0249 {
0250 return m_buffer;
0251 }
0252
0253
0254 private:
0255 buffer_iterator<T> begin() const
0256 {
0257 return buffer_iterator<T>(m_buffer, 0);
0258 }
0259
0260 buffer_iterator<T> end() const
0261 {
0262 return buffer_iterator<T>(m_buffer, size());
0263 }
0264
0265 private:
0266 buffer m_buffer;
0267 };
0268
0269
0270 #define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, assert) \
0271 template<class T> \
0272 inline valarray<T>& \
0273 valarray<T>::operator op##=(const T& val) \
0274 { \
0275 assert \
0276 transform(begin(), end(), begin(), \
0277 ::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
0278 return *this; \
0279 } \
0280 \
0281 template<class T> \
0282 inline valarray<T>& \
0283 valarray<T>::operator op##=(const valarray<T> &rhs) \
0284 { \
0285 assert \
0286 transform(begin(), end(), rhs.begin(), begin(), op_name<T>()); \
0287 return *this; \
0288 }
0289
0290
0291 #define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(op, op_name) \
0292 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, \
0293 BOOST_STATIC_ASSERT_MSG( \
0294 is_fundamental<T>::value, \
0295 "This operator can be used with all OpenCL built-in scalar" \
0296 " and vector types" \
0297 ); \
0298 )
0299
0300
0301
0302
0303 #define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(op, op_name) \
0304 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, \
0305 BOOST_STATIC_ASSERT_MSG( \
0306 is_fundamental<T>::value && \
0307 !is_floating_point<typename scalar_type<T>::type>::value, \
0308 "This operator can be used with all OpenCL built-in scalar" \
0309 " and vector types except the built-in scalar and vector float types" \
0310 ); \
0311 )
0312
0313
0314 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(+, plus)
0315 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(-, minus)
0316 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(*, multiplies)
0317 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(/, divides)
0318 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(^, bit_xor)
0319 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(&, bit_and)
0320 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(|, bit_or)
0321 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(<<, shift_left)
0322 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(>>, shift_right)
0323
0324
0325
0326
0327 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(%, modulus,
0328 BOOST_STATIC_ASSERT_MSG(
0329 is_integral<typename scalar_type<T>::type>::value,
0330 "This operator can be used only with OpenCL built-in integer types"
0331 );
0332 )
0333
0334 #undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY
0335 #undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP
0336
0337 #undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT
0338
0339
0340
0341 #define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, assert) \
0342 template<class T> \
0343 valarray<T> operator op (const valarray<T>& lhs, const valarray<T>& rhs) \
0344 { \
0345 assert \
0346 valarray<T> result(lhs.size()); \
0347 transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
0348 buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
0349 buffer_iterator<T>(rhs.get_buffer(), 0), \
0350 buffer_iterator<T>(result.get_buffer(), 0), \
0351 op_name<T>()); \
0352 return result; \
0353 } \
0354 \
0355 template<class T> \
0356 valarray<T> operator op (const T& val, const valarray<T>& rhs) \
0357 { \
0358 assert \
0359 valarray<T> result(rhs.size()); \
0360 transform(buffer_iterator<T>(rhs.get_buffer(), 0), \
0361 buffer_iterator<T>(rhs.get_buffer(), rhs.size()), \
0362 buffer_iterator<T>(result.get_buffer(), 0), \
0363 ::boost::compute::bind(op_name<T>(), val, placeholders::_1)); \
0364 return result; \
0365 } \
0366 \
0367 template<class T> \
0368 valarray<T> operator op (const valarray<T>& lhs, const T& val) \
0369 { \
0370 assert \
0371 valarray<T> result(lhs.size()); \
0372 transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
0373 buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
0374 buffer_iterator<T>(result.get_buffer(), 0), \
0375 ::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
0376 return result; \
0377 }
0378
0379
0380 #define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(op, op_name) \
0381 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, \
0382 BOOST_STATIC_ASSERT_MSG( \
0383 is_fundamental<T>::value, \
0384 "This operator can be used with all OpenCL built-in scalar" \
0385 " and vector types" \
0386 ); \
0387 )
0388
0389
0390
0391
0392 #define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(op, op_name) \
0393 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, \
0394 BOOST_STATIC_ASSERT_MSG( \
0395 is_fundamental<T>::value && \
0396 !is_floating_point<typename scalar_type<T>::type>::value, \
0397 "This operator can be used with all OpenCL built-in scalar" \
0398 " and vector types except the built-in scalar and vector float types" \
0399 ); \
0400 )
0401
0402
0403 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(+, plus)
0404 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(-, minus)
0405 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(*, multiplies)
0406 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(/, divides)
0407 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(^, bit_xor)
0408 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(&, bit_and)
0409 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(|, bit_or)
0410 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(<<, shift_left)
0411 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(>>, shift_right)
0412
0413 #undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY
0414 #undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP
0415
0416 #undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR
0417
0418
0419
0420
0421
0422
0423
0424 #define BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(op, op_name) \
0425 template<class T> \
0426 valarray<char> operator op (const valarray<T>& lhs, const valarray<T>& rhs) \
0427 { \
0428 BOOST_STATIC_ASSERT_MSG( \
0429 is_fundamental<T>::value, \
0430 "This operator can be used with all OpenCL built-in scalar" \
0431 " and vector types" \
0432 ); \
0433 valarray<char> result(lhs.size()); \
0434 transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
0435 buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
0436 buffer_iterator<T>(rhs.get_buffer(), 0), \
0437 buffer_iterator<char>(result.get_buffer(), 0), \
0438 op_name<T>()); \
0439 return result; \
0440 } \
0441 \
0442 template<class T> \
0443 valarray<char> operator op (const T& val, const valarray<T>& rhs) \
0444 { \
0445 BOOST_STATIC_ASSERT_MSG( \
0446 is_fundamental<T>::value, \
0447 "This operator can be used with all OpenCL built-in scalar" \
0448 " and vector types" \
0449 ); \
0450 valarray<char> result(rhs.size()); \
0451 transform(buffer_iterator<T>(rhs.get_buffer(), 0), \
0452 buffer_iterator<T>(rhs.get_buffer(), rhs.size()), \
0453 buffer_iterator<char>(result.get_buffer(), 0), \
0454 ::boost::compute::bind(op_name<T>(), val, placeholders::_1)); \
0455 return result; \
0456 } \
0457 \
0458 template<class T> \
0459 valarray<char> operator op (const valarray<T>& lhs, const T& val) \
0460 { \
0461 BOOST_STATIC_ASSERT_MSG( \
0462 is_fundamental<T>::value, \
0463 "This operator can be used with all OpenCL built-in scalar" \
0464 " and vector types" \
0465 ); \
0466 valarray<char> result(lhs.size()); \
0467 transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
0468 buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
0469 buffer_iterator<char>(result.get_buffer(), 0), \
0470 ::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
0471 return result; \
0472 }
0473
0474 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(==, equal_to)
0475 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(!=, not_equal_to)
0476 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(>, greater)
0477 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(<, less)
0478 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(>=, greater_equal)
0479 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(<=, less_equal)
0480
0481
0482
0483
0484
0485
0486
0487 #define BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(op, op_name) \
0488 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(op, op_name)
0489
0490 BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(&&, logical_and)
0491 BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(||, logical_or)
0492
0493 #undef BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR
0494
0495 #undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR
0496
0497 }
0498 }
0499
0500 #endif