count_if.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2007 Dan Marsden
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #if !defined(BOOST_FUSION_COUNT_IF_09162005_0141)
  8. #define BOOST_FUSION_COUNT_IF_09162005_0141
  9. #include <boost/fusion/support/config.hpp>
  10. #include <boost/mpl/bool.hpp>
  11. #include <boost/fusion/sequence/intrinsic/begin.hpp>
  12. #include <boost/fusion/sequence/intrinsic/end.hpp>
  13. #include <boost/fusion/iterator/equal_to.hpp>
  14. #include <boost/fusion/iterator/next.hpp>
  15. #include <boost/fusion/iterator/deref.hpp>
  16. #include <boost/fusion/iterator/equal_to.hpp>
  17. #include <boost/fusion/iterator/distance.hpp>
  18. #include <boost/fusion/iterator/advance.hpp>
  19. namespace boost { namespace fusion {
  20. struct random_access_traversal_tag;
  21. namespace detail
  22. {
  23. template <typename First, typename Last, typename F>
  24. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  25. inline int
  26. linear_count_if(First const&, Last const&, F const&, mpl::true_)
  27. {
  28. return 0;
  29. }
  30. template <typename First, typename Last, typename F>
  31. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  32. inline int
  33. linear_count_if(First const& first, Last const& last, F& f, mpl::false_)
  34. {
  35. int n =
  36. detail::linear_count_if(
  37. fusion::next(first)
  38. , last
  39. , f
  40. , result_of::equal_to<typename result_of::next<First>::type, Last>());
  41. if (f(*first))
  42. ++n;
  43. return n;
  44. }
  45. template <typename Sequence, typename F, typename Tag>
  46. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  47. inline int
  48. count_if(Sequence const& seq, F f, Tag)
  49. {
  50. return detail::linear_count_if(
  51. fusion::begin(seq)
  52. , fusion::end(seq)
  53. , f
  54. , result_of::equal_to<
  55. typename result_of::begin<Sequence>::type
  56. , typename result_of::end<Sequence>::type>());
  57. }
  58. template<int n>
  59. struct unrolled_count_if
  60. {
  61. template<typename I0, typename F>
  62. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  63. static int call(I0 const& i0, F f)
  64. {
  65. int ct = unrolled_count_if<n-4>::
  66. call(fusion::advance_c<4>(i0), f);
  67. if(f(*i0))
  68. ++ct;
  69. typedef typename result_of::next<I0>::type I1;
  70. I1 i1(fusion::next(i0));
  71. if(f(*i1))
  72. ++ct;
  73. typedef typename result_of::next<I1>::type I2;
  74. I2 i2(fusion::next(i1));
  75. if(f(*i2))
  76. ++ct;
  77. typedef typename result_of::next<I2>::type I3;
  78. I3 i3(fusion::next(i2));
  79. if(f(*i3))
  80. ++ct;
  81. return ct;
  82. }
  83. };
  84. template<>
  85. struct unrolled_count_if<3>
  86. {
  87. template<typename I0, typename F>
  88. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  89. static int call(I0 const& i0, F f)
  90. {
  91. int ct = 0;
  92. if(f(*i0))
  93. ++ct;
  94. typedef typename result_of::next<I0>::type I1;
  95. I1 i1(fusion::next(i0));
  96. if(f(*i1))
  97. ++ct;
  98. typedef typename result_of::next<I1>::type I2;
  99. I2 i2(fusion::next(i1));
  100. if(f(*i2))
  101. ++ct;
  102. return ct;
  103. }
  104. };
  105. template<>
  106. struct unrolled_count_if<2>
  107. {
  108. template<typename I0, typename F>
  109. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  110. static int call(I0 const& i0, F f)
  111. {
  112. int ct = 0;
  113. if(f(*i0))
  114. ++ct;
  115. typedef typename result_of::next<I0>::type I1;
  116. I1 i1(fusion::next(i0));
  117. if(f(*i1))
  118. ++ct;
  119. return ct;
  120. }
  121. };
  122. template<>
  123. struct unrolled_count_if<1>
  124. {
  125. template<typename I0, typename F>
  126. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  127. static int call(I0 const& i0, F f)
  128. {
  129. int ct = 0;
  130. if(f(*i0))
  131. ++ct;
  132. return ct;
  133. }
  134. };
  135. template<>
  136. struct unrolled_count_if<0>
  137. {
  138. template<typename I0, typename F>
  139. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  140. static int call(I0 const&, F)
  141. {
  142. return 0;
  143. }
  144. };
  145. template <typename Sequence, typename F>
  146. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  147. inline int
  148. count_if(Sequence const& seq, F f, random_access_traversal_tag)
  149. {
  150. typedef typename result_of::begin<Sequence>::type begin;
  151. typedef typename result_of::end<Sequence>::type end;
  152. return detail::unrolled_count_if<result_of::distance<begin, end>::type::value>::
  153. call(fusion::begin(seq), f);
  154. }
  155. }}}
  156. #endif