chunk.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_VIEW_CHUNK_HPP
  14. #define RANGES_V3_VIEW_CHUNK_HPP
  15. #include <limits>
  16. #include <utility>
  17. #include <meta/meta.hpp>
  18. #include <range/v3/range_fwd.hpp>
  19. #include <range/v3/functional/bind_back.hpp>
  20. #include <range/v3/iterator/default_sentinel.hpp>
  21. #include <range/v3/iterator/operations.hpp>
  22. #include <range/v3/range/access.hpp>
  23. #include <range/v3/range/concepts.hpp>
  24. #include <range/v3/range/traits.hpp>
  25. #include <range/v3/utility/box.hpp>
  26. #include <range/v3/utility/optional.hpp> // for non_propagating_cache
  27. #include <range/v3/utility/static_const.hpp>
  28. #include <range/v3/view/adaptor.hpp>
  29. #include <range/v3/view/all.hpp>
  30. #include <range/v3/view/facade.hpp>
  31. #include <range/v3/view/take.hpp>
  32. #include <range/v3/view/view.hpp>
  33. #include <range/v3/detail/prologue.hpp>
  34. namespace ranges
  35. {
  36. /// \cond
  37. namespace detail
  38. {
  39. template<typename Rng, bool Const>
  40. constexpr bool can_sized_sentinel_() noexcept
  41. {
  42. using I = iterator_t<meta::const_if_c<Const, Rng>>;
  43. return (bool)sized_sentinel_for<I, I>;
  44. }
  45. template<typename T>
  46. struct zero
  47. {
  48. zero() = default;
  49. constexpr explicit zero(T const &) noexcept
  50. {}
  51. constexpr zero & operator=(T const &) noexcept
  52. {
  53. return *this;
  54. }
  55. constexpr zero const & operator=(T const &) const noexcept
  56. {
  57. return *this;
  58. }
  59. constexpr operator T() const
  60. {
  61. return T(0);
  62. }
  63. constexpr T exchange(T const &) const
  64. {
  65. return T(0);
  66. }
  67. };
  68. } // namespace detail
  69. /// \endcond
  70. /// \addtogroup group-views
  71. /// @{
  72. template<typename Rng, bool IsForwardRange>
  73. struct chunk_view_
  74. : view_adaptor<chunk_view_<Rng, IsForwardRange>, Rng,
  75. is_finite<Rng>::value ? finite : range_cardinality<Rng>::value>
  76. {
  77. private:
  78. friend range_access;
  79. CPP_assert(forward_range<Rng>);
  80. template<bool Const>
  81. using offset_t =
  82. meta::if_c<bidirectional_range<meta::const_if_c<Const, Rng>> ||
  83. detail::can_sized_sentinel_<Rng, Const>(),
  84. range_difference_t<Rng>, detail::zero<range_difference_t<Rng>>>;
  85. range_difference_t<Rng> n_ = 0;
  86. template<bool Const>
  87. struct RANGES_EMPTY_BASES adaptor
  88. : adaptor_base
  89. , private box<offset_t<Const>>
  90. {
  91. private:
  92. friend adaptor<!Const>;
  93. using CRng = meta::const_if_c<Const, Rng>;
  94. range_difference_t<CRng> n_;
  95. sentinel_t<CRng> end_;
  96. constexpr offset_t<Const> const & offset() const
  97. {
  98. offset_t<Const> const & result = this->box<offset_t<Const>>::get();
  99. RANGES_EXPECT(0 <= result && result < n_);
  100. return result;
  101. }
  102. constexpr offset_t<Const> & offset()
  103. {
  104. return const_cast<offset_t<Const> &>(
  105. const_cast<adaptor const &>(*this).offset());
  106. }
  107. public:
  108. adaptor() = default;
  109. constexpr adaptor(meta::const_if_c<Const, chunk_view_> * cv)
  110. : box<offset_t<Const>>{0}
  111. , n_((RANGES_EXPECT(0 < cv->n_), cv->n_))
  112. , end_(ranges::end(cv->base()))
  113. {}
  114. template(bool Other)(
  115. requires Const AND CPP_NOT(Other)) //
  116. constexpr adaptor(adaptor<Other> that)
  117. : box<offset_t<Const>>(that.offset())
  118. , n_(that.n_)
  119. , end_(that.end_)
  120. {}
  121. constexpr auto read(iterator_t<CRng> const & it) const
  122. -> decltype(views::take(make_subrange(it, end_), n_))
  123. {
  124. RANGES_EXPECT(it != end_);
  125. RANGES_EXPECT(0 == offset());
  126. return views::take(make_subrange(it, end_), n_);
  127. }
  128. constexpr void next(iterator_t<CRng> & it)
  129. {
  130. RANGES_EXPECT(it != end_);
  131. RANGES_EXPECT(0 == offset());
  132. offset() = ranges::advance(it, n_, end_);
  133. }
  134. CPP_member
  135. constexpr auto prev(iterator_t<CRng> & it) //
  136. -> CPP_ret(void)(
  137. requires bidirectional_range<CRng>)
  138. {
  139. ranges::advance(it, -n_ + offset());
  140. offset() = 0;
  141. }
  142. CPP_member
  143. constexpr auto distance_to(iterator_t<CRng> const & here,
  144. iterator_t<CRng> const & there,
  145. adaptor const & that) const
  146. -> CPP_ret(range_difference_t<Rng>)(
  147. requires (detail::can_sized_sentinel_<Rng, Const>()))
  148. {
  149. auto const delta = (there - here) + (that.offset() - offset());
  150. // This can fail for cyclic base ranges when the chunk size does not
  151. // divide the cycle length. Such iterator pairs are NOT in the domain of
  152. // -.
  153. RANGES_ENSURE(0 == delta % n_);
  154. return delta / n_;
  155. }
  156. CPP_member
  157. constexpr auto advance(iterator_t<CRng> & it, range_difference_t<Rng> n) //
  158. -> CPP_ret(void)(
  159. requires random_access_range<CRng>)
  160. {
  161. using Limits = std::numeric_limits<range_difference_t<CRng>>;
  162. if(0 < n)
  163. {
  164. RANGES_EXPECT(0 == offset());
  165. RANGES_EXPECT(n <= Limits::max() / n_);
  166. auto const remainder = ranges::advance(it, n * n_, end_) % n_;
  167. RANGES_EXPECT(0 <= remainder && remainder < n_);
  168. offset() = remainder;
  169. }
  170. else if(0 > n)
  171. {
  172. RANGES_EXPECT(n >= Limits::min() / n_);
  173. ranges::advance(it, n * n_ + offset());
  174. offset() = 0;
  175. }
  176. }
  177. };
  178. constexpr adaptor<simple_view<Rng>()> begin_adaptor()
  179. {
  180. return adaptor<simple_view<Rng>()>{this};
  181. }
  182. CPP_member
  183. constexpr auto begin_adaptor() const //
  184. -> CPP_ret(adaptor<true>)(
  185. requires forward_range<Rng const>)
  186. {
  187. return adaptor<true>{this};
  188. }
  189. template<typename Size>
  190. constexpr Size size_(Size base_size) const
  191. {
  192. auto const n = static_cast<Size>(n_);
  193. return base_size / n + (0 != (base_size % n));
  194. }
  195. public:
  196. chunk_view_() = default;
  197. constexpr chunk_view_(Rng rng, range_difference_t<Rng> n)
  198. : chunk_view_::view_adaptor(detail::move(rng))
  199. , n_((RANGES_EXPECT(0 < n), n))
  200. {}
  201. CPP_auto_member
  202. constexpr auto CPP_fun(size)()(const
  203. requires sized_range<Rng const>)
  204. {
  205. return size_(ranges::size(this->base()));
  206. }
  207. CPP_auto_member
  208. constexpr auto CPP_fun(size)()(
  209. requires sized_range<Rng>)
  210. {
  211. return size_(ranges::size(this->base()));
  212. }
  213. };
  214. template<typename Rng>
  215. struct chunk_view_<Rng, false>
  216. : view_facade<chunk_view_<Rng, false>,
  217. is_finite<Rng>::value ? finite : range_cardinality<Rng>::value>
  218. {
  219. private:
  220. friend range_access;
  221. CPP_assert(input_range<Rng> && !forward_range<Rng>);
  222. using iter_cache_t = detail::non_propagating_cache<iterator_t<Rng>>;
  223. Rng base_;
  224. range_difference_t<Rng> n_;
  225. range_difference_t<Rng> remainder_;
  226. mutable iter_cache_t it_cache_;
  227. constexpr iterator_t<Rng> & it() noexcept
  228. {
  229. return *it_cache_;
  230. }
  231. constexpr iterator_t<Rng> const & it() const noexcept
  232. {
  233. return *it_cache_;
  234. }
  235. struct outer_cursor
  236. {
  237. private:
  238. struct inner_view : view_facade<inner_view, finite>
  239. {
  240. private:
  241. friend range_access;
  242. using value_type = range_value_t<Rng>;
  243. chunk_view_ * rng_ = nullptr;
  244. constexpr bool done() const noexcept
  245. {
  246. RANGES_EXPECT(rng_);
  247. return rng_->remainder_ == 0;
  248. }
  249. constexpr bool equal(default_sentinel_t) const noexcept
  250. {
  251. return done();
  252. }
  253. constexpr iter_reference_t<iterator_t<Rng>> read() const
  254. {
  255. RANGES_EXPECT(!done());
  256. return *rng_->it();
  257. }
  258. constexpr iter_rvalue_reference_t<iterator_t<Rng>> move() const
  259. {
  260. RANGES_EXPECT(!done());
  261. return ranges::iter_move(rng_->it());
  262. }
  263. constexpr void next()
  264. {
  265. RANGES_EXPECT(!done());
  266. ++rng_->it();
  267. --rng_->remainder_;
  268. if(rng_->remainder_ != 0 && rng_->it() == ranges::end(rng_->base_))
  269. rng_->remainder_ = 0;
  270. }
  271. CPP_member
  272. constexpr auto distance_to(default_sentinel_t) const
  273. -> CPP_ret(range_difference_t<Rng>)(
  274. requires sized_sentinel_for<sentinel_t<Rng>, iterator_t<Rng>>)
  275. {
  276. RANGES_EXPECT(rng_);
  277. auto const d = ranges::end(rng_->base_) - rng_->it();
  278. return ranges::min(d, rng_->remainder_);
  279. }
  280. public:
  281. inner_view() = default;
  282. constexpr explicit inner_view(chunk_view_ * view) noexcept
  283. : rng_{view}
  284. {}
  285. CPP_auto_member
  286. constexpr auto CPP_fun(size)()(
  287. requires sized_sentinel_for<sentinel_t<Rng>, iterator_t<Rng>>)
  288. {
  289. using size_type = detail::iter_size_t<iterator_t<Rng>>;
  290. return static_cast<size_type>(distance_to(default_sentinel_t{}));
  291. }
  292. };
  293. chunk_view_ * rng_ = nullptr;
  294. public:
  295. using value_type = inner_view;
  296. outer_cursor() = default;
  297. constexpr explicit outer_cursor(chunk_view_ * view) noexcept
  298. : rng_{view}
  299. {}
  300. constexpr inner_view read() const
  301. {
  302. RANGES_EXPECT(!done());
  303. return inner_view{rng_};
  304. }
  305. constexpr bool done() const
  306. {
  307. RANGES_EXPECT(rng_);
  308. return rng_->it() == ranges::end(rng_->base_) && rng_->remainder_ != 0;
  309. }
  310. constexpr bool equal(default_sentinel_t) const
  311. {
  312. return done();
  313. }
  314. constexpr void next()
  315. {
  316. RANGES_EXPECT(!done());
  317. ranges::advance(rng_->it(), rng_->remainder_, ranges::end(rng_->base_));
  318. rng_->remainder_ = rng_->n_;
  319. }
  320. CPP_member
  321. constexpr auto distance_to(default_sentinel_t) const
  322. -> CPP_ret(range_difference_t<Rng>)(
  323. requires sized_sentinel_for<sentinel_t<Rng>, iterator_t<Rng>>)
  324. {
  325. RANGES_EXPECT(rng_);
  326. auto d = ranges::end(rng_->base_) - rng_->it();
  327. if(d < rng_->remainder_)
  328. return 1;
  329. d -= rng_->remainder_;
  330. d = (d + rng_->n_ - 1) / rng_->n_;
  331. d += (rng_->remainder_ != 0);
  332. return d;
  333. }
  334. };
  335. constexpr outer_cursor begin_cursor() noexcept
  336. {
  337. it_cache_ = ranges::begin(base_);
  338. return outer_cursor{this};
  339. }
  340. template<typename Size>
  341. constexpr Size size_(Size base_size) const
  342. {
  343. auto const n = static_cast<Size>(this->n_);
  344. return base_size / n + (0 != base_size % n);
  345. }
  346. public:
  347. chunk_view_() = default;
  348. constexpr chunk_view_(Rng rng, range_difference_t<Rng> n)
  349. : base_(detail::move(rng))
  350. , n_((RANGES_EXPECT(0 < n), n))
  351. , remainder_(n)
  352. , it_cache_{nullopt}
  353. {}
  354. CPP_auto_member
  355. constexpr auto CPP_fun(size)()(const
  356. requires sized_range<Rng const>)
  357. {
  358. return size_(ranges::size(base_));
  359. }
  360. CPP_auto_member
  361. constexpr auto CPP_fun(size)()(
  362. requires sized_range<Rng>)
  363. {
  364. return size_(ranges::size(base_));
  365. }
  366. Rng base() const
  367. {
  368. return base_;
  369. }
  370. };
  371. template<typename Rng>
  372. struct chunk_view : chunk_view_<Rng, (bool)forward_range<Rng>>
  373. {
  374. chunk_view() = default;
  375. constexpr chunk_view(Rng rng, range_difference_t<Rng> n)
  376. : chunk_view_<Rng, (bool)forward_range<Rng>>(static_cast<Rng &&>(rng), n)
  377. {}
  378. };
  379. // Need to keep extra state for input_range, but forward_range is transparent
  380. template<typename Rng>
  381. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<chunk_view<Rng>> =
  382. enable_borrowed_range<Rng> && forward_range<Rng>;
  383. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  384. template<typename Rng>
  385. chunk_view(Rng &&, range_difference_t<Rng>)
  386. -> chunk_view<views::all_t<Rng>>;
  387. #endif
  388. namespace views
  389. {
  390. // In: range<T>
  391. // Out: range<range<T>>, where each inner range has $n$ elements.
  392. // The last range may have fewer.
  393. struct chunk_base_fn
  394. {
  395. template(typename Rng)(
  396. requires viewable_range<Rng> AND input_range<Rng>)
  397. constexpr chunk_view<all_t<Rng>> //
  398. operator()(Rng && rng, range_difference_t<Rng> n) const
  399. {
  400. return {all(static_cast<Rng &&>(rng)), n};
  401. }
  402. };
  403. struct chunk_fn : chunk_base_fn
  404. {
  405. using chunk_base_fn::operator();
  406. template(typename Int)(
  407. requires detail::integer_like_<Int>)
  408. constexpr auto operator()(Int n) const
  409. {
  410. return make_view_closure(bind_back(chunk_base_fn{}, n));
  411. }
  412. };
  413. /// \relates chunk_fn
  414. /// \ingroup group-views
  415. RANGES_INLINE_VARIABLE(chunk_fn, chunk)
  416. } // namespace views
  417. /// @}
  418. } // namespace ranges
  419. #include <range/v3/detail/epilogue.hpp>
  420. #include <range/v3/detail/satisfy_boost_range.hpp>
  421. RANGES_SATISFY_BOOST_RANGE(::ranges::chunk_view)
  422. #endif