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/counting_iterator.h
19 * \brief An iterator which returns an increasing incrementable value
20 * when dereferenced
21 */
22
23 /*
24 * Copyright David Abrahams 2003.
25 *
26 * Distributed under the Boost Software License, Version 1.0.
27 * (See accompanying NOTICE file for the complete license)
28 *
29 * For more information, see http://www.boost.org
30 */
31
32 #pragma once
33
34 #include <thrust/detail/config.h>
35 #include <thrust/iterator/iterator_adaptor.h>
36 #include <thrust/iterator/iterator_facade.h>
37 #include <thrust/iterator/iterator_categories.h>
38
39 // #include the details first
40 #include <thrust/iterator/detail/counting_iterator.inl>
41
42 namespace thrust
43 {
44
45 /*! \addtogroup iterators
46 * \{
47 */
48
49 /*! \addtogroup fancyiterator Fancy Iterators
50 * \ingroup iterators
51 * \{
52 */
53
54 /*! \p counting_iterator is an iterator which represents a pointer into a range
55 * of sequentially changing values. This iterator is useful for creating a range
56 * filled with a sequence without explicitly storing it in memory. Using
57 * \p counting_iterator saves memory capacity and bandwidth.
58 *
59 * The following code snippet demonstrates how to create a \p counting_iterator whose
60 * \c value_type is \c int and which sequentially increments by \c 1.
61 *
62 * \code
63 * #include <thrust/iterator/counting_iterator.h>
64 * ...
65 * // create iterators
66 * thrust::counting_iterator<int> first(10);
67 * thrust::counting_iterator<int> last = first + 3;
68 *
69 * first[0] // returns 10
70 * first[1] // returns 11
71 * first[100] // returns 110
72 *
73 * // sum of [first, last)
74 * thrust::reduce(first, last); // returns 33 (i.e. 10 + 11 + 12)
75 *
76 * // initialize vector to [0,1,2,..]
77 * thrust::counting_iterator<int> iter(0);
78 * thrust::device_vector<int> vec(500);
79 * thrust::copy(iter, iter + vec.size(), vec.begin());
80 * \endcode
81 *
82 * This next example demonstrates how to use a \p counting_iterator with the
83 * \p thrust::copy_if function to compute the indices of the non-zero elements
84 * of a \p device_vector. In this example, we use the \p make_counting_iterator
85 * function to avoid specifying the type of the \p counting_iterator.
86 *
87 * \code
88 * #include <thrust/iterator/counting_iterator.h>
89 * #include <thrust/copy.h>
90 * #include <thrust/functional.h>
91 * #include <thrust/device_vector.h>
92 *
93 * int main()
94 * {
95 * // this example computes indices for all the nonzero values in a sequence
96 *
97 * // sequence of zero and nonzero values
98 * thrust::device_vector<int> stencil(8);
99 * stencil[0] = 0;
100 * stencil[1] = 1;
101 * stencil[2] = 1;
102 * stencil[3] = 0;
103 * stencil[4] = 0;
104 * stencil[5] = 1;
105 * stencil[6] = 0;
106 * stencil[7] = 1;
107 *
108 * // storage for the nonzero indices
109 * thrust::device_vector<int> indices(8);
110 *
111 * // compute indices of nonzero elements
112 * typedef thrust::device_vector<int>::iterator IndexIterator;
113 *
114 * // use make_counting_iterator to define the sequence [0, 8)
115 * IndexIterator indices_end = thrust::copy_if(thrust::make_counting_iterator(0),
116 * thrust::make_counting_iterator(8),
117 * stencil.begin(),
118 * indices.begin(),
119 * thrust::identity<int>());
120 * // indices now contains [1,2,5,7]
121 *
122 * return 0;
123 * }
124 * \endcode
125 *
126 * \see make_counting_iterator
127 */
128 template<typename Incrementable,
129 typename System = use_default,
130 typename Traversal = use_default,
131 typename Difference = use_default>
132 class counting_iterator
133 : public detail::counting_iterator_base<Incrementable, System, Traversal, Difference>::type
134 {
135 /*! \cond
136 */
137 typedef typename detail::counting_iterator_base<Incrementable, System, Traversal, Difference>::type super_t;
138
139 friend class thrust::iterator_core_access;
140
141 public:
142 typedef typename super_t::reference reference;
143 typedef typename super_t::difference_type difference_type;
144
145 /*! \endcond
146 */
147
148 /*! Null constructor initializes this \p counting_iterator's \c Incrementable
149 * counter using its null constructor.
150 */
151 __host__ __device__
counting_iterator()152 counting_iterator() {}
153
154 /*! Copy constructor copies the value of another \p counting_iterator into a
155 * new \p counting_iterator.
156 *
157 * \p rhs The \p counting_iterator to copy.
158 */
159 __host__ __device__
counting_iterator(counting_iterator const & rhs)160 counting_iterator(counting_iterator const &rhs):super_t(rhs.base()){}
161
162 /*! Copy constructor copies the value of another counting_iterator
163 * with related System type.
164 *
165 * \param rhs The \p counting_iterator to copy.
166 */
167 template<typename OtherSystem>
168 __host__ __device__
169 counting_iterator(counting_iterator<Incrementable, OtherSystem, Traversal, Difference> const &rhs,
170 typename thrust::detail::enable_if_convertible<
171 typename thrust::iterator_system<counting_iterator<Incrementable,OtherSystem,Traversal,Difference> >::type,
172 typename thrust::iterator_system<super_t>::type
173 >::type * = 0)
174 : super_t(rhs.base()){}
175
176 /*! This \c explicit constructor copies the value of an \c Incrementable
177 * into a new \p counting_iterator's \c Incrementable counter.
178 *
179 * \param x The initial value of the new \p counting_iterator's \c Incrementable
180 * counter.
181 */
182 __host__ __device__
counting_iterator(Incrementable x)183 explicit counting_iterator(Incrementable x):super_t(x){}
184
185 /*! \cond
186 */
187 private:
188 __host__ __device__
dereference()189 reference dereference() const
190 {
191 return this->base_reference();
192 }
193
194 // note that we implement equal specially for floating point counting_iterator
195 template <typename OtherIncrementable, typename OtherSystem, typename OtherTraversal, typename OtherDifference>
196 __host__ __device__
equal(counting_iterator<OtherIncrementable,OtherSystem,OtherTraversal,OtherDifference> const & y)197 bool equal(counting_iterator<OtherIncrementable, OtherSystem, OtherTraversal, OtherDifference> const& y) const
198 {
199 typedef thrust::detail::counting_iterator_equal<difference_type,Incrementable,OtherIncrementable> e;
200 return e::equal(this->base(), y.base());
201 }
202
203 template <class OtherIncrementable>
204 __host__ __device__
205 difference_type
distance_to(counting_iterator<OtherIncrementable,System,Traversal,Difference> const & y)206 distance_to(counting_iterator<OtherIncrementable, System, Traversal, Difference> const& y) const
207 {
208 typedef typename
209 thrust::detail::eval_if<
210 thrust::detail::is_numeric<Incrementable>::value,
211 thrust::detail::identity_<thrust::detail::number_distance<difference_type, Incrementable, OtherIncrementable> >,
212 thrust::detail::identity_<thrust::detail::iterator_distance<difference_type, Incrementable, OtherIncrementable> >
213 >::type d;
214
215 return d::distance(this->base(), y.base());
216 }
217
218 /*! \endcond
219 */
220 }; // end counting_iterator
221
222
223 /*! \p make_counting_iterator creates a \p counting_iterator
224 * using an initial value for its \c Incrementable counter.
225 *
226 * \param x The initial value of the new \p counting_iterator's counter.
227 * \return A new \p counting_iterator whose counter has been initialized to \p x.
228 */
229 template <typename Incrementable>
230 inline __host__ __device__
make_counting_iterator(Incrementable x)231 counting_iterator<Incrementable> make_counting_iterator(Incrementable x)
232 {
233 return counting_iterator<Incrementable>(x);
234 }
235
236 /*! \} // end fancyiterators
237 */
238
239 /*! \} // end iterators
240 */
241
242 } // end thrust
243
244