Implement FunctionInterface::StaticTransform

This will allow a faster conversion than the dynamic transform and will
allow you to define compile-time types for transformation unlike dynamic
transform or invoke with transform.
This commit is contained in:
Kenneth Moreland 2014-05-06 13:28:08 -06:00
parent defb4f00cf
commit 438fe0ff8d
2 changed files with 220 additions and 2 deletions

@ -247,7 +247,7 @@ struct IdentityFunctor {
f(BOOST_PP_ENUM_SHIFTED(NumParamsPlusOne, VTK_M_DO_INVOKE_TPARAM, )); \
}
#define VTK_M_DO_INVOKE_REPEAT(z, NumParams, data) \
VTK_M_DO_INVOKE(BOOST_PP_INC(NumParams));
VTK_M_DO_INVOKE(BOOST_PP_INC(NumParams))
#define VTK_M_DO_INVOKE_NAME DoInvokeCont
#define VTK_M_DO_INVOKE_EXPORT VTKM_CONT_EXPORT
@ -318,6 +318,69 @@ struct FunctionInterfaceCopyParameters<0, ParameterIndex> {
}
};
template<typename OriginalSignature, typename Transform>
struct FunctionInterfaceStaticTransformType;
// The following code uses the Boost preprocessor utilities to create
// definitions of DoStaticTransform functions for all supported number of
// arguments. The created functions are conceptually defined as follows:
//
// template<typename Transform,
// typename OriginalSignature,
// typename TransformedSignature>
// VTKM_CONT_EXPORT
// void DoStaticTransformCont(
// const Transform &transform,
// const ParameterContainer<OriginalSignature> &originalParameters,
// ParameterContainer<TransformedSignature> &transformedParameters)
// {
// transformedParameters.Parameter1 = transform(originalParameters.Parameter1);
// transformedParameters.Parameter2 = transform(originalParameters.Parameter2);
// ...
// }
//
// We define multiple DoStaticTransformCont and DoStaticTransformExec that do
// identical things with different exports. It is important to have these
// separate definitions instead of a single version with VTKM_EXEC_CONT_EXPORT
// because the transform to be invoked may only be viable in one or the other.
#define VTK_M_DO_STATIC_TRANSFORM_ASSIGN(z, count, data) \
BOOST_PP_IF(count, \
BOOST_PP_CAT(transformedParameters.Parameter, count) = \
transform(BOOST_PP_CAT(originalParameters.Parameter, count));,)
#define VTK_M_DO_STATIC_TRANSFORM(NumParamsPlusOne) \
template<typename Transform, \
BOOST_PP_ENUM_PARAMS(NumParamsPlusOne, typename OriginalP), \
BOOST_PP_ENUM_PARAMS(NumParamsPlusOne, typename TransformedP)> \
VTK_M_DO_STATIC_TRANSFORM_EXPORT \
void VTK_M_DO_STATIC_TRANSFORM_NAME( \
const Transform &transform, \
ParameterContainer<OriginalP0(BOOST_PP_ENUM_SHIFTED_PARAMS(NumParamsPlusOne, OriginalP))> &originalParameters, \
ParameterContainer<TransformedP0(BOOST_PP_ENUM_SHIFTED_PARAMS(NumParamsPlusOne, TransformedP))> &transformedParameters) \
{ \
(void)transform; \
(void)originalParameters; \
(void)transformedParameters; \
BOOST_PP_REPEAT(NumParamsPlusOne, VTK_M_DO_STATIC_TRANSFORM_ASSIGN,) \
}
#define VTK_M_DO_STATIC_TRANSFORM_REPEAT(z, NumParams, data) \
VTK_M_DO_STATIC_TRANSFORM(BOOST_PP_INC(NumParams))
#define VTK_M_DO_STATIC_TRANSFORM_NAME DoStaticTransformCont
#define VTK_M_DO_STATIC_TRANSFORM_EXPORT VTKM_CONT_EXPORT
BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS),
VTK_M_DO_STATIC_TRANSFORM_REPEAT,)
#undef VTK_M_DO_STATIC_TRANSFORM_EXPORT
#undef VTK_M_DO_STATIC_TRANSFORM_NAME
#define VTK_M_DO_STATIC_TRANSFORM_NAME DoStaticTransformExec
#define VTK_M_DO_STATIC_TRANSFORM_EXPORT VTKM_EXEC_EXPORT
BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS),
VTK_M_DO_STATIC_TRANSFORM_REPEAT,)
#undef VTK_M_DO_STATIC_TRANSFORM_EXPORT
#undef VTK_M_DO_STATIC_TRANSFORM_NAME
template<typename OriginalFunction,
typename NewFunction,
typename TransformFunctor,
@ -559,6 +622,79 @@ public:
return replacedFuncInterface;
}
template<typename Transform>
struct StaticTransformType {
typedef FunctionInterface<
typename detail::FunctionInterfaceStaticTransformType<
FunctionSignature,Transform>::type> type;
};
/// \brief Transforms the \c FunctionInterface based on compile-time
/// information.
///
/// The \c StaticTransform method transforms all the parameters of this \c
/// FunctionInterface to different types and values based on compile-time
/// information. It operates by accepting a functor that defines a unary
/// function whose argument is the parameter to transform and the return
/// value is the transformed value. The functor must also contain a templated
/// struct name ReturnType with an internal type named \c type that defines
/// the return type of the transform for a given input type.
///
/// The transformation is only applied to the parameters of the function. The
/// return argument is uneffected.
///
/// The return type can be determined with the \c StaticTransformType
/// template.
///
/// Here is an example of a transformation that converts a \c
/// FunctionInterface to another \c FunctionInterface containing pointers to
/// all of the parameters.
///
/// \code
/// struct MyTransformFunctor {
/// template<typename T>
/// struct ReturnType {
/// typedef const T *type;
/// };
///
/// template<typename T>
/// DAX_CONT_EXPORT
/// const T *operator()(const T &x) const {
/// return &x;
/// }
/// };
///
/// template<typename FunctionSignature>
/// typename vtkm::internal::FunctionInterface<FunctionSignature>::template StaticTransformType<MyTransformFunctor>::type
/// ImportantStuff(const vtkm::internal::FunctionInterface<FunctionSignature> &funcInterface)
/// {
/// return funcInterface.StaticTransformCont(MyTransformFunctor());
/// }
/// \endcode
///
template<typename Transform>
VTKM_CONT_EXPORT
typename StaticTransformType<Transform>::type
StaticTransformCont(const Transform &transform)
{
typename StaticTransformType<Transform>::type newFuncInterface;
detail::DoStaticTransformCont(transform,
this->Parameters,
newFuncInterface.Parameters);
return newFuncInterface;
}
template<typename Transform>
VTKM_EXEC_EXPORT
typename StaticTransformType<Transform>::type
StaticTransformExec(const Transform &transform)
{
typename StaticTransformType<Transform>::type newFuncInterface;
detail::DoStaticTransformExec(transform,
this->Parameters,
newFuncInterface.Parameters);
return newFuncInterface;
}
/// \brief Transforms the \c FunctionInterface based on run-time information.
///
/// The \c DynamicTransform method transforms all the parameters of this \c
@ -655,6 +791,46 @@ private:
namespace detail {
// The following code uses the Boost preprocessor utilities to create
// definitions of FunctionInterfaceStaticTransformType for all supported number
// of arguments. The created classes are conceptually defined as follows:
//
// template<typename Transform,
// typename P0, // Return type
// typename P1,
// typename P2, ...>
// struct FunctionInterfaceStaticTransformType<P0(P1,P2,...), Transform> {
// typedef P0(type)(typename Transform::template ReturnType<P1>::type,
// typename Transform::template ReturnType<P2>::type, ...);
// };
#define VTK_M_STATIC_TRANSFORM_TPARAM(z, ParamIndex, data) \
BOOST_PP_IF( \
ParamIndex, \
typename Transform::template ReturnType<BOOST_PP_CAT(P,ParamIndex)>::type,)
#define VTK_M_STATIC_TRANSFORM_TYPE(NumParamsPlusOne) \
template<typename Transform, \
BOOST_PP_ENUM_PARAMS(NumParamsPlusOne, typename P)> \
struct FunctionInterfaceStaticTransformType< \
P0(BOOST_PP_ENUM_SHIFTED_PARAMS(NumParamsPlusOne, P)), \
Transform> \
{ \
typedef P0(type)( \
BOOST_PP_ENUM_SHIFTED(NumParamsPlusOne, VTK_M_STATIC_TRANSFORM_TPARAM,) \
); \
};
#define VTK_M_STATIC_TRANSFORM_TYPE_REPEAT(z, NumParams, data) \
VTK_M_STATIC_TRANSFORM_TYPE(BOOST_PP_INC(NumParams))
BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS),
VTK_M_STATIC_TRANSFORM_TYPE_REPEAT,)
#undef VTK_M_STATIC_TRANSFORM_TYPE_REPEAT
#undef VTK_M_STATIC_TRANSFORM_TYPE
#undef VTK_M_STATIC_TRANSFORM_TPARAM
template<typename OriginalFunction,
typename NewFunction,
typename TransformFunctor,

