diff --git a/thrust/functional.h b/thrust/functional.h index 603b49b88..b3d47f917 100644 --- a/thrust/functional.h +++ b/thrust/functional.h @@ -962,22 +962,116 @@ template /*! \} */ + +/*! \addtogroup placeholder_objects Placeholder Objects + * \ingroup function_objects + * \{ + */ + + +/*! \namespace placeholders + * \brief Facilities for constructing simple functions inline. + * + * Objects in the \p thrust::placeholders namespace may be used to create simple arithmetic functions inline + * in an algorithm invocation. Combining placeholders such as \p _1 and \p _2 with arithmetic operations such as \c + + * creates an unnamed function object which applies the operation to their arguments. + * + * The type of placeholder objects is implementation-defined. + * + * The following code snippet demonstrates how to use the placeholders \p _1 and \p _2 with \p thrust::transform + * to implement the SAXPY computation: + * + * \code + * #include + * #include + * #include + * + * int main() + * { + * thrust::device_vector x(4), y(4); + * x[0] = 1; + * x[1] = 2; + * x[2] = 3; + * x[3] = 4; + * + * y[0] = 1; + * y[1] = 1; + * y[2] = 1; + * y[3] = 1; + * + * float a = 2.0f; + * + * using namespace thrust::placeholders; + * + * thrust::transform(x.begin(), x.end(), y.begin(), y.begin(), + * a * _1 + 2 + * ); + * + * // y is now {3, 5, 7, 9} + * } + * \endcode + */ namespace placeholders { + +/*! \p thrust::placeholders::_1 is the placeholder for the first function parameter. + */ static const thrust::detail::functional::placeholder<0>::type _1; + + +/*! \p thrust::placeholders::_2 is the placeholder for the second function parameter. + */ static const thrust::detail::functional::placeholder<1>::type _2; + + +/*! \p thrust::placeholders::_3 is the placeholder for the third function parameter. + */ static const thrust::detail::functional::placeholder<2>::type _3; + + +/*! \p thrust::placeholders::_4 is the placeholder for the fourth function parameter. + */ static const thrust::detail::functional::placeholder<3>::type _4; + + +/*! \p thrust::placeholders::_5 is the placeholder for the fifth function parameter. + */ static const thrust::detail::functional::placeholder<4>::type _5; + + +/*! \p thrust::placeholders::_6 is the placeholder for the sixth function parameter. + */ static const thrust::detail::functional::placeholder<5>::type _6; + + +/*! \p thrust::placeholders::_7 is the placeholder for the seventh function parameter. + */ static const thrust::detail::functional::placeholder<6>::type _7; + + +/*! \p thrust::placeholders::_8 is the placeholder for the eighth function parameter. + */ static const thrust::detail::functional::placeholder<7>::type _8; + + +/*! \p thrust::placeholders::_9 is the placeholder for the ninth function parameter. + */ static const thrust::detail::functional::placeholder<8>::type _9; + + +/*! \p thrust::placeholders::_10 is the placeholder for the tenth function parameter. + */ static const thrust::detail::functional::placeholder<9>::type _10; + } // end placeholders + +/*! \} // placeholder_objects + */ + + } // end thrust #include diff --git a/thrust/iterator/iterator_adaptor.h b/thrust/iterator/iterator_adaptor.h index 9a41edaf5..7b9cca308 100644 --- a/thrust/iterator/iterator_adaptor.h +++ b/thrust/iterator/iterator_adaptor.h @@ -55,57 +55,46 @@ namespace thrust * functionality, it is occasionally more straightforward to derive from \p iterator_adaptor directly. * * To see how to use \p iterator_adaptor to create a novel iterator type, let's examine how to use it to - * define our own version of \p transform_iterator, a fancy iterator which fuses the application of - * a unary function with an iterator dereference: + * define \p repeat_iterator, a fancy iterator which repeats elements from another range a given number of time: * * \code * #include * - * // derive my_transform_iterator from iterator_adaptor - * template - * class my_transform_iterator + * // derive repeat_iterator from iterator_adaptor + * template + * class repeat_iterator * : public thrust::iterator_adaptor< - * my_transform_iterator, // the first template parameter is the name of the type we're creating - * Iterator, // the second template parameter is the name of the iterator we're adapting - * typename Function::result_type, // the third template parameter is the name of the iterator's value_type -- it's simply the function's result_type. - * thrust::use_default, // the fourth template parameter is the name of the iterator's system. use_default will use the same system as the base iterator. - * thrust::use_default, // the fifth template parameter is the name of the iterator's traversal. use_default will use the same traversal as the base iterator. - * typename Function::result_type // the sixth template parameter is the name of the iterator's reference. Like value_type, it's simply the function's result_type. + * repeat_iterator, // the first template parameter is the name of the iterator we're creating + * Iterator // the second template parameter is the name of the iterator we're adapting + * // we can use the default for the additional template parameters * > * { * public: * // shorthand for the name of the iterator_adaptor we're deriving from * typedef thrust::iterator_adaptor< - * my_transform_iterator, - * Iterator, - * typename Function::result_type, - * thrust::use_default, - * thrust::use_default, - * typename Function::result_type + * repeat_iterator, + * Iterator * > super_t; * * __host__ __device__ - * my_transform_iterator(const Iterator &x, Function f) : super_t(x), m_f(f) {} - * - * // other assorted constructors might go here - * ... + * repeat_iterator(const Iterator &x, int n) : super_t(x), begin(x), n(n) {} * * // befriend thrust::iterator_core_access to allow it access to the private interface below * friend class thrust::iterator_core_access; * * private: - * // here we define what it means to dereference my_transform_iterator + * // repeat each element of the adapted range n times + * unsigned int n; + * + * // used to keep track of where we began + * const Iterator begin; + * * // it is private because only thrust::iterator_core_access needs access to it * __host__ __device__ * typename super_t::reference dereference() const * { - * // when my_transform_iterator is dereferenced, it dereferences the base iterator - * // and applies the unary function - * return m_f(*this->base()); + * return *(begin + (this->base() - begin) / n); * } - * - * // the unary function - * Function m_f; * }; * \endcode * @@ -116,6 +105,10 @@ namespace thrust * The exception is Thrust's addition of the template parameter \p System, which is necessary to allow Thrust * to dispatch an algorithm to one of several parallel backend systems. * + * \p iterator_adaptor is a powerful tool for creating custom iterators directly. However, the large set of iterator semantics which must be satisfied + * for algorithm compatibility can make \p iterator_adaptor difficult to use correctly. Unless you require the full expressivity of \p iterator_adaptor, + * consider building a custom iterator through composition of existing higher-level fancy iterators instead. + * * Interested users may refer to boost::iterator_adaptor's documentation for further usage examples. */ template