Merge branch 'composite-vector-array' into dynamic-point-coordinates

This commit is contained in:
Kenneth Moreland 2014-05-14 14:26:23 -06:00
commit ff31afca3e
14 changed files with 2285 additions and 9 deletions

@ -21,6 +21,7 @@
include_directories(${Boost_INCLUDE_DIRS})
set(headers
Extent.h
ListTag.h
TypeListTag.h
Types.h

319
vtkm/Extent.h Normal file

@ -0,0 +1,319 @@
//============================================================================
// 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_Extent_h
#define vtk_m_Extent_h
#include <vtkm/Types.h>
namespace vtkm {
/// Extent stores the values for the index ranges for a structured grid array.
/// It does this through the minimum indices and the maximum indices.
///
template<int Dimensions>
struct Extent
{
vtkm::Tuple<vtkm::Id,Dimensions> Min;
vtkm::Tuple<vtkm::Id,Dimensions> Max;
VTKM_EXEC_CONT_EXPORT
Extent() : Min(0), Max(0) { }
VTKM_EXEC_CONT_EXPORT
Extent(const vtkm::Tuple<vtkm::Id,Dimensions> &min,
const vtkm::Tuple<vtkm::Id,Dimensions> &max)
: Min(min), Max(max) { }
VTKM_EXEC_CONT_EXPORT
Extent(const Extent<Dimensions> &other)
: Min(other.Min), Max(other.Max) { }
VTKM_EXEC_CONT_EXPORT
Extent<Dimensions> &operator=(const Extent<Dimensions> &rhs)
{
this->Min = rhs.Min;
this->Max = rhs.Max;
return *this;
}
} __attribute__ ((aligned(VTKM_SIZE_ID)));
/// This is the Extent to use for structured grids with 3 topological
/// dimensions.
///
typedef vtkm::Extent<3> Extent3 __attribute__ ((aligned(VTKM_SIZE_ID)));
/// This is the Extent to use for structured grids with 2 topological
/// dimensions.
///
typedef vtkm::Extent<2> Extent2 __attribute__ ((aligned(VTKM_SIZE_ID)));
/// Given an extent, returns the array dimensions for the points.
///
template<int Dimensions>
VTKM_EXEC_CONT_EXPORT
vtkm::Tuple<vtkm::Id,Dimensions>
ExtentPointDimensions(const vtkm::Extent<Dimensions> &extent)
{
return extent.Max - extent.Min + vtkm::Tuple<vtkm::Id,Dimensions>(1);
}
VTKM_EXEC_CONT_EXPORT
vtkm::Id3 ExtentPointDimensions(const vtkm::Extent3 &extent)
{
// Efficient implementation that uses no temporary Id3 to create dimensions.
return vtkm::Id3(extent.Max[0] - extent.Min[0] + 1,
extent.Max[1] - extent.Min[1] + 1,
extent.Max[2] - extent.Min[2] + 1);
}
VTKM_EXEC_CONT_EXPORT
vtkm::Id2 ExtentPointDimensions(const vtkm::Extent2 &extent)
{
// Efficient implementation that uses no temporary Id2 to create dimensions.
return vtkm::Id2(extent.Max[0] - extent.Min[0] + 1,
extent.Max[1] - extent.Min[1] + 1);
}
/// Given an extent, returns the array dimensions for the cells.
///
template<int Dimensions>
VTKM_EXEC_CONT_EXPORT
vtkm::Tuple<vtkm::Id,Dimensions>
ExtentCellDimensions(const vtkm::Extent<Dimensions> &extent)
{
return extent.Max - extent.Min;
}
/// Given an extent, returns the number of points in the structured mesh.
///
template<int Dimensions>
VTKM_EXEC_CONT_EXPORT
vtkm::Id ExtentNumberOfPoints(const vtkm::Extent<Dimensions> &extent)
{
return internal::product_vector<Dimensions>()(
vtkm::ExtentPointDimensions(extent));
}
template<>
VTKM_EXEC_CONT_EXPORT
vtkm::Id ExtentNumberOfPoints(const vtkm::Extent3 &extent)
{
// Efficient implementation that uses no temporary Id3.
return (
(extent.Max[0] - extent.Min[0] + 1)
* (extent.Max[1] - extent.Min[1] + 1)
* (extent.Max[2] - extent.Min[2] + 1));
}
template<>
VTKM_EXEC_CONT_EXPORT
vtkm::Id ExtentNumberOfPoints(const vtkm::Extent2 &extent)
{
// Efficient implementation that uses no temporary Id2.
return (
(extent.Max[0] - extent.Min[0] + 1)
* (extent.Max[1] - extent.Min[1] + 1));
}
/// Given an extent, returns the number of cells in the structured mesh.
///
template<int Dimensions>
VTKM_EXEC_CONT_EXPORT
vtkm::Id ExtentNumberOfCells(const vtkm::Extent<Dimensions> &extent)
{
return internal::product_vector<Dimensions>()(
vtkm::ExtentCellDimensions(extent));
}
template<>
VTKM_EXEC_CONT_EXPORT
vtkm::Id ExtentNumberOfCells(const vtkm::Extent3 &extent)
{
// Efficient implementation that uses no temporary Id3.
return (
(extent.Max[0] - extent.Min[0])
* (extent.Max[1] - extent.Min[1])
* (extent.Max[2] - extent.Min[2]));
}
template<>
VTKM_EXEC_CONT_EXPORT
vtkm::Id ExtentNumberOfCells(const vtkm::Extent2 &extent)
{
// Efficient implementation that uses no temporary Id2.
return (
(extent.Max[0] - extent.Min[0])
* (extent.Max[1] - extent.Min[1]));
}
/// Elements in structured grids have a single index with 0 being the entry at
/// the minimum extent in every direction and then increasing first in the r
/// then the s direction and so on. This method converts a flat index to the
/// topological coordinates (e.g. r,s,t for 3d topologies).
///
template<int Dimensions>
VTKM_EXEC_CONT_EXPORT
vtkm::Tuple<vtkm::Id,Dimensions>
ExtentPointFlatIndexToTopologyIndex(vtkm::Id index,
const vtkm::Extent<Dimensions> &extent)
{
const vtkm::Tuple<vtkm::Id,Dimensions> dims =
vtkm::ExtentPointDimensions(extent);
vtkm::Tuple<vtkm::Id,Dimensions> ijkIndex;
vtkm::Id indexOnDim = index;
for (int dimIndex = 0; dimIndex < Dimensions-1; dimIndex++)
{
ijkIndex[dimIndex] = indexOnDim % dims[dimIndex] + extent.Min[dimIndex];
indexOnDim /= dims[dimIndex];
}
// Special case for last dimension to remove some unneeded operations
ijkIndex[Dimensions-1] = indexOnDim + extent.Min[Dimensions-1];
return ijkIndex;
}
VTKM_EXEC_CONT_EXPORT
vtkm::Id3 ExtentPointFlatIndexToTopologyIndex(vtkm::Id index,
const vtkm::Extent3 &extent)
{
// Efficient implementation that tries to reduce the number of temporary
// variables.
const vtkm::Id3 dims = vtkm::ExtentPointDimensions(extent);
return vtkm::Id3((index % dims[0]) + extent.Min[0],
((index / dims[0]) % dims[1]) + extent.Min[1],
((index / (dims[0]*dims[1]))) + extent.Min[2]);
}
VTKM_EXEC_CONT_EXPORT
vtkm::Id2 ExtentPointFlatIndexToTopologyIndex(vtkm::Id index,
const vtkm::Extent2 &extent)
{
// Efficient implementation that tries to reduce the number of temporary
// variables.
const vtkm::Id2 dims = vtkm::ExtentPointDimensions(extent);
return vtkm::Id2((index % dims[0]) + extent.Min[0],
(index / dims[0]) + extent.Min[1]);
}
/// Elements in structured grids have a single index with 0 being the entry at
/// the minimum extent in every direction and then increasing first in the r
/// then the s direction and so on. This method converts a flat index to the
/// topological coordinates (e.g. r,s,t for 3d topologies).
///
template<int Dimensions>
VTKM_EXEC_CONT_EXPORT
vtkm::Tuple<vtkm::Id,Dimensions>
ExtentCellFlatIndexToTopologyIndex(vtkm::Id index,
const vtkm::Extent<Dimensions> &extent)
{
const vtkm::Tuple<vtkm::Id,Dimensions> dims =
vtkm::ExtentCellDimensions(extent);
vtkm::Tuple<vtkm::Id,Dimensions> ijkIndex;
vtkm::Id indexOnDim = index;
for (int dimIndex = 0; dimIndex < Dimensions-1; dimIndex++)
{
ijkIndex[dimIndex] = indexOnDim % dims[dimIndex] + extent.Min[dimIndex];
indexOnDim /= dims[dimIndex];
}
// Special case for last dimension to remove some unneeded operations
ijkIndex[Dimensions-1] = indexOnDim + extent.Min[Dimensions-1];
return ijkIndex;
}
VTKM_EXEC_CONT_EXPORT
vtkm::Id3 ExtentCellFlatIndexToTopologyIndex(vtkm::Id index,
const vtkm::Extent3 &extent)
{
// Efficient implementation that tries to reduce the number of temporary
// variables.
const vtkm::Id3 dims = vtkm::ExtentCellDimensions(extent);
return vtkm::Id3((index % dims[0]) + extent.Min[0],
((index / dims[0]) % dims[1]) + extent.Min[1],
((index / (dims[0]*dims[1]))) + extent.Min[2]);
}
VTKM_EXEC_CONT_EXPORT
vtkm::Id2 ExtentCellFlatIndexToTopologyIndex(vtkm::Id index,
const vtkm::Extent2 &extent)
{
// Efficient implementation that tries to reduce the number of temporary
// variables.
const vtkm::Id2 dims = vtkm::ExtentCellDimensions(extent);
return vtkm::Id2((index % dims[0]) + extent.Min[0],
(index / dims[0]) + extent.Min[1]);
}
/// Elements in structured grids have a single index with 0 being the entry at
/// the minimum extent in every direction and then increasing first in the r
/// then the s direction and so on. This method converts topological
/// coordinates to a flat index.
///
template<int Dimensions>
VTKM_EXEC_CONT_EXPORT
vtkm::Id
ExtentPointTopologyIndexToFlatIndex(const vtkm::Tuple<vtkm::Id,Dimensions> &ijk,
const vtkm::Extent<Dimensions> &extent)
{
const vtkm::Tuple<vtkm::Id,Dimensions> dims = ExtentPointDimensions(extent);
const vtkm::Tuple<vtkm::Id,Dimensions> deltas = ijk - extent.Min;
vtkm::Id flatIndex = deltas[Dimensions-1];
for (int dimIndex = Dimensions-2; dimIndex >= 0; dimIndex--)
{
flatIndex = flatIndex*dims[dimIndex] + deltas[dimIndex];
}
return flatIndex;
}
/// Elements in structured grids have a single index with 0 being the entry at
/// the minimum extent in every direction and then increasing first in the r
/// then the s direction and so on. This method converts topological
/// coordinates to a flat index.
///
template<int Dimensions>
VTKM_EXEC_CONT_EXPORT
vtkm::Id
ExtentCellTopologyIndexToFlatIndex(const vtkm::Tuple<vtkm::Id,Dimensions> &ijk,
const vtkm::Extent<Dimensions> &extent)
{
const vtkm::Tuple<vtkm::Id,Dimensions> dims = ExtentCellDimensions(extent);
const vtkm::Tuple<vtkm::Id,Dimensions> deltas = ijk - extent.Min;
vtkm::Id flatIndex = deltas[Dimensions-1];
for (int dimIndex = Dimensions-2; dimIndex >= 0; dimIndex--)
{
flatIndex = flatIndex*dims[dimIndex] + deltas[dimIndex];
}
return flatIndex;
}
/// Given a cell index, returns the index to the first point incident on that
/// cell.
///
template<int Dimensions>
VTKM_EXEC_CONT_EXPORT
vtkm::Id ExtentFirstPointOnCell(vtkm::Id cellIndex,
const Extent<Dimensions> &extent)
{
return ExtentPointTopologyIndexToFlatIndex(
ExtentCellFlatIndexToTopologyIndex(cellIndex,extent),
extent);
}
} // namespace vtkm
#endif //vtk_m_Extent_h

@ -241,6 +241,116 @@ struct copy_vector<3>
}
};
template<int Size>
struct sum_vector
{
template<typename T>
VTKM_EXEC_CONT_EXPORT
typename T::ComponentType operator()(const T &x)
{
return sum_vector<Size-1>()(x) + x[Size-1];
}
};
template<>
struct sum_vector<1>
{
template<typename T>
VTKM_EXEC_CONT_EXPORT
typename T::ComponentType operator()(const T &x)
{
return x[0];
}
};
template<>
struct sum_vector<2>
{
template<typename T>
VTKM_EXEC_CONT_EXPORT
typename T::ComponentType operator()(const T &x)
{
return x[0] + x[1];
}
};
template<>
struct sum_vector<3>
{
template<typename T>
VTKM_EXEC_CONT_EXPORT
typename T::ComponentType operator()(const T &x)
{
return x[0] + x[1] + x[2];
}
};
template<>
struct sum_vector<4>
{
template<typename T>
VTKM_EXEC_CONT_EXPORT
typename T::ComponentType operator()(const T &x)
{
return x[0] + x[1] + x[2] + x[3];
}
};
template<int Size>
struct product_vector
{
template<typename T>
VTKM_EXEC_CONT_EXPORT
typename T::ComponentType operator()(const T &x)
{
return product_vector<Size-1>()(x) * x[Size-1];
}
};
template<>
struct product_vector<1>
{
template<typename T>
VTKM_EXEC_CONT_EXPORT
typename T::ComponentType operator()(const T &x)
{
return x[0];
}
};
template<>
struct product_vector<2>
{
template<typename T>
VTKM_EXEC_CONT_EXPORT
typename T::ComponentType operator()(const T &x)
{
return x[0] * x[1];
}
};
template<>
struct product_vector<3>
{
template<typename T>
VTKM_EXEC_CONT_EXPORT
typename T::ComponentType operator()(const T &x)
{
return x[0] * x[1] * x[2];
}
};
template<>
struct product_vector<4>
{
template<typename T>
VTKM_EXEC_CONT_EXPORT
typename T::ComponentType operator()(const T &x)
{
return x[0] * x[1] * x[2] * x[3];
}
};
} // namespace internal

