counting_iterator.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
  3. //
  4. // Distributed under the Boost Software License, Version 1.0
  5. // See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. //
  8. // See http://boostorg.github.com/compute for more information.
  9. //---------------------------------------------------------------------------//
  10. #ifndef BOOST_COMPUTE_ITERATOR_COUNTING_ITERATOR_HPP
  11. #define BOOST_COMPUTE_ITERATOR_COUNTING_ITERATOR_HPP
  12. #include <string>
  13. #include <cstddef>
  14. #include <iterator>
  15. #include <boost/config.hpp>
  16. #include <boost/iterator/iterator_facade.hpp>
  17. #include <boost/compute/detail/meta_kernel.hpp>
  18. #include <boost/compute/type_traits/is_device_iterator.hpp>
  19. namespace boost {
  20. namespace compute {
  21. // forward declaration for counting_iterator<T>
  22. template<class T> class counting_iterator;
  23. namespace detail {
  24. // helper class which defines the iterator_facade super-class
  25. // type for counting_iterator<T>
  26. template<class T>
  27. class counting_iterator_base
  28. {
  29. public:
  30. typedef ::boost::iterator_facade<
  31. ::boost::compute::counting_iterator<T>,
  32. T,
  33. ::std::random_access_iterator_tag
  34. > type;
  35. };
  36. template<class T, class IndexExpr>
  37. struct counting_iterator_index_expr
  38. {
  39. typedef T result_type;
  40. counting_iterator_index_expr(const T init, const IndexExpr &expr)
  41. : m_init(init),
  42. m_expr(expr)
  43. {
  44. }
  45. const T m_init;
  46. const IndexExpr m_expr;
  47. };
  48. template<class T, class IndexExpr>
  49. inline meta_kernel& operator<<(meta_kernel &kernel,
  50. const counting_iterator_index_expr<T, IndexExpr> &expr)
  51. {
  52. return kernel << '(' << expr.m_init << '+' << expr.m_expr << ')';
  53. }
  54. } // end detail namespace
  55. /// \class counting_iterator
  56. /// \brief The counting_iterator class implements a counting iterator.
  57. ///
  58. /// A counting iterator returns an internal value (initialized with \p init)
  59. /// which is incremented each time the iterator is incremented.
  60. ///
  61. /// For example, this could be used to implement the iota() algorithm in terms
  62. /// of the copy() algorithm by copying from a range of counting iterators:
  63. ///
  64. /// \snippet test/test_counting_iterator.cpp iota_with_copy
  65. ///
  66. /// \see make_counting_iterator()
  67. template<class T>
  68. class counting_iterator : public detail::counting_iterator_base<T>::type
  69. {
  70. public:
  71. typedef typename detail::counting_iterator_base<T>::type super_type;
  72. typedef typename super_type::reference reference;
  73. typedef typename super_type::difference_type difference_type;
  74. counting_iterator(const T &init)
  75. : m_init(init)
  76. {
  77. }
  78. counting_iterator(const counting_iterator<T> &other)
  79. : m_init(other.m_init)
  80. {
  81. }
  82. counting_iterator<T>& operator=(const counting_iterator<T> &other)
  83. {
  84. if(this != &other){
  85. m_init = other.m_init;
  86. }
  87. return *this;
  88. }
  89. ~counting_iterator()
  90. {
  91. }
  92. size_t get_index() const
  93. {
  94. return 0;
  95. }
  96. template<class Expr>
  97. detail::counting_iterator_index_expr<T, Expr>
  98. operator[](const Expr &expr) const
  99. {
  100. return detail::counting_iterator_index_expr<T, Expr>(m_init, expr);
  101. }
  102. private:
  103. friend class ::boost::iterator_core_access;
  104. reference dereference() const
  105. {
  106. return m_init;
  107. }
  108. bool equal(const counting_iterator<T> &other) const
  109. {
  110. return m_init == other.m_init;
  111. }
  112. void increment()
  113. {
  114. m_init++;
  115. }
  116. void decrement()
  117. {
  118. m_init--;
  119. }
  120. void advance(difference_type n)
  121. {
  122. m_init += static_cast<T>(n);
  123. }
  124. difference_type distance_to(const counting_iterator<T> &other) const
  125. {
  126. return difference_type(other.m_init) - difference_type(m_init);
  127. }
  128. private:
  129. T m_init;
  130. };
  131. /// Returns a new counting_iterator starting at \p init.
  132. ///
  133. /// \param init the initial value
  134. ///
  135. /// \return a counting_iterator with \p init.
  136. ///
  137. /// For example, to create a counting iterator which returns unsigned integers
  138. /// and increments from one:
  139. /// \code
  140. /// auto iter = make_counting_iterator<uint_>(1);
  141. /// \endcode
  142. template<class T>
  143. inline counting_iterator<T> make_counting_iterator(const T &init)
  144. {
  145. return counting_iterator<T>(init);
  146. }
  147. /// \internal_ (is_device_iterator specialization for counting_iterator)
  148. template<class T>
  149. struct is_device_iterator<counting_iterator<T> > : boost::true_type {};
  150. } // end compute namespace
  151. } // end boost namespace
  152. #endif // BOOST_COMPUTE_ITERATOR_COUNTING_ITERATOR_HPP