Modified Math.h.in and VectorAnalysis.h to support integral types.

Unary operations on scalars and vectors will return vtkm::Float64 for
integral input types and vtkm::Float64 input types. Unary operations will
return vtkm::Float32 for vtkm::Float32 input vectors and scalars.
This commit is contained in:
Thomas J. Otahal 2017-01-26 13:30:28 -07:00
parent cd95cbe90b
commit 7d6601d794
5 changed files with 1043 additions and 1567 deletions

File diff suppressed because it is too large Load Diff

@ -61,41 +61,25 @@ $# Ignore the following comment. It is meant for the generated file.
#define VTKM_CUDA_MATH_FUNCTION_64(func) func
$py(
def unary_function(name, type, returntype = None, cuda_expression = None, std_expression = None):
if returntype is not None:
return '''static inline VTKM_EXEC_CONT
{2} {0}({1} x) {{
def unary_function(name, type, returntype, cuda_expression, std_expression, template_header, static_keywords):
return '''{5}
{6} VTKM_EXEC_CONT
{2}
{0}({1} x) {{
#ifdef VTKM_CUDA
return {3};
#else
return {4};
#endif
}}
'''.format(name, type, returntype, cuda_expression, std_expression)
else:
return '''template <typename T>
static inline VTKM_EXEC_CONT
vtkm::FloatDefault {0}(T x) {{
#ifdef VTKM_CUDA
if(std::is_same< vtkm::FloatDefault, vtkm::Float64 >::value)
return VTKM_CUDA_MATH_FUNCTION_64({1})(static_cast<vtkm::FloatDefault>(x));
else
return VTKM_CUDA_MATH_FUNCTION_32({1})(static_cast<vtkm::FloatDefault>(x));
#else
return std::{1}(static_cast<vtkm::FloatDefault>(x));
#endif
}}
'''.format(name, type)
'''.format(name, type, returntype, cuda_expression, std_expression, template_header, static_keywords)
def unary_Vec_function(vtkmname):
return '''template<typename T, vtkm::IdComponent N>
static inline VTKM_EXEC_CONT
vtkm::Vec<vtkm::FloatDefault,N> {0}(const vtkm::Vec<T,N> &x) {{
vtkm::Vec<vtkm::FloatDefault,N> result;
vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type,N>
{0}(const vtkm::Vec<T,N> &x) {{
vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type,N> result;
for (vtkm::IdComponent index = 0; index < N; index++)
{{
result[index] = vtkm::{0}(x[index]);
@ -104,70 +88,52 @@ vtkm::Vec<vtkm::FloatDefault,N> {0}(const vtkm::Vec<T,N> &x) {{
}}
template<typename T>
static inline VTKM_EXEC_CONT
vtkm::Vec<vtkm::FloatDefault,4> {0}(const vtkm::Vec<T,4> &x) {{
return vtkm::Vec<vtkm::FloatDefault,4>(vtkm::{0}(x[0]),
vtkm::{0}(x[1]),
vtkm::{0}(x[2]),
vtkm::{0}(x[3]));
vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type,4>
{0}(const vtkm::Vec<T,4> &x) {{
return vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type,4>(vtkm::{0}(x[0]),
vtkm::{0}(x[1]),
vtkm::{0}(x[2]),
vtkm::{0}(x[3]));
}}
template<typename T>
static inline VTKM_EXEC_CONT
vtkm::Vec<vtkm::FloatDefault,3> {0}(const vtkm::Vec<T,3> &x) {{
return vtkm::Vec<vtkm::FloatDefault,3>(vtkm::{0}(x[0]),
vtkm::{0}(x[1]),
vtkm::{0}(x[2]));
vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type,3>
{0}(const vtkm::Vec<T,3> &x) {{
return vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type,3>(vtkm::{0}(x[0]),
vtkm::{0}(x[1]),
vtkm::{0}(x[2]));
}}
template<typename T>
static inline VTKM_EXEC_CONT
vtkm::Vec<vtkm::FloatDefault,2> {0}(const vtkm::Vec<T,2> &x) {{
return vtkm::Vec<vtkm::FloatDefault,2>(vtkm::{0}(x[0]),
vtkm::{0}(x[1]));
}}
'''.format(vtkmname) + \
'''template<vtkm::IdComponent N>
static inline VTKM_EXEC_CONT
vtkm::Vec<vtkm::Float64,N> {0}(const vtkm::Vec<vtkm::Float64,N> &x) {{
vtkm::Vec<vtkm::Float64,N> result;
for (vtkm::IdComponent index = 0; index < N; index++)
{{
result[index] = vtkm::{0}(x[index]);
}}
return result;
}}
static inline VTKM_EXEC_CONT
vtkm::Vec<vtkm::Float64,4> {0}(const vtkm::Vec<vtkm::Float64,4> &x) {{
return vtkm::Vec<vtkm::Float64,4>(vtkm::{0}(x[0]),
vtkm::{0}(x[1]),
vtkm::{0}(x[2]),
vtkm::{0}(x[3]));
}}
static inline VTKM_EXEC_CONT
vtkm::Vec<vtkm::Float64,3> {0}(const vtkm::Vec<vtkm::Float64,3> &x) {{
return vtkm::Vec<vtkm::Float64,3>(vtkm::{0}(x[0]),
vtkm::{0}(x[1]),
vtkm::{0}(x[2]));
}}
static inline VTKM_EXEC_CONT
vtkm::Vec<vtkm::Float64,2> {0}(const vtkm::Vec<vtkm::Float64,2> &x) {{
return vtkm::Vec<vtkm::Float64,2>(vtkm::{0}(x[0]),
vtkm::{0}(x[1]));
vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type,2>
{0}(const vtkm::Vec<T,2> &x) {{
return vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type,2>(vtkm::{0}(x[0]),
vtkm::{0}(x[1]));
}}
'''.format(vtkmname)
def unary_math_function_no_vec(vtkmname, sysname, returntype = None):
return unary_function(vtkmname, sysname) + \
return unary_function(vtkmname,
'T',
'typename detail::FloatingPointReturnType<T>::Type' if returntype == None else returntype,
'VTKM_CUDA_MATH_FUNCTION_64(' + sysname + ')(static_cast<vtkm::Float64>(x))',
'std::' + sysname + '(static_cast<vtkm::Float64>(x))',
'template<typename T>',
'static inline') + \
unary_function(vtkmname,
'vtkm::Float32',
'vtkm::Float32' if returntype == None else returntype,
'detail::FloatingPointReturnType<vtkm::Float32>::Type' if returntype == None else returntype,
'VTKM_CUDA_MATH_FUNCTION_32(' + sysname + ')(x)',
'std::' + sysname + '(x)') + \
'std::' + sysname + '(x)',
'template<>',
'inline') + \
unary_function(vtkmname,
'vtkm::Float64',
'vtkm::Float64' if returntype == None else returntype,
'detail::FloatingPointReturnType<vtkm::Float64>::Type' if returntype == None else returntype,
'VTKM_CUDA_MATH_FUNCTION_64(' + sysname + ')(x)',
'std::' + sysname + '(x)')
'std::' + sysname + '(x)',
'template<>',
'inline')
def unary_math_function(vtkmname, sysname):
return unary_math_function_no_vec(vtkmname, sysname) + \
@ -275,6 +241,28 @@ vtkm::Float64 Pi_4()
return 0.78539816339744830961566084581987572;
}
namespace detail {
template<typename T>
struct FloatingPointReturnType
{
typedef vtkm::Float64 Type;
};
template<>
struct FloatingPointReturnType<vtkm::Float32>
{
typedef vtkm::Float32 Type;
};
template<vtkm::IdComponent N>
struct FloatingPointReturnType<Vec<vtkm::Float32,N> >
{
typedef vtkm::Float32 Type;
};
}
/// Compute the sine of \p x.
///
$unary_math_function('Sin', 'sin')\
@ -357,6 +345,11 @@ static inline VTKM_EXEC_CONT
vtkm::Float64 RSqrt(vtkm::Float64 x) {
return rsqrt(x);
}
template<typename T>
static inline VTKM_EXEC_CONT
vtkm::Float64 RSqrt(T x) {
return rsqrt(static_cast<vtkm::Float64>(x));
}
#else // !VTKM_CUDA
static inline VTKM_EXEC_CONT
vtkm::Float32 RSqrt(vtkm::Float32 x) {
@ -366,6 +359,11 @@ static inline VTKM_EXEC_CONT
vtkm::Float64 RSqrt(vtkm::Float64 x) {
return 1/vtkm::Sqrt(x);
}
template<typename T>
static inline VTKM_EXEC_CONT
vtkm::Float64 RSqrt(T x) {
return 1/static_cast<vtkm::Float64>(x);
}
#endif // !VTKM_CUDA
$unary_Vec_function('RSqrt')\
@ -390,6 +388,11 @@ static inline VTKM_EXEC_CONT
vtkm::Float64 RCbrt(vtkm::Float64 x) {
return rcbrt(x);
}
template<typename T>
static inline VTKM_EXEC_CONT
vtkm::Float64 RCbrt(T x) {
return rcbrt(static_cast<vtkm::Float64>(x));
}
#else // !VTKM_CUDA
static inline VTKM_EXEC_CONT
vtkm::Float32 RCbrt(vtkm::Float32 x) {
@ -399,6 +402,11 @@ static inline VTKM_EXEC_CONT
vtkm::Float64 RCbrt(vtkm::Float64 x) {
return 1/vtkm::Cbrt(x);
}
template<typename T>
static inline VTKM_EXEC_CONT
vtkm::Float64 RCbrt(T x) {
return 1/vtkm::Cbrt(static_cast<vtkm::Float64>(x));
}
#endif // !VTKM_CUDA
$unary_Vec_function('RCbrt')\
@ -431,6 +439,11 @@ static inline VTKM_EXEC_CONT
vtkm::Float64 Exp10(vtkm::Float64 x) {
return exp10(x);
}
template<typename T>
static inline VTKM_EXEC_CONT
vtkm::Float64 Exp10(T x) {
return exp10(static_cast<vtkm::Float64>(x));
}
#else // !VTKM_CUDA
static inline VTKM_EXEC_CONT
vtkm::Float32 Exp10(vtkm::Float32 x) {
@ -440,6 +453,11 @@ static inline VTKM_EXEC_CONT
vtkm::Float64 Exp10(vtkm::Float64 x) {
return vtkm::Pow(10, x);;
}
template<typename T>
static inline VTKM_EXEC_CONT
vtkm::Float64 Exp10(T x) {
return vtkm::Pow(10, static_cast<vtkm::Float64>(x));;
}
#endif // !VTKM_CUDA
$unary_Vec_function('Exp10')\

@ -85,21 +85,16 @@ MagnitudeSquared(const T &x)
namespace detail {
template<typename T>
VTKM_EXEC_CONT
T MagnitudeTemplate(T x, vtkm::TypeTraitsScalarTag)
typename detail::FloatingPointReturnType<T>::Type
MagnitudeTemplate(T &x, vtkm::TypeTraitsScalarTag)
{
return vtkm::Abs(x);
}
template<typename T>
VTKM_EXEC_CONT
vtkm::FloatDefault MagnitudeTemplate(const T &x, vtkm::TypeTraitsVectorTag)
{
return vtkm::Sqrt(vtkm::MagnitudeSquared(x));
}
template<vtkm::IdComponent Size>
VTKM_EXEC_CONT
vtkm::Float64 MagnitudeTemplate(const vtkm::Vec<vtkm::Float64, Size> &x)
typename detail::FloatingPointReturnType<T>::Type
MagnitudeTemplate(const T &x, vtkm::TypeTraitsVectorTag)
{
return vtkm::Sqrt(vtkm::MagnitudeSquared(x));
}
@ -116,30 +111,26 @@ vtkm::Float64 MagnitudeTemplate(const vtkm::Vec<vtkm::Float64, Size> &x)
///
template<typename T>
VTKM_EXEC_CONT
vtkm::FloatDefault Magnitude(const T &x)
typename detail::FloatingPointReturnType<T>::Type
Magnitude(const T &x)
{
return detail::MagnitudeTemplate(
x, typename vtkm::TypeTraits<T>::DimensionalityTag());
}
template<vtkm::IdComponent Size>
VTKM_EXEC_CONT
vtkm::Float64 Magnitude(const vtkm::Vec<vtkm::Float64, Size> &x)
{
return detail::MagnitudeTemplate(x);
}
// ----------------------------------------------------------------------------
namespace detail {
template<typename T>
VTKM_EXEC_CONT
T RMagnitudeTemplate(T x, vtkm::TypeTraitsScalarTag)
typename detail::FloatingPointReturnType<T>::Type
RMagnitudeTemplate(T x, vtkm::TypeTraitsScalarTag)
{
return T(1)/vtkm::Abs(x);
return 1.0/vtkm::Abs(x);
}
template<typename T>
VTKM_EXEC_CONT
typename vtkm::VecTraits<T>::ComponentType
typename detail::FloatingPointReturnType<T>::Type
RMagnitudeTemplate(const T &x, vtkm::TypeTraitsVectorTag)
{
return vtkm::RSqrt(vtkm::MagnitudeSquared(x));
@ -153,7 +144,7 @@ RMagnitudeTemplate(const T &x, vtkm::TypeTraitsVectorTag)
///
template<typename T>
VTKM_EXEC_CONT
typename vtkm::VecTraits<T>::ComponentType
typename detail::FloatingPointReturnType<T>::Type
RMagnitude(const T &x)
{
return detail::RMagnitudeTemplate(
@ -206,11 +197,12 @@ void Normalize(T &x)
///
template<typename T>
VTKM_EXEC_CONT
vtkm::Vec<T,3> Cross(const vtkm::Vec<T,3> &x, const vtkm::Vec<T,3> &y)
vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type,3>
Cross(const vtkm::Vec<T,3> &x, const vtkm::Vec<T,3> &y)
{
return vtkm::Vec<T,3>(x[1]*y[2] - x[2]*y[1],
x[2]*y[0] - x[0]*y[2],
x[0]*y[1] - x[1]*y[0]);
return vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type,3>(x[1]*y[2] - x[2]*y[1],
x[2]*y[0] - x[0]*y[2],
x[0]*y[1] - x[1]*y[0]);
}
//-----------------------------------------------------------------------------
@ -222,9 +214,10 @@ vtkm::Vec<T,3> Cross(const vtkm::Vec<T,3> &x, const vtkm::Vec<T,3> &y)
///
template<typename T>
VTKM_EXEC_CONT
vtkm::Vec<T,3> TriangleNormal(const vtkm::Vec<T,3> &a,
const vtkm::Vec<T,3> &b,
const vtkm::Vec<T,3> &c)
vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type,3>
TriangleNormal(const vtkm::Vec<T,3> &a,
const vtkm::Vec<T,3> &b,
const vtkm::Vec<T,3> &c)
{
return vtkm::Cross(b-a, c-a);
}

@ -46,8 +46,10 @@ VectorMagnitude::DoExecute(const vtkm::cont::DataSet &inDataSet,
const vtkm::filter::PolicyBase<DerivedPolicy>&,
const DeviceAdapter&)
{
typedef typename vtkm::VecTraits<T>::ComponentType ComponentType;
vtkm::cont::ArrayHandle<ComponentType> outArray;
//typedef typename vtkm::VecTraits<T>::ComponentType ComponentType;
//vtkm::cont::ArrayHandle<ComponentType> outArray;
typedef typename detail::FloatingPointReturnType<T>::Type ReturnType;
vtkm::cont::ArrayHandle<ReturnType> outArray;
vtkm::worklet::DispatcherMapField<vtkm::worklet::Magnitude,
DeviceAdapter > dispatcher(this->Worklet);

@ -18,6 +18,8 @@
// this software.
//============================================================================
#define VTKM_DEFAULT_TYPE_LIST_TAG ::vtkm::TypeListTagAll
#include <vtkm/filter/VectorMagnitude.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
@ -33,25 +35,36 @@ void TestVectorMagnitude()
vtkm::cont::testing::MakeTestDataSet testDataSet;
vtkm::cont::DataSet dataSet = testDataSet.Make3DUniformDataSet0();
//Verify that we can compute the gradient of a 3 component vector
const int nVerts = 18;
vtkm::Float64 vars[nVerts] = {10.1, 20.1, 30.1, 40.1, 50.2,
60.2, 70.2, 80.2, 90.3, 100.3,
110.3, 120.3, 130.4, 140.4,
150.4, 160.4, 170.5, 180.5};
std::vector< vtkm::Vec<vtkm::Float64,3> > vec(nVerts);
for(std::size_t i=0; i < vec.size(); ++i)
vtkm::Float64 fvars[nVerts] = {10.1, 20.1, 30.1, 40.1, 50.2,
60.2, 70.2, 80.2, 90.3, 100.3,
110.3, 120.3, 130.4, 140.4,
150.4, 160.4, 170.5, 180.5};
vtkm::Int32 ivars[nVerts] = {10, 20, 30, 40, 50,
60, 70, 80, 90, 100,
110, 120, 130, 140,
150, 160, 170, 180};
std::vector< vtkm::Vec<vtkm::Float64,3> > fvec(nVerts);
std::vector< vtkm::Vec<vtkm::Int32,3> > ivec(nVerts);
for(std::size_t i=0; i < fvec.size(); ++i)
{
vec[i] = vtkm::make_Vec(vars[i],vars[i],vars[i]);
fvec[i] = vtkm::make_Vec(fvars[i],fvars[i],fvars[i]);
ivec[i] = vtkm::make_Vec(ivars[i],ivars[i],ivars[i]);
}
vtkm::cont::ArrayHandle< vtkm::Vec<vtkm::Float64,3> > input =
vtkm::cont::make_ArrayHandle(vec);
vtkm::cont::DataSetFieldAdd::AddPointField(dataSet, "vec_pointvar", input);
vtkm::cont::ArrayHandle< vtkm::Vec<vtkm::Float64,3> > finput =
vtkm::cont::make_ArrayHandle(fvec);
vtkm::cont::ArrayHandle< vtkm::Vec<vtkm::Int32,3> > iinput =
vtkm::cont::make_ArrayHandle(ivec);
vtkm::cont::DataSetFieldAdd::AddPointField(dataSet, "double_vec_pointvar", finput);
vtkm::cont::DataSetFieldAdd::AddPointField(dataSet, "integer_vec_pointvar", iinput);
vtkm::filter::ResultField result;
vtkm::filter::VectorMagnitude vm;
result = vm.Execute(dataSet, dataSet.GetField("vec_pointvar"));
result = vm.Execute(dataSet, dataSet.GetField("double_vec_pointvar"));
VTKM_TEST_ASSERT( result.IsValid(), "result should be valid" );
VTKM_TEST_ASSERT(result.GetField().GetName() == "magnitude",
@ -61,12 +74,32 @@ void TestVectorMagnitude()
"Output field has wrong association");
vtkm::cont::ArrayHandle<vtkm::Float64> resultArrayHandle;
const bool valid = result.FieldAs(resultArrayHandle);
bool valid = result.FieldAs(resultArrayHandle);
if(valid)
{
for (vtkm::Id i = 0; i < resultArrayHandle.GetNumberOfValues(); ++i)
{
VTKM_TEST_ASSERT(test_equal(std::sqrt(3*vars[i]*vars[i]),
VTKM_TEST_ASSERT(test_equal(std::sqrt(3*fvars[i]*fvars[i]),
resultArrayHandle.GetPortalConstControl().Get(i)),
"Wrong result for Magnitude worklet");
}
}
result = vm.Execute(dataSet, dataSet.GetField("integer_vec_pointvar"));
VTKM_TEST_ASSERT( result.IsValid(), "result should be valid" );
VTKM_TEST_ASSERT(result.GetField().GetName() == "magnitude",
"Output field has wrong name.");
VTKM_TEST_ASSERT(result.GetField().GetAssociation() ==
vtkm::cont::Field::ASSOC_POINTS,
"Output field has wrong association");
valid = result.FieldAs(resultArrayHandle);
if(valid)
{
for (vtkm::Id i = 0; i < resultArrayHandle.GetNumberOfValues(); ++i)
{
VTKM_TEST_ASSERT(test_equal(std::sqrt(3*ivars[i]*ivars[i]),
resultArrayHandle.GetPortalConstControl().Get(i)),
"Wrong result for Magnitude worklet");
}