@ -135,10 +135,22 @@ struct GetReferenceFunctor
const T *operator()(const T &x) const { return &x; }
};
struct PointerTransform {
template<typename T>
struct ReturnType {
typedef const T *type;
};
template<typename T>
const T *operator()(const T &x) const {
return &x;
}
};
struct ThreePointerArgFunctor {
void operator()(const Type1 *a1, const Type2 *a2, const Type3 *a3) const
{
std::cout << "In 3 arg functor." << std::endl;
std::cout << "In 3 point arg functor." << std::endl;
VTKM_TEST_ASSERT(*a1 == Arg1, "Arg 1 incorrect.");
VTKM_TEST_ASSERT(*a2 == Arg2, "Arg 2 incorrect.");
@ -409,6 +421,35 @@ void TestTransformInvoke()
"Got bad result from invoke.");
}
void TestStaticTransform()
{
std::cout << "Trying static transform." << std::endl;
typedef vtkm::internal::FunctionInterface<void(Type1,Type2,Type3)>
OriginalType;
OriginalType funcInterface =
vtkm::internal::make_FunctionInterface<void>(Arg1, Arg2, Arg3);
std::cout << "Transform with reported type." << std::endl;
typedef OriginalType::StaticTransformType<PointerTransform>::type
ReportedType;
ReportedType funcInterfaceTransform1 =
funcInterface.StaticTransformCont(PointerTransform());
funcInterfaceTransform1.InvokeCont(ThreePointerArgFunctor());
funcInterfaceTransform1 =
funcInterface.StaticTransformExec(PointerTransform());
funcInterfaceTransform1.InvokeExec(ThreePointerArgFunctor());
std::cout << "Transform with expected type." << std::endl;
typedef vtkm::internal::FunctionInterface<void(Type1*,Type2*,Type3*)>
ExpectedType;
ReportedType funcInterfaceTransform2 =
funcInterface.StaticTransformCont(PointerTransform());
funcInterfaceTransform2.InvokeCont(ThreePointerArgFunctor());
funcInterfaceTransform2 =
funcInterface.StaticTransformExec(PointerTransform());
funcInterfaceTransform2.InvokeExec(ThreePointerArgFunctor());
}
void TestDynamicTransform()
{
std::cout << "Trying dynamic transform." << std::endl;
@ -487,6 +528,7 @@ void TestFunctionInterface()
TestInvokeResult();
TestAppend();
TestTransformInvoke();
TestStaticTransform();
TestDynamicTransform();
TestInvokeTime();
}