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.
This commit is contained in:
parent
58bd890c9c
commit
d9c988b200
68
vtkm/Types.h
68
vtkm/Types.h
@ -221,37 +221,81 @@ struct NullType
|
||||
#endif // gcc || clang
|
||||
struct Add
|
||||
{
|
||||
template <typename T>
|
||||
inline VTKM_EXEC_CONT T operator()(const T& a, const T& b) const
|
||||
template <typename T, typename U>
|
||||
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 <typename T>
|
||||
inline VTKM_EXEC_CONT
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
|
||||
operator()(T a, T b) const
|
||||
{
|
||||
return static_cast<T>(a + b);
|
||||
}
|
||||
};
|
||||
|
||||
struct Subtract
|
||||
{
|
||||
template <typename T>
|
||||
inline VTKM_EXEC_CONT T operator()(const T& a, const T& b) const
|
||||
template <typename T, typename U>
|
||||
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 <typename T>
|
||||
inline VTKM_EXEC_CONT
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
|
||||
operator()(T a, T b) const
|
||||
{
|
||||
return static_cast<T>(a - b);
|
||||
}
|
||||
};
|
||||
|
||||
struct Multiply
|
||||
{
|
||||
template <typename T>
|
||||
inline VTKM_EXEC_CONT T operator()(const T& a, const T& b) const
|
||||
template <typename T, typename U>
|
||||
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 <typename T>
|
||||
inline VTKM_EXEC_CONT
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
|
||||
operator()(T a, T b) const
|
||||
{
|
||||
return static_cast<T>(a * b);
|
||||
}
|
||||
};
|
||||
|
||||
struct Divide
|
||||
{
|
||||
template <typename T>
|
||||
inline VTKM_EXEC_CONT T operator()(const T& a, const T& b) const
|
||||
template <typename T, typename U>
|
||||
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 <typename T>
|
||||
inline VTKM_EXEC_CONT
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) < sizeof(int), T>::type
|
||||
operator()(T a, T b) const
|
||||
{
|
||||
return static_cast<T>(a / b);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user