diff --git a/include/boost/fusion/algorithm/query/count.hpp b/include/boost/fusion/algorithm/query/count.hpp index 88289301..27e3370e 100644 --- a/include/boost/fusion/algorithm/query/count.hpp +++ b/include/boost/fusion/algorithm/query/count.hpp @@ -1,19 +1,15 @@ /*============================================================================= Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ -#if !defined(FUSION_COUNT_09162005_0150) -#define FUSION_COUNT_09162005_0150 +#if !defined(BOOST_FUSION_COUNT_09162005_0150) +#define BOOST_FUSION_COUNT_09162005_0150 -#include -#include -#include -#include -#include +#include #include -#include namespace boost { namespace fusion { @@ -31,13 +27,7 @@ namespace boost { namespace fusion count(Sequence const& seq, T const& x) { detail::count_compare f(x); - return detail::count_if( - fusion::begin(seq) - , fusion::end(seq) - , f - , result_of::equal_to< - typename result_of::begin::type - , typename result_of::end::type>()); + return fusion::count_if(seq, f); } }} diff --git a/include/boost/fusion/algorithm/query/count_if.hpp b/include/boost/fusion/algorithm/query/count_if.hpp index 43531c67..a080b3b2 100644 --- a/include/boost/fusion/algorithm/query/count_if.hpp +++ b/include/boost/fusion/algorithm/query/count_if.hpp @@ -1,16 +1,15 @@ /*============================================================================= Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 Dan Marsden Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ -#if !defined(FUSION_COUNT_IF_09162005_0137) -#define FUSION_COUNT_IF_09162005_0137 +#if !defined(BOOST_FUSION_COUNT_IF_09162005_0137) +#define BOOST_FUSION_COUNT_IF_09162005_0137 -#include -#include -#include #include +#include namespace boost { namespace fusion { @@ -28,12 +27,7 @@ namespace boost { namespace fusion count_if(Sequence const& seq, F f) { return detail::count_if( - fusion::begin(seq) - , fusion::end(seq) - , f - , result_of::equal_to< - typename result_of::begin::type - , typename result_of::end::type>()); + seq, f, typename traits::category_of::type()); } }} diff --git a/include/boost/fusion/algorithm/query/detail/count_if.hpp b/include/boost/fusion/algorithm/query/detail/count_if.hpp index c4d612a8..d1f6ef7e 100644 --- a/include/boost/fusion/algorithm/query/detail/count_if.hpp +++ b/include/boost/fusion/algorithm/query/detail/count_if.hpp @@ -1,41 +1,169 @@ /*============================================================================= Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 Dan Marsden Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ -#if !defined(FUSION_COUNT_IF_09162005_0141) -#define FUSION_COUNT_IF_09162005_0141 +#if !defined(BOOST_FUSION_COUNT_IF_09162005_0141) +#define BOOST_FUSION_COUNT_IF_09162005_0141 #include +#include +#include #include #include #include +#include +#include +#include -namespace boost { namespace fusion { namespace detail +namespace boost { namespace fusion { + struct random_access_traversal_tag; +namespace detail { template inline int - count_if(First const&, Last const&, F const&, mpl::true_) + linear_count_if(First const&, Last const&, F const&, mpl::true_) { return 0; } template inline int - count_if(First const& first, Last const& last, F& f, mpl::false_) + linear_count_if(First const& first, Last const& last, F& f, mpl::false_) { - typename result_of::deref::type x = *first; int n = - detail::count_if( + detail::linear_count_if( fusion::next(first) , last , f , result_of::equal_to::type, Last>()); - if (f(x)) + if (f(*first)) ++n; return n; } + + template + inline int + count_if(Sequence const& seq, F f, Tag) + { + return detail::linear_count_if( + fusion::begin(seq) + , fusion::end(seq) + , f + , result_of::equal_to< + typename result_of::begin::type + , typename result_of::end::type>()); + } + + template + struct unrolled_count_if + { + template + static int call(I0 const& i0, F f) + { + int ct = unrolled_count_if:: + call(fusion::advance_c<4>(i0), f); + if(f(*i0)) + ++ct; + + typedef typename result_of::next::type I1; + I1 i1(fusion::next(i0)); + if(f(*i1)) + ++ct; + + typedef typename result_of::next::type I2; + I2 i2(fusion::next(i1)); + if(f(*i2)) + ++ct; + + typedef typename result_of::next::type I3; + I3 i3(fusion::next(i2)); + if(f(*i3)) + ++ct; + + return ct; + } + }; + + template<> + struct unrolled_count_if<3> + { + template + static int call(I0 const& i0, F f) + { + int ct = 0; + if(f(*i0)) + ++ct; + + typedef typename result_of::next::type I1; + I1 i1(fusion::next(i0)); + if(f(*i1)) + ++ct; + + typedef typename result_of::next::type I2; + I2 i2(fusion::next(i1)); + if(f(*i2)) + ++ct; + + return ct; + } + }; + + template<> + struct unrolled_count_if<2> + { + template + static int call(I0 const& i0, F f) + { + int ct = 0; + + if(f(*i0)) + ++ct; + + typedef typename result_of::next::type I1; + I1 i1(fusion::next(i0)); + if(f(*i1)) + ++ct; + + return ct; + } + }; + + template<> + struct unrolled_count_if<1> + { + template + static int call(I0 const& i0, F f) + { + int ct = 0; + if(f(*i0)) + ++ct; + return ct; + } + }; + + + template<> + struct unrolled_count_if<0> + { + template + static int call(I0 const&, F) + { + return 0; + } + }; + + template + inline int + count_if(Sequence const& seq, F f, random_access_traversal_tag) + { + typedef typename result_of::begin::type begin; + typedef typename result_of::end::type end; + return detail::unrolled_count_if::value>:: + call(fusion::begin(seq), f); + } }}} #endif