Allow ArrayExtractComponent to work with Vec-like value types

Before, `ArrayExtractComponent` only worked with `Vec` types. Anything
that was not specifically a `Vec` was assumed to be a basic component
even if it had `VecTraits`. This was changed to extract components out
of anything that has `VecTraits`. The assumption is that all components
of the Vec-like object are packed tightly in the object.

This allows `ArrayExtractComponent` to work with objects like
`vtkm::Range` and `vtkm::Bounds` and extract their parts as expected.
This commit is contained in:
Kenneth Moreland 2022-01-25 10:36:03 -07:00
parent f48b4b761e
commit ca032801a8
2 changed files with 66 additions and 10 deletions

@ -93,23 +93,52 @@ template <>
struct ArrayExtractComponentImpl<vtkm::cont::StorageTagStride> struct ArrayExtractComponentImpl<vtkm::cont::StorageTagStride>
{ {
template <typename T> template <typename T>
vtkm::cont::ArrayHandleStride<T> operator()( vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType> operator()(
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagStride>& src, const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagStride>& src,
vtkm::IdComponent componentIndex, vtkm::IdComponent componentIndex,
vtkm::CopyFlag vtkmNotUsed(allowCopy)) const vtkm::CopyFlag allowCopy) const
{ {
VTKM_ASSERT(componentIndex == 0); return this->DoExtract(
return src; src, componentIndex, allowCopy, typename vtkm::VecTraits<T>::HasMultipleComponents{});
} }
template <typename T, vtkm::IdComponent N> private:
auto operator()(const vtkm::cont::ArrayHandle<vtkm::Vec<T, N>, vtkm::cont::StorageTagStride>& src, template <typename T>
vtkm::IdComponent componentIndex, auto DoExtract(const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagStride>& src,
vtkm::CopyFlag allowCopy) const vtkm::IdComponent componentIndex,
-> decltype((*this)(vtkm::cont::ArrayHandleStride<T>{}, componentIndex, allowCopy)) vtkm::CopyFlag vtkmNotUsed(allowCopy),
vtkm::VecTraitsTagSingleComponent) const
{ {
VTKM_ASSERT(componentIndex == 0);
using VTraits = vtkm::VecTraits<T>;
using TBase = typename VTraits::BaseComponentType;
VTKM_STATIC_ASSERT(VTraits::NUM_COMPONENTS == 1);
vtkm::cont::ArrayHandleStride<T> array(src);
// Note, we are initializing the result in this strange way for cases where type
// T has a single component but does not equal its own BaseComponentType. A vtkm::Vec
// of size 1 fits into this category.
return vtkm::cont::ArrayHandleStride<TBase>(array.GetBuffers()[1],
array.GetNumberOfValues(),
array.GetStride(),
array.GetOffset(),
array.GetModulo(),
array.GetDivisor());
}
template <typename VecType>
auto DoExtract(const vtkm::cont::ArrayHandle<VecType, vtkm::cont::StorageTagStride>& src,
vtkm::IdComponent componentIndex,
vtkm::CopyFlag allowCopy,
vtkm::VecTraitsTagMultipleComponents) const
{
using VTraits = vtkm::VecTraits<VecType>;
using T = typename VTraits::ComponentType;
constexpr vtkm::IdComponent N = VTraits::NUM_COMPONENTS;
constexpr vtkm::IdComponent subStride = vtkm::internal::TotalNumComponents<T>::value; constexpr vtkm::IdComponent subStride = vtkm::internal::TotalNumComponents<T>::value;
vtkm::cont::ArrayHandleStride<vtkm::Vec<T, N>> array(src); vtkm::cont::ArrayHandleStride<VecType> array(src);
vtkm::cont::ArrayHandleStride<T> tmpIn(array.GetBuffers()[1], vtkm::cont::ArrayHandleStride<T> tmpIn(array.GetBuffers()[1],
array.GetNumberOfValues(), array.GetNumberOfValues(),
array.GetStride() * N, array.GetStride() * N,

@ -13,6 +13,9 @@
#include <vtkm/cont/ArrayHandleCast.h> #include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/ArrayHandleIndex.h> #include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/Bounds.h>
#include <vtkm/Range.h>
#include <vtkm/cont/testing/Testing.h> #include <vtkm/cont/testing/Testing.h>
namespace namespace
@ -145,11 +148,35 @@ void TryCopy()
} }
} }
void TryRange()
{
std::cout << "Trying vtkm::Range" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Range> values =
vtkm::cont::make_ArrayHandle<vtkm::Range>({ { 0.0, 1.0 }, { 1.0, 2.0 }, { 2.0, 4.0 } });
vtkm::Range range = vtkm::cont::ArrayGetValue(1, values);
VTKM_TEST_ASSERT(range == vtkm::Range{ 1.0, 2.0 });
}
void TryBounds()
{
std::cout << "Trying vtkm::Bounds" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Bounds> values =
vtkm::cont::make_ArrayHandle<vtkm::Bounds>({ { { 0.0, 1.0 }, { 0.0, 1.0 }, { 0.0, 1.0 } },
{ { 1.0, 2.0 }, { 1.0, 2.0 }, { 1.0, 2.0 } },
{ { 2.0, 4.0 }, { 2.0, 4.0 }, { 2.0, 4.0 } } });
vtkm::Bounds bounds = vtkm::cont::ArrayGetValue(1, values);
VTKM_TEST_ASSERT(bounds == vtkm::Bounds{ { 1.0, 2.0 }, { 1.0, 2.0 }, { 1.0, 2.0 } });
}
void Test() void Test()
{ {
TryCopy<vtkm::Id>(); TryCopy<vtkm::Id>();
TryCopy<vtkm::IdComponent>(); TryCopy<vtkm::IdComponent>();
TryCopy<vtkm::Float32>(); TryCopy<vtkm::Float32>();
TryRange();
TryBounds();
} }
} // anonymous namespace } // anonymous namespace