123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 |
- //---------------------------------------------------------------------------//
- // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
- //
- // Distributed under the Boost Software License, Version 1.0
- // See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt
- //
- // See http://boostorg.github.com/compute for more information.
- //---------------------------------------------------------------------------//
- #ifndef BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
- #define BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
- #include <cstddef>
- #include <valarray>
- #include <boost/static_assert.hpp>
- #include <boost/type_traits.hpp>
- #include <boost/compute/buffer.hpp>
- #include <boost/compute/algorithm/copy.hpp>
- #include <boost/compute/algorithm/fill.hpp>
- #include <boost/compute/algorithm/max_element.hpp>
- #include <boost/compute/algorithm/min_element.hpp>
- #include <boost/compute/algorithm/transform.hpp>
- #include <boost/compute/algorithm/accumulate.hpp>
- #include <boost/compute/detail/buffer_value.hpp>
- #include <boost/compute/functional.hpp>
- #include <boost/compute/functional/bind.hpp>
- #include <boost/compute/iterator/buffer_iterator.hpp>
- #include <boost/compute/type_traits.hpp>
- namespace boost {
- namespace compute {
- template<class T>
- class valarray
- {
- public:
- explicit valarray(const context &context = system::default_context())
- : m_buffer(context, 0)
- {
- }
- explicit valarray(size_t size,
- const context &context = system::default_context())
- : m_buffer(context, size * sizeof(T))
- {
- }
- valarray(const T &value,
- size_t size,
- const context &context = system::default_context())
- : m_buffer(context, size * sizeof(T))
- {
- fill(begin(), end(), value);
- }
- valarray(const T *values,
- size_t size,
- const context &context = system::default_context())
- : m_buffer(context, size * sizeof(T))
- {
- copy(values, values + size, begin());
- }
- valarray(const valarray<T> &other)
- : m_buffer(other.m_buffer.get_context(), other.size() * sizeof(T))
- {
- copy(other.begin(), other.end(), begin());
- }
- valarray(const std::valarray<T> &valarray,
- const context &context = system::default_context())
- : m_buffer(context, valarray.size() * sizeof(T))
- {
- copy(&valarray[0], &valarray[valarray.size()], begin());
- }
- valarray<T>& operator=(const valarray<T> &other)
- {
- if(this != &other){
- // change to other's OpenCL context
- m_buffer = buffer(other.m_buffer.get_context(), other.size() * sizeof(T));
- copy(other.begin(), other.end(), begin());
- }
- return *this;
- }
- valarray<T>& operator=(const std::valarray<T> &valarray)
- {
- m_buffer = buffer(m_buffer.get_context(), valarray.size() * sizeof(T));
- copy(&valarray[0], &valarray[valarray.size()], begin());
- return *this;
- }
- valarray<T>& operator*=(const T&);
- valarray<T>& operator/=(const T&);
- valarray<T>& operator%=(const T& val);
- valarray<T> operator+() const
- {
- // This operator can be used with any type.
- valarray<T> result(size());
- copy(begin(), end(), result.begin());
- return result;
- }
- valarray<T> operator-() const
- {
- BOOST_STATIC_ASSERT_MSG(
- is_fundamental<T>::value,
- "This operator can be used with all OpenCL built-in scalar"
- " and vector types"
- );
- valarray<T> result(size());
- BOOST_COMPUTE_FUNCTION(T, unary_minus, (T x),
- {
- return -x;
- });
- transform(begin(), end(), result.begin(), unary_minus);
- return result;
- }
- valarray<T> operator~() const
- {
- BOOST_STATIC_ASSERT_MSG(
- is_fundamental<T>::value &&
- !is_floating_point<typename scalar_type<T>::type>::value,
- "This operator can be used with all OpenCL built-in scalar"
- " and vector types except the built-in scalar and vector float types"
- );
- valarray<T> result(size());
- BOOST_COMPUTE_FUNCTION(T, bitwise_not, (T x),
- {
- return ~x;
- });
- transform(begin(), end(), result.begin(), bitwise_not);
- return result;
- }
- /// In OpenCL there cannot be memory buffer with bool type, for
- /// this reason return type is valarray<char> instead of valarray<bool>.
- /// 1 means true, 0 means false.
- valarray<char> operator!() const
- {
- BOOST_STATIC_ASSERT_MSG(
- is_fundamental<T>::value,
- "This operator can be used with all OpenCL built-in scalar"
- " and vector types"
- );
- valarray<char> result(size());
- BOOST_COMPUTE_FUNCTION(char, logical_not, (T x),
- {
- return !x;
- });
- transform(begin(), end(), &result[0], logical_not);
- return result;
- }
- valarray<T>& operator+=(const T&);
- valarray<T>& operator-=(const T&);
- valarray<T>& operator^=(const T&);
- valarray<T>& operator&=(const T&);
- valarray<T>& operator|=(const T&);
- valarray<T>& operator<<=(const T&);
- valarray<T>& operator>>=(const T&);
- valarray<T>& operator*=(const valarray<T>&);
- valarray<T>& operator/=(const valarray<T>&);
- valarray<T>& operator%=(const valarray<T>&);
- valarray<T>& operator+=(const valarray<T>&);
- valarray<T>& operator-=(const valarray<T>&);
- valarray<T>& operator^=(const valarray<T>&);
- valarray<T>& operator&=(const valarray<T>&);
- valarray<T>& operator|=(const valarray<T>&);
- valarray<T>& operator<<=(const valarray<T>&);
- valarray<T>& operator>>=(const valarray<T>&);
- ~valarray()
- {
- }
- size_t size() const
- {
- return m_buffer.size() / sizeof(T);
- }
- void resize(size_t size, T value = T())
- {
- m_buffer = buffer(m_buffer.get_context(), size * sizeof(T));
- fill(begin(), end(), value);
- }
- detail::buffer_value<T> operator[](size_t index)
- {
- return *(begin() + static_cast<ptrdiff_t>(index));
- }
- const detail::buffer_value<T> operator[](size_t index) const
- {
- return *(begin() + static_cast<ptrdiff_t>(index));
- }
- T (min)() const
- {
- return *(boost::compute::min_element(begin(), end()));
- }
- T (max)() const
- {
- return *(boost::compute::max_element(begin(), end()));
- }
- T sum() const
- {
- return boost::compute::accumulate(begin(), end(), T(0));
- }
- template<class UnaryFunction>
- valarray<T> apply(UnaryFunction function) const
- {
- valarray<T> result(size());
- transform(begin(), end(), result.begin(), function);
- return result;
- }
- const buffer& get_buffer() const
- {
- return m_buffer;
- }
- private:
- buffer_iterator<T> begin() const
- {
- return buffer_iterator<T>(m_buffer, 0);
- }
- buffer_iterator<T> end() const
- {
- return buffer_iterator<T>(m_buffer, size());
- }
- private:
- buffer m_buffer;
- };
- /// \internal_
- #define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, assert) \
- template<class T> \
- inline valarray<T>& \
- valarray<T>::operator op##=(const T& val) \
- { \
- assert \
- transform(begin(), end(), begin(), \
- ::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
- return *this; \
- } \
- \
- template<class T> \
- inline valarray<T>& \
- valarray<T>::operator op##=(const valarray<T> &rhs) \
- { \
- assert \
- transform(begin(), end(), rhs.begin(), begin(), op_name<T>()); \
- return *this; \
- }
- /// \internal_
- #define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(op, op_name) \
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, \
- BOOST_STATIC_ASSERT_MSG( \
- is_fundamental<T>::value, \
- "This operator can be used with all OpenCL built-in scalar" \
- " and vector types" \
- ); \
- )
- /// \internal_
- /// For some operators class T can't be floating point type.
- /// See OpenCL specification, operators chapter.
- #define BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(op, op_name) \
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(op, op_name, \
- BOOST_STATIC_ASSERT_MSG( \
- is_fundamental<T>::value && \
- !is_floating_point<typename scalar_type<T>::type>::value, \
- "This operator can be used with all OpenCL built-in scalar" \
- " and vector types except the built-in scalar and vector float types" \
- ); \
- )
- // defining operators
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(+, plus)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(-, minus)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(*, multiplies)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY(/, divides)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(^, bit_xor)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(&, bit_and)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(|, bit_or)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(<<, shift_left)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP(>>, shift_right)
- // The remainder (%) operates on
- // integer scalar and integer vector data types only.
- // See OpenCL specification.
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT(%, modulus,
- BOOST_STATIC_ASSERT_MSG(
- is_integral<typename scalar_type<T>::type>::value,
- "This operator can be used only with OpenCL built-in integer types"
- );
- )
- #undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_ANY
- #undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT_NO_FP
- #undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPOUND_ASSIGNMENT
- /// \internal_
- /// Macro for defining binary operators for valarray
- #define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, assert) \
- template<class T> \
- valarray<T> operator op (const valarray<T>& lhs, const valarray<T>& rhs) \
- { \
- assert \
- valarray<T> result(lhs.size()); \
- transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
- buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
- buffer_iterator<T>(rhs.get_buffer(), 0), \
- buffer_iterator<T>(result.get_buffer(), 0), \
- op_name<T>()); \
- return result; \
- } \
- \
- template<class T> \
- valarray<T> operator op (const T& val, const valarray<T>& rhs) \
- { \
- assert \
- valarray<T> result(rhs.size()); \
- transform(buffer_iterator<T>(rhs.get_buffer(), 0), \
- buffer_iterator<T>(rhs.get_buffer(), rhs.size()), \
- buffer_iterator<T>(result.get_buffer(), 0), \
- ::boost::compute::bind(op_name<T>(), val, placeholders::_1)); \
- return result; \
- } \
- \
- template<class T> \
- valarray<T> operator op (const valarray<T>& lhs, const T& val) \
- { \
- assert \
- valarray<T> result(lhs.size()); \
- transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
- buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
- buffer_iterator<T>(result.get_buffer(), 0), \
- ::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
- return result; \
- }
- /// \internal_
- #define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(op, op_name) \
- BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, \
- BOOST_STATIC_ASSERT_MSG( \
- is_fundamental<T>::value, \
- "This operator can be used with all OpenCL built-in scalar" \
- " and vector types" \
- ); \
- )
- /// \internal_
- /// For some operators class T can't be floating point type.
- /// See OpenCL specification, operators chapter.
- #define BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(op, op_name) \
- BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR(op, op_name, \
- BOOST_STATIC_ASSERT_MSG( \
- is_fundamental<T>::value && \
- !is_floating_point<typename scalar_type<T>::type>::value, \
- "This operator can be used with all OpenCL built-in scalar" \
- " and vector types except the built-in scalar and vector float types" \
- ); \
- )
- // defining binary operators for valarray
- BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(+, plus)
- BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(-, minus)
- BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(*, multiplies)
- BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY(/, divides)
- BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(^, bit_xor)
- BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(&, bit_and)
- BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(|, bit_or)
- BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(<<, shift_left)
- BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP(>>, shift_right)
- #undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_ANY
- #undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR_NO_FP
- #undef BOOST_COMPUTE_DEFINE_VALARRAY_BINARY_OPERATOR
- /// \internal_
- /// Macro for defining valarray comparison operators.
- /// For return type valarray<char> is used instead of valarray<bool> because
- /// in OpenCL there cannot be memory buffer with bool type.
- ///
- /// Note it's also used for defining binary logical operators (==, &&)
- #define BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(op, op_name) \
- template<class T> \
- valarray<char> operator op (const valarray<T>& lhs, const valarray<T>& rhs) \
- { \
- BOOST_STATIC_ASSERT_MSG( \
- is_fundamental<T>::value, \
- "This operator can be used with all OpenCL built-in scalar" \
- " and vector types" \
- ); \
- valarray<char> result(lhs.size()); \
- transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
- buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
- buffer_iterator<T>(rhs.get_buffer(), 0), \
- buffer_iterator<char>(result.get_buffer(), 0), \
- op_name<T>()); \
- return result; \
- } \
- \
- template<class T> \
- valarray<char> operator op (const T& val, const valarray<T>& rhs) \
- { \
- BOOST_STATIC_ASSERT_MSG( \
- is_fundamental<T>::value, \
- "This operator can be used with all OpenCL built-in scalar" \
- " and vector types" \
- ); \
- valarray<char> result(rhs.size()); \
- transform(buffer_iterator<T>(rhs.get_buffer(), 0), \
- buffer_iterator<T>(rhs.get_buffer(), rhs.size()), \
- buffer_iterator<char>(result.get_buffer(), 0), \
- ::boost::compute::bind(op_name<T>(), val, placeholders::_1)); \
- return result; \
- } \
- \
- template<class T> \
- valarray<char> operator op (const valarray<T>& lhs, const T& val) \
- { \
- BOOST_STATIC_ASSERT_MSG( \
- is_fundamental<T>::value, \
- "This operator can be used with all OpenCL built-in scalar" \
- " and vector types" \
- ); \
- valarray<char> result(lhs.size()); \
- transform(buffer_iterator<T>(lhs.get_buffer(), 0), \
- buffer_iterator<T>(lhs.get_buffer(), lhs.size()), \
- buffer_iterator<char>(result.get_buffer(), 0), \
- ::boost::compute::bind(op_name<T>(), placeholders::_1, val)); \
- return result; \
- }
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(==, equal_to)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(!=, not_equal_to)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(>, greater)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(<, less)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(>=, greater_equal)
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(<=, less_equal)
- /// \internal_
- /// Macro for defining binary logical operators for valarray.
- ///
- /// For return type valarray<char> is used instead of valarray<bool> because
- /// in OpenCL there cannot be memory buffer with bool type.
- /// 1 means true, 0 means false.
- #define BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(op, op_name) \
- BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR(op, op_name)
- BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(&&, logical_and)
- BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR(||, logical_or)
- #undef BOOST_COMPUTE_DEFINE_VALARRAY_LOGICAL_OPERATOR
- #undef BOOST_COMPUTE_DEFINE_VALARRAY_COMPARISON_OPERATOR
- } // end compute namespace
- } // end boost namespace
- #endif // BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
|