From 6976d5b764e05cfd5b34e60efc640b55b23fdacd Mon Sep 17 00:00:00 2001 From: Patrick Stotko Date: Wed, 17 Jul 2024 08:10:39 +0200 Subject: [PATCH] utility: Add custom pair implementation --- examples/cuda/unordered_map.cu | 3 +- examples/openmp/unordered_map.cpp | 3 +- src/stdgpu/impl/utility_detail.h | 100 ++++++++++++++++++++ src/stdgpu/utility.h | 150 +++++++++++++++++++++++++++++- 4 files changed, 252 insertions(+), 4 deletions(-) diff --git a/examples/cuda/unordered_map.cu b/examples/cuda/unordered_map.cu index 09e9aee3a..06bf2c3e2 100644 --- a/examples/cuda/unordered_map.cu +++ b/examples/cuda/unordered_map.cu @@ -104,7 +104,8 @@ main() stdgpu::pair sum = thrust::reduce(range_map.begin(), range_map.end(), stdgpu::pair(0, 0), int_pair_plus()); - const stdgpu::pair sum_closed_form = { n * (n + 1) / 2, n * (n + 1) * (2 * n + 1) / 6 }; + const stdgpu::pair sum_closed_form = { static_cast(n * (n + 1) / 2), + static_cast(n * (n + 1) * (2 * n + 1) / 6) }; std::cout << "The duplicate-free map of numbers contains " << map.size() << " elements (" << n + 1 << " expected) and the computed sums are (" << sum.first << ", " << sum.second << ") ((" diff --git a/examples/openmp/unordered_map.cpp b/examples/openmp/unordered_map.cpp index 3a61735c1..2ebc4a579 100644 --- a/examples/openmp/unordered_map.cpp +++ b/examples/openmp/unordered_map.cpp @@ -100,7 +100,8 @@ main() stdgpu::pair sum = thrust::reduce(range_map.begin(), range_map.end(), stdgpu::pair(0, 0), int_pair_plus()); - const stdgpu::pair sum_closed_form = { n * (n + 1) / 2, n * (n + 1) * (2 * n + 1) / 6 }; + const stdgpu::pair sum_closed_form = { static_cast(n * (n + 1) / 2), + static_cast(n * (n + 1) * (2 * n + 1) / 6) }; std::cout << "The duplicate-free map of numbers contains " << map.size() << " elements (" << n + 1 << " expected) and the computed sums are (" << sum.first << ", " << sum.second << ") ((" diff --git a/src/stdgpu/impl/utility_detail.h b/src/stdgpu/impl/utility_detail.h index a913768d6..748802ca7 100644 --- a/src/stdgpu/impl/utility_detail.h +++ b/src/stdgpu/impl/utility_detail.h @@ -19,6 +19,106 @@ namespace stdgpu { +template +template < + STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_default_constructible_v&& std::is_default_constructible_v)> +constexpr STDGPU_HOST_DEVICE +pair::pair() + : first() + , second() +{ +} + +template +template && std::is_copy_constructible_v)> +constexpr STDGPU_HOST_DEVICE +pair::pair(const T1& x, const T2& y) + : first(x) + , second(y) +{ +} + +template +template && std::is_constructible_v)> +constexpr STDGPU_HOST_DEVICE +pair::pair(U1&& x, U2&& y) + : first(forward(x)) + , second(forward(y)) +{ +} + +template +template && std::is_constructible_v)> +constexpr STDGPU_HOST_DEVICE +pair::pair(pair& p) + : first(p.first) + , second(p.second) +{ +} + +template +template && std::is_constructible_v)> +constexpr STDGPU_HOST_DEVICE +pair::pair(const pair& p) + : first(p.first) + , second(p.second) +{ +} + +template +template && std::is_constructible_v)> +constexpr STDGPU_HOST_DEVICE +pair::pair(pair&& p) + : first(forward(p.first)) + , second(forward(p.second)) +{ +} + +template +template && std::is_constructible_v)> +constexpr STDGPU_HOST_DEVICE +pair::pair(const pair&& p) + : first(forward(p.first)) + , second(forward(p.second)) +{ +} + +template +template && std::is_assignable_v)> +constexpr STDGPU_HOST_DEVICE pair& +pair::operator=(const pair& p) +{ + first = p.first; + second = p.second; + return *this; +} + +template +template && std::is_assignable_v)> +constexpr STDGPU_HOST_DEVICE pair& +pair::operator=(pair&& p) +{ + first = forward(p.first); + second = forward(p.second); + return *this; +} + template constexpr STDGPU_HOST_DEVICE T&& forward(std::remove_reference_t& t) noexcept diff --git a/src/stdgpu/utility.h b/src/stdgpu/utility.h index 61e697e5b..04c2afae5 100644 --- a/src/stdgpu/utility.h +++ b/src/stdgpu/utility.h @@ -25,10 +25,10 @@ * \file stdgpu/utility.h */ -#include #include #include +#include namespace stdgpu { @@ -40,7 +40,153 @@ namespace stdgpu * \brief A pair of two values of potentially different types */ template -using pair = thrust::pair; +struct pair +{ + using first_type = T1; /**< T1 */ + using second_type = T2; /**< T2 */ + + /** + * \brief Default Destructor + */ + ~pair() = default; + + /** + * \brief Constructor + */ + template && std::is_default_constructible_v)> + constexpr STDGPU_HOST_DEVICE + pair(); + + /** + * \brief Constructor + * \param[in] x The new first element + * \param[in] y The new second element + */ + template && std::is_copy_constructible_v)> + constexpr STDGPU_HOST_DEVICE + pair(const T1& x, const T2& y); + + /** + * \brief Constructor + * \tparam U1 The type of the first element + * \tparam U2 The type of the second element + * \param[in] x The new first element + * \param[in] y The new second element + */ + template && std::is_constructible_v)> + constexpr STDGPU_HOST_DEVICE + pair(U1&& x, U2&& y); + + /** + * \brief Copy constructor + * \tparam U1 The type of the other pair's first element + * \tparam U2 The type of the other pair's second element + * \param[in] p The pair to copy from + */ + template && std::is_constructible_v)> + constexpr STDGPU_HOST_DEVICE + pair(pair& p); // NOLINT(hicpp-explicit-conversions) + + /** + * \brief Copy constructor + * \tparam U1 The type of the other pair's first element + * \tparam U2 The type of the other pair's second element + * \param[in] p The copied pair + */ + template < + typename U1, + typename U2, + STDGPU_DETAIL_OVERLOAD_IF(std::is_constructible_v&& std::is_constructible_v)> + constexpr STDGPU_HOST_DEVICE + pair(const pair& p); // NOLINT(hicpp-explicit-conversions) + + /** + * \brief Move constructor + * \tparam U1 The type of the other pair's first element + * \tparam U2 The type of the other pair's second element + * \param[in] p The moved pair + */ + template && std::is_constructible_v)> + constexpr STDGPU_HOST_DEVICE + pair(pair&& p); // NOLINT(hicpp-explicit-conversions) + + /** + * \brief Move constructor + * \tparam U1 The type of the other pair's first element + * \tparam U2 The type of the other pair's second element + * \param[in] p The moved pair + */ + template && std::is_constructible_v)> + constexpr STDGPU_HOST_DEVICE + pair(const pair&& p); // NOLINT(hicpp-explicit-conversions) + + /** + * \brief Default copy constructor + * \param[in] p The copied pair + */ + pair(const pair& p) = default; + + /** + * \brief Default move constructor + * \param[in] p The moved pair + */ + pair(pair&& p) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + + /** + * \brief Default copy assignment operator + * \param[in] p The pair to copy from + * \return *this + */ + pair& + operator=(const pair& p) = default; + + /** + * \brief Copy assignment operator + * \tparam U1 The type of the other pair's first element + * \tparam U2 The type of the other pair's second element + * \param[in] p The pair to copy from + * \return *this + */ + template && std::is_assignable_v)> + constexpr STDGPU_HOST_DEVICE pair& + operator=(const pair& p); + + /** + * \brief Default move assignment operator + * \param[in] p The moved pair + * \return *this + */ + pair& + operator=(pair&& p) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + + /** + * \brief Move assignment operator + * \tparam U1 The type of the other pair's first element + * \tparam U2 The type of the other pair's second element + * \param[in] p The moved pair + * \return *this + */ + template && std::is_assignable_v)> + constexpr STDGPU_HOST_DEVICE pair& + operator=(pair&& p); + + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) + first_type first; /**< First element of pair */ + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) + second_type second; /**< Second element of pair */ +}; /** * \ingroup utility