Add DynamicTransform class.

This is used with the FunctionInterface::DynamicTransformCont method to
convert a call of arguments using dynamic array handles to a function
templated on concrete types.
This commit is contained in:
Kenneth Moreland 2014-04-30 09:34:49 -06:00
parent 90d78ca9b6
commit dac47ee550
6 changed files with 280 additions and 2 deletions

@ -26,6 +26,7 @@
#include <vtkm/cont/ContainerListTag.h>
#include <vtkm/cont/ErrorControlBadValue.h>
#include <vtkm/cont/internal/DynamicTransform.h>
#include <vtkm/cont/internal/SimplePolymorphicContainer.h>
#include <boost/smart_ptr/shared_ptr.hpp>
@ -246,6 +247,9 @@ template<typename TypeList, typename ContainerList>
class DynamicArrayHandleCast : public vtkm::cont::DynamicArrayHandle
{
public:
VTKM_CONT_EXPORT
DynamicArrayHandleCast() : DynamicArrayHandle() { }
VTKM_CONT_EXPORT
DynamicArrayHandleCast(const vtkm::cont::DynamicArrayHandle &array)
: DynamicArrayHandle(array) { }
@ -285,6 +289,18 @@ public:
}
};
template<>
struct DynamicTransformTraits<vtkm::cont::DynamicArrayHandle> {
typedef vtkm::cont::internal::DynamicTransformTagCastAndCall DynamicTag;
};
template<typename TypeList, typename ContainerList>
struct DynamicTransformTraits<
vtkm::cont::internal::DynamicArrayHandleCast<TypeList,ContainerList> >
{
typedef vtkm::cont::internal::DynamicTransformTagCastAndCall DynamicTag;
};
} // namespace internal
}

@ -32,6 +32,7 @@ set(headers
DeviceAdapterError.h
DeviceAdapterTag.h
DeviceAdapterTagSerial.h
DynamicTransform.h
IteratorFromArrayPortal.h
SimplePolymorphicContainer.h
)

@ -0,0 +1,121 @@
//============================================================================
// 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_cont_internal_DynamicTransform_h
#define vtk_m_cont_internal_DynamicTransform_h
#include "vtkm/internal/ExportMacros.h"
namespace vtkm {
namespace cont {
namespace internal {
namespace detail {
template<typename ContinueFunctor>
struct DynamicArrayTransformCastAndCall
{
const ContinueFunctor &Continue;
VTKM_CONT_EXPORT
DynamicArrayTransformCastAndCall(const ContinueFunctor &continueFunc)
: Continue(continueFunc) { }
template<typename T>
VTKM_CONT_EXPORT
void operator()(const T &x) const {
this->Continue(x);
}
};
} // namespace detail
/// Tag used to identify an object that is a dynamic object that contains a
/// CastAndCall method that iterates over all possible dynamic choices to run
/// templated code.
///
struct DynamicTransformTagCastAndCall { };
/// Tag used to identify an object that is a static object that, when used with
/// a \c DynamicTransform should just pass itself as a concrete object.
///
struct DynamicTransformTagStatic { };
/// A traits class that identifies whether an object used in a \c
/// DynamicTransform should use a \c CastAndCall functionality or treated as a
/// static object. The default implementation identifies the object as static
/// (as most objects are bound to be). Dynamic objects that implement
/// \c CastAndCall should specialize (or partially specialize) this traits class
/// to identify the object as dynamic. VTK-m classes like \c DynamicArray are
/// already specialized.
///
template<typename T>
struct DynamicTransformTraits {
/// A type set to either \c DynamicTransformTagStatic or \c
/// DynamicTransformTagCastAndCall. The default implementation is set to \c
/// DynamicTransformTagStatic. Dynamic objects that implement \c CastAndCall
/// should specialize this class redefine it to \c
/// DynamicTransformTagCastAndCall.
///
typedef vtkm::cont::internal::DynamicTransformTagStatic DynamicTag;
};
/// 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_CONT_EXPORT
void operator()(const InputType &input,
const ContinueFunctor &continueFunc) const
{
this->DoTransform(
input,
continueFunc,
typename vtkm::cont::internal::DynamicTransformTraits<InputType>::DynamicTag());
}
private:
template<typename InputType, typename ContinueFunctor>
VTKM_CONT_EXPORT
void DoTransform(const InputType &input,
const ContinueFunctor &continueFunc,
vtkm::cont::internal::DynamicTransformTagStatic) const
{
continueFunc(input);
}
template<typename InputType, typename ContinueFunctor>
VTKM_CONT_EXPORT
void DoTransform(const InputType &dynamicInput,
const ContinueFunctor &continueFunc,
vtkm::cont::internal::DynamicTransformTagCastAndCall) const
{
dynamicInput.CastAndCall(
detail::DynamicArrayTransformCastAndCall<ContinueFunctor>(continueFunc));
}
};
}
}
} // namespace vtkm::cont::internal
#endif //vtk_m_cont_internal_DynamicTransform_h

