Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:59

0001 //---------------------------------------------------------------------------//
0002 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
0003 //
0004 // Distributed under the Boost Software License, Version 1.0
0005 // See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt
0007 //
0008 // See http://boostorg.github.com/compute for more information.
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             // change to other's OpenCL context
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         //  This operator can be used with any type.
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     /// In OpenCL there cannot be memory buffer with bool type, for
0147     /// this reason return type is valarray<char> instead of valarray<bool>.
0148     /// 1 means true, 0 means false.
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 /// \internal_
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 /// \internal_
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 /// \internal_
0301 /// For some operators class T can't be floating point type.
0302 /// See OpenCL specification, operators chapter.
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 // defining operators
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 // The remainder (%) operates on
0325 // integer scalar and integer vector data types only.
0326 // See OpenCL specification.
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 /// \internal_
0340 /// Macro for defining binary operators for valarray
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 /// \internal_
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 /// \internal_
0390 /// For some operators class T can't be floating point type.
0391 /// See OpenCL specification, operators chapter.
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 // defining binary operators for valarray
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 /// \internal_
0419 /// Macro for defining valarray comparison operators.
0420 /// For return type valarray<char> is used instead of valarray<bool> because
0421 /// in OpenCL there cannot be memory buffer with bool type.
0422 ///
0423 /// Note it's also used for defining binary logical operators (==, &&)
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 /// \internal_
0482 /// Macro for defining binary logical operators for valarray.
0483 ///
0484 /// For return type valarray<char> is used instead of valarray<bool> because
0485 /// in OpenCL there cannot be memory buffer with bool type.
0486 /// 1 means true, 0 means false.
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 } // end compute namespace
0498 } // end boost namespace
0499 
0500 #endif // BOOST_COMPUTE_CONTAINER_VALARRAY_HPP