Skip to content
This repository has been archived by the owner on Mar 21, 2024. It is now read-only.

Commit

Permalink
Use transparent functionals in placeholder expressions.
Browse files Browse the repository at this point in the history
Fixes and adds regression tests for #1178 & #1229.
  • Loading branch information
alliepiper committed Jul 17, 2020
1 parent da47003 commit 1de9eb0
Show file tree
Hide file tree
Showing 11 changed files with 599 additions and 502 deletions.
33 changes: 33 additions & 0 deletions testing/find.cu
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <unittest/unittest.h>
#include <thrust/sequence.h>
#include <thrust/find.h>
#include <thrust/iterator/retag.h>

Expand Down Expand Up @@ -338,3 +339,35 @@ void TestFindWithBigIndexes()
TestFindWithBigIndexesHelper(33);
}
DECLARE_UNITTEST(TestFindWithBigIndexes);

namespace
{

class Weird
{
int value;

public:
__host__ __device__ Weird(int val, int)
: value(val)
{}

friend __host__ __device__
bool operator==(int x, Weird y)
{
return x == y.value;
}
};

} // end anon namespace

void TestFindAsymmetricEquality()
{ // Regression test for thrust/thrust#1229
thrust::host_vector<int> v(1000);
thrust::sequence(v.begin(), v.end());
thrust::device_vector<int> dv(v);
auto result = thrust::find(dv.begin(), dv.end(), Weird(333, 0));
ASSERT_EQUAL(*result, 333);
ASSERT_EQUAL(result - dv.begin(), 333);
}
DECLARE_UNITTEST(TestFindAsymmetricEquality);
18 changes: 18 additions & 0 deletions testing/inner_product.cu
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#include <unittest/unittest.h>
#include <thrust/inner_product.h>

#include <thrust/functional.h>
#include <thrust/iterator/retag.h>
#include <thrust/device_malloc.h>
#include <thrust/device_free.h>
#include <thrust/device_vector.h>

template <class Vector>
void TestInnerProductSimple(void)
Expand Down Expand Up @@ -153,3 +156,18 @@ void TestInnerProductWithBigIndexes()
TestInnerProductWithBigIndexesHelper(33);
}
DECLARE_UNITTEST(TestInnerProductWithBigIndexes);

void TestInnerProductPlaceholders()
{ // Regression test for thrust/thrust#1178
using namespace thrust::placeholders;

thrust::device_vector<float> v1(100, 1.f);
thrust::device_vector<float> v2(100, 1.f);

auto result = thrust::inner_product(v1.begin(), v1.end(), v2.begin(), 0.0f,
thrust::plus<float>{},
_1 * _2 + 1.0f);

ASSERT_ALMOST_EQUAL(result, 200.f);
}
DECLARE_UNITTEST(TestInnerProductPlaceholders);
80 changes: 32 additions & 48 deletions thrust/detail/functional/actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <thrust/detail/functional/value.h>
#include <thrust/detail/functional/composite.h>
#include <thrust/detail/functional/operators/assignment_operator.h>
#include <thrust/detail/raw_reference_cast.h>
#include <thrust/detail/type_traits/result_of_adaptable_function.h>

