Another round of simplifications to FunctionInterface

Yet more ways that we can reduce the complexity of `FunctionInterface`.
This is another step in figuring out what set of features the replacement
for `FunctionInterface` needs to have.
This commit is contained in:
Robert Maynard 2019-12-03 13:30:43 -05:00
parent 9ff1f5d8a9
commit daa6b0984b
8 changed files with 410 additions and 1804 deletions

@ -55,6 +55,37 @@ struct TestZeroPortal
ValueType Get(vtkm::Id) const { return 0; }
};
template <vtkm::IdComponent IndexToReplace, typename U>
struct replace
{
U theReplacement;
template <typename T, vtkm::IdComponent Index>
struct ReturnType
{
using type = T;
};
template <typename T>
struct ReturnType<T, IndexToReplace>
{
using type = U;
};
template <typename T, vtkm::IdComponent Index>
VTKM_CONT typename ReturnType<T, Index>::type operator()(T&& x,
vtkm::internal::IndexTag<Index>) const
{
return x;
}
template <typename T>
VTKM_CONT U operator()(T&&, vtkm::internal::IndexTag<IndexToReplace>) const
{
return theReplacement;
}
};
template <vtkm::IdComponent InputDomainIndex, vtkm::IdComponent ParamIndex, typename T>
struct FetchArrayTopologyMapInTests
{
@ -80,7 +111,7 @@ struct FetchArrayTopologyMapInTests
threadIndex, inputIndex, visitIndex, outputIndex, invocation.GetInputDomain());
typename FetchType::ValueType value =
fetch.Load(indices, invocation.Parameters.template GetParameter<ParamIndex>());
fetch.Load(indices, vtkm::internal::ParameterGet<ParamIndex>(invocation.Parameters));
VTKM_TEST_ASSERT(value.GetNumberOfComponents() == 8,
"Topology fetch got wrong number of components.");
@ -99,12 +130,6 @@ struct FetchArrayTopologyMapInTests
std::cout << "Trying ArrayTopologyMapIn fetch on parameter " << ParamIndex << " with type "
<< vtkm::testing::TypeName<T>::Name() << std::endl;
using BaseFunctionInterface = vtkm::internal::FunctionInterface<void(vtkm::internal::NullType,
vtkm::internal::NullType,
vtkm::internal::NullType,
vtkm::internal::NullType,
vtkm::internal::NullType)>;
vtkm::internal::ConnectivityStructuredInternals<3> connectivityInternals;
connectivityInternals.SetPointDimensions(vtkm::Id3(2, 2, 2));
vtkm::exec::ConnectivityStructured<vtkm::TopologyElementTagCell,
@ -112,18 +137,26 @@ struct FetchArrayTopologyMapInTests
3>
connectivity(connectivityInternals);
this->TryInvocation(vtkm::internal::make_Invocation<InputDomainIndex>(
BaseFunctionInterface()
.Replace<InputDomainIndex>(connectivity)
.template Replace<ParamIndex>(TestPortal<T>()),
BaseFunctionInterface(),
BaseFunctionInterface(),
TestIndexPortal(),
TestZeroPortal(),
TestIndexPortal()));
using NullType = vtkm::internal::NullType;
auto baseFunctionInterface = vtkm::internal::make_FunctionInterface<void>(
NullType{}, NullType{}, NullType{}, NullType{}, NullType{});
replace<InputDomainIndex, decltype(connectivity)> connReplaceFunctor{ connectivity };
replace<ParamIndex, TestPortal<T>> portalReplaceFunctor{ TestPortal<T>{} };
auto updatedInterface = baseFunctionInterface.StaticTransformCont(connReplaceFunctor)
.StaticTransformCont(portalReplaceFunctor);
this->TryInvocation(vtkm::internal::make_Invocation<InputDomainIndex>(updatedInterface,
baseFunctionInterface,
baseFunctionInterface,
TestIndexPortal(),
TestZeroPortal(),
TestIndexPortal()));
}
};
struct TryType
{
template <typename T>
@ -160,7 +193,7 @@ void TryStructuredPointCoordinatesInvocation(const Invocation& invocation)
vtkm::VecAxisAlignedPointCoordinates<NumDimensions> value =
fetch.Load(ThreadIndicesType(
threadIndex, inputIndex, visitIndex, outputIndex, invocation.GetInputDomain()),
invocation.Parameters.template GetParameter<ParamIndex>());
vtkm::internal::ParameterGet<ParamIndex>(invocation.Parameters));
VTKM_TEST_ASSERT(test_equal(value.GetOrigin(), origin), "Bad origin.");
VTKM_TEST_ASSERT(test_equal(value.GetSpacing(), spacing), "Bad spacing.");
}
@ -174,7 +207,7 @@ void TryStructuredPointCoordinatesInvocation(const Invocation& invocation)
vtkm::VecAxisAlignedPointCoordinates<NumDimensions> value =
fetch.Load(ThreadIndicesType(
threadIndex, inputIndex, visitIndex, outputIndex, invocation.GetInputDomain()),
invocation.Parameters.template GetParameter<ParamIndex>());
vtkm::internal::ParameterGet<ParamIndex>(invocation.Parameters));
VTKM_TEST_ASSERT(test_equal(value.GetOrigin(), origin), "Bad origin.");
VTKM_TEST_ASSERT(test_equal(value.GetSpacing(), spacing), "Bad spacing.");
}
@ -187,28 +220,34 @@ void TryStructuredPointCoordinates(
NumDimensions>& connectivity,
const vtkm::internal::ArrayPortalUniformPointCoordinates& coordinates)
{
using BaseFunctionInterface = vtkm::internal::FunctionInterface<void(vtkm::internal::NullType,
vtkm::internal::NullType,
vtkm::internal::NullType,
vtkm::internal::NullType,
vtkm::internal::NullType)>;
using NullType = vtkm::internal::NullType;
auto baseFunctionInterface = vtkm::internal::make_FunctionInterface<void>(
NullType{}, NullType{}, NullType{}, NullType{}, NullType{});
auto firstFunctionInterface = vtkm::internal::make_FunctionInterface<void>(
connectivity, coordinates, NullType{}, NullType{}, NullType{});
// Try with topology in argument 1 and point coordinates in argument 2
TryStructuredPointCoordinatesInvocation<NumDimensions, 2>(vtkm::internal::make_Invocation<1>(
BaseFunctionInterface().Replace<1>(connectivity).template Replace<2>(coordinates),
BaseFunctionInterface(),
BaseFunctionInterface(),
TestIndexPortal(),
TestZeroPortal(),
TestIndexPortal()));
TryStructuredPointCoordinatesInvocation<NumDimensions, 2>(
vtkm::internal::make_Invocation<1>(firstFunctionInterface,
baseFunctionInterface,
baseFunctionInterface,
TestIndexPortal(),
TestZeroPortal(),
TestIndexPortal()));
// Try again with topology in argument 3 and point coordinates in argument 1
TryStructuredPointCoordinatesInvocation<NumDimensions, 1>(vtkm::internal::make_Invocation<3>(
BaseFunctionInterface().Replace<3>(connectivity).template Replace<1>(coordinates),
BaseFunctionInterface(),
BaseFunctionInterface(),
TestIndexPortal(),
TestZeroPortal(),
TestIndexPortal()));
auto secondFunctionInterface = vtkm::internal::make_FunctionInterface<void>(
coordinates, NullType{}, connectivity, NullType{}, NullType{});
TryStructuredPointCoordinatesInvocation<NumDimensions, 1>(
vtkm::internal::make_Invocation<3>(secondFunctionInterface,
baseFunctionInterface,
baseFunctionInterface,
TestIndexPortal(),
TestZeroPortal(),
TestIndexPortal()));
}
void TryStructuredPointCoordinates()

