vtk-m2/vtkm/cont/testing/UnitTestArrayExtractComponent.cxx
Kenneth Moreland 0f24f82dad Disable resizing of ArrayHandleStride
The typical use case of `ArrayHandleStride` is to flexibly point into
another array, often looking at a single component in an array. It is
typical that multiple things will be accessing the same array, and bad
things could happen as they all try to resize. There was some code to
try to figure out what the size of the original array was, but it was
fragile.

It is safer for now to disable the behavior altogether. If a use case
pops up, we can reintroduce the code.
2020-12-16 17:22:44 -07:00

251 lines
8.9 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/ArrayExtractComponent.h>
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
#include <vtkm/cont/ArrayHandleCompositeVector.h>
#include <vtkm/cont/ArrayHandleExtractComponent.h>
#include <vtkm/cont/ArrayHandleGroupVec.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ArrayHandleMultiplexer.h>
#include <vtkm/cont/ArrayHandleReverse.h>
#include <vtkm/cont/ArrayHandleSOA.h>
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/ArrayHandleView.h>
#include <vtkm/VecFlat.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
constexpr vtkm::Id ARRAY_SIZE = 10;
template <typename T, typename S>
void CheckInputArray(const vtkm::cont::ArrayHandle<T, S>& originalArray,
vtkm::CopyFlag allowCopy = vtkm::CopyFlag::Off)
{
//std::cout << " Checking input array type "
// << vtkm::cont::TypeToString<vtkm::cont::ArrayHandle<T, S>>() << std::endl;
//std::cout << " Original array: ";
//vtkm::cont::printSummary_ArrayHandle(originalArray, std::cout);
using FlatVec = vtkm::VecFlat<T>;
using ComponentType = typename FlatVec::ComponentType;
for (vtkm::IdComponent componentId = 0; componentId < FlatVec::NUM_COMPONENTS; ++componentId)
{
vtkm::cont::ArrayHandleStride<ComponentType> componentArray =
vtkm::cont::ArrayExtractComponent(originalArray, componentId, allowCopy);
//std::cout << " Component " << componentId << ": ";
//vtkm::cont::printSummary_ArrayHandle(componentArray, std::cout);
auto originalPortal = originalArray.ReadPortal();
auto componentPortal = componentArray.ReadPortal();
VTKM_TEST_ASSERT(originalPortal.GetNumberOfValues() == componentPortal.GetNumberOfValues());
for (vtkm::Id arrayIndex = 0; arrayIndex < originalArray.GetNumberOfValues(); ++arrayIndex)
{
auto originalValue = vtkm::make_VecFlat(originalPortal.Get(arrayIndex));
ComponentType componentValue = componentPortal.Get(arrayIndex);
VTKM_TEST_ASSERT(test_equal(originalValue[componentId], componentValue));
}
}
}
template <typename T, typename S>
void CheckOutputArray(const vtkm::cont::ArrayHandle<T, S>& originalArray)
{
CheckInputArray(originalArray);
//std::cout << " Checking output array type "
// << vtkm::cont::TypeToString<vtkm::cont::ArrayHandle<T, S>>() << std::endl;
//std::cout << " Original array: ";
//vtkm::cont::printSummary_ArrayHandle(originalArray, std::cout);
vtkm::cont::ArrayHandle<T, S> outputArray;
outputArray.Allocate(originalArray.GetNumberOfValues());
using FlatVec = vtkm::VecFlat<T>;
using ComponentType = typename FlatVec::ComponentType;
constexpr vtkm::IdComponent numComponents = FlatVec::NUM_COMPONENTS;
for (vtkm::IdComponent componentId = 0; componentId < numComponents; ++componentId)
{
vtkm::cont::ArrayHandleStride<ComponentType> inComponentArray =
vtkm::cont::ArrayExtractComponent(originalArray, numComponents - componentId - 1);
vtkm::cont::ArrayHandleStride<ComponentType> outComponentArray =
vtkm::cont::ArrayExtractComponent(outputArray, componentId, vtkm::CopyFlag::Off);
auto inPortal = inComponentArray.ReadPortal();
auto outPortal = outComponentArray.WritePortal();
VTKM_TEST_ASSERT(inComponentArray.GetNumberOfValues() == originalArray.GetNumberOfValues());
VTKM_TEST_ASSERT(outComponentArray.GetNumberOfValues() == originalArray.GetNumberOfValues());
for (vtkm::Id arrayIndex = 0; arrayIndex < originalArray.GetNumberOfValues(); ++arrayIndex)
{
outPortal.Set(arrayIndex, inPortal.Get(arrayIndex));
}
}
//std::cout << " Output array: ";
//vtkm::cont::printSummary_ArrayHandle(outputArray, std::cout);
auto inPortal = originalArray.ReadPortal();
auto outPortal = outputArray.ReadPortal();
for (vtkm::Id arrayIndex = 0; arrayIndex < originalArray.GetNumberOfValues(); ++arrayIndex)
{
FlatVec inValue = vtkm::make_VecFlat(inPortal.Get(arrayIndex));
FlatVec outValue = vtkm::make_VecFlat(outPortal.Get(arrayIndex));
for (vtkm::IdComponent componentId = 0; componentId < numComponents; ++componentId)
{
VTKM_TEST_ASSERT(test_equal(inValue[componentId], outValue[numComponents - componentId - 1]));
}
}
}
void DoTest()
{
using ArrayMultiplexerType =
vtkm::cont::ArrayHandleMultiplexer<vtkm::cont::ArrayHandleBasic<vtkm::Vec3f>,
vtkm::cont::ArrayHandleSOA<vtkm::Vec3f>>;
{
std::cout << "Basic array" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Vec3f> array;
array.Allocate(ARRAY_SIZE);
SetPortal(array.WritePortal());
CheckOutputArray(array);
std::cout << "ArrayHandleExtractComponent" << std::endl;
CheckOutputArray(vtkm::cont::make_ArrayHandleExtractComponent(array, 1));
std::cout << "ArrayHandleMultiplexer" << std::endl;
CheckInputArray(ArrayMultiplexerType(array));
}
{
std::cout << "SOA array" << std::endl;
vtkm::cont::ArrayHandleSOA<vtkm::Vec3f> array;
array.Allocate(ARRAY_SIZE);
SetPortal(array.WritePortal());
CheckOutputArray(array);
CheckInputArray(ArrayMultiplexerType(array));
}
{
std::cout << "Stride array" << std::endl;
constexpr vtkm::Id STRIDE = 7;
vtkm::cont::ArrayHandleBasic<vtkm::Vec3f> originalArray;
originalArray.Allocate(ARRAY_SIZE * STRIDE);
for (vtkm::Id offset = 0; offset < STRIDE; ++offset)
{
vtkm::cont::ArrayHandleStride<vtkm::Vec3f> strideArray(
originalArray, ARRAY_SIZE, STRIDE, offset);
CheckInputArray(strideArray);
}
}
{
std::cout << "ArrayHandleGroupVec" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Vec3f> array;
array.Allocate(ARRAY_SIZE * 2);
SetPortal(array.WritePortal());
CheckOutputArray(vtkm::cont::make_ArrayHandleGroupVec<2>(array));
}
{
std::cout << "ArrayHandleCompositeVector" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Vec3f> array0;
vtkm::cont::ArrayHandle<vtkm::Vec3f> array1;
array0.Allocate(ARRAY_SIZE);
array1.Allocate(ARRAY_SIZE);
SetPortal(array0.WritePortal());
SetPortal(array1.WritePortal());
auto compositeArray = vtkm::cont::make_ArrayHandleCompositeVector(array0, array1);
CheckOutputArray(compositeArray);
CheckOutputArray(vtkm::cont::make_ArrayHandleExtractComponent(compositeArray, 1));
}
{
std::cout << "ArrayHandleCartesianProduct" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Float64> array0;
vtkm::cont::ArrayHandle<vtkm::Float64> array1;
vtkm::cont::ArrayHandle<vtkm::Float64> array2;
array0.Allocate(ARRAY_SIZE);
array1.Allocate(ARRAY_SIZE / 2);
array2.Allocate(ARRAY_SIZE + 2);
SetPortal(array0.WritePortal());
SetPortal(array1.WritePortal());
SetPortal(array2.WritePortal());
CheckInputArray(vtkm::cont::make_ArrayHandleCartesianProduct(array0, array1, array2));
}
{
std::cout << "ArrayHandleUniformPointCoordinates" << std::endl;
vtkm::cont::ArrayHandleUniformPointCoordinates array(
vtkm::Id3{ ARRAY_SIZE, ARRAY_SIZE + 2, ARRAY_SIZE / 2 });
CheckInputArray(array, vtkm::CopyFlag::On);
}
{
std::cout << "ArrayHandleReverse" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Vec3f> array;
array.Allocate(ARRAY_SIZE);
SetPortal(array.WritePortal());
CheckOutputArray(vtkm::cont::make_ArrayHandleReverse(array));
}
{
std::cout << "ArrayHandleView" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Vec3f> array;
array.Allocate(ARRAY_SIZE);
SetPortal(array.WritePortal());
CheckInputArray(
vtkm::cont::make_ArrayHandleView(array, (ARRAY_SIZE / 3), (ARRAY_SIZE / 3) + 1));
}
{
std::cout << "ArrayHandleIndex" << std::endl;
vtkm::cont::ArrayHandleIndex array(ARRAY_SIZE);
CheckInputArray(array, vtkm::CopyFlag::On);
}
{
std::cout << "Weird combination." << std::endl;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Vec4f, 2>> base0;
base0.Allocate(ARRAY_SIZE);
SetPortal(base0.WritePortal());
vtkm::cont::ArrayHandleSOA<vtkm::Vec4f> base1_sub;
base1_sub.Allocate(ARRAY_SIZE);
SetPortal(base1_sub.WritePortal());
auto base1 = vtkm::cont::make_ArrayHandleGroupVec<2>(base1_sub);
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Vec4f, 2>> base2_sub;
base2_sub.Allocate(ARRAY_SIZE + 10);
SetPortal(base2_sub.WritePortal());
auto base2 = vtkm::cont::make_ArrayHandleView(base2_sub, 2, ARRAY_SIZE + 4);
auto array = vtkm::cont::make_ArrayHandleCartesianProduct(base0, base1, base2);
CheckInputArray(array);
}
}
} // anonymous namespace
int UnitTestArrayExtractComponent(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoTest, argc, argv);
}