diff options
Diffstat (limited to 'boost/compute/iterator')
-rw-r--r-- | boost/compute/iterator/buffer_iterator.hpp | 280 | ||||
-rw-r--r-- | boost/compute/iterator/constant_buffer_iterator.hpp | 209 | ||||
-rw-r--r-- | boost/compute/iterator/constant_iterator.hpp | 171 | ||||
-rw-r--r-- | boost/compute/iterator/counting_iterator.hpp | 185 | ||||
-rw-r--r-- | boost/compute/iterator/detail/get_base_iterator_buffer.hpp | 52 | ||||
-rw-r--r-- | boost/compute/iterator/detail/swizzle_iterator.hpp | 188 | ||||
-rw-r--r-- | boost/compute/iterator/discard_iterator.hpp | 170 | ||||
-rw-r--r-- | boost/compute/iterator/function_input_iterator.hpp | 186 | ||||
-rw-r--r-- | boost/compute/iterator/permutation_iterator.hpp | 192 | ||||
-rw-r--r-- | boost/compute/iterator/strided_iterator.hpp | 296 | ||||
-rw-r--r-- | boost/compute/iterator/transform_iterator.hpp | 227 | ||||
-rw-r--r-- | boost/compute/iterator/zip_iterator.hpp | 316 |
12 files changed, 2472 insertions, 0 deletions
diff --git a/boost/compute/iterator/buffer_iterator.hpp b/boost/compute/iterator/buffer_iterator.hpp new file mode 100644 index 0000000000..cd68058f64 --- /dev/null +++ b/boost/compute/iterator/buffer_iterator.hpp @@ -0,0 +1,280 @@ +//---------------------------------------------------------------------------// +// 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_ITERATOR_BUFFER_ITERATOR_HPP +#define BOOST_COMPUTE_ITERATOR_BUFFER_ITERATOR_HPP + +#include <cstddef> +#include <iterator> + +#include <boost/config.hpp> +#include <boost/type_traits.hpp> +#include <boost/static_assert.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/iterator/iterator_facade.hpp> + +#include <boost/compute/buffer.hpp> +#include <boost/compute/detail/buffer_value.hpp> +#include <boost/compute/detail/is_buffer_iterator.hpp> +#include <boost/compute/detail/meta_kernel.hpp> +#include <boost/compute/detail/read_write_single_value.hpp> +#include <boost/compute/type_traits/is_device_iterator.hpp> + +namespace boost { +namespace compute { + +// forward declaration for buffer_iterator<T> +template<class T> class buffer_iterator; + +namespace detail { + +// helper class which defines the iterator_facade super-class +// type for buffer_iterator<T> +template<class T> +class buffer_iterator_base +{ +public: + typedef ::boost::iterator_facade< + ::boost::compute::buffer_iterator<T>, + T, + ::std::random_access_iterator_tag, + ::boost::compute::detail::buffer_value<T> + > type; +}; + +template<class T, class IndexExpr> +struct buffer_iterator_index_expr +{ + typedef T result_type; + + buffer_iterator_index_expr(const buffer &buffer, + size_t index, + const memory_object::address_space address_space, + const IndexExpr &expr) + : m_buffer(buffer), + m_index(index), + m_address_space(address_space), + m_expr(expr) + { + } + + operator T() const + { + BOOST_STATIC_ASSERT_MSG(boost::is_integral<IndexExpr>::value, + "Index expression must be integral"); + + return buffer_value<T>(m_buffer, size_t(m_expr) * sizeof(T)); + } + + const buffer &m_buffer; + size_t m_index; + memory_object::address_space m_address_space; + IndexExpr m_expr; +}; + +template<class T, class IndexExpr> +inline meta_kernel& operator<<(meta_kernel &kernel, + const buffer_iterator_index_expr<T, IndexExpr> &expr) +{ + if(expr.m_index == 0){ + return kernel << + kernel.get_buffer_identifier<T>(expr.m_buffer, expr.m_address_space) << + '[' << expr.m_expr << ']'; + } + else { + return kernel << + kernel.get_buffer_identifier<T>(expr.m_buffer, expr.m_address_space) << + '[' << uint_(expr.m_index) << "+(" << expr.m_expr << ")]"; + } +} + +} // end detail namespace + +/// \class buffer_iterator +/// \brief An iterator for values in a buffer. +/// +/// The buffer_iterator class iterates over values in a memory buffer on a +/// compute device. It is the most commonly used iterator in Boost.Compute +/// and is used by the \ref vector "vector<T>" and \ref array "array<T, N>" +/// container classes. +/// +/// Buffer iterators store a reference to a memory buffer along with an index +/// into that memory buffer. +/// +/// The buffer_iterator class allows for arbitrary OpenCL memory objects +/// (including those created outside of Boost.Compute) to be used with the +/// Boost.Compute algorithms (such as transform() and sort()). For example, +/// to reverse the contents of an OpenCL memory buffer containing a set of +/// integers: +/// +/// \snippet test/test_buffer_iterator.cpp reverse_external_buffer +/// +/// \see buffer, make_buffer_iterator() +template<class T> +class buffer_iterator : public detail::buffer_iterator_base<T>::type +{ +public: + typedef typename detail::buffer_iterator_base<T>::type super_type; + typedef typename super_type::reference reference; + typedef typename super_type::difference_type difference_type; + + buffer_iterator() + : m_index(0) + { + } + + buffer_iterator(const buffer &buffer, size_t index) + : m_buffer(buffer.get(), false), + m_index(index) + { + } + + buffer_iterator(const buffer_iterator<T> &other) + : m_buffer(other.m_buffer.get(), false), + m_index(other.m_index) + { + } + + buffer_iterator<T>& operator=(const buffer_iterator<T> &other) + { + if(this != &other){ + m_buffer.get() = other.m_buffer.get(); + m_index = other.m_index; + } + + return *this; + } + + ~buffer_iterator() + { + // set buffer to null so that its reference count will + // not be decremented when its destructor is called + m_buffer.get() = 0; + } + + const buffer& get_buffer() const + { + return m_buffer; + } + + size_t get_index() const + { + return m_index; + } + + T read(command_queue &queue) const + { + BOOST_ASSERT(m_buffer.get()); + BOOST_ASSERT(m_index < m_buffer.size() / sizeof(T)); + + return detail::read_single_value<T>(m_buffer, m_index, queue); + } + + void write(const T &value, command_queue &queue) + { + BOOST_ASSERT(m_buffer.get()); + BOOST_ASSERT(m_index < m_buffer.size() / sizeof(T)); + + detail::write_single_value<T>(value, m_buffer, m_index, queue); + } + + /// \internal_ + template<class Expr> + detail::buffer_iterator_index_expr<T, Expr> + operator[](const Expr &expr) const + { + BOOST_ASSERT(m_buffer.get()); + + return detail::buffer_iterator_index_expr<T, Expr>( + m_buffer, m_index, memory_object::global_memory, expr + ); + } + +private: + friend class ::boost::iterator_core_access; + + /// \internal_ + reference dereference() const + { + return detail::buffer_value<T>(m_buffer, m_index * sizeof(T)); + } + + /// \internal_ + bool equal(const buffer_iterator<T> &other) const + { + return m_buffer.get() == other.m_buffer.get() && + m_index == other.m_index; + } + + /// \internal_ + void increment() + { + m_index++; + } + + /// \internal_ + void decrement() + { + m_index--; + } + + /// \internal_ + void advance(difference_type n) + { + m_index = static_cast<size_t>(static_cast<difference_type>(m_index) + n); + } + + /// \internal_ + difference_type distance_to(const buffer_iterator<T> &other) const + { + return static_cast<difference_type>(other.m_index - m_index); + } + +private: + const buffer m_buffer; + size_t m_index; +}; + +/// Creates a new \ref buffer_iterator for \p buffer at \p index. +/// +/// \param buffer the \ref buffer object +/// \param index the index in the buffer +/// +/// \return a \c buffer_iterator for \p buffer at \p index +template<class T> +inline buffer_iterator<T> +make_buffer_iterator(const buffer &buffer, size_t index = 0) +{ + return buffer_iterator<T>(buffer, index); +} + +/// \internal_ (is_device_iterator specialization for buffer_iterator) +template<class T> +struct is_device_iterator<buffer_iterator<T> > : boost::true_type {}; + +namespace detail { + +// is_buffer_iterator specialization for buffer_iterator +template<class Iterator> +struct is_buffer_iterator< + Iterator, + typename boost::enable_if< + boost::is_same< + buffer_iterator<typename Iterator::value_type>, + typename boost::remove_const<Iterator>::type + > + >::type +> : public boost::true_type {}; + +} // end detail namespace +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ITERATOR_BUFFER_ITERATOR_HPP diff --git a/boost/compute/iterator/constant_buffer_iterator.hpp b/boost/compute/iterator/constant_buffer_iterator.hpp new file mode 100644 index 0000000000..ef9a2ac959 --- /dev/null +++ b/boost/compute/iterator/constant_buffer_iterator.hpp @@ -0,0 +1,209 @@ +//---------------------------------------------------------------------------// +// 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_ITERATOR_CONSTANT_BUFFER_ITERATOR_HPP +#define BOOST_COMPUTE_ITERATOR_CONSTANT_BUFFER_ITERATOR_HPP + +#include <cstddef> +#include <iterator> + +#include <boost/iterator/iterator_facade.hpp> + +#include <boost/compute/buffer.hpp> +#include <boost/compute/iterator/buffer_iterator.hpp> +#include <boost/compute/type_traits/is_device_iterator.hpp> + +namespace boost { +namespace compute { + +// forward declaration for constant_buffer_iterator<T> +template<class T> class constant_buffer_iterator; + +namespace detail { + +// helper class which defines the iterator_facade super-class +// type for constant_buffer_iterator<T> +template<class T> +class constant_buffer_iterator_base +{ +public: + typedef ::boost::iterator_facade< + ::boost::compute::constant_buffer_iterator<T>, + T, + ::std::random_access_iterator_tag, + ::boost::compute::detail::buffer_value<T> + > type; +}; + +} // end detail namespace + +/// \class constant_buffer_iterator +/// \brief An iterator for a buffer in the \c constant memory space. +/// +/// The constant_buffer_iterator class provides an iterator for values in a +/// buffer in the \c constant memory space. +/// +/// For iterating over values in the \c global memory space (the most common +/// case), use the buffer_iterator class. +/// +/// \see buffer_iterator +template<class T> +class constant_buffer_iterator : + public detail::constant_buffer_iterator_base<T>::type +{ +public: + typedef typename detail::constant_buffer_iterator_base<T>::type super_type; + typedef typename super_type::reference reference; + typedef typename super_type::difference_type difference_type; + + constant_buffer_iterator() + : m_buffer(0), + m_index(0) + { + } + + constant_buffer_iterator(const buffer &buffer, size_t index) + : m_buffer(&buffer), + m_index(index) + { + } + + constant_buffer_iterator(const constant_buffer_iterator<T> &other) + : m_buffer(other.m_buffer), + m_index(other.m_index) + { + } + + constant_buffer_iterator<T>& operator=(const constant_buffer_iterator<T> &other) + { + if(this != &other){ + m_buffer = other.m_buffer; + m_index = other.m_index; + } + + return *this; + } + + ~constant_buffer_iterator() + { + } + + const buffer& get_buffer() const + { + return *m_buffer; + } + + size_t get_index() const + { + return m_index; + } + + T read(command_queue &queue) const + { + BOOST_ASSERT(m_buffer && m_buffer->get()); + BOOST_ASSERT(m_index < m_buffer->size() / sizeof(T)); + + return detail::read_single_value<T>(m_buffer, m_index, queue); + } + + void write(const T &value, command_queue &queue) + { + BOOST_ASSERT(m_buffer && m_buffer->get()); + BOOST_ASSERT(m_index < m_buffer->size() / sizeof(T)); + + detail::write_single_value<T>(m_buffer, m_index, queue); + } + + template<class Expr> + detail::buffer_iterator_index_expr<T, Expr> + operator[](const Expr &expr) const + { + BOOST_ASSERT(m_buffer); + BOOST_ASSERT(m_buffer->get()); + + return detail::buffer_iterator_index_expr<T, Expr>( + *m_buffer, m_index, memory_object::constant_memory, expr + ); + } + +private: + friend class ::boost::iterator_core_access; + + reference dereference() const + { + return detail::buffer_value<T>(*m_buffer, m_index); + } + + bool equal(const constant_buffer_iterator<T> &other) const + { + return m_buffer == other.m_buffer && m_index == other.m_index; + } + + void increment() + { + m_index++; + } + + void decrement() + { + m_index--; + } + + void advance(difference_type n) + { + m_index = static_cast<size_t>(static_cast<difference_type>(m_index) + n); + } + + difference_type distance_to(const constant_buffer_iterator<T> &other) const + { + return static_cast<difference_type>(other.m_index - m_index); + } + +private: + const buffer *m_buffer; + size_t m_index; +}; + +/// Creates a new constant_buffer_iterator for \p buffer at \p index. +/// +/// \param buffer the \ref buffer object +/// \param index the index in the buffer +/// +/// \return a \c constant_buffer_iterator for \p buffer at \p index +template<class T> +inline constant_buffer_iterator<T> +make_constant_buffer_iterator(const buffer &buffer, size_t index = 0) +{ + return constant_buffer_iterator<T>(buffer, index); +} + +/// \internal_ (is_device_iterator specialization for constant_buffer_iterator) +template<class T> +struct is_device_iterator<constant_buffer_iterator<T> > : boost::true_type {}; + +namespace detail { + +// is_buffer_iterator specialization for constant_buffer_iterator +template<class Iterator> +struct is_buffer_iterator< + Iterator, + typename boost::enable_if< + boost::is_same< + constant_buffer_iterator<typename Iterator::value_type>, + typename boost::remove_const<Iterator>::type + > + >::type +> : public boost::true_type {}; + +} // end detail namespace +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ITERATOR_CONSTANT_BUFFER_ITERATOR_HPP diff --git a/boost/compute/iterator/constant_iterator.hpp b/boost/compute/iterator/constant_iterator.hpp new file mode 100644 index 0000000000..f0d45c02c0 --- /dev/null +++ b/boost/compute/iterator/constant_iterator.hpp @@ -0,0 +1,171 @@ +//---------------------------------------------------------------------------// +// 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_ITERATOR_CONSTANT_ITERATOR_HPP +#define BOOST_COMPUTE_ITERATOR_CONSTANT_ITERATOR_HPP + +#include <string> +#include <cstddef> +#include <iterator> + +#include <boost/config.hpp> +#include <boost/iterator/iterator_facade.hpp> + +#include <boost/compute/detail/meta_kernel.hpp> +#include <boost/compute/type_traits/is_device_iterator.hpp> + +namespace boost { +namespace compute { + +// forward declaration for constant_iterator<T> +template<class T> class constant_iterator; + +namespace detail { + +// helper class which defines the iterator_facade super-class +// type for constant_iterator<T> +template<class T> +class constant_iterator_base +{ +public: + typedef ::boost::iterator_facade< + ::boost::compute::constant_iterator<T>, + T, + ::std::random_access_iterator_tag + > type; +}; + +} // end detail namespace + +/// \class constant_iterator +/// \brief An iterator with a constant value. +/// +/// The constant_iterator class provides an iterator which returns a constant +/// value when dereferenced. +/// +/// For example, this could be used to implement the fill() algorithm in terms +/// of the copy() algorithm by copying from a range of constant iterators: +/// +/// \snippet test/test_constant_iterator.cpp fill_with_copy +/// +/// \see make_constant_iterator() +template<class T> +class constant_iterator : public detail::constant_iterator_base<T>::type +{ +public: + typedef typename detail::constant_iterator_base<T>::type super_type; + typedef typename super_type::reference reference; + typedef typename super_type::difference_type difference_type; + + constant_iterator(const T &value, size_t index = 0) + : m_value(value), + m_index(index) + { + } + + constant_iterator(const constant_iterator<T> &other) + : m_value(other.m_value), + m_index(other.m_index) + { + } + + constant_iterator<T>& operator=(const constant_iterator<T> &other) + { + if(this != &other){ + m_value = other.m_value; + m_index = other.m_index; + } + + return *this; + } + + ~constant_iterator() + { + } + + size_t get_index() const + { + return m_index; + } + + /// \internal_ + template<class Expr> + detail::meta_kernel_literal<T> operator[](const Expr &expr) const + { + (void) expr; + + return detail::meta_kernel::make_lit<T>(m_value); + } + +private: + friend class ::boost::iterator_core_access; + + /// \internal_ + reference dereference() const + { + return m_value; + } + + /// \internal_ + bool equal(const constant_iterator<T> &other) const + { + return m_value == other.m_value && m_index == other.m_index; + } + + /// \internal_ + void increment() + { + m_index++; + } + + /// \internal_ + void decrement() + { + m_index--; + } + + /// \internal_ + void advance(difference_type n) + { + m_index = static_cast<size_t>(static_cast<difference_type>(m_index) + n); + } + + /// \internal_ + difference_type distance_to(const constant_iterator<T> &other) const + { + return static_cast<difference_type>(other.m_index - m_index); + } + +private: + T m_value; + size_t m_index; +}; + +/// Returns a new constant_iterator with \p value at \p index. +/// +/// \param value the constant value +/// \param index the iterators index +/// +/// \return a \c constant_iterator with \p value +template<class T> +inline constant_iterator<T> +make_constant_iterator(const T &value, size_t index = 0) +{ + return constant_iterator<T>(value, index); +} + +/// \internal_ (is_device_iterator specialization for constant_iterator) +template<class T> +struct is_device_iterator<constant_iterator<T> > : boost::true_type {}; + +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ITERATOR_CONSTANT_ITERATOR_HPP diff --git a/boost/compute/iterator/counting_iterator.hpp b/boost/compute/iterator/counting_iterator.hpp new file mode 100644 index 0000000000..304c1e05cf --- /dev/null +++ b/boost/compute/iterator/counting_iterator.hpp @@ -0,0 +1,185 @@ +//---------------------------------------------------------------------------// +// 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_ITERATOR_COUNTING_ITERATOR_HPP +#define BOOST_COMPUTE_ITERATOR_COUNTING_ITERATOR_HPP + +#include <string> +#include <cstddef> +#include <iterator> + +#include <boost/config.hpp> +#include <boost/iterator/iterator_facade.hpp> + +#include <boost/compute/detail/meta_kernel.hpp> +#include <boost/compute/type_traits/is_device_iterator.hpp> + +namespace boost { +namespace compute { + +// forward declaration for counting_iterator<T> +template<class T> class counting_iterator; + +namespace detail { + +// helper class which defines the iterator_facade super-class +// type for counting_iterator<T> +template<class T> +class counting_iterator_base +{ +public: + typedef ::boost::iterator_facade< + ::boost::compute::counting_iterator<T>, + T, + ::std::random_access_iterator_tag + > type; +}; + +template<class T, class IndexExpr> +struct counting_iterator_index_expr +{ + typedef T result_type; + + counting_iterator_index_expr(const T &init, const IndexExpr &expr) + : m_init(init), + m_expr(expr) + { + } + + const T &m_init; + IndexExpr m_expr; +}; + +template<class T, class IndexExpr> +inline meta_kernel& operator<<(meta_kernel &kernel, + const counting_iterator_index_expr<T, IndexExpr> &expr) +{ + return kernel << '(' << expr.m_init << '+' << expr.m_expr << ')'; +} + +} // end detail namespace + +/// \class counting_iterator +/// \brief The counting_iterator class implements a counting iterator. +/// +/// A counting iterator returns an internal value (initialized with \p init) +/// which is incremented each time the iterator is incremented. +/// +/// For example, this could be used to implement the iota() algorithm in terms +/// of the copy() algorithm by copying from a range of counting iterators: +/// +/// \snippet test/test_counting_iterator.cpp iota_with_copy +/// +/// \see make_counting_iterator() +template<class T> +class counting_iterator : public detail::counting_iterator_base<T>::type +{ +public: + typedef typename detail::counting_iterator_base<T>::type super_type; + typedef typename super_type::reference reference; + typedef typename super_type::difference_type difference_type; + + counting_iterator(const T &init) + : m_init(init) + { + } + + counting_iterator(const counting_iterator<T> &other) + : m_init(other.m_init) + { + } + + counting_iterator<T>& operator=(const counting_iterator<T> &other) + { + if(this != &other){ + m_init = other.m_init; + } + + return *this; + } + + ~counting_iterator() + { + } + + size_t get_index() const + { + return 0; + } + + template<class Expr> + detail::counting_iterator_index_expr<T, Expr> + operator[](const Expr &expr) const + { + return detail::counting_iterator_index_expr<T, Expr>(m_init, expr); + } + +private: + friend class ::boost::iterator_core_access; + + reference dereference() const + { + return m_init; + } + + bool equal(const counting_iterator<T> &other) const + { + return m_init == other.m_init; + } + + void increment() + { + m_init++; + } + + void decrement() + { + m_init--; + } + + void advance(difference_type n) + { + m_init += static_cast<T>(n); + } + + difference_type distance_to(const counting_iterator<T> &other) const + { + return difference_type(other.m_init) - difference_type(m_init); + } + +private: + T m_init; +}; + +/// Returns a new counting_iterator starting at \p init. +/// +/// \param init the initial value +/// +/// \return a counting_iterator with \p init. +/// +/// For example, to create a counting iterator which returns unsigned integers +/// and increments from one: +/// \code +/// auto iter = make_counting_iterator<uint_>(1); +/// \endcode +template<class T> +inline counting_iterator<T> make_counting_iterator(const T &init) +{ + return counting_iterator<T>(init); +} + +/// \internal_ (is_device_iterator specialization for counting_iterator) +template<class T> +struct is_device_iterator<counting_iterator<T> > : boost::true_type {}; + +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ITERATOR_COUNTING_ITERATOR_HPP diff --git a/boost/compute/iterator/detail/get_base_iterator_buffer.hpp b/boost/compute/iterator/detail/get_base_iterator_buffer.hpp new file mode 100644 index 0000000000..3d14355115 --- /dev/null +++ b/boost/compute/iterator/detail/get_base_iterator_buffer.hpp @@ -0,0 +1,52 @@ +//---------------------------------------------------------------------------// +// 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_ITERATOR_DETAIL_GET_BASE_ITERATOR_BUFFER_HPP +#define BOOST_COMPUTE_ITERATOR_DETAIL_GET_BASE_ITERATOR_BUFFER_HPP + +namespace boost { +namespace compute { +namespace detail { + +// returns the buffer for an iterator adaptor's base iterator if +// it exists, otherwise returns a null buffer object. +template<class Iterator> +inline const buffer& +get_base_iterator_buffer(const Iterator &iter, + typename boost::enable_if< + is_buffer_iterator< + typename Iterator::base_type + > + >::type* = 0) +{ + return iter.base().get_buffer(); +} + +template<class Iterator> +inline const buffer& +get_base_iterator_buffer(const Iterator &iter, + typename boost::disable_if< + is_buffer_iterator< + typename Iterator::base_type + > + >::type* = 0) +{ + (void) iter; + + static buffer null_buffer; + + return null_buffer; +} + +} // end detail namespace +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ITERATOR_DETAIL_GET_BASE_ITERATOR_BUFFER_HPP diff --git a/boost/compute/iterator/detail/swizzle_iterator.hpp b/boost/compute/iterator/detail/swizzle_iterator.hpp new file mode 100644 index 0000000000..c7c3c45340 --- /dev/null +++ b/boost/compute/iterator/detail/swizzle_iterator.hpp @@ -0,0 +1,188 @@ +//---------------------------------------------------------------------------// +// 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_ITERATOR_DETAIL_SWIZZLE_ITERATOR_HPP +#define BOOST_COMPUTE_ITERATOR_DETAIL_SWIZZLE_ITERATOR_HPP + +#include <string> +#include <cstddef> +#include <iterator> + +#include <boost/config.hpp> +#include <boost/iterator/iterator_adaptor.hpp> + +#include <boost/compute/functional.hpp> +#include <boost/compute/detail/meta_kernel.hpp> +#include <boost/compute/type_traits/make_vector_type.hpp> +#include <boost/compute/detail/is_buffer_iterator.hpp> +#include <boost/compute/detail/read_write_single_value.hpp> +#include <boost/compute/iterator/detail/get_base_iterator_buffer.hpp> +#include <boost/compute/type_traits/is_device_iterator.hpp> + +namespace boost { +namespace compute { +namespace detail { + +// forward declaration for swizzle_iterator +template<class InputIterator, size_t Size> +class swizzle_iterator; + +// meta-function returing the value_type for a swizzle_iterator +template<class InputIterator, size_t Size> +struct make_swizzle_iterator_value_type +{ + typedef + typename make_vector_type< + typename scalar_type< + typename std::iterator_traits<InputIterator>::value_type + >::type, + Size + >::type type; +}; + +// helper class which defines the iterator_adaptor super-class +// type for swizzle_iterator +template<class InputIterator, size_t Size> +class swizzle_iterator_base +{ +public: + typedef ::boost::iterator_adaptor< + swizzle_iterator<InputIterator, Size>, + InputIterator, + typename make_swizzle_iterator_value_type<InputIterator, Size>::type, + typename std::iterator_traits<InputIterator>::iterator_category, + typename make_swizzle_iterator_value_type<InputIterator, Size>::type + > type; +}; + +template<class InputIterator, size_t Size, class IndexExpr> +struct swizzle_iterator_index_expr +{ + typedef typename make_swizzle_iterator_value_type<InputIterator, Size>::type result_type; + + swizzle_iterator_index_expr(const InputIterator &input_iter, + const IndexExpr &index_expr, + const std::string &components) + : m_input_iter(input_iter), + m_index_expr(index_expr), + m_components(components) + { + } + + InputIterator m_input_iter; + IndexExpr m_index_expr; + std::string m_components; +}; + +template<class InputIterator, size_t Size, class IndexExpr> +inline meta_kernel& operator<<(meta_kernel &kernel, + const swizzle_iterator_index_expr<InputIterator, + Size, + IndexExpr> &expr) +{ + return kernel << expr.m_input_iter[expr.m_index_expr] + << "." << expr.m_components; +} + +template<class InputIterator, size_t Size> +class swizzle_iterator : + public swizzle_iterator_base<InputIterator, Size>::type +{ +public: + typedef typename + swizzle_iterator_base<InputIterator, Size>::type + super_type; + typedef typename super_type::value_type value_type; + typedef typename super_type::reference reference; + typedef typename super_type::base_type base_type; + typedef typename super_type::difference_type difference_type; + + BOOST_STATIC_CONSTANT(size_t, vector_size = Size); + + swizzle_iterator(InputIterator iterator, const std::string &components) + : super_type(iterator), + m_components(components) + { + BOOST_ASSERT(components.size() == Size); + } + + swizzle_iterator(const swizzle_iterator<InputIterator, Size> &other) + : super_type(other.base()), + m_components(other.m_components) + { + BOOST_ASSERT(m_components.size() == Size); + } + + swizzle_iterator<InputIterator, Size>& + operator=(const swizzle_iterator<InputIterator, Size> &other) + { + if(this != &other){ + super_type::operator=(other); + + m_components = other.m_components; + } + + return *this; + } + + ~swizzle_iterator() + { + } + + size_t get_index() const + { + return super_type::base().get_index(); + } + + const buffer& get_buffer() const + { + return get_base_iterator_buffer(*this); + } + + template<class IndexExpression> + swizzle_iterator_index_expr<InputIterator, Size, IndexExpression> + operator[](const IndexExpression &expr) const + { + return swizzle_iterator_index_expr<InputIterator, + Size, + IndexExpression>(super_type::base(), + expr, + m_components); + } + +private: + friend class ::boost::iterator_core_access; + + reference dereference() const + { + return reference(); + } + +private: + std::string m_components; +}; + +template<size_t Size, class InputIterator> +inline swizzle_iterator<InputIterator, Size> +make_swizzle_iterator(InputIterator iterator, const std::string &components) +{ + return swizzle_iterator<InputIterator, Size>(iterator, components); +} + +} // end detail namespace + +// is_device_iterator specialization for swizzle_iterator +template<size_t Size, class InputIterator> +struct is_device_iterator<detail::swizzle_iterator<InputIterator, Size> > : boost::true_type {}; + +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ITERATOR_SWIZZLE_ITERATOR_HPP diff --git a/boost/compute/iterator/discard_iterator.hpp b/boost/compute/iterator/discard_iterator.hpp new file mode 100644 index 0000000000..e002cf2ac2 --- /dev/null +++ b/boost/compute/iterator/discard_iterator.hpp @@ -0,0 +1,170 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2013-2014 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_ITERATOR_DISCARD_ITERATOR_HPP +#define BOOST_COMPUTE_ITERATOR_DISCARD_ITERATOR_HPP + +#include <string> +#include <cstddef> +#include <iterator> + +#include <boost/config.hpp> +#include <boost/iterator/iterator_facade.hpp> + +#include <boost/compute/detail/meta_kernel.hpp> +#include <boost/compute/type_traits/is_device_iterator.hpp> + +namespace boost { +namespace compute { + +// forward declaration for discard_iterator +class discard_iterator; + +namespace detail { + +// helper class which defines the iterator_facade super-class +// type for discard_iterator +struct discard_iterator_base +{ + typedef ::boost::iterator_facade< + ::boost::compute::discard_iterator, + void, + ::std::random_access_iterator_tag, + void * + > type; +}; + +template<class IndexExpr> +struct discard_iterator_index_expr +{ + typedef void result_type; + + discard_iterator_index_expr(const IndexExpr &expr) + : m_expr(expr) + { + } + + IndexExpr m_expr; +}; + +template<class IndexExpr> +inline meta_kernel& operator<<(meta_kernel &kernel, + const discard_iterator_index_expr<IndexExpr> &expr) +{ + (void) expr; + + return kernel; +} + +} // end detail namespace + +/// \class discard_iterator +/// \brief An iterator which discards all values written to it. +/// +/// \see make_discard_iterator(), constant_iterator +class discard_iterator : public detail::discard_iterator_base::type +{ +public: + typedef detail::discard_iterator_base::type super_type; + typedef super_type::reference reference; + typedef super_type::difference_type difference_type; + + discard_iterator(size_t index = 0) + : m_index(index) + { + } + + discard_iterator(const discard_iterator &other) + : m_index(other.m_index) + { + } + + discard_iterator& operator=(const discard_iterator &other) + { + if(this != &other){ + m_index = other.m_index; + } + + return *this; + } + + ~discard_iterator() + { + } + + /// \internal_ + template<class Expr> + detail::discard_iterator_index_expr<Expr> + operator[](const Expr &expr) const + { + return detail::discard_iterator_index_expr<Expr>(expr); + } + +private: + friend class ::boost::iterator_core_access; + + /// \internal_ + reference dereference() const + { + return 0; + } + + /// \internal_ + bool equal(const discard_iterator &other) const + { + return m_index == other.m_index; + } + + /// \internal_ + void increment() + { + m_index++; + } + + /// \internal_ + void decrement() + { + m_index--; + } + + /// \internal_ + void advance(difference_type n) + { + m_index = static_cast<size_t>(static_cast<difference_type>(m_index) + n); + } + + /// \internal_ + difference_type distance_to(const discard_iterator &other) const + { + return static_cast<difference_type>(other.m_index - m_index); + } + +private: + size_t m_index; +}; + +/// Returns a new discard_iterator with \p index. +/// +/// \param index the index of the iterator +/// +/// \return a \c discard_iterator at \p index +inline discard_iterator make_discard_iterator(size_t index = 0) +{ + return discard_iterator(index); +} + +/// internal_ (is_device_iterator specialization for discard_iterator) +template<> +struct is_device_iterator<discard_iterator> : boost::true_type {}; + +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ITERATOR_DISCARD_ITERATOR_HPP diff --git a/boost/compute/iterator/function_input_iterator.hpp b/boost/compute/iterator/function_input_iterator.hpp new file mode 100644 index 0000000000..bd89b6c0fc --- /dev/null +++ b/boost/compute/iterator/function_input_iterator.hpp @@ -0,0 +1,186 @@ +//---------------------------------------------------------------------------// +// 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_ITERATOR_FUNCTION_INPUT_ITERATOR_HPP +#define BOOST_COMPUTE_ITERATOR_FUNCTION_INPUT_ITERATOR_HPP + +#include <cstddef> +#include <iterator> + +#include <boost/config.hpp> +#include <boost/iterator/iterator_facade.hpp> + +#include <boost/compute/detail/meta_kernel.hpp> +#include <boost/compute/type_traits/is_device_iterator.hpp> +#include <boost/compute/type_traits/result_of.hpp> + +namespace boost { +namespace compute { + +// forward declaration for function_input_iterator<Function> +template<class Function> class function_input_iterator; + +namespace detail { + +// helper class which defines the iterator_facade super-class +// type for function_input_iterator<Function> +template<class Function> +class function_input_iterator_base +{ +public: + typedef ::boost::iterator_facade< + ::boost::compute::function_input_iterator<Function>, + typename ::boost::compute::result_of<Function()>::type, + ::std::random_access_iterator_tag, + typename ::boost::compute::result_of<Function()>::type + > type; +}; + +template<class Function> +struct function_input_iterator_expr +{ + typedef typename ::boost::compute::result_of<Function()>::type result_type; + + function_input_iterator_expr(const Function &function) + : m_function(function) + { + } + + Function m_function; +}; + +template<class Function> +inline meta_kernel& operator<<(meta_kernel &kernel, + const function_input_iterator_expr<Function> &expr) +{ + return kernel << expr.m_function(); +} + +} // end detail namespace + +/// \class function_input_iterator +/// \brief Iterator which returns the result of a function when dereferenced +/// +/// For example: +/// +/// \snippet test/test_function_input_iterator.cpp generate_42 +/// +/// \see make_function_input_iterator() +template<class Function> +class function_input_iterator : + public detail::function_input_iterator_base<Function>::type +{ +public: + typedef typename detail::function_input_iterator_base<Function>::type super_type; + typedef typename super_type::reference reference; + typedef typename super_type::difference_type difference_type; + typedef Function function; + + function_input_iterator(const Function &function, size_t index = 0) + : m_function(function), + m_index(index) + { + } + + function_input_iterator(const function_input_iterator<Function> &other) + : m_function(other.m_function), + m_index(other.m_index) + { + } + + function_input_iterator<Function>& + operator=(const function_input_iterator<Function> &other) + { + if(this != &other){ + m_function = other.m_function; + m_index = other.m_index; + } + + return *this; + } + + ~function_input_iterator() + { + } + + size_t get_index() const + { + return m_index; + } + + template<class Expr> + detail::function_input_iterator_expr<Function> + operator[](const Expr &expr) const + { + (void) expr; + + return detail::function_input_iterator_expr<Function>(m_function); + } + +private: + friend class ::boost::iterator_core_access; + + reference dereference() const + { + return reference(); + } + + bool equal(const function_input_iterator<Function> &other) const + { + return m_function == other.m_function && m_index == other.m_index; + } + + void increment() + { + m_index++; + } + + void decrement() + { + m_index--; + } + + void advance(difference_type n) + { + m_index = static_cast<size_t>(static_cast<difference_type>(m_index) + n); + } + + difference_type + distance_to(const function_input_iterator<Function> &other) const + { + return static_cast<difference_type>(other.m_index - m_index); + } + +private: + Function m_function; + size_t m_index; +}; + +/// Returns a function_input_iterator with \p function. +/// +/// \param function function to execute when dereferenced +/// \param index index of the iterator +/// +/// \return a \c function_input_iterator with \p function +template<class Function> +inline function_input_iterator<Function> +make_function_input_iterator(const Function &function, size_t index = 0) +{ + return function_input_iterator<Function>(function, index); +} + +/// \internal_ (is_device_iterator specialization for function_input_iterator) +template<class Function> +struct is_device_iterator<function_input_iterator<Function> > : boost::true_type {}; + +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ITERATOR_FUNCTION_INPUT_ITERATOR_HPP diff --git a/boost/compute/iterator/permutation_iterator.hpp b/boost/compute/iterator/permutation_iterator.hpp new file mode 100644 index 0000000000..8a7f97a402 --- /dev/null +++ b/boost/compute/iterator/permutation_iterator.hpp @@ -0,0 +1,192 @@ +//---------------------------------------------------------------------------// +// 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_ITERATOR_PERMUTATION_ITERATOR_HPP +#define BOOST_COMPUTE_ITERATOR_PERMUTATION_ITERATOR_HPP + +#include <string> +#include <cstddef> +#include <iterator> + +#include <boost/config.hpp> +#include <boost/iterator/iterator_adaptor.hpp> + +#include <boost/compute/functional.hpp> +#include <boost/compute/detail/meta_kernel.hpp> +#include <boost/compute/detail/is_buffer_iterator.hpp> +#include <boost/compute/detail/read_write_single_value.hpp> +#include <boost/compute/iterator/detail/get_base_iterator_buffer.hpp> +#include <boost/compute/type_traits/is_device_iterator.hpp> + +namespace boost { +namespace compute { + +// forward declaration for transform_iterator +template<class ElementIterator, class IndexIterator> +class permutation_iterator; + +namespace detail { + +// helper class which defines the iterator_adaptor super-class +// type for permutation_iterator +template<class ElementIterator, class IndexIterator> +class permutation_iterator_base +{ +public: + typedef ::boost::iterator_adaptor< + ::boost::compute::permutation_iterator<ElementIterator, IndexIterator>, + ElementIterator + > type; +}; + +template<class ElementIterator, class IndexIterator, class IndexExpr> +struct permutation_iterator_access_expr +{ + typedef typename std::iterator_traits<ElementIterator>::value_type result_type; + + permutation_iterator_access_expr(const ElementIterator &e, + const IndexIterator &i, + const IndexExpr &expr) + : m_element_iter(e), + m_index_iter(i), + m_expr(expr) + { + } + + ElementIterator m_element_iter; + IndexIterator m_index_iter; + IndexExpr m_expr; +}; + +template<class ElementIterator, class IndexIterator, class IndexExpr> +inline meta_kernel& operator<<(meta_kernel &kernel, + const permutation_iterator_access_expr<ElementIterator, + IndexIterator, + IndexExpr> &expr) +{ + return kernel << expr.m_element_iter[expr.m_index_iter[expr.m_expr]]; +} + +} // end detail namespace + +/// \class permutation_iterator +/// \brief The permutation_iterator class provides a permuation iterator +/// +/// A permutation iterator iterates over a value range and an index range. When +/// dereferenced, it returns the value from the value range using the current +/// index from the index range. +/// +/// For example, to reverse a range using the copy() algorithm and a permutation +/// sequence: +/// +/// \snippet test/test_permutation_iterator.cpp reverse_range +/// +/// \see make_permutation_iterator() +template<class ElementIterator, class IndexIterator> +class permutation_iterator + : public detail::permutation_iterator_base<ElementIterator, + IndexIterator>::type +{ +public: + typedef typename + detail::permutation_iterator_base<ElementIterator, + IndexIterator>::type super_type; + typedef typename super_type::value_type value_type; + typedef typename super_type::reference reference; + typedef typename super_type::base_type base_type; + typedef typename super_type::difference_type difference_type; + typedef IndexIterator index_iterator; + + permutation_iterator(ElementIterator e, IndexIterator i) + : super_type(e), + m_map(i) + { + } + + permutation_iterator(const permutation_iterator<ElementIterator, + IndexIterator> &other) + : super_type(other), + m_map(other.m_map) + { + } + + permutation_iterator<ElementIterator, IndexIterator>& + operator=(const permutation_iterator<ElementIterator, + IndexIterator> &other) + { + if(this != &other){ + super_type::operator=(other); + m_map = other.m_map; + } + + return *this; + } + + ~permutation_iterator() + { + } + + size_t get_index() const + { + return super_type::base().get_index(); + } + + const buffer& get_buffer() const + { + return detail::get_base_iterator_buffer(*this); + } + + template<class IndexExpr> + detail::permutation_iterator_access_expr<ElementIterator, + IndexIterator, + IndexExpr> + operator[](const IndexExpr &expr) const + { + return detail::permutation_iterator_access_expr<ElementIterator, + IndexIterator, + IndexExpr>(super_type::base(), + m_map, + expr); + } + +private: + friend class ::boost::iterator_core_access; + + reference dereference() const + { + return reference(); + } + +private: + IndexIterator m_map; +}; + +/// Returns a permutation_iterator for \p e using indices from \p i. +/// +/// \param e the element range iterator +/// \param i the index range iterator +/// +/// \return a \c permutation_iterator for \p e using \p i +template<class ElementIterator, class IndexIterator> +inline permutation_iterator<ElementIterator, IndexIterator> +make_permutation_iterator(ElementIterator e, IndexIterator i) +{ + return permutation_iterator<ElementIterator, IndexIterator>(e, i); +} + +/// \internal_ (is_device_iterator specialization for permutation_iterator) +template<class ElementIterator, class IndexIterator> +struct is_device_iterator< + permutation_iterator<ElementIterator, IndexIterator> > : boost::true_type {}; + +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ITERATOR_PERMUTATION_ITERATOR_HPP diff --git a/boost/compute/iterator/strided_iterator.hpp b/boost/compute/iterator/strided_iterator.hpp new file mode 100644 index 0000000000..52e7f07bd8 --- /dev/null +++ b/boost/compute/iterator/strided_iterator.hpp @@ -0,0 +1,296 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2015 Jakub Szuppe <j.szuppe@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_ITERATOR_STRIDED_ITERATOR_HPP +#define BOOST_COMPUTE_ITERATOR_STRIDED_ITERATOR_HPP + +#include <cstddef> +#include <iterator> + +#include <boost/config.hpp> +#include <boost/iterator/iterator_adaptor.hpp> + +#include <boost/compute/functional.hpp> +#include <boost/compute/detail/meta_kernel.hpp> +#include <boost/compute/detail/is_buffer_iterator.hpp> +#include <boost/compute/detail/read_write_single_value.hpp> +#include <boost/compute/iterator/detail/get_base_iterator_buffer.hpp> +#include <boost/compute/type_traits/is_device_iterator.hpp> +#include <boost/compute/type_traits/result_of.hpp> + +namespace boost { +namespace compute { + +// forward declaration for strided_iterator +template<class Iterator> +class strided_iterator; + +namespace detail { + +// helper class which defines the iterator_adaptor super-class +// type for strided_iterator +template<class Iterator> +class strided_iterator_base +{ +public: + typedef ::boost::iterator_adaptor< + ::boost::compute::strided_iterator<Iterator>, + Iterator + > type; +}; + +// helper class for including stride value in index expression +template<class IndexExpr, class Stride> +struct stride_expr +{ + stride_expr(const IndexExpr &expr, const Stride &stride) + : m_index_expr(expr), + m_stride(stride) + { + } + + IndexExpr m_index_expr; + Stride m_stride; +}; + +template<class IndexExpr, class Stride> +inline stride_expr<IndexExpr, Stride> make_stride_expr(const IndexExpr &expr, + const Stride &stride) +{ + return stride_expr<IndexExpr, Stride>(expr, stride); +} + +template<class IndexExpr, class Stride> +inline meta_kernel& operator<<(meta_kernel &kernel, + const stride_expr<IndexExpr, Stride> &expr) +{ + // (expr.m_stride * (expr.m_index_expr)) + return kernel << "(" << static_cast<ulong_>(expr.m_stride) + << " * (" << expr.m_index_expr << "))"; +} + +template<class Iterator, class Stride, class IndexExpr> +struct strided_iterator_index_expr +{ + typedef typename std::iterator_traits<Iterator>::value_type result_type; + + strided_iterator_index_expr(const Iterator &input_iter, + const Stride &stride, + const IndexExpr &index_expr) + : m_input_iter(input_iter), + m_stride(stride), + m_index_expr(index_expr) + { + } + + Iterator m_input_iter; + const Stride& m_stride; + IndexExpr m_index_expr; +}; + +template<class Iterator, class Stride, class IndexExpr> +inline meta_kernel& operator<<(meta_kernel &kernel, + const strided_iterator_index_expr<Iterator, + Stride, + IndexExpr> &expr) +{ + return kernel << expr.m_input_iter[make_stride_expr(expr.m_index_expr, expr.m_stride)]; +} + +} // end detail namespace + +/// \class strided_iterator +/// \brief An iterator adaptor with adjustable iteration step. +/// +/// The strided iterator adaptor skips over multiple elements each time +/// it is incremented or decremented. +/// +/// \see buffer_iterator, make_strided_iterator(), make_strided_iterator_end() +template<class Iterator> +class strided_iterator : + public detail::strided_iterator_base<Iterator>::type +{ +public: + typedef typename + detail::strided_iterator_base<Iterator>::type super_type; + typedef typename super_type::value_type value_type; + typedef typename super_type::reference reference; + typedef typename super_type::base_type base_type; + typedef typename super_type::difference_type difference_type; + + strided_iterator(Iterator iterator, difference_type stride) + : super_type(iterator), + m_stride(static_cast<difference_type>(stride)) + { + // stride must be greater than zero + BOOST_ASSERT_MSG(stride > 0, "Stride must be greater than zero"); + } + + strided_iterator(const strided_iterator<Iterator> &other) + : super_type(other.base()), + m_stride(other.m_stride) + { + } + + strided_iterator<Iterator>& + operator=(const strided_iterator<Iterator> &other) + { + if(this != &other){ + super_type::operator=(other); + + m_stride = other.m_stride; + } + + return *this; + } + + ~strided_iterator() + { + } + + size_t get_index() const + { + return super_type::base().get_index(); + } + + const buffer& get_buffer() const + { + return detail::get_base_iterator_buffer(*this); + } + + template<class IndexExpression> + detail::strided_iterator_index_expr<Iterator, difference_type, IndexExpression> + operator[](const IndexExpression &expr) const + { + typedef + typename detail::strided_iterator_index_expr<Iterator, + difference_type, + IndexExpression> + StridedIndexExprType; + return StridedIndexExprType(super_type::base(),m_stride, expr); + } + +private: + friend class ::boost::iterator_core_access; + + reference dereference() const + { + return reference(); + } + + bool equal(const strided_iterator<Iterator> &other) const + { + return (other.m_stride == m_stride) + && (other.base_reference() == this->base_reference()); + } + + void increment() + { + std::advance(super_type::base_reference(), m_stride); + } + + void decrement() + { + std::advance(super_type::base_reference(),-m_stride); + } + + void advance(typename super_type::difference_type n) + { + std::advance(super_type::base_reference(), n * m_stride); + } + + difference_type distance_to(const strided_iterator<Iterator> &other) const + { + return std::distance(this->base_reference(), other.base_reference()) / m_stride; + } + +private: + difference_type m_stride; +}; + +/// Returns a strided_iterator for \p iterator with \p stride. +/// +/// \param iterator the underlying iterator +/// \param stride the iteration step for strided_iterator +/// +/// \return a \c strided_iterator for \p iterator with \p stride. +/// +/// For example, to create an iterator which iterates over every other +/// element in a \c vector<int>: +/// \code +/// auto strided_iterator = make_strided_iterator(vec.begin(), 2); +/// \endcode +template<class Iterator> +inline strided_iterator<Iterator> +make_strided_iterator(Iterator iterator, + typename std::iterator_traits<Iterator>::difference_type stride) +{ + return strided_iterator<Iterator>(iterator, stride); +} + +/// Returns a strided_iterator which refers to element that would follow +/// the last element accessible through strided_iterator for \p first iterator +/// with \p stride. +/// +/// Parameter \p stride must be greater than zero. +/// +/// \param first the iterator referring to the first element accessible +/// through strided_iterator for \p first with \p stride +/// \param last the iterator referring to the last element that may be +//// accessible through strided_iterator for \p first with \p stride +/// \param stride the iteration step +/// +/// \return a \c strided_iterator referring to element that would follow +/// the last element accessible through strided_iterator for \p first +/// iterator with \p stride. +/// +/// It can be helpful when iterating over strided_iterator: +/// \code +/// // vec.size() may not be divisible by 3 +/// auto strided_iterator_begin = make_strided_iterator(vec.begin(), 3); +/// auto strided_iterator_end = make_strided_iterator_end(vec.begin(), vec.end(), 3); +/// +/// // copy every 3rd element to result +/// boost::compute::copy( +/// strided_iterator_begin, +/// strided_iterator_end, +/// result.begin(), +/// queue +/// ); +/// \endcode +template<class Iterator> +strided_iterator<Iterator> +make_strided_iterator_end(Iterator first, + Iterator last, + typename std::iterator_traits<Iterator>::difference_type stride) +{ + typedef typename std::iterator_traits<Iterator>::difference_type difference_type; + + // calculate distance from end to the last element that would be + // accessible through strided_iterator. + difference_type range = std::distance(first, last); + difference_type d = (range - 1) / stride; + d *= stride; + d -= range; + // advance from end to the element that would follow the last + // accessible element + Iterator end_for_strided_iterator = last; + std::advance(end_for_strided_iterator, d + stride); + return strided_iterator<Iterator>(end_for_strided_iterator, stride); +} + +/// \internal_ (is_device_iterator specialization for strided_iterator) +template<class Iterator> +struct is_device_iterator<strided_iterator<Iterator> > : boost::true_type {}; + +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ITERATOR_STRIDED_ITERATOR_HPP diff --git a/boost/compute/iterator/transform_iterator.hpp b/boost/compute/iterator/transform_iterator.hpp new file mode 100644 index 0000000000..c040922f9d --- /dev/null +++ b/boost/compute/iterator/transform_iterator.hpp @@ -0,0 +1,227 @@ +//---------------------------------------------------------------------------// +// 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_ITERATOR_TRANSFORM_ITERATOR_HPP +#define BOOST_COMPUTE_ITERATOR_TRANSFORM_ITERATOR_HPP + +#include <cstddef> +#include <iterator> + +#include <boost/config.hpp> +#include <boost/iterator/iterator_adaptor.hpp> + +#include <boost/compute/functional.hpp> +#include <boost/compute/detail/meta_kernel.hpp> +#include <boost/compute/detail/is_buffer_iterator.hpp> +#include <boost/compute/detail/read_write_single_value.hpp> +#include <boost/compute/iterator/detail/get_base_iterator_buffer.hpp> +#include <boost/compute/type_traits/is_device_iterator.hpp> +#include <boost/compute/type_traits/result_of.hpp> + +namespace boost { +namespace compute { + +// forward declaration for transform_iterator +template<class InputIterator, class UnaryFunction> +class transform_iterator; + +namespace detail { + +// meta-function returning the value_type for a transform_iterator +template<class InputIterator, class UnaryFunction> +struct make_transform_iterator_value_type +{ + typedef typename std::iterator_traits<InputIterator>::value_type value_type; + + typedef typename boost::compute::result_of<UnaryFunction(value_type)>::type type; +}; + +// helper class which defines the iterator_adaptor super-class +// type for transform_iterator +template<class InputIterator, class UnaryFunction> +class transform_iterator_base +{ +public: + typedef ::boost::iterator_adaptor< + ::boost::compute::transform_iterator<InputIterator, UnaryFunction>, + InputIterator, + typename make_transform_iterator_value_type<InputIterator, UnaryFunction>::type, + typename std::iterator_traits<InputIterator>::iterator_category, + typename make_transform_iterator_value_type<InputIterator, UnaryFunction>::type + > type; +}; + +template<class InputIterator, class UnaryFunction, class IndexExpr> +struct transform_iterator_index_expr +{ + typedef typename + make_transform_iterator_value_type< + InputIterator, + UnaryFunction + >::type result_type; + + transform_iterator_index_expr(const InputIterator &input_iter, + const UnaryFunction &transform_expr, + const IndexExpr &index_expr) + : m_input_iter(input_iter), + m_transform_expr(transform_expr), + m_index_expr(index_expr) + { + } + + InputIterator m_input_iter; + UnaryFunction m_transform_expr; + IndexExpr m_index_expr; +}; + +template<class InputIterator, class UnaryFunction, class IndexExpr> +inline meta_kernel& operator<<(meta_kernel &kernel, + const transform_iterator_index_expr<InputIterator, + UnaryFunction, + IndexExpr> &expr) +{ + return kernel << expr.m_transform_expr(expr.m_input_iter[expr.m_index_expr]); +} + +} // end detail namespace + +/// \class transform_iterator +/// \brief A transform iterator adaptor. +/// +/// The transform_iterator adaptor applies a unary function to each element +/// produced from the underlying iterator when dereferenced. +/// +/// For example, to copy from an input range to an output range while taking +/// the absolute value of each element: +/// +/// \snippet test/test_transform_iterator.cpp copy_abs +/// +/// \see buffer_iterator, make_transform_iterator() +template<class InputIterator, class UnaryFunction> +class transform_iterator : + public detail::transform_iterator_base<InputIterator, UnaryFunction>::type +{ +public: + typedef typename + detail::transform_iterator_base<InputIterator, + UnaryFunction>::type super_type; + typedef typename super_type::value_type value_type; + typedef typename super_type::reference reference; + typedef typename super_type::base_type base_type; + typedef typename super_type::difference_type difference_type; + typedef UnaryFunction unary_function; + + transform_iterator(InputIterator iterator, UnaryFunction transform) + : super_type(iterator), + m_transform(transform) + { + } + + transform_iterator(const transform_iterator<InputIterator, + UnaryFunction> &other) + : super_type(other.base()), + m_transform(other.m_transform) + { + } + + transform_iterator<InputIterator, UnaryFunction>& + operator=(const transform_iterator<InputIterator, + UnaryFunction> &other) + { + if(this != &other){ + super_type::operator=(other); + + m_transform = other.m_transform; + } + + return *this; + } + + ~transform_iterator() + { + } + + size_t get_index() const + { + return super_type::base().get_index(); + } + + const buffer& get_buffer() const + { + return detail::get_base_iterator_buffer(*this); + } + + template<class IndexExpression> + detail::transform_iterator_index_expr<InputIterator, UnaryFunction, IndexExpression> + operator[](const IndexExpression &expr) const + { + return detail::transform_iterator_index_expr<InputIterator, + UnaryFunction, + IndexExpression>(super_type::base(), + m_transform, + expr); + } + +private: + friend class ::boost::iterator_core_access; + + reference dereference() const + { + const context &context = super_type::base().get_buffer().get_context(); + command_queue queue(context, context.get_device()); + + detail::meta_kernel k("read"); + size_t output_arg = k.add_arg<value_type *>(memory_object::global_memory, "output"); + k << "*output = " << m_transform(super_type::base()[k.lit(0)]) << ";"; + + kernel kernel = k.compile(context); + + buffer output_buffer(context, sizeof(value_type)); + + kernel.set_arg(output_arg, output_buffer); + + queue.enqueue_task(kernel); + + return detail::read_single_value<value_type>(output_buffer, queue); + } + +private: + UnaryFunction m_transform; +}; + +/// Returns a transform_iterator for \p iterator with \p transform. +/// +/// \param iterator the underlying iterator +/// \param transform the unary transform function +/// +/// \return a \c transform_iterator for \p iterator with \p transform +/// +/// For example, to create an iterator which returns the square-root of each +/// value in a \c vector<int>: +/// \code +/// auto sqrt_iterator = make_transform_iterator(vec.begin(), sqrt<int>()); +/// \endcode +template<class InputIterator, class UnaryFunction> +inline transform_iterator<InputIterator, UnaryFunction> +make_transform_iterator(InputIterator iterator, UnaryFunction transform) +{ + return transform_iterator<InputIterator, + UnaryFunction>(iterator, transform); +} + +/// \internal_ (is_device_iterator specialization for transform_iterator) +template<class InputIterator, class UnaryFunction> +struct is_device_iterator< + transform_iterator<InputIterator, UnaryFunction> > : boost::true_type {}; + +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ITERATOR_TRANSFORM_ITERATOR_HPP diff --git a/boost/compute/iterator/zip_iterator.hpp b/boost/compute/iterator/zip_iterator.hpp new file mode 100644 index 0000000000..2860d73a93 --- /dev/null +++ b/boost/compute/iterator/zip_iterator.hpp @@ -0,0 +1,316 @@ +//---------------------------------------------------------------------------// +// 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_ITERATOR_ZIP_ITERATOR_HPP +#define BOOST_COMPUTE_ITERATOR_ZIP_ITERATOR_HPP + +#include <cstddef> +#include <iterator> + +#include <boost/config.hpp> +#include <boost/fusion/algorithm/iteration/for_each.hpp> +#include <boost/iterator/iterator_facade.hpp> +#include <boost/mpl/back_inserter.hpp> +#include <boost/mpl/transform.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/preprocessor/repetition.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/tuple/tuple_comparison.hpp> + +#include <boost/compute/config.hpp> +#include <boost/compute/functional.hpp> +#include <boost/compute/detail/meta_kernel.hpp> +#include <boost/compute/detail/mpl_vector_to_tuple.hpp> +#include <boost/compute/types/tuple.hpp> +#include <boost/compute/type_traits/is_device_iterator.hpp> +#include <boost/compute/type_traits/type_name.hpp> + +namespace boost { +namespace compute { + +// forward declaration for zip_iterator +template<class IteratorTuple> +class zip_iterator; + +namespace detail { + +namespace mpl = boost::mpl; + +// meta-function returning the value_type for an iterator +template<class Iterator> +struct make_iterator_value_type +{ + typedef typename std::iterator_traits<Iterator>::value_type type; +}; + +// meta-function returning the value_type for a zip_iterator +template<class IteratorTuple> +struct make_zip_iterator_value_type +{ + typedef typename + detail::mpl_vector_to_tuple< + typename mpl::transform< + IteratorTuple, + make_iterator_value_type<mpl::_1>, + mpl::back_inserter<mpl::vector<> > + >::type + >::type type; +}; + +// helper class which defines the iterator_facade super-class +// type for zip_iterator +template<class IteratorTuple> +class zip_iterator_base +{ +public: + typedef ::boost::iterator_facade< + ::boost::compute::zip_iterator<IteratorTuple>, + typename make_zip_iterator_value_type<IteratorTuple>::type, + ::std::random_access_iterator_tag, + typename make_zip_iterator_value_type<IteratorTuple>::type + > type; +}; + +template<class IteratorTuple, class IndexExpr> +struct zip_iterator_index_expr +{ + typedef typename + make_zip_iterator_value_type<IteratorTuple>::type + result_type; + + zip_iterator_index_expr(const IteratorTuple &iterators, + const IndexExpr &index_expr) + : m_iterators(iterators), + m_index_expr(index_expr) + { + } + + IteratorTuple m_iterators; + IndexExpr m_index_expr; +}; + +/// \internal_ +#define BOOST_COMPUTE_PRINT_ELEM(z, n, unused) \ + BOOST_PP_EXPR_IF(n, << ", ") \ + << boost::get<n>(expr.m_iterators)[expr.m_index_expr] + +/// \internal_ +#define BOOST_COMPUTE_PRINT_ZIP_IDX(z, n, unused) \ +template<BOOST_PP_ENUM_PARAMS(n, class Iterator), class IndexExpr> \ +inline meta_kernel& operator<<( \ + meta_kernel &kernel, \ + const zip_iterator_index_expr< \ + boost::tuple<BOOST_PP_ENUM_PARAMS(n, Iterator)>, \ + IndexExpr \ + > &expr) \ +{ \ + typedef typename \ + boost::tuple<BOOST_PP_ENUM_PARAMS(n, Iterator)> \ + tuple_type; \ + typedef typename \ + make_zip_iterator_value_type<tuple_type>::type \ + value_type; \ + kernel.inject_type<value_type>(); \ + return kernel \ + << "(" << type_name<value_type>() << ")" \ + << "{ " \ + BOOST_PP_REPEAT(n, BOOST_COMPUTE_PRINT_ELEM, ~) \ + << "}"; \ +} + +BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_PRINT_ZIP_IDX, ~) + +#undef BOOST_COMPUTE_PRINT_ZIP_IDX +#undef BOOST_COMPUTE_PRINT_ELEM + +struct iterator_advancer +{ + iterator_advancer(size_t n) + : m_distance(n) + { + } + + template<class Iterator> + void operator()(Iterator &i) const + { + std::advance(i, m_distance); + } + + size_t m_distance; +}; + +template<class Iterator> +void increment_iterator(Iterator &i) +{ + i++; +} + +template<class Iterator> +void decrement_iterator(Iterator &i) +{ + i--; +} + +} // end detail namespace + +/// \class zip_iterator +/// \brief A zip iterator adaptor. +/// +/// The zip_iterator class combines values from multiple input iterators. When +/// dereferenced it returns a tuple containing each value at the current +/// position in each input range. +/// +/// \see make_zip_iterator() +template<class IteratorTuple> +class zip_iterator : public detail::zip_iterator_base<IteratorTuple>::type +{ +public: + typedef typename + detail::zip_iterator_base<IteratorTuple>::type + super_type; + typedef typename super_type::value_type value_type; + typedef typename super_type::reference reference; + typedef typename super_type::difference_type difference_type; + typedef IteratorTuple iterator_tuple; + + zip_iterator(IteratorTuple iterators) + : m_iterators(iterators) + { + } + + zip_iterator(const zip_iterator<IteratorTuple> &other) + : m_iterators(other.m_iterators) + { + } + + zip_iterator<IteratorTuple>& + operator=(const zip_iterator<IteratorTuple> &other) + { + if(this != &other){ + super_type::operator=(other); + + m_iterators = other.m_iterators; + } + + return *this; + } + + ~zip_iterator() + { + } + + const IteratorTuple& get_iterator_tuple() const + { + return m_iterators; + } + + template<class IndexExpression> + detail::zip_iterator_index_expr<IteratorTuple, IndexExpression> + operator[](const IndexExpression &expr) const + { + return detail::zip_iterator_index_expr<IteratorTuple, + IndexExpression>(m_iterators, + expr); + } + +private: + friend class ::boost::iterator_core_access; + + reference dereference() const + { + return reference(); + } + + bool equal(const zip_iterator<IteratorTuple> &other) const + { + return m_iterators == other.m_iterators; + } + + void increment() + { + boost::fusion::for_each(m_iterators, detail::increment_iterator); + } + + void decrement() + { + boost::fusion::for_each(m_iterators, detail::decrement_iterator); + } + + void advance(difference_type n) + { + boost::fusion::for_each(m_iterators, detail::iterator_advancer(n)); + } + + difference_type distance_to(const zip_iterator<IteratorTuple> &other) const + { + return std::distance(boost::get<0>(m_iterators), + boost::get<0>(other.m_iterators)); + } + +private: + IteratorTuple m_iterators; +}; + +/// Creates a zip_iterator for \p iterators. +/// +/// \param iterators a tuple of input iterators to zip together +/// +/// \return a \c zip_iterator for \p iterators +/// +/// For example, to zip together iterators from three vectors (\c a, \c b, and +/// \p c): +/// \code +/// auto zipped = boost::compute::make_zip_iterator( +/// boost::make_tuple(a.begin(), b.begin(), c.begin()) +/// ); +/// \endcode +template<class IteratorTuple> +inline zip_iterator<IteratorTuple> +make_zip_iterator(IteratorTuple iterators) +{ + return zip_iterator<IteratorTuple>(iterators); +} + +/// \internal_ (is_device_iterator specialization for zip_iterator) +template<class IteratorTuple> +struct is_device_iterator<zip_iterator<IteratorTuple> > : boost::true_type {}; + +namespace detail { + +// get<N>() specialization for zip_iterator +/// \internal_ +#define BOOST_COMPUTE_ZIP_GET_N(z, n, unused) \ +template<size_t N, class IteratorTuple, class IndexExpr, \ + BOOST_PP_ENUM_PARAMS(n, class T)> \ +inline meta_kernel& \ +operator<<(meta_kernel &kernel, \ + const invoked_get< \ + N, \ + zip_iterator_index_expr<IteratorTuple, IndexExpr>, \ + boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> \ + > &expr) \ +{ \ + typedef typename boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> Tuple; \ + typedef typename boost::tuples::element<N, Tuple>::type T; \ + BOOST_STATIC_ASSERT(N < size_t(boost::tuples::length<Tuple>::value)); \ + kernel.inject_type<T>(); \ + return kernel \ + << boost::get<N>(expr.m_arg.m_iterators)[expr.m_arg.m_index_expr]; \ +} + +BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_ZIP_GET_N, ~) + +#undef BOOST_COMPUTE_ZIP_GET_N + +} // end detail namespace +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ITERATOR_ZIP_ITERATOR_HPP |