| #include <unittest/unittest.h> |
| #include <thrust/sequence.h> |
| #include <thrust/find.h> |
| #include <thrust/iterator/retag.h> |
|
|
|
|
| template <typename T> |
| struct equal_to_value_pred |
| { |
| T value; |
|
|
| equal_to_value_pred(T value) : value(value) {} |
|
|
| __host__ __device__ |
| bool operator()(T v) const { return v == value; } |
| }; |
|
|
| template <typename T> |
| struct not_equal_to_value_pred |
| { |
| T value; |
|
|
| not_equal_to_value_pred(T value) : value(value) {} |
|
|
| __host__ __device__ |
| bool operator()(T v) const { return v != value; } |
| }; |
|
|
| template<typename T> |
| struct less_than_value_pred |
| { |
| T value; |
|
|
| less_than_value_pred(T value) : value(value) {} |
|
|
| __host__ __device__ |
| bool operator()(T v) const { return v < value; } |
| }; |
|
|
| template <class Vector> |
| void TestFindSimple(void) |
| { |
| Vector vec(5); |
| vec[0] = 1; |
| vec[1] = 2; |
| vec[2] = 3; |
| vec[3] = 3; |
| vec[4] = 5; |
|
|
| ASSERT_EQUAL(thrust::find(vec.begin(), vec.end(), 0) - vec.begin(), 5); |
| ASSERT_EQUAL(thrust::find(vec.begin(), vec.end(), 1) - vec.begin(), 0); |
| ASSERT_EQUAL(thrust::find(vec.begin(), vec.end(), 2) - vec.begin(), 1); |
| ASSERT_EQUAL(thrust::find(vec.begin(), vec.end(), 3) - vec.begin(), 2); |
| ASSERT_EQUAL(thrust::find(vec.begin(), vec.end(), 4) - vec.begin(), 5); |
| ASSERT_EQUAL(thrust::find(vec.begin(), vec.end(), 5) - vec.begin(), 4); |
| } |
| DECLARE_VECTOR_UNITTEST(TestFindSimple); |
|
|
| template<typename InputIterator, typename T> |
| InputIterator find(my_system &system, InputIterator first, InputIterator, const T&) |
| { |
| system.validate_dispatch(); |
| return first; |
| } |
|
|
| void TestFindDispatchExplicit() |
| { |
| thrust::device_vector<int> vec(1); |
|
|
| my_system sys(0); |
| thrust::find(sys, |
| vec.begin(), |
| vec.end(), |
| 0); |
|
|
| ASSERT_EQUAL(true, sys.is_valid()); |
| } |
| DECLARE_UNITTEST(TestFindDispatchExplicit); |
|
|
|
|
| template<typename InputIterator, typename T> |
| InputIterator find(my_tag, InputIterator first, InputIterator, const T&) |
| { |
| *first = 13; |
| return first; |
| } |
|
|
| void TestFindDispatchImplicit() |
| { |
| thrust::device_vector<int> vec(1); |
|
|
| thrust::find(thrust::retag<my_tag>(vec.begin()), |
| thrust::retag<my_tag>(vec.end()), |
| 0); |
|
|
| ASSERT_EQUAL(13, vec.front()); |
| } |
| DECLARE_UNITTEST(TestFindDispatchImplicit); |
|
|
|
|
| template <class Vector> |
| void TestFindIfSimple(void) |
| { |
| typedef typename Vector::value_type T; |
|
|
| Vector vec(5); |
| vec[0] = 1; |
| vec[1] = 2; |
| vec[2] = 3; |
| vec[3] = 3; |
| vec[4] = 5; |
|
|
| ASSERT_EQUAL(thrust::find_if(vec.begin(), vec.end(), equal_to_value_pred<T>(0)) - vec.begin(), 5); |
| ASSERT_EQUAL(thrust::find_if(vec.begin(), vec.end(), equal_to_value_pred<T>(1)) - vec.begin(), 0); |
| ASSERT_EQUAL(thrust::find_if(vec.begin(), vec.end(), equal_to_value_pred<T>(2)) - vec.begin(), 1); |
| ASSERT_EQUAL(thrust::find_if(vec.begin(), vec.end(), equal_to_value_pred<T>(3)) - vec.begin(), 2); |
| ASSERT_EQUAL(thrust::find_if(vec.begin(), vec.end(), equal_to_value_pred<T>(4)) - vec.begin(), 5); |
| ASSERT_EQUAL(thrust::find_if(vec.begin(), vec.end(), equal_to_value_pred<T>(5)) - vec.begin(), 4); |
| } |
| DECLARE_VECTOR_UNITTEST(TestFindIfSimple); |
|
|
| template<typename InputIterator, typename Predicate> |
| InputIterator find_if(my_system &system, InputIterator first, InputIterator, Predicate) |
| { |
| system.validate_dispatch(); |
| return first; |
| } |
|
|
| void TestFindIfDispatchExplicit() |
| { |
| thrust::device_vector<int> vec(1); |
|
|
| my_system sys(0); |
| thrust::find_if(sys, |
| vec.begin(), |
| vec.end(), |
| thrust::identity<int>()); |
|
|
| ASSERT_EQUAL(true, sys.is_valid()); |
| } |
| DECLARE_UNITTEST(TestFindIfDispatchExplicit); |
|
|
|
|
| template<typename InputIterator, typename Predicate> |
| InputIterator find_if(my_tag, InputIterator first, InputIterator, Predicate) |
| { |
| *first = 13; |
| return first; |
| } |
|
|
| void TestFindIfDispatchImplicit() |
| { |
| thrust::device_vector<int> vec(1); |
|
|
| thrust::find_if(thrust::retag<my_tag>(vec.begin()), |
| thrust::retag<my_tag>(vec.end()), |
| thrust::identity<int>()); |
|
|
| ASSERT_EQUAL(13, vec.front()); |
| } |
| DECLARE_UNITTEST(TestFindIfDispatchImplicit); |
|
|
|
|
| template <class Vector> |
| void TestFindIfNotSimple(void) |
| { |
| typedef typename Vector::value_type T; |
|
|
| Vector vec(5); |
| vec[0] = 0; |
| vec[1] = 1; |
| vec[2] = 2; |
| vec[3] = 3; |
| vec[4] = 4; |
|
|
| ASSERT_EQUAL(0, thrust::find_if_not(vec.begin(), vec.end(), less_than_value_pred<T>(0)) - vec.begin()); |
| ASSERT_EQUAL(1, thrust::find_if_not(vec.begin(), vec.end(), less_than_value_pred<T>(1)) - vec.begin()); |
| ASSERT_EQUAL(2, thrust::find_if_not(vec.begin(), vec.end(), less_than_value_pred<T>(2)) - vec.begin()); |
| ASSERT_EQUAL(3, thrust::find_if_not(vec.begin(), vec.end(), less_than_value_pred<T>(3)) - vec.begin()); |
| ASSERT_EQUAL(4, thrust::find_if_not(vec.begin(), vec.end(), less_than_value_pred<T>(4)) - vec.begin()); |
| ASSERT_EQUAL(5, thrust::find_if_not(vec.begin(), vec.end(), less_than_value_pred<T>(5)) - vec.begin()); |
| } |
| DECLARE_VECTOR_UNITTEST(TestFindIfNotSimple); |
|
|
|
|
| template<typename InputIterator, typename Predicate> |
| InputIterator find_if_not(my_system &system, InputIterator first, InputIterator, Predicate) |
| { |
| system.validate_dispatch(); |
| return first; |
| } |
|
|
| void TestFindIfNotDispatchExplicit() |
| { |
| thrust::device_vector<int> vec(1); |
|
|
| my_system sys(0); |
| thrust::find_if_not(sys, |
| vec.begin(), |
| vec.end(), |
| thrust::identity<int>()); |
|
|
| ASSERT_EQUAL(true, sys.is_valid()); |
| } |
| DECLARE_UNITTEST(TestFindIfNotDispatchExplicit); |
|
|
|
|
| template<typename InputIterator, typename Predicate> |
| InputIterator find_if_not(my_tag, InputIterator first, InputIterator, Predicate) |
| { |
| *first = 13; |
| return first; |
| } |
|
|
| void TestFindIfNotDispatchImplicit() |
| { |
| thrust::device_vector<int> vec(1); |
|
|
| thrust::find_if_not(thrust::retag<my_tag>(vec.begin()), |
| thrust::retag<my_tag>(vec.end()), |
| thrust::identity<int>()); |
|
|
| ASSERT_EQUAL(13, vec.front()); |
| } |
| DECLARE_UNITTEST(TestFindIfNotDispatchImplicit); |
|
|
|
|
| template <typename T> |
| struct TestFind |
| { |
| void operator()(const size_t n) |
| { |
| thrust::host_vector<T> h_data = unittest::random_integers<T>(n); |
| thrust::device_vector<T> d_data = h_data; |
|
|
| typename thrust::host_vector<T>::iterator h_iter; |
| typename thrust::device_vector<T>::iterator d_iter; |
|
|
| h_iter = thrust::find(h_data.begin(), h_data.end(), T(0)); |
| d_iter = thrust::find(d_data.begin(), d_data.end(), T(0)); |
| ASSERT_EQUAL(h_iter - h_data.begin(), d_iter - d_data.begin()); |
|
|
| for (size_t i = 1; i < n; i *= 2) |
| { |
| T sample = h_data[i]; |
| h_iter = thrust::find(h_data.begin(), h_data.end(), sample); |
| d_iter = thrust::find(d_data.begin(), d_data.end(), sample); |
| ASSERT_EQUAL(h_iter - h_data.begin(), d_iter - d_data.begin()); |
| } |
| } |
| }; |
| VariableUnitTest<TestFind, SignedIntegralTypes> TestFindInstance; |
|
|
|
|
| template <typename T> |
| struct TestFindIf |
| { |
| void operator()(const size_t n) |
| { |
| thrust::host_vector<T> h_data = unittest::random_integers<T>(n); |
| thrust::device_vector<T> d_data = h_data; |
|
|
| typename thrust::host_vector<T>::iterator h_iter; |
| typename thrust::device_vector<T>::iterator d_iter; |
|
|
| h_iter = thrust::find_if(h_data.begin(), h_data.end(), equal_to_value_pred<T>(0)); |
| d_iter = thrust::find_if(d_data.begin(), d_data.end(), equal_to_value_pred<T>(0)); |
| ASSERT_EQUAL(h_iter - h_data.begin(), d_iter - d_data.begin()); |
|
|
| for (size_t i = 1; i < n; i *= 2) |
| { |
| T sample = h_data[i]; |
| h_iter = thrust::find_if(h_data.begin(), h_data.end(), equal_to_value_pred<T>(sample)); |
| d_iter = thrust::find_if(d_data.begin(), d_data.end(), equal_to_value_pred<T>(sample)); |
| ASSERT_EQUAL(h_iter - h_data.begin(), d_iter - d_data.begin()); |
| } |
| } |
| }; |
| VariableUnitTest<TestFindIf, SignedIntegralTypes> TestFindIfInstance; |
|
|
|
|
| template <typename T> |
| struct TestFindIfNot |
| { |
| void operator()(const size_t n) |
| { |
| thrust::host_vector<T> h_data = unittest::random_integers<T>(n); |
| thrust::device_vector<T> d_data = h_data; |
|
|
| typename thrust::host_vector<T>::iterator h_iter; |
| typename thrust::device_vector<T>::iterator d_iter; |
|
|
| h_iter = thrust::find_if_not(h_data.begin(), h_data.end(), not_equal_to_value_pred<T>(0)); |
| d_iter = thrust::find_if_not(d_data.begin(), d_data.end(), not_equal_to_value_pred<T>(0)); |
| ASSERT_EQUAL(h_iter - h_data.begin(), d_iter - d_data.begin()); |
|
|
| for (size_t i = 1; i < n; i *= 2) |
| { |
| T sample = h_data[i]; |
| h_iter = thrust::find_if_not(h_data.begin(), h_data.end(), not_equal_to_value_pred<T>(sample)); |
| d_iter = thrust::find_if_not(d_data.begin(), d_data.end(), not_equal_to_value_pred<T>(sample)); |
| ASSERT_EQUAL(h_iter - h_data.begin(), d_iter - d_data.begin()); |
| } |
| } |
| }; |
| VariableUnitTest<TestFindIfNot, SignedIntegralTypes> TestFindIfNotInstance; |
|
|
| void TestFindWithBigIndexesHelper(int magnitude) |
| { |
| thrust::counting_iterator<long long> begin(1); |
| thrust::counting_iterator<long long> end = begin + (1ll << magnitude); |
| ASSERT_EQUAL(thrust::distance(begin, end), 1ll << magnitude); |
|
|
| thrust::detail::intmax_t distance_low_value = thrust::distance( |
| begin, |
| thrust::find( |
| thrust::device, |
| begin, |
| end, |
| 17)); |
|
|
| thrust::detail::intmax_t distance_high_value = thrust::distance( |
| begin, |
| thrust::find( |
| thrust::device, |
| begin, |
| end, |
| (1ll << magnitude) - 17)); |
|
|
| ASSERT_EQUAL(distance_low_value, 16); |
| ASSERT_EQUAL(distance_high_value, (1ll << magnitude) - 18); |
| } |
|
|
| void TestFindWithBigIndexes() |
| { |
| TestFindWithBigIndexesHelper(30); |
| TestFindWithBigIndexesHelper(31); |
| TestFindWithBigIndexesHelper(32); |
| 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; |
| } |
| }; |
|
|
| } |
|
|
| void TestFindAsymmetricEquality() |
| { |
| 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); |
|
|