/****************************************************************************** * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. * Modifications Copyright (c) 2019-2025, Advanced Micro Devices, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the NVIDIA CORPORATION nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ******************************************************************************/ #pragma once #include #if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC) # pragma GCC system_header #elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG) # pragma clang system_header #elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC) # pragma system_header #endif // no system header #if THRUST_DEVICE_COMPILER == THRUST_DEVICE_COMPILER_HIP # include # include # include # include # include # include # include # include # include // rocprim include # include # include # include _THRUST_STD_INCLUDE(type_traits) THRUST_NAMESPACE_BEGIN template THRUST_HOST_DEVICE OutputIterator adjacent_difference( const thrust::detail::execution_policy_base& exec, InputIterator first, InputIterator last, OutputIterator result, BinaryFunction binary_op); namespace hip_rocprim { namespace __adjacent_difference { template hipError_t THRUST_HIP_RUNTIME_FUNCTION __adjecent_difference( void* const temporary_storage, size_t& storage_size, const InputIt input, const OutputIt output, const size_t size, const BinaryOp op, const hipStream_t stream, const bool debug_synchronous, thrust::detail::integral_constant /* iterators are comparable */) { if (input != output) { return rocprim::adjacent_difference( temporary_storage, storage_size, input, output, size, op, stream, debug_synchronous); } else { return rocprim::adjacent_difference_inplace( temporary_storage, storage_size, input, output, size, op, stream, debug_synchronous); } } template hipError_t THRUST_HIP_RUNTIME_FUNCTION __adjecent_difference( void* const temporary_storage, size_t& storage_size, const InputIt input, const OutputIt output, const size_t size, const BinaryOp op, const hipStream_t stream, const bool debug_synchronous, thrust::detail::integral_constant /* iterators are not comparable */) { return rocprim::adjacent_difference_inplace( temporary_storage, storage_size, input, output, size, op, stream, debug_synchronous); } template OutputIt THRUST_HIP_RUNTIME_FUNCTION adjacent_difference(execution_policy& policy, InputIt first, InputIt last, OutputIt result, BinaryOp binary_op) { const auto num_items = static_cast(thrust::distance(first, last)); std::size_t storage_size = 0; hipStream_t stream = hip_rocprim::stream(policy); bool debug_sync = THRUST_HIP_DEBUG_SYNC_FLAG; if (num_items <= 0) { return result; } using UnwrapInputIt = thrust::try_unwrap_contiguous_iterator_t; using UnwrapOutputIt = thrust::try_unwrap_contiguous_iterator_t; using InputValueT = thrust::iterator_value_t; using OutputValueT = thrust::iterator_value_t; constexpr bool can_compare_iterators = _THRUST_STD::is_pointer::value && _THRUST_STD::is_pointer::value && std::is_same::value; auto first_unwrap = thrust::try_unwrap_contiguous_iterator(first); auto result_unwrap = thrust::try_unwrap_contiguous_iterator(result); thrust::detail::integral_constant comparable; // Determine temporary device storage requirements. hip_rocprim::throw_on_error( __adjecent_difference( nullptr, storage_size, first_unwrap, result_unwrap, static_cast(num_items), binary_op, stream, debug_sync, comparable), "adjacent_difference failed on 1st step"); // Allocate temporary storage. thrust::detail::temporary_array tmp(policy, storage_size); void* ptr = static_cast(tmp.data().get()); hip_rocprim::throw_on_error( __adjecent_difference( ptr, storage_size, first_unwrap, result_unwrap, static_cast(num_items), binary_op, stream, debug_sync, comparable), "adjacent_difference failed on 2nd step"); hip_rocprim::throw_on_error(hip_rocprim::synchronize_optional(policy), "adjacent_difference failed to synchronize"); return result + num_items; } } // namespace __adjacent_difference //------------------------- // Thrust API entry points //------------------------- THRUST_EXEC_CHECK_DISABLE template OutputIt THRUST_HOST_DEVICE adjacent_difference(execution_policy& policy, InputIt first, InputIt last, OutputIt result, BinaryOp binary_op) { // struct workaround is required for HIP-clang struct workaround { THRUST_HOST static void par(execution_policy& policy, InputIt first, InputIt last, OutputIt& result, BinaryOp binary_op) { result = __adjacent_difference::adjacent_difference(policy, first, last, result, binary_op); } # if !__THRUST_HAS_HIPRT__ THRUST_DEVICE static void seq(execution_policy& policy, InputIt first, InputIt last, OutputIt& result, BinaryOp binary_op) { result = thrust::adjacent_difference(cvt_to_seq(derived_cast(policy)), first, last, result, binary_op); } # endif }; # if __THRUST_HAS_HIPRT__ workaround::par(policy, first, last, result, binary_op); # else workaround::seq(policy, first, last, result, binary_op); # endif return result; } template OutputIt THRUST_HOST_DEVICE adjacent_difference(execution_policy& policy, InputIt first, InputIt last, OutputIt result) { using input_type = typename iterator_traits::value_type; return hip_rocprim::adjacent_difference(policy, first, last, result, minus()); } } // namespace hip_rocprim THRUST_NAMESPACE_END // # include # include #endif