Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:02

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_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 // forward declaration for transform_iterator
0032 template<class InputIterator, class UnaryFunction>
0033 class transform_iterator;
0034 
0035 namespace detail {
0036 
0037 // meta-function returning the value_type for a transform_iterator
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 // helper class which defines the iterator_adaptor super-class
0047 // type for transform_iterator
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 } // end detail namespace
0094 
0095 /// \class transform_iterator
0096 /// \brief A transform iterator adaptor.
0097 ///
0098 /// The transform_iterator adaptor applies a unary function to each element
0099 /// produced from the underlying iterator when dereferenced.
0100 ///
0101 /// For example, to copy from an input range to an output range while taking
0102 /// the absolute value of each element:
0103 ///
0104 /// \snippet test/test_transform_iterator.cpp copy_abs
0105 ///
0106 /// \see buffer_iterator, make_transform_iterator()
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 /// Returns a transform_iterator for \p iterator with \p transform.
0200 ///
0201 /// \param iterator the underlying iterator
0202 /// \param transform the unary transform function
0203 ///
0204 /// \return a \c transform_iterator for \p iterator with \p transform
0205 ///
0206 /// For example, to create an iterator which returns the square-root of each
0207 /// value in a \c vector<int>:
0208 /// \code
0209 /// auto sqrt_iterator = make_transform_iterator(vec.begin(), sqrt<int>());
0210 /// \endcode
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 /// \internal_ (is_device_iterator specialization for transform_iterator)
0220 template<class InputIterator, class UnaryFunction>
0221 struct is_device_iterator<
0222     transform_iterator<InputIterator, UnaryFunction> > : boost::true_type {};
0223 
0224 } // end compute namespace
0225 } // end boost namespace
0226 
0227 #endif // BOOST_COMPUTE_ITERATOR_TRANSFORM_ITERATOR_HPP