loop unrolling count(_if)

[SVN r37875]
This commit is contained in:
Dan Marsden
2007-06-02 21:48:14 +00:00
parent b33ce64895
commit 40524cfda1
3 changed files with 146 additions and 34 deletions

View File

@ -1,19 +1,15 @@
/*============================================================================= /*=============================================================================
Copyright (c) 2001-2006 Joel de Guzman Copyright (c) 2001-2006 Joel de Guzman
Copyright (c) 2007
Distributed under the Boost Software License, Version 1.0. (See accompanying 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) file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/ ==============================================================================*/
#if !defined(FUSION_COUNT_09162005_0150) #if !defined(BOOST_FUSION_COUNT_09162005_0150)
#define FUSION_COUNT_09162005_0150 #define BOOST_FUSION_COUNT_09162005_0150
#include <boost/fusion/support/detail/as_fusion_element.hpp> #include <boost/fusion/algorithm/query/count_if.hpp>
#include <boost/fusion/sequence/intrinsic/begin.hpp>
#include <boost/fusion/sequence/intrinsic/end.hpp>
#include <boost/fusion/iterator/equal_to.hpp>
#include <boost/fusion/algorithm/query/detail/count_if.hpp>
#include <boost/fusion/algorithm/query/detail/count.hpp> #include <boost/fusion/algorithm/query/detail/count.hpp>
#include <boost/fusion/support/detail/access.hpp>
namespace boost { namespace fusion namespace boost { namespace fusion
{ {
@ -31,13 +27,7 @@ namespace boost { namespace fusion
count(Sequence const& seq, T const& x) count(Sequence const& seq, T const& x)
{ {
detail::count_compare<T> f(x); detail::count_compare<T> f(x);
return detail::count_if( return fusion::count_if(seq, f);
fusion::begin(seq)
, fusion::end(seq)
, f
, result_of::equal_to<
typename result_of::begin<Sequence>::type
, typename result_of::end<Sequence>::type>());
} }
}} }}

View File

@ -1,16 +1,15 @@
/*============================================================================= /*=============================================================================
Copyright (c) 2001-2006 Joel de Guzman Copyright (c) 2001-2006 Joel de Guzman
Copyright (c) 2007 Dan Marsden
Distributed under the Boost Software License, Version 1.0. (See accompanying 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) file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/ ==============================================================================*/
#if !defined(FUSION_COUNT_IF_09162005_0137) #if !defined(BOOST_FUSION_COUNT_IF_09162005_0137)
#define FUSION_COUNT_IF_09162005_0137 #define BOOST_FUSION_COUNT_IF_09162005_0137
#include <boost/fusion/sequence/intrinsic/begin.hpp>
#include <boost/fusion/sequence/intrinsic/end.hpp>
#include <boost/fusion/iterator/equal_to.hpp>
#include <boost/fusion/algorithm/query/detail/count_if.hpp> #include <boost/fusion/algorithm/query/detail/count_if.hpp>
#include <boost/fusion/support/category_of.hpp>
namespace boost { namespace fusion namespace boost { namespace fusion
{ {
@ -28,12 +27,7 @@ namespace boost { namespace fusion
count_if(Sequence const& seq, F f) count_if(Sequence const& seq, F f)
{ {
return detail::count_if( return detail::count_if(
fusion::begin(seq) seq, f, typename traits::category_of<Sequence>::type());
, fusion::end(seq)
, f
, result_of::equal_to<
typename result_of::begin<Sequence>::type
, typename result_of::end<Sequence>::type>());
} }
}} }}

View File

@ -1,41 +1,169 @@
/*============================================================================= /*=============================================================================
Copyright (c) 2001-2006 Joel de Guzman Copyright (c) 2001-2006 Joel de Guzman
Copyright (c) 2007 Dan Marsden
Distributed under the Boost Software License, Version 1.0. (See accompanying 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) file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/ ==============================================================================*/
#if !defined(FUSION_COUNT_IF_09162005_0141) #if !defined(BOOST_FUSION_COUNT_IF_09162005_0141)
#define FUSION_COUNT_IF_09162005_0141 #define BOOST_FUSION_COUNT_IF_09162005_0141
#include <boost/mpl/bool.hpp> #include <boost/mpl/bool.hpp>
#include <boost/fusion/sequence/intrinsic/begin.hpp>
#include <boost/fusion/sequence/intrinsic/end.hpp>
#include <boost/fusion/iterator/equal_to.hpp> #include <boost/fusion/iterator/equal_to.hpp>
#include <boost/fusion/iterator/next.hpp> #include <boost/fusion/iterator/next.hpp>
#include <boost/fusion/iterator/deref.hpp> #include <boost/fusion/iterator/deref.hpp>
#include <boost/fusion/iterator/equal_to.hpp>
#include <boost/fusion/iterator/distance.hpp>
#include <boost/fusion/iterator/advance.hpp>
namespace boost { namespace fusion { namespace detail namespace boost { namespace fusion {
struct random_access_traversal_tag;
namespace detail
{ {
template <typename First, typename Last, typename F> template <typename First, typename Last, typename F>
inline int 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; return 0;
} }
template <typename First, typename Last, typename F> template <typename First, typename Last, typename F>
inline int 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<First>::type x = *first;
int n = int n =
detail::count_if( detail::linear_count_if(
fusion::next(first) fusion::next(first)
, last , last
, f , f
, result_of::equal_to<typename result_of::next<First>::type, Last>()); , result_of::equal_to<typename result_of::next<First>::type, Last>());
if (f(x)) if (f(*first))
++n; ++n;
return n; return n;
} }
template <typename Sequence, typename F, typename Tag>
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<Sequence>::type
, typename result_of::end<Sequence>::type>());
}
template<int n>
struct unrolled_count_if
{
template<typename I0, typename F>
static int call(I0 const& i0, F f)
{
int ct = unrolled_count_if<n-4>::
call(fusion::advance_c<4>(i0), f);
if(f(*i0))
++ct;
typedef typename result_of::next<I0>::type I1;
I1 i1(fusion::next(i0));
if(f(*i1))
++ct;
typedef typename result_of::next<I1>::type I2;
I2 i2(fusion::next(i1));
if(f(*i2))
++ct;
typedef typename result_of::next<I2>::type I3;
I3 i3(fusion::next(i2));
if(f(*i3))
++ct;
return ct;
}
};
template<>
struct unrolled_count_if<3>
{
template<typename I0, typename F>
static int call(I0 const& i0, F f)
{
int ct = 0;
if(f(*i0))
++ct;
typedef typename result_of::next<I0>::type I1;
I1 i1(fusion::next(i0));
if(f(*i1))
++ct;
typedef typename result_of::next<I1>::type I2;
I2 i2(fusion::next(i1));
if(f(*i2))
++ct;
return ct;
}
};
template<>
struct unrolled_count_if<2>
{
template<typename I0, typename F>
static int call(I0 const& i0, F f)
{
int ct = 0;
if(f(*i0))
++ct;
typedef typename result_of::next<I0>::type I1;
I1 i1(fusion::next(i0));
if(f(*i1))
++ct;
return ct;
}
};
template<>
struct unrolled_count_if<1>
{
template<typename I0, typename F>
static int call(I0 const& i0, F f)
{
int ct = 0;
if(f(*i0))
++ct;
return ct;
}
};
template<>
struct unrolled_count_if<0>
{
template<typename I0, typename F>
static int call(I0 const&, F)
{
return 0;
}
};
template <typename Sequence, typename F>
inline int
count_if(Sequence const& seq, F f, random_access_traversal_tag)
{
typedef typename result_of::begin<Sequence>::type begin;
typedef typename result_of::end<Sequence>::type end;
return detail::unrolled_count_if<result_of::distance<begin, end>::value>::
call(fusion::begin(seq), f);
}
}}} }}}
#endif #endif