namespace thrust
Expand All @@ -39,6 +40,34 @@ namespace detail
namespace functional
{

template <typename T, typename = void>
struct eval_ref_impl
{
using type = T&;
};

template <typename T>
struct eval_ref_impl<
T,
typename std::enable_if<thrust::detail::is_wrapped_reference<T>::value>::type>
{
using type = T;
};

// eval_ref<T> is
// - is T when T is a subclass of thrust::reference
// - is T& otherwise
// This is used to let thrust::references pass through actor evaluations.
template <typename T>
using eval_ref =
typename eval_ref_impl<
typename thrust::detail::remove_reference<T>::type
>::type;

// Convenience def for tuple of eval_ref<T>s:
template <typename ...T>
using eval_tuple = thrust::tuple<eval_ref<T>...>;

template<typename Action, typename Env>
struct apply_actor
{
Expand All @@ -61,55 +90,10 @@ template<typename Eval>
typename apply_actor<eval_type, thrust::null_type >::type
operator()(void) const;

template<typename T0>
__host__ __device__
typename apply_actor<eval_type, thrust::tuple<T0&> >::type
operator()(T0 &_0) const;

template<typename T0, typename T1>
__host__ __device__
typename apply_actor<eval_type, thrust::tuple<T0&,T1&> >::type
operator()(T0 &_0, T1 &_1) const;

template<typename T0, typename T1, typename T2>
__host__ __device__
typename apply_actor<eval_type, thrust::tuple<T0&,T1&,T2&> >::type
operator()(T0 &_0, T1 &_1, T2 &_2) const;

template<typename T0, typename T1, typename T2, typename T3>
__host__ __device__
typename apply_actor<eval_type, thrust::tuple<T0&,T1&,T2&,T3&> >::type
operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3) const;

template<typename T0, typename T1, typename T2, typename T3, typename T4>
__host__ __device__
typename apply_actor<eval_type, thrust::tuple<T0&,T1&,T2&,T3&,T4&> >::type
operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3, T4 &_4) const;

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
__host__ __device__
typename apply_actor<eval_type, thrust::tuple<T0&,T1&,T2&,T3&,T4&,T5&> >::type
operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3, T4 &_4, T5 &_5) const;

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
__host__ __device__
typename apply_actor<eval_type, thrust::tuple<T0&,T1&,T2&,T3&,T4&,T5&,T6&> >::type
operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3, T4 &_4, T5 &_5, T6 &_6) const;

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
__host__ __device__
typename apply_actor<eval_type, thrust::tuple<T0&,T1&,T2&,T3&,T4&,T5&,T6&,T7&> >::type
operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3, T4 &_4, T5 &_5, T6 &_6, T7 &_7) const;

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
__host__ __device__
typename apply_actor<eval_type, thrust::tuple<T0&,T1&,T2&,T3&,T4&,T5&,T6&,T7&,T8&> >::type
operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3, T4 &_4, T5 &_5, T6 &_6, T7 &_7, T8 &_8) const;

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
template <typename... Ts>
__host__ __device__
typename apply_actor<eval_type, thrust::tuple<T0&,T1&,T2&,T3&,T4&,T5&,T6&,T7&,T8&,T9&> >::type
operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3, T4 &_4, T5 &_5, T6 &_6, T7 &_7, T8 &_8, T9 &_9) const;
typename apply_actor<eval_type, eval_tuple<Ts...>>::type
operator()(Ts&&... ts) const;

template<typename T>
__host__ __device__
Expand Down
134 changes: 7 additions & 127 deletions thrust/detail/functional/actor.inl
Original file line number Diff line number Diff line change
Expand Up @@ -63,134 +63,14 @@ template<typename Eval>
} // end basic_environment::operator()

template<typename Eval>
template<typename T0>
__host__ __device__
typename apply_actor<
typename actor<Eval>::eval_type,
typename thrust::tuple<T0&>
>::type
actor<Eval>
::operator()(T0 &_0) const
{
return eval_type::eval(thrust::tie(_0));
} // end basic_environment::operator()

template<typename Eval>
template<typename T0, typename T1>
__host__ __device__
typename apply_actor<
typename actor<Eval>::eval_type,
typename thrust::tuple<T0&,T1&>
>::type
actor<Eval>
::operator()(T0 &_0, T1 &_1) const
template<typename... Ts>
__host__ __device__
typename apply_actor<typename actor<Eval>::eval_type, eval_tuple<Ts...>>::type
actor<Eval>::operator()(Ts&&... ts) const
{
return eval_type::eval(thrust::tie(_0,_1));
} // end basic_environment::operator()

