Commit 37dac920 authored by Kenneth Moreland's avatar Kenneth Moreland

Add index tags to FunctionInterface features.

The functors in the ForEach, StaticTransform, and DynamicTransform
methods sometimes can use the index of the parameter that they are
operating on. This can be a helpful diagnostic in compile and run-time
errors. It is also helpful when linking parameters from one
FunctionInterface with those of another.

This new features are now replacing implementations using the Zip
functionality that was removed earlier. The implementation is actually
simplified a bit.
parent 0fdc3116
......@@ -30,6 +30,8 @@
#include <boost/static_assert.hpp>
#include <sstream>
namespace vtkm {
namespace cont {
......@@ -128,16 +130,17 @@ struct CompositeVectorArrayToPortalCont {
template<typename DeviceAdapterTag>
struct CompositeVectorArrayToPortalExec {
template<typename ArrayHandleType>
template<typename ArrayHandleType, vtkm::IdComponent Index>
struct ReturnType {
typedef typename ArrayHandleType::template ExecutionTypes<
DeviceAdapterTag>::PortalConst type;
};
template<typename ArrayHandleType>
template<typename ArrayHandleType, vtkm::IdComponent Index>
VTKM_CONT_EXPORT
typename ReturnType<ArrayHandleType>::type
operator()(const ArrayHandleType &array) const {
typename ReturnType<ArrayHandleType, Index>::type
operator()(const ArrayHandleType &array,
vtkm::internal::IndexTag<Index>) const {
return array.PrepareForInput(DeviceAdapterTag());
}
};
......@@ -146,12 +149,15 @@ struct CheckArraySizeFunctor {
vtkm::Id ExpectedSize;
CheckArraySizeFunctor(vtkm::Id expectedSize) : ExpectedSize(expectedSize) { }
template<typename T>
void operator()(const T &a) const {
template<typename T, vtkm::IdComponent Index>
void operator()(const T &a, vtkm::internal::IndexTag<Index>) const {
if (a.GetNumberOfValues() != this->ExpectedSize)
{
throw vtkm::cont::ErrorControlBadValue(
"All input arrays to ArrayHandleCompositeVector must be the same size.");
std::stringstream message;
message << "All input arrays to ArrayHandleCompositeVector must be the same size.\n"
<< "Array " << Index-1 << " has " << a.GetNumberOfValues()
<< ". Expected " << this->ExpectedSize << ".";
throw vtkm::cont::ErrorControlBadValue(message.str().c_str());
}
}
};
......
......@@ -20,7 +20,7 @@
#ifndef vtk_m_cont_internal_DynamicTransform_h
#define vtk_m_cont_internal_DynamicTransform_h
#include "vtkm/internal/ExportMacros.h"
#include "vtkm/internal/IndexTag.h"
namespace vtkm {
namespace cont {
......@@ -62,10 +62,13 @@ struct DynamicTransformTraits {
///
struct DynamicTransform
{
template<typename InputType, typename ContinueFunctor>
template<typename InputType,
typename ContinueFunctor,
vtkm::IdComponent Index>
VTKM_CONT_EXPORT
void operator()(const InputType &input,
const ContinueFunctor &continueFunc) const
const ContinueFunctor &continueFunc,
vtkm::internal::IndexTag<Index>) const
{
this->DoTransform(
input,
......
......@@ -85,22 +85,24 @@ 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()));
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()));
TRY_TRANSFORM(transform(concreteArray, ArrayHandleScalarFunctor(), indexTag));
std::cout << " Trying scalar dynamic array." << std::endl;
vtkm::cont::DynamicArrayHandle dynamicArray = concreteArray;
TRY_TRANSFORM(transform(dynamicArray, ArrayHandleScalarFunctor()));
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.ResetTypeList(TypeListTagString()),
ArrayHandleStringFunctor()));
ArrayHandleStringFunctor(),
indexTag));
}
void TestFunctionTransform()
......
......@@ -25,6 +25,7 @@ set(headers
FunctionInterface.h
FunctionInterfaceDetailPost.h
FunctionInterfaceDetailPre.h
IndexTag.h
Invocation.h
ListTagDetail.h
)
......
This diff is collapsed.
......@@ -53,7 +53,7 @@ template<typename Transform,
typename P1>
struct FunctionInterfaceStaticTransformType<R(P1), Transform> {
typedef R(type)(
typename Transform::template ReturnType<P1>::type
typename Transform::template ReturnType<P1,1>::type
);
};
......@@ -63,8 +63,8 @@ template<typename Transform,
typename P2>
struct FunctionInterfaceStaticTransformType<R(P1,P2), Transform> {
typedef R(type)(
typename Transform::template ReturnType<P1>::type,
typename Transform::template ReturnType<P2>::type
typename Transform::template ReturnType<P1,1>::type,
typename Transform::template ReturnType<P2,2>::type
);
};
......@@ -75,9 +75,9 @@ template<typename Transform,
typename P3>
struct FunctionInterfaceStaticTransformType<R(P1,P2,P3), Transform> {
typedef R(type)(
typename Transform::template ReturnType<P1>::type,
typename Transform::template ReturnType<P2>::type,
typename Transform::template ReturnType<P3>::type
typename Transform::template ReturnType<P1,1>::type,
typename Transform::template ReturnType<P2,2>::type,
typename Transform::template ReturnType<P3,3>::type
);
};
......@@ -89,10 +89,10 @@ template<typename Transform,
typename P4>
struct FunctionInterfaceStaticTransformType<R(P1,P2,P3,P4), Transform> {
typedef R(type)(
typename Transform::template ReturnType<P1>::type,
typename Transform::template ReturnType<P2>::type,
typename Transform::template ReturnType<P3>::type,
typename Transform::template ReturnType<P4>::type
typename Transform::template ReturnType<P1,1>::type,
typename Transform::template ReturnType<P2,2>::type,
typename Transform::template ReturnType<P3,3>::type,
typename Transform::template ReturnType<P4,4>::type
);
};
......@@ -105,11 +105,11 @@ template<typename Transform,
typename P5>
struct FunctionInterfaceStaticTransformType<R(P1,P2,P3,P4,P5), Transform> {
typedef R(type)(
typename Transform::template ReturnType<P1>::type,
typename Transform::template ReturnType<P2>::type,
typename Transform::template ReturnType<P3>::type,
typename Transform::template ReturnType<P4>::type,
typename Transform::template ReturnType<P5>::type
typename Transform::template ReturnType<P1,1>::type,
typename Transform::template ReturnType<P2,2>::type,
typename Transform::template ReturnType<P3,3>::type,
typename Transform::template ReturnType<P4,4>::type,
typename Transform::template ReturnType<P5,5>::type
);
};
......@@ -123,12 +123,12 @@ template<typename Transform,
typename P6>
struct FunctionInterfaceStaticTransformType<R(P1,P2,P3,P4,P5,P6), Transform> {
typedef R(type)(
typename Transform::template ReturnType<P1>::type,
typename Transform::template ReturnType<P2>::type,
typename Transform::template ReturnType<P3>::type,
typename Transform::template ReturnType<P4>::type,
typename Transform::template ReturnType<P5>::type,
typename Transform::template ReturnType<P6>::type
typename Transform::template ReturnType<P1,1>::type,
typename Transform::template ReturnType<P2,2>::type,
typename Transform::template ReturnType<P3,3>::type,
typename Transform::template ReturnType<P4,4>::type,
typename Transform::template ReturnType<P5,5>::type,
typename Transform::template ReturnType<P6,6>::type
);
};
......@@ -143,13 +143,13 @@ template<typename Transform,
typename P7>
struct FunctionInterfaceStaticTransformType<R(P1,P2,P3,P4,P5,P6,P7), Transform> {
typedef R(type)(
typename Transform::template ReturnType<P1>::type,
typename Transform::template ReturnType<P2>::type,
typename Transform::template ReturnType<P3>::type,
typename Transform::template ReturnType<P4>::type,
typename Transform::template ReturnType<P5>::type,
typename Transform::template ReturnType<P6>::type,
typename Transform::template ReturnType<P7>::type
typename Transform::template ReturnType<P1,1>::type,
typename Transform::template ReturnType<P2,2>::type,
typename Transform::template ReturnType<P3,3>::type,
typename Transform::template ReturnType<P4,4>::type,
typename Transform::template ReturnType<P5,5>::type,
typename Transform::template ReturnType<P6,6>::type,
typename Transform::template ReturnType<P7,7>::type
);
};
......@@ -165,14 +165,14 @@ template<typename Transform,
typename P8>
struct FunctionInterfaceStaticTransformType<R(P1,P2,P3,P4,P5,P6,P7,P8), Transform> {
typedef R(type)(
typename Transform::template ReturnType<P1>::type,
typename Transform::template ReturnType<P2>::type,
typename Transform::template ReturnType<P3>::type,
typename Transform::template ReturnType<P4>::type,
typename Transform::template ReturnType<P5>::type,
typename Transform::template ReturnType<P6>::type,
typename Transform::template ReturnType<P7>::type,
typename Transform::template ReturnType<P8>::type
typename Transform::template ReturnType<P1,1>::type,
typename Transform::template ReturnType<P2,2>::type,
typename Transform::template ReturnType<P3,3>::type,
typename Transform::template ReturnType<P4,4>::type,
typename Transform::template ReturnType<P5,5>::type,
typename Transform::template ReturnType<P6,6>::type,
typename Transform::template ReturnType<P7,7>::type,
typename Transform::template ReturnType<P8,8>::type
);
};
......@@ -189,15 +189,15 @@ template<typename Transform,
typename P9>
struct FunctionInterfaceStaticTransformType<R(P1,P2,P3,P4,P5,P6,P7,P8,P9), Transform> {
typedef R(type)(
typename Transform::template ReturnType<P1>::type,
typename Transform::template ReturnType<P2>::type,
typename Transform::template ReturnType<P3>::type,
typename Transform::template ReturnType<P4>::type,
typename Transform::template ReturnType<P5>::type,
typename Transform::template ReturnType<P6>::type,
typename Transform::template ReturnType<P7>::type,
typename Transform::template ReturnType<P8>::type,
typename Transform::template ReturnType<P9>::type
typename Transform::template ReturnType<P1,1>::type,
typename Transform::template ReturnType<P2,2>::type,
typename Transform::template ReturnType<P3,3>::type,
typename Transform::template ReturnType<P4,4>::type,
typename Transform::template ReturnType<P5,5>::type,
typename Transform::template ReturnType<P6,6>::type,
typename Transform::template ReturnType<P7,7>::type,
typename Transform::template ReturnType<P8,8>::type,
typename Transform::template ReturnType<P9,9>::type
);
};
......@@ -215,16 +215,16 @@ template<typename Transform,
typename P10>
struct FunctionInterfaceStaticTransformType<R(P1,P2,P3,P4,P5,P6,P7,P8,P9,P10), Transform> {
typedef R(type)(
typename Transform::template ReturnType<P1>::type,
typename Transform::template ReturnType<P2>::type,
typename Transform::template ReturnType<P3>::type,
typename Transform::template ReturnType<P4>::type,
typename Transform::template ReturnType<P5>::type,
typename Transform::template ReturnType<P6>::type,
typename Transform::template ReturnType<P7>::type,
typename Transform::template ReturnType<P8>::type,
typename Transform::template ReturnType<P9>::type,
typename Transform::template ReturnType<P10>::type
typename Transform::template ReturnType<P1,1>::type,
typename Transform::template ReturnType<P2,2>::type,
typename Transform::template ReturnType<P3,3>::type,
typename Transform::template ReturnType<P4,4>::type,
typename Transform::template ReturnType<P5,5>::type,
typename Transform::template ReturnType<P6,6>::type,
typename Transform::template ReturnType<P7,7>::type,
typename Transform::template ReturnType<P8,8>::type,
typename Transform::template ReturnType<P9,9>::type,
typename Transform::template ReturnType<P10,10>::type
);
};
......
......@@ -94,7 +94,7 @@ template<typename Transform,
struct FunctionInterfaceStaticTransformType<$signature(num_params), Transform> {
typedef $ptype(0)(type)(
$for(param_index in xrange(1, num_params+1))\
typename Transform::template ReturnType<$ptype(param_index)>::type$comma_if(param_index<num_params)
typename Transform::template ReturnType<$ptype(param_index),$(param_index)>::type$comma_if(param_index<num_params)
$endfor\
);
};
......
This diff is collapsed.
......@@ -40,6 +40,7 @@ $# Ignore the following comment. It is meant for the generated file.
#endif
#include <vtkm/Types.h>
#include <vtkm/internal/IndexTag.h>
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/at.hpp>
......@@ -228,7 +229,8 @@ $if(num_params < 1)\
(void)transformedParameters;
$else\
$for(param_index in xrange(1, num_params+1))\
transformedParameters.Parameter$(param_index) = transform(originalParameters.Parameter$(param_index));
transformedParameters.Parameter$(param_index) =
transform(originalParameters.Parameter$(param_index), vtkm::internal::IndexTag<$(param_index)>());
$endfor\
$endif\
}
......@@ -255,7 +257,7 @@ $if(num_params < 1)\
(void)parameters;
$else\
$for(param_index in xrange(1, num_params+1))\
f(parameters.Parameter$(param_index));
f(parameters.Parameter$(param_index), vtkm::internal::IndexTag<$(param_index)>());
$endfor\
$endif\
}
......
//============================================================================
// 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.
//
// Copyright 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014. Los Alamos National Security
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_internal_StaticIndex_h
#define vtk_m_internal_StaticIndex_h
#include <vtkm/Types.h>
namespace vtkm {
namespace internal {
/// \brief A convenience tag to represent static indices.
///
/// Some classes like \c FunctionInterface have a list of items that have
/// numeric indices that must be resolved at compile time. Typically these are
/// referenced with an integer template argument. However, such template
/// arguments have to be explicitly defined in the template. They cannot be
/// resolved through function or method arguments. In such cases, it is
/// convenient to use this tag to encapsulate the index.
///
template<vtkm::IdComponent Index>
struct IndexTag
{
static const vtkm::IdComponent INDEX = Index;
};
}
} // namespace vtkm::internal
#endif //vtk_m_internal_StaticIndex_h
......@@ -83,13 +83,13 @@ struct GetReferenceFunctor
};
struct PointerTransform {
template<typename T>
template<typename T, vtkm::IdComponent Index>
struct ReturnType {
typedef const T *type;
};
template<typename T>
const T *operator()(const T &x) const {
template<typename T, typename IndexTag>
const T *operator()(const T &x, IndexTag) const {
return &x;
}
};
......@@ -216,15 +216,19 @@ struct ThreeArgStringFunctorWithReturn
struct DynamicTransformFunctor
{
template<typename T, typename ContinueFunctor>
void operator()(const T &input, const ContinueFunctor continueFunc) const
template<typename T, typename ContinueFunctor, vtkm::IdComponent Index>
void operator()(const T &input,
const ContinueFunctor continueFunc,
vtkm::internal::IndexTag<Index>) const
{
continueFunc(input);
continueFunc(ToString(input));
continueFunc(input+T(Index));
continueFunc(ToString(input+T(Index)));
}
template<typename ContinueFunctor>
void operator()(const std::string &input, const ContinueFunctor continueFunc) const
template<typename ContinueFunctor, vtkm::IdComponent Index>
void operator()(const std::string &input,
const ContinueFunctor continueFunc,
vtkm::internal::IndexTag<Index>) const
{
continueFunc(input);
}
......@@ -238,9 +242,9 @@ struct DynamicTransformFinish
void operator()(vtkm::internal::FunctionInterface<Signature> &funcInterface) const
{
g_DynamicTransformFinishCalls++;
VTKM_TEST_ASSERT(ToString(funcInterface.template GetParameter<1>()) == ToString(Arg1),
VTKM_TEST_ASSERT(ToString(funcInterface.template GetParameter<1>()) == ToString(Arg1+1),
"Arg 1 incorrect");
VTKM_TEST_ASSERT(ToString(funcInterface.template GetParameter<2>()) == ToString(Arg2),
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");
......@@ -249,10 +253,17 @@ struct DynamicTransformFinish
struct ForEachFunctor
{
template<typename T>
void operator()(T &x) const { x = T(2)*x; }
template<typename T, vtkm::IdComponent Index>
void operator()(T &x, vtkm::internal::IndexTag<Index>) const {
x = T(Index)+x;
}
void operator()(std::string &x) const { x.append("*2"); }
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(
......@@ -273,7 +284,7 @@ void TryFunctionInterface5(
std::cout << "Swizzling parameters with replace." << std::endl;
funcInterface.Replace<1>(Arg5)
.Replace<2>(Arg1)
.Replace(Arg1, vtkm::internal::IndexTag<2>())
.Replace<5>(Arg2)
.InvokeCont(FiveArgSwizzledFunctor());
}
......@@ -288,7 +299,7 @@ void TestBasicFunctionInterface()
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<2>() == Arg2, "Arg 2 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter(vtkm::internal::IndexTag<2>()) == Arg2, "Arg 2 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() == Arg3, "Arg 3 incorrect.");
std::cout << "Checking invocation." << std::endl;
......@@ -297,7 +308,7 @@ void TestBasicFunctionInterface()
std::cout << "Checking invocation with argument modification." << std::endl;
funcInterface.SetParameter<1>(Type1());
funcInterface.SetParameter<2>(Type2());
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.");
......@@ -440,18 +451,18 @@ void TestForEach()
VTKM_TEST_ASSERT(funcInterface.GetParameter<5>() == Arg5, "Arg 5 incorrect.");
funcInterface.ForEachCont(ForEachFunctor());
VTKM_TEST_ASSERT(funcInterface.GetParameter<1>() == 2*Arg1, "Arg 1 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<2>() == 2*Arg2, "Arg 2 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() == Arg3+"*2", "Arg 3 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<4>() == 2.0f*Arg4, "Arg 4 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<5>() == 2*Arg5, "Arg 5 incorrect.");
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>() == 4*Arg1, "Arg 1 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<2>() == 4*Arg2, "Arg 2 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<3>() == Arg3+"*2*2", "Arg 3 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<4>() == 4.0f*Arg4, "Arg 4 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<5>() == 4*Arg5, "Arg 5 incorrect.");
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
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment