From d9c988b200202673df4349813651ad88674daeec Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Tue, 2 Mar 2021 13:08:51 -0700 Subject: [PATCH] Allow for different types in basic type operators The basic type operators in `Types.h` (i.e. `vtkm::Add`, `vtkm::Subtract`, `vtkm::Multiply` and `vtkm::Divide`) required the same type for both arguments. This caused problems when used with `Reduce` and the initial value type did not match exactly. Use some tricks from `BinaryOperators.h` to be flexible about using different types. --- vtkm/Types.h | 68 +++++++++++++++++++----- vtkm/cont/testing/TestingDeviceAdapter.h | 6 +-- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/vtkm/Types.h b/vtkm/Types.h index 4adb6f68a..35db388f2 100644 --- a/vtkm/Types.h +++ b/vtkm/Types.h @@ -221,37 +221,81 @@ struct NullType #endif // gcc || clang struct Add { - template - inline VTKM_EXEC_CONT T operator()(const T& a, const T& b) const + template + inline VTKM_EXEC_CONT auto operator()(const T& a, const U& b) const -> decltype(a + b) { - return T(a + b); + return a + b; + } + + // If both arguments are short integers, explicitly cast the result back to the + // type to avoid narrowing conversion warnings from operations that promote to + // integers. + template + inline VTKM_EXEC_CONT + typename std::enable_if::value && sizeof(T) < sizeof(int), T>::type + operator()(T a, T b) const + { + return static_cast(a + b); } }; struct Subtract { - template - inline VTKM_EXEC_CONT T operator()(const T& a, const T& b) const + template + inline VTKM_EXEC_CONT auto operator()(const T& a, const U& b) const -> decltype(a - b) { - return T(a - b); + return a - b; + } + + // If both arguments are short integers, explicitly cast the result back to the + // type to avoid narrowing conversion warnings from operations that promote to + // integers. + template + inline VTKM_EXEC_CONT + typename std::enable_if::value && sizeof(T) < sizeof(int), T>::type + operator()(T a, T b) const + { + return static_cast(a - b); } }; struct Multiply { - template - inline VTKM_EXEC_CONT T operator()(const T& a, const T& b) const + template + inline VTKM_EXEC_CONT auto operator()(const T& a, const U& b) const -> decltype(a * b) { - return T(a * b); + return a * b; + } + + // If both arguments are short integers, explicitly cast the result back to the + // type to avoid narrowing conversion warnings from operations that promote to + // integers. + template + inline VTKM_EXEC_CONT + typename std::enable_if::value && sizeof(T) < sizeof(int), T>::type + operator()(T a, T b) const + { + return static_cast(a * b); } }; struct Divide { - template - inline VTKM_EXEC_CONT T operator()(const T& a, const T& b) const + template + inline VTKM_EXEC_CONT auto operator()(const T& a, const U& b) const -> decltype(a / b) { - return T(a / b); + return a / b; + } + + // If both arguments are short integers, explicitly cast the result back to the + // type to avoid narrowing conversion warnings from operations that promote to + // integers. + template + inline VTKM_EXEC_CONT + typename std::enable_if::value && sizeof(T) < sizeof(int), T>::type + operator()(T a, T b) const + { + return static_cast(a / b); } }; diff --git a/vtkm/cont/testing/TestingDeviceAdapter.h b/vtkm/cont/testing/TestingDeviceAdapter.h index 42c34e86f..e2e7a5f95 100644 --- a/vtkm/cont/testing/TestingDeviceAdapter.h +++ b/vtkm/cont/testing/TestingDeviceAdapter.h @@ -1332,17 +1332,17 @@ private: //the output of reduce and scan inclusive should be the same std::cout << " Reduce with initial value of 0." << std::endl; - vtkm::Id reduce_sum = Algorithm::Reduce(array, vtkm::Id(0)); + vtkm::Id reduce_sum = Algorithm::Reduce(array, 0); std::cout << " Reduce with initial value." << std::endl; vtkm::Id reduce_sum_with_intial_value = Algorithm::Reduce(array, vtkm::Id(ARRAY_SIZE)); std::cout << " Inclusive scan to check" << std::endl; vtkm::Id inclusive_sum = Algorithm::ScanInclusive(array, array); std::cout << " Reduce with 1 value." << std::endl; array.Allocate(1, vtkm::CopyFlag::On); - vtkm::Id reduce_sum_one_value = Algorithm::Reduce(array, vtkm::Id(0)); + vtkm::Id reduce_sum_one_value = Algorithm::Reduce(array, 0); std::cout << " Reduce with 0 values." << std::endl; array.Allocate(0); - vtkm::Id reduce_sum_no_values = Algorithm::Reduce(array, vtkm::Id(0)); + vtkm::Id reduce_sum_no_values = Algorithm::Reduce(array, 0); VTKM_TEST_ASSERT(reduce_sum == OFFSET * ARRAY_SIZE, "Got bad sum from Reduce"); VTKM_TEST_ASSERT(reduce_sum_with_intial_value == reduce_sum + ARRAY_SIZE, "Got bad sum from Reduce with initial value");