loop unrolling for fusion iteration algorithms

[SVN r37806]
This commit is contained in:
Dan Marsden
2007-05-28 23:12:53 +00:00
parent 2c7e484787
commit b935ea84a9
5 changed files with 324 additions and 121 deletions

View File

@ -7,9 +7,7 @@
#if !defined(FUSION_ACCUMULATE_09172005_1032) #if !defined(FUSION_ACCUMULATE_09172005_1032)
#define FUSION_ACCUMULATE_09172005_1032 #define FUSION_ACCUMULATE_09172005_1032
#include <boost/fusion/algorithm/iteration/detail/fold.hpp> #include <boost/fusion/algorithm/iteration/fold.hpp>
#include <boost/fusion/iterator/equal_to.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
namespace boost { namespace fusion namespace boost { namespace fusion
{ {
@ -19,46 +17,22 @@ namespace boost { namespace fusion
{ {
template <typename Sequence, typename State, typename F> template <typename Sequence, typename State, typename F>
struct accumulate struct accumulate
{ : result_of::fold<Sequence, State, F>
typedef typename {};
detail::static_fold<
typename result_of::begin<Sequence>::type
, typename result_of::end<Sequence>::type
, State
, F
>::type
type;
};
} }
template <typename Sequence, typename State, typename F> template <typename Sequence, typename State, typename F>
inline typename result_of::accumulate<Sequence, State, F>::type inline typename result_of::accumulate<Sequence, State, F>::type
accumulate(Sequence& seq, State const& state, F const& f) accumulate(Sequence& seq, State const& state, F const& f)
{ {
return detail::fold( return fusion::fold(seq, state, f);
fusion::begin(seq)
, fusion::end(seq)
, state
, f
, result_of::equal_to<
typename result_of::begin<Sequence>::type
, typename result_of::end<Sequence>::type>()
);
} }
template <typename Sequence, typename State, typename F> template <typename Sequence, typename State, typename F>
inline typename result_of::accumulate<Sequence const, State, F>::type inline typename result_of::accumulate<Sequence const, State, F>::type
accumulate(Sequence const& seq, State const& state, F const& f) accumulate(Sequence const& seq, State const& state, F const& f)
{ {
return detail::fold( return fusion::fold(seq, state, f);
fusion::begin(seq)
, fusion::end(seq)
, state
, f
, result_of::equal_to<
typename result_of::begin<Sequence const>::type
, typename result_of::end<Sequence const>::type>()
);
} }
}} }}

View File

@ -1,11 +1,5 @@
/*============================================================================= #if !defined(BOOST_FUSION_FOLD_HPP_20070528_1253)
Copyright (c) 2001-2006 Joel de Guzman #define BOOST_FUSION_FOLD_HPP_20070528_1253
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_FOLD_05052005_1211)
#define FUSION_FOLD_05052005_1211
#include <boost/mpl/bool.hpp> #include <boost/mpl/bool.hpp>
#include <boost/mpl/apply.hpp> #include <boost/mpl/apply.hpp>
@ -16,11 +10,16 @@
#include <boost/fusion/iterator/deref.hpp> #include <boost/fusion/iterator/deref.hpp>
#include <boost/fusion/iterator/value_of.hpp> #include <boost/fusion/iterator/value_of.hpp>
#include <boost/fusion/iterator/next.hpp> #include <boost/fusion/iterator/next.hpp>
#include <boost/fusion/iterator/distance.hpp>
namespace boost { namespace fusion { namespace detail namespace boost { namespace fusion {
namespace result_of
{
template <typename Sequence, typename State, typename F>
struct fold;
}
namespace detail
{ {
// Unary arguments version
template <typename F> template <typename F>
struct apply_fold_result struct apply_fold_result
{ {
@ -66,10 +65,79 @@ namespace boost { namespace fusion { namespace detail
typedef typename result::type type; typedef typename result::type type;
}; };
template<typename I0, typename State, typename F, int N>
struct result_of_unrolled_fold;
template<int N>
struct unrolled_fold
{
template<typename I0, typename State, typename F>
static typename result_of_unrolled_fold<I0, State, F, N>::type
call(I0 const& i0, State const& state, F const& f)
{
typedef typename result_of::next<I0>::type I1;
I1 i1 = fusion::next(i0);
typedef typename result_of::next<I1>::type I2;
I2 i2 = fusion::next(i1);
typedef typename result_of::next<I2>::type I3;
I3 i3 = fusion::next(i2);
return f(*i0, f(*i1, f(*i2, unrolled_fold<N-3>::call(i3, state, f))));
}
};
template<>
struct unrolled_fold<3>
{
template<typename I0, typename State, typename F>
static typename result_of_unrolled_fold<I0, State, F, 3>::type
call(I0 const& i0, State const& state, F const& f)
{
typedef typename result_of::next<I0>::type I1;
I1 i1 = fusion::next(i0);
typedef typename result_of::next<I1>::type I2;
I2 i2 = fusion::next(i1);
return f(*i0, f(*i1, f(*i2, state)));
}
};
template<>
struct unrolled_fold<2>
{
template<typename I0, typename State, typename F>
static typename result_of_unrolled_fold<I0, State, F, 2>::type
call(I0 const& i0, State const& state, F const& f)
{
typedef typename result_of::next<I0>::type I1;
I1 i1 = fusion::next(i0);
return f(*i0, f(*i1, state));
}
};
template<>
struct unrolled_fold<1>
{
template<typename I0, typename State, typename F>
static typename result_of_unrolled_fold<I0, State, F, 1>::type
call(I0 const& i0, State const& state, F const& f)
{
return f(*i0, state);
}
};
template<>
struct unrolled_fold<0>
{
template<typename I0, typename State, typename F>
static State call(I0 const&, State const& state, F const&)
{
return state;
}
};
// terminal case // terminal case
template <typename First, typename Last, typename State, typename F> template <typename First, typename Last, typename State, typename F>
inline State const& inline State const&
fold(First const&, Last const&, State const& state, F const&, mpl::true_) linear_fold(First const&, Last const&, State const& state, F const&, mpl::true_)
{ {
return state; return state;
} }
@ -77,14 +145,14 @@ namespace boost { namespace fusion { namespace detail
// non-terminal case // non-terminal case
template <typename First, typename Last, typename State, typename F> template <typename First, typename Last, typename State, typename F>
inline typename static_fold<First, Last, State, F>::type inline typename static_fold<First, Last, State, F>::type
fold( linear_fold(
First const& first First const& first
, Last const& last , Last const& last
, State const& state , State const& state
, F const& f , F const& f
, mpl::false_) , mpl::false_)
{ {
return detail::fold( return detail::linear_fold(
fusion::next(first) fusion::next(first)
, last , last
, f(*first, state) , f(*first, state)
@ -92,7 +160,102 @@ namespace boost { namespace fusion { namespace detail
, result_of::equal_to<typename result_of::next<First>::type, Last>() , result_of::equal_to<typename result_of::next<First>::type, Last>()
); );
} }
template<typename I0, typename State, typename F, int N>
struct result_of_unrolled_fold
{
typedef typename result_of::next<I0>::type I1;
typedef typename result_of::next<I1>::type I2;
typedef typename result_of::next<I2>::type I3;
typedef typename result_of::next<I3>::type I4;
typedef typename result_of_unrolled_fold<I4, State, F, N-4>::type Rest;
typedef typename fold_apply<I3, Rest, F>::type Rest2;
typedef typename fold_apply<I2, Rest2, F>::type Rest3;
typedef typename fold_apply<I1, Rest3, F>::type Rest4;
typedef typename fold_apply<I0, Rest4, F>::type type;
};
template<typename I0, typename State, typename F>
struct result_of_unrolled_fold<I0, State, F, 3>
{
typedef typename result_of::next<I0>::type I1;
typedef typename result_of::next<I1>::type I2;
typedef typename fold_apply<I2, State, F>::type Rest;
typedef typename fold_apply<I1, Rest, F>::type Rest2;
typedef typename fold_apply<I0, Rest2, F>::type type;
};
template<typename I0, typename State, typename F>
struct result_of_unrolled_fold<I0, State, F, 2>
{
typedef typename result_of::next<I0>::type I1;
typedef typename fold_apply<I1, State, F>::type Rest;
typedef typename fold_apply<I0, Rest, F>::type type;
};
template<typename I0, typename State, typename F>
struct result_of_unrolled_fold<I0, State, F, 1>
{
typedef typename fold_apply<I0, State, F>::type type;
};
template<typename I0, typename State, typename F>
struct result_of_unrolled_fold<I0, State, F, 0>
{
typedef State type;
};
template<typename Sequence, typename State, typename F, bool>
struct choose_fold;
template<typename Sequence, typename State, typename F>
struct choose_fold<Sequence, State, F, true>
{
typedef typename result_of::begin<Sequence>::type begin;
typedef typename result_of::end<Sequence>::type end;
typedef typename result_of_unrolled_fold<
begin, State, F, result_of::distance<begin, end>::value>::type type;
};
template<typename Sequence, typename State, typename F>
struct choose_fold<Sequence, State, F, false>
{
typedef typename
detail::static_fold<
typename result_of::begin<Sequence>::type
, typename result_of::end<Sequence>::type
, State
, F
>::type
type;
};
template<typename Sequence, typename State, typename F, typename Tag>
typename result_of::fold<Sequence, State, F>::type
fold(Sequence& seq, State const& state, F const& f, Tag)
{
return linear_fold(
fusion::begin(seq)
, fusion::end(seq)
, state
, f
, result_of::equal_to<
typename result_of::begin<Sequence>::type
, typename result_of::end<Sequence>::type>()
);
}
template<typename Sequence, typename State, typename F>
typename result_of::fold<Sequence, State, F>::type
fold(Sequence& seq, State const& state, F const& f, random_access_traversal_tag)
{
typedef typename result_of::begin<Sequence>::type begin;
typedef typename result_of::end<Sequence>::type end;
return unrolled_fold<result_of::distance<begin, end>::value>::call(
fusion::begin(seq)
, state
, f);
}
}}} }}}
#endif #endif

View File

@ -7,28 +7,124 @@
#if !defined(FUSION_FOR_EACH_05052005_1028) #if !defined(FUSION_FOR_EACH_05052005_1028)
#define FUSION_FOR_EACH_05052005_1028 #define FUSION_FOR_EACH_05052005_1028
#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/distance.hpp>
#include <boost/mpl/bool.hpp>
namespace boost { namespace fusion { namespace detail namespace boost { namespace fusion {
namespace detail
{ {
template <typename First, typename Last, typename F> template <typename First, typename Last, typename F>
inline void inline void
for_each(First const&, Last const&, F const&, mpl::true_) for_each_linear(First const&, Last const&, F const&, mpl::true_)
{ {
} }
template <typename First, typename Last, typename F> template <typename First, typename Last, typename F>
inline void inline void
for_each(First const& first, Last const& last, F const& f, mpl::false_) for_each_linear(First const& first, Last const& last, F const& f, mpl::false_)
{ {
f(*first); f(*first);
detail::for_each(fusion::next(first), last, f detail::for_each_linear(fusion::next(first), last, f,
, result_of::equal_to<typename result_of::next<First>::type, Last>()); result_of::equal_to<typename result_of::next<First>::type, Last>());
}
template <typename Sequence, typename F, typename Tag>
inline void
for_each(Sequence& seq, F const& f, Tag)
{
detail::for_each_linear(
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 for_each_unrolled
{
template<typename I0, typename F>
static void call(I0 const& i0, F const& f)
{
f(*i0);
typedef typename result_of::next<I0>::type I1;
I1 i1(fusion::next(i0));
f(*i1);
typedef typename result_of::next<I1>::type I2;
I2 i2(fusion::next(i1));
f(*i2);
typedef typename result_of::next<I2>::type I3;
I3 i3(fusion::next(i2));
f(*i3);
for_each_unrolled<N-4>::call(fusion::next(i3), f);
}
};
template<>
struct for_each_unrolled<3>
{
template<typename I0, typename F>
static void call(I0 const& i0, F const& f)
{
f(*i0);
typedef typename result_of::next<I0>::type I1;
I1 i1(fusion::next(i0));
f(*i1);
typedef typename result_of::next<I1>::type I2;
I2 i2(fusion::next(i1));
f(*i2);
}
};
template<>
struct for_each_unrolled<2>
{
template<typename I0, typename F>
static void call(I0 const& i0, F const& f)
{
f(*i0);
typedef typename result_of::next<I0>::type I1;
I1 i1(fusion::next(i0));
f(*i1);
}
};
template<>
struct for_each_unrolled<1>
{
template<typename I0, typename F>
static void call(I0 const& i0, F const& f)
{
f(*i0);
}
};
template<>
struct for_each_unrolled<0>
{
template<typename It, typename F>
static void call(It const&, F const&)
{
}
};
template <typename Sequence, typename F>
inline void
for_each(Sequence& seq, F const& f, random_access_traversal_tag)
{
typedef typename result_of::begin<Sequence>::type begin;
typedef typename result_of::end<Sequence>::type end;
for_each_unrolled<result_of::distance<begin, end>::value>::call(fusion::begin(seq), f);
} }
}}} }}}
#endif #endif

View File

@ -1,65 +1,46 @@
/*============================================================================= /*=============================================================================
Copyright (c) 2001-2006 Joel de Guzman Copyright (c) 2001-2007 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_FOLD_05052005_1214) #if !defined(BOOST_FUSION_FOLD_05052005_1214)
#define FUSION_FOLD_05052005_1214 #define BOOST_FUSION_FOLD_05052005_1214
#include <boost/fusion/algorithm/iteration/detail/fold.hpp> #include <boost/fusion/algorithm/iteration/detail/fold.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp> #include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/iterator/equal_to.hpp> #include <boost/fusion/support/category_of.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
namespace boost { namespace fusion namespace boost { namespace fusion {
{
struct void_; struct random_access_traversal_tag;
namespace result_of namespace result_of
{ {
template <typename Sequence, typename State, typename F> template <typename Sequence, typename State, typename F>
struct fold struct fold
{ : fusion::detail::choose_fold<
typedef typename Sequence, State, F
detail::static_fold< , is_base_of<random_access_traversal_tag, typename traits::category_of<Sequence>::type>::value>
typename result_of::begin<Sequence>::type {};
, typename result_of::end<Sequence>::type
, State
, F
>::type
type;
};
} }
template <typename Sequence, typename State, typename F> template <typename Sequence, typename State, typename F>
inline typename result_of::fold<Sequence, State, F>::type inline typename result_of::fold<Sequence, State, F>::type
fold(Sequence& seq, State const& state, F const& f) fold(Sequence& seq, State const& state, F const& f)
{ {
return detail::fold( return detail::fold(seq, state, f, typename traits::category_of<Sequence>::type());
fusion::begin(seq)
, fusion::end(seq)
, state
, f
, result_of::equal_to<
typename result_of::begin<Sequence>::type
, typename result_of::end<Sequence>::type>()
);
} }
template <typename Sequence, typename State, typename F> template <typename Sequence, typename State, typename F>
inline typename result_of::fold<Sequence const, State, F>::type inline typename result_of::fold<Sequence const, State, F>::type
fold(Sequence const& seq, State const& state, F const& f) fold(Sequence const& seq, State const& state, F const& f)
{ {
return detail::fold( return detail::fold(seq, state, f, typename traits::category_of<Sequence>::type());
fusion::begin(seq)
, fusion::end(seq)
, state
, f
, result_of::equal_to<
typename result_of::begin<Sequence const>::type
, typename result_of::end<Sequence const>::type>()
);
} }
}} }}

View File

@ -1,19 +1,19 @@
/*============================================================================= /*=============================================================================
Copyright (c) 2001-2006 Joel de Guzman Copyright (c) 2001-2007 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_FOR_EACH_05052005_1027) #if !defined(BOOST_FUSION_FOR_EACH_20070527_0943)
#define FUSION_FOR_EACH_05052005_1027 #define BOOST_FUSION_FOR_EACH_20070527_0943
#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/iteration/detail/for_each.hpp> #include <boost/fusion/algorithm/iteration/detail/for_each.hpp>
namespace boost { namespace fusion #include <boost/fusion/support/category_of.hpp>
{
namespace boost { namespace fusion {
namespace result_of namespace result_of
{ {
template <typename Sequence, typename F> template <typename Sequence, typename F>
@ -23,32 +23,21 @@ namespace boost { namespace fusion
}; };
} }
struct random_access_traversal_tag;
template <typename Sequence, typename F> template <typename Sequence, typename F>
inline void inline void
for_each(Sequence& seq, F const& f) for_each(Sequence& seq, F const& f)
{ {
detail::for_each( detail::for_each(seq, f, typename traits::category_of<Sequence>::type());
fusion::begin(seq)
, fusion::end(seq)
, f
, result_of::equal_to<
typename result_of::begin<Sequence>::type
, typename result_of::end<Sequence>::type>());
} }
template <typename Sequence, typename F> template <typename Sequence, typename F>
inline void inline void
for_each(Sequence const& seq, F const& f) for_each(Sequence const& seq, F const& f)
{ {
detail::for_each( detail::for_each(seq, f, typename traits::category_of<Sequence>::type());
fusion::begin(seq)
, fusion::end(seq)
, f
, result_of::equal_to<
typename result_of::begin<Sequence const>::type
, typename result_of::end<Sequence const>::type>());
} }
}} }}
#endif #endif