Spaces:
Sleeping
Sleeping
| #include <unittest/unittest.h> | |
| #include <thrust/scan.h> | |
| #include <thrust/functional.h> | |
| #include <thrust/iterator/discard_iterator.h> | |
| #include <thrust/iterator/constant_iterator.h> | |
| #include <thrust/iterator/retag.h> | |
| #include <thrust/device_malloc.h> | |
| #include <thrust/device_free.h> | |
| template<typename T> | |
| struct max_functor | |
| { | |
| __host__ __device__ | |
| T operator()(T rhs, T lhs) const | |
| { | |
| return thrust::max(rhs,lhs); | |
| } | |
| }; | |
| template <class Vector> | |
| void TestScanSimple(void) | |
| { | |
| typedef typename Vector::value_type T; | |
| typename Vector::iterator iter; | |
| Vector input(5); | |
| Vector result(5); | |
| Vector output(5); | |
| input[0] = 1; input[1] = 3; input[2] = -2; input[3] = 4; input[4] = -5; | |
| Vector input_copy(input); | |
| // inclusive scan | |
| iter = thrust::inclusive_scan(input.begin(), input.end(), output.begin()); | |
| result[0] = 1; result[1] = 4; result[2] = 2; result[3] = 6; result[4] = 1; | |
| ASSERT_EQUAL(std::size_t(iter - output.begin()), input.size()); | |
| ASSERT_EQUAL(input, input_copy); | |
| ASSERT_EQUAL(output, result); | |
| // exclusive scan | |
| iter = thrust::exclusive_scan(input.begin(), input.end(), output.begin(), T(0)); | |
| result[0] = 0; result[1] = 1; result[2] = 4; result[3] = 2; result[4] = 6; | |
| ASSERT_EQUAL(std::size_t(iter - output.begin()), input.size()); | |
| ASSERT_EQUAL(input, input_copy); | |
| ASSERT_EQUAL(output, result); | |
| // exclusive scan with init | |
| iter = thrust::exclusive_scan(input.begin(), input.end(), output.begin(), T(3)); | |
| result[0] = 3; result[1] = 4; result[2] = 7; result[3] = 5; result[4] = 9; | |
| ASSERT_EQUAL(std::size_t(iter - output.begin()), input.size()); | |
| ASSERT_EQUAL(input, input_copy); | |
| ASSERT_EQUAL(output, result); | |
| // inclusive scan with op | |
| iter = thrust::inclusive_scan(input.begin(), input.end(), output.begin(), thrust::plus<T>()); | |
| result[0] = 1; result[1] = 4; result[2] = 2; result[3] = 6; result[4] = 1; | |
| ASSERT_EQUAL(std::size_t(iter - output.begin()), input.size()); | |
| ASSERT_EQUAL(input, input_copy); | |
| ASSERT_EQUAL(output, result); | |
| // exclusive scan with init and op | |
| iter = thrust::exclusive_scan(input.begin(), input.end(), output.begin(), T(3), thrust::plus<T>()); | |
| result[0] = 3; result[1] = 4; result[2] = 7; result[3] = 5; result[4] = 9; | |
| ASSERT_EQUAL(std::size_t(iter - output.begin()), input.size()); | |
| ASSERT_EQUAL(input, input_copy); | |
| ASSERT_EQUAL(output, result); | |
| // inplace inclusive scan | |
| input = input_copy; | |
| iter = thrust::inclusive_scan(input.begin(), input.end(), input.begin()); | |
| result[0] = 1; result[1] = 4; result[2] = 2; result[3] = 6; result[4] = 1; | |
| ASSERT_EQUAL(std::size_t(iter - input.begin()), input.size()); | |
| ASSERT_EQUAL(input, result); | |
| // inplace exclusive scan with init | |
| input = input_copy; | |
| iter = thrust::exclusive_scan(input.begin(), input.end(), input.begin(), T(3)); | |
| result[0] = 3; result[1] = 4; result[2] = 7; result[3] = 5; result[4] = 9; | |
| ASSERT_EQUAL(std::size_t(iter - input.begin()), input.size()); | |
| ASSERT_EQUAL(input, result); | |
| // inplace exclusive scan with implicit init=0 | |
| input = input_copy; | |
| iter = thrust::exclusive_scan(input.begin(), input.end(), input.begin()); | |
| result[0] = 0; result[1] = 1; result[2] = 4; result[3] = 2; result[4] = 6; | |
| ASSERT_EQUAL(std::size_t(iter - input.begin()), input.size()); | |
| ASSERT_EQUAL(input, result); | |
| } | |
| DECLARE_VECTOR_UNITTEST(TestScanSimple); | |
| template<typename InputIterator, | |
| typename OutputIterator> | |
| OutputIterator inclusive_scan(my_system &system, | |
| InputIterator, | |
| InputIterator, | |
| OutputIterator result) | |
| { | |
| system.validate_dispatch(); | |
| return result; | |
| } | |
| void TestInclusiveScanDispatchExplicit() | |
| { | |
| thrust::device_vector<int> vec(1); | |
| my_system sys(0); | |
| thrust::inclusive_scan(sys, | |
| vec.begin(), | |
| vec.begin(), | |
| vec.begin()); | |
| ASSERT_EQUAL(true, sys.is_valid()); | |
| } | |
| DECLARE_UNITTEST(TestInclusiveScanDispatchExplicit); | |
| template<typename InputIterator, | |
| typename OutputIterator> | |
| OutputIterator inclusive_scan(my_tag, | |
| InputIterator, | |
| InputIterator, | |
| OutputIterator result) | |
| { | |
| *result = 13; | |
| return result; | |
| } | |
| void TestInclusiveScanDispatchImplicit() | |
| { | |
| thrust::device_vector<int> vec(1); | |
| thrust::inclusive_scan(thrust::retag<my_tag>(vec.begin()), | |
| thrust::retag<my_tag>(vec.begin()), | |
| thrust::retag<my_tag>(vec.begin())); | |
| ASSERT_EQUAL(13, vec.front()); | |
| } | |
| DECLARE_UNITTEST(TestInclusiveScanDispatchImplicit); | |
| template<typename InputIterator, | |
| typename OutputIterator> | |
| OutputIterator exclusive_scan(my_system &system, | |
| InputIterator, | |
| InputIterator, | |
| OutputIterator result) | |
| { | |
| system.validate_dispatch(); | |
| return result; | |
| } | |
| void TestExclusiveScanDispatchExplicit() | |
| { | |
| thrust::device_vector<int> vec(1); | |
| my_system sys(0); | |
| thrust::exclusive_scan(sys, | |
| vec.begin(), | |
| vec.begin(), | |
| vec.begin()); | |
| ASSERT_EQUAL(true, sys.is_valid()); | |
| } | |
| DECLARE_UNITTEST(TestExclusiveScanDispatchExplicit); | |
| template<typename InputIterator, | |
| typename OutputIterator> | |
| OutputIterator exclusive_scan(my_tag, | |
| InputIterator, | |
| InputIterator, | |
| OutputIterator result) | |
| { | |
| *result = 13; | |
| return result; | |
| } | |
| void TestExclusiveScanDispatchImplicit() | |
| { | |
| thrust::device_vector<int> vec(1); | |
| thrust::exclusive_scan(thrust::retag<my_tag>(vec.begin()), | |
| thrust::retag<my_tag>(vec.begin()), | |
| thrust::retag<my_tag>(vec.begin())); | |
| ASSERT_EQUAL(13, vec.front()); | |
| } | |
| DECLARE_UNITTEST(TestExclusiveScanDispatchImplicit); | |
| void TestInclusiveScan32(void) | |
| { | |
| typedef int T; | |
| size_t n = 32; | |
| thrust::host_vector<T> h_input = unittest::random_integers<T>(n); | |
| thrust::device_vector<T> d_input = h_input; | |
| thrust::host_vector<T> h_output(n); | |
| thrust::device_vector<T> d_output(n); | |
| thrust::inclusive_scan(h_input.begin(), h_input.end(), h_output.begin()); | |
| thrust::inclusive_scan(d_input.begin(), d_input.end(), d_output.begin()); | |
| ASSERT_EQUAL(d_output, h_output); | |
| } | |
| DECLARE_UNITTEST(TestInclusiveScan32); | |
| void TestExclusiveScan32(void) | |
| { | |
| typedef int T; | |
| size_t n = 32; | |
| T init = 13; | |
| thrust::host_vector<T> h_input = unittest::random_integers<T>(n); | |
| thrust::device_vector<T> d_input = h_input; | |
| thrust::host_vector<T> h_output(n); | |
| thrust::device_vector<T> d_output(n); | |
| thrust::exclusive_scan(h_input.begin(), h_input.end(), h_output.begin(), init); | |
| thrust::exclusive_scan(d_input.begin(), d_input.end(), d_output.begin(), init); | |
| ASSERT_EQUAL(d_output, h_output); | |
| } | |
| DECLARE_UNITTEST(TestExclusiveScan32); | |
| template <class IntVector, class FloatVector> | |
| void TestScanMixedTypes(void) | |
| { | |
| // make sure we get types for default args and operators correct | |
| IntVector int_input(4); | |
| int_input[0] = 1; | |
| int_input[1] = 2; | |
| int_input[2] = 3; | |
| int_input[3] = 4; | |
| FloatVector float_input(4); | |
| float_input[0] = 1.5; | |
| float_input[1] = 2.5; | |
| float_input[2] = 3.5; | |
| float_input[3] = 4.5; | |
| IntVector int_output(4); | |
| FloatVector float_output(4); | |
| // float -> int should use plus<void> operator and float accumulator by default | |
| thrust::inclusive_scan(float_input.begin(), float_input.end(), int_output.begin()); | |
| ASSERT_EQUAL(int_output[0], 1); // in: 1.5 accum: 1.5f out: 1 | |
| ASSERT_EQUAL(int_output[1], 4); // in: 2.5 accum: 4.0f out: 4 | |
| ASSERT_EQUAL(int_output[2], 7); // in: 3.5 accum: 7.5f out: 7 | |
| ASSERT_EQUAL(int_output[3], 12); // in: 4.5 accum: 12.f out: 12 | |
| // float -> float with plus<int> operator (float accumulator) | |
| thrust::inclusive_scan(float_input.begin(), float_input.end(), float_output.begin(), thrust::plus<int>()); | |
| ASSERT_EQUAL(float_output[0], 1.5f); // in: 1.5 accum: 1.5f out: 1.5f | |
| ASSERT_EQUAL(float_output[1], 3.0f); // in: 2.5 accum: 3.0f out: 3.0f | |
| ASSERT_EQUAL(float_output[2], 6.0f); // in: 3.5 accum: 6.0f out: 6.0f | |
| ASSERT_EQUAL(float_output[3], 10.0f); // in: 4.5 accum: 10.f out: 10.f | |
| // float -> int should use plus<void> operator and float accumulator by default | |
| thrust::exclusive_scan(float_input.begin(), float_input.end(), int_output.begin()); | |
| ASSERT_EQUAL(int_output[0], 0); // out: 0.0f in: 1.5 accum: 1.5f | |
| ASSERT_EQUAL(int_output[1], 1); // out: 1.5f in: 2.5 accum: 4.0f | |
| ASSERT_EQUAL(int_output[2], 4); // out: 4.0f in: 3.5 accum: 7.5f | |
| ASSERT_EQUAL(int_output[3], 7); // out: 7.5f in: 4.5 accum: 12.f | |
| // float -> int should use plus<> operator and float accumulator by default | |
| thrust::exclusive_scan(float_input.begin(), float_input.end(), int_output.begin(), (float) 5.5); | |
| ASSERT_EQUAL(int_output[0], 5); // out: 5.5f in: 1.5 accum: 7.0f | |
| ASSERT_EQUAL(int_output[1], 7); // out: 7.0f in: 2.5 accum: 9.5f | |
| ASSERT_EQUAL(int_output[2], 9); // out: 9.5f in: 3.5 accum: 13.0f | |
| ASSERT_EQUAL(int_output[3], 13); // out: 13.f in: 4.5 accum: 17.4f | |
| // int -> float should use using plus<> operator and int accumulator by default | |
| thrust::inclusive_scan(int_input.begin(), int_input.end(), float_output.begin()); | |
| ASSERT_EQUAL(float_output[0], 1.f); // in: 1 accum: 1 out: 1 | |
| ASSERT_EQUAL(float_output[1], 3.f); // in: 2 accum: 3 out: 3 | |
| ASSERT_EQUAL(float_output[2], 6.f); // in: 3 accum: 6 out: 6 | |
| ASSERT_EQUAL(float_output[3], 10.f); // in: 4 accum: 10 out: 10 | |
| // int -> float + float init_value should use using plus<> operator and | |
| // float accumulator by default | |
| thrust::exclusive_scan(int_input.begin(), int_input.end(), float_output.begin(), (float) 5.5); | |
| ASSERT_EQUAL(float_output[0], 5.5f); // out: 5.5f in: 1 accum: 6.5f | |
| ASSERT_EQUAL(float_output[1], 6.5f); // out: 6.0f in: 2 accum: 8.5f | |
| ASSERT_EQUAL(float_output[2], 8.5f); // out: 8.0f in: 3 accum: 11.5f | |
| ASSERT_EQUAL(float_output[3], 11.5f); // out: 11.f in: 4 accum: 15.5f | |
| } | |
| void TestScanMixedTypesHost(void) | |
| { | |
| TestScanMixedTypes< thrust::host_vector<int>, thrust::host_vector<float> >(); | |
| } | |
| DECLARE_UNITTEST(TestScanMixedTypesHost); | |
| void TestScanMixedTypesDevice(void) | |
| { | |
| TestScanMixedTypes< thrust::device_vector<int>, thrust::device_vector<float> >(); | |
| } | |
| DECLARE_UNITTEST(TestScanMixedTypesDevice); | |
| template <typename T> | |
| struct TestScanWithOperator | |
| { | |
| void operator()(const size_t n) | |
| { | |
| thrust::host_vector<T> h_input = unittest::random_integers<T>(n); | |
| thrust::device_vector<T> d_input = h_input; | |
| thrust::host_vector<T> h_output(n); | |
| thrust::device_vector<T> d_output(n); | |
| thrust::inclusive_scan(h_input.begin(), h_input.end(), h_output.begin(), max_functor<T>()); | |
| thrust::inclusive_scan(d_input.begin(), d_input.end(), d_output.begin(), max_functor<T>()); | |
| ASSERT_EQUAL(d_output, h_output); | |
| thrust::exclusive_scan(h_input.begin(), h_input.end(), h_output.begin(), T(13), max_functor<T>()); | |
| thrust::exclusive_scan(d_input.begin(), d_input.end(), d_output.begin(), T(13), max_functor<T>()); | |
| ASSERT_EQUAL(d_output, h_output); | |
| } | |
| }; | |
| VariableUnitTest<TestScanWithOperator, SignedIntegralTypes> TestScanWithOperatorInstance; | |
| template <typename T> | |
| struct TestScanWithOperatorToDiscardIterator | |
| { | |
| void operator()(const size_t n) | |
| { | |
| thrust::host_vector<T> h_input = unittest::random_integers<T>(n); | |
| thrust::device_vector<T> d_input = h_input; | |
| thrust::discard_iterator<> reference(n); | |
| thrust::discard_iterator<> h_result = | |
| thrust::inclusive_scan(h_input.begin(), h_input.end(), thrust::make_discard_iterator(), max_functor<T>()); | |
| thrust::discard_iterator<> d_result = | |
| thrust::inclusive_scan(d_input.begin(), d_input.end(), thrust::make_discard_iterator(), max_functor<T>()); | |
| ASSERT_EQUAL_QUIET(reference, h_result); | |
| ASSERT_EQUAL_QUIET(reference, d_result); | |
| h_result = | |
| thrust::exclusive_scan(h_input.begin(), h_input.end(), thrust::make_discard_iterator(), T(13), max_functor<T>()); | |
| d_result = | |
| thrust::exclusive_scan(d_input.begin(), d_input.end(), thrust::make_discard_iterator(), T(13), max_functor<T>()); | |
| ASSERT_EQUAL_QUIET(reference, h_result); | |
| ASSERT_EQUAL_QUIET(reference, d_result); | |
| } | |
| }; | |
| VariableUnitTest<TestScanWithOperatorToDiscardIterator, unittest::type_list<unittest::int8_t,unittest::int16_t,unittest::int32_t> > TestScanWithOperatorToDiscardIteratorInstance; | |
| template <typename T> | |
| struct TestScan | |
| { | |
| void operator()(const size_t n) | |
| { | |
| thrust::host_vector<T> h_input = unittest::random_integers<T>(n); | |
| thrust::device_vector<T> d_input = h_input; | |
| thrust::host_vector<T> h_output(n); | |
| thrust::device_vector<T> d_output(n); | |
| thrust::inclusive_scan(h_input.begin(), h_input.end(), h_output.begin()); | |
| thrust::inclusive_scan(d_input.begin(), d_input.end(), d_output.begin()); | |
| ASSERT_EQUAL(d_output, h_output); | |
| thrust::exclusive_scan(h_input.begin(), h_input.end(), h_output.begin()); | |
| thrust::exclusive_scan(d_input.begin(), d_input.end(), d_output.begin()); | |
| ASSERT_EQUAL(d_output, h_output); | |
| thrust::exclusive_scan(h_input.begin(), h_input.end(), h_output.begin(), (T) 11); | |
| thrust::exclusive_scan(d_input.begin(), d_input.end(), d_output.begin(), (T) 11); | |
| ASSERT_EQUAL(d_output, h_output); | |
| // in-place scans | |
| h_output = h_input; | |
| d_output = d_input; | |
| thrust::inclusive_scan(h_output.begin(), h_output.end(), h_output.begin()); | |
| thrust::inclusive_scan(d_output.begin(), d_output.end(), d_output.begin()); | |
| ASSERT_EQUAL(d_output, h_output); | |
| h_output = h_input; | |
| d_output = d_input; | |
| thrust::exclusive_scan(h_output.begin(), h_output.end(), h_output.begin()); | |
| thrust::exclusive_scan(d_output.begin(), d_output.end(), d_output.begin()); | |
| ASSERT_EQUAL(d_output, h_output); | |
| } | |
| }; | |
| VariableUnitTest<TestScan, IntegralTypes> TestScanInstance; | |
| template <typename T> | |
| struct TestScanToDiscardIterator | |
| { | |
| void operator()(const size_t n) | |
| { | |
| thrust::host_vector<T> h_input = unittest::random_integers<T>(n); | |
| thrust::device_vector<T> d_input = h_input; | |
| thrust::discard_iterator<> h_result = | |
| thrust::inclusive_scan(h_input.begin(), h_input.end(), thrust::make_discard_iterator()); | |
| thrust::discard_iterator<> d_result = | |
| thrust::inclusive_scan(d_input.begin(), d_input.end(), thrust::make_discard_iterator()); | |
| thrust::discard_iterator<> reference(n); | |
| ASSERT_EQUAL_QUIET(reference, h_result); | |
| ASSERT_EQUAL_QUIET(reference, d_result); | |
| h_result = | |
| thrust::exclusive_scan(h_input.begin(), h_input.end(), thrust::make_discard_iterator(), (T) 11); | |
| d_result = | |
| thrust::exclusive_scan(d_input.begin(), d_input.end(), thrust::make_discard_iterator(), (T) 11); | |
| ASSERT_EQUAL_QUIET(reference, h_result); | |
| ASSERT_EQUAL_QUIET(reference, d_result); | |
| } | |
| }; | |
| VariableUnitTest<TestScanToDiscardIterator, unittest::type_list<unittest::int8_t,unittest::int16_t,unittest::int32_t> > TestScanToDiscardIteratorInstance; | |
| void TestScanMixedTypes(void) | |
| { | |
| const unsigned int n = 113; | |
| thrust::host_vector<unsigned int> h_input = unittest::random_integers<unsigned int>(n); | |
| for(size_t i = 0; i < n; i++) | |
| h_input[i] %= 10; | |
| thrust::device_vector<unsigned int> d_input = h_input; | |
| thrust::host_vector<float> h_float_output(n); | |
| thrust::device_vector<float> d_float_output(n); | |
| thrust::host_vector<int> h_int_output(n); | |
| thrust::device_vector<int> d_int_output(n); | |
| //mixed input/output types | |
| thrust::inclusive_scan(h_input.begin(), h_input.end(), h_float_output.begin()); | |
| thrust::inclusive_scan(d_input.begin(), d_input.end(), d_float_output.begin()); | |
| ASSERT_EQUAL(d_float_output, h_float_output); | |
| thrust::exclusive_scan(h_input.begin(), h_input.end(), h_float_output.begin(), (float) 3.5); | |
| thrust::exclusive_scan(d_input.begin(), d_input.end(), d_float_output.begin(), (float) 3.5); | |
| ASSERT_EQUAL(d_float_output, h_float_output); | |
| thrust::exclusive_scan(h_input.begin(), h_input.end(), h_float_output.begin(), (int) 3); | |
| thrust::exclusive_scan(d_input.begin(), d_input.end(), d_float_output.begin(), (int) 3); | |
| ASSERT_EQUAL(d_float_output, h_float_output); | |
| thrust::exclusive_scan(h_input.begin(), h_input.end(), h_int_output.begin(), (int) 3); | |
| thrust::exclusive_scan(d_input.begin(), d_input.end(), d_int_output.begin(), (int) 3); | |
| ASSERT_EQUAL(d_int_output, h_int_output); | |
| thrust::exclusive_scan(h_input.begin(), h_input.end(), h_int_output.begin(), (float) 3.5); | |
| thrust::exclusive_scan(d_input.begin(), d_input.end(), d_int_output.begin(), (float) 3.5); | |
| ASSERT_EQUAL(d_int_output, h_int_output); | |
| } | |
| DECLARE_UNITTEST(TestScanMixedTypes); | |
| template <typename T, unsigned int N> | |
| void _TestScanWithLargeTypes(void) | |
| { | |
| size_t n = (1024 * 1024) / sizeof(FixedVector<T,N>); | |
| thrust::host_vector< FixedVector<T,N> > h_input(n); | |
| thrust::host_vector< FixedVector<T,N> > h_output(n); | |
| for(size_t i = 0; i < h_input.size(); i++) | |
| h_input[i] = FixedVector<T,N>(i); | |
| thrust::device_vector< FixedVector<T,N> > d_input = h_input; | |
| thrust::device_vector< FixedVector<T,N> > d_output(n); | |
| thrust::inclusive_scan(h_input.begin(), h_input.end(), h_output.begin()); | |
| thrust::inclusive_scan(d_input.begin(), d_input.end(), d_output.begin()); | |
| ASSERT_EQUAL_QUIET(h_output, d_output); | |
| thrust::exclusive_scan(h_input.begin(), h_input.end(), h_output.begin(), FixedVector<T,N>(0)); | |
| thrust::exclusive_scan(d_input.begin(), d_input.end(), d_output.begin(), FixedVector<T,N>(0)); | |
| ASSERT_EQUAL_QUIET(h_output, d_output); | |
| } | |
| void TestScanWithLargeTypes(void) | |
| { | |
| _TestScanWithLargeTypes<int, 1>(); | |
| #if !defined(__QNX__) | |
| _TestScanWithLargeTypes<int, 8>(); | |
| _TestScanWithLargeTypes<int, 64>(); | |
| #else | |
| KNOWN_FAILURE; | |
| #endif | |
| } | |
| DECLARE_UNITTEST(TestScanWithLargeTypes); | |
| template <typename T> | |
| struct plus_mod3 | |
| { | |
| T * table; | |
| plus_mod3(T * table) : table(table) {} | |
| __host__ __device__ | |
| T operator()(T a, T b) | |
| { | |
| return table[(int) (a + b)]; | |
| } | |
| }; | |
| template <typename Vector> | |
| void TestInclusiveScanWithIndirection(void) | |
| { | |
| // add numbers modulo 3 with external lookup table | |
| typedef typename Vector::value_type T; | |
| Vector data(7); | |
| data[0] = 0; | |
| data[1] = 1; | |
| data[2] = 2; | |
| data[3] = 1; | |
| data[4] = 2; | |
| data[5] = 0; | |
| data[6] = 1; | |
| Vector table(6); | |
| table[0] = 0; | |
| table[1] = 1; | |
| table[2] = 2; | |
| table[3] = 0; | |
| table[4] = 1; | |
| table[5] = 2; | |
| thrust::inclusive_scan(data.begin(), data.end(), data.begin(), plus_mod3<T>(thrust::raw_pointer_cast(&table[0]))); | |
| ASSERT_EQUAL(data[0], T(0)); | |
| ASSERT_EQUAL(data[1], T(1)); | |
| ASSERT_EQUAL(data[2], T(0)); | |
| ASSERT_EQUAL(data[3], T(1)); | |
| ASSERT_EQUAL(data[4], T(0)); | |
| ASSERT_EQUAL(data[5], T(0)); | |
| ASSERT_EQUAL(data[6], T(1)); | |
| } | |
| DECLARE_INTEGRAL_VECTOR_UNITTEST(TestInclusiveScanWithIndirection); | |
| struct only_set_when_expected_it | |
| { | |
| long long expected; | |
| bool * flag; | |
| __host__ __device__ only_set_when_expected_it operator++() const { return *this; } | |
| __host__ __device__ only_set_when_expected_it operator*() const { return *this; } | |
| template<typename Difference> | |
| __host__ __device__ only_set_when_expected_it operator+(Difference) const { return *this; } | |
| template<typename Index> | |
| __host__ __device__ only_set_when_expected_it operator[](Index) const { return *this; } | |
| __device__ | |
| void operator=(long long value) const | |
| { | |
| if (value == expected) | |
| { | |
| *flag = true; | |
| } | |
| } | |
| }; | |
| namespace thrust | |
| { | |
| template<> | |
| struct iterator_traits<only_set_when_expected_it> | |
| { | |
| typedef long long value_type; | |
| typedef only_set_when_expected_it reference; | |
| }; | |
| } | |
| void TestInclusiveScanWithBigIndexesHelper(int magnitude) | |
| { | |
| thrust::constant_iterator<long long> begin(1); | |
| thrust::constant_iterator<long long> end = begin + (1ll << magnitude); | |
| ASSERT_EQUAL(thrust::distance(begin, end), 1ll << magnitude); | |
| thrust::device_ptr<bool> has_executed = thrust::device_malloc<bool>(1); | |
| *has_executed = false; | |
| only_set_when_expected_it out = { (1ll << magnitude), thrust::raw_pointer_cast(has_executed) }; | |
| thrust::inclusive_scan(thrust::device, begin, end, out); | |
| bool has_executed_h = *has_executed; | |
| thrust::device_free(has_executed); | |
| ASSERT_EQUAL(has_executed_h, true); | |
| } | |
| void TestInclusiveScanWithBigIndexes() | |
| { | |
| TestInclusiveScanWithBigIndexesHelper(30); | |
| TestInclusiveScanWithBigIndexesHelper(31); | |
| TestInclusiveScanWithBigIndexesHelper(32); | |
| TestInclusiveScanWithBigIndexesHelper(33); | |
| } | |
| DECLARE_UNITTEST(TestInclusiveScanWithBigIndexes); | |
| void TestExclusiveScanWithBigIndexesHelper(int magnitude) | |
| { | |
| thrust::constant_iterator<long long> begin(1); | |
| thrust::constant_iterator<long long> end = begin + (1ll << magnitude); | |
| ASSERT_EQUAL(thrust::distance(begin, end), 1ll << magnitude); | |
| thrust::device_ptr<bool> has_executed = thrust::device_malloc<bool>(1); | |
| *has_executed = false; | |
| only_set_when_expected_it out = { (1ll << magnitude) - 1, thrust::raw_pointer_cast(has_executed) }; | |
| thrust::exclusive_scan(thrust::device, begin, end, out,0ll); | |
| bool has_executed_h = *has_executed; | |
| thrust::device_free(has_executed); | |
| ASSERT_EQUAL(has_executed_h, true); | |
| } | |
| void TestExclusiveScanWithBigIndexes() | |
| { | |
| TestExclusiveScanWithBigIndexesHelper(30); | |
| TestExclusiveScanWithBigIndexesHelper(31); | |
| TestExclusiveScanWithBigIndexesHelper(32); | |
| TestExclusiveScanWithBigIndexesHelper(33); | |
| } | |
| DECLARE_UNITTEST(TestExclusiveScanWithBigIndexes); | |
| #if THRUST_CPP_DIALECT >= 2011 | |
| struct Int { | |
| int i{}; | |
| __host__ __device__ explicit Int(int num) : i(num) {} | |
| __host__ __device__ Int() : i{} {} | |
| __host__ __device__ Int operator+(Int const& o) const { return Int{this->i + o.i}; } | |
| }; | |
| void TestInclusiveScanWithUserDefinedType() | |
| { | |
| thrust::device_vector<Int> vec(5, Int{1}); | |
| thrust::inclusive_scan( | |
| thrust::device, | |
| vec.cbegin(), | |
| vec.cend(), | |
| vec.begin()); | |
| ASSERT_EQUAL(static_cast<Int>(vec.back()).i, 5); | |
| } | |
| DECLARE_UNITTEST(TestInclusiveScanWithUserDefinedType); | |
| #endif // c++11 | |