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`.
This commit is contained in:
Kenneth Moreland 2022-01-25 09:52:43 -07:00
parent ab86763c74
commit f48b4b761e
5 changed files with 189 additions and 1 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

@ -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