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