Merge topic 'vectraits-range'

ca032801a Allow ArrayExtractComponent to work with Vec-like value types
f48b4b761 Add implementation of VecTraits for Range and Bounds

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Gunther Weber <ghweber@lbl.gov>
Merge-request: !2683
This commit is contained in:
Kenneth Moreland 2022-01-31 15:15:07 +00:00 committed by Kitware Robot
commit 45e9b7fa76
7 changed files with 255 additions and 11 deletions

@ -0,0 +1,6 @@
# Add implementation of `VecTraits` for `Range` and `Bounds`
Added specializations of `vtkm::VecTraits` for the simple structures of
`vtkm::Range` and `vtkm::Bounds`. This expands the support for using these
structures in things like `ArrayHandle` and `UnknownArrayHandle`.

@ -218,11 +218,98 @@ struct Bounds
/// Helper function for printing bounds during testing
///
static inline VTKM_CONT std::ostream& operator<<(std::ostream& stream, const vtkm::Bounds& bounds)
inline VTKM_CONT std::ostream& operator<<(std::ostream& stream, const vtkm::Bounds& bounds)
{
return stream << "{ X:" << bounds.X << ", Y:" << bounds.Y << ", Z:" << bounds.Z << " }";
}
template <>
struct VTKM_NEVER_EXPORT VecTraits<vtkm::Bounds>
{
using ComponentType = vtkm::Range;
using BaseComponentType = vtkm::VecTraits<vtkm::Range>::BaseComponentType;
static constexpr vtkm::IdComponent NUM_COMPONENTS = 3;
static constexpr vtkm::IdComponent GetNumberOfComponents(const vtkm::Bounds&)
{
return NUM_COMPONENTS;
}
using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents;
using IsSizeStatic = vtkm::VecTraitsTagSizeStatic;
VTKM_EXEC_CONT
static const ComponentType& GetComponent(const vtkm::Bounds& bounds, vtkm::IdComponent component)
{
VTKM_ASSERT((component >= 0) || (component < 3));
switch (component)
{
case 0:
return bounds.X;
case 1:
return bounds.Y;
case 2:
return bounds.Z;
default:
// Should never reach here
return bounds.X;
}
}
VTKM_EXEC_CONT
static ComponentType& GetComponent(vtkm::Bounds& bounds, vtkm::IdComponent component)
{
VTKM_ASSERT((component >= 0) || (component < 3));
switch (component)
{
case 0:
return bounds.X;
case 1:
return bounds.Y;
case 2:
return bounds.Z;
default:
// Should never reach here
return bounds.X;
}
}
VTKM_EXEC_CONT
static void SetComponent(vtkm::Bounds& bounds,
vtkm::IdComponent component,
const ComponentType& value)
{
VTKM_ASSERT((component >= 0) || (component < 3));
switch (component)
{
case 0:
bounds.X = value;
break;
case 1:
bounds.Y = value;
break;
case 2:
bounds.Z = value;
break;
}
}
template <typename NewComponentType>
using ReplaceComponentType = vtkm::Vec<NewComponentType, NUM_COMPONENTS>;
template <typename NewComponentType>
using ReplaceBaseComponentType =
vtkm::Vec<NewComponentType, NUM_COMPONENTS * vtkm::VecTraits<vtkm::Range>::NUM_COMPONENTS>;
template <vtkm::IdComponent destSize>
VTKM_EXEC_CONT static void CopyInto(const vtkm::Bounds& src,
vtkm::Vec<ComponentType, destSize>& dest)
{
const vtkm::IdComponent maxComponent = (destSize < NUM_COMPONENTS) ? destSize : NUM_COMPONENTS;
for (vtkm::IdComponent component = 0; component < maxComponent; ++component)
{
dest[component] = GetComponent(src, component);
}
}
};
} // namespace vtkm
#endif //vtk_m_Bounds_h

