• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 // See http://boostorg.github.com/compute for more information.
9 //---------------------------------------------------------------------------//
10 
11 #ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_REDUCE_HPP
12 #define BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_REDUCE_HPP
13 
14 #include <boost/compute/algorithm/reduce.hpp>
15 #include <boost/compute/iterator/transform_iterator.hpp>
16 #include <boost/compute/types/fundamental.hpp>
17 
18 namespace boost {
19 namespace compute {
20 namespace detail {
21 
22 template<class Predicate, class Arg>
23 struct invoked_countable_predicate
24 {
invoked_countable_predicateboost::compute::detail::invoked_countable_predicate25     invoked_countable_predicate(Predicate p, Arg a)
26         : predicate(p), arg(a)
27     {
28     }
29 
30     Predicate predicate;
31     Arg arg;
32 };
33 
34 template<class Predicate, class Arg>
operator <<(meta_kernel & kernel,const invoked_countable_predicate<Predicate,Arg> & expr)35 inline meta_kernel& operator<<(meta_kernel &kernel,
36                                const invoked_countable_predicate<Predicate, Arg> &expr)
37 {
38     return kernel << "(" << expr.predicate(expr.arg) << " ? 1 : 0)";
39 }
40 
41 // the countable_predicate wraps Predicate and converts its result from
42 // bool to ulong so that it can be used with reduce()
43 template<class Predicate>
44 struct countable_predicate
45 {
46     typedef ulong_ result_type;
47 
countable_predicateboost::compute::detail::countable_predicate48     countable_predicate(Predicate predicate)
49         : m_predicate(predicate)
50     {
51     }
52 
53     template<class Arg>
operator ()boost::compute::detail::countable_predicate54     invoked_countable_predicate<Predicate, Arg> operator()(const Arg &arg) const
55     {
56         return invoked_countable_predicate<Predicate, Arg>(m_predicate, arg);
57     }
58 
59     Predicate m_predicate;
60 };
61 
62 // counts the number of elements matching predicate using reduce()
63 template<class InputIterator, class Predicate>
count_if_with_reduce(InputIterator first,InputIterator last,Predicate predicate,command_queue & queue)64 inline size_t count_if_with_reduce(InputIterator first,
65                                    InputIterator last,
66                                    Predicate predicate,
67                                    command_queue &queue)
68 {
69     countable_predicate<Predicate> reduce_predicate(predicate);
70 
71     ulong_ count = 0;
72     ::boost::compute::reduce(
73         ::boost::compute::make_transform_iterator(first, reduce_predicate),
74         ::boost::compute::make_transform_iterator(last, reduce_predicate),
75         &count,
76         ::boost::compute::plus<ulong_>(),
77         queue
78     );
79 
80     return static_cast<size_t>(count);
81 }
82 
83 } // end detail namespace
84 } // end compute namespace
85 } // end boost namespace
86 
87 #endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_REDUCE_HPP
88