@ -0,0 +1,716 @@
//============================================================================
// 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/VectorTraits.h>
#include <vtkm/internal/FunctionInterface.h>
#include <boost/static_assert.hpp>
namespace vtkm {
namespace cont {
namespace internal {
namespace detail {
template<typename ValueType>
struct CompositeVectorSwizzleFunctor
{
static const int NUM_COMPONENTS =
vtkm::VectorTraits<ValueType>::NUM_COMPONENTS;
typedef vtkm::Tuple<int, 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::VectorTraits<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::VectorTraits<T1>::GetComponent(p1, this->SourceComponents[0]),
vtkm::VectorTraits<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::VectorTraits<T1>::GetComponent(p1, this->SourceComponents[0]),
vtkm::VectorTraits<T2>::GetComponent(p2, this->SourceComponents[1]),
vtkm::VectorTraits<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::VectorTraits<T1>::GetComponent(p1, this->SourceComponents[0]),
vtkm::VectorTraits<T2>::GetComponent(p2, this->SourceComponents[1]),
vtkm::VectorTraits<T3>::GetComponent(p3, this->SourceComponents[2]),
vtkm::VectorTraits<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>
struct ReturnType {
typedef typename ArrayHandleType::template ExecutionTypes<
DeviceAdapterTag>::PortalConst type;
};
template<typename ArrayHandleType>
VTKM_CONT_EXPORT
typename ReturnType<ArrayHandleType>::type
operator()(const ArrayHandleType &array) const {
return array.PrepareForInput(DeviceAdapterTag());
}
};
struct CheckArraySizeFunctor {
vtkm::Id ExpectedSize;
CheckArraySizeFunctor(vtkm::Id expectedSize) : ExpectedSize(expectedSize) { }
template<typename T>
void operator()(const T &a) const {
if (a.GetNumberOfValues() != this->ExpectedSize)
{
throw vtkm::cont::ErrorControlBadValue(
"All input arrays to ArrayHandleCompositeVector must be the same size.");
}
}
};
} // 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::Tuple<int, PortalTypes::ARITY> ComponentMapType;
public:
typedef typename PortalTypes::ResultType ValueType;
static const int NUM_COMPONENTS =
vtkm::VectorTraits<ValueType>::NUM_COMPONENTS;
BOOST_STATIC_ASSERT(NUM_COMPONENTS == PortalTypes::ARITY);
VTKM_EXEC_CONT_EXPORT
ArrayPortalCompositeVector() { }
VTKM_CONT_EXPORT
ArrayPortalCompositeVector(
const PortalTypes portals,
vtkm::Tuple<int, 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 int NUM_COMPONENTS =
vtkm::VectorTraits<ValueType>::NUM_COMPONENTS;
typedef vtkm::Tuple<int, 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.
BOOST_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("Not implemented.");
}
VTKM_CONT_EXPORT
void Set(vtkm::Id vtkmNotUsed(index), ValueType vtkmNotUsed(value)) {
throw vtkm::cont::ErrorControlInternal("Not implemented.");
}
// Not a viable type, but there is no implementation.
typedef ValueType *IteratorType;
VTKM_CONT_EXPORT
IteratorType GetIteratorBegin() const {
throw vtkm::cont::ErrorControlInternal("Not implemented.");
}
VTKM_CONT_EXPORT
IteratorType GetIteratorEnd() const {
throw vtkm::cont::ErrorControlInternal("Not implemented.");
}
private:
vtkm::Id NumberOfValues;
};
template<typename SignatureWithArrays>
struct ArrayContainerControlTagCompositeVector { };
/// A convenience class that provides a typedef to the appropriate tag for
/// a counting array container.
template<typename SignatureWithArrays>
struct ArrayHandleCompositeVectorTraits
{
typedef vtkm::cont::internal::ArrayContainerControlTagCompositeVector<
SignatureWithArrays> Tag;
typedef typename vtkm::internal::FunctionInterface<SignatureWithArrays>::ResultType
ValueType;
typedef vtkm::cont::internal::ArrayContainerControl<
ValueType, Tag> ContainerType;
};
// 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 ArrayContainerControl<
typename ArrayHandleCompositeVectorTraits<SignatureWithArrays>::ValueType,
vtkm::cont::internal::ArrayContainerControlTagCompositeVector<SignatureWithArrays> >
{
typedef vtkm::internal::FunctionInterface<SignatureWithArrays>
FunctionInterfaceWithArrays;
static const int NUM_COMPONENTS = FunctionInterfaceWithArrays::ARITY;
typedef vtkm::Tuple<int, NUM_COMPONENTS> ComponentMapType;
public:
typedef ArrayPortalCompositeVectorCont<SignatureWithArrays> PortalType;
typedef PortalType PortalConstType;
typedef typename PortalType::ValueType ValueType;
VTKM_CONT_EXPORT
ArrayContainerControl() : Valid(false) { }
VTKM_CONT_EXPORT
ArrayContainerControl(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 control array "
"container should never have been called. The allocate is generally "
"only called by the execution array manager, and the array transfer "
"for the transform container 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::ArrayContainerControlTagCompositeVector<SignatureWithArrays>,
DeviceAdapterTag>
{
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
typedef typename ArrayHandleCompositeVectorTraits<SignatureWithArrays>::ContainerType
ContainerType;
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 ContainerType::PortalType PortalControl;
typedef typename ContainerType::PortalConstType PortalConstControl;
typedef ArrayPortalCompositeVector<SignatureWithPortals> PortalExecution;
typedef ArrayPortalCompositeVector<SignatureWithPortals> PortalConstExecution;
VTKM_CONT_EXPORT
ArrayTransfer() : ContainerValid(false) { }
VTKM_CONT_EXPORT
vtkm::Id GetNumberOfValues() const {
VTKM_ASSERT_CONT(this->ContainerValid);
return this->Container.GetNumberOfValues();
}
VTKM_CONT_EXPORT
void LoadDataForInput(PortalConstControl vtkmNotUsed(contPortal))
{
throw vtkm::cont::ErrorControlInternal(
"ArrayHandleCompositeVector in a bad state. "
"There must be a UserArray set, but how did that happen?");
}
VTKM_CONT_EXPORT
void LoadDataForInput(const ContainerType &controlArray)
{
this->Container = controlArray;
this->ContainerValid = true;
}
VTKM_CONT_EXPORT
void LoadDataForInPlace(ContainerType &vtkmNotUsed(controlArray))
{
throw vtkm::cont::ErrorControlBadValue(
"Composite vector arrays cannot be used for output or in place.");
}
VTKM_CONT_EXPORT
void AllocateArrayForOutput(ContainerType &vtkmNotUsed(controlArray),
vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorControlBadValue(
"Composite vector arrays cannot be used for output.");
}
VTKM_CONT_EXPORT
void RetrieveOutputData(ContainerType &vtkmNotUsed(controlArray)) const
{
throw vtkm::cont::ErrorControlBadValue(
"Composite vector arrays cannot be used for output.");
}
template<typename IteratorTypeControl>
VTKM_CONT_EXPORT
void CopyInto(IteratorTypeControl vtkmNotUsed(dest)) const
{
throw vtkm::cont::ErrorControlInternal(
"CopyInto not implemented for composite vector arrays.");
}
VTKM_CONT_EXPORT
void Shrink(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorControlBadValue(
"Composite vector arrays cannot be resized.");
}
VTKM_CONT_EXPORT
PortalExecution GetPortalExecution()
{
throw vtkm::cont::ErrorControlBadValue(
"Composite vector arrays are read-only. (Get the const portal.)");
}
VTKM_CONT_EXPORT
PortalConstExecution GetPortalConstExecution() const
{
VTKM_ASSERT_CONT(this->ContainerValid);
return
PortalConstExecution(
this->Container.GetArrays().StaticTransformCont(
detail::CompositeVectorArrayToPortalExec<DeviceAdapterTag>()),
this->Container.GetSourceComponents());
}
VTKM_CONT_EXPORT
void ReleaseResources() {
this->Container.ReleaseResources();
}
private:
bool ContainerValid;
ContainerType Container;
};
} // 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 vtkm::cont::ArrayHandle<
typename internal::ArrayHandleCompositeVectorTraits<Signature>::ValueType,
typename internal::ArrayHandleCompositeVectorTraits<Signature>::Tag>
{
typedef typename internal::ArrayHandleCompositeVectorTraits<Signature>::ContainerType
ArrayContainerControlType;
typedef typename internal::ArrayPortalCompositeVectorCont<Signature>::ComponentMapType
ComponentMapType;
public:
typedef vtkm::cont::ArrayHandle<
typename internal::ArrayHandleCompositeVectorTraits<Signature>::ValueType,
typename internal::ArrayHandleCompositeVectorTraits<Signature>::Tag>
Superclass;
typedef typename Superclass::ValueType ValueType;
VTKM_CONT_EXPORT
ArrayHandleCompositeVector() : Superclass() { }
VTKM_CONT_EXPORT
ArrayHandleCompositeVector(
const vtkm::internal::FunctionInterface<Signature> &arrays,
const ComponentMapType &sourceComponents)
: Superclass(ArrayContainerControlType(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,
int sourceComponent1)
: Superclass(ArrayContainerControlType(
vtkm::internal::make_FunctionInterface<ValueType>(array1),
ComponentMapType(sourceComponent1)))
{ }
template<typename ArrayHandleType1,
typename ArrayHandleType2>
VTKM_CONT_EXPORT
ArrayHandleCompositeVector(const ArrayHandleType1 &array1,
int sourceComponent1,
const ArrayHandleType2 &array2,
int sourceComponent2)
: Superclass(ArrayContainerControlType(
vtkm::internal::make_FunctionInterface<ValueType>(
array1, array2),
ComponentMapType(sourceComponent1,
sourceComponent2)))
{ }
template<typename ArrayHandleType1,
typename ArrayHandleType2,
typename ArrayHandleType3>
VTKM_CONT_EXPORT
ArrayHandleCompositeVector(const ArrayHandleType1 &array1,
int sourceComponent1,
const ArrayHandleType2 &array2,
int sourceComponent2,
const ArrayHandleType3 &array3,
int sourceComponent3)
: Superclass(ArrayContainerControlType(
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,
int sourceComponent1,
const ArrayHandleType2 &array2,
int sourceComponent2,
const ArrayHandleType3 &array3,
int sourceComponent3,
const ArrayHandleType4 &array4,
int sourceComponent4)
: Superclass(ArrayContainerControlType(
vtkm::internal::make_FunctionInterface<ValueType>(
array1, array2, array3, array4),
ComponentMapType(sourceComponent1,
sourceComponent2,
sourceComponent3,
sourceComponent4)))
{ }
};
/// Create a composite vector array from other arrays.
///
template<typename ValueType1, typename Container1>
VTKM_CONT_EXPORT
ArrayHandleCompositeVector<
typename vtkm::VectorTraits<ValueType1>::ComponentType(
vtkm::cont::ArrayHandle<ValueType1,Container1>)>
make_ArrayHandleCompositeVector(
const vtkm::cont::ArrayHandle<ValueType1,Container1> &array1,
int sourceComponent1)
{
return ArrayHandleCompositeVector<
typename vtkm::VectorTraits<ValueType1>::ComponentType(
vtkm::cont::ArrayHandle<ValueType1,Container1>)>(array1,
sourceComponent1);
}
template<typename ValueType1, typename Container1,
typename ValueType2, typename Container2>
VTKM_CONT_EXPORT
ArrayHandleCompositeVector<
vtkm::Tuple<typename vtkm::VectorTraits<ValueType1>::ComponentType,2>(
vtkm::cont::ArrayHandle<ValueType1,Container1>,
vtkm::cont::ArrayHandle<ValueType2,Container2>)>
make_ArrayHandleCompositeVector(
const vtkm::cont::ArrayHandle<ValueType1,Container1> &array1,
int sourceComponent1,
const vtkm::cont::ArrayHandle<ValueType2,Container2> &array2,
int sourceComponent2)
{
return ArrayHandleCompositeVector<
vtkm::Tuple<typename vtkm::VectorTraits<ValueType1>::ComponentType,2>(
vtkm::cont::ArrayHandle<ValueType1,Container1>,
vtkm::cont::ArrayHandle<ValueType2,Container2>)>(array1,
sourceComponent1,
array2,
sourceComponent2);
}
template<typename ValueType1, typename Container1,
typename ValueType2, typename Container2,
typename ValueType3, typename Container3>
VTKM_CONT_EXPORT
ArrayHandleCompositeVector<
vtkm::Tuple<typename vtkm::VectorTraits<ValueType1>::ComponentType,3>(
vtkm::cont::ArrayHandle<ValueType1,Container1>,
vtkm::cont::ArrayHandle<ValueType2,Container2>,
vtkm::cont::ArrayHandle<ValueType3,Container3>)>
make_ArrayHandleCompositeVector(
const vtkm::cont::ArrayHandle<ValueType1,Container1> &array1,
int sourceComponent1,
const vtkm::cont::ArrayHandle<ValueType2,Container2> &array2,
int sourceComponent2,
const vtkm::cont::ArrayHandle<ValueType3,Container3> &array3,
int sourceComponent3)
{
return ArrayHandleCompositeVector<
vtkm::Tuple<typename vtkm::VectorTraits<ValueType1>::ComponentType,3>(
vtkm::cont::ArrayHandle<ValueType1,Container1>,
vtkm::cont::ArrayHandle<ValueType2,Container2>,
vtkm::cont::ArrayHandle<ValueType3,Container3>)>(array1,
sourceComponent1,
array2,
sourceComponent2,
array3,
sourceComponent3);
}
template<typename ValueType1, typename Container1,
typename ValueType2, typename Container2,
typename ValueType3, typename Container3,
typename ValueType4, typename Container4>
VTKM_CONT_EXPORT
ArrayHandleCompositeVector<
vtkm::Tuple<typename vtkm::VectorTraits<ValueType1>::ComponentType,4>(
vtkm::cont::ArrayHandle<ValueType1,Container1>,
vtkm::cont::ArrayHandle<ValueType2,Container2>,
vtkm::cont::ArrayHandle<ValueType3,Container3>,
vtkm::cont::ArrayHandle<ValueType4,Container4>)>
make_ArrayHandleCompositeVector(
const vtkm::cont::ArrayHandle<ValueType1,Container1> &array1,
int sourceComponent1,
const vtkm::cont::ArrayHandle<ValueType2,Container2> &array2,
int sourceComponent2,
const vtkm::cont::ArrayHandle<ValueType3,Container3> &array3,
int sourceComponent3,
const vtkm::cont::ArrayHandle<ValueType4,Container4> &array4,
int sourceComponent4)
{
return ArrayHandleCompositeVector<
vtkm::Tuple<typename vtkm::VectorTraits<ValueType1>::ComponentType,4>(
vtkm::cont::ArrayHandle<ValueType1,Container1>,
vtkm::cont::ArrayHandle<ValueType2,Container2>,
vtkm::cont::ArrayHandle<ValueType3,Container3>,
vtkm::cont::ArrayHandle<ValueType4,Container4>)>(array1,
sourceComponent1,
array2,
sourceComponent2,
array3,
sourceComponent3,
array4,
sourceComponent4);
}
}
} // namespace vtkm::cont
#endif //vtk_m_ArrayHandleCompositeVector_h

@ -118,11 +118,13 @@ class ArrayHandleCounting
> Superclass;
public:
VTKM_CONT_EXPORT
ArrayHandleCounting(CountingValueType startingValue, vtkm::Id length)
:Superclass(typename Superclass::PortalConstControl(startingValue, length))
{
}
VTKM_CONT_EXPORT
ArrayHandleCounting():Superclass() {}
};

@ -0,0 +1,158 @@
//============================================================================
// 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_ArrayHandleUniformPointCoordinates_h
#define vtk_m_cont_ArrayHandleUniformPointCoordinates_h
#include <vtkm/Extent.h>
#include <vtkm/cont/ArrayContainerControlImplicit.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/internal/IteratorFromArrayPortal.h>
namespace vtkm {
namespace cont {
namespace internal {
/// \brief An implicit array port that computes point coordinates for a uniform
/// grid.
///
class ArrayPortalUniformPointCoordinates
{
public:
typedef vtkm::Vector3 ValueType;
VTKM_EXEC_CONT_EXPORT
ArrayPortalUniformPointCoordinates() : NumberOfValues(0) { }
VTKM_EXEC_CONT_EXPORT
ArrayPortalUniformPointCoordinates(vtkm::Extent3 extent,
vtkm::Vector3 origin,
vtkm::Vector3 spacing)
: Extent(extent),
Dimensions(vtkm::ExtentPointDimensions(extent)),
NumberOfValues(vtkm::ExtentNumberOfPoints(extent)),
Origin(origin),
Spacing(spacing)
{ }
VTKM_EXEC_CONT_EXPORT
ArrayPortalUniformPointCoordinates(
const ArrayPortalUniformPointCoordinates &src)
: Extent(src.Extent),
Dimensions(src.Dimensions),
NumberOfValues(src.NumberOfValues),
Origin(src.Origin),
Spacing(src.Spacing)
{ }
VTKM_EXEC_CONT_EXPORT
ArrayPortalUniformPointCoordinates &
operator=(const ArrayPortalUniformPointCoordinates &src)
{
this->Extent = src.Extent;
this->Dimensions = src.Dimensions;
this->NumberOfValues = src.NumberOfValues;
this->Origin = src.Origin;
this->Spacing = src.Spacing;
return *this;
}
VTKM_EXEC_CONT_EXPORT
vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; }
VTKM_EXEC_CONT_EXPORT
vtkm::Vector3 Get(vtkm::Id index) const {
return this->GetCoordinatesForTopologyIndex(
vtkm::ExtentPointFlatIndexToTopologyIndex(index, this->Extent));
}
VTKM_EXEC_CONT_EXPORT
vtkm::Id3 GetRange3() const { return this->Dimensions; }
VTKM_EXEC_CONT_EXPORT
vtkm::Vector3 Get(vtkm::Id3 index) const {
return this->GetCoordinatesForTopologyIndex(index + this->Extent.Min);
}
typedef vtkm::cont::internal::IteratorFromArrayPortal<
ArrayPortalUniformPointCoordinates> IteratorType;
VTKM_CONT_EXPORT
IteratorType GetIteratorBegin() const {
return IteratorType(*this);
}
VTKM_CONT_EXPORT
IteratorType GetIteratorEnd() const {
return IteratorType(*this, this->NumberOfValues);
}
private:
vtkm::Extent3 Extent;
vtkm::Id3 Dimensions;
vtkm::Id NumberOfValues;
vtkm::Vector3 Origin;
vtkm::Vector3 Spacing;
VTKM_EXEC_CONT_EXPORT
vtkm::Vector3 GetCoordinatesForTopologyIndex(vtkm::Id3 ijk) const {
return vtkm::Vector3(this->Origin[0] + this->Spacing[0]*ijk[0],
this->Origin[1] + this->Spacing[1]*ijk[1],
this->Origin[2] + this->Spacing[2]*ijk[2]);
}
};
} // namespace internal
/// ArrayHandleUniformPointCoordinates is a specialization of ArrayHandle. It
/// contains the information necessary to compute the point coordinates in a
/// uniform orthogonal grid (extent, origin, and spacing) and implicitly
/// computes these coordinates in its array portal.
///
class ArrayHandleUniformPointCoordinates
: public vtkm::cont::ArrayHandle<
vtkm::Vector3,
vtkm::cont::ArrayContainerControlTagImplicit<
internal::ArrayPortalUniformPointCoordinates> >
{
typedef vtkm::cont::ArrayHandle<
vtkm::Vector3,
vtkm::cont::ArrayContainerControlTagImplicit<
internal::ArrayPortalUniformPointCoordinates> > Superclass;
public:
VTKM_CONT_EXPORT
ArrayHandleUniformPointCoordinates() : Superclass() { }
VTKM_CONT_EXPORT
ArrayHandleUniformPointCoordinates(vtkm::Extent3 extent,
vtkm::Vector3 origin,
vtkm::Vector3 spacing)
: Superclass(
internal::ArrayPortalUniformPointCoordinates(extent, origin, spacing))
{ }
};
}
} // namespace vtkm::cont
#endif //vtk_+m_cont_ArrayHandleUniformPointCoordinates_h

@ -25,7 +25,9 @@ set(headers
ArrayContainerControlBasic.h
ArrayContainerControlImplicit.h
ArrayHandle.h
ArrayHandleCompositeVector.h
ArrayHandleCounting.h
ArrayHandleUniformPointCoordinates.h
ArrayPortal.h
Assert.h
ContainerListTag.h

@ -29,7 +29,9 @@ set(unit_tests
UnitTestArrayContainerControlBasic.cxx
UnitTestArrayContainerControlImplicit.cxx
UnitTestArrayHandle.cxx
UnitTestArrayHandleCompositeVector.cxx
UnitTestArrayHandleCounting.cxx
UnitTestArrayHandleUniformPointCoordinates.cxx
UnitTestContainerListTag.cxx
UnitTestContTesting.cxx
UnitTestDeviceAdapterAlgorithmDependency.cxx

@ -0,0 +1,313 @@
//============================================================================
// 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.
//============================================================================
// Make sure ArrayHandleCompositeVector does not rely on default container or
// device adapter.
#define VTKM_ARRAY_CONTAINER_CONTROL VTKM_ARRAY_CONTAINER_CONTROL_ERROR
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_ERROR
#include <vtkm/cont/ArrayHandleCompositeVector.h>
#include <vtkm/VectorTraits.h>
#include <vtkm/cont/ArrayContainerControlBasic.h>
#include <vtkm/cont/DeviceAdapterSerial.h>
#include <vtkm/cont/testing/Testing.h>
#include <vector>
namespace {
const vtkm::Id ARRAY_SIZE = 10;
typedef vtkm::cont::ArrayContainerControlTagBasic Container;
vtkm::Scalar TestValue(vtkm::Id index, int inComponentIndex, int inArrayId)
{
return index + vtkm::Scalar(0.1)*inComponentIndex + vtkm::Scalar(0.01)*inArrayId;
}
template<typename ValueType>
vtkm::cont::ArrayHandle<ValueType, Container>
MakeInputArray(int arrayId)
{
typedef vtkm::VectorTraits<ValueType> VTraits;
// Create a buffer with valid test values.
ValueType buffer[ARRAY_SIZE];
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
{
for (int componentIndex = 0;
componentIndex < VTraits::NUM_COMPONENTS;
componentIndex++)
{
VTraits::SetComponent(buffer[index],
componentIndex,
TestValue(index, componentIndex, arrayId));
}
}
// Make an array handle that points to this buffer.
typedef vtkm::cont::ArrayHandle<ValueType, Container> ArrayHandleType;
ArrayHandleType bufferHandle =
vtkm::cont::make_ArrayHandle(buffer, ARRAY_SIZE, Container());
// When this function returns, the array is going to go out of scope, which
// will invalidate the array handle we just created. So copy to a new buffer
// that will stick around after we return.
ArrayHandleType copyHandle;
vtkm::cont::DeviceAdapterAlgorithm<vtkm::cont::DeviceAdapterTagSerial>::Copy(
bufferHandle, copyHandle);
return copyHandle;
}
template<typename ValueType, typename C>
void CheckArray(const vtkm::cont::ArrayHandle<ValueType,C> &outArray,
const int *inComponents,
const int *inArrayIds)
{
// ArrayHandleCompositeVector currently does not implement the ability to
// get to values on the control side, so copy to an array that is accessible.
typedef vtkm::cont::ArrayHandle<ValueType, Container> ArrayHandleType;
ArrayHandleType arrayCopy;
vtkm::cont::DeviceAdapterAlgorithm<vtkm::cont::DeviceAdapterTagSerial>::Copy(
outArray, arrayCopy);
typename ArrayHandleType::PortalConstControl portal =
arrayCopy.GetPortalConstControl();
typedef vtkm::VectorTraits<ValueType> VTraits;
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
{
ValueType retreivedValue = portal.Get(index);
for (int componentIndex = 0;
componentIndex < VTraits::NUM_COMPONENTS;
componentIndex++)
{
vtkm::Scalar retrievedComponent =
VTraits::GetComponent(retreivedValue, componentIndex);
vtkm::Scalar expectedComponent = TestValue(index,
inComponents[componentIndex],
inArrayIds[componentIndex]);
VTKM_TEST_ASSERT(retrievedComponent == expectedComponent,
"Got bad value.");
}
}
}
template<int inComponents>
void TryScalarArray()
{
std::cout << "Creating a scalar array from one of "
<< inComponents << " components." << std::endl;
typedef vtkm::Tuple<vtkm::Scalar,inComponents> InValueType;
typedef vtkm::cont::ArrayHandle<InValueType, Container> InArrayType;
int inArrayId = 0;
InArrayType inArray = MakeInputArray<InValueType>(inArrayId);
typedef vtkm::cont::ArrayHandleCompositeVector<vtkm::Scalar(InArrayType)>
OutArrayType;
for (int inComponentIndex = 0;
inComponentIndex < inComponents;
inComponentIndex++)
{
OutArrayType outArray =
vtkm::cont::make_ArrayHandleCompositeVector(inArray, inComponentIndex);
CheckArray(outArray, &inComponentIndex, &inArrayId);
}
}
template<typename T1, typename T2, typename T3, typename T4>
void TryVector4(vtkm::cont::ArrayHandle<T1,Container> array1,
vtkm::cont::ArrayHandle<T2,Container> array2,
vtkm::cont::ArrayHandle<T3,Container> array3,
vtkm::cont::ArrayHandle<T4,Container> array4)
{
int arrayIds[4] = {0, 1, 2, 3};
int inComponents[4];
for (inComponents[0] = 0;
inComponents[0] < vtkm::VectorTraits<T1>::NUM_COMPONENTS;
inComponents[0]++)
{
for (inComponents[1] = 0;
inComponents[1] < vtkm::VectorTraits<T2>::NUM_COMPONENTS;
inComponents[1]++)
{
for (inComponents[2] = 0;
inComponents[2] < vtkm::VectorTraits<T3>::NUM_COMPONENTS;
inComponents[2]++)
{
for (inComponents[3] = 0;
inComponents[3] < vtkm::VectorTraits<T4>::NUM_COMPONENTS;
inComponents[3]++)
{
CheckArray(
vtkm::cont::make_ArrayHandleCompositeVector(
array1, inComponents[0],
array2, inComponents[1],
array3, inComponents[2],
array4, inComponents[3]),
inComponents,
arrayIds);
}
}
}
}
}
template<typename T1, typename T2, typename T3>
void TryVector3(vtkm::cont::ArrayHandle<T1,Container> array1,
vtkm::cont::ArrayHandle<T2,Container> array2,
vtkm::cont::ArrayHandle<T3,Container> array3)
{
int arrayIds[3] = {0, 1, 2};
int inComponents[3];
for (inComponents[0] = 0;
inComponents[0] < vtkm::VectorTraits<T1>::NUM_COMPONENTS;
inComponents[0]++)
{
for (inComponents[1] = 0;
inComponents[1] < vtkm::VectorTraits<T2>::NUM_COMPONENTS;
inComponents[1]++)
{
for (inComponents[2] = 0;
inComponents[2] < vtkm::VectorTraits<T3>::NUM_COMPONENTS;
inComponents[2]++)
{
CheckArray(
vtkm::cont::make_ArrayHandleCompositeVector(
array1, inComponents[0],
array2, inComponents[1],
array3, inComponents[2]),
inComponents,
arrayIds);
}
}
}
std::cout << " Fourth component from Scalar." << std::endl;
TryVector4(array1, array2, array3, MakeInputArray<vtkm::Scalar>(3));
std::cout << " Fourth component from Vector4." << std::endl;
TryVector4(array1, array2, array3, MakeInputArray<vtkm::Vector4>(3));
}
template<typename T1, typename T2>
void TryVector2(vtkm::cont::ArrayHandle<T1,Container> array1,
vtkm::cont::ArrayHandle<T2,Container> array2)
{
int arrayIds[2] = {0, 1};
int inComponents[2];
for (inComponents[0] = 0;
inComponents[0] < vtkm::VectorTraits<T1>::NUM_COMPONENTS;
inComponents[0]++)
{
for (inComponents[1] = 0;
inComponents[1] < vtkm::VectorTraits<T2>::NUM_COMPONENTS;
inComponents[1]++)
{
CheckArray(
vtkm::cont::make_ArrayHandleCompositeVector(
array1, inComponents[0],
array2, inComponents[1]),
inComponents,
arrayIds);
}
}
std::cout << " Third component from Scalar." << std::endl;
TryVector3(array1, array2, MakeInputArray<vtkm::Scalar>(2));
std::cout << " Third component from Vector2." << std::endl;
TryVector3(array1, array2, MakeInputArray<vtkm::Vector2>(2));
}
template<typename T1>
void TryVector1(vtkm::cont::ArrayHandle<T1,Container> array1)
{
int arrayIds[1] = {0};
int inComponents[1];
for (inComponents[0] = 0;
inComponents[0] < vtkm::VectorTraits<T1>::NUM_COMPONENTS;
inComponents[0]++)
{
CheckArray(
vtkm::cont::make_ArrayHandleCompositeVector(array1, inComponents[0]),
inComponents,
arrayIds);
}
std::cout << " Second component from Scalar." << std::endl;
TryVector2(array1, MakeInputArray<vtkm::Scalar>(1));
std::cout << " Second component from Vector4." << std::endl;
TryVector2(array1, MakeInputArray<vtkm::Vector4>(1));
}
void TryVector()
{
std::cout << "Trying many permutations of composite vectors." << std::endl;
std::cout << " First component from Scalar." << std::endl;
TryVector1(MakeInputArray<vtkm::Scalar>(0));
std::cout << " First component from Vector3." << std::endl;
TryVector1(MakeInputArray<vtkm::Vector3>(0));
}
void TestBadArrayLengths() {
std::cout << "Checking behavior when size of input arrays do not agree."
<< std::endl;
typedef vtkm::cont::ArrayHandle<vtkm::Id, Container> InArrayType;
InArrayType longInArray = MakeInputArray<vtkm::Id>(0);
InArrayType shortInArray = MakeInputArray<vtkm::Id>(1);
shortInArray.Shrink(ARRAY_SIZE/2);
try
{
vtkm::cont::make_ArrayHandleCompositeVector(longInArray,0, shortInArray,0);
VTKM_TEST_FAIL("Did not get exception like expected.");
}
catch (vtkm::cont::ErrorControlBadValue error)
{
std::cout << "Got expected error: " << std::endl
<< error.GetMessage() << std::endl;
}
}
void TestCompositeVector() {
TryScalarArray<2>();
TryScalarArray<3>();
TryScalarArray<4>();
TryVector();
TestBadArrayLengths();
}
} // anonymous namespace
int UnitTestArrayHandleCompositeVector(int, char *[])
{
return vtkm::cont::testing::Testing::Run(TestCompositeVector);
}

@ -0,0 +1,87 @@
//============================================================================
// 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/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/testing/Testing.h>
namespace {
const vtkm::Id3 MIN_VALUES(-5, 8, 40);
const vtkm::Id3 MAX_VALUES(10, 25, 44);
const vtkm::Id3 POINT_DIMS(16, 18, 5);
const vtkm::Id NUM_POINTS = 1440;
const vtkm::Vector3 ORIGIN(30, -3, -14);
const vtkm::Vector3 SPACING(10, 1, 0.1);
const vtkm::Vector3 LOWER_LEFT(-20, 5, -10); // MIN_VALUES*SPACING + ORIGIN
void TestArrayHandleUniformPointCoordinates()
{
std::cout << "Creating ArrayHandleUniformPointCoordinates" << std::endl;
vtkm::cont::ArrayHandleUniformPointCoordinates arrayHandle(
vtkm::Extent3(MIN_VALUES, MAX_VALUES), ORIGIN, SPACING);
VTKM_TEST_ASSERT(arrayHandle.GetNumberOfValues() == NUM_POINTS,
"Array computed wrong number of points.");
std::cout << "Getting array portal." << std::endl;
vtkm::cont::internal::ArrayPortalUniformPointCoordinates portal =
arrayHandle.GetPortalConstControl();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == NUM_POINTS,
"Portal has wrong number of points.");
VTKM_TEST_ASSERT(portal.GetRange3() == POINT_DIMS,
"Portal range is wrong.");
std::cout << "Checking computed values of portal." << std::endl;
vtkm::Vector3 expectedValue;
vtkm::Id flatIndex = 0;
vtkm::Id3 blockIndex;
expectedValue[2] = LOWER_LEFT[2];
for (blockIndex[2] = 0; blockIndex[2] < POINT_DIMS[2]; blockIndex[2]++)
{
expectedValue[1] = LOWER_LEFT[1];
for (blockIndex[1] = 0; blockIndex[1] < POINT_DIMS[1]; blockIndex[1]++)
{
expectedValue[0] = LOWER_LEFT[0];
for (blockIndex[0] = 0; blockIndex[0] < POINT_DIMS[0]; blockIndex[0]++)
{
VTKM_TEST_ASSERT(test_equal(expectedValue, portal.Get(flatIndex)),
"Got wrong value for flat index.");
VTKM_TEST_ASSERT(test_equal(expectedValue, portal.Get(blockIndex)),
"Got wrong value for block index.");
flatIndex++;
expectedValue[0] += SPACING[0];
}
expectedValue[1] += SPACING[1];
}
expectedValue[2] += SPACING[2];
}
}
} // anonymous namespace
int UnitTestArrayHandleUniformPointCoordinates(int, char *[])
{
return vtkm::cont::testing::Testing::Run(
TestArrayHandleUniformPointCoordinates);
}

@ -192,11 +192,15 @@ struct IdentityFunctor {
// definitions of DoInvoke functions for all supported number of arguments.
// The created functions are conceptually defined as follows:
//
// template<typename Function, typename Signature, typename TransformFunctor>
// template<typename Function,
// typename TransformFunctor,
// typename P0,
// typename P1,
// typename P2,...>
// VTKM_CONT_EXPORT
// void DoInvokeCont(const Function &f,
// ParameterContainer<Signature> &parameters,
// FunctionInterfaceReturnContainer<R> &result,
// ParameterContainer<P0(P1,P2,...)> &parameters,
// FunctionInterfaceReturnContainer<P0> &result,
// const TransformFunctor &transform)
// {
// result.Value = transform(f(transform(parameters.Parameter1),...));
@ -247,7 +251,7 @@ struct IdentityFunctor {
f(BOOST_PP_ENUM_SHIFTED(NumParamsPlusOne, VTK_M_DO_INVOKE_TPARAM, )); \
}
#define VTK_M_DO_INVOKE_REPEAT(z, NumParams, data) \
VTK_M_DO_INVOKE(BOOST_PP_INC(NumParams));
VTK_M_DO_INVOKE(BOOST_PP_INC(NumParams))
#define VTK_M_DO_INVOKE_NAME DoInvokeCont
#define VTK_M_DO_INVOKE_EXPORT VTKM_CONT_EXPORT
@ -318,12 +322,159 @@ struct FunctionInterfaceCopyParameters<0, ParameterIndex> {
}
};
template<typename OriginalSignature, typename Transform>
struct FunctionInterfaceStaticTransformType;
// The following code uses the Boost preprocessor utilities to create
// definitions of DoStaticTransform functions for all supported number of
// arguments. The created functions are conceptually defined as follows:
//
// template<typename Transform,
// typename OriginalSignature,
// typename TransformedSignature>
// VTKM_CONT_EXPORT
// void DoStaticTransformCont(
// const Transform &transform,
// const ParameterContainer<OriginalSignature> &originalParameters,
// ParameterContainer<TransformedSignature> &transformedParameters)
// {
// transformedParameters.Parameter1 = transform(originalParameters.Parameter1);
// transformedParameters.Parameter2 = transform(originalParameters.Parameter2);
// ...
// }
//
// We define multiple DoStaticTransformCont and DoStaticTransformExec that do
// identical things with different exports. It is important to have these
// separate definitions instead of a single version with VTKM_EXEC_CONT_EXPORT
// because the transform to be invoked may only be viable in one or the other.
#define VTK_M_DO_STATIC_TRANSFORM_ASSIGN(z, count, data) \
BOOST_PP_IF(count, \
BOOST_PP_CAT(transformedParameters.Parameter, count) = \
transform(BOOST_PP_CAT(originalParameters.Parameter, count));,)
#define VTK_M_DO_STATIC_TRANSFORM(NumParamsPlusOne) \
template<typename Transform, \
BOOST_PP_ENUM_PARAMS(NumParamsPlusOne, typename OriginalP), \
BOOST_PP_ENUM_PARAMS(NumParamsPlusOne, typename TransformedP)> \
VTK_M_DO_STATIC_TRANSFORM_EXPORT \
void VTK_M_DO_STATIC_TRANSFORM_NAME( \
const Transform &transform, \
const ParameterContainer<OriginalP0(BOOST_PP_ENUM_SHIFTED_PARAMS(NumParamsPlusOne, OriginalP))> &originalParameters, \
ParameterContainer<TransformedP0(BOOST_PP_ENUM_SHIFTED_PARAMS(NumParamsPlusOne, TransformedP))> &transformedParameters) \
{ \
(void)transform; \
(void)originalParameters; \
(void)transformedParameters; \
BOOST_PP_REPEAT(NumParamsPlusOne, VTK_M_DO_STATIC_TRANSFORM_ASSIGN,) \
}
#define VTK_M_DO_STATIC_TRANSFORM_REPEAT(z, NumParams, data) \
VTK_M_DO_STATIC_TRANSFORM(BOOST_PP_INC(NumParams))
#define VTK_M_DO_STATIC_TRANSFORM_NAME DoStaticTransformCont
#define VTK_M_DO_STATIC_TRANSFORM_EXPORT VTKM_CONT_EXPORT
BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS),
VTK_M_DO_STATIC_TRANSFORM_REPEAT,)
#undef VTK_M_DO_STATIC_TRANSFORM_EXPORT
#undef VTK_M_DO_STATIC_TRANSFORM_NAME
#define VTK_M_DO_STATIC_TRANSFORM_NAME DoStaticTransformExec
#define VTK_M_DO_STATIC_TRANSFORM_EXPORT VTKM_EXEC_EXPORT
BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS),
VTK_M_DO_STATIC_TRANSFORM_REPEAT,)
#undef VTK_M_DO_STATIC_TRANSFORM_EXPORT
#undef VTK_M_DO_STATIC_TRANSFORM_NAME
#undef VTK_M_DO_STATIC_TRANSFORM_REPEAT
#undef VTK_M_DO_STATIC_TRANSFORM
#undef VTK_M_DO_STATIC_TRANSFORM_ASSIGN
template<typename OriginalFunction,
typename NewFunction,
typename TransformFunctor,
typename FinishFunctor>
class FunctionInterfaceDynamicTransformContContinue;
// The following code uses the Boost preprocessor utilities to create
// definitions of DoForEach functions for all supported number of arguments.
// The created functions are conceptually defined as follows:
//
// template<typename Functor, typename P0, typename P1, typename P2,...>
// VTKM_CONT_EXPORT
// void DoForEachCont(const Functor &f,
// ParameterContainer<P0(P1,P2,...)> &parameters)
//
// {
// f(parameters.Parameter1);
// f(parameters.Parameter2);
// ...
// }
//
// We define multiple DoForEachCont and DoForEachExec that do identical things
// with different exports. It is important to have these separate definitions
// instead of a single version with VTKM_EXEC_CONT_EXPORT because the functor
// to be invoked on each parameter may only be viable in one or the other.
// There are also separate versions that support a const FunctionInterface and
// a non-const FunctionInterface.
#define VTK_M_DO_FOR_EACH_CALL_PARAM(z, count, data) \
BOOST_PP_IF(count, f(BOOST_PP_CAT(parameters.Parameter, count));,)
#define VTK_M_DO_FOR_EACH(NumParamsPlusOne) \
template<typename Functor, \
BOOST_PP_ENUM_PARAMS(NumParamsPlusOne, typename P)> \
VTK_M_DO_FOR_EACH_EXPORT \
void VTK_M_DO_FOR_EACH_NAME( \
const Functor &f, \
VTK_M_DO_FOR_EACH_FI_CONST ParameterContainer<P0(BOOST_PP_ENUM_SHIFTED_PARAMS(NumParamsPlusOne, P))> &parameters) \
{ \
(void)f; \
(void)parameters; \
BOOST_PP_REPEAT(NumParamsPlusOne, VTK_M_DO_FOR_EACH_CALL_PARAM,) \
}
#define VTK_M_DO_FOR_EACH_REPEAT(z, NumParams, data) \
VTK_M_DO_FOR_EACH(BOOST_PP_INC(NumParams))
#define VTK_M_DO_FOR_EACH_EXPORT VTKM_CONT_EXPORT
#define VTK_M_DO_FOR_EACH_NAME DoForEachCont
#define VTK_M_DO_FOR_EACH_FI_CONST const
BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS),
VTK_M_DO_FOR_EACH_REPEAT,)
#undef VTK_M_DO_FOR_EACH_FI_CONST
#undef VTK_M_DO_FOR_EACH_NAME
#undef VTK_M_DO_FOR_EACH_EXPORT
#define VTK_M_DO_FOR_EACH_EXPORT VTKM_CONT_EXPORT
#define VTK_M_DO_FOR_EACH_NAME DoForEachCont
#define VTK_M_DO_FOR_EACH_FI_CONST
BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS),
VTK_M_DO_FOR_EACH_REPEAT,)
#undef VTK_M_DO_FOR_EACH_FI_CONST
#undef VTK_M_DO_FOR_EACH_NAME
#undef VTK_M_DO_FOR_EACH_EXPORT
#define VTK_M_DO_FOR_EACH_EXPORT VTKM_EXEC_EXPORT
#define VTK_M_DO_FOR_EACH_NAME DoForEachExec
#define VTK_M_DO_FOR_EACH_FI_CONST const
BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS),
VTK_M_DO_FOR_EACH_REPEAT,)
#undef VTK_M_DO_FOR_EACH_FI_CONST
#undef VTK_M_DO_FOR_EACH_NAME
#undef VTK_M_DO_FOR_EACH_EXPORT
#define VTK_M_DO_FOR_EACH_EXPORT VTKM_EXEC_EXPORT
#define VTK_M_DO_FOR_EACH_NAME DoForEachExec
#define VTK_M_DO_FOR_EACH_FI_CONST
BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS),
VTK_M_DO_FOR_EACH_REPEAT,)
#undef VTK_M_DO_FOR_EACH_FI_CONST
#undef VTK_M_DO_FOR_EACH_NAME
#undef VTK_M_DO_FOR_EACH_EXPORT
#undef VTK_M_DO_FOR_EACH_REPEAT
#undef VTK_M_DO_FOR_EACH
#undef VTK_M_DO_FOR_EACH_CALL_PARAM
} // namespace detail
template<typename FunctionSignature>
@ -398,7 +549,7 @@ public:
template<int ParameterIndex>
VTKM_EXEC_CONT_EXPORT
typename ParameterType<ParameterIndex>::type
GetParameter() {
GetParameter() const {
return detail::GetParameter<ParameterIndex>(this->Parameters);
}
@ -559,6 +710,79 @@ public:
return replacedFuncInterface;
}
template<typename Transform>
struct StaticTransformType {
typedef FunctionInterface<
typename detail::FunctionInterfaceStaticTransformType<
FunctionSignature,Transform>::type> type;
};
/// \brief Transforms the \c FunctionInterface based on compile-time
/// information.
///
/// The \c StaticTransform methods transform all the parameters of this \c
/// FunctionInterface to different types and values based on compile-time
/// information. It operates by accepting a functor that defines a unary
/// function whose argument is the parameter to transform and the return
/// value is the transformed value. The functor must also contain a templated
/// struct name ReturnType with an internal type named \c type that defines
/// the return type of the transform for a given input type.
///
/// The transformation is only applied to the parameters of the function. The
/// return argument is uneffected.
///
/// The return type can be determined with the \c StaticTransformType
/// template.
///
/// Here is an example of a transformation that converts a \c
/// FunctionInterface to another \c FunctionInterface containing pointers to
/// all of the parameters.
///
/// \code
/// struct MyTransformFunctor {
/// template<typename T>
/// struct ReturnType {
/// typedef const T *type;
/// };
///
/// template<typename T>
/// DAX_CONT_EXPORT
/// const T *operator()(const T &x) const {
/// return &x;
/// }
/// };
///
/// template<typename FunctionSignature>
/// typename vtkm::internal::FunctionInterface<FunctionSignature>::template StaticTransformType<MyTransformFunctor>::type
/// ImportantStuff(const vtkm::internal::FunctionInterface<FunctionSignature> &funcInterface)
/// {
/// return funcInterface.StaticTransformCont(MyTransformFunctor());
/// }
/// \endcode
///
template<typename Transform>
VTKM_CONT_EXPORT
typename StaticTransformType<Transform>::type
StaticTransformCont(const Transform &transform) const
{
typename StaticTransformType<Transform>::type newFuncInterface;
detail::DoStaticTransformCont(transform,
this->Parameters,
newFuncInterface.Parameters);
return newFuncInterface;
}
template<typename Transform>
VTKM_EXEC_EXPORT
typename StaticTransformType<Transform>::type
StaticTransformExec(const Transform &transform) const
{
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
@ -631,9 +855,8 @@ public:
///
template<typename TransformFunctor, typename FinishFunctor>
VTKM_CONT_EXPORT
void
DynamicTransformCont(const TransformFunctor &transform,
const FinishFunctor &finish) {
void DynamicTransformCont(const TransformFunctor &transform,
const FinishFunctor &finish) {
typedef detail::FunctionInterfaceDynamicTransformContContinue<
FunctionSignature,
ResultType(),
@ -648,6 +871,33 @@ public:
this->Result = emptyInterface.GetReturnValueSafe();
}
/// \brief Applies a function to all the parameters.
///
/// The \c ForEach methods take a function and apply that function to each
/// of the parameters in the \c FunctionInterface. (Return values are not
/// effected.)
///
template<typename Functor>
VTKM_CONT_EXPORT
void ForEachCont(const Functor &f) const {
detail::DoForEachCont(f, this->Parameters);
}
template<typename Functor>
VTKM_CONT_EXPORT
void ForEachCont(const Functor &f) {
detail::DoForEachCont(f, this->Parameters);
}
template<typename Functor>
VTKM_EXEC_EXPORT
void ForEachExec(const Functor &f) const {
detail::DoForEachExec(f, this->Parameters);
}
template<typename Functor>
VTKM_EXEC_EXPORT
void ForEachExec(const Functor &f) {
detail::DoForEachExec(f, this->Parameters);
}
private:
vtkm::internal::FunctionInterfaceReturnContainer<ResultType> Result;
detail::ParameterContainer<FunctionSignature> Parameters;
@ -655,6 +905,46 @@ private:
namespace detail {
// The following code uses the Boost preprocessor utilities to create
// definitions of FunctionInterfaceStaticTransformType for all supported number
// of arguments. The created classes are conceptually defined as follows:
//
// template<typename Transform,
// typename P0, // Return type
// typename P1,
// typename P2, ...>
// struct FunctionInterfaceStaticTransformType<P0(P1,P2,...), Transform> {
// typedef P0(type)(typename Transform::template ReturnType<P1>::type,
// typename Transform::template ReturnType<P2>::type, ...);
// };
#define VTK_M_STATIC_TRANSFORM_TPARAM(z, ParamIndex, data) \
BOOST_PP_IF( \
ParamIndex, \
typename Transform::template ReturnType<BOOST_PP_CAT(P,ParamIndex)>::type,)
#define VTK_M_STATIC_TRANSFORM_TYPE(NumParamsPlusOne) \
template<typename Transform, \
BOOST_PP_ENUM_PARAMS(NumParamsPlusOne, typename P)> \
struct FunctionInterfaceStaticTransformType< \
P0(BOOST_PP_ENUM_SHIFTED_PARAMS(NumParamsPlusOne, P)), \
Transform> \
{ \
typedef P0(type)( \
BOOST_PP_ENUM_SHIFTED(NumParamsPlusOne, VTK_M_STATIC_TRANSFORM_TPARAM,) \
); \
};
#define VTK_M_STATIC_TRANSFORM_TYPE_REPEAT(z, NumParams, data) \
VTK_M_STATIC_TRANSFORM_TYPE(BOOST_PP_INC(NumParams))
BOOST_PP_REPEAT(BOOST_PP_INC(VTKM_MAX_FUNCTION_PARAMETERS),
VTK_M_STATIC_TRANSFORM_TYPE_REPEAT,)
#undef VTK_M_STATIC_TRANSFORM_TYPE_REPEAT
#undef VTK_M_STATIC_TRANSFORM_TYPE
#undef VTK_M_STATIC_TRANSFORM_TPARAM
template<typename OriginalFunction,
typename NewFunction,
typename TransformFunctor,

@ -135,10 +135,22 @@ struct GetReferenceFunctor
const T *operator()(const T &x) const { return &x; }
};
struct PointerTransform {
template<typename T>
struct ReturnType {
typedef const T *type;
};
template<typename T>
const T *operator()(const T &x) const {
return &x;
}
};
struct ThreePointerArgFunctor {
void operator()(const Type1 *a1, const Type2 *a2, const Type3 *a3) const
{
std::cout << "In 3 arg functor." << std::endl;
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.");
@ -286,6 +298,14 @@ struct DynamicTransformFinish
}
};
struct ForEachFunctor
{
template<typename T>
void operator()(T &x) const { x = 2*x; }
void operator()(std::string &x) const { x.append("*2"); }
};
void TryFunctionInterface5(
vtkm::internal::FunctionInterface<void(Type1,Type2,Type3,Type4,Type5)> funcInterface)
{
@ -409,6 +429,35 @@ void TestTransformInvoke()
"Got bad result from invoke.");
}
void TestStaticTransform()
{
std::cout << "Trying static transform." << std::endl;
typedef vtkm::internal::FunctionInterface<void(Type1,Type2,Type3)>
OriginalType;
OriginalType funcInterface =
vtkm::internal::make_FunctionInterface<void>(Arg1, Arg2, Arg3);
std::cout << "Transform with reported type." << std::endl;
typedef OriginalType::StaticTransformType<PointerTransform>::type
ReportedType;
ReportedType funcInterfaceTransform1 =
funcInterface.StaticTransformCont(PointerTransform());
funcInterfaceTransform1.InvokeCont(ThreePointerArgFunctor());
funcInterfaceTransform1 =
funcInterface.StaticTransformExec(PointerTransform());
funcInterfaceTransform1.InvokeExec(ThreePointerArgFunctor());
std::cout << "Transform with expected type." << std::endl;
typedef vtkm::internal::FunctionInterface<void(Type1*,Type2*,Type3*)>
ExpectedType;
ReportedType funcInterfaceTransform2 =
funcInterface.StaticTransformCont(PointerTransform());
funcInterfaceTransform2.InvokeCont(ThreePointerArgFunctor());
funcInterfaceTransform2 =
funcInterface.StaticTransformExec(PointerTransform());
funcInterfaceTransform2.InvokeExec(ThreePointerArgFunctor());
}
void TestDynamicTransform()
{
std::cout << "Trying dynamic transform." << std::endl;
@ -429,6 +478,33 @@ void TestDynamicTransform()
"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>() == 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*Arg4, "Arg 4 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<5>() == 2*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*Arg4, "Arg 4 incorrect.");
VTKM_TEST_ASSERT(funcInterface.GetParameter<5>() == 4*Arg5, "Arg 5 incorrect.");
}
void TestInvokeTime()
{
std::cout << "Checking time to call lots of args lots of times." << std::endl;
@ -487,7 +563,9 @@ void TestFunctionInterface()
TestInvokeResult();
TestAppend();
TestTransformInvoke();
TestStaticTransform();
TestDynamicTransform();
TestForEach();
TestInvokeTime();
}

