From d3134b70509181f6f32f757004174a1dc0692867 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Tue, 13 May 2014 13:18:21 -0600 Subject: [PATCH] Add ForEach methods to FunctionInterface. Provides a convienient mechanism to do an in-place type-preserving transform or a check of each parameter. --- vtkm/internal/FunctionInterface.h | 136 ++++++++++++++++-- .../testing/UnitTestFunctionInterface.cxx | 36 +++++ 2 files changed, 161 insertions(+), 11 deletions(-) diff --git a/vtkm/internal/FunctionInterface.h b/vtkm/internal/FunctionInterface.h index 714e671d8..02a5a8bb8 100644 --- a/vtkm/internal/FunctionInterface.h +++ b/vtkm/internal/FunctionInterface.h @@ -192,11 +192,15 @@ struct IdentityFunctor { // definitions of DoInvoke functions for all supported number of arguments. // The created functions are conceptually defined as follows: // -// template +// template // VTKM_CONT_EXPORT // void DoInvokeCont(const Function &f, -// ParameterContainer ¶meters, -// FunctionInterfaceReturnContainer &result, +// ParameterContainer ¶meters, +// FunctionInterfaceReturnContainer &result, // const TransformFunctor &transform) // { // result.Value = transform(f(transform(parameters.Parameter1),...)); @@ -356,7 +360,7 @@ struct FunctionInterfaceStaticTransformType; VTK_M_DO_STATIC_TRANSFORM_EXPORT \ void VTK_M_DO_STATIC_TRANSFORM_NAME( \ const Transform &transform, \ - ParameterContainer &originalParameters, \ + const ParameterContainer &originalParameters, \ ParameterContainer &transformedParameters) \ { \ (void)transform; \ @@ -381,12 +385,96 @@ BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS), #undef VTK_M_DO_STATIC_TRANSFORM_EXPORT #undef VTK_M_DO_STATIC_TRANSFORM_NAME +#undef VTK_M_DO_STATIC_TRANSFORM_REPEAT +#undef VTK_M_DO_STATIC_TRANSFORM +#undef VTK_M_DO_STATIC_TRANSFORM_ASSIGN + template class FunctionInterfaceDynamicTransformContContinue; +// The following code uses the Boost preprocessor utilities to create +// definitions of DoForEach functions for all supported number of arguments. +// The created functions are conceptually defined as follows: +// +// template +// VTKM_CONT_EXPORT +// void DoForEachCont(const Functor &f, +// ParameterContainer ¶meters) +// +// { +// f(parameters.Parameter1); +// f(parameters.Parameter2); +// ... +// } +// +// We define multiple DoForEachCont and DoForEachExec 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 functor +// to be invoked on each parameter may only be viable in one or the other. +// There are also separate versions that support a const FunctionInterface and +// a non-const FunctionInterface. + +#define VTK_M_DO_FOR_EACH_CALL_PARAM(z, count, data) \ + BOOST_PP_IF(count, f(BOOST_PP_CAT(parameters.Parameter, count));,) + +#define VTK_M_DO_FOR_EACH(NumParamsPlusOne) \ + template \ + VTK_M_DO_FOR_EACH_EXPORT \ + void VTK_M_DO_FOR_EACH_NAME( \ + const Functor &f, \ + VTK_M_DO_FOR_EACH_FI_CONST ParameterContainer ¶meters) \ + { \ + (void)f; \ + (void)parameters; \ + BOOST_PP_REPEAT(NumParamsPlusOne, VTK_M_DO_FOR_EACH_CALL_PARAM,) \ + } +#define VTK_M_DO_FOR_EACH_REPEAT(z, NumParams, data) \ + VTK_M_DO_FOR_EACH(BOOST_PP_INC(NumParams)) + +#define VTK_M_DO_FOR_EACH_EXPORT VTKM_CONT_EXPORT +#define VTK_M_DO_FOR_EACH_NAME DoForEachCont +#define VTK_M_DO_FOR_EACH_FI_CONST const +BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS), + VTK_M_DO_FOR_EACH_REPEAT,) +#undef VTK_M_DO_FOR_EACH_FI_CONST +#undef VTK_M_DO_FOR_EACH_NAME +#undef VTK_M_DO_FOR_EACH_EXPORT + +#define VTK_M_DO_FOR_EACH_EXPORT VTKM_CONT_EXPORT +#define VTK_M_DO_FOR_EACH_NAME DoForEachCont +#define VTK_M_DO_FOR_EACH_FI_CONST +BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS), + VTK_M_DO_FOR_EACH_REPEAT,) +#undef VTK_M_DO_FOR_EACH_FI_CONST +#undef VTK_M_DO_FOR_EACH_NAME +#undef VTK_M_DO_FOR_EACH_EXPORT + +#define VTK_M_DO_FOR_EACH_EXPORT VTKM_EXEC_EXPORT +#define VTK_M_DO_FOR_EACH_NAME DoForEachExec +#define VTK_M_DO_FOR_EACH_FI_CONST const +BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS), + VTK_M_DO_FOR_EACH_REPEAT,) +#undef VTK_M_DO_FOR_EACH_FI_CONST +#undef VTK_M_DO_FOR_EACH_NAME +#undef VTK_M_DO_FOR_EACH_EXPORT + +#define VTK_M_DO_FOR_EACH_EXPORT VTKM_EXEC_EXPORT +#define VTK_M_DO_FOR_EACH_NAME DoForEachExec +#define VTK_M_DO_FOR_EACH_FI_CONST +BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS), + VTK_M_DO_FOR_EACH_REPEAT,) +#undef VTK_M_DO_FOR_EACH_FI_CONST +#undef VTK_M_DO_FOR_EACH_NAME +#undef VTK_M_DO_FOR_EACH_EXPORT + +#undef VTK_M_DO_FOR_EACH_REPEAT +#undef VTK_M_DO_FOR_EACH +#undef VTK_M_DO_FOR_EACH_CALL_PARAM + } // namespace detail template @@ -461,7 +549,7 @@ public: template VTKM_EXEC_CONT_EXPORT typename ParameterType::type - GetParameter() { + GetParameter() const { return detail::GetParameter(this->Parameters); } @@ -632,7 +720,7 @@ public: /// \brief Transforms the \c FunctionInterface based on compile-time /// information. /// - /// The \c StaticTransform method transforms all the parameters of this \c + /// The \c StaticTransform methods transform 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 @@ -675,7 +763,7 @@ public: template VTKM_CONT_EXPORT typename StaticTransformType::type - StaticTransformCont(const Transform &transform) + StaticTransformCont(const Transform &transform) const { typename StaticTransformType::type newFuncInterface; detail::DoStaticTransformCont(transform, @@ -686,7 +774,7 @@ public: template VTKM_EXEC_EXPORT typename StaticTransformType::type - StaticTransformExec(const Transform &transform) + StaticTransformExec(const Transform &transform) const { typename StaticTransformType::type newFuncInterface; detail::DoStaticTransformExec(transform, @@ -767,9 +855,8 @@ public: /// template VTKM_CONT_EXPORT - void - DynamicTransformCont(const TransformFunctor &transform, - const FinishFunctor &finish) { + void DynamicTransformCont(const TransformFunctor &transform, + const FinishFunctor &finish) { typedef detail::FunctionInterfaceDynamicTransformContContinue< FunctionSignature, ResultType(), @@ -784,6 +871,33 @@ public: this->Result = emptyInterface.GetReturnValueSafe(); } + /// \brief Applies a function to all the parameters. + /// + /// The \c ForEach methods take a function and apply that function to each + /// of the parameters in the \c FunctionInterface. (Return values are not + /// effected.) + /// + template + VTKM_CONT_EXPORT + void ForEachCont(const Functor &f) const { + detail::DoForEachCont(f, this->Parameters); + } + template + VTKM_CONT_EXPORT + void ForEachCont(const Functor &f) { + detail::DoForEachCont(f, this->Parameters); + } + template + VTKM_EXEC_EXPORT + void ForEachExec(const Functor &f) const { + detail::DoForEachExec(f, this->Parameters); + } + template + VTKM_EXEC_EXPORT + void ForEachExec(const Functor &f) { + detail::DoForEachExec(f, this->Parameters); + } + private: vtkm::internal::FunctionInterfaceReturnContainer Result; detail::ParameterContainer Parameters; diff --git a/vtkm/internal/testing/UnitTestFunctionInterface.cxx b/vtkm/internal/testing/UnitTestFunctionInterface.cxx index 5a961a7cc..e41f124a0 100644 --- a/vtkm/internal/testing/UnitTestFunctionInterface.cxx +++ b/vtkm/internal/testing/UnitTestFunctionInterface.cxx @@ -298,6 +298,14 @@ struct DynamicTransformFinish } }; +struct ForEachFunctor +{ + template + void operator()(T &x) const { x = 2*x; } + + void operator()(std::string &x) const { x.append("*2"); } +}; + void TryFunctionInterface5( vtkm::internal::FunctionInterface funcInterface) { @@ -470,6 +478,33 @@ void TestDynamicTransform() "DynamicTransform did not call finish the right number of times."); } +void TestForEach() +{ + std::cout << "Checking running a function on each parameter." << std::endl; + vtkm::internal::FunctionInterface + funcInterface = vtkm::internal::make_FunctionInterface( + Arg1, Arg2, Arg3, Arg4, Arg5); + VTKM_TEST_ASSERT(funcInterface.GetParameter<1>() == Arg1, "Arg 1 incorrect."); + VTKM_TEST_ASSERT(funcInterface.GetParameter<2>() == Arg2, "Arg 2 incorrect."); + VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() == Arg3, "Arg 3 incorrect."); + VTKM_TEST_ASSERT(funcInterface.GetParameter<4>() == Arg4, "Arg 4 incorrect."); + VTKM_TEST_ASSERT(funcInterface.GetParameter<5>() == Arg5, "Arg 5 incorrect."); + + funcInterface.ForEachCont(ForEachFunctor()); + VTKM_TEST_ASSERT(funcInterface.GetParameter<1>() == 2*Arg1, "Arg 1 incorrect."); + VTKM_TEST_ASSERT(funcInterface.GetParameter<2>() == 2*Arg2, "Arg 2 incorrect."); + VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() == Arg3+"*2", "Arg 3 incorrect."); + VTKM_TEST_ASSERT(funcInterface.GetParameter<4>() == 2*Arg4, "Arg 4 incorrect."); + VTKM_TEST_ASSERT(funcInterface.GetParameter<5>() == 2*Arg5, "Arg 5 incorrect."); + + funcInterface.ForEachExec(ForEachFunctor()); + VTKM_TEST_ASSERT(funcInterface.GetParameter<1>() == 4*Arg1, "Arg 1 incorrect."); + VTKM_TEST_ASSERT(funcInterface.GetParameter<2>() == 4*Arg2, "Arg 2 incorrect."); + VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() == Arg3+"*2*2", "Arg 3 incorrect."); + VTKM_TEST_ASSERT(funcInterface.GetParameter<4>() == 4*Arg4, "Arg 4 incorrect."); + VTKM_TEST_ASSERT(funcInterface.GetParameter<5>() == 4*Arg5, "Arg 5 incorrect."); +} + void TestInvokeTime() { std::cout << "Checking time to call lots of args lots of times." << std::endl; @@ -530,6 +565,7 @@ void TestFunctionInterface() TestTransformInvoke(); TestStaticTransform(); TestDynamicTransform(); + TestForEach(); TestInvokeTime(); }