@ -14,6 +14,7 @@
#include <vtkm/Assert.h>
#include <vtkm/Math.h>
#include <vtkm/Types.h>
#include <vtkm/VecTraits.h>
namespace vtkm
{
@ -185,6 +186,65 @@ inline VTKM_CONT std::ostream& operator<<(std::ostream& stream, const vtkm::Rang
{
return stream << "[" << range.Min << ".." << range.Max << "]";
} // Declared inside of vtkm namespace so that the operator work with ADL lookup
template <>
struct VTKM_NEVER_EXPORT VecTraits<vtkm::Range>
{
using ComponentType = vtkm::Float64;
using BaseComponentType = vtkm::Float64;
static constexpr vtkm::IdComponent NUM_COMPONENTS = 2;
static constexpr vtkm::IdComponent GetNumberOfComponents(const vtkm::Range&)
{
return NUM_COMPONENTS;
}
using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents;
using IsSizeStatic = vtkm::VecTraitsTagSizeStatic;
VTKM_EXEC_CONT
static const ComponentType& GetComponent(const vtkm::Range& range, vtkm::IdComponent component)
{
VTKM_ASSERT((component == 0) || (component == 1));
return (component == 0) ? range.Min : range.Max;
}
VTKM_EXEC_CONT
static ComponentType& GetComponent(vtkm::Range& range, vtkm::IdComponent component)
{
VTKM_ASSERT((component == 0) || (component == 1));
return (component == 0) ? range.Min : range.Max;
}
VTKM_EXEC_CONT
static void SetComponent(vtkm::Range& range, vtkm::IdComponent component, ComponentType value)
{
VTKM_ASSERT((component == 0) || (component == 1));
if (component == 0)
{
range.Min = value;
}
else
{
range.Max = value;
}
}
template <typename NewComponentType>
using ReplaceComponentType = vtkm::Vec<NewComponentType, NUM_COMPONENTS>;
template <typename NewComponentType>
using ReplaceBaseComponentType = vtkm::Vec<NewComponentType, NUM_COMPONENTS>;
template <vtkm::IdComponent destSize>
VTKM_EXEC_CONT static void CopyInto(const vtkm::Range& src,
vtkm::Vec<ComponentType, destSize>& dest)
{
const vtkm::IdComponent maxComponent = (destSize < NUM_COMPONENTS) ? destSize : NUM_COMPONENTS;
for (vtkm::IdComponent component = 0; component < maxComponent; ++component)
{
dest[component] = GetComponent(src, component);
}
}
};
} // namespace vtkm

@ -93,23 +93,52 @@ template <>
struct ArrayExtractComponentImpl<vtkm::cont::StorageTagStride>
{
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,
vtkm::IdComponent componentIndex,
vtkm::CopyFlag vtkmNotUsed(allowCopy)) const
vtkm::CopyFlag allowCopy) const
{
VTKM_ASSERT(componentIndex == 0);
return src;
return this->DoExtract(
src, componentIndex, allowCopy, typename vtkm::VecTraits<T>::HasMultipleComponents{});
}
template <typename T, vtkm::IdComponent N>
auto operator()(const vtkm::cont::ArrayHandle<vtkm::Vec<T, N>, vtkm::cont::StorageTagStride>& src,
vtkm::IdComponent componentIndex,
vtkm::CopyFlag allowCopy) const
-> decltype((*this)(vtkm::cont::ArrayHandleStride<T>{}, componentIndex, allowCopy))
private:
template <typename T>
auto DoExtract(const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagStride>& src,
vtkm::IdComponent componentIndex,
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;
vtkm::cont::ArrayHandleStride<vtkm::Vec<T, N>> array(src);
vtkm::cont::ArrayHandleStride<VecType> array(src);
vtkm::cont::ArrayHandleStride<T> tmpIn(array.GetBuffers()[1],
array.GetNumberOfValues(),
array.GetStride() * N,

@ -13,6 +13,9 @@
#include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/Bounds.h>
#include <vtkm/Range.h>
#include <vtkm/cont/testing/Testing.h>
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()
{
TryCopy<vtkm::Id>();
TryCopy<vtkm::IdComponent>();
TryCopy<vtkm::Float32>();
TryRange();
TryBounds();
}
} // anonymous namespace

@ -9,6 +9,7 @@
//============================================================================
#include <vtkm/Bounds.h>
#include <vtkm/VecTraits.h>
#include <vtkm/testing/Testing.h>
@ -130,6 +131,23 @@ void TestBounds()
VTKM_TEST_ASSERT(unionBounds.Contains(Vec3(4)), "Contains fail");
VTKM_TEST_ASSERT(unionBounds.Contains(Vec3(17, 3, 7)), "Contains fail");
VTKM_TEST_ASSERT(unionBounds.Contains(Vec3(25)), "Contains fail");
std::cout << "Try VecTraits." << std::endl;
using VTraits = vtkm::VecTraits<vtkm::Bounds>;
VTKM_TEST_ASSERT(VTraits::NUM_COMPONENTS == 3);
vtkm::Bounds simpleBounds{ { 0.0, 1.0 }, { 2.0, 4.0 }, { 8.0, 16.0 } };
VTKM_TEST_ASSERT(VTraits::GetNumberOfComponents(simpleBounds) == 3);
VTKM_TEST_ASSERT(VTraits::GetComponent(simpleBounds, 0) == vtkm::Range{ 0.0, 1.0 });
VTKM_TEST_ASSERT(VTraits::GetComponent(simpleBounds, 1) == vtkm::Range{ 2.0, 4.0 });
VTKM_TEST_ASSERT(VTraits::GetComponent(simpleBounds, 2) == vtkm::Range{ 8.0, 16.0 });
vtkm::Vec<vtkm::Range, 3> simpleBoundsCopy;
VTraits::CopyInto(simpleBounds, simpleBoundsCopy);
VTKM_TEST_ASSERT(simpleBoundsCopy == vtkm::Vec<vtkm::Range, 3>{ { 0, 1 }, { 2, 4 }, { 8, 16 } });
VTraits::SetComponent(simpleBounds, 0, { 8.0, 16.0 });
VTraits::SetComponent(simpleBounds, 2, { 2.0, 4.0 });
VTraits::SetComponent(simpleBounds, 1, { 0.0, 1.0 });
VTKM_TEST_ASSERT(!simpleBounds.Contains(vtkm::Vec3f_64{ 0.5, 3.0, 12.0 }));
VTKM_TEST_ASSERT(simpleBounds.Contains(vtkm::Vec3f_64{ 12.0, 0.5, 3.0 }));
}
} // anonymous namespace

