// SPDX-FileCopyrightText: Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. // SPDX-License-Identifier: BSD-3 /** * \file * Define helper math functions. */ #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 #include #include #include #include #include #include #include #include CUB_NAMESPACE_BEGIN namespace detail { template using is_integral_or_enum = ::cuda::std::integral_constant || ::cuda::std::is_enum_v>; /** * Computes lhs + rhs, but bounds the result to the maximum number representable by the given type, if the addition * would overflow. Note, lhs must be non-negative. * * Effectively performs `min((lhs + rhs), ::cuda::std::numeric_limits::max())`, but is robust against the case * where `(lhs + rhs)` would overflow. */ template _CCCL_HOST_DEVICE _CCCL_FORCEINLINE OffsetT safe_add_bound_to_max(OffsetT lhs, OffsetT rhs) { static_assert(::cuda::std::is_integral_v, "OffsetT must be an integral type"); static_assert(sizeof(OffsetT) >= 4, "OffsetT must be at least 32 bits in size"); auto const capped_operand_rhs = (::cuda::std::min) (rhs, ::cuda::std::numeric_limits::max() - lhs); return lhs + capped_operand_rhs; } constexpr _CCCL_HOST_DEVICE int nominal_4B_items_to_items(int nominal_items_per_thread, int item_size) { return ::cuda::std::clamp(nominal_items_per_thread * 4 / item_size, 1, nominal_items_per_thread); } constexpr _CCCL_HOST_DEVICE int nominal_8B_items_to_items(int nominal_items_per_thread, int item_size) { if (item_size <= 8) { return nominal_items_per_thread; } return ::cuda::std::clamp(::cuda::ceil_div(nominal_items_per_thread * 8, item_size), 1, nominal_items_per_thread); } } // namespace detail constexpr _CCCL_HOST_DEVICE int Nominal4BItemsToItemsCombined(int nominal_items_per_thread, int combined_bytes) { return ( ::cuda::std::min) (nominal_items_per_thread, (::cuda::std::max) (1, nominal_items_per_thread * 8 / combined_bytes)); } template constexpr _CCCL_HOST_DEVICE int Nominal4BItemsToItems(int nominal_items_per_thread) { return detail::nominal_4B_items_to_items(nominal_items_per_thread, int{sizeof(T)}); } template constexpr _CCCL_HOST_DEVICE int Nominal8BItemsToItems(int nominal_items_per_thread) { return detail::nominal_8B_items_to_items(nominal_items_per_thread, int{sizeof(ItemT)}); } /** * \brief Computes the midpoint of the integers * * Extra operation is performed in order to prevent overflow. * * \return Half the sum of \p begin and \p end */ template constexpr _CCCL_HOST_DEVICE T MidPoint(T begin, T end) { return begin + (end - begin) / 2; } CUB_NAMESPACE_END