mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-10-05 01:49:02 +00:00
vtkm::Vec: added unrolled arithmetic operators overload
Signed-off-by: Vicente Adolfo Bolea Sanchez <vicente.bolea@kitware.com>
This commit is contained in:
parent
278ab6c504
commit
fb919e048e
198
vtkm/Types.h
198
vtkm/Types.h
@ -196,119 +196,15 @@ using FloatDefault = vtkm::Float64;
|
||||
using FloatDefault = vtkm::Float32;
|
||||
#endif
|
||||
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/// Placeholder class for when a type is not applicable.
|
||||
///
|
||||
struct NullType
|
||||
{
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <vtkm::IdComponent Size>
|
||||
struct VecComponentWiseUnaryOperation
|
||||
{
|
||||
template <typename T, typename UnaryOpType>
|
||||
inline VTKM_EXEC_CONT T operator()(const T& v, const UnaryOpType& unaryOp) const
|
||||
{
|
||||
T result;
|
||||
for (vtkm::IdComponent i = 0; i < Size; ++i)
|
||||
{
|
||||
result[i] = unaryOp(v[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VecComponentWiseUnaryOperation<1>
|
||||
{
|
||||
template <typename T, typename UnaryOpType>
|
||||
inline VTKM_EXEC_CONT T operator()(const T& v, const UnaryOpType& unaryOp) const
|
||||
{
|
||||
return T(unaryOp(v[0]));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VecComponentWiseUnaryOperation<2>
|
||||
{
|
||||
template <typename T, typename UnaryOpType>
|
||||
inline VTKM_EXEC_CONT T operator()(const T& v, const UnaryOpType& unaryOp) const
|
||||
{
|
||||
return T(unaryOp(v[0]), unaryOp(v[1]));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VecComponentWiseUnaryOperation<3>
|
||||
{
|
||||
template <typename T, typename UnaryOpType>
|
||||
inline VTKM_EXEC_CONT T operator()(const T& v, const UnaryOpType& unaryOp) const
|
||||
{
|
||||
return T(unaryOp(v[0]), unaryOp(v[1]), unaryOp(v[2]));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VecComponentWiseUnaryOperation<4>
|
||||
{
|
||||
template <typename T, typename UnaryOpType>
|
||||
inline VTKM_EXEC_CONT T operator()(const T& v, const UnaryOpType& unaryOp) const
|
||||
{
|
||||
return T(unaryOp(v[0]), unaryOp(v[1]), unaryOp(v[2]), unaryOp(v[3]));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename BinaryOpType, typename ReturnT = T>
|
||||
struct BindLeftBinaryOp
|
||||
{
|
||||
// Warning: a reference.
|
||||
const T& LeftValue;
|
||||
const BinaryOpType BinaryOp;
|
||||
VTKM_EXEC_CONT
|
||||
BindLeftBinaryOp(const T& leftValue, BinaryOpType binaryOp = BinaryOpType())
|
||||
: LeftValue(leftValue)
|
||||
, BinaryOp(binaryOp)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename RightT>
|
||||
VTKM_EXEC_CONT ReturnT operator()(const RightT& rightValue) const
|
||||
{
|
||||
return static_cast<ReturnT>(this->BinaryOp(this->LeftValue, static_cast<T>(rightValue)));
|
||||
}
|
||||
|
||||
private:
|
||||
void operator=(const BindLeftBinaryOp<T, BinaryOpType, ReturnT>&) = delete;
|
||||
};
|
||||
|
||||
template <typename T, typename BinaryOpType, typename ReturnT = T>
|
||||
struct BindRightBinaryOp
|
||||
{
|
||||
// Warning: a reference.
|
||||
const T& RightValue;
|
||||
const BinaryOpType BinaryOp;
|
||||
VTKM_EXEC_CONT
|
||||
BindRightBinaryOp(const T& rightValue, BinaryOpType binaryOp = BinaryOpType())
|
||||
: RightValue(rightValue)
|
||||
, BinaryOp(binaryOp)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename LeftT>
|
||||
VTKM_EXEC_CONT ReturnT operator()(const LeftT& leftValue) const
|
||||
{
|
||||
return static_cast<ReturnT>(this->BinaryOp(static_cast<T>(leftValue), this->RightValue));
|
||||
}
|
||||
|
||||
private:
|
||||
void operator=(const BindRightBinaryOp<T, BinaryOpType, ReturnT>&) = delete;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Disable conversion warnings for Add, Subtract, Multiply, Divide on GCC only.
|
||||
@ -717,7 +613,6 @@ public:
|
||||
return this->Components[idx];
|
||||
}
|
||||
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename OtherComponentType, typename OtherClass>
|
||||
inline VTKM_EXEC_CONT DerivedClass
|
||||
@ -1664,94 +1559,6 @@ inline VTKM_EXEC_CONT T ReduceProduct(const vtkm::Vec<T, 4>& a)
|
||||
template <typename U, typename V>
|
||||
struct Pair;
|
||||
|
||||
template <typename T, vtkm::IdComponent Size>
|
||||
inline VTKM_EXEC_CONT vtkm::Vec<T, Size> operator*(T scalar, const vtkm::Vec<T, Size>& vec)
|
||||
{
|
||||
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
|
||||
vec, vtkm::internal::BindLeftBinaryOp<T, vtkm::Multiply>(scalar));
|
||||
}
|
||||
|
||||
template <typename T, vtkm::IdComponent Size>
|
||||
inline VTKM_EXEC_CONT vtkm::Vec<T, Size> operator*(const vtkm::Vec<T, Size>& vec, T scalar)
|
||||
{
|
||||
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
|
||||
vec, vtkm::internal::BindRightBinaryOp<T, vtkm::Multiply>(scalar));
|
||||
}
|
||||
|
||||
template <typename T, vtkm::IdComponent Size>
|
||||
inline VTKM_EXEC_CONT vtkm::Vec<T, Size> operator*(vtkm::Float64 scalar,
|
||||
const vtkm::Vec<T, Size>& vec)
|
||||
{
|
||||
return vtkm::Vec<T, Size>(vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
|
||||
vec, vtkm::internal::BindLeftBinaryOp<vtkm::Float64, vtkm::Multiply, T>(scalar)));
|
||||
}
|
||||
|
||||
template <typename T, vtkm::IdComponent Size>
|
||||
inline VTKM_EXEC_CONT vtkm::Vec<T, Size> operator*(const vtkm::Vec<T, Size>& vec,
|
||||
vtkm::Float64 scalar)
|
||||
{
|
||||
return vtkm::Vec<T, Size>(vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
|
||||
vec, vtkm::internal::BindRightBinaryOp<vtkm::Float64, vtkm::Multiply, T>(scalar)));
|
||||
}
|
||||
|
||||
template <vtkm::IdComponent Size>
|
||||
inline VTKM_EXEC_CONT vtkm::Vec<vtkm::Float64, Size> operator*(
|
||||
vtkm::Float64 scalar,
|
||||
const vtkm::Vec<vtkm::Float64, Size>& vec)
|
||||
{
|
||||
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
|
||||
vec, vtkm::internal::BindLeftBinaryOp<vtkm::Float64, vtkm::Multiply>(scalar));
|
||||
}
|
||||
|
||||
template <vtkm::IdComponent Size>
|
||||
inline VTKM_EXEC_CONT vtkm::Vec<vtkm::Float64, Size> operator*(
|
||||
const vtkm::Vec<vtkm::Float64, Size>& vec,
|
||||
vtkm::Float64 scalar)
|
||||
{
|
||||
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
|
||||
vec, vtkm::internal::BindRightBinaryOp<vtkm::Float64, vtkm::Multiply>(scalar));
|
||||
}
|
||||
|
||||
template <typename T, vtkm::IdComponent Size>
|
||||
inline VTKM_EXEC_CONT vtkm::Vec<T, Size> operator/(const vtkm::Vec<T, Size>& vec, T scalar)
|
||||
{
|
||||
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
|
||||
vec, vtkm::internal::BindRightBinaryOp<T, vtkm::Divide>(scalar));
|
||||
}
|
||||
|
||||
template <typename T, vtkm::IdComponent Size>
|
||||
inline VTKM_EXEC_CONT vtkm::Vec<T, Size> operator/(const vtkm::Vec<T, Size>& vec,
|
||||
vtkm::Float64 scalar)
|
||||
{
|
||||
return vtkm::Vec<T, Size>(vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
|
||||
vec, vtkm::internal::BindRightBinaryOp<vtkm::Float64, vtkm::Divide, T>(scalar)));
|
||||
}
|
||||
|
||||
template <vtkm::IdComponent Size>
|
||||
inline VTKM_EXEC_CONT vtkm::Vec<vtkm::Float64, Size> operator/(
|
||||
const vtkm::Vec<vtkm::Float64, Size>& vec,
|
||||
vtkm::Float64 scalar)
|
||||
{
|
||||
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(
|
||||
vec, vtkm::internal::BindRightBinaryOp<vtkm::Float64, vtkm::Divide>(scalar));
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// The enable_if for this operator is effectively disabling the negate
|
||||
// operator for Vec of unsigned integers. Another approach would be
|
||||
// to use enable_if<!is_unsigned>. That would be more inclusive but would
|
||||
// also allow other types like Vec<Vec<unsigned> >. If necessary, we could
|
||||
// change this implementation to be more inclusive.
|
||||
template <typename T, vtkm::IdComponent Size>
|
||||
inline VTKM_EXEC_CONT
|
||||
typename std::enable_if<(std::is_floating_point<T>::value || std::is_signed<T>::value),
|
||||
vtkm::Vec<T, Size>>::type
|
||||
operator-(const vtkm::Vec<T, Size>& x)
|
||||
{
|
||||
return vtkm::internal::VecComponentWiseUnaryOperation<Size>()(x, vtkm::Negate());
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
/// Helper function for printing out vectors during testing.
|
||||
///
|
||||
template <typename T, vtkm::IdComponent Size>
|
||||
@ -1773,7 +1580,8 @@ inline VTKM_EXEC_CONT std::ostream& operator<<(std::ostream& stream, const vtkm:
|
||||
return stream << "[" << vec.first << "," << vec.second << "]";
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace vtkm
|
||||
|
||||
#include <vtkm/internal/VecOperators.h>
|
||||
// Declared inside of vtkm namespace so that the operator work with ADL lookup
|
||||
#endif //vtk_m_Types_h
|
||||
|
@ -74,6 +74,7 @@ set(headers
|
||||
Unreachable.h
|
||||
Variant.h
|
||||
VariantDetail.h
|
||||
VecOperators.h
|
||||
Windows.h
|
||||
)
|
||||
|
||||
@ -82,5 +83,6 @@ vtkm_declare_headers(${headers})
|
||||
vtkm_pyexpander_generated_file(FunctionInterfaceDetailPre.h)
|
||||
vtkm_pyexpander_generated_file(FunctionInterfaceDetailPost.h)
|
||||
vtkm_pyexpander_generated_file(VariantDetail.h)
|
||||
vtkm_pyexpander_generated_file(VecOperators.h)
|
||||
|
||||
add_subdirectory(testing)
|
||||
|
1461
vtkm/internal/VecOperators.h
Normal file
1461
vtkm/internal/VecOperators.h
Normal file
File diff suppressed because it is too large
Load Diff
200
vtkm/internal/VecOperators.h.in
Normal file
200
vtkm/internal/VecOperators.h.in
Normal file
@ -0,0 +1,200 @@
|
||||
$# vim: ft=python.cpp foldmethod=marker
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
//$# This file uses the pyexpander macro processing utility to build the
|
||||
//$# FunctionInterface facilities that use a variable number of arguments.
|
||||
//$# Information, documentation, and downloads for pyexpander can be found at:
|
||||
//$#
|
||||
//$# http://pyexpander.sourceforge.net/
|
||||
//$#
|
||||
//$# To build the source code, execute the following (after installing
|
||||
//$# pyexpander, of course):
|
||||
//$#
|
||||
//$# expander.py VecOperators.h.in > VecOperators.h
|
||||
//$#
|
||||
//$# Ignore the following comment. It is meant for the generated file.
|
||||
// **** DO NOT EDIT THIS FILE!!! ****
|
||||
// This file is automatically generated by VecOperators.h.in
|
||||
// clang-format off
|
||||
#ifndef vtk_m_internal_VecOperators_h
|
||||
#define vtk_m_internal_VecOperators_h
|
||||
|
||||
#include <vtkm/internal/Configure.h>
|
||||
|
||||
namespace vtkm {
|
||||
|
||||
#if (!(defined(VTKM_CUDA) && (__CUDACC_VER_MAJOR__ < 8)))
|
||||
#if (defined(VTKM_GCC) || defined(VTKM_CLANG))
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#pragma GCC diagnostic ignored "-Wfloat-conversion"
|
||||
#endif // gcc || clang
|
||||
#endif // not using cuda < 8
|
||||
|
||||
#if defined(VTKM_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4244)
|
||||
#endif
|
||||
|
||||
|
||||
$py(
|
||||
max_size = 4
|
||||
operators = ['+', '*', '-', '/']
|
||||
operands = {
|
||||
"Vec_Vec" : [['T', 'T']],
|
||||
"Vec_Scalar" : [['T', 'T'], ['T', "vtkm::Float64"], ["vtkm::Float64", "vtkm::Float64"]],
|
||||
"Scalar_Vec" : [['T', 'T'], ['T', "vtkm::Float64"], ["vtkm::Float64", "vtkm::Float64"]]
|
||||
}
|
||||
)\
|
||||
\
|
||||
// operator- unary overloads for generic and specific sizes {{{
|
||||
template <typename T, vtkm::IdComponent Size>
|
||||
inline VTKM_EXEC_CONT
|
||||
typename std::enable_if<(std::is_floating_point<T>::value || std::is_signed<T>::value),
|
||||
vtkm::Vec<T, Size>>::type
|
||||
operator-(vtkm::Vec<T, Size> x)
|
||||
{
|
||||
for(int i=0; i < Size; ++i)
|
||||
{
|
||||
x[i] = -x[i];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
$for(SIZE in range(1, max_size+1))\
|
||||
template <typename T>
|
||||
inline VTKM_EXEC_CONT
|
||||
typename std::enable_if<(std::is_floating_point<T>::value || std::is_signed<T>::value),
|
||||
vtkm::Vec<T, $(SIZE)>>::type
|
||||
operator-(const vtkm::Vec<T, $(SIZE)>& x)
|
||||
{
|
||||
return vtkm::Vec<T, $(SIZE)>(\
|
||||
$for(i in range(0, SIZE))\
|
||||
\
|
||||
$# Trailing comma between arguments
|
||||
$if(i != 0)\
|
||||
, \
|
||||
$endif\
|
||||
\
|
||||
-x[$(i)]\
|
||||
\
|
||||
$endfor\
|
||||
);
|
||||
}
|
||||
|
||||
$endfor\
|
||||
|
||||
//}}}
|
||||
|
||||
$for(OPERATOR in operators)\
|
||||
// operator$(OPERATOR) overloads for generic vector sizes -------------------{{{
|
||||
$for((PARAMETERS, types) in operands.items())\
|
||||
$for(TYPE in types)\
|
||||
\
|
||||
// $(PARAMETERS) for $(TYPE)
|
||||
$if(TYPE[0] == "vtkm::Float64")\
|
||||
template <IdComponent Size>
|
||||
$else\
|
||||
template <typename T, IdComponent Size>
|
||||
$endif\
|
||||
inline VTKM_EXEC_CONT vtkm::Vec<$(TYPE[0]), Size> operator$(OPERATOR)(
|
||||
$if(PARAMETERS == "Vec_Vec")\
|
||||
vtkm::Vec<$(TYPE[0]), Size> a, const vtkm::Vec<$(TYPE[1]), Size>& b
|
||||
$elif(PARAMETERS == "Vec_Scalar")\
|
||||
vtkm::Vec<$(TYPE[0]), Size> a, $(TYPE[1]) scalar
|
||||
$else\
|
||||
$(TYPE[1]) scalar, vtkm::Vec<$(TYPE[0]), Size> a
|
||||
$endif\
|
||||
)
|
||||
{
|
||||
for (int i = 0; i < Size; ++i)
|
||||
{
|
||||
$if(PARAMETERS == "Vec_Vec")\
|
||||
a[i] = a[i] $(OPERATOR) b[i];
|
||||
$elif(PARAMETERS == "Vec_Scalar")\
|
||||
a[i] = a[i] $(OPERATOR) scalar;
|
||||
$else\
|
||||
a[i] = scalar $(OPERATOR) a[i];
|
||||
$endif\
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
$endfor\
|
||||
$endfor\
|
||||
//}}}
|
||||
$endfor\
|
||||
|
||||
$for(OPERATOR in operators)\
|
||||
// operator$(OPERATOR) overloads for specific vector sizes -------------------{{{
|
||||
$for(SIZE in range(1, max_size+1))\
|
||||
$for((PARAMETERS, types) in operands.items())\
|
||||
$for(TYPE in types)\
|
||||
\
|
||||
// $(PARAMETERS) for $(TYPE)
|
||||
$# No need for templates when all parameters are not templated
|
||||
$if(TYPE[0] != "vtkm::Float64")\
|
||||
template <typename T>
|
||||
$endif\
|
||||
inline VTKM_EXEC_CONT vtkm::Vec<$(TYPE[0]), $(SIZE)> operator$(OPERATOR)(
|
||||
$if(PARAMETERS == "Vec_Vec")\
|
||||
const vtkm::Vec<$(TYPE[0]), $(SIZE)>& a, const vtkm::Vec<$(TYPE[1]), $(SIZE)>& b
|
||||
$elif(PARAMETERS == "Vec_Scalar")\
|
||||
const vtkm::Vec<$(TYPE[0]), $(SIZE)>& a, $(TYPE[1]) scalar
|
||||
$else\
|
||||
$(TYPE[1]) scalar, const vtkm::Vec<$(TYPE[0]), $(SIZE)>& a
|
||||
$endif\
|
||||
)
|
||||
{
|
||||
return vtkm::Vec<$(TYPE[0]), $(SIZE)>(\
|
||||
$for(i in range(0, SIZE))\
|
||||
\
|
||||
$# Trailing comma between arguments
|
||||
$if(i != 0)\
|
||||
, \
|
||||
$endif\
|
||||
\
|
||||
$if(PARAMETERS == "Vec_Vec")\
|
||||
a[$(i)] $(OPERATOR) b[$(i)]\
|
||||
\
|
||||
$elif(PARAMETERS == "Vec_Scalar")\
|
||||
a[$(i)] $(OPERATOR) scalar\
|
||||
\
|
||||
$else\
|
||||
scalar $(OPERATOR) a[$(i)]\
|
||||
\
|
||||
$endif\
|
||||
$endfor\
|
||||
);
|
||||
}
|
||||
|
||||
$endfor\
|
||||
$endfor\
|
||||
$endfor\
|
||||
//}}}
|
||||
$endfor\
|
||||
|
||||
|
||||
#if defined(VTKM_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#if (defined(VTKM_CUDA) && (__CUDACC_VER_MAJOR__ < 8))
|
||||
#if (defined(VTKM_GCC) || defined(VTKM_CLANG))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // gcc || clang
|
||||
#endif // use cuda < 8
|
||||
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
#endif //vtk_m_internal_VecOperators_h
|
Loading…
Reference in New Issue
Block a user