Thrust
iterator_facade.h
Go to the documentation of this file.
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 
21 /*
22  * (C) Copyright David Abrahams 2002.
23  * (C) Copyright Jeremy Siek 2002.
24  * (C) Copyright Thomas Witt 2002.
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 
33 #pragma once
34 
35 #include <thrust/detail/config.h>
36 #include <thrust/detail/type_traits.h>
37 #include <thrust/iterator/detail/iterator_facade_category.h>
38 #include <thrust/iterator/detail/distance_from_result.h>
39 
40 THRUST_NAMESPACE_BEGIN
41 
52 // This forward declaration is required for the friend declaration
53 // in iterator_core_access
54 template<typename Derived, typename Value, typename System, typename Traversal, typename Reference, typename Difference> class iterator_facade;
55 
56 
61 {
65  // declare our friends
66  template<typename Derived, typename Value, typename System, typename Traversal, typename Reference, typename Difference> friend class iterator_facade;
67 
68  // iterator comparisons are our friends
69  template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
70  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
71  inline __host__ __device__
72  friend bool
75 
76  template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
77  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
78  inline __host__ __device__
79  friend bool
82 
83  template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
84  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
85  inline __host__ __device__
86  friend bool
87  operator <(iterator_facade<Derived1,Value1,System1,Traversal1,Reference1,Difference1> const& lhs,
89 
90  template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
91  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
92  inline __host__ __device__
93  friend bool
96 
97  template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
98  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
99  inline __host__ __device__
100  friend bool
101  operator <=(iterator_facade<Derived1,Value1,System1,Traversal1,Reference1,Difference1> const& lhs,
103 
104  template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
105  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
106  inline __host__ __device__
107  friend bool
110 
111  // iterator difference is our friend
112  template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
113  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
114  inline __host__ __device__
115  friend
116  typename thrust::detail::distance_from_result<
119  >::type
120  operator-(iterator_facade<Derived1,Value1,System1,Traversal1,Reference1,Difference1> const& lhs,
122 
123  template<typename Facade>
124  __host__ __device__
125  static typename Facade::reference dereference(Facade const& f)
126  {
127  return f.dereference();
128  }
129 
130  template<typename Facade>
131  __host__ __device__
132  static void increment(Facade& f)
133  {
134  f.increment();
135  }
136 
137  template<typename Facade>
138  __host__ __device__
139  static void decrement(Facade& f)
140  {
141  f.decrement();
142  }
143 
144  template <class Facade1, class Facade2>
145  __host__ __device__
146  static bool equal(Facade1 const& f1, Facade2 const& f2)
147  {
148  return f1.equal(f2);
149  }
150 
151  // XXX TODO: Investigate whether we need both of these cases
152  //template <class Facade1, class Facade2>
153  //__host__ __device__
154  //static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::true_)
155  //{
156  // return f1.equal(f2);
157  //}
158 
159  //template <class Facade1, class Facade2>
160  //__host__ __device__
161  //static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::false_)
162  //{
163  // return f2.equal(f1);
164  //}
165 
166  template <class Facade>
167  __host__ __device__
168  static void advance(Facade& f, typename Facade::difference_type n)
169  {
170  f.advance(n);
171  }
172 
173  // Facade2 is convertible to Facade1,
174  // so return Facade1's difference_type
175  template <class Facade1, class Facade2>
176  __host__ __device__
177  static typename Facade1::difference_type
178  distance_from(Facade1 const& f1, Facade2 const& f2, thrust::detail::true_type)
179  {
180  return -f1.distance_to(f2);
181  }
182 
183  // Facade2 is not convertible to Facade1,
184  // so return Facade2's difference_type
185  template <class Facade1, class Facade2>
186  __host__ __device__
187  static typename Facade2::difference_type
188  distance_from(Facade1 const& f1, Facade2 const& f2, thrust::detail::false_type)
189  {
190  return f2.distance_to(f1);
191  }
192 
193  template <class Facade1, class Facade2>
194  __host__ __device__
195  static typename thrust::detail::distance_from_result<Facade1,Facade2>::type
196  distance_from(Facade1 const& f1, Facade2 const& f2)
197  {
198  // dispatch the implementation of this method upon whether or not
199  // Facade2 is convertible to Facade1
200  return distance_from(f1, f2,
201  typename thrust::detail::is_convertible<Facade2,Facade1>::type());
202  }
203 
204  //
205  // Curiously Recurring Template interface.
206  //
207  template <typename Derived, typename Value, typename System, typename Traversal, typename Reference, typename Difference>
208  __host__ __device__
210  {
211  return *static_cast<Derived*>(&facade);
212  }
213 
214  template <typename Derived, typename Value, typename System, typename Traversal, typename Reference, typename Difference>
215  __host__ __device__
216  static Derived const& derived(iterator_facade<Derived,Value,System,Traversal,Reference,Difference> const& facade)
217  {
218  return *static_cast<Derived const*>(&facade);
219  }
220 
223 }; // end iterator_core_access
224 
225 
245 template<typename Derived,
246  typename Value,
247  typename System,
248  typename Traversal,
249  typename Reference,
250  typename Difference = std::ptrdiff_t>
251  class iterator_facade
252 {
253  private:
257  //
258  // Curiously Recurring Template interface.
259  //
260  __host__ __device__
261  Derived& derived()
262  {
263  return *static_cast<Derived*>(this);
264  }
265 
266  __host__ __device__
267  Derived const& derived() const
268  {
269  return *static_cast<Derived const*>(this);
270  }
274  public:
277  typedef typename thrust::detail::remove_const<Value>::type value_type;
278 
281  typedef Reference reference;
282 
290  typedef void pointer;
291 
295  typedef Difference difference_type;
296 
299  typedef typename thrust::detail::iterator_facade_category<
300  System, Traversal, Value, Reference
302 
306  __host__ __device__
307  reference operator*() const
308  {
309  return iterator_core_access::dereference(this->derived());
310  }
311 
312  // XXX unimplemented for now, consider implementing it later
313  //pointer operator->() const
314  //{
315  // return;
316  //}
317 
318  // XXX investigate whether or not we need to go to the lengths
319  // boost does to determine the return type
320 
324  __host__ __device__
325  reference operator[](difference_type n) const
326  {
327  return *(this->derived() + n);
328  }
329 
333  __host__ __device__
334  Derived& operator++()
335  {
336  iterator_core_access::increment(this->derived());
337  return this->derived();
338  }
339 
343  __host__ __device__
344  Derived operator++(int)
345  {
346  Derived tmp(this->derived());
347  ++*this;
348  return tmp;
349  }
350 
354  __host__ __device__
355  Derived& operator--()
356  {
357  iterator_core_access::decrement(this->derived());
358  return this->derived();
359  }
360 
364  __host__ __device__
365  Derived operator--(int)
366  {
367  Derived tmp(this->derived());
368  --*this;
369  return tmp;
370  }
371 
376  __host__ __device__
377  Derived& operator+=(difference_type n)
378  {
379  iterator_core_access::advance(this->derived(), n);
380  return this->derived();
381  }
382 
387  __host__ __device__
388  Derived& operator-=(difference_type n)
389  {
390  iterator_core_access::advance(this->derived(), -n);
391  return this->derived();
392  }
393 
398  __host__ __device__
399  Derived operator-(difference_type n) const
400  {
401  Derived result(this->derived());
402  return result -= n;
403  }
404 }; // end iterator_facade
405 
409 // Comparison operators
410 template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
411  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
412 inline __host__ __device__
413 // XXX it might be nice to implement this at some point
414 //typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition
415 bool
418 {
419  return iterator_core_access
420  ::equal(*static_cast<Derived1 const*>(&lhs),
421  *static_cast<Derived2 const*>(&rhs));
422 }
423 
424 template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
425  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
426 inline __host__ __device__
427 // XXX it might be nice to implement this at some point
428 //typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition
429 bool
432 {
433  return !iterator_core_access
434  ::equal(*static_cast<Derived1 const*>(&lhs),
435  *static_cast<Derived2 const*>(&rhs));
436 }
437 
438 template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
439  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
440 inline __host__ __device__
441 // XXX it might be nice to implement this at some point
442 //typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition
443 bool
444 operator <(iterator_facade<Derived1,Value1,System1,Traversal1,Reference1,Difference1> const& lhs,
446 {
447  return 0 > iterator_core_access
448  ::distance_from(*static_cast<Derived1 const*>(&lhs),
449  *static_cast<Derived2 const*>(&rhs));
450 }
451 
452 template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
453  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
454 inline __host__ __device__
455 // XXX it might be nice to implement this at some point
456 //typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition
457 bool
460 {
461  return 0 < iterator_core_access
462  ::distance_from(*static_cast<Derived1 const*>(&lhs),
463  *static_cast<Derived2 const*>(&rhs));
464 }
465 
466 template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
467  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
468 inline __host__ __device__
469 // XXX it might be nice to implement this at some point
470 //typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition
471 bool
472 operator <=(iterator_facade<Derived1,Value1,System1,Traversal1,Reference1,Difference1> const& lhs,
474 {
475  return 0 >= iterator_core_access
476  ::distance_from(*static_cast<Derived1 const*>(&lhs),
477  *static_cast<Derived2 const*>(&rhs));
478 }
479 
480 template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
481  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
482 inline __host__ __device__
483 // XXX it might be nice to implement this at some point
484 //typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition
485 bool
488 {
489  return 0 <= iterator_core_access
490  ::distance_from(*static_cast<Derived1 const*>(&lhs),
491  *static_cast<Derived2 const*>(&rhs));
492 }
493 
494 // Iterator difference
495 template <typename Derived1, typename Value1, typename System1, typename Traversal1, typename Reference1, typename Difference1,
496  typename Derived2, typename Value2, typename System2, typename Traversal2, typename Reference2, typename Difference2>
497 inline __host__ __device__
498 
499 // divine the type this operator returns
500 typename thrust::detail::distance_from_result<
503 >::type
504 
507 {
508  return iterator_core_access
509  ::distance_from(*static_cast<Derived1 const*>(&lhs),
510  *static_cast<Derived2 const*>(&rhs));
511 }
512 
513 // Iterator addition
514 template <typename Derived, typename Value, typename System, typename Traversal, typename Reference, typename Difference>
515 inline __host__ __device__
517  typename Derived::difference_type n)
518 {
519  Derived tmp(static_cast<Derived const&>(i));
520  return tmp += n;
521 }
522 
523 template <typename Derived, typename Value, typename System, typename Traversal, typename Reference, typename Difference>
524 inline __host__ __device__
525 Derived operator+ (typename Derived::difference_type n,
527 {
528  Derived tmp(static_cast<Derived const&>(i));
529  return tmp += n;
530 }
531 
541 THRUST_NAMESPACE_END
542 
__host__ __device__ Derived & operator++()
Definition: iterator_facade.h:334
Reference reference
Definition: iterator_facade.h:281
__host__ __device__ reference operator*() const
Definition: iterator_facade.h:307
__host__ __device__ complex< typename detail::promoted_numerical_type< T0, T1 >::type > operator-(const complex< T0 > &x, const complex< T1 > &y)
thrust::reference< T, thrust::system::cpp::tag > reference
Definition: pointer.h:98
__host__ __device__ void advance(InputIterator &i, Distance n)
Definition: iterator_facade.h:60
__host__ __device__ Derived operator--(int)
Definition: iterator_facade.h:365
__host__ __device__ bool operator>=(const pair< T1, T2 > &x, const pair< T1, T2 > &y)
__host__ __device__ Derived & operator--()
Definition: iterator_facade.h:355
__host__ __device__ bool equal(const thrust::detail::execution_policy_base< DerivedPolicy > &exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
__host__ __device__ reference operator[](difference_type n) const
Definition: iterator_facade.h:325
__host__ __device__ Derived operator-(difference_type n) const
Definition: iterator_facade.h:399
thrust::detail::iterator_facade_category< System, Traversal, Value, Reference >::type iterator_category
Definition: iterator_facade.h:301
__host__ __device__ complex< typename detail::promoted_numerical_type< T0, T1 >::type > operator+(const complex< T0 > &x, const complex< T1 > &y)
__host__ __device__ bool operator!=(const complex< T0 > &x, const complex< T1 > &y)
__host__ __device__ Derived & operator-=(difference_type n)
Definition: iterator_facade.h:388
thrust::detail::remove_const< Value >::type value_type
Definition: iterator_facade.h:277
Definition: iterator_facade.h:54
Difference difference_type
Definition: iterator_facade.h:295
__host__ __device__ bool operator==(const complex< T0 > &x, const complex< T1 > &y)
__host__ __device__ Derived operator++(int)
Definition: iterator_facade.h:344
void pointer
Definition: iterator_facade.h:290
__host__ __device__ bool operator>(const pair< T1, T2 > &x, const pair< T1, T2 > &y)
__host__ __device__ Derived & operator+=(difference_type n)
Definition: iterator_facade.h:377