fix transform_inclusive_scan with different value types
MODIFY
testing/transform_scan.cu
testing/transform_scan.cu
@@ -211,6 +211,61 @@ void TestTransformScanSimple(void)
}
DECLARE_INTEGRAL_VECTOR_UNITTEST(TestTransformScanSimple);
+struct Record {
+ int number;
+
+ bool operator==(const Record& rhs) const {
+ return number == rhs.number;
+ }
+ bool operator!=(const Record& rhs) const {
+ return !(rhs == *this);
+ }
+ friend Record operator+(Record lhs, const Record& rhs) {
+ lhs.number += rhs.number;
+ return lhs;
+ }
+ friend std::ostream& operator<<(std::ostream& os, const Record& record) {
+ os << "number: " << record.number;
+ return os;
+ }
+};
+
+struct negate {
+ __host__ __device__ int operator()(Record const& record) const
+ {
+ return - record.number;
+ }
+};
+
+void TestTransformInclusiveScanDifferentTypes()
+{
+ typename thrust::host_vector<int>::iterator h_iter;
+
+ thrust::host_vector<Record> h_input(5);
+ thrust::host_vector<int> h_output(5);
+ thrust::host_vector<int> result(5);
+
+ h_input[0] = {1}; h_input[1] = {3}; h_input[2] = {-2}; h_input[3] = {4}; h_input[4] = {-5};
+
+ thrust::host_vector<Record> input_copy(h_input);
+
+ h_iter = thrust::transform_inclusive_scan(h_input.begin(), h_input.end(), h_output.begin(), negate{}, thrust::plus<int>{});
+ result[0] = -1; result[1] = -4; result[2] = -2; result[3] = -6; result[4] = -1;
+ ASSERT_EQUAL(std::size_t(h_iter - h_output.begin()), h_input.size());
+ ASSERT_EQUAL(h_input, input_copy);
+ ASSERT_EQUAL(h_output, result);
+
+ typename thrust::device_vector<int>::iterator d_iter;
+
+ thrust::device_vector<Record> d_input = h_input;
+ thrust::device_vector<int> d_output(5);
+
+ d_iter = thrust::transform_inclusive_scan(d_input.begin(), d_input.end(), d_output.begin(), negate{}, thrust::plus<int>{});
+ ASSERT_EQUAL(std::size_t(d_iter - d_output.begin()), d_input.size());
+ ASSERT_EQUAL(d_input, input_copy);
+ ASSERT_EQUAL(d_output, result);
+}
+DECLARE_UNITTEST(TestTransformInclusiveScanDifferentTypes);
template <typename T>
struct TestTransformScan

MODIFY
thrust/system/cuda/detail/transform_scan.h
thrust/system/cuda/detail/transform_scan.h
@@ -50,8 +50,8 @@ transform_inclusive_scan(execution_policy<Derived> &policy,
TransformOp transform_op,
ScanOp scan_op)
{
- // Use the input iterator's value type per https://wg21.link/P0571
- using result_type = typename thrust::iterator_value<InputIt>::type;
+ using input_type = typename thrust::iterator_value<InputIt>::type;
+ using result_type = typename std::result_of<TransformOp(input_type)>::type;
typedef typename iterator_traits<InputIt>::difference_type size_type;
size_type num_items = static_cast<size_type>(thrust::distance(first, last));

MODIFY
thrust/system/detail/generic/transform_scan.inl
thrust/system/detail/generic/transform_scan.inl
@@ -48,8 +48,8 @@ __host__ __device__
UnaryFunction unary_op,
BinaryFunction binary_op)
{
- // Use the input iterator's value type per https://wg21.link/P0571
- using ValueType = typename thrust::iterator_value<InputIterator>::type;
+ using InputType = typename thrust::iterator_value<InputIterator>::type;
+ using ValueType = typename std::result_of<UnaryFunction(InputType)>::type;
thrust::transform_iterator<UnaryFunction, InputIterator, ValueType> _first(first, unary_op);
thrust::transform_iterator<UnaryFunction, InputIterator, ValueType> _last(last, unary_op);

fix transform_inclusive_scan with different value types