File indexing completed on 2025-01-18 09:30:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_COMPUTE_ITERATOR_TRANSFORM_ITERATOR_HPP
0012 #define BOOST_COMPUTE_ITERATOR_TRANSFORM_ITERATOR_HPP
0013
0014 #include <cstddef>
0015 #include <iterator>
0016
0017 #include <boost/config.hpp>
0018 #include <boost/iterator/iterator_adaptor.hpp>
0019
0020 #include <boost/compute/functional.hpp>
0021 #include <boost/compute/detail/meta_kernel.hpp>
0022 #include <boost/compute/detail/is_buffer_iterator.hpp>
0023 #include <boost/compute/detail/read_write_single_value.hpp>
0024 #include <boost/compute/iterator/detail/get_base_iterator_buffer.hpp>
0025 #include <boost/compute/type_traits/is_device_iterator.hpp>
0026 #include <boost/compute/type_traits/result_of.hpp>
0027
0028 namespace boost {
0029 namespace compute {
0030
0031
0032 template<class InputIterator, class UnaryFunction>
0033 class transform_iterator;
0034
0035 namespace detail {
0036
0037
0038 template<class InputIterator, class UnaryFunction>
0039 struct make_transform_iterator_value_type
0040 {
0041 typedef typename std::iterator_traits<InputIterator>::value_type value_type;
0042
0043 typedef typename boost::compute::result_of<UnaryFunction(value_type)>::type type;
0044 };
0045
0046
0047
0048 template<class InputIterator, class UnaryFunction>
0049 class transform_iterator_base
0050 {
0051 public:
0052 typedef ::boost::iterator_adaptor<
0053 ::boost::compute::transform_iterator<InputIterator, UnaryFunction>,
0054 InputIterator,
0055 typename make_transform_iterator_value_type<InputIterator, UnaryFunction>::type,
0056 typename std::iterator_traits<InputIterator>::iterator_category,
0057 typename make_transform_iterator_value_type<InputIterator, UnaryFunction>::type
0058 > type;
0059 };
0060
0061 template<class InputIterator, class UnaryFunction, class IndexExpr>
0062 struct transform_iterator_index_expr
0063 {
0064 typedef typename
0065 make_transform_iterator_value_type<
0066 InputIterator,
0067 UnaryFunction
0068 >::type result_type;
0069
0070 transform_iterator_index_expr(const InputIterator &input_iter,
0071 const UnaryFunction &transform_expr,
0072 const IndexExpr &index_expr)
0073 : m_input_iter(input_iter),
0074 m_transform_expr(transform_expr),
0075 m_index_expr(index_expr)
0076 {
0077 }
0078
0079 const InputIterator m_input_iter;
0080 const UnaryFunction m_transform_expr;
0081 const IndexExpr m_index_expr;
0082 };
0083
0084 template<class InputIterator, class UnaryFunction, class IndexExpr>
0085 inline meta_kernel& operator<<(meta_kernel &kernel,
0086 const transform_iterator_index_expr<InputIterator,
0087 UnaryFunction,
0088 IndexExpr> &expr)
0089 {
0090 return kernel << expr.m_transform_expr(expr.m_input_iter[expr.m_index_expr]);
0091 }
0092
0093 }
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 template<class InputIterator, class UnaryFunction>
0108 class transform_iterator :
0109 public detail::transform_iterator_base<InputIterator, UnaryFunction>::type
0110 {
0111 public:
0112 typedef typename
0113 detail::transform_iterator_base<InputIterator,
0114 UnaryFunction>::type super_type;
0115 typedef typename super_type::value_type value_type;
0116 typedef typename super_type::reference reference;
0117 typedef typename super_type::base_type base_type;
0118 typedef typename super_type::difference_type difference_type;
0119 typedef UnaryFunction unary_function;
0120
0121 transform_iterator(InputIterator iterator, UnaryFunction transform)
0122 : super_type(iterator),
0123 m_transform(transform)
0124 {
0125 }
0126
0127 transform_iterator(const transform_iterator<InputIterator,
0128 UnaryFunction> &other)
0129 : super_type(other.base()),
0130 m_transform(other.m_transform)
0131 {
0132 }
0133
0134 transform_iterator<InputIterator, UnaryFunction>&
0135 operator=(const transform_iterator<InputIterator,
0136 UnaryFunction> &other)
0137 {
0138 if(this != &other){
0139 super_type::operator=(other);
0140
0141 m_transform = other.m_transform;
0142 }
0143
0144 return *this;
0145 }
0146
0147 ~transform_iterator()
0148 {
0149 }
0150
0151 size_t get_index() const
0152 {
0153 return super_type::base().get_index();
0154 }
0155
0156 const buffer& get_buffer() const
0157 {
0158 return detail::get_base_iterator_buffer(*this);
0159 }
0160
0161 template<class IndexExpression>
0162 detail::transform_iterator_index_expr<InputIterator, UnaryFunction, IndexExpression>
0163 operator[](const IndexExpression &expr) const
0164 {
0165 return detail::transform_iterator_index_expr<InputIterator,
0166 UnaryFunction,
0167 IndexExpression>(super_type::base(),
0168 m_transform,
0169 expr);
0170 }
0171
0172 private:
0173 friend class ::boost::iterator_core_access;
0174
0175 reference dereference() const
0176 {
0177 const context &context = super_type::base().get_buffer().get_context();
0178 command_queue queue(context, context.get_device());
0179
0180 detail::meta_kernel k("read");
0181 size_t output_arg = k.add_arg<value_type *>(memory_object::global_memory, "output");
0182 k << "*output = " << m_transform(super_type::base()[k.lit(0)]) << ";";
0183
0184 kernel kernel = k.compile(context);
0185
0186 buffer output_buffer(context, sizeof(value_type));
0187
0188 kernel.set_arg(output_arg, output_buffer);
0189
0190 queue.enqueue_task(kernel);
0191
0192 return detail::read_single_value<value_type>(output_buffer, queue);
0193 }
0194
0195 private:
0196 UnaryFunction m_transform;
0197 };
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211 template<class InputIterator, class UnaryFunction>
0212 inline transform_iterator<InputIterator, UnaryFunction>
0213 make_transform_iterator(InputIterator iterator, UnaryFunction transform)
0214 {
0215 return transform_iterator<InputIterator,
0216 UnaryFunction>(iterator, transform);
0217 }
0218
0219
0220 template<class InputIterator, class UnaryFunction>
0221 struct is_device_iterator<
0222 transform_iterator<InputIterator, UnaryFunction> > : boost::true_type {};
0223
0224 }
0225 }
0226
0227 #endif