Skip to content
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
13 changes: 11 additions & 2 deletions cub/cub/device/device_transform.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,33 @@
#include <cub/device/dispatch/dispatch_transform.cuh>
#include <cub/util_namespace.cuh>

#include <cuda/__functional/address_stability.h>
#include <cuda/std/tuple>

CUB_NAMESPACE_BEGIN

namespace detail
{
template <typename T>
struct __return_constant
{
T value;

THRUST_DEVICE_FUNCTION auto operator()() const -> T
template <typename... Args>
_CCCL_HOST_DEVICE auto operator()(Args&&...) const -> T
{
return value;
}
};
} // namespace detail
CUB_NAMESPACE_END

_CCCL_BEGIN_NAMESPACE_CUDA
template <typename T>
struct proclaims_copyable_arguments<CUB_NS_QUALIFIER::detail::__return_constant<T>> : ::cuda::std::true_type

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use cub::detail:: instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. If the user uses a wrapped namespace for cub, then __return_constant would live in user_defined_ns::cub::detail. Since we are completely outside this namespace, lookup would not find it.

{};
_CCCL_END_NAMESPACE_CUDA

CUB_NAMESPACE_BEGIN
//! DeviceTransform provides device-wide, parallel operations for transforming elements tuple-wise from multiple input
//! sequences into an output sequence.
struct DeviceTransform
Expand Down
39 changes: 37 additions & 2 deletions thrust/thrust/detail/internal_functional.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <thrust/iterator/iterator_traits.h>
#include <thrust/tuple.h>

#include <cuda/__functional/address_stability.h>
#include <cuda/__iterator/discard_iterator.h>
#include <cuda/__iterator/tabulate_output_iterator.h>
#include <cuda/__iterator/transform_input_output_iterator.h>
Expand Down Expand Up @@ -92,6 +93,25 @@ struct tuple_binary_predicate
mutable Predicate pred;
};

template <class Predicate, class NewType, class OutputType>
struct new_value_if_f
{
Predicate pred;
NewType new_value;

template <class T>
_CCCL_DEVICE_API OutputType operator()(T const& x)
{
return pred(x) ? new_value : x;
}

template <class T, class P>
_CCCL_DEVICE_API OutputType operator()(T const& x, P const& y)
{
return pred(y) ? new_value : x;
}
};

// We need to mark proxy iterators as such
template <>
inline constexpr bool is_proxy_reference_v<::cuda::discard_iterator::__discard_proxy> = true;
Expand Down Expand Up @@ -287,7 +307,22 @@ struct compare_first
return comp(thrust::raw_reference_cast(::cuda::std::get<0>(x)), thrust::raw_reference_cast(::cuda::std::get<0>(y)));
}
}; // end compare_first

} // end namespace detail

THRUST_NAMESPACE_END

_CCCL_BEGIN_NAMESPACE_CUDA
template <typename Predicate, typename IntegralType>
struct proclaims_copyable_arguments<THRUST_NS_QUALIFIER::detail::predicate_to_integral<Predicate, IntegralType>>
: proclaims_copyable_arguments<Predicate>
{};

template <typename Predicate>
struct proclaims_copyable_arguments<THRUST_NS_QUALIFIER::detail::tuple_binary_predicate<Predicate>>
: proclaims_copyable_arguments<Predicate>
{};

template <class Predicate, class NewType, class OutputType>
struct proclaims_copyable_arguments<THRUST_NS_QUALIFIER::detail::new_value_if_f<Predicate, NewType, OutputType>>
: proclaims_copyable_arguments<Predicate>
{};
_CCCL_END_NAMESPACE_CUDA
54 changes: 12 additions & 42 deletions thrust/thrust/system/cuda/detail/replace.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,55 +43,24 @@
THRUST_NAMESPACE_BEGIN
namespace cuda_cub
{

namespace __replace
{
template <class T>
struct constant_f
{
T value;

template <class U>
THRUST_DEVICE_FUNCTION T operator()(U const&) const
{
return value;
}
};

template <class Predicate, class NewType, class OutputType>
struct new_value_if_f
{
Predicate pred;
NewType new_value;

template <class T>
OutputType THRUST_DEVICE_FUNCTION operator()(T const& x)
{
return pred(x) ? new_value : x;
}

template <class T, class P>
OutputType THRUST_DEVICE_FUNCTION operator()(T const& x, P const& y)
{
return pred(y) ? new_value : x;
}
};

} // namespace __replace

template <class Derived, class Iterator, class T>
void _CCCL_HOST_DEVICE
replace(execution_policy<Derived>& policy, Iterator first, Iterator last, T const& old_value, T const& new_value)
{
using thrust::placeholders::_1;
cuda_cub::transform_if(policy, first, last, first, __replace::constant_f<T>{new_value}, _1 == old_value);
cuda_cub::transform_if(
policy,
first,
last,
first,
CUB_NS_QUALIFIER::detail::__return_constant<T>{new_value},
thrust::detail::equal_to_value<T>{old_value});
}

template <class Derived, class Iterator, class Predicate, class T>
void _CCCL_HOST_DEVICE
replace_if(execution_policy<Derived>& policy, Iterator first, Iterator last, Predicate pred, T const& new_value)
{
cuda_cub::transform_if(policy, first, last, first, __replace::constant_f<T>{new_value}, pred);
cuda_cub::transform_if(policy, first, last, first, CUB_NS_QUALIFIER::detail::__return_constant<T>{new_value}, pred);
}

template <class Derived, class Iterator, class StencilIt, class Predicate, class T>
Expand All @@ -103,7 +72,8 @@ void _CCCL_HOST_DEVICE replace_if(
Predicate pred,
T const& new_value)
{
cuda_cub::transform_if(policy, first, last, stencil, first, __replace::constant_f<T>{new_value}, pred);
cuda_cub::transform_if(
policy, first, last, stencil, first, CUB_NS_QUALIFIER::detail::__return_constant<T>{new_value}, pred);
}

template <class Derived, class InputIt, class OutputIt, class Predicate, class T>
Expand All @@ -116,7 +86,7 @@ OutputIt _CCCL_HOST_DEVICE replace_copy_if(
T const& new_value)
{
using output_type = thrust::detail::it_value_t<OutputIt>;
using new_value_if_t = __replace::new_value_if_f<Predicate, T, output_type>;
using new_value_if_t = thrust::detail::new_value_if_f<Predicate, T, output_type>;
return cuda_cub::transform(policy, first, last, result, new_value_if_t{predicate, new_value});
}

Expand All @@ -131,7 +101,7 @@ OutputIt _CCCL_HOST_DEVICE replace_copy_if(
T const& new_value)
{
using output_type = thrust::detail::it_value_t<OutputIt>;
using new_value_if_t = __replace::new_value_if_f<Predicate, T, output_type>;
using new_value_if_t = thrust::detail::new_value_if_f<Predicate, T, output_type>;
return cuda_cub::transform(policy, first, last, stencil, result, new_value_if_t{predicate, new_value});
}

Expand Down