//---------------------------------------------------------------------------// // Copyright (c) 2013-2015 Kyle Lutz // // 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 // // See http://boostorg.github.com/compute for more information. //---------------------------------------------------------------------------// #ifndef BOOST_COMPUTE_ALGORITHM_TRANSFORM_IF_HPP #define BOOST_COMPUTE_ALGORITHM_TRANSFORM_IF_HPP #include #include #include #include #include #include #include #include #include #include namespace boost { namespace compute { namespace detail { template inline OutputIterator transform_if_impl(InputIterator first, InputIterator last, OutputIterator result, UnaryFunction function, Predicate predicate, bool copyIndex, command_queue &queue) { typedef typename std::iterator_traits::difference_type difference_type; size_t count = detail::iterator_range_size(first, last); if(count == 0){ return result; } const context &context = queue.get_context(); // storage for destination indices ::boost::compute::vector indices(count, context); // write counts ::boost::compute::detail::meta_kernel k1("transform_if_write_counts"); k1 << indices.begin()[k1.get_global_id(0)] << " = " << predicate(first[k1.get_global_id(0)]) << " ? 1 : 0;\n"; k1.exec_1d(queue, 0, count); // count number of elements to be copied size_t copied_element_count = ::boost::compute::count(indices.begin(), indices.end(), 1, queue); // scan indices ::boost::compute::exclusive_scan( indices.begin(), indices.end(), indices.begin(), queue ); // copy values ::boost::compute::detail::meta_kernel k2("transform_if_do_copy"); k2 << "if(" << predicate(first[k2.get_global_id(0)]) << ")" << " " << result[indices.begin()[k2.get_global_id(0)]] << "="; if(copyIndex){ k2 << k2.get_global_id(0) << ";\n"; } else { k2 << function(first[k2.get_global_id(0)]) << ";\n"; } k2.exec_1d(queue, 0, count); return result + static_cast(copied_element_count); } template inline discard_iterator transform_if_impl(InputIterator first, InputIterator last, discard_iterator result, UnaryFunction function, Predicate predicate, bool copyIndex, command_queue &queue) { (void) function; (void) copyIndex; return result + count_if(first, last, predicate, queue); } } // end detail namespace /// Copies each element in the range [\p first, \p last) for which /// \p predicate returns \c true to the range beginning at \p result. template inline OutputIterator transform_if(InputIterator first, InputIterator last, OutputIterator result, UnaryFunction function, Predicate predicate, command_queue &queue = system::default_queue()) { return detail::transform_if_impl( first, last, result, function, predicate, false, queue ); } } // end compute namespace } // end boost namespace #endif // BOOST_COMPUTE_ALGORITHM_TRANSFORM_IF_HPP