@ -93,7 +93,7 @@ struct InvocationToFetch
VTKM_EXEC static ExecObjectType GetParameterImpl(const Invocation& invocation, std::false_type)
{
return invocation.Parameters.template GetParameter<ControlParameterIndex>();
return vtkm::internal::ParameterGet<ControlParameterIndex>(invocation.Parameters);
}
VTKM_EXEC static ExecObjectType GetParameter(const Invocation& invocation)

@ -154,7 +154,7 @@ struct InvocationToFetch
VTKM_EXEC static ExecObjectType GetParameterImpl(const Invocation& invocation, std::false_type)
{
return invocation.Parameters.template GetParameter<ControlParameterIndex>();
return vtkm::internal::ParameterGet<ControlParameterIndex>(invocation.Parameters);
}
VTKM_EXEC static ExecObjectType GetParameter(const Invocation& invocation)

@ -25,38 +25,6 @@ namespace internal
namespace detail
{
// These functions exist to help copy components of a FunctionInterface.
template <vtkm::IdComponent NumToMove, vtkm::IdComponent ParameterIndex = 1>
struct FunctionInterfaceMoveParameters
{
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename DestSignature, typename SrcSignature>
static VTKM_EXEC_CONT void Move(
vtkm::internal::detail::ParameterContainer<DestSignature>& dest,
const vtkm::internal::detail::ParameterContainer<SrcSignature>& src)
{
ParameterContainerAccess<ParameterIndex> pca;
// using forwarding_type = typename AtType<ParameterIndex, SrcSignature>::type;
pca.Move(dest, src);
// std::forward<forwarding_type>(pca.Get(src)) );
// pca.Get(src));
FunctionInterfaceMoveParameters<NumToMove - 1, ParameterIndex + 1>::Move(dest, src);
}
};
template <vtkm::IdComponent ParameterIndex>
struct FunctionInterfaceMoveParameters<0, ParameterIndex>
{
template <typename DestSignature, typename SrcSignature>
static VTKM_EXEC_CONT void Move(vtkm::internal::detail::ParameterContainer<DestSignature>&,
const vtkm::internal::detail::ParameterContainer<SrcSignature>&)
{
// Nothing left to move.
}
};
template <typename OriginalSignature, typename Transform>
struct FunctionInterfaceStaticTransformType;
@ -116,46 +84,9 @@ struct FunctionInterfaceStaticTransformType;
/// functionInterface.GetArity();
/// \endcode
///
/// You can get a particular parameter using the templated method \c
/// GetParameter. The template parameter is the index of the parameter
/// (starting at 1). Note that if the \c FunctionInterface is used in a
/// templated function or method where the type is not fully resolved, you need
/// to use the \c template keyword. One of the two forms should work. Try
/// switching if you get a compiler error.
///
/// \code{.cpp}
/// // Use this form if functionInterface is a fully resolved type.
/// functionInterface.GetParameter<1>();
///
/// // Use this form if functionInterface is partially specified.
/// functionInterface.template GetParameter<1>();
/// \endcode
///
/// Likewise, there is a \c SetParameter method for changing parameters. The
/// same rules for indexing and template specification apply.
///
/// \code{.cpp}
/// // Use this form if functionInterface is a fully resolved type.
/// functionInterface.SetParameter<1>(100);
///
/// // Use this form if functionInterface is partially specified.
/// functionInterface.template SetParameter<1>(100);
/// \endcode
///
/// \c FunctionInterface also provides several methods for modifying the
/// parameters. First, the \c Append method tacks an additional parameter to
/// the end of the function signature.
///
/// \code{.cpp}
/// functionInterface.Append<std::string>(std::string("New Arg"));
/// \endcode
///
/// Next, the \c Replace method removes a parameter at a particular position
/// and replaces it with another object of a different type.
///
/// \code{.cpp}
/// functionInterface.Replace<1>(std::string("new first argument"));
/// \endcode
/// You can get a particular parameter using the templated function \c
/// ParameterGet. The template parameter is the index of the parameter
/// (starting at 1).
///
/// Finally, there is a way to replace all of the parameters at
/// once. The \c StaticTransform methods take a transform functor that modifies
@ -185,8 +116,6 @@ public:
// the number of parameters as an integral constant
using SigInfo = detail::FunctionSigInfo<FunctionSignature>;
using SignatureArity = typename SigInfo::ArityType;
using ResultType = typename SigInfo::ResultType;
using ComponentSig = typename SigInfo::Components;
using ParameterSig = typename SigInfo::Parameters;
@ -206,195 +135,6 @@ public:
VTKM_EXEC_CONT
vtkm::IdComponent GetArity() const { return ARITY; }
/// Gets the value for the parameter of the given index. Parameters are
/// indexed starting at 1. To use this method you have to specify a static,
/// compile time index. There are two ways to specify the index. The first is
/// to specify a specific template parameter (e.g.
/// <tt>GetParameter<1>()</tt>). Note that if you are using FunctionInterface
/// within a template (which is almost always the case), then you will have
/// to use the template keyword. For example, here is a simple implementation
/// of a method that grabs the first parameter of FunctionInterface.
///
/// \code{.cpp}
/// template<FunctionSignature>
/// void Foo(const vtkm::internal::FunctionInterface<FunctionSignature> &fInterface)
/// {
/// bar(fInterface.template GetParameter<1>());
/// }
/// \endcode
///
/// Alternatively the \c GetParameter method also has an optional argument
/// that can be a \c IndexTag that specifies the parameter index. Here is
/// a repeat of the previous example using this method.
///
/// \code{.cpp}
/// template<FunctionSignature>
/// void Foo(const vtkm::internal::FunctionInterface<FunctionSignature> &fInterface)
/// {
/// using vtkm::internal::IndexTag;
/// bar(fInterface.GetParameter(IndexTag<1>()));
/// }
/// \endcode
///
template <vtkm::IdComponent ParameterIndex>
VTKM_EXEC_CONT const typename ParameterType<ParameterIndex>::type& GetParameter(
vtkm::internal::IndexTag<ParameterIndex> = vtkm::internal::IndexTag<ParameterIndex>()) const
{
return (detail::ParameterContainerAccess<ParameterIndex>()).Get(this->Parameters);
}
/// Sets the value for the parameter of the given index. Parameters are
/// indexed starting at 1. To use this method you have to specify a static,
/// compile time index. There are two ways to specify the index. The first is
/// to specify a specific template parameter (e.g.
/// <tt>SetParameter<1>(value)</tt>). Note that if you are using
/// FunctionInterface within a template (which is almost always the case),
/// then you will have to use the template keyword. For example, here is a
/// simple implementation of a method that grabs the first parameter of
/// FunctionInterface.
///
/// \code{.cpp}
/// template<FunctionSignature>
/// void Foo(vtkm::internal::FunctionInterface<FunctionSignature> &fInterface)
/// {
/// fInterface.template SetParameter<1>(bar);
/// }
/// \endcode
///
/// Alternatively the \c GetParameter method also has an optional argument
/// that can be a \c IndexTag that specifies the parameter index. Here is
/// a repeat of the previous example using this method.
///
/// \code{.cpp}
/// template<FunctionSignature>
/// void Foo(vtkm::internal::FunctionInterface<FunctionSignature> &fInterface)
/// {
/// using vtkm::internal::IndexTag;
/// fInterface.SetParameter(bar, IndexTag<1>());
/// }
/// \endcode
///
/// Sets the value for the parameter of the given index. Parameters are
/// indexed starting at 1. To use this method you have to specify the index
/// as a template parameter. If you are using FunctionInterface within a
/// template (which is almost always the case), then you will have to use the
/// template keyword.
///
template <vtkm::IdComponent ParameterIndex>
VTKM_EXEC_CONT void SetParameter(
const typename ParameterType<ParameterIndex>::type& parameter,
vtkm::internal::IndexTag<ParameterIndex> = vtkm::internal::IndexTag<ParameterIndex>())
{
return (detail::ParameterContainerAccess<ParameterIndex>()).Set(this->Parameters, parameter);
}
/// Copies the parameters and return values from the given \c
/// FunctionInterface to this object. The types must be copiable from source
/// to destination. If the number of parameters in the two objects are not
/// the same, copies the first N arguments, where N is the smaller arity of
/// the two function interfaces.
///
template <typename SrcFunctionSignature>
void Copy(const FunctionInterface<SrcFunctionSignature>& src)
{
constexpr vtkm::UInt16 minArity = (ARITY < FunctionInterface<SrcFunctionSignature>::ARITY)
? ARITY
: FunctionInterface<SrcFunctionSignature>::ARITY;
(detail::CopyAllParameters<minArity>()).Copy(this->Parameters, src.Parameters);
}
void Copy(const FunctionInterface<FunctionSignature>& src)
{ //optimized version for assignment/copy
this->Parameters = src.Parameters;
}
template <typename NewType>
struct AppendType
{
using type = FunctionInterface<typename detail::AppendType<ComponentSig, NewType>::type>;
};
/// Returns a new \c FunctionInterface with all the parameters of this \c
/// FunctionInterface and the given method argument appended to these
/// parameters. The return type can be determined with the \c AppendType
/// template.
///
template <typename NewType>
VTKM_CONT typename AppendType<NewType>::type Append(const NewType& newParameter) const
{
using AppendSignature = typename detail::AppendType<ComponentSig, NewType>::type;
FunctionInterface<AppendSignature> appendedFuncInterface;
appendedFuncInterface.Copy(*this);
appendedFuncInterface.template SetParameter<ARITY + 1>(newParameter);
return appendedFuncInterface;
}
template <vtkm::IdComponent ParameterIndex, typename NewType>
struct ReplaceType
{
using type =
FunctionInterface<typename detail::ReplaceType<ComponentSig, ParameterIndex, NewType>::type>;
};
/// Returns a new \c FunctionInterface with all the parameters of this \c
/// FunctionInterface except that the parameter indexed at the template
/// parameter \c ParameterIndex (also specified with the optional second
/// argument) is replaced with the given argument. This method can be used in
/// place of SetParameter when the parameter type changes. The return type
/// can be determined with the \c ReplaceType template.
/// Gets the value for the parameter of the given index. Parameters are
/// indexed starting at 1. To use this method you have to specify a static,
/// compile time index. There are two ways to specify the index. The first is
/// to specify a specific template parameter (e.g.
/// <tt>GetParameter<1>()</tt>). Note that if you are using FunctionInterface
/// within a template (which is almost always the case), then you will have
/// to use the template keyword. For example, here is a simple implementation
/// of a method that grabs the first parameter of FunctionInterface.
///
/// \code{.cpp}
/// template<FunctionSignature>
/// void Foo(const vtkm::internal::FunctionInterface<FunctionSignature> &fInterface)
/// {
/// bar(fInterface.template GetParameter<1>());
/// }
/// \endcode
///
/// Alternatively the \c GetParameter method also has an optional argument
/// that can be a \c IndexTag that specifies the parameter index. Here is
/// a repeat of the previous example using this method.
///
/// \code{.cpp}
/// template<FunctionSignature>
/// void Foo(const vtkm::internal::FunctionInterface<FunctionSignature> &fInterface)
/// {
/// using vtkm::internal::IndexTag;
/// bar(fInterface.GetParameter(IndexTag<1>()));
/// }
/// \endcode
///
///
template <vtkm::IdComponent ParameterIndex, typename NewType>
VTKM_CONT typename ReplaceType<ParameterIndex, NewType>::type Replace(
const NewType& newParameter,
vtkm::internal::IndexTag<ParameterIndex> = vtkm::internal::IndexTag<ParameterIndex>()) const
{
using ReplaceSigType =
typename detail::ReplaceType<ComponentSig, ParameterIndex, NewType>::type;
FunctionInterface<ReplaceSigType> replacedFuncInterface;
detail::FunctionInterfaceMoveParameters<ParameterIndex - 1>::Move(
replacedFuncInterface.Parameters, this->Parameters);
replacedFuncInterface.template SetParameter<ParameterIndex>(newParameter);
detail::FunctionInterfaceMoveParameters<ARITY - ParameterIndex, ParameterIndex + 1>::Move(
replacedFuncInterface.Parameters, this->Parameters);
return replacedFuncInterface;
}
template <typename Transform>
struct StaticTransformType
{
@ -451,15 +191,35 @@ public:
VTKM_CONT typename StaticTransformType<Transform>::type StaticTransformCont(
const Transform& transform)
{
typename StaticTransformType<Transform>::type newFuncInterface;
detail::DoStaticTransformCont(transform, this->Parameters, newFuncInterface.Parameters);
return newFuncInterface;
using FuncIface = typename StaticTransformType<Transform>::type;
using PC = detail::ParameterContainer<typename FuncIface::Signature>;
return FuncIface{ detail::DoStaticTransformCont<PC>(transform, this->Parameters) };
}
private:
detail::ParameterContainer<FunctionSignature> Parameters;
};
/// Gets the value for the parameter of the given index. Parameters are
/// indexed starting at 1. To use this method you have to specify a static,
/// compile time index.
///
/// \code{.cpp}
/// template<FunctionSignature>
/// void Foo(const vtkm::internal::FunctionInterface<FunctionSignature> &fInterface)
/// {
/// bar( ParameterGet<2>(fInterface) );
/// }
/// \endcode
///
template <vtkm::IdComponent ParameterIndex, typename FunctionSignature>
VTKM_EXEC_CONT auto ParameterGet(const FunctionInterface<FunctionSignature>& fInterface)
-> decltype(detail::ParameterGet(fInterface.Parameters,
vtkm::internal::IndexTag<ParameterIndex>{}))
{
return detail::ParameterGet(fInterface.Parameters, vtkm::internal::IndexTag<ParameterIndex>{});
}
//============================================================================
/// \brief Create a \c FunctionInterface
///

File diff suppressed because it is too large Load Diff

@ -143,105 +143,22 @@ struct AtType<Index, R(ArgTypes...)>
using type = brigand::at_c<brigand::list<R, ArgTypes...>, Index>;
};
template <typename Collection, typename NewType>
struct AppendType;
template <template <typename...> class L, typename T, typename NT, typename... U>
struct AppendType<L<T, U...>, NT>
{
using type = T(U..., NT);
};
template <typename Collection>
struct AsSigType;
template <template <typename...> class L, typename T, typename... U>
struct AsSigType<L<T, U...>>
{
using type = T(U...);
};
template <typename Components, vtkm::IdComponent ParameterIndex, typename NewType>
class ReplaceType
{
using Index = std::integral_constant<std::size_t, (std::size_t)ParameterIndex>;
using split = brigand::split_at<Components, Index>;
using front = brigand::push_back<brigand::front<split>, NewType>;
using back = brigand::pop_front<brigand::back<split>>;
using replaced = brigand::append<front, back>;
public:
using type = typename AsSigType<replaced>::type;
};
//============================================================================
template <int ParameterIndex>
struct ParameterContainerAccess;
// clang-format off
$for(param_index in range(1, max_parameters+1))\
template <>
struct ParameterContainerAccess<$(param_index)>
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename FunctionSignature>
VTKM_EXEC_CONT auto ParameterGet(const ParameterContainer<FunctionSignature>& parameters,
vtkm::internal::IndexTag<$(param_index)>)
-> decltype(parameters.Parameter$(param_index)) const&
{
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename FunctionSignature>
VTKM_EXEC_CONT const typename AtType<$(param_index), FunctionSignature>::type& Get(
const ParameterContainer<FunctionSignature>& parameters)
{
return parameters.Parameter$(param_index);
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename FunctionSignature>
VTKM_EXEC_CONT void Set(ParameterContainer<FunctionSignature>& parameters,
const typename AtType<$(param_index), FunctionSignature>::type& value)
{
parameters.Parameter$(param_index) = value;
}
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename FunctionSignatureDest, typename FunctionSignatureSrc>
VTKM_EXEC_CONT void Move(ParameterContainer<FunctionSignatureDest>& dest,
const ParameterContainer<FunctionSignatureSrc>& src)
{
dest.Parameter$(param_index) = std::move(src.Parameter$(param_index));
}
};
return parameters.Parameter$(param_index);
}
$endfor\
//============================================================================
template <vtkm::IdComponent NumToCopy>
struct CopyAllParameters;
$for(num_params in range(1, max_parameters+1))\
template <>
struct CopyAllParameters<$(num_params)>
{
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename DestSignature, typename SrcSignature>
VTKM_EXEC_CONT void Copy(vtkm::internal::detail::ParameterContainer<DestSignature>& dest,
const vtkm::internal::detail::ParameterContainer<SrcSignature>& src)
{
$for(param_index in range(1, num_params+1))\
dest.Parameter$(param_index) = src.Parameter$(param_index);
$endfor\
}
};
$endfor\
template <>
struct CopyAllParameters<0>
{
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename DestSignature, typename SrcSignature>
VTKM_EXEC_CONT void Copy(vtkm::internal::detail::ParameterContainer<DestSignature>&,
const vtkm::internal::detail::ParameterContainer<SrcSignature>&)
{
// Nothing to copy.
}
};
// clang-format on
//============================================================================
@ -253,20 +170,18 @@ struct FunctionInterfaceStaticTransformType;
$for(num_params in range(0, max_parameters))\
$for(environment in ['Cont'])\
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename Transform,
$template_params(num_params,0,'Original'),
$template_params(num_params,0,'Transformed')>
VTKM_$(environment.upper()) void DoStaticTransform$(environment)(
template <typename Result,
typename Transform,
$template_params(num_params,0,'Original')>
VTKM_$(environment.upper()) Result DoStaticTransform$(environment)(
const Transform& transform,
ParameterContainer<$signature(num_params,ptype(0,'Original'),'Original')>& originalParameters,
ParameterContainer<$signature(num_params,ptype(0,'Transformed'),'Transformed')>& transformedParameters)
ParameterContainer<$signature(num_params,ptype(0,'Original'),'Original')>& originalParameters)
{
$if(num_params < 1)\
(void)transform;
(void)originalParameters;
(void)transformedParameters;
$else\
transformedParameters = {
return Result{
$for(param_index in range(1, num_params+1))\
transform(originalParameters.Parameter$(param_index), vtkm::internal::IndexTag<$(param_index)>())$comma_if(param_index<num_params)
$endfor\

@ -11,6 +11,7 @@
#define vtk_m_internal_Invocation_h
#include <vtkm/Types.h>
#include <vtkm/internal/FunctionInterface.h>
namespace vtkm
{
@ -342,7 +343,7 @@ struct Invocation
VTKM_EXEC_CONT
const InputDomainType& GetInputDomain() const
{
return this->Parameters.template GetParameter<InputDomainIndex>();
return vtkm::internal::ParameterGet<InputDomainIndex>(this->Parameters);
}
/// The state of an \c Invocation object holds the parameters of the

@ -46,77 +46,38 @@ struct PointerTransform
}
};
void TryFunctionInterface5(
vtkm::internal::FunctionInterface<void(Type1, Type2, Type3, Type4, Type5)> funcInterface)
{
std::cout << "Checking 5 parameter function interface." << std::endl;
VTKM_TEST_ASSERT(funcInterface.GetArity() == 5, "Got wrong number of parameters.");
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.");
std::cout << "Swizzling parameters with replace." << std::endl;
funcInterface.Replace<1>(Arg5).Replace(Arg1, vtkm::internal::IndexTag<2>()).Replace<5>(Arg2);
}
void TestBasicFunctionInterface()
{
using vtkm::internal::ParameterGet;
std::cout << "Creating basic function interface." << std::endl;
vtkm::internal::FunctionInterface<void(Type1, Type2, Type3)> funcInterface =
vtkm::internal::make_FunctionInterface<void>(Arg1, Arg2, Arg3);
std::cout << "Checking parameters." << std::endl;
VTKM_TEST_ASSERT(funcInterface.GetArity() == 3, "Got wrong number of parameters.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<1>() == Arg1, "Arg 1 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter(vtkm::internal::IndexTag<2>()) == Arg2,
"Arg 2 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() == Arg3, "Arg 3 incorrect.");
VTKM_TEST_ASSERT(ParameterGet<1>(funcInterface) == Arg1, "Arg 1 incorrect.");
VTKM_TEST_ASSERT(ParameterGet<2>(funcInterface) == Arg2, "Arg 2 incorrect.");
VTKM_TEST_ASSERT(ParameterGet<3>(funcInterface) == Arg3, "Arg 3 incorrect.");
std::cout << "Checking invocation with argument modification." << std::endl;
funcInterface.SetParameter<1>(Type1());
funcInterface.SetParameter(Type2(), vtkm::internal::IndexTag<2>());
funcInterface.SetParameter<3>(Type3());
VTKM_TEST_ASSERT(funcInterface.GetParameter<1>() != Arg1, "Arg 1 not cleared.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<2>() != Arg2, "Arg 2 not cleared.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() != Arg3, "Arg 3 not cleared.");
vtkm::internal::FunctionInterface<void(Type1, Type2, Type3)> funcInterfaceEmpty;
VTKM_TEST_ASSERT(funcInterfaceEmpty.GetArity() == 3, "Got wrong number of parameters.");
VTKM_TEST_ASSERT(ParameterGet<1>(funcInterfaceEmpty) != Arg1, "Arg 1 incorrect.");
VTKM_TEST_ASSERT(ParameterGet<2>(funcInterfaceEmpty) != Arg2, "Arg 2 incorrect.");
VTKM_TEST_ASSERT(ParameterGet<3>(funcInterfaceEmpty) != Arg3, "Arg 3 incorrect.");
funcInterface.SetParameter(Arg2, vtkm::internal::IndexTag<2>());
funcInterface.SetParameter<1>(Arg1);
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 not cleared.");
TryFunctionInterface5(vtkm::internal::make_FunctionInterface<void>(Arg1, Arg2, Arg3, Arg4, Arg5));
}
void TestAppend()
{
std::cout << "Appending interface with return value." << std::endl;
vtkm::internal::FunctionInterface<std::string(Type1, Type2)> funcInterface2ArgWRet =
vtkm::internal::make_FunctionInterface<std::string>(Arg1, Arg2);
vtkm::internal::FunctionInterface<std::string(Type1, Type2, Type3)> funcInterface3ArgWRet =
funcInterface2ArgWRet.Append(Arg3);
VTKM_TEST_ASSERT(funcInterface3ArgWRet.GetParameter<1>() == Arg1, "Arg 1 incorrect.");
VTKM_TEST_ASSERT(funcInterface3ArgWRet.GetParameter<2>() == Arg2, "Arg 2 incorrect.");
VTKM_TEST_ASSERT(funcInterface3ArgWRet.GetParameter<3>() == Arg3, "Arg 3 incorrect.");
std::cout << "Appending another value." << std::endl;
vtkm::internal::FunctionInterface<std::string(Type1, Type2, Type3, Type4)> funcInterface4ArgWRet =
funcInterface3ArgWRet.Append(Arg4);
VTKM_TEST_ASSERT(funcInterface4ArgWRet.GetParameter<4>() == Arg4, "Arg 4 incorrect.");
std::cout << "Checking double append." << std::endl;
vtkm::internal::FunctionInterface<void(Type1, Type2, Type3)> funcInterface3 =
vtkm::internal::make_FunctionInterface<void>(Arg1, Arg2, Arg3);
TryFunctionInterface5(funcInterface3.Append(Arg4).Append(Arg5));
auto funcInterface5 = vtkm::internal::make_FunctionInterface<void>(Arg1, Arg2, Arg3, Arg4, Arg5);
std::cout << "Checking 5 parameter function interface." << std::endl;
VTKM_TEST_ASSERT(funcInterface5.GetArity() == 5, "Got wrong number of parameters.");
VTKM_TEST_ASSERT(ParameterGet<1>(funcInterface5) == Arg1, "Arg 1 incorrect.");
VTKM_TEST_ASSERT(ParameterGet<2>(funcInterface5) == Arg2, "Arg 2 incorrect.");
VTKM_TEST_ASSERT(ParameterGet<3>(funcInterface5) == Arg3, "Arg 3 incorrect.");
VTKM_TEST_ASSERT(ParameterGet<4>(funcInterface5) == Arg4, "Arg 4 incorrect.");
VTKM_TEST_ASSERT(ParameterGet<5>(funcInterface5) == Arg5, "Arg 5 incorrect.");
}
void TestStaticTransform()
{
using vtkm::internal::ParameterGet;
std::cout << "Trying static transform." << std::endl;
using OriginalType = vtkm::internal::FunctionInterface<void(Type1, Type2, Type3)>;
OriginalType funcInterface = vtkm::internal::make_FunctionInterface<void>(Arg1, Arg2, Arg3);
@ -124,9 +85,9 @@ void TestStaticTransform()
std::cout << "Transform to pointer type." << std::endl;
auto funcInterfaceTransform1 = funcInterface.StaticTransformCont(PointerTransform());
using P1 = typename std::decay<decltype(funcInterfaceTransform1.GetParameter<1>())>::type;
using P2 = typename std::decay<decltype(funcInterfaceTransform1.GetParameter<2>())>::type;
using P3 = typename std::decay<decltype(funcInterfaceTransform1.GetParameter<3>())>::type;
using P1 = typename std::decay<decltype(ParameterGet<1>(funcInterfaceTransform1))>::type;
using P2 = typename std::decay<decltype(ParameterGet<2>(funcInterfaceTransform1))>::type;
using P3 = typename std::decay<decltype(ParameterGet<3>(funcInterfaceTransform1))>::type;
VTKM_STATIC_ASSERT((std::is_same<const Type1*, P1>::value));
VTKM_STATIC_ASSERT((std::is_same<const Type2*, P2>::value));
@ -136,7 +97,6 @@ void TestStaticTransform()
void TestFunctionInterface()
{
TestBasicFunctionInterface();
TestAppend();
TestStaticTransform();
}