diff --git a/include/boost/fusion/algorithm/iteration/accumulate.hpp b/include/boost/fusion/algorithm/iteration/accumulate.hpp index b22147dc..10309cc2 100644 --- a/include/boost/fusion/algorithm/iteration/accumulate.hpp +++ b/include/boost/fusion/algorithm/iteration/accumulate.hpp @@ -7,9 +7,7 @@ #if !defined(FUSION_ACCUMULATE_09172005_1032) #define FUSION_ACCUMULATE_09172005_1032 -#include -#include -#include +#include namespace boost { namespace fusion { @@ -19,46 +17,22 @@ namespace boost { namespace fusion { template struct accumulate - { - typedef typename - detail::static_fold< - typename result_of::begin::type - , typename result_of::end::type - , State - , F - >::type - type; - }; + : result_of::fold + {}; } template inline typename result_of::accumulate::type accumulate(Sequence& seq, State const& state, F const& f) { - return detail::fold( - fusion::begin(seq) - , fusion::end(seq) - , state - , f - , result_of::equal_to< - typename result_of::begin::type - , typename result_of::end::type>() - ); + return fusion::fold(seq, state, f); } template inline typename result_of::accumulate::type accumulate(Sequence const& seq, State const& state, F const& f) { - return detail::fold( - fusion::begin(seq) - , fusion::end(seq) - , state - , f - , result_of::equal_to< - typename result_of::begin::type - , typename result_of::end::type>() - ); + return fusion::fold(seq, state, f); } }} diff --git a/include/boost/fusion/algorithm/iteration/detail/fold.hpp b/include/boost/fusion/algorithm/iteration/detail/fold.hpp index 83a6eefc..af7e21f4 100644 --- a/include/boost/fusion/algorithm/iteration/detail/fold.hpp +++ b/include/boost/fusion/algorithm/iteration/detail/fold.hpp @@ -1,11 +1,5 @@ -/*============================================================================= - Copyright (c) 2001-2006 Joel de Guzman - - 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 +#if !defined(BOOST_FUSION_FOLD_HPP_20070528_1253) +#define BOOST_FUSION_FOLD_HPP_20070528_1253 #include #include @@ -16,11 +10,16 @@ #include #include #include +#include -namespace boost { namespace fusion { namespace detail +namespace boost { namespace fusion { +namespace result_of +{ + template + struct fold; +} +namespace detail { - // Unary arguments version - template struct apply_fold_result { @@ -43,11 +42,11 @@ namespace boost { namespace fusion { namespace detail struct next_result_of_fold { typedef typename - static_fold< - typename result_of::next::type - , Last - , typename fold_apply::type - , F + static_fold< + typename result_of::next::type + , Last + , typename fold_apply::type + , F >::type type; }; @@ -56,20 +55,89 @@ namespace boost { namespace fusion { namespace detail struct static_fold { typedef typename - mpl::if_< - result_of::equal_to - , mpl::identity - , next_result_of_fold - >::type + mpl::if_< + result_of::equal_to + , mpl::identity + , next_result_of_fold + >::type result; typedef typename result::type type; }; + template + struct result_of_unrolled_fold; + + template + struct unrolled_fold + { + template + static typename result_of_unrolled_fold::type + call(I0 const& i0, State const& state, F const& f) + { + typedef typename result_of::next::type I1; + I1 i1 = fusion::next(i0); + typedef typename result_of::next::type I2; + I2 i2 = fusion::next(i1); + typedef typename result_of::next::type I3; + I3 i3 = fusion::next(i2); + return f(*i0, f(*i1, f(*i2, unrolled_fold::call(i3, state, f)))); + } + }; + + template<> + struct unrolled_fold<3> + { + template + static typename result_of_unrolled_fold::type + call(I0 const& i0, State const& state, F const& f) + { + typedef typename result_of::next::type I1; + I1 i1 = fusion::next(i0); + typedef typename result_of::next::type I2; + I2 i2 = fusion::next(i1); + return f(*i0, f(*i1, f(*i2, state))); + } + }; + + template<> + struct unrolled_fold<2> + { + template + static typename result_of_unrolled_fold::type + call(I0 const& i0, State const& state, F const& f) + { + typedef typename result_of::next::type I1; + I1 i1 = fusion::next(i0); + return f(*i0, f(*i1, state)); + } + }; + + template<> + struct unrolled_fold<1> + { + template + static typename result_of_unrolled_fold::type + call(I0 const& i0, State const& state, F const& f) + { + return f(*i0, state); + } + }; + + template<> + struct unrolled_fold<0> + { + template + static State call(I0 const&, State const& state, F const&) + { + return state; + } + }; + // terminal case template 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; } @@ -77,14 +145,14 @@ namespace boost { namespace fusion { namespace detail // non-terminal case template inline typename static_fold::type - fold( + linear_fold( First const& first , Last const& last , State const& state , F const& f , mpl::false_) { - return detail::fold( + return detail::linear_fold( fusion::next(first) , last , f(*first, state) @@ -92,7 +160,102 @@ namespace boost { namespace fusion { namespace detail , result_of::equal_to::type, Last>() ); } + + template + struct result_of_unrolled_fold + { + typedef typename result_of::next::type I1; + typedef typename result_of::next::type I2; + typedef typename result_of::next::type I3; + typedef typename result_of::next::type I4; + typedef typename result_of_unrolled_fold::type Rest; + typedef typename fold_apply::type Rest2; + typedef typename fold_apply::type Rest3; + typedef typename fold_apply::type Rest4; + typedef typename fold_apply::type type; + }; + + template + struct result_of_unrolled_fold + { + typedef typename result_of::next::type I1; + typedef typename result_of::next::type I2; + typedef typename fold_apply::type Rest; + typedef typename fold_apply::type Rest2; + typedef typename fold_apply::type type; + }; + + template + struct result_of_unrolled_fold + { + typedef typename result_of::next::type I1; + typedef typename fold_apply::type Rest; + typedef typename fold_apply::type type; + }; + + template + struct result_of_unrolled_fold + { + typedef typename fold_apply::type type; + }; + + template + struct result_of_unrolled_fold + { + typedef State type; + }; + + template + struct choose_fold; + + template + struct choose_fold + { + typedef typename result_of::begin::type begin; + typedef typename result_of::end::type end; + typedef typename result_of_unrolled_fold< + begin, State, F, result_of::distance::value>::type type; + }; + + template + struct choose_fold + { + typedef typename + detail::static_fold< + typename result_of::begin::type + , typename result_of::end::type + , State + , F + >::type + type; + }; + + template + typename result_of::fold::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::type + , typename result_of::end::type>() + ); + } + + template + typename result_of::fold::type + fold(Sequence& seq, State const& state, F const& f, random_access_traversal_tag) + { + typedef typename result_of::begin::type begin; + typedef typename result_of::end::type end; + return unrolled_fold::value>::call( + fusion::begin(seq) + , state + , f); + } }}} #endif - diff --git a/include/boost/fusion/algorithm/iteration/detail/for_each.hpp b/include/boost/fusion/algorithm/iteration/detail/for_each.hpp index 7f81d9af..a67978c6 100644 --- a/include/boost/fusion/algorithm/iteration/detail/for_each.hpp +++ b/include/boost/fusion/algorithm/iteration/detail/for_each.hpp @@ -7,28 +7,124 @@ #if !defined(FUSION_FOR_EACH_05052005_1028) #define FUSION_FOR_EACH_05052005_1028 -#include +#include +#include #include #include #include +#include +#include -namespace boost { namespace fusion { namespace detail +namespace boost { namespace fusion { +namespace detail { template inline void - for_each(First const&, Last const&, F const&, mpl::true_) + for_each_linear(First const&, Last const&, F const&, mpl::true_) { } - + template 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); - detail::for_each(fusion::next(first), last, f - , result_of::equal_to::type, Last>()); + detail::for_each_linear(fusion::next(first), last, f, + result_of::equal_to::type, Last>()); + } + + + template + 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::type + , typename result_of::end::type>()); + } + + template + struct for_each_unrolled + { + template + static void call(I0 const& i0, F const& f) + { + f(*i0); + typedef typename result_of::next::type I1; + I1 i1(fusion::next(i0)); + f(*i1); + typedef typename result_of::next::type I2; + I2 i2(fusion::next(i1)); + f(*i2); + typedef typename result_of::next::type I3; + I3 i3(fusion::next(i2)); + f(*i3); + for_each_unrolled::call(fusion::next(i3), f); + } + }; + + template<> + struct for_each_unrolled<3> + { + template + static void call(I0 const& i0, F const& f) + { + f(*i0); + typedef typename result_of::next::type I1; + I1 i1(fusion::next(i0)); + f(*i1); + typedef typename result_of::next::type I2; + I2 i2(fusion::next(i1)); + f(*i2); + } + }; + + template<> + struct for_each_unrolled<2> + { + template + static void call(I0 const& i0, F const& f) + { + f(*i0); + typedef typename result_of::next::type I1; + I1 i1(fusion::next(i0)); + f(*i1); + } + }; + + template<> + struct for_each_unrolled<1> + { + template + static void call(I0 const& i0, F const& f) + { + f(*i0); + } + }; + + template<> + struct for_each_unrolled<0> + { + template + static void call(It const&, F const&) + { + } + }; + + template + inline void + for_each(Sequence& seq, F const& f, random_access_traversal_tag) + { + typedef typename result_of::begin::type begin; + typedef typename result_of::end::type end; + for_each_unrolled::value>::call(fusion::begin(seq), f); } }}} + #endif diff --git a/include/boost/fusion/algorithm/iteration/fold.hpp b/include/boost/fusion/algorithm/iteration/fold.hpp index e6930ff6..046acb86 100644 --- a/include/boost/fusion/algorithm/iteration/fold.hpp +++ b/include/boost/fusion/algorithm/iteration/fold.hpp @@ -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 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ -#if !defined(FUSION_FOLD_05052005_1214) -#define FUSION_FOLD_05052005_1214 +#if !defined(BOOST_FUSION_FOLD_05052005_1214) +#define BOOST_FUSION_FOLD_05052005_1214 #include #include -#include +#include + +#include #include -namespace boost { namespace fusion -{ - struct void_; +namespace boost { namespace fusion { + + struct random_access_traversal_tag; namespace result_of { template struct fold - { - typedef typename - detail::static_fold< - typename result_of::begin::type - , typename result_of::end::type - , State - , F - >::type - type; - }; + : fusion::detail::choose_fold< + Sequence, State, F + , is_base_of::type>::value> + {}; } template inline typename result_of::fold::type fold(Sequence& seq, State const& state, F const& f) { - return detail::fold( - fusion::begin(seq) - , fusion::end(seq) - , state - , f - , result_of::equal_to< - typename result_of::begin::type - , typename result_of::end::type>() - ); + return detail::fold(seq, state, f, typename traits::category_of::type()); } template inline typename result_of::fold::type fold(Sequence const& seq, State const& state, F const& f) { - return detail::fold( - fusion::begin(seq) - , fusion::end(seq) - , state - , f - , result_of::equal_to< - typename result_of::begin::type - , typename result_of::end::type>() - ); + return detail::fold(seq, state, f, typename traits::category_of::type()); } }} diff --git a/include/boost/fusion/algorithm/iteration/for_each.hpp b/include/boost/fusion/algorithm/iteration/for_each.hpp index 0d96a04e..fffb0f00 100644 --- a/include/boost/fusion/algorithm/iteration/for_each.hpp +++ b/include/boost/fusion/algorithm/iteration/for_each.hpp @@ -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 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ -#if !defined(FUSION_FOR_EACH_05052005_1027) -#define FUSION_FOR_EACH_05052005_1027 +#if !defined(BOOST_FUSION_FOR_EACH_20070527_0943) +#define BOOST_FUSION_FOR_EACH_20070527_0943 -#include -#include -#include #include -namespace boost { namespace fusion -{ +#include + +namespace boost { namespace fusion { + namespace result_of { template @@ -23,32 +23,21 @@ namespace boost { namespace fusion }; } + struct random_access_traversal_tag; + template inline void for_each(Sequence& seq, F const& f) { - detail::for_each( - fusion::begin(seq) - , fusion::end(seq) - , f - , result_of::equal_to< - typename result_of::begin::type - , typename result_of::end::type>()); + detail::for_each(seq, f, typename traits::category_of::type()); } template inline void for_each(Sequence const& seq, F const& f) { - detail::for_each( - fusion::begin(seq) - , fusion::end(seq) - , f - , result_of::equal_to< - typename result_of::begin::type - , typename result_of::end::type>()); + detail::for_each(seq, f, typename traits::category_of::type()); } }} #endif -