mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-10-05 01:49:02 +00:00
Simplify FunctionInterface
This includes removing Exec, and Cont methods that VTK-m is no longer using. Also we simplify the used methods as much as possible.
This commit is contained in:
parent
462aacebb3
commit
d6d40c90d7
@ -22,7 +22,6 @@ set(headers
|
||||
ConnectivityExplicitInternals.h
|
||||
DeviceAdapterAlgorithmGeneral.h
|
||||
DeviceAdapterListHelpers.h
|
||||
DynamicTransform.h
|
||||
FunctorsGeneral.h
|
||||
IteratorFromArrayPortal.h
|
||||
KXSort.h
|
||||
|
@ -1,62 +0,0 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_cont_internal_DynamicTransform_h
|
||||
#define vtk_m_cont_internal_DynamicTransform_h
|
||||
|
||||
#include <vtkm/cont/CastAndCall.h>
|
||||
#include <vtkm/internal/IndexTag.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
/// This functor can be used as the transform in the \c DynamicTransformCont
|
||||
/// method of \c FunctionInterface. It will allow dynamic objects like
|
||||
/// \c DynamicArray to be cast to their concrete types for templated operation.
|
||||
///
|
||||
struct DynamicTransform
|
||||
{
|
||||
template <typename InputType, typename ContinueFunctor, vtkm::IdComponent Index>
|
||||
VTKM_CONT void operator()(const InputType& input,
|
||||
const ContinueFunctor& continueFunc,
|
||||
vtkm::internal::IndexTag<Index>) const
|
||||
{
|
||||
this->DoTransform(
|
||||
input,
|
||||
continueFunc,
|
||||
typename vtkm::cont::internal::DynamicTransformTraits<InputType>::DynamicTag());
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename InputType, typename ContinueFunctor>
|
||||
VTKM_CONT void DoTransform(const InputType& input,
|
||||
const ContinueFunctor& continueFunc,
|
||||
vtkm::cont::internal::DynamicTransformTagStatic) const
|
||||
{
|
||||
continueFunc(input);
|
||||
}
|
||||
|
||||
template <typename InputType, typename ContinueFunctor>
|
||||
VTKM_CONT void DoTransform(const InputType& dynamicInput,
|
||||
const ContinueFunctor& continueFunc,
|
||||
vtkm::cont::internal::DynamicTransformTagCastAndCall) const
|
||||
{
|
||||
CastAndCall(dynamicInput, continueFunc);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::cont::internal
|
||||
|
||||
#endif //vtk_m_cont_internal_DynamicTransform_h
|
@ -12,7 +12,6 @@
|
||||
set(unit_tests
|
||||
UnitTestArrayManagerExecutionShareWithControl.cxx
|
||||
UnitTestArrayPortalFromIterators.cxx
|
||||
UnitTestDynamicTransform.cxx
|
||||
UnitTestIteratorFromArrayPortal.cxx
|
||||
)
|
||||
vtkm_unit_tests(SOURCES ${unit_tests} DEFINES VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG)
|
||||
|
@ -1,196 +0,0 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
#include <vtkm/cont/internal/DynamicTransform.h>
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/DynamicCellSet.h>
|
||||
#include <vtkm/cont/VariantArrayHandle.h>
|
||||
|
||||
#include <vtkm/internal/FunctionInterface.h>
|
||||
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
|
||||
// VariantArrayHandle requires its value type to have a defined VecTraits
|
||||
// class. One of the tests is to use an "unusual" array of std::string
|
||||
// (which is pretty pointless but might tease out some assumptions).
|
||||
// Make an implementation here. Because I am lazy, this is only a partial
|
||||
// implementation.
|
||||
template <>
|
||||
struct VecTraits<std::string>
|
||||
{
|
||||
using IsSizeStatic = vtkm::VecTraitsTagSizeStatic;
|
||||
static constexpr vtkm::IdComponent NUM_COMPONENTS = 1;
|
||||
using HasMultipleComponents = vtkm::VecTraitsTagSingleComponent;
|
||||
};
|
||||
|
||||
} // namespace vtkm
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static int g_FunctionCalls;
|
||||
|
||||
#define TRY_TRANSFORM(expr) \
|
||||
g_FunctionCalls = 0; \
|
||||
expr; \
|
||||
VTKM_TEST_ASSERT(g_FunctionCalls == 1, "Functor not called correctly.")
|
||||
|
||||
struct TypeListTagString : vtkm::ListTagBase<std::string>
|
||||
{
|
||||
};
|
||||
|
||||
struct ScalarFunctor
|
||||
{
|
||||
void operator()(vtkm::FloatDefault) const
|
||||
{
|
||||
std::cout << " In Scalar functor." << std::endl;
|
||||
g_FunctionCalls++;
|
||||
}
|
||||
};
|
||||
|
||||
struct ArrayHandleScalarFunctor
|
||||
{
|
||||
template <typename ArrayType>
|
||||
void operator()(const ArrayType&) const
|
||||
{
|
||||
VTKM_TEST_FAIL("Called wrong form of functor operator.");
|
||||
}
|
||||
void operator()(const vtkm::cont::ArrayHandleVirtual<vtkm::FloatDefault>&) const
|
||||
{
|
||||
std::cout << " In ArrayHandleVirtual<Scalar> functor." << std::endl;
|
||||
g_FunctionCalls++;
|
||||
}
|
||||
void operator()(const vtkm::cont::ArrayHandle<vtkm::FloatDefault>&) const
|
||||
{
|
||||
std::cout << " In ArrayHandle<Scalar> functor." << std::endl;
|
||||
g_FunctionCalls++;
|
||||
}
|
||||
};
|
||||
|
||||
struct ArrayHandleStringFunctor
|
||||
{
|
||||
void operator()(const vtkm::cont::ArrayHandleVirtual<std::string>&) const
|
||||
{
|
||||
std::cout << " In ArrayHandleVirtual<string> functor." << std::endl;
|
||||
g_FunctionCalls++;
|
||||
}
|
||||
};
|
||||
|
||||
struct CellSetStructuredFunctor
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(const T&) const
|
||||
{
|
||||
VTKM_TEST_FAIL("Called wrong form of functor operator.");
|
||||
}
|
||||
void operator()(const vtkm::cont::CellSetStructured<3>&) const
|
||||
{
|
||||
std::cout << " In CellSetStructured<3> functor." << std::endl;
|
||||
g_FunctionCalls++;
|
||||
}
|
||||
};
|
||||
|
||||
struct FunctionInterfaceFunctor
|
||||
{
|
||||
template <typename Signature>
|
||||
void operator()(const vtkm::internal::FunctionInterface<Signature>&) const
|
||||
{
|
||||
VTKM_TEST_FAIL("Called wrong form of functor operator.");
|
||||
}
|
||||
void operator()(
|
||||
const vtkm::internal::FunctionInterface<void(vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
|
||||
vtkm::cont::ArrayHandle<std::string>,
|
||||
vtkm::cont::CellSetStructured<3>)>&) const
|
||||
{
|
||||
std::cout << " In FunctionInterface<...> functor." << std::endl;
|
||||
g_FunctionCalls++;
|
||||
}
|
||||
|
||||
void operator()(
|
||||
const vtkm::internal::FunctionInterface<void(vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
|
||||
vtkm::cont::ArrayHandleVirtual<vtkm::FloatDefault>,
|
||||
vtkm::cont::ArrayHandleVirtual<std::string>,
|
||||
vtkm::cont::CellSetStructured<3>)>&) const
|
||||
{
|
||||
std::cout << " In FunctionInterface<...> functor." << std::endl;
|
||||
g_FunctionCalls++;
|
||||
}
|
||||
};
|
||||
|
||||
void TestBasicTransform()
|
||||
{
|
||||
std::cout << "Testing basic transform." << std::endl;
|
||||
|
||||
vtkm::cont::internal::DynamicTransform transform;
|
||||
vtkm::internal::IndexTag<1> indexTag;
|
||||
|
||||
std::cout << " Trying with simple scalar." << std::endl;
|
||||
TRY_TRANSFORM(transform(vtkm::FloatDefault(5), ScalarFunctor(), indexTag));
|
||||
|
||||
std::cout << " Trying with basic scalar array." << std::endl;
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> concreteArray;
|
||||
TRY_TRANSFORM(transform(concreteArray, ArrayHandleScalarFunctor(), indexTag));
|
||||
|
||||
std::cout << " Trying scalar dynamic array." << std::endl;
|
||||
vtkm::cont::VariantArrayHandle dynamicArray = concreteArray;
|
||||
TRY_TRANSFORM(transform(dynamicArray, ArrayHandleScalarFunctor(), indexTag));
|
||||
|
||||
std::cout << " Trying with unusual (string) dynamic array." << std::endl;
|
||||
dynamicArray = vtkm::cont::ArrayHandle<std::string>();
|
||||
TRY_TRANSFORM(
|
||||
transform(dynamicArray.ResetTypes(TypeListTagString()), ArrayHandleStringFunctor(), indexTag));
|
||||
|
||||
std::cout << " Trying with structured cell set." << std::endl;
|
||||
vtkm::cont::CellSetStructured<3> concreteCellSet;
|
||||
TRY_TRANSFORM(transform(concreteCellSet, CellSetStructuredFunctor(), indexTag));
|
||||
|
||||
std::cout << " Trying with dynamic cell set." << std::endl;
|
||||
vtkm::cont::DynamicCellSet dynamicCellSet = concreteCellSet;
|
||||
TRY_TRANSFORM(transform(dynamicCellSet, CellSetStructuredFunctor(), indexTag));
|
||||
}
|
||||
|
||||
void TestFunctionTransform()
|
||||
{
|
||||
std::cout << "Testing transforms in FunctionInterface." << std::endl;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> scalarArray;
|
||||
vtkm::cont::ArrayHandle<std::string> stringArray;
|
||||
vtkm::cont::CellSetStructured<3> structuredCellSet;
|
||||
|
||||
std::cout << " Trying basic functor call w/o transform (make sure it works)." << std::endl;
|
||||
TRY_TRANSFORM(FunctionInterfaceFunctor()(vtkm::internal::make_FunctionInterface<void>(
|
||||
scalarArray, scalarArray, stringArray, structuredCellSet)));
|
||||
|
||||
std::cout << " Trying dynamic cast" << std::endl;
|
||||
TRY_TRANSFORM(
|
||||
vtkm::internal::make_FunctionInterface<void>(
|
||||
scalarArray,
|
||||
vtkm::cont::VariantArrayHandle(scalarArray),
|
||||
vtkm::cont::VariantArrayHandle(stringArray).ResetTypes(TypeListTagString()),
|
||||
vtkm::cont::DynamicCellSet(structuredCellSet))
|
||||
.DynamicTransformCont(vtkm::cont::internal::DynamicTransform(), FunctionInterfaceFunctor()));
|
||||
}
|
||||
|
||||
void TestDynamicTransform()
|
||||
{
|
||||
TestBasicTransform();
|
||||
TestFunctionTransform();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestDynamicTransform(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(TestDynamicTransform, argc, argv);
|
||||
}
|
@ -25,21 +25,6 @@ namespace internal
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct IdentityFunctor
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT T& operator()(T& x) const
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT const T& operator()(const T& x) const
|
||||
{
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
// These functions exist to help copy components of a FunctionInterface.
|
||||
|
||||
template <vtkm::IdComponent NumToMove, vtkm::IdComponent ParameterIndex = 1>
|
||||
@ -75,11 +60,6 @@ struct FunctionInterfaceMoveParameters<0, ParameterIndex>
|
||||
template <typename OriginalSignature, typename Transform>
|
||||
struct FunctionInterfaceStaticTransformType;
|
||||
|
||||
template <typename OriginalFunction,
|
||||
typename NewFunction,
|
||||
typename TransformFunctor,
|
||||
typename FinishFunctor>
|
||||
class FunctionInterfaceDynamicTransformContContinue;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@ -92,10 +72,10 @@ class FunctionInterfaceDynamicTransformContContinue;
|
||||
/// series of transformations and operations can occur.
|
||||
///
|
||||
/// Supporting arbitrary function and template arguments is difficult and
|
||||
/// really requires separate implementations for ANSI and C++11 versions of
|
||||
/// compilers. Thus, variatic template arguments are, at this point in time,
|
||||
/// really requires separate implementations for pre-C++11 and C++11 versions of
|
||||
/// compilers. Thus, variadic template arguments are, at this point in time,
|
||||
/// something to be avoided when possible. The intention of \c
|
||||
/// FunctionInterface is to collect most of the variatic template code into one
|
||||
/// FunctionInterface is to collect most of the variadic template code into one
|
||||
/// place. The \c FunctionInterface template class takes a function signature,
|
||||
/// which can have a variable number of arguments. The \c FunctionInterface
|
||||
/// will hold in its state a copy of all input parameters (regardless of number
|
||||
@ -162,39 +142,6 @@ class FunctionInterfaceDynamicTransformContContinue;
|
||||
/// functionInterface.template SetParameter<1>(100);
|
||||
/// \endcode
|
||||
///
|
||||
/// \c FunctionInterface can invoke a functor of a matching signature using the
|
||||
/// parameters stored within. If the functor returns a value, that return value
|
||||
/// will be stored in the \c FunctionInterface object for later retrieval.
|
||||
/// There are several versions of the invoke method including those for the
|
||||
/// control and execution environments as well as methods that allow
|
||||
/// transformation of the parameters and return value. See the method document
|
||||
/// for more details.
|
||||
///
|
||||
/// \code{.cpp}
|
||||
/// functionInterface.InvokeCont(Functor());
|
||||
/// \endcode
|
||||
///
|
||||
/// Once a functor has been invoked, the return value can be retrieved with the
|
||||
/// \c GetReturnValue method. \c GetReturnValue should only be used if the
|
||||
/// function signature has a non-void return value. Otherwise calling this
|
||||
/// method will result in a compile error.
|
||||
///
|
||||
/// \code{.cpp}
|
||||
/// functionInterface.GetReturnValue();
|
||||
/// \endcode
|
||||
///
|
||||
/// Providing the appropriate template specification to specialize when there
|
||||
/// is no return value can be done but can be tricky. To make it easier, \c
|
||||
/// FunctionInterface also has a \c GetReturnValueSafe method that provides the
|
||||
/// return value wrapped in a \c FunctionInterfaceReturnContainer structure.
|
||||
/// This will work regardless of whether the return value exists (although this
|
||||
/// container might be empty). Specializing on the type of \c
|
||||
/// FunctionInterfaceReturnContainer is much easier.
|
||||
///
|
||||
/// \code{.cpp}
|
||||
/// functionInterface.GetReturnValueSafe();
|
||||
/// \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.
|
||||
@ -210,12 +157,10 @@ class FunctionInterfaceDynamicTransformContContinue;
|
||||
/// functionInterface.Replace<1>(std::string("new first argument"));
|
||||
/// \endcode
|
||||
///
|
||||
/// Finally, there are a couple of ways to replace all of the parameters at
|
||||
/// Finally, there is a way to replace all of the parameters at
|
||||
/// once. The \c StaticTransform methods take a transform functor that modifies
|
||||
/// each of the parameters. The \c DynamicTransform methods similarly take a
|
||||
/// transform functor, but is called in a different way to defer the type
|
||||
/// resolution to run time. See the documentation for each of these methods for
|
||||
/// details on how they are used.
|
||||
/// each of the parameters. See the documentation for this method for
|
||||
/// details on how it is used.
|
||||
///
|
||||
template <typename FunctionSignature>
|
||||
class FunctionInterface
|
||||
@ -228,15 +173,13 @@ public:
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
FunctionInterface()
|
||||
: Result()
|
||||
, Parameters()
|
||||
: Parameters()
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
explicit FunctionInterface(const detail::ParameterContainer<FunctionSignature>& p)
|
||||
: Result()
|
||||
, Parameters(p)
|
||||
: Parameters(p)
|
||||
{
|
||||
}
|
||||
|
||||
@ -253,8 +196,6 @@ public:
|
||||
using type = typename detail::AtType<ParameterIndex, FunctionSignature>::type;
|
||||
};
|
||||
|
||||
static constexpr bool RETURN_VALID = FunctionInterfaceReturnContainer<ResultType>::VALID;
|
||||
|
||||
/// The number of parameters in this \c Function Interface.
|
||||
///
|
||||
static constexpr vtkm::IdComponent ARITY = SigInfo::Arity;
|
||||
@ -265,27 +206,6 @@ public:
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::IdComponent GetArity() const { return ARITY; }
|
||||
|
||||
/// Retrieves the return value from the last invocation called. This method
|
||||
/// will result in a compiler error if used with a function having a void
|
||||
/// return type.
|
||||
///
|
||||
VTKM_EXEC_CONT
|
||||
ResultType GetReturnValue() const { return this->Result.Value; }
|
||||
|
||||
/// Retrieves the return value from the last invocation wrapped in a \c
|
||||
/// FunctionInterfaceReturnContainer object. This call can succeed even if
|
||||
/// the return type is void. You still have to somehow check to make sure the
|
||||
/// return is non-void before trying to use it, but using this method can
|
||||
/// simplify templated programming.
|
||||
///
|
||||
VTKM_EXEC_CONT
|
||||
const FunctionInterfaceReturnContainer<ResultType>& GetReturnValueSafe() const
|
||||
{
|
||||
return this->Result;
|
||||
}
|
||||
VTKM_EXEC_CONT
|
||||
FunctionInterfaceReturnContainer<ResultType>& GetReturnValueSafe() { return this->Result; }
|
||||
|
||||
/// 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
|
||||
@ -377,8 +297,6 @@ public:
|
||||
template <typename SrcFunctionSignature>
|
||||
void Copy(const FunctionInterface<SrcFunctionSignature>& src)
|
||||
{
|
||||
this->Result = src.GetReturnValueSafe();
|
||||
|
||||
constexpr vtkm::UInt16 minArity = (ARITY < FunctionInterface<SrcFunctionSignature>::ARITY)
|
||||
? ARITY
|
||||
: FunctionInterface<SrcFunctionSignature>::ARITY;
|
||||
@ -388,68 +306,9 @@ public:
|
||||
|
||||
void Copy(const FunctionInterface<FunctionSignature>& src)
|
||||
{ //optimized version for assignment/copy
|
||||
this->Result = src.GetReturnValueSafe();
|
||||
this->Parameters = src.Parameters;
|
||||
}
|
||||
|
||||
/// Invoke a function \c f using the arguments stored in this
|
||||
/// FunctionInterface.
|
||||
///
|
||||
/// If this FunctionInterface specifies a non-void return value, then the
|
||||
/// result of the function call is stored within this FunctionInterface and
|
||||
/// can be retrieved with GetReturnValue().
|
||||
///
|
||||
template <typename Function>
|
||||
VTKM_CONT void InvokeCont(const Function& f)
|
||||
{
|
||||
detail::DoInvokeCont(f, this->Parameters, this->Result, detail::IdentityFunctor());
|
||||
}
|
||||
template <typename Function>
|
||||
VTKM_CONT void InvokeCont(Function& f)
|
||||
{
|
||||
detail::DoInvokeCont(f, this->Parameters, this->Result, detail::IdentityFunctor());
|
||||
}
|
||||
template <typename Function>
|
||||
VTKM_EXEC void InvokeExec(const Function& f)
|
||||
{
|
||||
detail::DoInvokeExec(f, this->Parameters, this->Result, detail::IdentityFunctor());
|
||||
}
|
||||
template <typename Function>
|
||||
VTKM_EXEC void InvokeExec(Function& f)
|
||||
{
|
||||
detail::DoInvokeExec(f, this->Parameters, this->Result, detail::IdentityFunctor());
|
||||
}
|
||||
|
||||
/// Invoke a function \c f using the arguments stored in this
|
||||
/// FunctionInterface and a transform.
|
||||
///
|
||||
/// These versions of invoke also apply a transform to the input arguments.
|
||||
/// The transform is a second functor passed a second argument. If this
|
||||
/// FunctionInterface specifies a non-void return value, then the result of
|
||||
/// the function call is also transformed and stored within this
|
||||
/// FunctionInterface and can be retrieved with GetReturnValue().
|
||||
///
|
||||
template <typename Function, typename TransformFunctor>
|
||||
VTKM_CONT void InvokeCont(const Function& f, const TransformFunctor& transform)
|
||||
{
|
||||
detail::DoInvokeCont(f, this->Parameters, this->Result, transform);
|
||||
}
|
||||
template <typename Function, typename TransformFunctor>
|
||||
VTKM_CONT void InvokeCont(Function& f, const TransformFunctor& transform)
|
||||
{
|
||||
detail::DoInvokeCont(f, this->Parameters, this->Result, transform);
|
||||
}
|
||||
template <typename Function, typename TransformFunctor>
|
||||
VTKM_EXEC void InvokeExec(const Function& f, const TransformFunctor& transform)
|
||||
{
|
||||
detail::DoInvokeExec(f, this->Parameters, this->Result, transform);
|
||||
}
|
||||
template <typename Function, typename TransformFunctor>
|
||||
VTKM_EXEC void InvokeExec(Function& f, const TransformFunctor& transform)
|
||||
{
|
||||
detail::DoInvokeExec(f, this->Parameters, this->Result, transform);
|
||||
}
|
||||
|
||||
template <typename NewType>
|
||||
struct AppendType
|
||||
{
|
||||
@ -596,236 +455,31 @@ public:
|
||||
detail::DoStaticTransformCont(transform, this->Parameters, newFuncInterface.Parameters);
|
||||
return newFuncInterface;
|
||||
}
|
||||
template <typename Transform>
|
||||
VTKM_EXEC 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
|
||||
/// FunctionInterface to different types and values based on run-time
|
||||
/// information. It operates by accepting two functors. The first functor
|
||||
/// accepts three arguments. The first argument is a parameter to transform,
|
||||
/// the second is a functor to call with the transformed result, and the third
|
||||
/// is an instance of \c IndexTag denoting the index parameter..
|
||||
///
|
||||
/// The second argument to \c DynamicTransform is another functor that
|
||||
/// accepts the transformed \c FunctionInterface and does something. If that
|
||||
/// transformed \c FunctionInterface has a return value, that return value
|
||||
/// will be passed back to this \c FunctionInterface.
|
||||
///
|
||||
/// Here is a contrived but illustrative example. This transformation will
|
||||
/// pass all arguments except any string that looks like a number will be
|
||||
/// converted to a vtkm::FloatDefault. Note that because the types are not
|
||||
/// determined until runtime, this transform cannot be determined at compile
|
||||
/// time with meta-template programming.
|
||||
///
|
||||
/// \code
|
||||
/// struct MyTransformFunctor {
|
||||
/// template<typename InputType,
|
||||
/// typename ContinueFunctor,
|
||||
/// vtkm::IdComponent Index>
|
||||
/// VTKM_CONT
|
||||
/// void operator()(const InputType &input,
|
||||
/// const ContinueFunctor &continueFunc,
|
||||
/// vtkm::internal::IndexTag<Index>) const
|
||||
/// {
|
||||
/// continueFunc(input);
|
||||
/// }
|
||||
///
|
||||
/// template<typename ContinueFunctor, vtkm::IdComponent Index>
|
||||
/// VTKM_CONT
|
||||
/// void operator()(const std::string &input,
|
||||
/// const ContinueFunctor &continueFunc,
|
||||
/// vtkm::internal::IndexTag<Index>) const
|
||||
/// {
|
||||
/// if ((input[0] >= '0' && (input[0] <= '9'))
|
||||
/// {
|
||||
/// std::stringstream stream(input);
|
||||
/// vtkm::FloatDefault value;
|
||||
/// stream >> value;
|
||||
/// continueFunc(value);
|
||||
/// }
|
||||
/// else
|
||||
/// {
|
||||
/// continueFunc(input);
|
||||
/// }
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// struct MyFinishFunctor {
|
||||
/// template<typename FunctionSignature>
|
||||
/// VTKM_CONT
|
||||
/// void operator()(vtkm::internal::FunctionInterface<FunctionSignature> &funcInterface) const
|
||||
/// {
|
||||
/// // Do something
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// template<typename FunctionSignature>
|
||||
/// void ImportantStuff(vtkm::internal::FunctionInterface<FunctionSignature> &funcInterface)
|
||||
/// {
|
||||
/// funcInterface.DynamicTransformCont(MyContinueFunctor(), MyFinishFunctor());
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// An interesting feature of \c DynamicTransform is that there does not have
|
||||
/// to be a one-to-one transform. It is possible to make many valid
|
||||
/// transforms by calling the continue functor multiple times within the
|
||||
/// transform functor. It is also possible to abort the transform by not
|
||||
/// calling the continue functor.
|
||||
///
|
||||
template <typename TransformFunctor, typename FinishFunctor>
|
||||
VTKM_CONT void DynamicTransformCont(const TransformFunctor& transform,
|
||||
const FinishFunctor& finish) const
|
||||
{
|
||||
using ContinueFunctorType =
|
||||
detail::FunctionInterfaceDynamicTransformContContinue<FunctionSignature,
|
||||
ResultType(),
|
||||
TransformFunctor,
|
||||
FinishFunctor>;
|
||||
|
||||
FunctionInterface<ResultType()> emptyInterface;
|
||||
ContinueFunctorType continueFunctor =
|
||||
ContinueFunctorType(*this, emptyInterface, transform, finish);
|
||||
|
||||
continueFunctor.DoNextTransform(emptyInterface);
|
||||
// this->Result = emptyInterface.GetReturnValueSafe();
|
||||
}
|
||||
|
||||
/// \brief Applies a function to all the parameters.
|
||||
///
|
||||
/// The \c ForEach methods take a functor and apply that functor to each of
|
||||
/// the parameters in the \c FunctionInterface. (Return values are not
|
||||
/// effected.) The first argument of the functor is the parameter value and
|
||||
/// the second argument is an \c IndexTag, which can be used to identify the
|
||||
/// index of the parameter.
|
||||
///
|
||||
template <typename Functor>
|
||||
VTKM_CONT void ForEachCont(const Functor& f) const
|
||||
{
|
||||
detail::DoForEachCont(f, this->Parameters);
|
||||
}
|
||||
template <typename Functor>
|
||||
VTKM_CONT void ForEachCont(const Functor& f)
|
||||
{
|
||||
detail::DoForEachCont(f, this->Parameters);
|
||||
}
|
||||
template <typename Functor>
|
||||
VTKM_EXEC void ForEachExec(const Functor& f) const
|
||||
{
|
||||
detail::DoForEachExec(f, this->Parameters);
|
||||
}
|
||||
template <typename Functor>
|
||||
VTKM_EXEC void ForEachExec(const Functor& f)
|
||||
{
|
||||
detail::DoForEachExec(f, this->Parameters);
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::internal::FunctionInterfaceReturnContainer<ResultType> Result;
|
||||
detail::ParameterContainer<FunctionSignature> Parameters;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
//============================================================================
|
||||
/// \brief Create a \c FunctionInterface
|
||||
///
|
||||
/// \c make_FunctionInterface is a function that takes a variable number of
|
||||
/// arguments and returns a \c FunctionInterface object containing these
|
||||
/// objects. Since the return type for the function signature is not specified,
|
||||
/// you must always specify it as a template parameter
|
||||
///
|
||||
/// \code{.cpp}
|
||||
/// vtkm::internal::FunctionInterface<void(int,double,char)> functionInterface =
|
||||
/// vtkm::internal::make_FunctionInterface<void>(1, 2.5, 'a');
|
||||
/// \endcode
|
||||
///
|
||||
|
||||
template <typename R, typename... Args>
|
||||
FunctionInterface<R(Args...)> make_FunctionInterface(const Args&... args)
|
||||
{
|
||||
|
||||
template <typename OriginalFunction,
|
||||
typename NewFunction,
|
||||
typename TransformFunctor,
|
||||
typename FinishFunctor>
|
||||
class FunctionInterfaceDynamicTransformContContinue
|
||||
{
|
||||
public:
|
||||
FunctionInterfaceDynamicTransformContContinue(
|
||||
const vtkm::internal::FunctionInterface<OriginalFunction>& originalInterface,
|
||||
vtkm::internal::FunctionInterface<NewFunction>& newInterface,
|
||||
const TransformFunctor& transform,
|
||||
const FinishFunctor& finish)
|
||||
: OriginalInterface(originalInterface)
|
||||
, NewInterface(newInterface)
|
||||
, Transform(transform)
|
||||
, Finish(finish)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
VTKM_CONT void operator()(const T& newParameter) const
|
||||
{
|
||||
using NewFSigComp = typename FunctionInterface<NewFunction>::ComponentSig;
|
||||
|
||||
//Determine if we should do the next transform
|
||||
using appended = brigand::push_back<NewFSigComp, T>;
|
||||
using interfaceSig = typename detail::AsSigType<appended>::type;
|
||||
using NextInterfaceType = FunctionInterface<interfaceSig>;
|
||||
|
||||
static constexpr std::size_t newArity = NextInterfaceType::ARITY;
|
||||
static constexpr std::size_t oldArity = detail::FunctionSigInfo<OriginalFunction>::Arity;
|
||||
using ShouldDoNextTransformType = std::integral_constant<bool, (newArity < oldArity)>;
|
||||
|
||||
NextInterfaceType nextInterface = this->NewInterface.Append(newParameter);
|
||||
|
||||
this->DoNextTransform(nextInterface, ShouldDoNextTransformType());
|
||||
this->NewInterface.GetReturnValueSafe() = nextInterface.GetReturnValueSafe();
|
||||
}
|
||||
|
||||
template <typename NextFunction>
|
||||
void DoNextTransform(vtkm::internal::FunctionInterface<NextFunction>& nextInterface) const
|
||||
{
|
||||
using NextContinueType = FunctionInterfaceDynamicTransformContContinue<OriginalFunction,
|
||||
NextFunction,
|
||||
TransformFunctor,
|
||||
FinishFunctor>;
|
||||
NextContinueType nextContinue =
|
||||
NextContinueType(this->OriginalInterface, nextInterface, this->Transform, this->Finish);
|
||||
static constexpr vtkm::IdComponent Index =
|
||||
vtkm::internal::FunctionInterface<NextFunction>::ARITY + 1;
|
||||
vtkm::internal::IndexTag<Index> indexTag;
|
||||
this->Transform(this->OriginalInterface.GetParameter(indexTag), nextContinue, indexTag);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename NextFunction>
|
||||
void DoNextTransform(vtkm::internal::FunctionInterface<NextFunction>& nextInterface,
|
||||
std::true_type) const
|
||||
{
|
||||
using NextContinueType = FunctionInterfaceDynamicTransformContContinue<OriginalFunction,
|
||||
NextFunction,
|
||||
TransformFunctor,
|
||||
FinishFunctor>;
|
||||
NextContinueType nextContinue =
|
||||
NextContinueType(this->OriginalInterface, nextInterface, this->Transform, this->Finish);
|
||||
static constexpr vtkm::IdComponent Index =
|
||||
vtkm::internal::FunctionInterface<NextFunction>::ARITY + 1;
|
||||
vtkm::internal::IndexTag<Index> indexTag;
|
||||
this->Transform(this->OriginalInterface.GetParameter(indexTag), nextContinue, indexTag);
|
||||
}
|
||||
|
||||
template <typename NextFunction>
|
||||
void DoNextTransform(vtkm::internal::FunctionInterface<NextFunction>& nextInterface,
|
||||
std::false_type) const
|
||||
{
|
||||
this->Finish(nextInterface);
|
||||
}
|
||||
|
||||
private:
|
||||
const vtkm::internal::FunctionInterface<OriginalFunction>& OriginalInterface;
|
||||
vtkm::internal::FunctionInterface<NewFunction>& NewInterface;
|
||||
const TransformFunctor& Transform;
|
||||
const FinishFunctor& Finish;
|
||||
|
||||
void operator=(const FunctionInterfaceDynamicTransformContContinue<OriginalFunction,
|
||||
NewFunction,
|
||||
TransformFunctor,
|
||||
FinishFunctor>&) = delete;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
detail::ParameterContainer<R(Args...)> container = { args... };
|
||||
return FunctionInterface<R(Args...)>{ container };
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::internal
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -101,45 +101,6 @@ $endfor\
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//============================================================================
|
||||
|
||||
// clang-format off
|
||||
|
||||
$for(num_params in range(0, max_parameters+1))\
|
||||
/// \brief Create a \c FunctionInterface
|
||||
///
|
||||
/// \c make_FunctionInterface is a function that takes a variable number of
|
||||
/// arguments and returns a \c FunctionInterface object containing these
|
||||
/// objects. Since the return type for the function signature is not specified,
|
||||
/// you must always specify it as a template parameter
|
||||
///
|
||||
/// \code{.cpp}
|
||||
/// vtkm::internal::FunctionInterface<void(int,double,char)> functionInterface =
|
||||
/// vtkm::internal::make_FunctionInterface<void>(1, 2.5, 'a');
|
||||
/// \endcode
|
||||
///
|
||||
template<$template_params(num_params)>
|
||||
FunctionInterface<$signature(num_params)>
|
||||
make_FunctionInterface(
|
||||
$for(param_index in range(1,num_params+1))\
|
||||
const $ptype(param_index)& p$(param_index)$comma_if(param_index<num_params)
|
||||
$endfor\
|
||||
)
|
||||
{
|
||||
detail::ParameterContainer<$signature(num_params)> container =
|
||||
{
|
||||
$for(param_index in range(1,num_params+1))\
|
||||
p$(param_index)$comma_if(param_index<num_params)
|
||||
$endfor\
|
||||
};
|
||||
|
||||
return FunctionInterface<$signature(num_params)>{container};
|
||||
}
|
||||
|
||||
$endfor\
|
||||
|
||||
// clang-format off
|
||||
|
||||
}
|
||||
} // namespace vtkm::internal
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -243,64 +243,6 @@ struct CopyAllParameters<0>
|
||||
};
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
// clang-format off
|
||||
|
||||
$for(num_params in range(0, max_parameters+1))\
|
||||
$# Invoke functions need both control and execution versions
|
||||
$for(environment in ['Cont', 'Exec'])\
|
||||
$# Invoke functions also need to accept const and non-const versions of the functor
|
||||
$for(functor_const in ['const ', ''])\
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename Functor,
|
||||
typename TransformFunctor,
|
||||
$template_params(num_params)>
|
||||
VTKM_$(environment.upper()) void DoInvoke$(environment)($(functor_const)Functor& f,
|
||||
ParameterContainer<$signature(num_params)>& parameters,
|
||||
FunctionInterfaceReturnContainer<$ptype(0)>& result,
|
||||
const TransformFunctor& transform)
|
||||
{
|
||||
$if(num_params < 1)\
|
||||
(void)parameters;
|
||||
result.Value = transform(f());
|
||||
$else\
|
||||
result.Value = transform(f(
|
||||
$for(param_index in range(1, num_params))\
|
||||
transform(parameters.Parameter$(param_index)),
|
||||
$endfor\
|
||||
transform(parameters.Parameter$(num_params))));
|
||||
$endif\
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename Functor,
|
||||
typename TransformFunctor$comma_if(num_params>0)
|
||||
$template_params(num_params,1)>
|
||||
VTKM_$(environment.upper()) void DoInvoke$(environment)($(functor_const)Functor& f,
|
||||
ParameterContainer<$signature(num_params,'void')>& parameters,
|
||||
FunctionInterfaceReturnContainer<void>&,
|
||||
const TransformFunctor& transform)
|
||||
{
|
||||
$if(num_params < 1)\
|
||||
(void)parameters;
|
||||
(void)transform;
|
||||
f();
|
||||
$else\
|
||||
f(
|
||||
$for(param_index in range(1, num_params))\
|
||||
transform(parameters.Parameter$(param_index)),
|
||||
$endfor\
|
||||
transform(parameters.Parameter$(num_params)));
|
||||
$endif\
|
||||
}
|
||||
|
||||
$endfor\
|
||||
$endfor\
|
||||
$endfor\
|
||||
|
||||
// clang-format on
|
||||
|
||||
//============================================================================
|
||||
|
||||
template <typename OriginalSignature, typename Transform>
|
||||
@ -309,8 +251,7 @@ struct FunctionInterfaceStaticTransformType;
|
||||
// clang-format off
|
||||
|
||||
$for(num_params in range(0, max_parameters))\
|
||||
$# Transform functions need both control and execution versions
|
||||
$for(environment in ['Cont', 'Exec'])\
|
||||
$for(environment in ['Cont'])\
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename Transform,
|
||||
$template_params(num_params,0,'Original'),
|
||||
@ -325,10 +266,11 @@ $if(num_params < 1)\
|
||||
(void)originalParameters;
|
||||
(void)transformedParameters;
|
||||
$else\
|
||||
transformedParameters = {
|
||||
$for(param_index in range(1, num_params+1))\
|
||||
transformedParameters.Parameter$(param_index) =
|
||||
transform(originalParameters.Parameter$(param_index), vtkm::internal::IndexTag<$(param_index)>());
|
||||
transform(originalParameters.Parameter$(param_index), vtkm::internal::IndexTag<$(param_index)>())$comma_if(param_index<num_params)
|
||||
$endfor\
|
||||
};
|
||||
$endif\
|
||||
}
|
||||
|
||||
@ -336,38 +278,6 @@ $endfor\
|
||||
$endfor\
|
||||
// clang-format on
|
||||
|
||||
//============================================================================
|
||||
|
||||
// clang-format off
|
||||
|
||||
$for(num_params in range(0, max_parameters))\
|
||||
$# ForEach functions need both control and execution versions
|
||||
$for(environment in ['Cont', 'Exec'])\
|
||||
$# ForEach functions also need to accept const and non-const versions of the FunctionInterface
|
||||
$for(function_interface_const in ['const ', ''])\
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename Functor,
|
||||
$template_params(num_params)>
|
||||
VTKM_$(environment.upper()) void DoForEach$(environment)(
|
||||
const Functor& f,
|
||||
$(function_interface_const)ParameterContainer<$signature(num_params)>& parameters)
|
||||
{
|
||||
$if(num_params < 1)\
|
||||
(void)f;
|
||||
(void)parameters;
|
||||
$else\
|
||||
$for(param_index in range(1, num_params+1))\
|
||||
f(parameters.Parameter$(param_index), vtkm::internal::IndexTag<$(param_index)>());
|
||||
$endfor\
|
||||
$endif\
|
||||
}
|
||||
|
||||
$endfor\
|
||||
$endfor\
|
||||
$endfor\
|
||||
|
||||
// clang-format on
|
||||
|
||||
} // namespace detail
|
||||
}
|
||||
} // namespace vtkm::internal
|
||||
|
@ -13,14 +13,6 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
// Disable the test on the overhead to invoke a function. It is unreliable and
|
||||
// the most critical invoke (for the instance of a worklet) does not directly
|
||||
// use the Invoke method.
|
||||
//#define TEST_INVOKE_TIME
|
||||
#ifdef TEST_INVOKE_TIME
|
||||
#include <vtkm/cont/Timer.h>
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@ -39,45 +31,6 @@ const Type4 Arg4(1.2f, 3.4f, 5.6f);
|
||||
using Type5 = vtkm::Id3;
|
||||
const Type5 Arg5(4, 5, 6);
|
||||
|
||||
struct ThreeArgFunctor
|
||||
{
|
||||
void operator()(const Type1& a1, const Type2& a2, const Type3& a3) const
|
||||
{
|
||||
std::cout << "In 3 arg functor." << std::endl;
|
||||
|
||||
VTKM_TEST_ASSERT(a1 == Arg1, "Arg 1 incorrect.");
|
||||
VTKM_TEST_ASSERT(a2 == Arg2, "Arg 2 incorrect.");
|
||||
VTKM_TEST_ASSERT(a3 == Arg3, "Arg 3 incorrect.");
|
||||
}
|
||||
};
|
||||
|
||||
struct ThreeArgModifyFunctor
|
||||
{
|
||||
void operator()(Type1& a1, Type2& a2, Type3& a3) const
|
||||
{
|
||||
std::cout << "In 3 arg modify functor." << std::endl;
|
||||
|
||||
a1 = Arg1;
|
||||
a2 = Arg2;
|
||||
a3 = Arg3;
|
||||
}
|
||||
};
|
||||
|
||||
struct GetReferenceFunctor
|
||||
{
|
||||
template <typename T>
|
||||
struct ReturnType
|
||||
{
|
||||
using type = const typename std::remove_reference<T>::type*;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const T* operator()(const T& x) const
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
};
|
||||
|
||||
struct PointerTransform
|
||||
{
|
||||
template <typename T, vtkm::IdComponent Index>
|
||||
@ -93,187 +46,6 @@ struct PointerTransform
|
||||
}
|
||||
};
|
||||
|
||||
struct ThreePointerArgFunctor
|
||||
{
|
||||
void operator()(const Type1* a1, const Type2* a2, const Type3* a3) const
|
||||
{
|
||||
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.");
|
||||
VTKM_TEST_ASSERT(*a3 == Arg3, "Arg 3 incorrect.");
|
||||
}
|
||||
};
|
||||
|
||||
struct ThreeArgFunctorWithReturn
|
||||
{
|
||||
std::string operator()(const Type1& a1, const Type2& a2, const Type3& a3) const
|
||||
{
|
||||
std::cout << "In 3 arg functor with return." << std::endl;
|
||||
|
||||
std::stringstream buffer;
|
||||
buffer.precision(10);
|
||||
buffer << a1 << " " << a2 << " " << a3;
|
||||
return buffer.str();
|
||||
}
|
||||
};
|
||||
|
||||
struct FiveArgFunctor
|
||||
{
|
||||
void operator()(const Type1& a1,
|
||||
const Type2& a2,
|
||||
const Type3& a3,
|
||||
const Type4& a4,
|
||||
const Type5& a5) const
|
||||
{
|
||||
std::cout << "In 5 arg functor." << std::endl;
|
||||
|
||||
VTKM_TEST_ASSERT(a1 == Arg1, "Arg 1 incorrect.");
|
||||
VTKM_TEST_ASSERT(a2 == Arg2, "Arg 2 incorrect.");
|
||||
VTKM_TEST_ASSERT(a3 == Arg3, "Arg 3 incorrect.");
|
||||
VTKM_TEST_ASSERT(a4 == Arg4, "Arg 4 incorrect.");
|
||||
VTKM_TEST_ASSERT(a5 == Arg5, "Arg 5 incorrect.");
|
||||
}
|
||||
};
|
||||
|
||||
struct FiveArgSwizzledFunctor
|
||||
{
|
||||
void operator()(const Type5& a5,
|
||||
const Type1& a1,
|
||||
const Type3& a3,
|
||||
const Type4& a4,
|
||||
const Type2& a2) const
|
||||
{
|
||||
std::cout << "In 5 arg functor." << std::endl;
|
||||
|
||||
VTKM_TEST_ASSERT(a1 == Arg1, "Arg 1 incorrect.");
|
||||
VTKM_TEST_ASSERT(a2 == Arg2, "Arg 2 incorrect.");
|
||||
VTKM_TEST_ASSERT(a3 == Arg3, "Arg 3 incorrect.");
|
||||
VTKM_TEST_ASSERT(a4 == Arg4, "Arg 4 incorrect.");
|
||||
VTKM_TEST_ASSERT(a5 == Arg5, "Arg 5 incorrect.");
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef TEST_INVOKE_TIME
|
||||
struct LotsOfArgsFunctor
|
||||
{
|
||||
LotsOfArgsFunctor()
|
||||
: Field(0)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(vtkm::FloatDefault arg1,
|
||||
vtkm::FloatDefault arg2,
|
||||
vtkm::FloatDefault arg3,
|
||||
vtkm::FloatDefault arg4,
|
||||
vtkm::FloatDefault arg5,
|
||||
vtkm::FloatDefault arg6,
|
||||
vtkm::FloatDefault arg7,
|
||||
vtkm::FloatDefault arg8,
|
||||
vtkm::FloatDefault arg9,
|
||||
vtkm::FloatDefault arg10)
|
||||
{
|
||||
VTKM_TEST_ASSERT(arg1 == 1.0, "Got bad argument");
|
||||
VTKM_TEST_ASSERT(arg2 == 2.0, "Got bad argument");
|
||||
VTKM_TEST_ASSERT(arg3 == 3.0, "Got bad argument");
|
||||
VTKM_TEST_ASSERT(arg4 == 4.0, "Got bad argument");
|
||||
VTKM_TEST_ASSERT(arg5 == 5.0, "Got bad argument");
|
||||
VTKM_TEST_ASSERT(arg6 == 6.0, "Got bad argument");
|
||||
VTKM_TEST_ASSERT(arg7 == 7.0, "Got bad argument");
|
||||
VTKM_TEST_ASSERT(arg8 == 8.0, "Got bad argument");
|
||||
VTKM_TEST_ASSERT(arg9 == 9.0, "Got bad argument");
|
||||
VTKM_TEST_ASSERT(arg10 == 10.0, "Got bad argument");
|
||||
|
||||
this->Field += arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10;
|
||||
}
|
||||
vtkm::FloatDefault Field;
|
||||
};
|
||||
#endif //TEST_INVOKE_TIME
|
||||
|
||||
template <typename T>
|
||||
std::string ToString(const T& value)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream.precision(10);
|
||||
stream << value;
|
||||
return stream.str();
|
||||
}
|
||||
std::string ToString(const std::string& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
struct StringTransform
|
||||
{
|
||||
template <typename T>
|
||||
std::string operator()(const T& input) const
|
||||
{
|
||||
return ToString(input);
|
||||
}
|
||||
};
|
||||
|
||||
struct ThreeArgStringFunctorWithReturn
|
||||
{
|
||||
std::string operator()(std::string arg1, std::string arg2, std::string arg3) const
|
||||
{
|
||||
return arg1 + " " + arg2 + " " + arg3;
|
||||
}
|
||||
};
|
||||
|
||||
struct DynamicTransformFunctor
|
||||
{
|
||||
template <typename T, typename ContinueFunctor, vtkm::IdComponent Index>
|
||||
void operator()(const T& input,
|
||||
const ContinueFunctor continueFunc,
|
||||
vtkm::internal::IndexTag<Index>) const
|
||||
{
|
||||
continueFunc(input + T(Index));
|
||||
continueFunc(ToString(input + T(Index)));
|
||||
}
|
||||
|
||||
template <typename ContinueFunctor, vtkm::IdComponent Index>
|
||||
void operator()(const std::string& input,
|
||||
const ContinueFunctor continueFunc,
|
||||
vtkm::internal::IndexTag<Index>) const
|
||||
{
|
||||
continueFunc(input);
|
||||
}
|
||||
};
|
||||
|
||||
vtkm::Id g_DynamicTransformFinishCalls;
|
||||
|
||||
struct DynamicTransformFinish
|
||||
{
|
||||
template <typename Signature>
|
||||
void operator()(vtkm::internal::FunctionInterface<Signature>& funcInterface) const
|
||||
{
|
||||
g_DynamicTransformFinishCalls++;
|
||||
VTKM_TEST_ASSERT(ToString(funcInterface.template GetParameter<1>()) == ToString(Arg1 + 1),
|
||||
"Arg 1 incorrect");
|
||||
VTKM_TEST_ASSERT(ToString(funcInterface.template GetParameter<2>()) == ToString(Arg2 + 2),
|
||||
"Arg 2 incorrect");
|
||||
VTKM_TEST_ASSERT(ToString(funcInterface.template GetParameter<3>()) == ToString(Arg3),
|
||||
"Arg 3 incorrect");
|
||||
}
|
||||
};
|
||||
|
||||
struct ForEachFunctor
|
||||
{
|
||||
template <typename T, vtkm::IdComponent Index>
|
||||
void operator()(T& x, vtkm::internal::IndexTag<Index>) const
|
||||
{
|
||||
x = T(Index) + x;
|
||||
}
|
||||
|
||||
template <vtkm::IdComponent Index>
|
||||
void operator()(std::string& x, vtkm::internal::IndexTag<Index>) const
|
||||
{
|
||||
std::stringstream message;
|
||||
message << x << "+" << Index;
|
||||
x = message.str();
|
||||
}
|
||||
};
|
||||
|
||||
void TryFunctionInterface5(
|
||||
vtkm::internal::FunctionInterface<void(Type1, Type2, Type3, Type4, Type5)> funcInterface)
|
||||
{
|
||||
@ -285,15 +57,9 @@ void TryFunctionInterface5(
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<4>() == Arg4, "Arg 4 incorrect.");
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<5>() == Arg5, "Arg 5 incorrect.");
|
||||
|
||||
std::cout << "Checking invocation." << std::endl;
|
||||
funcInterface.InvokeCont(FiveArgFunctor());
|
||||
funcInterface.InvokeExec(FiveArgFunctor());
|
||||
|
||||
std::cout << "Swizzling parameters with replace." << std::endl;
|
||||
funcInterface.Replace<1>(Arg5)
|
||||
.Replace(Arg1, vtkm::internal::IndexTag<2>())
|
||||
.Replace<5>(Arg2)
|
||||
.InvokeCont(FiveArgSwizzledFunctor());
|
||||
funcInterface.Replace<1>(Arg5).Replace(Arg1, vtkm::internal::IndexTag<2>()).Replace<5>(Arg2);
|
||||
}
|
||||
|
||||
void TestBasicFunctionInterface()
|
||||
@ -309,10 +75,6 @@ void TestBasicFunctionInterface()
|
||||
"Arg 2 incorrect.");
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() == Arg3, "Arg 3 incorrect.");
|
||||
|
||||
std::cout << "Checking invocation." << std::endl;
|
||||
funcInterface.InvokeCont(ThreeArgFunctor());
|
||||
funcInterface.InvokeExec(ThreeArgFunctor());
|
||||
|
||||
std::cout << "Checking invocation with argument modification." << std::endl;
|
||||
funcInterface.SetParameter<1>(Type1());
|
||||
funcInterface.SetParameter(Type2(), vtkm::internal::IndexTag<2>());
|
||||
@ -321,27 +83,15 @@ void TestBasicFunctionInterface()
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<2>() != Arg2, "Arg 2 not cleared.");
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() != Arg3, "Arg 3 not cleared.");
|
||||
|
||||
funcInterface.InvokeCont(ThreeArgModifyFunctor());
|
||||
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 incorrect.");
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() != Arg3, "Arg 3 not cleared.");
|
||||
|
||||
TryFunctionInterface5(vtkm::internal::make_FunctionInterface<void>(Arg1, Arg2, Arg3, Arg4, Arg5));
|
||||
}
|
||||
|
||||
void TestInvokeResult()
|
||||
{
|
||||
std::cout << "Checking invocation with return." << std::endl;
|
||||
vtkm::internal::FunctionInterface<std::string(Type1, Type2, Type3)> funcInterface =
|
||||
vtkm::internal::make_FunctionInterface<std::string>(Arg1, Arg2, Arg3);
|
||||
|
||||
funcInterface.InvokeCont(ThreeArgFunctorWithReturn());
|
||||
std::string result = funcInterface.GetReturnValue();
|
||||
|
||||
std::cout << "Got result: " << result << std::endl;
|
||||
VTKM_TEST_ASSERT(result == "1234 5678.125 Third argument", "Got bad result from invoke.");
|
||||
}
|
||||
|
||||
void TestAppend()
|
||||
{
|
||||
std::cout << "Appending interface with return value." << std::endl;
|
||||
@ -354,19 +104,10 @@ void TestAppend()
|
||||
VTKM_TEST_ASSERT(funcInterface3ArgWRet.GetParameter<2>() == Arg2, "Arg 2 incorrect.");
|
||||
VTKM_TEST_ASSERT(funcInterface3ArgWRet.GetParameter<3>() == Arg3, "Arg 3 incorrect.");
|
||||
|
||||
std::cout << "Invoking appended function interface." << std::endl;
|
||||
funcInterface3ArgWRet.InvokeExec(ThreeArgFunctorWithReturn());
|
||||
std::string result = funcInterface3ArgWRet.GetReturnValue();
|
||||
|
||||
std::cout << "Got result: " << result << std::endl;
|
||||
VTKM_TEST_ASSERT(result == "1234 5678.125 Third argument", "Got bad result from invoke.");
|
||||
|
||||
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.");
|
||||
VTKM_TEST_ASSERT(funcInterface4ArgWRet.GetReturnValue() == "1234 5678.125 Third argument",
|
||||
"Got bad result from copy.");
|
||||
|
||||
std::cout << "Checking double append." << std::endl;
|
||||
vtkm::internal::FunctionInterface<void(Type1, Type2, Type3)> funcInterface3 =
|
||||
@ -374,157 +115,29 @@ void TestAppend()
|
||||
TryFunctionInterface5(funcInterface3.Append(Arg4).Append(Arg5));
|
||||
}
|
||||
|
||||
void TestTransformInvoke()
|
||||
{
|
||||
std::cout << "Trying transform invoke." << std::endl;
|
||||
vtkm::internal::FunctionInterface<std::string(Type1, Type2, Type3)> funcInterface =
|
||||
vtkm::internal::make_FunctionInterface<std::string>(Arg1, Arg2, Arg3);
|
||||
|
||||
funcInterface.InvokeCont(ThreeArgStringFunctorWithReturn(), StringTransform());
|
||||
std::string result = funcInterface.GetReturnValue();
|
||||
|
||||
std::cout << "Got result: " << result << std::endl;
|
||||
VTKM_TEST_ASSERT(result == "1234 5678.125 Third argument", "Got bad result from invoke.");
|
||||
}
|
||||
|
||||
void TestStaticTransform()
|
||||
{
|
||||
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);
|
||||
|
||||
std::cout << "Transform with reported type." << std::endl;
|
||||
using ReportedType = OriginalType::StaticTransformType<PointerTransform>::type;
|
||||
ReportedType funcInterfaceTransform1 = funcInterface.StaticTransformCont(PointerTransform());
|
||||
funcInterfaceTransform1.InvokeCont(ThreePointerArgFunctor());
|
||||
funcInterfaceTransform1 = funcInterface.StaticTransformExec(PointerTransform());
|
||||
funcInterfaceTransform1.InvokeExec(ThreePointerArgFunctor());
|
||||
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;
|
||||
|
||||
VTKM_STATIC_ASSERT((std::is_same<const Type1*, P1>::value));
|
||||
VTKM_STATIC_ASSERT((std::is_same<const Type2*, P2>::value));
|
||||
VTKM_STATIC_ASSERT((std::is_same<const Type3*, P3>::value));
|
||||
}
|
||||
|
||||
void TestDynamicTransform()
|
||||
{
|
||||
std::cout << "Trying dynamic transform." << std::endl;
|
||||
vtkm::internal::FunctionInterface<void(Type1, Type2, Type3)> funcInterface =
|
||||
vtkm::internal::make_FunctionInterface<void>(Arg1, Arg2, Arg3);
|
||||
|
||||
g_DynamicTransformFinishCalls = 0;
|
||||
|
||||
funcInterface.DynamicTransformCont(DynamicTransformFunctor(), DynamicTransformFinish());
|
||||
|
||||
// We use an idiosyncrasy of DynamicTransform to call finish with two
|
||||
// permutations for every non string argument and one permutation for every
|
||||
// string argument. Thus, we expect it to be called 4 times.
|
||||
std::cout << "Number of finish calls: " << g_DynamicTransformFinishCalls << std::endl;
|
||||
VTKM_TEST_ASSERT(g_DynamicTransformFinishCalls == 4,
|
||||
"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<void(Type1, Type2, Type3, Type4, Type5)> funcInterface =
|
||||
vtkm::internal::make_FunctionInterface<void>(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>() == Type1(1) + Arg1, "Arg 1 incorrect.");
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<2>() == Type2(2) + Arg2, "Arg 2 incorrect.");
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() == Arg3 + "+3", "Arg 3 incorrect.");
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<4>() == Type4(4) + Arg4, "Arg 4 incorrect.");
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<5>() == Type5(5) + Arg5, "Arg 5 incorrect.");
|
||||
|
||||
funcInterface.ForEachExec(ForEachFunctor());
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<1>() == Type1(2) + Arg1, "Arg 1 incorrect.");
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<2>() == Type2(4) + Arg2, "Arg 2 incorrect.");
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() == Arg3 + "+3+3", "Arg 3 incorrect.");
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<4>() == Type4(8) + Arg4, "Arg 4 incorrect.");
|
||||
VTKM_TEST_ASSERT(funcInterface.GetParameter<5>() == Type5(10) + Arg5, "Arg 5 incorrect.");
|
||||
}
|
||||
|
||||
#ifdef TEST_INVOKE_TIME
|
||||
void TestInvokeTime()
|
||||
{
|
||||
std::cout << "Checking time to call lots of args lots of times." << std::endl;
|
||||
static vtkm::Id NUM_TRIALS = 50000;
|
||||
LotsOfArgsFunctor f;
|
||||
|
||||
vtkm::cont::Timer<> timer;
|
||||
for (vtkm::Id trial = 0; trial < NUM_TRIALS; trial++)
|
||||
{
|
||||
f(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f);
|
||||
}
|
||||
vtkm::Float64 directCallTime = timer.GetElapsedTime();
|
||||
std::cout << "Time for direct call: " << directCallTime << " seconds" << std::endl;
|
||||
|
||||
vtkm::internal::FunctionInterface<void(vtkm::FloatDefault,
|
||||
vtkm::FloatDefault,
|
||||
vtkm::FloatDefault,
|
||||
vtkm::FloatDefault,
|
||||
vtkm::FloatDefault,
|
||||
vtkm::FloatDefault,
|
||||
vtkm::FloatDefault,
|
||||
vtkm::FloatDefault,
|
||||
vtkm::FloatDefault,
|
||||
vtkm::FloatDefault)>
|
||||
funcInterface = vtkm::internal::make_FunctionInterface<void>(vtkm::FloatDefault(1),
|
||||
vtkm::FloatDefault(2),
|
||||
vtkm::FloatDefault(3),
|
||||
vtkm::FloatDefault(4),
|
||||
vtkm::FloatDefault(5),
|
||||
vtkm::FloatDefault(6),
|
||||
vtkm::FloatDefault(7),
|
||||
vtkm::FloatDefault(8),
|
||||
vtkm::FloatDefault(9),
|
||||
vtkm::FloatDefault(10));
|
||||
|
||||
timer.Reset();
|
||||
for (vtkm::Id trial = 0; trial < NUM_TRIALS; trial++)
|
||||
{
|
||||
funcInterface.InvokeCont(f);
|
||||
}
|
||||
vtkm::Float64 invokeCallTime = timer.GetElapsedTime();
|
||||
std::cout << "Time for invoking function interface: " << invokeCallTime << " seconds"
|
||||
<< std::endl;
|
||||
std::cout << "Pointless result (making sure compiler computes it) " << f.Field << std::endl;
|
||||
|
||||
#if !defined(NDEBUG) && defined(VTKM_MSVC)
|
||||
// We expect function calls through the FunctionInterface class to take
|
||||
// about the same amount of time as calling the function directly. If
|
||||
// optimization is on and functions are properly inlined, this should
|
||||
// certainly be the case. Most compilers are close even in debug mode.
|
||||
// However, some compilers might add extra debug instructions for each
|
||||
// function call, so this might slow things down. Handle that contingency
|
||||
// here with just a warning. (Future builds might need to add more cases
|
||||
// here.)
|
||||
if (invokeCallTime >= 1.05 * directCallTime)
|
||||
{
|
||||
std::cout << "WARNING: Function interface took longer than expected." << std::endl
|
||||
<< "That should be corrected in release builds." << std::endl;
|
||||
}
|
||||
#else
|
||||
// Might need to disable this for non-release builds.
|
||||
VTKM_TEST_ASSERT(invokeCallTime < 1.05 * directCallTime,
|
||||
"Function interface invoke took longer than expected.");
|
||||
#endif
|
||||
}
|
||||
#endif // if TEST_INVOKE_TIME
|
||||
|
||||
void TestFunctionInterface()
|
||||
{
|
||||
TestBasicFunctionInterface();
|
||||
TestInvokeResult();
|
||||
TestAppend();
|
||||
TestTransformInvoke();
|
||||
TestStaticTransform();
|
||||
TestDynamicTransform();
|
||||
TestForEach();
|
||||
#ifdef TEST_INVOKE_TIME
|
||||
TestInvokeTime();
|
||||
#endif //TEST_INVOKE_TIME
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <vtkm/cont/arg/ControlSignatureTagBase.h>
|
||||
#include <vtkm/cont/arg/Transport.h>
|
||||
#include <vtkm/cont/arg/TypeCheck.h>
|
||||
#include <vtkm/cont/internal/DynamicTransform.h>
|
||||
|
||||
#include <vtkm/exec/arg/ExecutionSignatureTagBase.h>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user