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