/Src/Dependencies/Boost/boost/range/adaptor/strided.hpp

http://hadesmem.googlecode.com/ · C++ Header · 350 lines · 293 code · 44 blank · 13 comment · 16 complexity · c6c9834477182a746befe056c02381c0 MD5 · raw file

  1. // Boost.Range library
  2. //
  3. // Copyright Neil Groves 2007. Use, modification and
  4. // distribution is subject to the Boost Software License, Version
  5. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. //
  9. // For more information, see http://www.boost.org/libs/range/
  10. //
  11. #ifndef BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED
  12. #define BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED
  13. #include <boost/range/adaptor/argument_fwd.hpp>
  14. #include <boost/range/iterator_range.hpp>
  15. #include <boost/iterator/iterator_adaptor.hpp>
  16. #include <iterator>
  17. namespace boost
  18. {
  19. namespace range_detail
  20. {
  21. // strided_iterator for wrapping a forward traversal iterator
  22. template<class BaseIterator, class Category>
  23. class strided_iterator
  24. : public iterator_adaptor<
  25. strided_iterator<BaseIterator, Category>
  26. , BaseIterator
  27. , use_default
  28. , boost::forward_traversal_tag
  29. >
  30. {
  31. friend class ::boost::iterator_core_access;
  32. typedef iterator_adaptor<
  33. strided_iterator<BaseIterator, Category>
  34. , BaseIterator
  35. , use_default
  36. , boost::forward_traversal_tag
  37. > super_t;
  38. public:
  39. typedef BOOST_DEDUCED_TYPENAME std::iterator_traits<BaseIterator>::difference_type difference_type;
  40. typedef BaseIterator base_iterator;
  41. strided_iterator()
  42. : m_last()
  43. , m_stride()
  44. {
  45. }
  46. strided_iterator(base_iterator first, base_iterator it, base_iterator last, difference_type stride)
  47. : super_t(it)
  48. , m_last(last)
  49. , m_stride(stride)
  50. {
  51. }
  52. template<class OtherIterator>
  53. strided_iterator(const strided_iterator<OtherIterator, Category>& other,
  54. BOOST_DEDUCED_TYPENAME enable_if_convertible<OtherIterator, base_iterator>::type* = 0)
  55. : super_t(other)
  56. , m_last(other.base_end())
  57. , m_stride(other.get_stride())
  58. {
  59. }
  60. base_iterator base_end() const { return m_last; }
  61. difference_type get_stride() const { return m_stride; }
  62. private:
  63. void increment()
  64. {
  65. base_iterator& it = this->base_reference();
  66. for (difference_type i = 0; (it != m_last) && (i < m_stride); ++i)
  67. ++it;
  68. }
  69. base_iterator m_last;
  70. difference_type m_stride;
  71. };
  72. // strided_iterator for wrapping a bidirectional iterator
  73. template<class BaseIterator>
  74. class strided_iterator<BaseIterator, bidirectional_traversal_tag>
  75. : public iterator_adaptor<
  76. strided_iterator<BaseIterator, bidirectional_traversal_tag>
  77. , BaseIterator
  78. , use_default
  79. , bidirectional_traversal_tag
  80. >
  81. {
  82. friend class ::boost::iterator_core_access;
  83. typedef iterator_adaptor<
  84. strided_iterator<BaseIterator, bidirectional_traversal_tag>
  85. , BaseIterator
  86. , use_default
  87. , bidirectional_traversal_tag
  88. > super_t;
  89. public:
  90. typedef BOOST_DEDUCED_TYPENAME std::iterator_traits<BaseIterator>::difference_type difference_type;
  91. typedef BaseIterator base_iterator;
  92. strided_iterator()
  93. : m_first()
  94. , m_last()
  95. , m_stride()
  96. {
  97. }
  98. strided_iterator(base_iterator first, base_iterator it, base_iterator last, difference_type stride)
  99. : super_t(it)
  100. , m_first(first)
  101. , m_last(last)
  102. , m_stride(stride)
  103. {
  104. }
  105. template<class OtherIterator>
  106. strided_iterator(const strided_iterator<OtherIterator, bidirectional_traversal_tag>& other,
  107. BOOST_DEDUCED_TYPENAME enable_if_convertible<OtherIterator, base_iterator>::type* = 0)
  108. : super_t(other.base())
  109. , m_first(other.base_begin())
  110. , m_last(other.base_end())
  111. , m_stride(other.get_stride())
  112. {
  113. }
  114. base_iterator base_begin() const { return m_first; }
  115. base_iterator base_end() const { return m_last; }
  116. difference_type get_stride() const { return m_stride; }
  117. private:
  118. void increment()
  119. {
  120. base_iterator& it = this->base_reference();
  121. for (difference_type i = 0; (it != m_last) && (i < m_stride); ++i)
  122. ++it;
  123. }
  124. void decrement()
  125. {
  126. base_iterator& it = this->base_reference();
  127. for (difference_type i = 0; (it != m_first) && (i < m_stride); ++i)
  128. --it;
  129. }
  130. base_iterator m_first;
  131. base_iterator m_last;
  132. difference_type m_stride;
  133. };
  134. // strided_iterator implementation for wrapping a random access iterator
  135. template<class BaseIterator>
  136. class strided_iterator<BaseIterator, random_access_traversal_tag>
  137. : public iterator_adaptor<
  138. strided_iterator<BaseIterator, random_access_traversal_tag>
  139. , BaseIterator
  140. , use_default
  141. , random_access_traversal_tag
  142. >
  143. {
  144. friend class ::boost::iterator_core_access;
  145. typedef iterator_adaptor<
  146. strided_iterator<BaseIterator, random_access_traversal_tag>
  147. , BaseIterator
  148. , use_default
  149. , random_access_traversal_tag
  150. > super_t;
  151. public:
  152. typedef BOOST_DEDUCED_TYPENAME super_t::difference_type difference_type;
  153. typedef BaseIterator base_iterator;
  154. strided_iterator()
  155. : m_first()
  156. , m_last()
  157. , m_index(0)
  158. , m_stride()
  159. {
  160. }
  161. strided_iterator(BaseIterator first, BaseIterator it, BaseIterator last, difference_type stride)
  162. : super_t(it)
  163. , m_first(first)
  164. , m_last(last)
  165. , m_index(stride ? (it - first) / stride : 0)
  166. , m_stride(stride)
  167. {
  168. }
  169. template<class OtherIterator>
  170. strided_iterator(const strided_iterator<OtherIterator, random_access_traversal_tag>& other,
  171. BOOST_DEDUCED_TYPENAME enable_if_convertible<OtherIterator, BaseIterator>::type* = 0)
  172. : super_t(other.base())
  173. , m_first(other.base_begin())
  174. , m_last(other.base_end())
  175. , m_index(other.get_index())
  176. , m_stride(other.get_stride())
  177. {
  178. }
  179. base_iterator base_begin() const { return m_first; }
  180. base_iterator base_end() const { return m_last; }
  181. difference_type get_stride() const { return m_stride; }
  182. difference_type get_index() const { return m_index; }
  183. private:
  184. void increment()
  185. {
  186. m_index += m_stride;
  187. if (m_index < (m_last - m_first))
  188. this->base_reference() = m_first + m_index;
  189. else
  190. this->base_reference() = m_last;
  191. }
  192. void decrement()
  193. {
  194. m_index -= m_stride;
  195. if (m_index >= 0)
  196. this->base_reference() = m_first + m_index;
  197. else
  198. this->base_reference() = m_first;
  199. }
  200. void advance(difference_type offset)
  201. {
  202. offset *= m_stride;
  203. m_index += offset;
  204. if (m_index < 0)
  205. this->base_reference() = m_first;
  206. else if (m_index > (m_last - m_first))
  207. this->base_reference() = m_last;
  208. else
  209. this->base_reference() = m_first + m_index;
  210. }
  211. template<class OtherIterator>
  212. difference_type distance_to(const strided_iterator<OtherIterator, random_access_traversal_tag>& other,
  213. BOOST_DEDUCED_TYPENAME enable_if_convertible<OtherIterator, BaseIterator>::type* = 0) const
  214. {
  215. if (other.base() >= this->base())
  216. return (other.base() - this->base() + (m_stride - 1)) / m_stride;
  217. return (other.base() - this->base() - (m_stride - 1)) / m_stride;
  218. }
  219. bool equal(const strided_iterator& other) const
  220. {
  221. return this->base() == other.base();
  222. }
  223. private:
  224. base_iterator m_first;
  225. base_iterator m_last;
  226. difference_type m_index;
  227. difference_type m_stride;
  228. };
  229. template<class BaseIterator, class Difference> inline
  230. strided_iterator<BaseIterator, BOOST_DEDUCED_TYPENAME iterator_traversal<BaseIterator>::type>
  231. make_strided_iterator(BaseIterator first, BaseIterator it,
  232. BaseIterator last, Difference stride)
  233. {
  234. BOOST_ASSERT( stride >= 0 );
  235. typedef BOOST_DEDUCED_TYPENAME iterator_traversal<BaseIterator>::type traversal_tag;
  236. return strided_iterator<BaseIterator, traversal_tag>(first, it, last, stride);
  237. }
  238. template< class Rng
  239. , class Category = BOOST_DEDUCED_TYPENAME iterator_traversal<
  240. BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type
  241. >::type
  242. >
  243. class strided_range
  244. : public iterator_range<
  245. range_detail::strided_iterator<
  246. BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type,
  247. Category
  248. >
  249. >
  250. {
  251. typedef range_detail::strided_iterator<
  252. BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type,
  253. Category
  254. > iter_type;
  255. typedef iterator_range<iter_type> super_t;
  256. public:
  257. template<class Difference>
  258. strided_range(Difference stride, Rng& rng)
  259. : super_t(make_strided_iterator(boost::begin(rng), boost::begin(rng), boost::end(rng), stride),
  260. make_strided_iterator(boost::begin(rng), boost::end(rng), boost::end(rng), stride))
  261. {
  262. BOOST_ASSERT( stride >= 0 );
  263. }
  264. };
  265. template<class Difference>
  266. class strided_holder : public holder<Difference>
  267. {
  268. public:
  269. explicit strided_holder(Difference value) : holder<Difference>(value) {}
  270. };
  271. template<class Rng, class Difference>
  272. inline strided_range<Rng>
  273. operator|(Rng& rng, const strided_holder<Difference>& stride)
  274. {
  275. return strided_range<Rng>(stride.val, rng);
  276. }
  277. template<class Rng, class Difference>
  278. inline strided_range<const Rng>
  279. operator|(const Rng& rng, const strided_holder<Difference>& stride)
  280. {
  281. return strided_range<const Rng>(stride.val, rng);
  282. }
  283. } // namespace range_detail
  284. using range_detail::strided_range;
  285. namespace adaptors
  286. {
  287. namespace
  288. {
  289. const range_detail::forwarder<range_detail::strided_holder>
  290. strided = range_detail::forwarder<range_detail::strided_holder>();
  291. }
  292. template<class Range, class Difference>
  293. inline strided_range<Range>
  294. stride(Range& rng, Difference step)
  295. {
  296. return strided_range<Range>(step, rng);
  297. }
  298. template<class Range, class Difference>
  299. inline strided_range<const Range>
  300. stride(const Range& rng, Difference step)
  301. {
  302. return strided_range<const Range>(step, rng);
  303. }
  304. } // namespace 'adaptors'
  305. } // namespace 'boost'
  306. #endif