1 /*
2  *  Copyright 2008-2018 NVIDIA Corporation
3  *
4  *  Licensed under the Apache License, Vesion 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 /*! \file thrust/iterator/transform_output_iterator.h
18  *  \brief An output iterator which adapts another output iterator by applying a
19  *         function to the result of its dereference before writing it.
20  */
21 
22 #pragma once
23 
24 #include <thrust/detail/config.h>
25 #include <thrust/iterator/detail/transform_output_iterator.inl>
26 
27 namespace thrust
28 {
29 
30 /*! \addtogroup iterators
31  *  \{
32  */
33 
34 /*! \addtogroup fancyiterator Fancy Iterators
35  *  \ingroup iterators
36  *  \{
37  */
38 
39 /*! \p transform_output_iterator is a special kind of output iterator which
40  * transforms a value written upon dereference. This iterator is useful
41  * for transforming an output from algorithms without explicitly storing the
42  * intermediate result in the memory and applying subsequent transformation,
43  * thereby avoiding wasting memory capacity and bandwidth.
44  * Using \p transform_iterator facilitates kernel fusion by deferring execution
45  * of transformation until the value is written while saving both memory
46  * capacity and bandwidth.
47  *
48  * The following code snippet demonstrated how to create a
49  * \p transform_output_iterator which applies \c sqrtf to the assigning value.
50  *
51  * \code
52  * #include <thrust/iterator/transform_output_iterator.h>
53  * #include <thrust/device_vector.h>
54  *
55  * // note: functor inherits form unary function
56  *  // note: functor inherits from unary_function
57  *  struct square_root : public thrust::unary_function<float,float>
58  *  {
59  *    __host__ __device__
60  *    float operator()(float x) const
61  *    {
62  *      return sqrtf(x);
63  *    }
64  *  };
65  *
66  *  int main()
67  *  {
68  *    thrust::device_vector<float> v(4);
69  *
70  *    typedef thrust::device_vector<float>::iterator FloatIterator;
71  *    thrust::transform_output_iterator<square_root, FloatIterator> iter(v.begin(), square_root());
72  *
73  *    iter[0] =  1.0f;    // stores sqrtf( 1.0f)
74  *    iter[1] =  4.0f;    // stores sqrtf( 4.0f)
75  *    iter[2] =  9.0f;    // stores sqrtf( 9.0f)
76  *    iter[3] = 16.0f;    // stores sqrtf(16.0f)
77  *    // iter[4] is an out-of-bounds error
78  *
79  *    v[0]; // returns 1.0f;
80  *    v[1]; // returns 2.0f;
81  *    v[2]; // returns 3.0f;
82  *    v[3]; // returns 4.0f;
83  *
84  *  }
85  *  \endcode
86  *
87  *  \see make_transform_output_iterator
88  */
89 
90 template <typename UnaryFunction, typename OutputIterator>
91   class transform_output_iterator
92     : public detail::transform_output_iterator_base<UnaryFunction, OutputIterator>::type
93 {
94 
95   /*! \cond
96    */
97 
98   public:
99 
100     typedef typename
101     detail::transform_output_iterator_base<UnaryFunction, OutputIterator>::type
102     super_t;
103 
104     friend class thrust::iterator_core_access;
105   /*! \endcond
106    */
107 
108   /*! This constructor takes as argument an \c OutputIterator and an \c
109    * UnaryFunction and copies them to a new \p transform_output_iterator
110    *
111    * \param out An \c OutputIterator pointing to the output range whereto the result of
112    *            \p transform_output_iterator's \c UnaryFunction will be written.
113    * \param fun An \c UnaryFunction used to transform the objects assigned to
114    *            this \p transform_output_iterator.
115    */
116     __host__ __device__
transform_output_iterator(OutputIterator const & out,UnaryFunction fun)117     transform_output_iterator(OutputIterator const& out, UnaryFunction fun) : super_t(out), fun(fun)
118     {
119     }
120 
121     /*! \cond
122      */
123   private:
124 
125     __host__ __device__
dereference()126     typename super_t::reference dereference() const
127     {
128       return detail::transform_output_iterator_proxy<
129         UnaryFunction, OutputIterator
130       >(this->base_reference(), fun);
131     }
132 
133     UnaryFunction fun;
134 
135     /*! \endcond
136      */
137 }; // end transform_output_iterator
138 
139 /* \p make_transform_output_iterator creates a \p transform_output_iterator from
140  * an \c OutputIterator and \c UnaryFunction.
141  *
142  * \param out The \c OutputIterator pointing to the output range of the newly
143  *            created \p transform_output_iterator
144  * \param fun The \c UnaryFunction transform the object before assigning it to
145  *            \c out by the newly created \p transform_output_iterator
146  * \see transform_output_iterator
147  */
148 
149 template <typename UnaryFunction, typename OutputIterator>
150 transform_output_iterator<UnaryFunction, OutputIterator>
151 __host__ __device__
make_transform_output_iterator(OutputIterator out,UnaryFunction fun)152 make_transform_output_iterator(OutputIterator out, UnaryFunction fun)
153 {
154     return transform_output_iterator<UnaryFunction, OutputIterator>(out, fun);
155 } // end make_transform_output_iterator
156 
157 /*! \} // end fancyiterators
158  */
159 
160 /*! \} // end iterators
161  */
162 
163 } // end thrust
164 
165