@ -9,6 +9,7 @@
//============================================================================
#include <vtkm/Range.h>
#include <vtkm/VecTraits.h>
#include <vtkm/testing/Testing.h>
@ -132,6 +133,22 @@ void TestRange()
VTKM_TEST_ASSERT(unionRange.Contains(10), "Contains fail");
VTKM_TEST_ASSERT(unionRange.Contains(17), "Contains fail");
VTKM_TEST_ASSERT(unionRange.Contains(25), "Contains fail");
std::cout << "Try VecTraits." << std::endl;
using VTraits = vtkm::VecTraits<vtkm::Range>;
VTKM_TEST_ASSERT(VTraits::NUM_COMPONENTS == 2);
vtkm::Range simpleRange(2.0, 4.0);
VTKM_TEST_ASSERT(VTraits::GetNumberOfComponents(simpleRange) == 2);
VTKM_TEST_ASSERT(VTraits::GetComponent(simpleRange, 0) == 2.0);
VTKM_TEST_ASSERT(VTraits::GetComponent(simpleRange, 1) == 4.0);
vtkm::Vec2f_64 simpleRangeCopy;
VTraits::CopyInto(simpleRange, simpleRangeCopy);
VTKM_TEST_ASSERT(simpleRangeCopy == vtkm::Vec2f_64{ 2.0, 4.0 });
VTraits::SetComponent(simpleRange, 0, 1.0);
VTraits::SetComponent(simpleRange, 1, 2.0);
VTKM_TEST_ASSERT(!simpleRange.Contains(0.0));
VTKM_TEST_ASSERT(simpleRange.Contains(1.5));
VTKM_TEST_ASSERT(!simpleRange.Contains(3.0));
}
} // anonymous namespace