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