2 * Copyright 2008-2013 NVIDIA Corporation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 /*! \file thrust/iterator/transform_iterator.h
19 * \brief An iterator which adapts another iterator by applying a function to the result of its dereference
23 * (C) Copyright David Abrahams 2002.
24 * (C) Copyright Jeremy Siek 2002.
25 * (C) Copyright Thomas Witt 2002.
27 * Distributed under the Boost Software License, Version 1.0.
28 * (See accompanying NOTICE file for the complete license)
30 * For more information, see http://www.boost.org
35 #include <thrust/detail/config.h>
37 // #include the details first
38 #include <thrust/iterator/detail/transform_iterator.inl>
39 #include <thrust/iterator/iterator_facade.h>
40 #include <thrust/detail/type_traits.h>
41 #include <thrust/detail/function.h>
46 /*! \addtogroup iterators
50 /*! \addtogroup fancyiterator Fancy Iterators
55 /*! \p transform_iterator is an iterator which represents a pointer into a range
56 * of values after transformation by a function. This iterator is useful for
57 * creating a range filled with the result of applying an operation to another range
58 * without either explicitly storing it in memory, or explicitly executing the transformation.
59 * Using \p transform_iterator facilitates kernel fusion by deferring the execution
60 * of a transformation until the value is needed while saving both memory capacity
63 * The following code snippet demonstrates how to create a \p transform_iterator
64 * which represents the result of \c sqrtf applied to the contents of a \p device_vector.
67 * #include <thrust/iterator/transform_iterator.h>
68 * #include <thrust/device_vector.h>
70 * // note: functor inherits from unary_function
71 * struct square_root : public thrust::unary_function<float,float>
74 * float operator()(float x) const
82 * thrust::device_vector<float> v(4);
88 * typedef thrust::device_vector<float>::iterator FloatIterator;
90 * thrust::transform_iterator<square_root, FloatIterator> iter(v.begin(), square_root());
92 * *iter; // returns 1.0f
93 * iter[0]; // returns 1.0f;
94 * iter[1]; // returns 2.0f;
95 * iter[2]; // returns 3.0f;
96 * iter[3]; // returns 4.0f;
98 * // iter[4] is an out-of-bounds error
102 * This next example demonstrates how to use a \p transform_iterator with the
103 * \p thrust::reduce function to compute the sum of squares of a sequence.
104 * We will create temporary \p transform_iterators with the
105 * \p make_transform_iterator function in order to avoid explicitly specifying their type:
108 * #include <thrust/iterator/transform_iterator.h>
109 * #include <thrust/device_vector.h>
110 * #include <thrust/reduce.h>
111 * #include <iostream>
113 * // note: functor inherits from unary_function
114 * struct square : public thrust::unary_function<float,float>
116 * __host__ __device__
117 * float operator()(float x) const
125 * // initialize a device array
126 * thrust::device_vector<float> v(4);
132 * float sum_of_squares =
133 * thrust::reduce(thrust::make_transform_iterator(v.begin(), square()),
134 * thrust::make_transform_iterator(v.end(), square()));
136 * std::cout << "sum of squares: " << sum_of_squares << std::endl;
141 * Note that in the previous two examples the transform functor (namely \c square_root
142 * and \c square) inherits from \c thrust::unary_function. Inheriting from
143 * \c thrust::unary_function ensures that a functor is a valid \c AdaptableUnaryFunction
144 * and provides all the necessary \c typedef declarations. The \p transform_iterator
145 * can also be applied to a \c UnaryFunction that does not inherit from
146 * \c thrust::unary_function using an optional template argument. The following example
147 * illustrates how to use the third template argument to specify the \c result_type of
151 * #include <thrust/iterator/transform_iterator.h>
152 * #include <thrust/device_vector.h>
154 * // note: functor *does not* inherit from unary_function
157 * __host__ __device__
158 * float operator()(float x) const
166 * thrust::device_vector<float> v(4);
172 * typedef thrust::device_vector<float>::iterator FloatIterator;
174 * // note: float result_type is specified explicitly
175 * thrust::transform_iterator<square_root, FloatIterator, float> iter(v.begin(), square_root());
177 * *iter; // returns 1.0f
178 * iter[0]; // returns 1.0f;
179 * iter[1]; // returns 2.0f;
180 * iter[2]; // returns 3.0f;
181 * iter[3]; // returns 4.0f;
183 * // iter[4] is an out-of-bounds error
187 * \see make_transform_iterator
189 template <class AdaptableUnaryFunction, class Iterator, class Reference = use_default, class Value = use_default>
190 class transform_iterator
191 : public detail::transform_iterator_base<AdaptableUnaryFunction, Iterator, Reference, Value>::type
197 detail::transform_iterator_base<AdaptableUnaryFunction, Iterator, Reference, Value>::type
200 friend class thrust::iterator_core_access;
205 /*! Null constructor does nothing.
208 transform_iterator() {}
210 /*! This constructor takes as arguments an \c Iterator and an \c AdaptableUnaryFunction
211 * and copies them to a new \p transform_iterator.
213 * \param x An \c Iterator pointing to the input to this \p transform_iterator's \c AdaptableUnaryFunction.
214 * \param f An \c AdaptableUnaryFunction used to transform the objects pointed to by \p x.
217 transform_iterator(Iterator const& x, AdaptableUnaryFunction f)
218 : super_t(x), m_f(f) {
221 /*! This explicit constructor copies the value of a given \c Iterator and creates
222 * this \p transform_iterator's \c AdaptableUnaryFunction using its null constructor.
224 * \param x An \c Iterator to copy.
227 explicit transform_iterator(Iterator const& x)
230 /*! This copy constructor creates a new \p transform_iterator from another
231 * \p transform_iterator.
233 * \param other The \p transform_iterator to copy.
235 template<typename OtherAdaptableUnaryFunction,
236 typename OtherIterator,
237 typename OtherReference,
240 transform_iterator(const transform_iterator<OtherAdaptableUnaryFunction, OtherIterator, OtherReference, OtherValue> &other,
241 typename thrust::detail::enable_if_convertible<OtherIterator, Iterator>::type* = 0,
242 typename thrust::detail::enable_if_convertible<OtherAdaptableUnaryFunction, AdaptableUnaryFunction>::type* = 0)
243 : super_t(other.base()), m_f(other.functor()) {}
245 /*! Copy assignment operator copies from another \p transform_iterator.
246 * \p other The other \p transform_iterator to copy
247 * \return <tt>*this</tt>
249 * \note If the type of this \p transform_iterator's functor is not copy assignable
250 * (for example, if it is a lambda) it is not an error to call this function.
251 * In this case, however, the functor will not be modified.
253 * In any case, this \p transform_iterator's underlying iterator will be copy assigned.
256 transform_iterator &operator=(const transform_iterator &other)
258 return do_assign(other,
259 // XXX gcc 4.2.1 crashes on is_copy_assignable; just assume the functor is assignable as a WAR
260 #if (THRUST_HOST_COMPILER == THRUST_HOST_COMPILER_GCC) && (THRUST_GCC_VERSION <= 40201)
261 thrust::detail::true_type()
263 typename thrust::detail::is_copy_assignable<AdaptableUnaryFunction>::type()
264 #endif // THRUST_HOST_COMPILER
268 /*! This method returns a copy of this \p transform_iterator's \c AdaptableUnaryFunction.
269 * \return A copy of this \p transform_iterator's \c AdaptableUnaryFunction.
272 AdaptableUnaryFunction functor() const
279 transform_iterator &do_assign(const transform_iterator &other, thrust::detail::true_type)
281 super_t::operator=(other);
284 m_f = other.functor();
290 transform_iterator &do_assign(const transform_iterator &other, thrust::detail::false_type)
292 super_t::operator=(other);
294 // don't assign to m_f
299 __thrust_hd_warning_disable__
301 typename super_t::reference dereference() const
303 // XXX consider making this a member instead of a temporary created inside dereference
304 thrust::detail::host_device_function<AdaptableUnaryFunction, typename super_t::reference> wrapped_f(m_f);
306 return wrapped_f(*this->base());
309 // tag this as mutable per Dave Abrahams in this thread:
310 // http://lists.boost.org/Archives/boost/2004/05/65332.php
311 mutable AdaptableUnaryFunction m_f;
315 }; // end transform_iterator
318 /*! \p make_transform_iterator creates a \p transform_iterator
319 * from an \c Iterator and \c AdaptableUnaryFunction.
321 * \param it The \c Iterator pointing to the input range of the
322 * newly created \p transform_iterator.
323 * \param fun The \c AdaptableUnaryFunction used to transform the range pointed
324 * to by \p it in the newly created \p transform_iterator.
325 * \return A new \p transform_iterator which transforms the range at
327 * \see transform_iterator
329 template <class AdaptableUnaryFunction, class Iterator>
330 inline __host__ __device__
331 transform_iterator<AdaptableUnaryFunction, Iterator>
332 make_transform_iterator(Iterator it, AdaptableUnaryFunction fun)
334 return transform_iterator<AdaptableUnaryFunction, Iterator>(it, fun);
335 } // end make_transform_iterator
337 /*! \} // end fancyiterators
340 /*! \} // end iterators