text: /*=============================================================================
      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(BOOST_FUSION_COUNT_IF_09162005_0141)
  #define BOOST_FUSION_COUNT_IF_09162005_0141
  
  #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/next.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 { 
      struct random_access_traversal_tag;
  namespace detail
  {
      template <typename First, typename Last, typename F>
      inline int
      linear_count_if(First const&, Last const&, F const&, mpl::true_)
      {
          return 0;
      }
  
      template <typename First, typename Last, typename F>
      inline int
      linear_count_if(First const& first, Last const& last, F& f, mpl::false_)
      {
          int n =  
              detail::linear_count_if(
                  fusion::next(first)
                , last
                , f
                , result_of::equal_to<typename result_of::next<First>::type, Last>());
          if (f(*first))
              ++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>::type::value>::
              call(fusion::begin(seq), f);
      }
  }}}
  
  #endif
  
  