vtk-m2/vtkm/cont/testing/TestingFancyArrayHandles.h
Kenneth Moreland 26ea2ab420 Break circular dependency of ArrayCopy.h and UnknownArrayHandle.h
The circular dependency came from UnknownArrayHandle.h needing
VTKmDefaultTypes.h, which needed all the cell set types. Some of those
cell sets used ArrayCopy in templated functions. Changed those functions
to directly deep copy the ArrayHandle.
2021-02-02 17:33:08 -07:00

1695 lines
62 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.
//============================================================================
#ifndef vtk_m_cont_testing_TestingFancyArrayHandles_h
#define vtk_m_cont_testing_TestingFancyArrayHandles_h
#include <vtkm/VecTraits.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/ArrayHandleCompositeVector.h>
#include <vtkm/cont/ArrayHandleConcatenate.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandleDiscard.h>
#include <vtkm/cont/ArrayHandleGroupVec.h>
#include <vtkm/cont/ArrayHandleGroupVecVariable.h>
#include <vtkm/cont/ArrayHandleImplicit.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ArrayHandleMultiplexer.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/ArrayHandleRecombineVec.h>
#include <vtkm/cont/ArrayHandleSOA.h>
#include <vtkm/cont/ArrayHandleTransform.h>
#include <vtkm/cont/ArrayHandleView.h>
#include <vtkm/cont/ArrayHandleZip.h>
#include <vtkm/cont/VirtualObjectHandle.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/testing/Testing.h>
#include <vector>
namespace fancy_array_detail
{
template <typename ValueType>
struct IndexSquared
{
VTKM_EXEC_CONT
ValueType operator()(vtkm::Id index) const
{
using ComponentType = typename vtkm::VecTraits<ValueType>::ComponentType;
return ValueType(static_cast<ComponentType>(index * index));
}
};
template <typename ValueType>
struct ValueSquared
{
template <typename U>
VTKM_EXEC_CONT ValueType operator()(U u) const
{
return vtkm::Dot(u, u);
}
};
struct ValueScale
{
ValueScale()
: Factor(1.0)
{
}
ValueScale(vtkm::Float64 factor)
: Factor(factor)
{
}
template <typename ValueType>
VTKM_EXEC_CONT ValueType operator()(const ValueType& v) const
{
using Traits = vtkm::VecTraits<ValueType>;
using TTraits = vtkm::TypeTraits<ValueType>;
using ComponentType = typename Traits::ComponentType;
ValueType result = TTraits::ZeroInitialization();
for (vtkm::IdComponent i = 0; i < Traits::GetNumberOfComponents(v); ++i)
{
vtkm::Float64 vi = static_cast<vtkm::Float64>(Traits::GetComponent(v, i));
vtkm::Float64 ri = vi * this->Factor;
Traits::SetComponent(result, i, static_cast<ComponentType>(ri));
}
return result;
}
private:
vtkm::Float64 Factor;
};
struct InverseValueScale
{
InverseValueScale()
: InverseFactor(1.0)
{
}
InverseValueScale(vtkm::Float64 factor)
: InverseFactor(1.0 / factor)
{
}
template <typename ValueType>
VTKM_EXEC_CONT ValueType operator()(const ValueType& v) const
{
using Traits = vtkm::VecTraits<ValueType>;
using TTraits = vtkm::TypeTraits<ValueType>;
using ComponentType = typename Traits::ComponentType;
ValueType result = TTraits::ZeroInitialization();
for (vtkm::IdComponent i = 0; i < Traits::GetNumberOfComponents(v); ++i)
{
vtkm::Float64 vi = static_cast<vtkm::Float64>(Traits::GetComponent(v, i));
vtkm::Float64 ri = vi * this->InverseFactor;
Traits::SetComponent(result, i, static_cast<ComponentType>(ri));
}
return result;
}
private:
vtkm::Float64 InverseFactor;
};
template <typename ValueType>
struct VirtualTransformFunctorBase : public vtkm::VirtualObjectBase
{
VirtualTransformFunctorBase() = default;
VTKM_EXEC_CONT
virtual ValueType operator()(const ValueType& v) const = 0;
};
template <typename ValueType, typename FunctorType>
struct VirtualTransformFunctor : VirtualTransformFunctorBase<ValueType>
{
FunctorType Functor;
VTKM_CONT
VirtualTransformFunctor(const FunctorType& functor)
: Functor(functor)
{
}
VTKM_EXEC_CONT
ValueType operator()(const ValueType& v) const override { return this->Functor(v); }
};
template <typename ValueType>
struct TransformExecObject : public vtkm::cont::ExecutionAndControlObjectBase
{
vtkm::cont::VirtualObjectHandle<VirtualTransformFunctorBase<ValueType>> VirtualFunctor;
VTKM_CONT TransformExecObject() = default;
template <typename FunctorType>
VTKM_CONT TransformExecObject(const FunctorType& functor)
{
// Need to make sure the serial device is supported, since that is what is used on the
// control side. Therefore we reset to all supported devices.
vtkm::cont::ScopedRuntimeDeviceTracker scopedTracker(
vtkm::cont::DeviceAdapterTagSerial{}, vtkm::cont::RuntimeDeviceTrackerMode::Enable);
this->VirtualFunctor.Reset(new VirtualTransformFunctor<ValueType, FunctorType>(functor));
}
struct FunctorWrapper
{
const VirtualTransformFunctorBase<ValueType>* FunctorPointer;
FunctorWrapper() = default;
VTKM_CONT
FunctorWrapper(const VirtualTransformFunctorBase<ValueType>* functorPointer)
: FunctorPointer(functorPointer)
{
}
template <typename InValueType>
VTKM_EXEC ValueType operator()(const InValueType& value) const
{
return (*this->FunctorPointer)(value);
}
};
template <typename DeviceAdapterTag>
VTKM_CONT FunctorWrapper PrepareForExecution(DeviceAdapterTag device,
vtkm::cont::Token& token) const
{
return FunctorWrapper(this->VirtualFunctor.PrepareForExecution(device, token));
}
VTKM_CONT FunctorWrapper PrepareForControl() const
{
return FunctorWrapper(this->VirtualFunctor.Get());
}
};
}
namespace vtkm
{
namespace cont
{
namespace testing
{
/// This class has a single static member, Run, that tests that all Fancy Array
/// Handles work with the given DeviceAdapter
///
template <class DeviceAdapterTag>
struct TestingFancyArrayHandles
{
private:
static const int ARRAY_SIZE = 10;
public:
struct PassThrough : public vtkm::worklet::WorkletMapField
{
using ControlSignature = void(FieldIn, FieldOut);
using ExecutionSignature = void(_1, _2);
template <typename InValue, typename OutValue>
VTKM_EXEC void operator()(const InValue& inValue, OutValue& outValue) const
{
outValue = inValue;
}
};
struct InplaceFunctorPair : public vtkm::worklet::WorkletMapField
{
using ControlSignature = void(FieldInOut);
using ExecutionSignature = void(_1);
template <typename T>
VTKM_EXEC void operator()(vtkm::Pair<T, T>& value) const
{
value.second = value.first;
}
};
#ifndef VTKM_CUDA
private:
#endif
struct TestArrayPortalSOA
{
template <typename ComponentType>
VTKM_CONT void operator()(ComponentType) const
{
constexpr vtkm::IdComponent NUM_COMPONENTS = 4;
using ValueType = vtkm::Vec<ComponentType, NUM_COMPONENTS>;
using ComponentArrayType = vtkm::cont::ArrayHandle<ComponentType>;
using SOAPortalType =
vtkm::internal::ArrayPortalSOA<ValueType, typename ComponentArrayType::WritePortalType>;
std::cout << "Test SOA portal reflects data in component portals." << std::endl;
SOAPortalType soaPortalIn(ARRAY_SIZE);
std::array<vtkm::cont::ArrayHandle<ComponentType>, NUM_COMPONENTS> implArrays;
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
vtkm::cont::ArrayHandle<ComponentType> array;
array.Allocate(ARRAY_SIZE);
auto portal = array.WritePortal();
for (vtkm::IdComponent valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex)
{
portal.Set(valueIndex, TestValue(valueIndex, ValueType{})[componentIndex]);
}
soaPortalIn.SetPortal(componentIndex, portal);
implArrays[static_cast<std::size_t>(componentIndex)] = array;
}
VTKM_TEST_ASSERT(soaPortalIn.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaPortalIn);
std::cout << "Test data set in SOA portal gets set in component portals." << std::endl;
{
SOAPortalType soaPortalOut(ARRAY_SIZE);
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS;
++componentIndex)
{
vtkm::cont::ArrayHandle<ComponentType> array;
array.Allocate(ARRAY_SIZE);
auto portal = array.WritePortal();
soaPortalOut.SetPortal(componentIndex, portal);
implArrays[static_cast<std::size_t>(componentIndex)] = array;
}
SetPortal(soaPortalOut);
}
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
auto portal = implArrays[static_cast<size_t>(componentIndex)].ReadPortal();
for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex)
{
ComponentType x = TestValue(valueIndex, ValueType{})[componentIndex];
VTKM_TEST_ASSERT(test_equal(x, portal.Get(valueIndex)));
}
}
}
};
struct TestSOAAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using VTraits = vtkm::VecTraits<ValueType>;
using ComponentType = typename VTraits::ComponentType;
constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS;
{
vtkm::cont::ArrayHandleSOA<ValueType> soaArray;
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS;
++componentIndex)
{
vtkm::cont::ArrayHandle<ComponentType> componentArray;
componentArray.Allocate(ARRAY_SIZE);
auto componentPortal = componentArray.WritePortal();
for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex)
{
componentPortal.Set(
valueIndex,
VTraits::GetComponent(TestValue(valueIndex, ValueType{}), componentIndex));
}
soaArray.SetArray(componentIndex, componentArray);
}
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
VTKM_TEST_ASSERT(soaArray.ReadPortal().GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaArray.ReadPortal());
vtkm::cont::ArrayHandle<ValueType> basicArray;
vtkm::cont::ArrayCopy(soaArray, basicArray);
VTKM_TEST_ASSERT(basicArray.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(basicArray.ReadPortal());
}
{
// Check constructors
using Vec3 = vtkm::Vec<ComponentType, 3>;
std::vector<ComponentType> vector0;
std::vector<ComponentType> vector1;
std::vector<ComponentType> vector2;
for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex)
{
Vec3 value = TestValue(valueIndex, Vec3{});
vector0.push_back(value[0]);
vector1.push_back(value[1]);
vector2.push_back(value[2]);
}
{
vtkm::cont::ArrayHandleSOA<Vec3> soaArray =
vtkm::cont::make_ArrayHandleSOA<Vec3>({ vector0, vector1, vector2 });
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaArray.ReadPortal());
}
{
vtkm::cont::ArrayHandleSOA<Vec3> soaArray =
vtkm::cont::make_ArrayHandleSOA(vtkm::CopyFlag::Off, vector0, vector1, vector2);
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaArray.ReadPortal());
// Make sure calling ReleaseResources does not result in error.
soaArray.ReleaseResources();
}
{
vtkm::cont::ArrayHandleSOA<Vec3> soaArray = vtkm::cont::make_ArrayHandleSOA<Vec3>(
{ vector0.data(), vector1.data(), vector2.data() }, ARRAY_SIZE, vtkm::CopyFlag::Off);
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaArray.ReadPortal());
}
{
vtkm::cont::ArrayHandleSOA<Vec3> soaArray = vtkm::cont::make_ArrayHandleSOA(
ARRAY_SIZE, vtkm::CopyFlag::Off, vector0.data(), vector1.data(), vector2.data());
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaArray.ReadPortal());
}
}
}
};
struct TestSOAAsOutput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using VTraits = vtkm::VecTraits<ValueType>;
using ComponentType = typename VTraits::ComponentType;
constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS;
vtkm::cont::ArrayHandle<ValueType> basicArray;
basicArray.Allocate(ARRAY_SIZE);
SetPortal(basicArray.WritePortal());
vtkm::cont::ArrayHandleSOA<ValueType> soaArray;
vtkm::cont::ArrayCopy(basicArray, soaArray);
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
vtkm::cont::ArrayHandle<ComponentType> componentArray = soaArray.GetArray(componentIndex);
auto componentPortal = componentArray.ReadPortal();
for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex)
{
ComponentType expected =
VTraits::GetComponent(TestValue(valueIndex, ValueType{}), componentIndex);
ComponentType got = componentPortal.Get(valueIndex);
VTKM_TEST_ASSERT(test_equal(expected, got));
}
}
}
};
struct TestCompositeAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
const ValueType value = TestValue(13, ValueType());
std::vector<ValueType> compositeData(ARRAY_SIZE, value);
vtkm::cont::ArrayHandle<ValueType> compositeInput =
vtkm::cont::make_ArrayHandle(compositeData, vtkm::CopyFlag::Off);
auto composite =
vtkm::cont::make_ArrayHandleCompositeVector(compositeInput, compositeInput, compositeInput);
vtkm::cont::ArrayHandle<vtkm::Vec<ValueType, 3>> result;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(composite, result);
//verify that the control portal works
auto resultPortal = result.ReadPortal();
auto compositePortal = composite.ReadPortal();
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
const vtkm::Vec<ValueType, 3> result_v = resultPortal.Get(i);
VTKM_TEST_ASSERT(test_equal(result_v, vtkm::Vec<ValueType, 3>(value)),
"CompositeVector Handle Failed");
const vtkm::Vec<ValueType, 3> result_c = compositePortal.Get(i);
VTKM_TEST_ASSERT(test_equal(result_c, vtkm::Vec<ValueType, 3>(value)),
"CompositeVector Handle Failed");
}
composite.ReleaseResources();
}
};
struct TestConstantAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
const ValueType value = TestValue(43, ValueType());
vtkm::cont::ArrayHandleConstant<ValueType> constant =
vtkm::cont::make_ArrayHandleConstant(value, ARRAY_SIZE);
VTKM_TEST_ASSERT(constant.GetValue() == value);
vtkm::cont::ArrayHandle<ValueType> result;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(constant, result);
//verify that the control portal works
auto resultPortal = result.ReadPortal();
auto constantPortal = constant.ReadPortal();
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
const ValueType result_v = resultPortal.Get(i);
const ValueType control_value = constantPortal.Get(i);
VTKM_TEST_ASSERT(test_equal(result_v, value), "Counting Handle Failed");
VTKM_TEST_ASSERT(test_equal(result_v, control_value), "Counting Handle Control Failed");
}
constant.ReleaseResources();
}
};
struct TestCountingAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using ComponentType = typename vtkm::VecTraits<ValueType>::ComponentType;
const vtkm::Id length = ARRAY_SIZE;
//need to initialize the start value or else vectors will have
//random values to start
ComponentType component_value(0);
const ValueType start = ValueType(component_value);
vtkm::cont::ArrayHandleCounting<ValueType> counting =
vtkm::cont::make_ArrayHandleCounting(start, ValueType(1), length);
vtkm::cont::ArrayHandle<ValueType> result;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(counting, result);
//verify that the control portal works
auto resultPortal = result.ReadPortal();
auto countingPortal = counting.ReadPortal();
for (vtkm::Id i = 0; i < length; ++i)
{
const ValueType result_v = resultPortal.Get(i);
const ValueType correct_value = ValueType(component_value);
const ValueType control_value = countingPortal.Get(i);
VTKM_TEST_ASSERT(test_equal(result_v, correct_value), "Counting Handle Failed");
VTKM_TEST_ASSERT(test_equal(result_v, control_value), "Counting Handle Control Failed");
component_value = ComponentType(component_value + ComponentType(1));
}
counting.ReleaseResources();
}
};
struct TestImplicitAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
const vtkm::Id length = ARRAY_SIZE;
using FunctorType = ::fancy_array_detail::IndexSquared<ValueType>;
FunctorType functor;
vtkm::cont::ArrayHandleImplicit<FunctorType> implicit =
vtkm::cont::make_ArrayHandleImplicit(functor, length);
vtkm::cont::ArrayHandle<ValueType> result;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(implicit, result);
//verify that the control portal works
auto resultPortal = result.ReadPortal();
auto implicitPortal = implicit.ReadPortal();
for (vtkm::Id i = 0; i < length; ++i)
{
const ValueType result_v = resultPortal.Get(i);
const ValueType correct_value = functor(i);
const ValueType control_value = implicitPortal.Get(i);
VTKM_TEST_ASSERT(test_equal(result_v, correct_value), "Implicit Handle Failed");
VTKM_TEST_ASSERT(test_equal(result_v, control_value), "Implicit Handle Failed");
}
implicit.ReleaseResources();
}
};
struct TestConcatenateAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
const vtkm::Id length = ARRAY_SIZE;
using FunctorType = ::fancy_array_detail::IndexSquared<ValueType>;
using ComponentType = typename vtkm::VecTraits<ValueType>::ComponentType;
using ValueHandleType = vtkm::cont::ArrayHandleImplicit<FunctorType>;
using BasicArrayType = vtkm::cont::ArrayHandle<ValueType>;
using ConcatenateType = vtkm::cont::ArrayHandleConcatenate<ValueHandleType, BasicArrayType>;
FunctorType functor;
for (vtkm::Id start_pos = 0; start_pos < length; start_pos += length / 4)
{
vtkm::Id implicitLen = length - start_pos;
vtkm::Id basicLen = start_pos;
// make an implicit array
ValueHandleType implicit = vtkm::cont::make_ArrayHandleImplicit(functor, implicitLen);
// make a basic array
std::vector<ValueType> basicVec;
for (vtkm::Id i = 0; i < basicLen; i++)
{
basicVec.push_back(ValueType(static_cast<ComponentType>(i)));
basicVec.push_back(ValueType(ComponentType(i)));
}
BasicArrayType basic = vtkm::cont::make_ArrayHandle(basicVec, vtkm::CopyFlag::Off);
// concatenate two arrays together
ConcatenateType concatenate = vtkm::cont::make_ArrayHandleConcatenate(implicit, basic);
vtkm::cont::ArrayHandle<ValueType> result;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(concatenate, result);
//verify that the control portal works
auto resultPortal = result.ReadPortal();
auto implicitPortal = implicit.ReadPortal();
auto basicPortal = basic.ReadPortal();
auto concatPortal = concatenate.ReadPortal();
for (vtkm::Id i = 0; i < length; ++i)
{
const ValueType result_v = resultPortal.Get(i);
ValueType correct_value;
if (i < implicitLen)
correct_value = implicitPortal.Get(i);
else
correct_value = basicPortal.Get(i - implicitLen);
const ValueType control_value = concatPortal.Get(i);
VTKM_TEST_ASSERT(test_equal(result_v, correct_value),
"ArrayHandleConcatenate as Input Failed");
VTKM_TEST_ASSERT(test_equal(result_v, control_value),
"ArrayHandleConcatenate as Input Failed");
}
concatenate.ReleaseResources();
}
}
};
struct TestPermutationAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
const vtkm::Id length = ARRAY_SIZE;
using FunctorType = ::fancy_array_detail::IndexSquared<ValueType>;
using KeyHandleType = vtkm::cont::ArrayHandleCounting<vtkm::Id>;
using ValueHandleType = vtkm::cont::ArrayHandleImplicit<FunctorType>;
using PermutationHandleType =
vtkm::cont::ArrayHandlePermutation<KeyHandleType, ValueHandleType>;
FunctorType functor;
for (vtkm::Id start_pos = 0; start_pos < length; start_pos += length / 4)
{
const vtkm::Id counting_length = length - start_pos;
KeyHandleType counting =
vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(start_pos, 1, counting_length);
ValueHandleType implicit = vtkm::cont::make_ArrayHandleImplicit(functor, length);
PermutationHandleType permutation =
vtkm::cont::make_ArrayHandlePermutation(counting, implicit);
vtkm::cont::ArrayHandle<ValueType> result;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(permutation, result);
//verify that the control portal works
auto resultPortal = result.ReadPortal();
auto implicitPortal = implicit.ReadPortal();
auto permutationPortal = permutation.ReadPortal();
for (vtkm::Id i = 0; i < counting_length; ++i)
{
const vtkm::Id value_index = i;
const vtkm::Id key_index = start_pos + i;
const ValueType result_v = resultPortal.Get(value_index);
const ValueType correct_value = implicitPortal.Get(key_index);
const ValueType control_value = permutationPortal.Get(value_index);
VTKM_TEST_ASSERT(test_equal(result_v, correct_value), "Implicit Handle Failed");
VTKM_TEST_ASSERT(test_equal(result_v, control_value), "Implicit Handle Failed");
}
permutation.ReleaseResources();
}
}
};
struct TestViewAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
const vtkm::Id length = ARRAY_SIZE;
using FunctorType = ::fancy_array_detail::IndexSquared<ValueType>;
using ValueHandleType = vtkm::cont::ArrayHandleImplicit<FunctorType>;
using ViewHandleType = vtkm::cont::ArrayHandleView<ValueHandleType>;
FunctorType functor;
for (vtkm::Id start_pos = 0; start_pos < length; start_pos += length / 4)
{
const vtkm::Id counting_length = length - start_pos;
ValueHandleType implicit = vtkm::cont::make_ArrayHandleImplicit(functor, length);
ViewHandleType view =
vtkm::cont::make_ArrayHandleView(implicit, start_pos, counting_length);
vtkm::cont::ArrayHandle<ValueType> result;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(view, result);
//verify that the control portal works
auto resultPortal = result.ReadPortal();
auto implicitPortal = implicit.ReadPortal();
auto viewPortal = view.ReadPortal();
for (vtkm::Id i = 0; i < counting_length; ++i)
{
const vtkm::Id value_index = i;
const vtkm::Id key_index = start_pos + i;
const ValueType result_v = resultPortal.Get(value_index);
const ValueType correct_value = implicitPortal.Get(key_index);
const ValueType control_value = viewPortal.Get(value_index);
VTKM_TEST_ASSERT(test_equal(result_v, correct_value), "Implicit Handle Failed");
VTKM_TEST_ASSERT(test_equal(result_v, control_value), "Implicit Handle Failed");
}
view.ReleaseResources();
}
}
};
struct TestTransformAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using FunctorType = fancy_array_detail::ValueScale;
const vtkm::Id length = ARRAY_SIZE;
FunctorType functor(2.0);
vtkm::cont::ArrayHandle<ValueType> input;
vtkm::cont::ArrayHandleTransform<vtkm::cont::ArrayHandle<ValueType>, FunctorType>
transformed = vtkm::cont::make_ArrayHandleTransform(input, functor);
input.Allocate(length);
SetPortal(input.WritePortal());
vtkm::cont::ArrayHandle<ValueType> result;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(transformed, result);
//verify that the control portal works
auto resultPortal = result.ReadPortal();
auto transformedPortal = transformed.ReadPortal();
for (vtkm::Id i = 0; i < length; ++i)
{
const ValueType result_v = resultPortal.Get(i);
const ValueType correct_value = functor(TestValue(i, ValueType()));
const ValueType control_value = transformedPortal.Get(i);
VTKM_TEST_ASSERT(test_equal(result_v, correct_value), "Transform Handle Failed");
VTKM_TEST_ASSERT(test_equal(result_v, control_value), "Transform Handle Control Failed");
}
transformed.ReleaseResources();
}
};
struct TestTransformVirtualAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using FunctorType = fancy_array_detail::ValueScale;
using VirtualFunctorType = fancy_array_detail::TransformExecObject<ValueType>;
const vtkm::Id length = ARRAY_SIZE;
FunctorType functor(2.0);
VirtualFunctorType virtualFunctor(functor);
vtkm::cont::ArrayHandle<ValueType> input;
auto transformed = vtkm::cont::make_ArrayHandleTransform(input, virtualFunctor);
input.Allocate(length);
SetPortal(input.WritePortal());
vtkm::cont::ArrayHandle<ValueType> result;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(transformed, result);
//verify that the control portal works
auto resultPortal = result.ReadPortal();
auto transformedPortal = transformed.ReadPortal();
for (vtkm::Id i = 0; i < length; ++i)
{
const ValueType result_v = resultPortal.Get(i);
const ValueType correct_value = functor(TestValue(i, ValueType()));
const ValueType control_value = transformedPortal.Get(i);
VTKM_TEST_ASSERT(test_equal(result_v, correct_value), "Transform Handle Failed");
VTKM_TEST_ASSERT(test_equal(result_v, control_value), "Transform Handle Control Failed");
}
}
};
struct TestCountingTransformAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using ComponentType = typename vtkm::VecTraits<ValueType>::ComponentType;
using OutputValueType = ComponentType;
using FunctorType = fancy_array_detail::ValueSquared<OutputValueType>;
vtkm::Id length = ARRAY_SIZE;
FunctorType functor;
//need to initialize the start value or else vectors will have
//random values to start
ComponentType component_value(0);
const ValueType start = ValueType(component_value);
vtkm::cont::ArrayHandleCounting<ValueType> counting(start, ValueType(1), length);
vtkm::cont::ArrayHandleTransform<vtkm::cont::ArrayHandleCounting<ValueType>, FunctorType>
countingTransformed = vtkm::cont::make_ArrayHandleTransform(counting, functor);
vtkm::cont::ArrayHandle<OutputValueType> result;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(countingTransformed, result);
//verify that the control portal works
auto resultPortal = result.ReadPortal();
auto countingPortal = countingTransformed.ReadPortal();
for (vtkm::Id i = 0; i < length; ++i)
{
const OutputValueType result_v = resultPortal.Get(i);
const OutputValueType correct_value = functor(ValueType(component_value));
const OutputValueType control_value = countingPortal.Get(i);
VTKM_TEST_ASSERT(test_equal(result_v, correct_value), "Transform Counting Handle Failed");
VTKM_TEST_ASSERT(test_equal(result_v, control_value),
"Transform Counting Handle Control Failed");
component_value = ComponentType(component_value + ComponentType(1));
}
countingTransformed.ReleaseResources();
}
};
struct TestCastAsInput
{
template <typename CastToType>
VTKM_CONT void operator()(CastToType vtkmNotUsed(type)) const
{
using InputArrayType = vtkm::cont::ArrayHandleIndex;
InputArrayType input(ARRAY_SIZE);
vtkm::cont::ArrayHandleCast<CastToType, InputArrayType> castArray =
vtkm::cont::make_ArrayHandleCast(input, CastToType());
vtkm::cont::ArrayHandle<CastToType> result;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(castArray, result);
// verify results
vtkm::Id length = ARRAY_SIZE;
auto resultPortal = result.ReadPortal();
auto inputPortal = input.ReadPortal();
for (vtkm::Id i = 0; i < length; ++i)
{
VTKM_TEST_ASSERT(resultPortal.Get(i) == static_cast<CastToType>(inputPortal.Get(i)),
"Casting ArrayHandle Failed");
}
castArray.ReleaseResources();
}
};
struct TestCastAsOutput
{
template <typename CastFromType>
VTKM_CONT void operator()(CastFromType vtkmNotUsed(type)) const
{
using InputArrayType = vtkm::cont::ArrayHandleIndex;
using ResultArrayType = vtkm::cont::ArrayHandle<CastFromType>;
InputArrayType input(ARRAY_SIZE);
ResultArrayType result;
vtkm::cont::ArrayHandleCast<vtkm::Id, ResultArrayType> castArray =
vtkm::cont::make_ArrayHandleCast<CastFromType>(result);
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(input, castArray);
// verify results
vtkm::Id length = ARRAY_SIZE;
auto inputPortal = input.ReadPortal();
auto resultPortal = result.ReadPortal();
for (vtkm::Id i = 0; i < length; ++i)
{
VTKM_TEST_ASSERT(inputPortal.Get(i) == static_cast<vtkm::Id>(resultPortal.Get(i)),
"Casting ArrayHandle Failed");
}
}
};
struct TestMultiplexerAsInput
{
vtkm::cont::Invoker Invoke;
template <typename T>
VTKM_CONT void operator()(T vtkmNotUsed(type)) const
{
using InputArrayType = vtkm::cont::ArrayHandleCounting<T>;
InputArrayType input(T(1), T(2), ARRAY_SIZE);
vtkm::cont::ArrayHandleMultiplexer<
vtkm::cont::ArrayHandle<T>,
InputArrayType,
vtkm::cont::ArrayHandleCast<T, vtkm::cont::ArrayHandleIndex>>
multiplexArray(input);
vtkm::cont::ArrayHandle<T> result;
this->Invoke(PassThrough{}, multiplexArray, result);
// verify results
VTKM_TEST_ASSERT(test_equal_portals(result.ReadPortal(), input.ReadPortal()),
"CastingArrayHandle failed");
multiplexArray.ReleaseResources();
}
};
struct TestMultiplexerAsOutput
{
vtkm::cont::Invoker Invoke;
template <typename CastFromType>
VTKM_CONT void operator()(CastFromType vtkmNotUsed(type)) const
{
using InputArrayType = vtkm::cont::ArrayHandleIndex;
using ResultArrayType = vtkm::cont::ArrayHandle<CastFromType>;
InputArrayType input(ARRAY_SIZE);
ResultArrayType result;
vtkm::cont::ArrayHandleMultiplexer<vtkm::cont::ArrayHandle<vtkm::Id>,
vtkm::cont::ArrayHandleCast<vtkm::Id, ResultArrayType>>
multiplexerArray = vtkm::cont::make_ArrayHandleCast<vtkm::Id>(result);
this->Invoke(PassThrough{}, input, multiplexerArray);
// verify results
VTKM_TEST_ASSERT(test_equal_portals(input.ReadPortal(), result.ReadPortal()),
"Multiplexing ArrayHandle failed");
}
};
template <vtkm::IdComponent NUM_COMPONENTS>
struct TestGroupVecAsInput
{
template <typename ComponentType>
VTKM_CONT void operator()(ComponentType) const
{
using ValueType = vtkm::Vec<ComponentType, NUM_COMPONENTS>;
vtkm::cont::ArrayHandle<ComponentType> baseArray;
baseArray.Allocate(ARRAY_SIZE * NUM_COMPONENTS);
SetPortal(baseArray.WritePortal());
vtkm::cont::ArrayHandleGroupVec<vtkm::cont::ArrayHandle<ComponentType>, NUM_COMPONENTS>
groupArray(baseArray);
VTKM_TEST_ASSERT(groupArray.GetNumberOfValues() == ARRAY_SIZE,
"Group array reporting wrong array size.");
vtkm::cont::ArrayHandle<ValueType> resultArray;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(groupArray, resultArray);
VTKM_TEST_ASSERT(resultArray.GetNumberOfValues() == ARRAY_SIZE, "Got bad result array size.");
//verify that the control portal works
vtkm::Id totalIndex = 0;
auto resultPortal = resultArray.ReadPortal();
for (vtkm::Id index = 0; index < ARRAY_SIZE; ++index)
{
const ValueType result = resultPortal.Get(index);
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS;
componentIndex++)
{
const ComponentType expectedValue = TestValue(totalIndex, ComponentType());
VTKM_TEST_ASSERT(test_equal(result[componentIndex], expectedValue),
"Result array got wrong value.");
totalIndex++;
}
}
groupArray.ReleaseResources();
}
};
template <vtkm::IdComponent NUM_COMPONENTS>
struct TestGroupVecAsOutput
{
template <typename ComponentType>
VTKM_CONT void operator()(ComponentType) const
{
using ValueType = vtkm::Vec<ComponentType, NUM_COMPONENTS>;
vtkm::cont::ArrayHandle<ValueType> baseArray;
baseArray.Allocate(ARRAY_SIZE);
SetPortal(baseArray.WritePortal());
vtkm::cont::ArrayHandle<ComponentType> resultArray;
vtkm::cont::ArrayHandleGroupVec<vtkm::cont::ArrayHandle<ComponentType>, NUM_COMPONENTS>
groupArray(resultArray);
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(baseArray, groupArray);
VTKM_TEST_ASSERT(groupArray.GetNumberOfValues() == ARRAY_SIZE,
"Group array reporting wrong array size.");
VTKM_TEST_ASSERT(resultArray.GetNumberOfValues() == ARRAY_SIZE * NUM_COMPONENTS,
"Got bad result array size.");
//verify that the control portal works
vtkm::Id totalIndex = 0;
auto resultPortal = resultArray.ReadPortal();
for (vtkm::Id index = 0; index < ARRAY_SIZE; ++index)
{
const ValueType expectedValue = TestValue(index, ValueType());
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS;
componentIndex++)
{
const ComponentType result = resultPortal.Get(totalIndex);
VTKM_TEST_ASSERT(test_equal(result, expectedValue[componentIndex]),
"Result array got wrong value.");
totalIndex++;
}
}
}
};
// GroupVecVariable is a bit strange because it supports values of different
// lengths, so a simple pass through worklet will not work. Use custom
// worklets.
struct GroupVariableInputWorklet : public vtkm::worklet::WorkletMapField
{
using ControlSignature = void(FieldIn, FieldOut);
using ExecutionSignature = void(_1, WorkIndex, _2);
template <typename InputType>
VTKM_EXEC void operator()(const InputType& input, vtkm::Id workIndex, vtkm::Id& dummyOut) const
{
using ComponentType = typename InputType::ComponentType;
vtkm::IdComponent expectedSize = static_cast<vtkm::IdComponent>(workIndex + 1);
if (expectedSize != input.GetNumberOfComponents())
{
this->RaiseError("Got unexpected number of components.");
}
vtkm::Id valueIndex = workIndex * (workIndex + 1) / 2;
dummyOut = valueIndex;
for (vtkm::IdComponent componentIndex = 0; componentIndex < expectedSize; componentIndex++)
{
ComponentType expectedValue = TestValue(valueIndex, ComponentType());
if (vtkm::Abs(expectedValue - input[componentIndex]) > 0.000001)
{
this->RaiseError("Got bad value in GroupVariableInputWorklet.");
}
valueIndex++;
}
}
};
struct TestGroupVecVariableAsInput
{
template <typename ComponentType>
VTKM_CONT void operator()(ComponentType) const
{
vtkm::Id sourceArraySize;
vtkm::cont::ArrayHandleCounting<vtkm::IdComponent> numComponentsArray(1, 1, ARRAY_SIZE);
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray =
vtkm::cont::ConvertNumComponentsToOffsets(numComponentsArray, sourceArraySize);
vtkm::cont::ArrayHandle<ComponentType> sourceArray;
sourceArray.Allocate(sourceArraySize);
SetPortal(sourceArray.WritePortal());
vtkm::cont::ArrayHandle<vtkm::Id> dummyArray;
auto groupVecArray = vtkm::cont::make_ArrayHandleGroupVecVariable(sourceArray, offsetsArray);
vtkm::worklet::DispatcherMapField<GroupVariableInputWorklet> dispatcher;
dispatcher.Invoke(groupVecArray, dummyArray);
dummyArray.ReadPortal();
groupVecArray.ReleaseResources();
}
};
// GroupVecVariable is a bit strange because it supports values of different
// lengths, so a simple pass through worklet will not work. Use custom
// worklets.
struct GroupVariableOutputWorklet : public vtkm::worklet::WorkletMapField
{
using ControlSignature = void(FieldIn, FieldOut);
using ExecutionSignature = void(_2, WorkIndex);
template <typename OutputType>
VTKM_EXEC void operator()(OutputType& output, vtkm::Id workIndex) const
{
using ComponentType = typename OutputType::ComponentType;
vtkm::IdComponent expectedSize = static_cast<vtkm::IdComponent>(workIndex + 1);
if (expectedSize != output.GetNumberOfComponents())
{
this->RaiseError("Got unexpected number of components.");
}
vtkm::Id valueIndex = workIndex * (workIndex + 1) / 2;
for (vtkm::IdComponent componentIndex = 0; componentIndex < expectedSize; componentIndex++)
{
output[componentIndex] = TestValue(valueIndex, ComponentType());
valueIndex++;
}
}
};
struct TestGroupVecVariableAsOutput
{
template <typename ComponentType>
VTKM_CONT void operator()(ComponentType) const
{
vtkm::Id sourceArraySize;
vtkm::cont::ArrayHandleCounting<vtkm::IdComponent> numComponentsArray(1, 1, ARRAY_SIZE);
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray = vtkm::cont::ConvertNumComponentsToOffsets(
numComponentsArray, sourceArraySize, DeviceAdapterTag());
vtkm::cont::ArrayHandle<ComponentType> sourceArray;
sourceArray.Allocate(sourceArraySize);
vtkm::worklet::DispatcherMapField<GroupVariableOutputWorklet> dispatcher;
dispatcher.Invoke(vtkm::cont::ArrayHandleIndex(ARRAY_SIZE),
vtkm::cont::make_ArrayHandleGroupVecVariable(sourceArray, offsetsArray));
CheckPortal(sourceArray.ReadPortal());
}
};
struct TestRecombineVecAsInput
{
template <typename T>
VTKM_CONT void operator()(T) const
{
vtkm::cont::ArrayHandle<T> baseArray;
baseArray.Allocate(ARRAY_SIZE);
SetPortal(baseArray.WritePortal());
using VTraits = vtkm::VecTraits<T>;
vtkm::cont::ArrayHandleRecombineVec<typename VTraits::ComponentType> recombinedArray;
for (vtkm::IdComponent cIndex = 0; cIndex < VTraits::NUM_COMPONENTS; ++cIndex)
{
recombinedArray.AppendComponentArray(vtkm::cont::ArrayExtractComponent(baseArray, cIndex));
}
VTKM_TEST_ASSERT(recombinedArray.GetNumberOfComponents() == VTraits::NUM_COMPONENTS);
VTKM_TEST_ASSERT(recombinedArray.GetNumberOfValues() == ARRAY_SIZE);
vtkm::cont::ArrayHandle<T> outputArray;
vtkm::cont::Invoker invoke;
invoke(PassThrough{}, recombinedArray, outputArray);
VTKM_TEST_ASSERT(test_equal_ArrayHandles(baseArray, outputArray));
}
};
struct TestRecombineVecAsOutput
{
template <typename T>
VTKM_CONT void operator()(T) const
{
vtkm::cont::ArrayHandle<T> baseArray;
baseArray.Allocate(ARRAY_SIZE);
SetPortal(baseArray.WritePortal());
vtkm::cont::ArrayHandle<T> outputArray;
outputArray.Allocate(ARRAY_SIZE); // Cannot resize after recombine
using VTraits = vtkm::VecTraits<T>;
vtkm::cont::ArrayHandleRecombineVec<typename VTraits::ComponentType> recombinedArray;
for (vtkm::IdComponent cIndex = 0; cIndex < VTraits::NUM_COMPONENTS; ++cIndex)
{
recombinedArray.AppendComponentArray(
vtkm::cont::ArrayExtractComponent(outputArray, cIndex));
}
VTKM_TEST_ASSERT(recombinedArray.GetNumberOfComponents() == VTraits::NUM_COMPONENTS);
VTKM_TEST_ASSERT(recombinedArray.GetNumberOfValues() == ARRAY_SIZE);
vtkm::cont::Invoker invoke;
invoke(PassThrough{}, baseArray, recombinedArray);
VTKM_TEST_ASSERT(test_equal_ArrayHandles(baseArray, outputArray));
}
};
struct TestZipAsInput
{
template <typename KeyType, typename ValueType>
VTKM_CONT void operator()(vtkm::Pair<KeyType, ValueType> vtkmNotUsed(pair)) const
{
using PairType = vtkm::Pair<KeyType, ValueType>;
using KeyComponentType = typename vtkm::VecTraits<KeyType>::ComponentType;
using ValueComponentType = typename vtkm::VecTraits<ValueType>::ComponentType;
KeyType testKeys[ARRAY_SIZE];
ValueType testValues[ARRAY_SIZE];
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
testKeys[i] = KeyType(static_cast<KeyComponentType>(ARRAY_SIZE - i));
testValues[i] = ValueType(static_cast<ValueComponentType>(i));
}
vtkm::cont::ArrayHandle<KeyType> keys =
vtkm::cont::make_ArrayHandle(testKeys, ARRAY_SIZE, vtkm::CopyFlag::Off);
vtkm::cont::ArrayHandle<ValueType> values =
vtkm::cont::make_ArrayHandle(testValues, ARRAY_SIZE, vtkm::CopyFlag::Off);
vtkm::cont::ArrayHandleZip<vtkm::cont::ArrayHandle<KeyType>,
vtkm::cont::ArrayHandle<ValueType>>
zip = vtkm::cont::make_ArrayHandleZip(keys, values);
vtkm::cont::ArrayHandle<PairType> result;
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(zip, result);
//verify that the control portal works
auto resultPortal = result.ReadPortal();
for (int i = 0; i < ARRAY_SIZE; ++i)
{
const PairType result_v = resultPortal.Get(i);
const PairType correct_value(KeyType(static_cast<KeyComponentType>(ARRAY_SIZE - i)),
ValueType(static_cast<ValueComponentType>(i)));
VTKM_TEST_ASSERT(test_equal(result_v, correct_value), "ArrayHandleZip Failed as input");
}
zip.ReleaseResources();
}
};
struct TestDiscardAsOutput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using DiscardHandleType = vtkm::cont::ArrayHandleDiscard<ValueType>;
const vtkm::Id length = ARRAY_SIZE;
vtkm::cont::ArrayHandle<ValueType> input;
input.Allocate(length);
SetPortal(input.WritePortal());
DiscardHandleType discard;
discard.Allocate(length);
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(input, discard);
// No output to verify since none is stored in memory. Just checking that
// this compiles/runs without errors.
discard.ReleaseResources();
}
};
struct TestPermutationAsOutput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
const vtkm::Id length = ARRAY_SIZE;
using KeyHandleType = vtkm::cont::ArrayHandleCounting<vtkm::Id>;
using ValueHandleType = vtkm::cont::ArrayHandle<ValueType>;
using PermutationHandleType =
vtkm::cont::ArrayHandlePermutation<KeyHandleType, ValueHandleType>;
vtkm::cont::ArrayHandle<ValueType> input;
input.Allocate(length);
SetPortal(input.WritePortal());
ValueHandleType values;
values.Allocate(length * 2);
KeyHandleType counting = vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(length, 1, length);
PermutationHandleType permutation = vtkm::cont::make_ArrayHandlePermutation(counting, values);
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(input, permutation);
//verify that the control portal works
CheckPortal(permutation.ReadPortal());
}
};
struct TestViewAsOutput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
const vtkm::Id length = ARRAY_SIZE;
using ValueHandleType = vtkm::cont::ArrayHandle<ValueType>;
using ViewHandleType = vtkm::cont::ArrayHandleView<ValueHandleType>;
vtkm::cont::ArrayHandle<ValueType> input;
input.Allocate(length);
SetPortal(input.WritePortal());
ValueHandleType values;
values.Allocate(length * 2);
ViewHandleType view = vtkm::cont::make_ArrayHandleView(values, length, length);
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(input, view);
//verify that the control portal works
CheckPortal(view.ReadPortal());
}
};
struct TestTransformAsOutput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using FunctorType = fancy_array_detail::ValueScale;
using InverseFunctorType = fancy_array_detail::InverseValueScale;
const vtkm::Id length = ARRAY_SIZE;
FunctorType functor(2.0);
InverseFunctorType inverseFunctor(2.0);
vtkm::cont::ArrayHandle<ValueType> input;
input.Allocate(length);
SetPortal(input.WritePortal());
vtkm::cont::ArrayHandle<ValueType> output;
auto transformed = vtkm::cont::make_ArrayHandleTransform(output, functor, inverseFunctor);
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(input, transformed);
//verify that the control portal works
auto outputPortal = output.ReadPortal();
auto transformedPortal = transformed.ReadPortal();
for (vtkm::Id i = 0; i < length; ++i)
{
const ValueType result_v = outputPortal.Get(i);
const ValueType correct_value = inverseFunctor(TestValue(i, ValueType()));
const ValueType control_value = transformedPortal.Get(i);
VTKM_TEST_ASSERT(test_equal(result_v, correct_value), "Transform Handle Failed");
VTKM_TEST_ASSERT(test_equal(functor(result_v), control_value),
"Transform Handle Control Failed");
}
}
};
struct TestTransformVirtualAsOutput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using FunctorType = fancy_array_detail::ValueScale;
using InverseFunctorType = fancy_array_detail::InverseValueScale;
using VirtualFunctorType = fancy_array_detail::TransformExecObject<ValueType>;
const vtkm::Id length = ARRAY_SIZE;
FunctorType functor(2.0);
InverseFunctorType inverseFunctor(2.0);
VirtualFunctorType virtualFunctor(functor);
VirtualFunctorType virtualInverseFunctor(inverseFunctor);
vtkm::cont::ArrayHandle<ValueType> input;
input.Allocate(length);
SetPortal(input.WritePortal());
vtkm::cont::ArrayHandle<ValueType> output;
auto transformed =
vtkm::cont::make_ArrayHandleTransform(output, virtualFunctor, virtualInverseFunctor);
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(input, transformed);
//verify that the control portal works
auto outputPortal = output.ReadPortal();
auto transformedPortal = transformed.ReadPortal();
for (vtkm::Id i = 0; i < length; ++i)
{
const ValueType result_v = outputPortal.Get(i);
const ValueType correct_value = inverseFunctor(TestValue(i, ValueType()));
const ValueType control_value = transformedPortal.Get(i);
VTKM_TEST_ASSERT(test_equal(result_v, correct_value), "Transform Handle Failed");
VTKM_TEST_ASSERT(test_equal(functor(result_v), control_value),
"Transform Handle Control Failed");
}
}
};
struct TestZipAsOutput
{
template <typename KeyType, typename ValueType>
VTKM_CONT void operator()(vtkm::Pair<KeyType, ValueType> vtkmNotUsed(pair)) const
{
using PairType = vtkm::Pair<KeyType, ValueType>;
using KeyComponentType = typename vtkm::VecTraits<KeyType>::ComponentType;
using ValueComponentType = typename vtkm::VecTraits<ValueType>::ComponentType;
PairType testKeysAndValues[ARRAY_SIZE];
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
testKeysAndValues[i] = PairType(KeyType(static_cast<KeyComponentType>(ARRAY_SIZE - i)),
ValueType(static_cast<ValueComponentType>(i)));
}
vtkm::cont::ArrayHandle<PairType> input =
vtkm::cont::make_ArrayHandle(testKeysAndValues, ARRAY_SIZE, vtkm::CopyFlag::Off);
vtkm::cont::ArrayHandle<KeyType> result_keys;
vtkm::cont::ArrayHandle<ValueType> result_values;
vtkm::cont::ArrayHandleZip<vtkm::cont::ArrayHandle<KeyType>,
vtkm::cont::ArrayHandle<ValueType>>
result_zip = vtkm::cont::make_ArrayHandleZip(result_keys, result_values);
vtkm::worklet::DispatcherMapField<PassThrough> dispatcher;
dispatcher.Invoke(input, result_zip);
//now the two arrays we have zipped should have data inside them
auto keysPortal = result_keys.ReadPortal();
auto valsPortal = result_values.ReadPortal();
for (int i = 0; i < ARRAY_SIZE; ++i)
{
const KeyType result_key = keysPortal.Get(i);
const ValueType result_value = valsPortal.Get(i);
VTKM_TEST_ASSERT(
test_equal(result_key, KeyType(static_cast<KeyComponentType>(ARRAY_SIZE - i))),
"ArrayHandleZip Failed as input for key");
VTKM_TEST_ASSERT(test_equal(result_value, ValueType(static_cast<ValueComponentType>(i))),
"ArrayHandleZip Failed as input for value");
}
}
};
struct TestZipAsInPlace
{
template <typename ValueType>
VTKM_CONT void operator()(ValueType) const
{
vtkm::cont::ArrayHandle<ValueType> inputValues;
inputValues.Allocate(ARRAY_SIZE);
SetPortal(inputValues.WritePortal());
vtkm::cont::ArrayHandle<ValueType> outputValues;
outputValues.Allocate(ARRAY_SIZE);
vtkm::worklet::DispatcherMapField<InplaceFunctorPair> dispatcher;
dispatcher.Invoke(vtkm::cont::make_ArrayHandleZip(inputValues, outputValues));
CheckPortal(outputValues.ReadPortal());
}
};
using ScalarTypesToTest = vtkm::List<vtkm::UInt8, vtkm::FloatDefault>;
using VectorTypesToTest = vtkm::List<vtkm::Vec2i_8, vtkm::Vec3f_32>;
using ZipTypesToTest = vtkm::List<vtkm::Pair<vtkm::UInt8, vtkm::Id>,
vtkm::Pair<vtkm::Float64, vtkm::Vec4ui_8>,
vtkm::Pair<vtkm::Vec3f_32, vtkm::Vec4i_8>>;
using HandleTypesToTest =
vtkm::List<vtkm::Id, vtkm::Vec2i_32, vtkm::FloatDefault, vtkm::Vec3f_64>;
using CastTypesToTest = vtkm::List<vtkm::Int32, vtkm::UInt32>;
struct TestAll
{
VTKM_CONT void operator()() const
{
std::cout << "Doing FancyArrayHandle tests" << std::endl;
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayPortalSOA" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestArrayPortalSOA(), ScalarTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleSOA as Input" << std::endl;
vtkm::testing::Testing::TryTypes(TestingFancyArrayHandles<DeviceAdapterTag>::TestSOAAsInput(),
VectorTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleSOA as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestSOAAsOutput(), VectorTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleCompositeVector as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestCompositeAsInput(), ScalarTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleConstant as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestConstantAsInput(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleCounting as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestCountingAsInput(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleImplicit as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestImplicitAsInput(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandlePermutation as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestPermutationAsInput(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleView as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestViewAsInput(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleTransform as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestTransformAsInput(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleTransform with virtual as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestTransformVirtualAsInput(),
HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleTransform with Counting as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestCountingTransformAsInput(),
HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleCast as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestCastAsInput(), CastTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleCast as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestCastAsOutput(), CastTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleMultiplexer as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestMultiplexerAsInput(), CastTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleMultiplexer as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestMultiplexerAsOutput(), CastTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleGroupVec<3> as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestGroupVecAsInput<3>(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleGroupVec<4> as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestGroupVecAsInput<4>(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleGroupVec<2> as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestGroupVecAsOutput<2>(), ScalarTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleGroupVec<3> as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestGroupVecAsOutput<3>(), ScalarTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleGroupVecVariable as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestGroupVecVariableAsInput(),
ScalarTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleGroupVecVariable as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestGroupVecVariableAsOutput(),
ScalarTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleRecombineVec as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestRecombineVecAsInput(), HandleTypesToTest{});
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleRecombineVec as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestRecombineVecAsOutput(),
HandleTypesToTest{});
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleZip as Input" << std::endl;
vtkm::testing::Testing::TryTypes(TestingFancyArrayHandles<DeviceAdapterTag>::TestZipAsInput(),
ZipTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandlePermutation as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestPermutationAsOutput(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleView as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestViewAsOutput(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleTransform as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestTransformAsOutput(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleTransform with virtual as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestTransformVirtualAsOutput(),
HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleDiscard as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestDiscardAsOutput(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleZip as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestZipAsOutput(), ZipTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleZip as In Place" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestZipAsInPlace(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleConcatenate as Input" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestConcatenateAsInput(), HandleTypesToTest());
}
};
public:
/// Run a suite of tests to check to see if a DeviceAdapter properly supports
/// all the fancy array handles that vtkm supports. Returns an
/// error code that can be returned from the main function of a test.
///
static VTKM_CONT int Run(int argc, char* argv[])
{
vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(DeviceAdapterTag());
return vtkm::cont::testing::Testing::Run(TestAll(), argc, argv);
}
};
}
}
} // namespace vtkm::cont::testing
#endif //vtk_m_cont_testing_TestingFancyArrayHandles_h