Support component extraction from ArrayHandleConstant better

Previously, `ArrayHandleConstant` did not really support component
extraction. Instead, it let a fallback operation create a full array on
the CPU.

Component extraction is now quite efficient for `ArrayHandleConstant`. It
creates a basic `ArrayHandle` with one entry and sets a modulo on the
`ArrayHandleStride` to access that value for all indices.
This commit is contained in:
Kenneth Moreland 2023-08-04 14:09:36 -06:00
parent 969e55048b
commit 14460dbb31
5 changed files with 64 additions and 1 deletions

@ -0,0 +1,9 @@
# Added support for component extraction from ArrayHandleConstant better
Previously, `ArrayHandleConstant` did not really support component
extraction. Instead, it let a fallback operation create a full array on
the CPU.
Component extraction is now quite efficient for `ArrayHandleConstant`. It
creates a basic `ArrayHandle` with one entry and sets a modulo on the
`ArrayHandleStride` to access that value for all indices.

@ -10,6 +10,7 @@
#ifndef vtk_m_cont_ArrayHandleConstant_h
#define vtk_m_cont_ArrayHandleConstant_h
#include <vtkm/cont/ArrayExtractComponent.h>
#include <vtkm/cont/ArrayHandleImplicit.h>
#include <vtkm/cont/internal/ArrayRangeComputeUtils.h>
@ -100,6 +101,33 @@ vtkm::cont::ArrayHandleConstant<T> make_ArrayHandleConstant(T value, vtkm::Id nu
namespace internal
{
template <>
struct VTKM_CONT_EXPORT ArrayExtractComponentImpl<vtkm::cont::StorageTagConstant>
{
template <typename T>
VTKM_CONT auto operator()(const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagConstant>& src,
vtkm::IdComponent componentIndex,
vtkm::CopyFlag allowCopy) const
{
if (allowCopy != vtkm::CopyFlag::On)
{
throw vtkm::cont::ErrorBadValue(
"Cannot extract component of ArrayHandleConstant without copying. "
"(However, the whole array does not need to be copied.)");
}
vtkm::cont::ArrayHandleConstant<T> srcArray = src;
vtkm::VecFlat<T> vecValue{ srcArray.GetValue() };
// Make a basic array with one entry (the constant value).
auto basicArray = vtkm::cont::make_ArrayHandle({ vecValue[componentIndex] });
// Set up a modulo = 1 so all indices go to this one value.
return vtkm::cont::make_ArrayHandleStride(basicArray, src.GetNumberOfValues(), 1, 0, 1, 1);
}
};
template <typename S>
struct ArrayRangeComputeImpl;

@ -375,6 +375,20 @@ public:
}
};
/// @brief Create an array by adding a stride to a basic array.
///
template <typename T>
vtkm::cont::ArrayHandleStride<T> make_ArrayHandleStride(
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>& array,
vtkm::Id numValues,
vtkm::Id stride,
vtkm::Id offset,
vtkm::Id modulo = 0,
vtkm::Id divisor = 1)
{
return { array, numValues, stride, offset, modulo, divisor };
}
}
} // namespace vtkm::cont

@ -11,7 +11,6 @@
#define vtk_m_cont_ArrayHandleUniformPointCoordinates_h
#include <vtkm/Range.h>
#include <vtkm/cont/ArrayExtractComponent.h>
#include <vtkm/cont/ArrayHandleImplicit.h>
#include <vtkm/internal/ArrayPortalUniformPointCoordinates.h>
@ -68,9 +67,15 @@ public:
VTKM_CONT vtkm::Vec3f GetSpacing() const;
};
template <typename T>
class ArrayHandleStride;
namespace internal
{
template <typename S>
struct ArrayExtractComponentImpl;
template <>
struct VTKM_CONT_EXPORT ArrayExtractComponentImpl<vtkm::cont::StorageTagUniformPoints>
{

@ -12,6 +12,7 @@
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
#include <vtkm/cont/ArrayHandleCompositeVector.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleExtractComponent.h>
#include <vtkm/cont/ArrayHandleGroupVec.h>
#include <vtkm/cont/ArrayHandleIndex.h>
@ -283,6 +284,12 @@ void DoTest()
CheckInputArray(array, vtkm::CopyFlag::On);
}
{
std::cout << "ArrayHandleConstant" << std::endl;
vtkm::cont::ArrayHandleConstant<vtkm::Vec3f> array(TestValue(0, vtkm::Vec3f{}), ARRAY_SIZE);
CheckInputArray(array, vtkm::CopyFlag::On);
}
{
std::cout << "Weird combination." << std::endl;