OSDN Git Service

CUDA
[eos/hostdependX86LINUX64.git] / util / X86LINUX64 / cuda-6.5 / include / thrust / iterator / transform_iterator.h
1 /*
2  *  Copyright 2008-2013 NVIDIA Corporation
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17
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 
20  */
21
22 /*
23  * (C) Copyright David Abrahams 2002.
24  * (C) Copyright Jeremy Siek    2002.
25  * (C) Copyright Thomas Witt    2002.
26  * 
27  * Distributed under the Boost Software License, Version 1.0.
28  * (See accompanying NOTICE file for the complete license)
29  *
30  * For more information, see http://www.boost.org
31  */
32
33 #pragma once
34
35 #include <thrust/detail/config.h>
36
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>
42
43 namespace thrust
44 {
45
46 /*! \addtogroup iterators
47  *  \{
48  */
49
50 /*! \addtogroup fancyiterator Fancy Iterators
51  *  \ingroup iterators
52  *  \{
53  */
54
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
61  *  and bandwidth.
62  *
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.
65  *
66  *  \code
67  *  #include <thrust/iterator/transform_iterator.h>
68  *  #include <thrust/device_vector.h>
69  *  
70  *  // note: functor inherits from unary_function
71  *  struct square_root : public thrust::unary_function<float,float>
72  *  {
73  *    __host__ __device__
74  *    float operator()(float x) const
75  *    {
76  *      return sqrtf(x);
77  *    }
78  *  };
79  *  
80  *  int main(void)
81  *  {
82  *    thrust::device_vector<float> v(4);
83  *    v[0] = 1.0f;
84  *    v[1] = 4.0f;
85  *    v[2] = 9.0f;
86  *    v[3] = 16.0f;
87  *                                                                                           
88  *    typedef thrust::device_vector<float>::iterator FloatIterator;
89  *                                                                                           
90  *    thrust::transform_iterator<square_root, FloatIterator> iter(v.begin(), square_root());
91  *                                                                                           
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;
97  *                                                                                           
98  *    // iter[4] is an out-of-bounds error
99  *  }
100  *  \endcode
101  *
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:
106  *
107  *  \code
108  *  #include <thrust/iterator/transform_iterator.h>
109  *  #include <thrust/device_vector.h>
110  *  #include <thrust/reduce.h>
111  *  #include <iostream>
112  *  
113  *  // note: functor inherits from unary_function
114  *  struct square : public thrust::unary_function<float,float>
115  *  {
116  *    __host__ __device__
117  *    float operator()(float x) const
118  *    {
119  *      return x * x;
120  *    }
121  *  };
122  *  
123  *  int main(void)
124  *  {
125  *    // initialize a device array
126  *    thrust::device_vector<float> v(4);
127  *    v[0] = 1.0f;
128  *    v[1] = 2.0f;
129  *    v[2] = 3.0f;
130  *    v[3] = 4.0f;
131  *  
132  *    float sum_of_squares =
133  *     thrust::reduce(thrust::make_transform_iterator(v.begin(), square()),
134  *                    thrust::make_transform_iterator(v.end(),   square()));
135  *  
136  *    std::cout << "sum of squares: " << sum_of_squares << std::endl;
137  *    return 0;
138  *  }
139  *  \endcode
140  *
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
148  *  the function.   
149  *
150  *  \code
151  *  #include <thrust/iterator/transform_iterator.h>
152  *  #include <thrust/device_vector.h>
153  *  
154  *  // note: functor *does not* inherit from unary_function
155  *  struct square_root
156  *  {
157  *    __host__ __device__
158  *    float operator()(float x) const
159  *    {
160  *      return sqrtf(x);
161  *    }
162  *  };
163  *  
164  *  int main(void)
165  *  {
166  *    thrust::device_vector<float> v(4);
167  *    v[0] = 1.0f;
168  *    v[1] = 4.0f;
169  *    v[2] = 9.0f;
170  *    v[3] = 16.0f;
171  *                                                                                           
172  *    typedef thrust::device_vector<float>::iterator FloatIterator;
173  *    
174  *    // note: float result_type is specified explicitly
175  *    thrust::transform_iterator<square_root, FloatIterator, float> iter(v.begin(), square_root());
176  *                                                                                           
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;
182  *                                                                                           
183  *    // iter[4] is an out-of-bounds error
184  *  }
185  *  \endcode
186  *
187  *  \see make_transform_iterator
188  */
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
192 {
193   /*! \cond
194    */
195   public:
196     typedef typename
197     detail::transform_iterator_base<AdaptableUnaryFunction, Iterator, Reference, Value>::type
198     super_t;
199
200     friend class thrust::iterator_core_access;
201   /*! \endcond
202    */
203
204   public:
205     /*! Null constructor does nothing.
206      */
207     __host__ __device__
208     transform_iterator() {}
209   
210     /*! This constructor takes as arguments an \c Iterator and an \c AdaptableUnaryFunction
211      *  and copies them to a new \p transform_iterator.
212      *
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.
215      */
216     __host__ __device__
217     transform_iterator(Iterator const& x, AdaptableUnaryFunction f)
218       : super_t(x), m_f(f) {
219     }
220   
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.
223      *
224      *  \param x An \c Iterator to copy.
225      */
226     __host__ __device__
227     explicit transform_iterator(Iterator const& x)
228       : super_t(x) { }
229
230     /*! This copy constructor creates a new \p transform_iterator from another
231      *  \p transform_iterator.
232      *
233      *  \param other The \p transform_iterator to copy.
234      */
235     template<typename OtherAdaptableUnaryFunction,
236              typename OtherIterator,
237              typename OtherReference,
238              typename OtherValue>
239     __host__ __device__
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()) {}
244
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>
248      *
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.
252      *
253      *        In any case, this \p transform_iterator's underlying iterator will be copy assigned.
254      */
255     __host__ __device__
256     transform_iterator &operator=(const transform_iterator &other)
257     {
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()
262 #else
263           typename thrust::detail::is_copy_assignable<AdaptableUnaryFunction>::type()
264 #endif // THRUST_HOST_COMPILER
265       );
266     }
267
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.
270      */
271     __host__ __device__
272     AdaptableUnaryFunction functor() const
273       { return m_f; }
274
275     /*! \cond
276      */
277   private:
278     __host__ __device__
279     transform_iterator &do_assign(const transform_iterator &other, thrust::detail::true_type)
280     {
281       super_t::operator=(other);
282
283       // do assign to m_f
284       m_f = other.functor();
285
286       return *this;
287     }
288
289     __host__ __device__
290     transform_iterator &do_assign(const transform_iterator &other, thrust::detail::false_type)
291     {
292       super_t::operator=(other);
293
294       // don't assign to m_f
295
296       return *this;
297     }
298
299     __thrust_hd_warning_disable__
300     __host__ __device__
301     typename super_t::reference dereference() const
302     { 
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);
305
306       return wrapped_f(*this->base());
307     }
308
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;
312
313     /*! \endcond
314      */
315 }; // end transform_iterator
316
317
318 /*! \p make_transform_iterator creates a \p transform_iterator
319  *  from an \c Iterator and \c AdaptableUnaryFunction.
320  *
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
326  *          \p it by \p fun.
327  *  \see transform_iterator
328  */
329 template <class AdaptableUnaryFunction, class Iterator>
330 inline __host__ __device__
331 transform_iterator<AdaptableUnaryFunction, Iterator>
332 make_transform_iterator(Iterator it, AdaptableUnaryFunction fun)
333 {
334   return transform_iterator<AdaptableUnaryFunction, Iterator>(it, fun);
335 } // end make_transform_iterator
336
337 /*! \} // end fancyiterators
338  */
339
340 /*! \} // end iterators
341  */
342
343 } // end thrust
344