//---------------------------------------------------------------------------// // Copyright (c) 2013-2014 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_ADJACENT_DIFFERENCE_HPP #define BOOST_COMPUTE_ALGORITHM_ADJACENT_DIFFERENCE_HPP #include #include #include #include #include #include #include #include #include namespace boost { namespace compute { namespace detail { template inline OutputIterator dispatch_adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryFunction op, command_queue &queue = system::default_queue()) { size_t count = detail::iterator_range_size(first, last); detail::meta_kernel k("adjacent_difference"); k << "const uint i = get_global_id(0);\n" << "if(i == 0){\n" << " " << result[k.var("0")] << " = " << first[k.var("0")] << ";\n" << "}\n" << "else {\n" << " " << result[k.var("i")] << " = " << op(first[k.var("i")], first[k.var("i-1")]) << ";\n" << "}\n"; k.exec_1d(queue, 0, count, 1); return result + count; } } // end detail namespace /// Stores the difference of each pair of consecutive values in the range /// [\p first, \p last) to the range beginning at \p result. If \p op is not /// provided, \c minus is used. /// /// \param first first element in the input range /// \param last last element in the input range /// \param result first element in the output range /// \param op binary difference function /// \param queue command queue to perform the operation /// /// \return \c OutputIterator to the end of the result range /// /// Space complexity: \Omega(1)
/// Space complexity when \p result == \p first: \Omega(n) /// /// \see adjacent_find() template inline OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryFunction op, command_queue &queue = system::default_queue()) { BOOST_STATIC_ASSERT(is_device_iterator::value); BOOST_STATIC_ASSERT(is_device_iterator::value); typedef typename std::iterator_traits::value_type value_type; if(first == last) { return result; } if (first == result) { vector temp(detail::iterator_range_size(first, last), queue.get_context()); copy(first, last, temp.begin(), queue); return ::boost::compute::detail::dispatch_adjacent_difference( temp.begin(), temp.end(), result, op, queue ); } else { return ::boost::compute::detail::dispatch_adjacent_difference( first, last, result, op, queue ); } } /// \overload template inline OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, command_queue &queue = system::default_queue()) { BOOST_STATIC_ASSERT(is_device_iterator::value); BOOST_STATIC_ASSERT(is_device_iterator::value); typedef typename std::iterator_traits::value_type value_type; return ::boost::compute::adjacent_difference( first, last, result, ::boost::compute::minus(), queue ); } } // end compute namespace } // end boost namespace #endif // BOOST_COMPUTE_ALGORITHM_ADJACENT_DIFFERENCE_HPP