mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
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:
parent
9ff1f5d8a9
commit
daa6b0984b
@ -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();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user