@ -22,6 +22,7 @@
set(unit_tests
UnitTestArrayManagerExecutionShareWithControl.cxx
UnitTestArrayPortalFromIterators.cxx
UnitTestDynamicTransform.cxx
UnitTestIteratorFromArrayPortal.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests})

@ -0,0 +1,139 @@
//============================================================================
// 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.
//============================================================================
#include "vtkm/cont/internal/DynamicTransform.h"
#include "vtkm/cont/ArrayHandle.h"
#include "vtkm/cont/DynamicArrayHandle.h"
#include "vtkm/internal/FunctionInterface.h"
#include "vtkm/cont/testing/Testing.h"
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::Scalar) const {
std::cout << " In Scalar functor." << std::endl;
g_FunctionCalls++;
}
};
struct ArrayHandleScalarFunctor {
template<typename T>
void operator()(const vtkm::cont::ArrayHandle<T> &) const {
VTKM_TEST_FAIL("Called wrong form of functor operator.");
}
void operator()(const vtkm::cont::ArrayHandle<vtkm::Scalar> &) const {
std::cout << " In ArrayHandle<Scalar> functor." << std::endl;
g_FunctionCalls++;
}
};
struct ArrayHandleStringFunctor {
void operator()(const vtkm::cont::ArrayHandle<std::string> &) const {
std::cout << " In ArrayHandle<string> 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::Scalar>,
vtkm::cont::ArrayHandle<vtkm::Scalar>,
vtkm::cont::ArrayHandle<std::string>)> &) const {
std::cout << " In FunctionInterface<...> functor." << std::endl;
g_FunctionCalls++;
}
};
void TestBasicTransform()
{
std::cout << "Testing basic transform." << std::endl;
vtkm::cont::internal::DynamicTransform transform;
std::cout << " Trying with simple scalar." << std::endl;
TRY_TRANSFORM(transform(vtkm::Scalar(5), ScalarFunctor()));
std::cout << " Trying with basic scalar array." << std::endl;
vtkm::cont::ArrayHandle<vtkm::Scalar> concreteArray;
TRY_TRANSFORM(transform(concreteArray, ArrayHandleScalarFunctor()));
std::cout << " Trying scalar dynamic array." << std::endl;
vtkm::cont::DynamicArrayHandle dynamicArray = concreteArray;
TRY_TRANSFORM(transform(dynamicArray, ArrayHandleScalarFunctor()));
std::cout << " Trying with unusual (string) dynamic array." << std::endl;
dynamicArray = vtkm::cont::ArrayHandle<std::string>();
TRY_TRANSFORM(transform(dynamicArray.ResetTypeList(TypeListTagString()),
ArrayHandleStringFunctor()));
}
void TestFunctionTransform()
{
std::cout << "Testing transforms in FunctionInterface." << std::endl;
vtkm::cont::ArrayHandle<vtkm::Scalar> scalarArray;
vtkm::cont::ArrayHandle<std::string> stringArray;
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)));
std::cout << " Trying dynamic cast" << std::endl;
TRY_TRANSFORM(
vtkm::internal::make_FunctionInterface<void>(
scalarArray,
vtkm::cont::DynamicArrayHandle(scalarArray),
vtkm::cont::DynamicArrayHandle(stringArray).ResetTypeList(TypeListTagString()))
.DynamicTransformCont(vtkm::cont::internal::DynamicTransform(),
FunctionInterfaceFunctor()));
}
void TestDynamicTransform()
{
TestBasicTransform();
TestFunctionTransform();
}
} // anonymous namespace
int UnitTestDynamicTransform(int, char *[])
{
return vtkm::cont::testing::Testing::Run(TestDynamicTransform);
}

@ -583,9 +583,9 @@ public:
/// template<typename InputType, typename ContinueFunctor>
/// VTKM_CONT_EXPORT
/// void operator()(const InputType &input,
/// const ContinueFunctor &continue) const
/// const ContinueFunctor &continueFunc) const
/// {
/// continue(input);
/// continueFunc(input);
/// }
///
/// template<typename ContinueFunctor>