Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

utility: Add custom pair implementation #425

Merged
merged 1 commit into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/cuda/unordered_map.cu
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ main()
stdgpu::pair<int, int> sum =
thrust::reduce(range_map.begin(), range_map.end(), stdgpu::pair<int, int>(0, 0), int_pair_plus());

const stdgpu::pair<int, int> sum_closed_form = { n * (n + 1) / 2, n * (n + 1) * (2 * n + 1) / 6 };
const stdgpu::pair<int, int> sum_closed_form = { static_cast<int>(n * (n + 1) / 2),
static_cast<int>(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 << ") (("
Expand Down
3 changes: 2 additions & 1 deletion examples/openmp/unordered_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ main()
stdgpu::pair<int, int> sum =
thrust::reduce(range_map.begin(), range_map.end(), stdgpu::pair<int, int>(0, 0), int_pair_plus());

const stdgpu::pair<int, int> sum_closed_form = { n * (n + 1) / 2, n * (n + 1) * (2 * n + 1) / 6 };
const stdgpu::pair<int, int> sum_closed_form = { static_cast<int>(n * (n + 1) / 2),
static_cast<int>(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 << ") (("
Expand Down
100 changes: 100 additions & 0 deletions src/stdgpu/impl/utility_detail.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,106 @@
namespace stdgpu
{

template <typename T1, typename T2>
template <
STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_default_constructible_v<T1>&& std::is_default_constructible_v<T2>)>
constexpr STDGPU_HOST_DEVICE
pair<T1, T2>::pair()
: first()
, second()
{
}

template <typename T1, typename T2>
template <STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_copy_constructible_v<T1>&& std::is_copy_constructible_v<T2>)>
constexpr STDGPU_HOST_DEVICE
pair<T1, T2>::pair(const T1& x, const T2& y)
: first(x)
, second(y)
{
}

template <typename T1, typename T2>
template <class U1,
class U2,
STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_constructible_v<T1, U1>&& std::is_constructible_v<T2, U2>)>
constexpr STDGPU_HOST_DEVICE
pair<T1, T2>::pair(U1&& x, U2&& y)
: first(forward<U1>(x))
, second(forward<U2>(y))
{
}

template <typename T1, typename T2>
template <typename U1,
typename U2,
STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_constructible_v<T1, U1&>&& std::is_constructible_v<T2, U2&>)>
constexpr STDGPU_HOST_DEVICE
pair<T1, T2>::pair(pair<U1, U2>& p)
: first(p.first)
, second(p.second)
{
}

template <typename T1, typename T2>
template <typename U1,
typename U2,
STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(
std::is_constructible_v<T1, const U1&>&& std::is_constructible_v<T2, const U2&>)>
constexpr STDGPU_HOST_DEVICE
pair<T1, T2>::pair(const pair<U1, U2>& p)
: first(p.first)
, second(p.second)
{
}

template <typename T1, typename T2>
template <typename U1,
typename U2,
STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_constructible_v<T1, U1>&& std::is_constructible_v<T2, U2>)>
constexpr STDGPU_HOST_DEVICE
pair<T1, T2>::pair(pair<U1, U2>&& p)
: first(forward<U1>(p.first))
, second(forward<U2>(p.second))
{
}

template <typename T1, typename T2>
template <typename U1,
typename U2,
STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_constructible_v<T1, U1>&& std::is_constructible_v<T2, U2>)>
constexpr STDGPU_HOST_DEVICE
pair<T1, T2>::pair(const pair<U1, U2>&& p)
: first(forward<const U1>(p.first))
, second(forward<const U2>(p.second))
{
}

template <typename T1, typename T2>
template <class U1,
class U2,
STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(
std::is_assignable_v<T1&, const U1&>&& std::is_assignable_v<T2&, const U2&>)>
constexpr STDGPU_HOST_DEVICE pair<T1, T2>&
pair<T1, T2>::operator=(const pair<U1, U2>& p)
{
first = p.first;
second = p.second;
return *this;
}

template <typename T1, typename T2>
template <class U1,
class U2,
STDGPU_DETAIL_OVERLOAD_DEFINITION_IF(std::is_assignable_v<T1&, U1>&& std::is_assignable_v<T2&, U2>)>
constexpr STDGPU_HOST_DEVICE pair<T1, T2>&
pair<T1, T2>::operator=(pair<U1, U2>&& p)
{
first = forward<U1>(p.first);
second = forward<U1>(p.second);
return *this;
}

template <class T>
constexpr STDGPU_HOST_DEVICE T&&
forward(std::remove_reference_t<T>& t) noexcept
Expand Down
150 changes: 148 additions & 2 deletions src/stdgpu/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
* \file stdgpu/utility.h
*/

#include <thrust/pair.h>
#include <type_traits>

#include <stdgpu/platform.h>
#include <stdgpu/type_traits.h>

namespace stdgpu
{
Expand All @@ -40,7 +40,153 @@ namespace stdgpu
* \brief A pair of two values of potentially different types
*/
template <typename T1, typename T2>
using pair = thrust::pair<T1, T2>;
struct pair
{
using first_type = T1; /**< T1 */
using second_type = T2; /**< T2 */

/**
* \brief Default Destructor
*/
~pair() = default;

/**
* \brief Constructor
*/
template <STDGPU_DETAIL_OVERLOAD_IF(std::is_default_constructible_v<T1>&& std::is_default_constructible_v<T2>)>
constexpr STDGPU_HOST_DEVICE
pair();

/**
* \brief Constructor
* \param[in] x The new first element
* \param[in] y The new second element
*/
template <STDGPU_DETAIL_OVERLOAD_IF(std::is_copy_constructible_v<T1>&& std::is_copy_constructible_v<T2>)>
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 <class U1 = T1,
class U2 = T2,
STDGPU_DETAIL_OVERLOAD_IF(std::is_constructible_v<T1, U1>&& std::is_constructible_v<T2, U2>)>
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 <typename U1,
typename U2,
STDGPU_DETAIL_OVERLOAD_IF(std::is_constructible_v<T1, U1&>&& std::is_constructible_v<T2, U2&>)>
constexpr STDGPU_HOST_DEVICE
pair(pair<U1, U2>& 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<T1, const U1&>&& std::is_constructible_v<T2, const U2&>)>
constexpr STDGPU_HOST_DEVICE
pair(const pair<U1, U2>& 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 <class U1,
class U2,
STDGPU_DETAIL_OVERLOAD_IF(std::is_constructible_v<T1, U1>&& std::is_constructible_v<T2, U2>)>
constexpr STDGPU_HOST_DEVICE
pair(pair<U1, U2>&& 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 <class U1,
class U2,
STDGPU_DETAIL_OVERLOAD_IF(std::is_constructible_v<T1, U1>&& std::is_constructible_v<T2, U2>)>
constexpr STDGPU_HOST_DEVICE
pair(const pair<U1, U2>&& 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 <class U1,
class U2,
STDGPU_DETAIL_OVERLOAD_IF(std::is_assignable_v<T1&, const U1&>&& std::is_assignable_v<T2&, const U2&>)>
constexpr STDGPU_HOST_DEVICE pair&
operator=(const pair<U1, U2>& 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 <class U1,
class U2,
STDGPU_DETAIL_OVERLOAD_IF(std::is_assignable_v<T1&, U1>&& std::is_assignable_v<T2&, U2>)>
constexpr STDGPU_HOST_DEVICE pair&
operator=(pair<U1, U2>&& 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
Expand Down