diff --git a/docs/changelog/vectraits-range.md b/docs/changelog/vectraits-range.md new file mode 100644 index 000000000..28b8367b1 --- /dev/null +++ b/docs/changelog/vectraits-range.md @@ -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`. + diff --git a/vtkm/Bounds.h b/vtkm/Bounds.h index cebb602ae..9ef8de5c4 100644 --- a/vtkm/Bounds.h +++ b/vtkm/Bounds.h @@ -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 +{ + using ComponentType = vtkm::Range; + using BaseComponentType = vtkm::VecTraits::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 + using ReplaceComponentType = vtkm::Vec; + template + using ReplaceBaseComponentType = + vtkm::Vec::NUM_COMPONENTS>; + + template + VTKM_EXEC_CONT static void CopyInto(const vtkm::Bounds& src, + vtkm::Vec& 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 diff --git a/vtkm/Range.h b/vtkm/Range.h index 27f45e9dc..bcf14e478 100644 --- a/vtkm/Range.h +++ b/vtkm/Range.h @@ -14,6 +14,7 @@ #include #include #include +#include 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 +{ + 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 + using ReplaceComponentType = vtkm::Vec; + template + using ReplaceBaseComponentType = vtkm::Vec; + + template + VTKM_EXEC_CONT static void CopyInto(const vtkm::Range& src, + vtkm::Vec& 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 diff --git a/vtkm/testing/UnitTestBounds.cxx b/vtkm/testing/UnitTestBounds.cxx index 6f5b8f0da..a89e5b234 100644 --- a/vtkm/testing/UnitTestBounds.cxx +++ b/vtkm/testing/UnitTestBounds.cxx @@ -9,6 +9,7 @@ //============================================================================ #include +#include #include @@ -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_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 simpleBoundsCopy; + VTraits::CopyInto(simpleBounds, simpleBoundsCopy); + VTKM_TEST_ASSERT(simpleBoundsCopy == vtkm::Vec{ { 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 diff --git a/vtkm/testing/UnitTestRange.cxx b/vtkm/testing/UnitTestRange.cxx index db1868c49..bf822966d 100644 --- a/vtkm/testing/UnitTestRange.cxx +++ b/vtkm/testing/UnitTestRange.cxx @@ -9,6 +9,7 @@ //============================================================================ #include +#include #include @@ -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_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