template<typename Eval>
template<typename T0, typename T1, typename T2>
__host__ __device__
typename apply_actor<
typename actor<Eval>::eval_type,
typename thrust::tuple<T0&,T1&,T2&>
>::type
actor<Eval>
::operator()(T0 &_0, T1 &_1, T2 &_2) const
{
return eval_type::eval(thrust::tie(_0,_1,_2));
} // end basic_environment::operator()

template<typename Eval>
template<typename T0, typename T1, typename T2, typename T3>
__host__ __device__
typename apply_actor<
typename actor<Eval>::eval_type,
typename thrust::tuple<T0&,T1&,T2&,T3&>
>::type
actor<Eval>
::operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3) const
{
return eval_type::eval(thrust::tie(_0,_1,_2,_3));
} // end basic_environment::operator()

template<typename Eval>
template<typename T0, typename T1, typename T2, typename T3, typename T4>
__host__ __device__
typename apply_actor<
typename actor<Eval>::eval_type,
typename thrust::tuple<T0&,T1&,T2&,T3&,T4&>
>::type
actor<Eval>
::operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3, T4 &_4) const
{
return eval_type::eval(thrust::tie(_0,_1,_2,_3,_4));
} // end basic_environment::operator()

template<typename Eval>
template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
__host__ __device__
typename apply_actor<
typename actor<Eval>::eval_type,
typename thrust::tuple<T0&,T1&,T2&,T3&,T4&,T5&>
>::type
actor<Eval>
::operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3, T4 &_4, T5 &_5) const
{
return eval_type::eval(thrust::tie(_0,_1,_2,_3,_4,_5));
} // end basic_environment::operator()

template<typename Eval>
template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
__host__ __device__
typename apply_actor<
typename actor<Eval>::eval_type,
typename thrust::tuple<T0&,T1&,T2&,T3&,T4&,T5&,T6&>
>::type
actor<Eval>
::operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3, T4 &_4, T5 &_5, T6 &_6) const
{
return eval_type::eval(thrust::tie(_0,_1,_2,_3,_4,_5,_6));
} // end basic_environment::operator()

template<typename Eval>
template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
__host__ __device__
typename apply_actor<
typename actor<Eval>::eval_type,
typename thrust::tuple<T0&,T1&,T2&,T3&,T4&,T5&,T6&,T7&>
>::type
actor<Eval>
::operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3, T4 &_4, T5 &_5, T6 &_6, T7 &_7) const
{
return eval_type::eval(thrust::tie(_0,_1,_2,_3,_4,_5,_6,_7));
} // end basic_environment::operator()

template<typename Eval>
template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
__host__ __device__
typename apply_actor<
typename actor<Eval>::eval_type,
typename thrust::tuple<T0&,T1&,T2&,T3&,T4&,T5&,T6&,T7&,T8&>
>::type
actor<Eval>
::operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3, T4 &_4, T5 &_5, T6 &_6, T7 &_7, T8 &_8) const
{
return eval_type::eval(thrust::tie(_0,_1,_2,_3,_4,_5,_6,_7,_8));
} // end basic_environment::operator()

template<typename Eval>
template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
__host__ __device__
typename apply_actor<
typename actor<Eval>::eval_type,
typename thrust::tuple<T0&,T1&,T2&,T3&,T4&,T5&,T6&,T7&,T8&,T9&>
>::type
actor<Eval>
::operator()(T0 &_0, T1 &_1, T2 &_2, T3 &_3, T4 &_4, T5 &_5, T6 &_6, T7 &_7, T8 &_8, T9 &_9) const
{
return eval_type::eval(thrust::tie(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9));
} // end basic_environment::operator()
using tuple_type = eval_tuple<Ts...>;
return eval_type::eval(tuple_type(THRUST_FWD(ts)...));
} // end actor<Eval>::operator()

template<typename Eval>
template<typename T>
Expand Down
Loading

0 comments on commit 1de9eb0

Please sign in to comment.