File indexing completed on 2025-01-18 09:31:09
0001
0002
0003
0004
0005
0006
0007
0008 #if !defined(BOOST_FUSION_COUNT_IF_09162005_0141)
0009 #define BOOST_FUSION_COUNT_IF_09162005_0141
0010
0011 #include <boost/fusion/support/config.hpp>
0012 #include <boost/mpl/bool.hpp>
0013 #include <boost/fusion/sequence/intrinsic/begin.hpp>
0014 #include <boost/fusion/sequence/intrinsic/end.hpp>
0015 #include <boost/fusion/iterator/equal_to.hpp>
0016 #include <boost/fusion/iterator/next.hpp>
0017 #include <boost/fusion/iterator/deref.hpp>
0018 #include <boost/fusion/iterator/equal_to.hpp>
0019 #include <boost/fusion/iterator/distance.hpp>
0020 #include <boost/fusion/iterator/advance.hpp>
0021
0022 namespace boost { namespace fusion {
0023 struct random_access_traversal_tag;
0024 namespace detail
0025 {
0026 template <typename First, typename Last, typename F>
0027 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0028 inline int
0029 linear_count_if(First const&, Last const&, F const&, mpl::true_)
0030 {
0031 return 0;
0032 }
0033
0034 template <typename First, typename Last, typename F>
0035 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0036 inline int
0037 linear_count_if(First const& first, Last const& last, F& f, mpl::false_)
0038 {
0039 int n =
0040 detail::linear_count_if(
0041 fusion::next(first)
0042 , last
0043 , f
0044 , result_of::equal_to<typename result_of::next<First>::type, Last>());
0045 if (f(*first))
0046 ++n;
0047 return n;
0048 }
0049
0050 template <typename Sequence, typename F, typename Tag>
0051 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0052 inline int
0053 count_if(Sequence const& seq, F f, Tag)
0054 {
0055 return detail::linear_count_if(
0056 fusion::begin(seq)
0057 , fusion::end(seq)
0058 , f
0059 , result_of::equal_to<
0060 typename result_of::begin<Sequence>::type
0061 , typename result_of::end<Sequence>::type>());
0062 }
0063
0064 template<int n>
0065 struct unrolled_count_if
0066 {
0067 template<typename I0, typename F>
0068 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0069 static int call(I0 const& i0, F f)
0070 {
0071 int ct = unrolled_count_if<n-4>::
0072 call(fusion::advance_c<4>(i0), f);
0073 if(f(*i0))
0074 ++ct;
0075
0076 typedef typename result_of::next<I0>::type I1;
0077 I1 i1(fusion::next(i0));
0078 if(f(*i1))
0079 ++ct;
0080
0081 typedef typename result_of::next<I1>::type I2;
0082 I2 i2(fusion::next(i1));
0083 if(f(*i2))
0084 ++ct;
0085
0086 typedef typename result_of::next<I2>::type I3;
0087 I3 i3(fusion::next(i2));
0088 if(f(*i3))
0089 ++ct;
0090
0091 return ct;
0092 }
0093 };
0094
0095 template<>
0096 struct unrolled_count_if<3>
0097 {
0098 template<typename I0, typename F>
0099 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0100 static int call(I0 const& i0, F f)
0101 {
0102 int ct = 0;
0103 if(f(*i0))
0104 ++ct;
0105
0106 typedef typename result_of::next<I0>::type I1;
0107 I1 i1(fusion::next(i0));
0108 if(f(*i1))
0109 ++ct;
0110
0111 typedef typename result_of::next<I1>::type I2;
0112 I2 i2(fusion::next(i1));
0113 if(f(*i2))
0114 ++ct;
0115
0116 return ct;
0117 }
0118 };
0119
0120 template<>
0121 struct unrolled_count_if<2>
0122 {
0123 template<typename I0, typename F>
0124 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0125 static int call(I0 const& i0, F f)
0126 {
0127 int ct = 0;
0128
0129 if(f(*i0))
0130 ++ct;
0131
0132 typedef typename result_of::next<I0>::type I1;
0133 I1 i1(fusion::next(i0));
0134 if(f(*i1))
0135 ++ct;
0136
0137 return ct;
0138 }
0139 };
0140
0141 template<>
0142 struct unrolled_count_if<1>
0143 {
0144 template<typename I0, typename F>
0145 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0146 static int call(I0 const& i0, F f)
0147 {
0148 int ct = 0;
0149 if(f(*i0))
0150 ++ct;
0151 return ct;
0152 }
0153 };
0154
0155
0156 template<>
0157 struct unrolled_count_if<0>
0158 {
0159 template<typename I0, typename F>
0160 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0161 static int call(I0 const&, F)
0162 {
0163 return 0;
0164 }
0165 };
0166
0167 template <typename Sequence, typename F>
0168 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0169 inline int
0170 count_if(Sequence const& seq, F f, random_access_traversal_tag)
0171 {
0172 typedef typename result_of::begin<Sequence>::type begin;
0173 typedef typename result_of::end<Sequence>::type end;
0174 return detail::unrolled_count_if<result_of::distance<begin, end>::type::value>::
0175 call(fusion::begin(seq), f);
0176 }
0177 }}}
0178
0179 #endif
0180