vtk-m/vtkm/cont/ArrayHandleCompositeVector.h
Kenneth Moreland 65c2261892 Add default constructors/destructors/assignment to ArrayHandle classes
The ArrayHandle classes all exclusively work in the control environment.
However, CUDA likes to add __device__ to constructors, destructors, and
assignment operators it automatically adds. This in turn causes warnings
about the __device__ function using host-only classes (like
boost::shared_ptr). Solve this problem by adding explicit methods for
all of these.

Implemented this by wrapping up all these default objects in a macro.
This also solved the problem of other constructors that are necessary
for array handles such as a constructor that takes the base array
handle.
2015-10-21 13:36:27 -06:00

735 lines
26 KiB
C++

//============================================================================
// 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_ArrayHandleCompositeVector_h
#define vtk_m_ArrayHandleCompositeVector_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ErrorControlBadValue.h>
#include <vtkm/cont/ErrorControlInternal.h>
#include <vtkm/StaticAssert.h>
#include <vtkm/VecTraits.h>
#include <vtkm/internal/FunctionInterface.h>
#include <sstream>
namespace vtkm {
namespace cont {
namespace internal {
namespace detail {
template<typename ValueType>
struct CompositeVectorSwizzleFunctor
{
static const vtkm::IdComponent NUM_COMPONENTS =
vtkm::VecTraits<ValueType>::NUM_COMPONENTS;
typedef vtkm::Vec<vtkm::IdComponent, NUM_COMPONENTS> ComponentMapType;
// Caution! This is a reference.
const ComponentMapType &SourceComponents;
VTKM_EXEC_CONT_EXPORT
CompositeVectorSwizzleFunctor(const ComponentMapType &sourceComponents)
: SourceComponents(sourceComponents) { }
// Currently only supporting 1-4 components.
template<typename T1>
VTKM_EXEC_CONT_EXPORT
ValueType operator()(const T1 &p1) const {
return ValueType(
vtkm::VecTraits<T1>::GetComponent(p1, this->SourceComponents[0]));
}
template<typename T1, typename T2>
VTKM_EXEC_CONT_EXPORT
ValueType operator()(const T1 &p1, const T2 &p2) const {
return ValueType(
vtkm::VecTraits<T1>::GetComponent(p1, this->SourceComponents[0]),
vtkm::VecTraits<T2>::GetComponent(p2, this->SourceComponents[1]));
}
template<typename T1, typename T2, typename T3>
VTKM_EXEC_CONT_EXPORT
ValueType operator()(const T1 &p1, const T2 &p2, const T3 &p3) const {
return ValueType(
vtkm::VecTraits<T1>::GetComponent(p1, this->SourceComponents[0]),
vtkm::VecTraits<T2>::GetComponent(p2, this->SourceComponents[1]),
vtkm::VecTraits<T3>::GetComponent(p3, this->SourceComponents[2]));
}
template<typename T1, typename T2, typename T3, typename T4>
VTKM_EXEC_CONT_EXPORT
ValueType operator()(const T1 &p1,
const T2 &p2,
const T3 &p3,
const T4 &p4) const {
return ValueType(
vtkm::VecTraits<T1>::GetComponent(p1, this->SourceComponents[0]),
vtkm::VecTraits<T2>::GetComponent(p2, this->SourceComponents[1]),
vtkm::VecTraits<T3>::GetComponent(p3, this->SourceComponents[2]),
vtkm::VecTraits<T4>::GetComponent(p4, this->SourceComponents[3]));
}
};
template<typename ReturnValueType>
struct CompositeVectorPullValueFunctor
{
vtkm::Id Index;
VTKM_EXEC_EXPORT
CompositeVectorPullValueFunctor(vtkm::Id index) : Index(index) { }
// This form is to pull values out of array arguments.
template<typename PortalType>
VTKM_EXEC_EXPORT
typename PortalType::ValueType operator()(const PortalType &portal) const {
return portal.Get(this->Index);
}
// This form is an identity to pass the return value back.
VTKM_EXEC_EXPORT
const ReturnValueType &operator()(const ReturnValueType &value) const {
return value;
}
};
struct CompositeVectorArrayToPortalCont {
template<typename ArrayHandleType>
struct ReturnType {
typedef typename ArrayHandleType::PortalConstControl type;
};
template<typename ArrayHandleType>
VTKM_CONT_EXPORT
typename ReturnType<ArrayHandleType>::type
operator()(const ArrayHandleType &array) const {
return array.GetPortalConstControl();
}
};
template<typename DeviceAdapterTag>
struct CompositeVectorArrayToPortalExec {
template<typename ArrayHandleType, vtkm::IdComponent Index>
struct ReturnType {
typedef typename ArrayHandleType::template ExecutionTypes<
DeviceAdapterTag>::PortalConst type;
};
template<typename ArrayHandleType, vtkm::IdComponent Index>
VTKM_CONT_EXPORT
typename ReturnType<ArrayHandleType, Index>::type
operator()(const ArrayHandleType &array,
vtkm::internal::IndexTag<Index>) const {
return array.PrepareForInput(DeviceAdapterTag());
}
};
struct CheckArraySizeFunctor {
vtkm::Id ExpectedSize;
CheckArraySizeFunctor(vtkm::Id expectedSize) : ExpectedSize(expectedSize) { }
template<typename T, vtkm::IdComponent Index>
void operator()(const T &a, vtkm::internal::IndexTag<Index>) const {
if (a.GetNumberOfValues() != this->ExpectedSize)
{
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());
}
}
};
} // namespace detail
/// \brief A portal that gets values from components of other portals.
///
/// This is the portal used within ArrayHandleCompositeVector.
///
template<typename SignatureWithPortals>
class ArrayPortalCompositeVector
{
typedef vtkm::internal::FunctionInterface<SignatureWithPortals> PortalTypes;
typedef vtkm::Vec<vtkm::IdComponent, PortalTypes::ARITY> ComponentMapType;
public:
typedef typename PortalTypes::ResultType ValueType;
static const vtkm::IdComponent NUM_COMPONENTS =
vtkm::VecTraits<ValueType>::NUM_COMPONENTS;
VTKM_STATIC_ASSERT(NUM_COMPONENTS == PortalTypes::ARITY);
VTKM_EXEC_CONT_EXPORT
ArrayPortalCompositeVector() { }
VTKM_CONT_EXPORT
ArrayPortalCompositeVector(
const PortalTypes portals,
vtkm::Vec<vtkm::IdComponent, NUM_COMPONENTS> sourceComponents)
: Portals(portals), SourceComponents(sourceComponents) { }
VTKM_EXEC_EXPORT
vtkm::Id GetNumberOfValues() const {
return this->Portals.template GetParameter<1>().GetNumberOfValues();
}
VTKM_EXEC_EXPORT
ValueType Get(vtkm::Id index) const {
// This might be inefficient because we are copying all the portals only
// because they are coupled with the return value.
PortalTypes localPortals = this->Portals;
localPortals.InvokeExec(
detail::CompositeVectorSwizzleFunctor<ValueType>(this->SourceComponents),
detail::CompositeVectorPullValueFunctor<ValueType>(index));
return localPortals.GetReturnValue();
}
private:
PortalTypes Portals;
ComponentMapType SourceComponents;
};
/// \brief A "portal" that holds arrays to get components from.
///
/// This class takes place as the control-side portal within an
/// ArrayHandleCompositeVector. This is an incomplete implementation, so you
/// really can't use it to get values. However, between this and the
/// specialization ArrayTransfer, it's enough to get values to the execution
/// environment.
///
template<typename SignatureWithArrays>
class ArrayPortalCompositeVectorCont
{
typedef vtkm::internal::FunctionInterface<SignatureWithArrays>
FunctionInterfaceArrays;
public:
typedef typename FunctionInterfaceArrays::ResultType ValueType;
static const vtkm::IdComponent NUM_COMPONENTS =
vtkm::VecTraits<ValueType>::NUM_COMPONENTS;
typedef vtkm::Vec<vtkm::IdComponent, NUM_COMPONENTS> ComponentMapType;
// If you get a compile error here, it means you probably tried to create
// an ArrayHandleCompositeVector with a return type of a vector with a
// different number of components than the number of arrays given.
VTKM_STATIC_ASSERT(NUM_COMPONENTS == FunctionInterfaceArrays::ARITY);
VTKM_CONT_EXPORT
ArrayPortalCompositeVectorCont() : NumberOfValues(0) { }
VTKM_CONT_EXPORT
ArrayPortalCompositeVectorCont(
const FunctionInterfaceArrays &arrays,
const ComponentMapType &vtkmNotUsed(sourceComponents))
: NumberOfValues(arrays.template GetParameter<1>().GetNumberOfValues()) { }
VTKM_CONT_EXPORT
vtkm::Id GetNumberOfValues() const {
return this->NumberOfValues;
}
VTKM_CONT_EXPORT
ValueType Get(vtkm::Id vtkmNotUsed(index)) const {
throw vtkm::cont::ErrorControlInternal(
"Const Array Portal not implemented for composite vector.");
}
VTKM_CONT_EXPORT
void Set(vtkm::Id vtkmNotUsed(index), ValueType vtkmNotUsed(value)) {
throw vtkm::cont::ErrorControlInternal(
"Const Array Portal not implemented for composite vector.");
}
private:
vtkm::Id NumberOfValues;
};
template<typename SignatureWithArrays>
struct StorageTagCompositeVector { };
/// A convenience class that provides a typedef to the appropriate tag for
/// a composite storage.
template<typename SignatureWithArrays>
struct ArrayHandleCompositeVectorTraits
{
typedef vtkm::cont::internal::StorageTagCompositeVector<SignatureWithArrays>
Tag;
typedef typename vtkm::internal::FunctionInterface<SignatureWithArrays>::ResultType
ValueType;
typedef vtkm::cont::internal::Storage<ValueType, Tag> StorageType;
typedef vtkm::cont::ArrayHandle<ValueType, Tag> Superclass;
};
// It may seem weird that this specialization throws an exception for
// everything, but that is because all the functionality is handled in the
// ArrayTransfer class.
template<typename SignatureWithArrays>
class Storage<
typename ArrayHandleCompositeVectorTraits<SignatureWithArrays>::ValueType,
vtkm::cont::internal::StorageTagCompositeVector<SignatureWithArrays> >
{
typedef vtkm::internal::FunctionInterface<SignatureWithArrays>
FunctionInterfaceWithArrays;
static const vtkm::IdComponent NUM_COMPONENTS = FunctionInterfaceWithArrays::ARITY;
typedef vtkm::Vec<vtkm::IdComponent, NUM_COMPONENTS> ComponentMapType;
public:
typedef ArrayPortalCompositeVectorCont<SignatureWithArrays> PortalType;
typedef PortalType PortalConstType;
typedef typename PortalType::ValueType ValueType;
VTKM_CONT_EXPORT
Storage() : Valid(false) { }
VTKM_CONT_EXPORT
Storage(const FunctionInterfaceWithArrays &arrays,
const ComponentMapType &sourceComponents)
: Arrays(arrays), SourceComponents(sourceComponents), Valid(true)
{
arrays.ForEachCont(
detail::CheckArraySizeFunctor(this->GetNumberOfValues()));
}
VTKM_CONT_EXPORT
PortalType GetPortal() {
throw vtkm::cont::ErrorControlBadValue(
"Composite vector arrays are read only.");
}
VTKM_CONT_EXPORT
PortalConstType GetPortalConst() const {
if (!this->Valid)
{
throw vtkm::cont::ErrorControlBadValue(
"Tried to use an ArrayHandleCompositeHandle without dependent arrays.");
}
return PortalConstType(this->Arrays, this->SourceComponents);
}
VTKM_CONT_EXPORT
vtkm::Id GetNumberOfValues() const {
if (!this->Valid)
{
throw vtkm::cont::ErrorControlBadValue(
"Tried to use an ArrayHandleCompositeHandle without dependent arrays.");
}
return this->Arrays.template GetParameter<1>().GetNumberOfValues();
}
VTKM_CONT_EXPORT
void Allocate(vtkm::Id vtkmNotUsed(numberOfValues)) {
throw vtkm::cont::ErrorControlInternal(
"The allocate method for the composite vector storage should never "
"have been called. The allocate is generally only called by the "
"execution array manager, and the array transfer for the composite "
"storage should prevent the execution array manager from being "
"directly used.");
}
VTKM_CONT_EXPORT
void Shrink(vtkm::Id vtkmNotUsed(numberOfValues)) {
throw vtkm::cont::ErrorControlBadValue(
"Composite vector arrays are read-only.");
}
VTKM_CONT_EXPORT
void ReleaseResources() {
if (this->Valid)
{
// TODO: Implement this.
}
}
VTKM_CONT_EXPORT
const FunctionInterfaceWithArrays &GetArrays() const {
VTKM_ASSERT_CONT(this->Valid);
return this->Arrays;
}
VTKM_CONT_EXPORT
const ComponentMapType &GetSourceComponents() const {
VTKM_ASSERT_CONT(this->Valid);
return this->SourceComponents;
}
private:
FunctionInterfaceWithArrays Arrays;
ComponentMapType SourceComponents;
bool Valid;
};
template<typename SignatureWithArrays, typename DeviceAdapterTag>
class ArrayTransfer<
typename ArrayHandleCompositeVectorTraits<SignatureWithArrays>::ValueType,
vtkm::cont::internal::StorageTagCompositeVector<SignatureWithArrays>,
DeviceAdapterTag>
{
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
typedef typename ArrayHandleCompositeVectorTraits<SignatureWithArrays>::StorageType
StorageType;
typedef vtkm::internal::FunctionInterface<SignatureWithArrays>
FunctionWithArrays;
typedef typename FunctionWithArrays::template StaticTransformType<
detail::CompositeVectorArrayToPortalExec<DeviceAdapterTag> >::type
FunctionWithPortals;
typedef typename FunctionWithPortals::Signature SignatureWithPortals;
public:
typedef typename ArrayHandleCompositeVectorTraits<SignatureWithArrays>::ValueType
ValueType;
// These are not currently fully implemented.
typedef typename StorageType::PortalType PortalControl;
typedef typename StorageType::PortalConstType PortalConstControl;
typedef ArrayPortalCompositeVector<SignatureWithPortals> PortalExecution;
typedef ArrayPortalCompositeVector<SignatureWithPortals> PortalConstExecution;
VTKM_CONT_EXPORT
ArrayTransfer(StorageType *storage) : Storage(storage) { }
VTKM_CONT_EXPORT
vtkm::Id GetNumberOfValues() const {
return this->Storage->GetNumberOfValues();
}
VTKM_CONT_EXPORT
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData)) const
{
return
PortalConstExecution(
this->Storage->GetArrays().StaticTransformCont(
detail::CompositeVectorArrayToPortalExec<DeviceAdapterTag>()),
this->Storage->GetSourceComponents());
}
VTKM_CONT_EXPORT
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
{
// It may be the case a composite vector could be used for in place
// operations, but this is not implemented currently.
throw vtkm::cont::ErrorControlBadValue(
"Composite vector arrays cannot be used for output or in place.");
}
VTKM_CONT_EXPORT
PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues))
{
// It may be the case a composite vector could be used for output if you
// want the delegate arrays to be resized, but this is not implemented
// currently.
throw vtkm::cont::ErrorControlBadValue(
"Composite vector arrays cannot be used for output.");
}
VTKM_CONT_EXPORT
void RetrieveOutputData(StorageType *vtkmNotUsed(storage)) const
{
throw vtkm::cont::ErrorControlBadValue(
"Composite vector arrays cannot be used for output.");
}
VTKM_CONT_EXPORT
void Shrink(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorControlBadValue(
"Composite vector arrays cannot be resized.");
}
VTKM_CONT_EXPORT
void ReleaseResources() {
this->Storage->ReleaseResources();
}
private:
StorageType *Storage;
};
} // namespace internal
/// \brief An \c ArrayHandle that combines components from other arrays.
///
/// \c ArrayHandleCompositeVector is a specialization of \c ArrayHandle that
/// derives its content from other arrays. It takes up to 4 other \c
/// ArrayHandle objects and mimics an array that contains vectors with
/// components that come from these delegate arrays.
///
/// The easiest way to create and type an \c ArrayHandleCompositeVector is
/// to use the \c make_ArrayHandleCompositeVector functions.
///
template<typename Signature>
class ArrayHandleCompositeVector
: public internal::ArrayHandleCompositeVectorTraits<Signature>::Superclass
{
typedef typename internal::ArrayHandleCompositeVectorTraits<Signature>::StorageType
StorageType;
typedef typename internal::ArrayPortalCompositeVectorCont<Signature>::ComponentMapType
ComponentMapType;
public:
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleCompositeVector,
(ArrayHandleCompositeVector<Signature>),
(typename internal::ArrayHandleCompositeVectorTraits<Signature>::Superclass));
VTKM_CONT_EXPORT
ArrayHandleCompositeVector(
const vtkm::internal::FunctionInterface<Signature> &arrays,
const ComponentMapType &sourceComponents)
: Superclass(StorageType(arrays, sourceComponents))
{ }
/// Template constructors for passing in types. You'll get weird compile
/// errors if the argument types do not actually match the types in the
/// signature.
///
template<typename ArrayHandleType1>
VTKM_CONT_EXPORT
ArrayHandleCompositeVector(const ArrayHandleType1 &array1,
vtkm::IdComponent sourceComponent1)
: Superclass(StorageType(
vtkm::internal::make_FunctionInterface<ValueType>(array1),
ComponentMapType(sourceComponent1)))
{ }
template<typename ArrayHandleType1,
typename ArrayHandleType2>
VTKM_CONT_EXPORT
ArrayHandleCompositeVector(const ArrayHandleType1 &array1,
vtkm::IdComponent sourceComponent1,
const ArrayHandleType2 &array2,
vtkm::IdComponent sourceComponent2)
: Superclass(StorageType(
vtkm::internal::make_FunctionInterface<ValueType>(
array1, array2),
ComponentMapType(sourceComponent1,
sourceComponent2)))
{ }
template<typename ArrayHandleType1,
typename ArrayHandleType2,
typename ArrayHandleType3>
VTKM_CONT_EXPORT
ArrayHandleCompositeVector(const ArrayHandleType1 &array1,
vtkm::IdComponent sourceComponent1,
const ArrayHandleType2 &array2,
vtkm::IdComponent sourceComponent2,
const ArrayHandleType3 &array3,
vtkm::IdComponent sourceComponent3)
: Superclass(StorageType(
vtkm::internal::make_FunctionInterface<ValueType>(
array1, array2, array3),
ComponentMapType(sourceComponent1,
sourceComponent2,
sourceComponent3)))
{ }
template<typename ArrayHandleType1,
typename ArrayHandleType2,
typename ArrayHandleType3,
typename ArrayHandleType4>
VTKM_CONT_EXPORT
ArrayHandleCompositeVector(const ArrayHandleType1 &array1,
vtkm::IdComponent sourceComponent1,
const ArrayHandleType2 &array2,
vtkm::IdComponent sourceComponent2,
const ArrayHandleType3 &array3,
vtkm::IdComponent sourceComponent3,
const ArrayHandleType4 &array4,
vtkm::IdComponent sourceComponent4)
: Superclass(StorageType(
vtkm::internal::make_FunctionInterface<ValueType>(
array1, array2, array3, array4),
ComponentMapType(sourceComponent1,
sourceComponent2,
sourceComponent3,
sourceComponent4)))
{ }
};
/// \brief Get the type for an ArrayHandleCompositeVector
///
/// The ArrayHandleCompositeVector has a difficult template specification.
/// Use this helper template to covert a list of array handle types to a
/// composite vector of these array handles. Here is a simple example.
///
/// \code{.cpp}
/// typedef vtkm::cont::ArrayHandleCompositeVector<
/// vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
/// vtkm::cont::ArrayHandle<vtkm::FloatDefault> >::type OutArrayType;
/// OutArrayType outArray = vtkm::cont::make_ArrayHandleCompositeVector(a1,a2);
/// \endcode
///
template<typename ArrayHandleType1,
typename ArrayHandleType2 = void,
typename ArrayHandleType3 = void,
typename ArrayHandleType4 = void>
struct ArrayHandleCompositeVectorType
{
private:
typedef typename vtkm::VecTraits<typename ArrayHandleType1::ValueType>::ComponentType
ComponentType;
typedef vtkm::Vec<ComponentType,4> Signature(
ArrayHandleType1,ArrayHandleType2,ArrayHandleType3,ArrayHandleType4);
public:
typedef vtkm::cont::ArrayHandleCompositeVector<Signature> type;
};
template<typename ArrayHandleType1,
typename ArrayHandleType2,
typename ArrayHandleType3>
struct ArrayHandleCompositeVectorType<
ArrayHandleType1,ArrayHandleType2,ArrayHandleType3>
{
private:
typedef typename vtkm::VecTraits<typename ArrayHandleType1::ValueType>::ComponentType
ComponentType;
typedef vtkm::Vec<ComponentType,3> Signature(
ArrayHandleType1,ArrayHandleType2,ArrayHandleType3);
public:
typedef vtkm::cont::ArrayHandleCompositeVector<Signature> type;
};
template<typename ArrayHandleType1,
typename ArrayHandleType2>
struct ArrayHandleCompositeVectorType<ArrayHandleType1,ArrayHandleType2>
{
private:
typedef typename vtkm::VecTraits<typename ArrayHandleType1::ValueType>::ComponentType
ComponentType;
typedef vtkm::Vec<ComponentType,2> Signature(
ArrayHandleType1,ArrayHandleType2);
public:
typedef vtkm::cont::ArrayHandleCompositeVector<Signature> type;
};
template<typename ArrayHandleType1>
struct ArrayHandleCompositeVectorType<ArrayHandleType1>
{
private:
typedef typename vtkm::VecTraits<typename ArrayHandleType1::ValueType>::ComponentType
ComponentType;
typedef ComponentType Signature(ArrayHandleType1);
public:
typedef vtkm::cont::ArrayHandleCompositeVector<Signature> type;
};
/// Create a composite vector array from other arrays.
///
template<typename ValueType1, typename Storage1>
VTKM_CONT_EXPORT
typename ArrayHandleCompositeVectorType<
vtkm::cont::ArrayHandle<ValueType1,Storage1> >::type
make_ArrayHandleCompositeVector(
const vtkm::cont::ArrayHandle<ValueType1,Storage1> &array1,
vtkm::IdComponent sourceComponent1)
{
return typename ArrayHandleCompositeVectorType<
vtkm::cont::ArrayHandle<ValueType1,Storage1> >::type(array1,
sourceComponent1);
}
template<typename ValueType1, typename Storage1,
typename ValueType2, typename Storage2>
VTKM_CONT_EXPORT
typename ArrayHandleCompositeVectorType<
vtkm::cont::ArrayHandle<ValueType1,Storage1>,
vtkm::cont::ArrayHandle<ValueType2,Storage2> >::type
make_ArrayHandleCompositeVector(
const vtkm::cont::ArrayHandle<ValueType1,Storage1> &array1,
vtkm::IdComponent sourceComponent1,
const vtkm::cont::ArrayHandle<ValueType2,Storage2> &array2,
vtkm::IdComponent sourceComponent2)
{
return typename ArrayHandleCompositeVectorType<
vtkm::cont::ArrayHandle<ValueType1,Storage1>,
vtkm::cont::ArrayHandle<ValueType2,Storage2> >::type(array1,
sourceComponent1,
array2,
sourceComponent2);
}
template<typename ValueType1, typename Storage1,
typename ValueType2, typename Storage2,
typename ValueType3, typename Storage3>
VTKM_CONT_EXPORT
typename ArrayHandleCompositeVectorType<
vtkm::cont::ArrayHandle<ValueType1,Storage1>,
vtkm::cont::ArrayHandle<ValueType2,Storage2>,
vtkm::cont::ArrayHandle<ValueType3,Storage3> >::type
make_ArrayHandleCompositeVector(
const vtkm::cont::ArrayHandle<ValueType1,Storage1> &array1,
vtkm::IdComponent sourceComponent1,
const vtkm::cont::ArrayHandle<ValueType2,Storage2> &array2,
vtkm::IdComponent sourceComponent2,
const vtkm::cont::ArrayHandle<ValueType3,Storage3> &array3,
vtkm::IdComponent sourceComponent3)
{
return typename ArrayHandleCompositeVectorType<
vtkm::cont::ArrayHandle<ValueType1,Storage1>,
vtkm::cont::ArrayHandle<ValueType2,Storage2>,
vtkm::cont::ArrayHandle<ValueType3,Storage3> >::type(array1,
sourceComponent1,
array2,
sourceComponent2,
array3,
sourceComponent3);
}
template<typename ValueType1, typename Storage1,
typename ValueType2, typename Storage2,
typename ValueType3, typename Storage3,
typename ValueType4, typename Storage4>
VTKM_CONT_EXPORT
typename ArrayHandleCompositeVectorType<
vtkm::cont::ArrayHandle<ValueType1,Storage1>,
vtkm::cont::ArrayHandle<ValueType2,Storage2>,
vtkm::cont::ArrayHandle<ValueType3,Storage3>,
vtkm::cont::ArrayHandle<ValueType4,Storage4> >::type
make_ArrayHandleCompositeVector(
const vtkm::cont::ArrayHandle<ValueType1,Storage1> &array1,
vtkm::IdComponent sourceComponent1,
const vtkm::cont::ArrayHandle<ValueType2,Storage2> &array2,
vtkm::IdComponent sourceComponent2,
const vtkm::cont::ArrayHandle<ValueType3,Storage3> &array3,
vtkm::IdComponent sourceComponent3,
const vtkm::cont::ArrayHandle<ValueType4,Storage4> &array4,
vtkm::IdComponent sourceComponent4)
{
return typename ArrayHandleCompositeVectorType<
vtkm::cont::ArrayHandle<ValueType1,Storage1>,
vtkm::cont::ArrayHandle<ValueType2,Storage2>,
vtkm::cont::ArrayHandle<ValueType3,Storage3>,
vtkm::cont::ArrayHandle<ValueType4,Storage4> >::type(array1,
sourceComponent1,
array2,
sourceComponent2,
array3,
sourceComponent3,
array4,
sourceComponent4);
}
}
} // namespace vtkm::cont
#endif //vtk_m_ArrayHandleCompositeVector_h