count_if_with_reduce.hpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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. #ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_REDUCE_HPP
  11. #define BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_REDUCE_HPP
  12. #include <boost/compute/algorithm/reduce.hpp>
  13. #include <boost/compute/iterator/transform_iterator.hpp>
  14. #include <boost/compute/types/fundamental.hpp>
  15. namespace boost {
  16. namespace compute {
  17. namespace detail {
  18. template<class Predicate, class Arg>
  19. struct invoked_countable_predicate
  20. {
  21. invoked_countable_predicate(Predicate p, Arg a)
  22. : predicate(p), arg(a)
  23. {
  24. }
  25. Predicate predicate;
  26. Arg arg;
  27. };
  28. template<class Predicate, class Arg>
  29. inline meta_kernel& operator<<(meta_kernel &kernel,
  30. const invoked_countable_predicate<Predicate, Arg> &expr)
  31. {
  32. return kernel << "(" << expr.predicate(expr.arg) << " ? 1 : 0)";
  33. }
  34. // the countable_predicate wraps Predicate and converts its result from
  35. // bool to ulong so that it can be used with reduce()
  36. template<class Predicate>
  37. struct countable_predicate
  38. {
  39. typedef ulong_ result_type;
  40. countable_predicate(Predicate predicate)
  41. : m_predicate(predicate)
  42. {
  43. }
  44. template<class Arg>
  45. invoked_countable_predicate<Predicate, Arg> operator()(const Arg &arg) const
  46. {
  47. return invoked_countable_predicate<Predicate, Arg>(m_predicate, arg);
  48. }
  49. Predicate m_predicate;
  50. };
  51. // counts the number of elements matching predicate using reduce()
  52. template<class InputIterator, class Predicate>
  53. inline size_t count_if_with_reduce(InputIterator first,
  54. InputIterator last,
  55. Predicate predicate,
  56. command_queue &queue)
  57. {
  58. countable_predicate<Predicate> reduce_predicate(predicate);
  59. ulong_ count = 0;
  60. ::boost::compute::reduce(
  61. ::boost::compute::make_transform_iterator(first, reduce_predicate),
  62. ::boost::compute::make_transform_iterator(last, reduce_predicate),
  63. &count,
  64. ::boost::compute::plus<ulong_>(),
  65. queue
  66. );
  67. return static_cast<size_t>(count);
  68. }
  69. } // end detail namespace
  70. } // end compute namespace
  71. } // end boost namespace
  72. #endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COUNT_IF_WITH_REDUCE_HPP