1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
8 // See http://boostorg.github.com/compute for more information.
9 //---------------------------------------------------------------------------//
11 #ifndef BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
12 #define BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
17 #include <boost/static_assert.hpp>
18 #include <boost/type_traits.hpp>
20 #include <boost/compute/buffer.hpp>
21 #include <boost/compute/algorithm/copy.hpp>
22 #include <boost/compute/algorithm/fill.hpp>
23 #include <boost/compute/algorithm/max_element.hpp>
24 #include <boost/compute/algorithm/min_element.hpp>
25 #include <boost/compute/algorithm/transform.hpp>
26 #include <boost/compute/algorithm/accumulate.hpp>
27 #include <boost/compute/detail/buffer_value.hpp>
28 #include <boost/compute/functional.hpp>
29 #include <boost/compute/functional/bind.hpp>
30 #include <boost/compute/iterator/buffer_iterator.hpp>
31 #include <boost/compute/type_traits.hpp>
40 explicit valarray(const context &context = system::default_context())
41 : m_buffer(context, 0)
45 explicit valarray(size_t size,
46 const context &context = system::default_context())
47 : m_buffer(context, size * sizeof(T))
51 valarray(const T &value,
53 const context &context = system::default_context())
54 : m_buffer(context, size * sizeof(T))
56 fill(begin(), end(), value);
59 valarray(const T *values,
61 const context &context = system::default_context())
62 : m_buffer(context, size * sizeof(T))
64 copy(values, values + size, begin());
67 valarray(const valarray<T> &other)
68 : m_buffer(other.m_buffer.get_context(), other.size() * sizeof(T))
70 copy(other.begin(), other.end(), begin());
73 valarray(const std::valarray<T> &valarray,
74 const context &context = system::default_context())
75 : m_buffer(context, valarray.size() * sizeof(T))
77 copy(&valarray[0], &valarray[valarray.size()], begin());
80 valarray<T>& operator=(const valarray<T> &other)
83 // change to other's OpenCL context
84 m_buffer = buffer(other.m_buffer.get_context(), other.size() * sizeof(T));
85 copy(other.begin(), other.end(), begin());
91 valarray<T>& operator=(const std::valarray<T> &valarray)
93 m_buffer = buffer(m_buffer.get_context(), valarray.size() * sizeof(T));
94 copy(&valarray[0], &valarray[valarray.size()], begin());
99 valarray<T>& operator*=(const T&);
101 valarray<T>& operator/=(const T&);
103 valarray<T>& operator%=(const T& val);
105 valarray<T> operator+() const
107 // This operator can be used with any type.
108 valarray<T> result(size());
109 copy(begin(), end(), result.begin());
113 valarray<T> operator-() const
115 BOOST_STATIC_ASSERT_MSG(
116 is_fundamental<T>::value,
117 "This operator can be used with all OpenCL built-in scalar"
120 valarray<T> result(size());
121 BOOST_COMPUTE_FUNCTION(T, unary_minus, (T x),
125 transform(begin(), end(), result.begin(), unary_minus);
129 valarray<T> operator~() const
131 BOOST_STATIC_ASSERT_MSG(
132 is_fundamental<T>::value &&
133 !is_floating_point<typename scalar_type<T>::type>::value,
134 "This operator can be used with all OpenCL built-in scalar"
135 " and vector types except the built-in scalar and vector float types"
137 valarray<T> result(size());
138 BOOST_COMPUTE_FUNCTION(T, bitwise_not, (T x),
142 transform(begin(), end(), result.begin(), bitwise_not);
146 /// In OpenCL there cannot be memory buffer with bool type, for
147 /// this reason return type is valarray<char> instead of valarray<bool>.
148 /// 1 means true, 0 means false.
149 valarray<char> operator!() const
151 BOOST_STATIC_ASSERT_MSG(
152 is_fundamental<T>::value,
153 "This operator can be used with all OpenCL built-in scalar"
156 valarray<char> result(size());
157 BOOST_COMPUTE_FUNCTION(char, logical_not, (T x),
161 transform(begin(), end(), &result[0], logical_not);
165 valarray<T>& operator+=(const T&);
167 valarray<T>& operator-=(const T&);
169 valarray<T>& operator^=(const T&);
171 valarray<T>& operator&=(const T&);
173 valarray<T>& operator|=(const T&);
175 valarray<T>& operator<<=(const T&);
177 valarray<T>& operator>>=(const T&);
179 valarray<T>& operator*=(const valarray<T>&);
181 valarray<T>& operator/=(const valarray<T>&);
183 valarray<T>& operator%=(const valarray<T>&);
185 valarray<T>& operator+=(const valarray<T>&);
187 valarray<T>& operator-=(const valarray<T>&);
189 valarray<T>& operator^=(const valarray<T>&);
191 valarray<T>& operator&=(const valarray<T>&);
193 valarray<T>& operator|=(const valarray<T>&);
195 valarray<T>& operator<<=(const valarray<T>&);
197 valarray<T>& operator>>=(const valarray<T>&);
206 return m_buffer.size() / sizeof(T);
209 void resize(size_t size, T value = T())
211 m_buffer = buffer(m_buffer.get_context(), size * sizeof(T));
212 fill(begin(), end(), value);
215 detail::buffer_value<T> operator[](size_t index)
217 return *(begin() + static_cast<ptrdiff_t>(index));
220 const detail::buffer_value<T> operator[](size_t index) const
222 return *(begin() + static_cast<ptrdiff_t>(index));
227 return *(boost::compute::min_element(begin(), end()));
232 return *(boost::compute::max_element(begin(), end()));
237 return boost::compute::accumulate(begin(), end(), T(0));
240 template<class UnaryFunction>
241 valarray<T> apply(UnaryFunction function) const
243 valarray<T> result(size());
244 transform(begin(), end(), result.begin(), function);
248 const buffer& get_buffer() const
255 buffer_iterator<T> begin() const
257 return buffer_iterator<T>(m_buffer, 0);
260 buffer_iterator<T> end() const
262 return buffer_iterator<T>(m_buffer, size());
270 #define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, assert) \
272 inline valarray<T>& \
273 valarray<T>::operator op##=(const T& val) \
276 transform(begin(), end(), begin(), \
277 ::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
282 inline valarray<T>& \
283 valarray<T>::operator op##=(const valarray<T> &rhs) \
286 transform(begin(), end(), rhs.begin(), begin(), op_name<T>()); \
291 #define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(op, op_name) \
292 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, \
293 BOOST_STATIC_ASSERT_MSG( \
294 is_fundamental<T>::value, \
295 "This operator can be used with all OpenCL built-in scalar" \
296 " and vector types" \
301 /// For some operators class T can't be floating point type.
302 /// See OpenCL specification, operators chapter.
303 #define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(op, op_name) \
304 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, \
305 BOOST_STATIC_ASSERT_MSG( \
306 is_fundamental<T>::value && \
307 !is_floating_point<typename scalar_type<T>::type>::value, \
308 "This operator can be used with all OpenCL built-in scalar" \
309 " and vector types except the built-in scalar and vector float types" \
313 // defining operators
314 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(+, plus)
315 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(-, minus)
316 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(*, multiplies)
317 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(/, divides)
318 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(^, bit_xor)
319 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(&, bit_and)
320 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(|, bit_or)
321 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(<<, shift_left)
322 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(>>, shift_right)
324 // The remainder (%) operates on
325 // integer scalar and integer vector data types only.
326 // See OpenCL specification.
327 BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(%, modulus,
328 BOOST_STATIC_ASSERT_MSG(
329 is_integral<typename scalar_type<T>::type>::value,
330 "This operator can be used only with OpenCL built-in integer types"
334 #undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY
335 #undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP
337 #undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT
340 /// Macro for defining binary operators for valarray
341 #define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, assert) \
343 valarray<T> operator op (const valarray<T>& lhs, const valarray<T>& rhs) \
346 valarray<T> result(lhs.size()); \
347 transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
348 buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
349 buffer_iterator<T>(rhs.get_buffer(), 0), \
350 buffer_iterator<T>(result.get_buffer(), 0), \
356 valarray<T> operator op (const T& val, const valarray<T>& rhs) \
359 valarray<T> result(rhs.size()); \
360 transform(buffer_iterator<T>(rhs.get_buffer(), 0), \
361 buffer_iterator<T>(rhs.get_buffer(), rhs.size()), \
362 buffer_iterator<T>(result.get_buffer(), 0), \
363 ::boost::compute::bind(op_name<T>(), val, placeholders::_1)); \
368 valarray<T> operator op (const valarray<T>& lhs, const T& val) \
371 valarray<T> result(lhs.size()); \
372 transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
373 buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
374 buffer_iterator<T>(result.get_buffer(), 0), \
375 ::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
380 #define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(op, op_name) \
381 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, \
382 BOOST_STATIC_ASSERT_MSG( \
383 is_fundamental<T>::value, \
384 "This operator can be used with all OpenCL built-in scalar" \
385 " and vector types" \
390 /// For some operators class T can't be floating point type.
391 /// See OpenCL specification, operators chapter.
392 #define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(op, op_name) \
393 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, \
394 BOOST_STATIC_ASSERT_MSG( \
395 is_fundamental<T>::value && \
396 !is_floating_point<typename scalar_type<T>::type>::value, \
397 "This operator can be used with all OpenCL built-in scalar" \
398 " and vector types except the built-in scalar and vector float types" \
402 // defining binary operators for valarray
403 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(+, plus)
404 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(-, minus)
405 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(*, multiplies)
406 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(/, divides)
407 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(^, bit_xor)
408 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(&, bit_and)
409 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(|, bit_or)
410 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(<<, shift_left)
411 BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(>>, shift_right)
413 #undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY
414 #undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP
416 #undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR
419 /// Macro for defining valarray comparison operators.
420 /// For return type valarray<char> is used instead of valarray<bool> because
421 /// in OpenCL there cannot be memory buffer with bool type.
423 /// Note it's also used for defining binary logical operators (==, &&)
424 #define BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(op, op_name) \
426 valarray<char> operator op (const valarray<T>& lhs, const valarray<T>& rhs) \
428 BOOST_STATIC_ASSERT_MSG( \
429 is_fundamental<T>::value, \
430 "This operator can be used with all OpenCL built-in scalar" \
431 " and vector types" \
433 valarray<char> result(lhs.size()); \
434 transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
435 buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
436 buffer_iterator<T>(rhs.get_buffer(), 0), \
437 buffer_iterator<char>(result.get_buffer(), 0), \
443 valarray<char> operator op (const T& val, const valarray<T>& rhs) \
445 BOOST_STATIC_ASSERT_MSG( \
446 is_fundamental<T>::value, \
447 "This operator can be used with all OpenCL built-in scalar" \
448 " and vector types" \
450 valarray<char> result(rhs.size()); \
451 transform(buffer_iterator<T>(rhs.get_buffer(), 0), \
452 buffer_iterator<T>(rhs.get_buffer(), rhs.size()), \
453 buffer_iterator<char>(result.get_buffer(), 0), \
454 ::boost::compute::bind(op_name<T>(), val, placeholders::_1)); \
459 valarray<char> operator op (const valarray<T>& lhs, const T& val) \
461 BOOST_STATIC_ASSERT_MSG( \
462 is_fundamental<T>::value, \
463 "This operator can be used with all OpenCL built-in scalar" \
464 " and vector types" \
466 valarray<char> result(lhs.size()); \
467 transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
468 buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
469 buffer_iterator<char>(result.get_buffer(), 0), \
470 ::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
474 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(==, equal_to)
475 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(!=, not_equal_to)
476 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(>, greater)
477 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(<, less)
478 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(>=, greater_equal)
479 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(<=, less_equal)
482 /// Macro for defining binary logical operators for valarray.
484 /// For return type valarray<char> is used instead of valarray<bool> because
485 /// in OpenCL there cannot be memory buffer with bool type.
486 /// 1 means true, 0 means false.
487 #define BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(op, op_name) \
488 BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(op, op_name)
490 BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(&&, logical_and)
491 BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(||, logical_or)
493 #undef BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR
495 #undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR
497 } // end compute namespace
498 } // end boost namespace
500 #endif // BOOST_COMPUTE_CONTAINER_VALARRAY_HPP