vtk-m/vtkm/cont/testing/UnitTestArrayHandleView.cxx
Kenneth Moreland 9b992dcdde Add GetNumberOfComponentsFlat method to ArrayHandle
Getting the number of components (or the number of flattened components)
from an `ArrayHandle` is usually trivial. However, if the `ArrayHandle` is
special in that the number of components is specified at runtime, then it
becomes much more difficult to determine.

Getting the number of components is most important when extracting
component arrays (or reconstructions using component arrays) with
`UnknownArrayHandle`. Previously, `UnknownArrayHandle` used a hack to get
the number of components, which mostly worked but broke down when wrapping
a runtime array inside another array such as `ArrayHandleView`.

To prevent this issue, the ability to get the number of components has been
added to `ArrayHandle` proper. All `Storage` objects for `ArrayHandle`s now
need a method named `GetNumberOfComponentsFlat`. The implementation of this
method is usually trivial. The `ArrayHandle` template now also provides a
`GetNumberOfComponentsFlat` method that gets this information from the
`Storage`. This provides an easy access point for the `UnknownArrayHandle`
to pull this information.
2023-10-03 10:31:38 -04:00

149 lines
4.7 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.
//============================================================================
#include <vtkm/cont/ArrayHandleView.h>
#include <vtkm/cont/Invoker.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
constexpr vtkm::Id ARRAY_SIZE = 10;
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));
}
};
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 TestViewAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using FunctorType = IndexSquared<ValueType>;
using ValueHandleType = vtkm::cont::ArrayHandleImplicit<FunctorType>;
using ViewHandleType = vtkm::cont::ArrayHandleView<ValueHandleType>;
FunctorType functor;
for (vtkm::Id start_pos = 0; start_pos < ARRAY_SIZE; start_pos += ARRAY_SIZE / 4)
{
const vtkm::Id counting_ARRAY_SIZE = ARRAY_SIZE - start_pos;
ValueHandleType implicit = vtkm::cont::make_ArrayHandleImplicit(functor, ARRAY_SIZE);
ViewHandleType view =
vtkm::cont::make_ArrayHandleView(implicit, start_pos, counting_ARRAY_SIZE);
VTKM_TEST_ASSERT(view.GetNumberOfComponentsFlat() ==
vtkm::VecFlat<ValueType>::NUM_COMPONENTS);
VTKM_TEST_ASSERT(view.GetNumberOfValues() == counting_ARRAY_SIZE);
vtkm::cont::ArrayHandle<ValueType> result;
vtkm::cont::Invoker invoke;
invoke(PassThrough{}, 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_ARRAY_SIZE; ++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 TestViewAsOutput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using ValueHandleType = vtkm::cont::ArrayHandle<ValueType>;
using ViewHandleType = vtkm::cont::ArrayHandleView<ValueHandleType>;
vtkm::cont::ArrayHandle<ValueType> input;
input.Allocate(ARRAY_SIZE);
SetPortal(input.WritePortal());
ValueHandleType values;
values.Allocate(ARRAY_SIZE * 2);
ViewHandleType view = vtkm::cont::make_ArrayHandleView(values, ARRAY_SIZE, ARRAY_SIZE);
vtkm::cont::Invoker invoke;
invoke(PassThrough{}, input, view);
//verify that the control portal works
CheckPortal(view.ReadPortal());
//verify that filling works
const ValueType expected = TestValue(20, ValueType{});
view.Fill(expected);
auto valuesPortal = values.ReadPortal();
for (vtkm::Id index = ARRAY_SIZE; index < 2 * ARRAY_SIZE; ++index)
{
VTKM_TEST_ASSERT(valuesPortal.Get(index) == expected);
}
}
};
void Run()
{
using HandleTypesToTest =
vtkm::List<vtkm::Id, vtkm::Vec2i_32, vtkm::FloatDefault, vtkm::Vec3f_64>;
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleView as Input" << std::endl;
vtkm::testing::Testing::TryTypes(TestViewAsInput(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleView as Output" << std::endl;
vtkm::testing::Testing::TryTypes(TestViewAsOutput(), HandleTypesToTest());
}
} // anonymous namespace
int UnitTestArrayHandleView(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Run, argc, argv);
}