@ -26,6 +26,7 @@ set(headers
VTKM_declare_headers(${headers})
set(unit_tests
UnitTestExtent.cxx
UnitTestListTag.cxx
UnitTestTesting.cxx
UnitTestTypeListTag.cxx

@ -0,0 +1,197 @@
//============================================================================
// 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/Extent.h>
#include <vtkm/testing/Testing.h>
namespace {
const int MIN_VALUES[] = { -5, 8, 40, -8, -3 };
const int MAX_VALUES[] = { 10, 25, 44, -2, 1 };
const int POINT_DIMS[] = { 16, 18, 5, 7, 5 };
const int CELL_DIMS[] = { 15, 17, 4, 6, 4 };
const int NUM_POINTS[] = { 0, 16, 288, 1440, 10080, 50400 };
const int NUM_CELLS[] = { 0, 15, 255, 1020, 6120, 24480 };
template<int Dimensions>
void TestDimensions(vtkm::Extent<Dimensions>)
{
std::cout << "Testing Dimension sizes for " << Dimensions << " dimensions"
<< std::endl;
vtkm::Extent<Dimensions> extent;
vtkm::Tuple<vtkm::Id,Dimensions> pointDims;
vtkm::Tuple<vtkm::Id,Dimensions> cellDims;
vtkm::Id numPoints;
vtkm::Id numCells;
for (int dimIndex = 0; dimIndex < Dimensions; dimIndex++)
{
extent.Min[dimIndex] = 0; extent.Max[dimIndex] = 10;
}
pointDims = vtkm::ExtentPointDimensions(extent);
cellDims = vtkm::ExtentCellDimensions(extent);
for (int dimIndex = 0; dimIndex < Dimensions; dimIndex++)
{
VTKM_TEST_ASSERT(pointDims[dimIndex] == 11,
"Got incorrect point dimensions for extent.");
VTKM_TEST_ASSERT(cellDims[dimIndex] == 10,
"Got incorrect point dimensions for extent.");
}
for (int dimIndex = 0; dimIndex < Dimensions; dimIndex++)
{
extent.Min[dimIndex] = MIN_VALUES[dimIndex];
extent.Max[dimIndex] = MAX_VALUES[dimIndex];
}
pointDims = vtkm::ExtentPointDimensions(extent);
cellDims = vtkm::ExtentCellDimensions(extent);
for (int dimIndex = 0; dimIndex < Dimensions; dimIndex++)
{
VTKM_TEST_ASSERT(pointDims[dimIndex] == POINT_DIMS[dimIndex],
"Got incorrect point dimensions for extent.");
VTKM_TEST_ASSERT(cellDims[dimIndex] == CELL_DIMS[dimIndex],
"Got incorrect point dimensions for extent.");
}
numPoints = vtkm::ExtentNumberOfPoints(extent);
numCells = vtkm::ExtentNumberOfCells(extent);
VTKM_TEST_ASSERT(numPoints == NUM_POINTS[Dimensions],
"Got wrong number of points.");
VTKM_TEST_ASSERT(numCells == NUM_CELLS[Dimensions],
"Got wrong number of cells.");
}
template<int Dimensions>
void TryIndexConversion(const vtkm::Extent<Dimensions> &extent)
{
typedef vtkm::Tuple<vtkm::Id,Dimensions> IdX;
vtkm::Id lastFlatIndex;
IdX correctTopologyIndex;
std::cout << " Testing point index conversion" << std::endl;
correctTopologyIndex = IdX(100000);
lastFlatIndex = vtkm::ExtentNumberOfPoints(extent);
for (vtkm::Id correctFlatIndex = 0;
correctFlatIndex < lastFlatIndex;
correctFlatIndex++)
{
// Increment topology index
for (int dimIndex = 0; dimIndex < Dimensions; dimIndex++)
{
correctTopologyIndex[dimIndex]++;
if (correctTopologyIndex[dimIndex] <= extent.Max[dimIndex]) { break; }
correctTopologyIndex[dimIndex] = extent.Min[dimIndex];
// Iterate to increment the next index.
}
vtkm::Id computedFlatIndex =
vtkm::ExtentPointTopologyIndexToFlatIndex(correctTopologyIndex, extent);
VTKM_TEST_ASSERT(computedFlatIndex == correctFlatIndex,
"Got incorrect flat index.");
IdX computedTopologyIndex =
vtkm::ExtentPointFlatIndexToTopologyIndex(correctFlatIndex, extent);
VTKM_TEST_ASSERT(computedTopologyIndex == correctTopologyIndex,
"Got incorrect topology index.");
}
// Sanity check to make sure we got to the last topology index.
VTKM_TEST_ASSERT(correctTopologyIndex == extent.Max,
"Test code error. Indexing problem.");
std::cout << " Testing cell index conversion" << std::endl;
correctTopologyIndex = IdX(100000);
lastFlatIndex = vtkm::ExtentNumberOfCells(extent);
for (vtkm::Id correctFlatIndex = 0;
correctFlatIndex < lastFlatIndex;
correctFlatIndex++)
{
// Increment topology index
for (int dimIndex = 0; dimIndex < Dimensions; dimIndex++)
{
correctTopologyIndex[dimIndex]++;
if (correctTopologyIndex[dimIndex] < extent.Max[dimIndex]) { break; }
correctTopologyIndex[dimIndex] = extent.Min[dimIndex];
// Iterate to increment the next index.
}
vtkm::Id computedFlatIndex =
vtkm::ExtentCellTopologyIndexToFlatIndex(correctTopologyIndex, extent);
VTKM_TEST_ASSERT(computedFlatIndex == correctFlatIndex,
"Got incorrect flat index.");
IdX computedTopologyIndex =
vtkm::ExtentCellFlatIndexToTopologyIndex(correctFlatIndex, extent);
VTKM_TEST_ASSERT(computedTopologyIndex == correctTopologyIndex,
"Got incorrect topology index.");
vtkm::Id expectedFirstPointIndex =
vtkm::ExtentPointTopologyIndexToFlatIndex(correctTopologyIndex, extent);
vtkm::Id computedFirstPointIndex =
vtkm::ExtentFirstPointOnCell(correctFlatIndex, extent);
VTKM_TEST_ASSERT(computedFirstPointIndex == expectedFirstPointIndex,
"Got wrong first point index.");
}
// Sanity check to make sure we got to the last topology index.
VTKM_TEST_ASSERT(correctTopologyIndex == extent.Max - IdX(1),
"Test code error. Indexing problem.");
}
template<int Dimensions>
void TestIndexConversion(vtkm::Extent<Dimensions>)
{
std::cout << "Testing index conversion for " << Dimensions << " dimensions."
<< std::endl;
vtkm::Extent<Dimensions> extent;
for (int dimIndex = 0; dimIndex < Dimensions; dimIndex++)
{
extent.Min[dimIndex] = 0; extent.Max[dimIndex] = 10;
}
TryIndexConversion(extent);
for (int dimIndex = 0; dimIndex < Dimensions; dimIndex++)
{
extent.Min[dimIndex] = MIN_VALUES[dimIndex];
extent.Max[dimIndex] = MAX_VALUES[dimIndex];
}
TryIndexConversion(extent);
}
void ExtentTests()
{
TestDimensions(vtkm::Extent<1>());
TestDimensions(vtkm::Extent2());
TestDimensions(vtkm::Extent3());
TestDimensions(vtkm::Extent<5>());
TestIndexConversion(vtkm::Extent<1>());
TestIndexConversion(vtkm::Extent2());
TestIndexConversion(vtkm::Extent3());
TestIndexConversion(vtkm::Extent<5>());
}
} // anonymous namespace
int UnitTestExtent(int, char *[])
{
return vtkm::testing::Testing::Run(ExtentTests);
}