segmented_fold_until_impl.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /*=============================================================================
  2. Copyright (c) 2011 Eric Niebler
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. ==============================================================================*/
  6. #if !defined(BOOST_FUSION_SEGMENTED_FOLD_UNTIL_IMPL_HPP_INCLUDED)
  7. #define BOOST_FUSION_SEGMENTED_FOLD_UNTIL_IMPL_HPP_INCLUDED
  8. #include <boost/fusion/support/config.hpp>
  9. #include <boost/mpl/bool.hpp>
  10. #include <boost/mpl/eval_if.hpp>
  11. #include <boost/mpl/identity.hpp>
  12. #include <boost/utility/result_of.hpp>
  13. #include <boost/type_traits/add_const.hpp>
  14. #include <boost/type_traits/remove_reference.hpp>
  15. #include <boost/fusion/support/void.hpp>
  16. #include <boost/fusion/container/list/cons_fwd.hpp>
  17. #include <boost/fusion/sequence/intrinsic_fwd.hpp>
  18. #include <boost/fusion/iterator/equal_to.hpp>
  19. #include <boost/fusion/iterator/deref.hpp>
  20. #include <boost/fusion/iterator/next.hpp>
  21. #include <boost/fusion/support/is_segmented.hpp>
  22. #include <boost/fusion/sequence/intrinsic/segments.hpp>
  23. // fun(seq, state, context)
  24. // seq: a non-segmented range
  25. // state: the state of the fold so far
  26. // context: the path to the current range
  27. //
  28. // returns: (state', fcontinue)
  29. namespace boost { namespace fusion
  30. {
  31. template <typename First, typename Last>
  32. struct iterator_range;
  33. template <typename Context>
  34. struct segmented_iterator;
  35. namespace result_of
  36. {
  37. template <typename Cur, typename Context>
  38. struct make_segmented_iterator
  39. {
  40. typedef
  41. iterator_range<
  42. Cur
  43. , typename result_of::end<
  44. typename remove_reference<
  45. typename add_const<
  46. typename result_of::deref<
  47. typename Context::car_type::begin_type
  48. >::type
  49. >::type
  50. >::type
  51. >::type
  52. >
  53. range_type;
  54. typedef
  55. segmented_iterator<cons<range_type, Context> >
  56. type;
  57. };
  58. }
  59. template <typename Cur, typename Context>
  60. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  61. inline typename result_of::make_segmented_iterator<Cur, Context>::type
  62. make_segmented_iterator(Cur const& cur, Context const& context)
  63. {
  64. typedef result_of::make_segmented_iterator<Cur, Context> impl_type;
  65. typedef typename impl_type::type type;
  66. typedef typename impl_type::range_type range_type;
  67. return type(cons<range_type, Context>(range_type(cur, fusion::end(*context.car.first)), context));
  68. }
  69. namespace detail
  70. {
  71. template <
  72. typename Begin
  73. , typename End
  74. , typename State
  75. , typename Context
  76. , typename Fun
  77. , bool IsEmpty
  78. >
  79. struct segmented_fold_until_iterate_skip_empty;
  80. template <
  81. typename Begin
  82. , typename End
  83. , typename State
  84. , typename Context
  85. , typename Fun
  86. , bool IsDone = result_of::equal_to<Begin, End>::type::value
  87. >
  88. struct segmented_fold_until_iterate;
  89. template <
  90. typename Sequence
  91. , typename State
  92. , typename Context
  93. , typename Fun
  94. , bool IsSegmented = traits::is_segmented<Sequence>::type::value
  95. >
  96. struct segmented_fold_until_impl;
  97. template <typename Segments, typename State, typename Context, typename Fun>
  98. struct segmented_fold_until_on_segments;
  99. //auto push_context(cur, end, context)
  100. //{
  101. // return push_back(context, segment_sequence(iterator_range(cur, end)));
  102. //}
  103. template <typename Cur, typename End, typename Context>
  104. struct push_context
  105. {
  106. typedef iterator_range<Cur, End> range_type;
  107. typedef cons<range_type, Context> type;
  108. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  109. static type call(Cur const& cur, End const& end, Context const& context)
  110. {
  111. return cons<range_type, Context>(range_type(cur, end), context);
  112. }
  113. };
  114. //auto make_segmented_iterator(cur, end, context)
  115. //{
  116. // return segmented_iterator(push_context(cur, end, context));
  117. //}
  118. //
  119. //auto segmented_fold_until_impl(seq, state, context, fun)
  120. //{
  121. // if (is_segmented(seq))
  122. // {
  123. // segmented_fold_until_on_segments(segments(seq), state, context, fun);
  124. // }
  125. // else
  126. // {
  127. // return fun(seq, state, context);
  128. // }
  129. //}
  130. template <
  131. typename Sequence
  132. , typename State
  133. , typename Context
  134. , typename Fun
  135. , bool IsSegmented
  136. >
  137. struct segmented_fold_until_impl
  138. {
  139. typedef
  140. segmented_fold_until_on_segments<
  141. typename remove_reference<
  142. typename add_const<
  143. typename result_of::segments<Sequence>::type
  144. >::type
  145. >::type
  146. , State
  147. , Context
  148. , Fun
  149. >
  150. impl;
  151. typedef typename impl::type type;
  152. typedef typename impl::continue_type continue_type;
  153. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  154. static type call(Sequence& seq, State const& state, Context const& context, Fun const& fun)
  155. {
  156. return impl::call(fusion::segments(seq), state, context, fun);
  157. }
  158. };
  159. template <
  160. typename Sequence
  161. , typename State
  162. , typename Context
  163. , typename Fun
  164. >
  165. struct segmented_fold_until_impl<Sequence, State, Context, Fun, false>
  166. {
  167. typedef
  168. typename Fun::template apply<Sequence, State, Context>
  169. apply_type;
  170. typedef typename apply_type::type type;
  171. typedef typename apply_type::continue_type continue_type;
  172. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  173. static type call(Sequence& seq, State const& state, Context const& context, Fun const& fun)
  174. {
  175. return apply_type::call(seq, state, context, fun);
  176. }
  177. };
  178. //auto segmented_fold_until_on_segments(segs, state, context, fun)
  179. //{
  180. // auto cur = begin(segs), end = end(segs);
  181. // for (; cur != end; ++cur)
  182. // {
  183. // if (empty(*cur))
  184. // continue;
  185. // auto context` = push_context(cur, end, context);
  186. // state = segmented_fold_until_impl(*cur, state, context`, fun);
  187. // if (!second(state))
  188. // return state;
  189. // }
  190. //}
  191. template <typename Apply>
  192. struct continue_wrap
  193. {
  194. typedef typename Apply::continue_type type;
  195. };
  196. template <typename Begin, typename End, typename State, typename Context, typename Fun, bool IsEmpty>
  197. struct segmented_fold_until_iterate_skip_empty
  198. {
  199. // begin != end and !empty(*begin)
  200. typedef
  201. push_context<Begin, End, Context>
  202. push_context_impl;
  203. typedef
  204. typename push_context_impl::type
  205. next_context_type;
  206. typedef
  207. segmented_fold_until_impl<
  208. typename remove_reference<
  209. typename add_const<
  210. typename result_of::deref<Begin>::type
  211. >::type
  212. >::type
  213. , State
  214. , next_context_type
  215. , Fun
  216. >
  217. fold_recurse_impl;
  218. typedef
  219. typename fold_recurse_impl::type
  220. next_state_type;
  221. typedef
  222. segmented_fold_until_iterate<
  223. typename result_of::next<Begin>::type
  224. , End
  225. , next_state_type
  226. , Context
  227. , Fun
  228. >
  229. next_iteration_impl;
  230. typedef
  231. typename mpl::eval_if<
  232. typename fold_recurse_impl::continue_type
  233. , next_iteration_impl
  234. , mpl::identity<next_state_type>
  235. >::type
  236. type;
  237. typedef
  238. typename mpl::eval_if<
  239. typename fold_recurse_impl::continue_type
  240. , continue_wrap<next_iteration_impl>
  241. , mpl::identity<mpl::false_>
  242. >::type
  243. continue_type;
  244. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  245. static type call(Begin const& beg, End const& end, State const& state
  246. , Context const& context, Fun const& fun)
  247. {
  248. return call(beg, end, state, context, fun, typename fold_recurse_impl::continue_type());
  249. }
  250. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  251. static type call(Begin const& beg, End const& end, State const& state
  252. , Context const& context, Fun const& fun, mpl::true_) // continue
  253. {
  254. return next_iteration_impl::call(
  255. fusion::next(beg)
  256. , end
  257. , fold_recurse_impl::call(
  258. *beg
  259. , state
  260. , push_context_impl::call(beg, end, context)
  261. , fun)
  262. , context
  263. , fun);
  264. }
  265. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  266. static type call(Begin const& beg, End const& end, State const& state
  267. , Context const& context, Fun const& fun, mpl::false_) // break
  268. {
  269. return fold_recurse_impl::call(
  270. *beg
  271. , state
  272. , push_context_impl::call(beg, end, context)
  273. , fun);
  274. }
  275. };
  276. template <typename Begin, typename End, typename State, typename Context, typename Fun>
  277. struct segmented_fold_until_iterate_skip_empty<Begin, End, State, Context, Fun, true>
  278. {
  279. typedef
  280. segmented_fold_until_iterate<
  281. typename result_of::next<Begin>::type
  282. , End
  283. , State
  284. , Context
  285. , Fun
  286. >
  287. impl;
  288. typedef typename impl::type type;
  289. typedef typename impl::continue_type continue_type;
  290. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  291. static type call(Begin const& beg, End const& end, State const& state
  292. , Context const& context, Fun const& fun)
  293. {
  294. return impl::call(fusion::next(beg), end, state, context, fun);
  295. }
  296. };
  297. template <typename Begin, typename End, typename State, typename Context, typename Fun, bool IsDone>
  298. struct segmented_fold_until_iterate
  299. {
  300. typedef
  301. typename result_of::empty<
  302. typename remove_reference<
  303. typename result_of::deref<Begin>::type
  304. >::type
  305. >::type
  306. empty_type;
  307. typedef
  308. segmented_fold_until_iterate_skip_empty<Begin, End, State, Context, Fun, empty_type::value>
  309. impl;
  310. typedef typename impl::type type;
  311. typedef typename impl::continue_type continue_type;
  312. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  313. static type call(Begin const& beg, End const& end, State const& state
  314. , Context const& context, Fun const& fun)
  315. {
  316. return impl::call(beg, end, state, context, fun);
  317. }
  318. };
  319. template <typename Begin, typename End, typename State, typename Context, typename Fun>
  320. struct segmented_fold_until_iterate<Begin, End, State, Context, Fun, true>
  321. {
  322. typedef State type;
  323. typedef mpl::true_ continue_type;
  324. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  325. static type call(Begin const&, End const&, State const& state
  326. , Context const&, Fun const&)
  327. {
  328. return state;
  329. }
  330. };
  331. template <typename Segments, typename State, typename Context, typename Fun>
  332. struct segmented_fold_until_on_segments
  333. {
  334. typedef
  335. segmented_fold_until_iterate<
  336. typename result_of::begin<Segments>::type
  337. , typename result_of::end<Segments>::type
  338. , State
  339. , Context
  340. , Fun
  341. >
  342. impl;
  343. typedef typename impl::type type;
  344. typedef typename impl::continue_type continue_type;
  345. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  346. static type call(Segments& segs, State const& state, Context const& context, Fun const& fun)
  347. {
  348. return impl::call(fusion::begin(segs), fusion::end(segs), state, context, fun);
  349. }
  350. };
  351. }
  352. }}
  353. #endif