From 01bacbcde0303d02d45cb62f5443a70649e07e8b Mon Sep 17 00:00:00 2001 From: Sujin Philip Date: Fri, 2 Jun 2023 08:23:03 -0400 Subject: [PATCH] Advanced Compute Range Add support for masks, vector magnitude range (L2 norm), and finite values only range computations. --- docs/changelog/advanced-compute-range.md | 21 + vtkm/cont/ArrayHandleCartesianProduct.h | 89 ++- vtkm/cont/ArrayHandleConstant.h | 56 +- vtkm/cont/ArrayHandleCounting.h | 57 +- vtkm/cont/ArrayHandleDecorator.h | 2 +- vtkm/cont/ArrayHandleIndex.cxx | 51 ++ vtkm/cont/ArrayHandleIndex.h | 24 +- vtkm/cont/ArrayHandleRecombineVec.h | 107 +++ vtkm/cont/ArrayHandleTransform.h | 2 +- .../ArrayHandleUniformPointCoordinates.cxx | 14 +- .../cont/ArrayHandleUniformPointCoordinates.h | 2 + vtkm/cont/ArrayRangeCompute.cxx | 241 ++++--- vtkm/cont/ArrayRangeCompute.h | 118 +++- vtkm/cont/ArrayRangeComputeTemplate.h | 631 ++++++++++++++---- ...ngeComputeTemplateInstantiationsIncludes.h | 22 + vtkm/cont/CMakeLists.txt | 6 +- vtkm/cont/internal/ArrayRangeComputeUtils.cxx | 52 ++ vtkm/cont/internal/ArrayRangeComputeUtils.h | 33 + vtkm/cont/internal/CMakeLists.txt | 1 + .../testing/UnitTestArrayRangeCompute.cxx | 292 +++++++- .../testing/UnitTestMeshQualityFilter.cxx | 1 - .../meshtypes/ContourTreeMesh.h | 6 +- 22 files changed, 1456 insertions(+), 372 deletions(-) create mode 100644 docs/changelog/advanced-compute-range.md create mode 100644 vtkm/cont/ArrayHandleIndex.cxx create mode 100644 vtkm/cont/ArrayRangeComputeTemplateInstantiationsIncludes.h create mode 100644 vtkm/cont/internal/ArrayRangeComputeUtils.cxx create mode 100644 vtkm/cont/internal/ArrayRangeComputeUtils.h diff --git a/docs/changelog/advanced-compute-range.md b/docs/changelog/advanced-compute-range.md new file mode 100644 index 000000000..ea6f4b518 --- /dev/null +++ b/docs/changelog/advanced-compute-range.md @@ -0,0 +1,21 @@ +# New features for computing array ranges + +ArrayRangeCompute has been update to support more features that are present +in VTK and ParaView. + +New overloads for `ArrayRangeCompute` have been added: +1. Takes a boolean parameter, `computeFiniteRange`, that specifies +whether to compute only the finite range by ignoring any non-finite values (+/-inf) +in the array. + +2. Takes a `maskArray` parameter of type `vtkm::cont::ArrayHandle`. +The mask array must contain the same number of elements as the input array. +A value in the input array is treated as masked off if the +corresponding value in the mask array is non-zero. Masked off values are ignored +in the range computation. + +A new function `ArrayRangeComputeMagnitude` has been added. If the input array +has multiple components, this function computes the range of the magnitude of +the values of the array. Nested Vecs are treated as flat. A single `Range` object +is returned containing the result. `ArrayRangeComputMagnitude` also has similar +overloads as `ArrayRangeCompute`. diff --git a/vtkm/cont/ArrayHandleCartesianProduct.h b/vtkm/cont/ArrayHandleCartesianProduct.h index d9fb12c1c..4bac216cc 100644 --- a/vtkm/cont/ArrayHandleCartesianProduct.h +++ b/vtkm/cont/ArrayHandleCartesianProduct.h @@ -484,6 +484,13 @@ struct ArrayExtractComponentImpl> } }; +template +vtkm::cont::ArrayHandle ArrayRangeComputeGeneric( + const vtkm::cont::ArrayHandle& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device); + template struct ArrayRangeComputeImpl; @@ -494,63 +501,43 @@ struct VTKM_CONT_EXPORT ArrayRangeComputeImpl operator()( const vtkm::cont::ArrayHandle, vtkm::cont::StorageTagCartesianProduct>& input_, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, vtkm::cont::DeviceAdapterId device) const { + if (maskArray.GetNumberOfValues() != 0) + { + return vtkm::cont::internal::ArrayRangeComputeGeneric( + input_, maskArray, computeFiniteRange, device); + } + + const auto& input = + static_cast, + vtkm::cont::ArrayHandle, + vtkm::cont::ArrayHandle>&>( + input_); + + vtkm::cont::ArrayHandle ranges[3]; + ranges[0] = vtkm::cont::internal::ArrayRangeComputeImpl{}( + input.GetFirstArray(), maskArray, computeFiniteRange, device); + ranges[1] = vtkm::cont::internal::ArrayRangeComputeImpl{}( + input.GetSecondArray(), maskArray, computeFiniteRange, device); + ranges[2] = vtkm::cont::internal::ArrayRangeComputeImpl{}( + input.GetThirdArray(), maskArray, computeFiniteRange, device); + + auto numComponents = + ranges[0].GetNumberOfValues() + ranges[1].GetNumberOfValues() + ranges[2].GetNumberOfValues(); vtkm::cont::ArrayHandle result; - result.Allocate(3); + result.Allocate(numComponents); auto resultPortal = result.WritePortal(); - - const vtkm::cont::ArrayHandleCartesianProduct, - vtkm::cont::ArrayHandle, - vtkm::cont::ArrayHandle>& input = input_; - vtkm::cont::ArrayHandle componentRangeArray; - - vtkm::IdComponent index = 0; - vtkm::cont::ArrayHandle firstArray = input.GetFirstArray(); - componentRangeArray = vtkm::cont::internal::ArrayRangeComputeImpl{}(firstArray, device); - vtkm::Id numSubComponents = componentRangeArray.GetNumberOfValues(); - if (numSubComponents > 1) + for (vtkm::Id i = 0, index = 0; i < 3; ++i) { - result.Allocate(result.GetNumberOfValues() + numSubComponents - 1, vtkm::CopyFlag::On); - resultPortal = result.WritePortal(); + auto rangePortal = ranges[i].ReadPortal(); + for (vtkm::Id j = 0; j < rangePortal.GetNumberOfValues(); ++j, ++index) + { + resultPortal.Set(index, rangePortal.Get(j)); + } } - auto componentRangePortal = componentRangeArray.ReadPortal(); - for (vtkm::IdComponent subComponent = 0; subComponent < numSubComponents; ++subComponent) - { - resultPortal.Set(index, componentRangePortal.Get(subComponent)); - ++index; - } - - vtkm::cont::ArrayHandle secondArray = input.GetSecondArray(); - componentRangeArray = vtkm::cont::internal::ArrayRangeComputeImpl{}(secondArray, device); - numSubComponents = componentRangeArray.GetNumberOfValues(); - if (numSubComponents > 1) - { - result.Allocate(result.GetNumberOfValues() + numSubComponents - 1, vtkm::CopyFlag::On); - resultPortal = result.WritePortal(); - } - componentRangePortal = componentRangeArray.ReadPortal(); - for (vtkm::IdComponent subComponent = 0; subComponent < numSubComponents; ++subComponent) - { - resultPortal.Set(index, componentRangePortal.Get(subComponent)); - ++index; - } - - vtkm::cont::ArrayHandle thirdArray = input.GetThirdArray(); - componentRangeArray = vtkm::cont::internal::ArrayRangeComputeImpl{}(thirdArray, device); - numSubComponents = componentRangeArray.GetNumberOfValues(); - if (numSubComponents > 1) - { - result.Allocate(result.GetNumberOfValues() + numSubComponents - 1, vtkm::CopyFlag::On); - resultPortal = result.WritePortal(); - } - componentRangePortal = componentRangeArray.ReadPortal(); - for (vtkm::IdComponent subComponent = 0; subComponent < numSubComponents; ++subComponent) - { - resultPortal.Set(index, componentRangePortal.Get(subComponent)); - ++index; - } - return result; } }; diff --git a/vtkm/cont/ArrayHandleConstant.h b/vtkm/cont/ArrayHandleConstant.h index 45d67e198..ed59e1318 100644 --- a/vtkm/cont/ArrayHandleConstant.h +++ b/vtkm/cont/ArrayHandleConstant.h @@ -12,8 +12,11 @@ #include +#include + #include #include +#include namespace vtkm { @@ -106,8 +109,18 @@ struct VTKM_CONT_EXPORT ArrayRangeComputeImpl template VTKM_CONT vtkm::cont::ArrayHandle operator()( const vtkm::cont::ArrayHandle& input, - vtkm::cont::DeviceAdapterId) const + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId devId) const { + bool allMasked = false; + if (maskArray.GetNumberOfValues() != 0) + { + // Find if there is atleast one value that is not masked + auto ids = GetFirstAndLastUnmaskedIndices(maskArray, devId); + allMasked = (ids[1] < ids[0]); + } + auto value = vtkm::make_VecFlat(input.ReadPortal().Get(0)); vtkm::cont::ArrayHandle result; @@ -115,12 +128,51 @@ struct VTKM_CONT_EXPORT ArrayRangeComputeImpl auto resultPortal = result.WritePortal(); for (vtkm::IdComponent index = 0; index < value.GetNumberOfComponents(); ++index) { - resultPortal.Set(index, vtkm::Range{ value[index], value[index] }); + auto comp = static_cast(value[index]); + if (allMasked || (computeFiniteRange && !vtkm::IsFinite(comp))) + { + resultPortal.Set(index, vtkm::Range{}); + } + else + { + resultPortal.Set(index, vtkm::Range{ comp, comp }); + } } return result; } }; +template +struct ArrayRangeComputeMagnitudeImpl; + +template <> +struct VTKM_CONT_EXPORT ArrayRangeComputeMagnitudeImpl +{ + template + VTKM_CONT vtkm::Range operator()( + const vtkm::cont::ArrayHandle& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId devId) const + { + if (maskArray.GetNumberOfValues() != 0) + { + // Find if there is atleast one value that is not masked + auto ids = GetFirstAndLastUnmaskedIndices(maskArray, devId); + if (ids[1] < ids[0]) + { + return vtkm::Range{}; + } + } + + auto value = input.ReadPortal().Get(0); + vtkm::Float64 rangeValue = vtkm::Magnitude(vtkm::make_VecFlat(value)); + return (computeFiniteRange && !vtkm::IsFinite(rangeValue)) + ? vtkm::Range{} + : vtkm::Range{ rangeValue, rangeValue }; + } +}; + } // namespace internal } diff --git a/vtkm/cont/ArrayHandleCounting.h b/vtkm/cont/ArrayHandleCounting.h index 7f2eae8c1..b0ef36dd7 100644 --- a/vtkm/cont/ArrayHandleCounting.h +++ b/vtkm/cont/ArrayHandleCounting.h @@ -12,8 +12,11 @@ #include +#include + #include #include +#include #include namespace vtkm @@ -156,33 +159,45 @@ struct VTKM_CONT_EXPORT ArrayRangeComputeImpl template VTKM_CONT vtkm::cont::ArrayHandle operator()( const vtkm::cont::ArrayHandle& input, - vtkm::cont::DeviceAdapterId) const + const vtkm::cont::ArrayHandle& maskArray, + bool vtkmNotUsed(computeFiniteRange), // assume array produces only finite values + vtkm::cont::DeviceAdapterId device) const { - using Traits = vtkm::VecTraits; + using Traits = vtkm::VecTraits>; vtkm::cont::ArrayHandle result; result.Allocate(Traits::NUM_COMPONENTS); + + if (input.GetNumberOfValues() <= 0) + { + result.Fill(vtkm::Range{}); + return result; + } + + vtkm::Id2 firstAndLast{ 0, input.GetNumberOfValues() - 1 }; + if (maskArray.GetNumberOfValues() > 0) + { + firstAndLast = GetFirstAndLastUnmaskedIndices(maskArray, device); + } + + if (firstAndLast[1] < firstAndLast[0]) + { + result.Fill(vtkm::Range{}); + return result; + } + auto portal = result.WritePortal(); - if (portal.GetNumberOfValues() > 0) + // assume the values to be finite + auto first = make_VecFlat(input.ReadPortal().Get(firstAndLast[0])); + auto last = make_VecFlat(input.ReadPortal().Get(firstAndLast[1])); + for (vtkm::IdComponent cIndex = 0; cIndex < Traits::NUM_COMPONENTS; ++cIndex) { - T first = input.ReadPortal().Get(0); - T last = input.ReadPortal().Get(input.GetNumberOfValues() - 1); - for (vtkm::IdComponent cIndex = 0; cIndex < Traits::NUM_COMPONENTS; ++cIndex) - { - auto firstComponent = Traits::GetComponent(first, cIndex); - auto lastComponent = Traits::GetComponent(last, cIndex); - portal.Set(cIndex, - vtkm::Range(vtkm::Min(firstComponent, lastComponent), - vtkm::Max(firstComponent, lastComponent))); - } - } - else - { - // Array is empty - for (vtkm::IdComponent cIndex = 0; cIndex < Traits::NUM_COMPONENTS; ++cIndex) - { - portal.Set(cIndex, vtkm::Range{}); - } + auto firstComponent = Traits::GetComponent(first, cIndex); + auto lastComponent = Traits::GetComponent(last, cIndex); + portal.Set(cIndex, + vtkm::Range(vtkm::Min(firstComponent, lastComponent), + vtkm::Max(firstComponent, lastComponent))); } + return result; } }; diff --git a/vtkm/cont/ArrayHandleDecorator.h b/vtkm/cont/ArrayHandleDecorator.h index ffd85d0de..b934fa415 100644 --- a/vtkm/cont/ArrayHandleDecorator.h +++ b/vtkm/cont/ArrayHandleDecorator.h @@ -23,7 +23,7 @@ #include - +#include #include #include #include diff --git a/vtkm/cont/ArrayHandleIndex.cxx b/vtkm/cont/ArrayHandleIndex.cxx new file mode 100644 index 000000000..05c6731a2 --- /dev/null +++ b/vtkm/cont/ArrayHandleIndex.cxx @@ -0,0 +1,51 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#include +#include + +namespace vtkm +{ +namespace cont +{ +namespace internal +{ + +VTKM_CONT vtkm::cont::ArrayHandle +ArrayRangeComputeImpl::operator()( + const vtkm::cont::ArrayHandle& input, + const vtkm::cont::ArrayHandle& maskArray, + bool vtkmNotUsed(computeFiniteRange), // assume array produces only finite values + vtkm::cont::DeviceAdapterId device) const +{ + vtkm::Range range{}; + + if (input.GetNumberOfValues() > 0) + { + vtkm::Id2 firstAndLast{ 0, input.GetNumberOfValues() - 1 }; + if (maskArray.GetNumberOfValues() > 0) + { + firstAndLast = vtkm::cont::internal::GetFirstAndLastUnmaskedIndices(maskArray, device); + } + if (firstAndLast[0] < firstAndLast[1]) + { + range = vtkm::Range(firstAndLast[0], firstAndLast[1]); + } + } + + vtkm::cont::ArrayHandle result; + result.Allocate(1); + result.WritePortal().Set(0, range); + return result; +} + +} +} +} // vtkm::cont::internal diff --git a/vtkm/cont/ArrayHandleIndex.h b/vtkm/cont/ArrayHandleIndex.h index 7bccba25b..f522de29b 100644 --- a/vtkm/cont/ArrayHandleIndex.h +++ b/vtkm/cont/ArrayHandleIndex.h @@ -84,12 +84,26 @@ struct VTKM_CONT_EXPORT ArrayRangeComputeImpl { VTKM_CONT vtkm::cont::ArrayHandle operator()( const vtkm::cont::ArrayHandle& input, - vtkm::cont::DeviceAdapterId) const + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) const; +}; + +template +struct ArrayRangeComputeMagnitudeImpl; + +template <> +struct VTKM_CONT_EXPORT ArrayRangeComputeMagnitudeImpl +{ + VTKM_CONT vtkm::Range operator()( + const vtkm::cont::ArrayHandle& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) const { - vtkm::cont::ArrayHandle result; - result.Allocate(1); - result.WritePortal().Set(0, vtkm::Range(0, input.GetNumberOfValues() - 1)); - return result; + auto rangeAH = ArrayRangeComputeImpl{}( + input, maskArray, computeFiniteRange, device); + return rangeAH.ReadPortal().Get(0); } }; diff --git a/vtkm/cont/ArrayHandleRecombineVec.h b/vtkm/cont/ArrayHandleRecombineVec.h index 121d3fa4a..d02ddd883 100644 --- a/vtkm/cont/ArrayHandleRecombineVec.h +++ b/vtkm/cont/ArrayHandleRecombineVec.h @@ -13,8 +13,11 @@ #include #include #include +#include #include +#include + #include namespace vtkm @@ -648,6 +651,110 @@ struct ArrayExtractComponentImpl } }; +//------------------------------------------------------------------------------------------------- +template +struct ArrayRangeComputeImpl; + +template +struct ArrayRangeComputeMagnitudeImpl; + +template +inline vtkm::cont::ArrayHandle ArrayRangeComputeImplCaller( + const vtkm::cont::ArrayHandle& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) +{ + return vtkm::cont::internal::ArrayRangeComputeImpl{}( + input, maskArray, computeFiniteRange, device); +} + +template +inline vtkm::Range ArrayRangeComputeMagnitudeImplCaller( + const vtkm::cont::ArrayHandle& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) +{ + return vtkm::cont::internal::ArrayRangeComputeMagnitudeImpl{}( + input, maskArray, computeFiniteRange, device); +} + +template <> +struct VTKM_CONT_EXPORT ArrayRangeComputeImpl +{ + template + VTKM_CONT vtkm::cont::ArrayHandle operator()( + const vtkm::cont::ArrayHandle& + input_, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) const + { + auto input = + static_cast>( + input_); + + vtkm::cont::ArrayHandle result; + result.Allocate(input.GetNumberOfComponents()); + + if (input.GetNumberOfValues() < 1) + { + result.Fill(vtkm::Range{}); + return result; + } + + auto resultPortal = result.WritePortal(); + for (vtkm::IdComponent i = 0; i < input.GetNumberOfComponents(); ++i) + { + auto rangeAH = ArrayRangeComputeImplCaller( + input.GetComponentArray(i), maskArray, computeFiniteRange, device); + resultPortal.Set(i, rangeAH.ReadPortal().Get(0)); + } + + return result; + } +}; + +template +struct ArrayValueIsNested; + +template +struct ArrayValueIsNested< + vtkm::cont::ArrayHandle> +{ + static constexpr bool Value = false; +}; + +template <> +struct VTKM_CONT_EXPORT ArrayRangeComputeMagnitudeImpl +{ + template + VTKM_CONT vtkm::Range operator()( + const vtkm::cont::ArrayHandle& + input_, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) const + { + auto input = + static_cast>( + input_); + + if (input.GetNumberOfValues() < 1) + { + return vtkm::Range{}; + } + if (input.GetNumberOfComponents() == 1) + { + return ArrayRangeComputeMagnitudeImplCaller( + input.GetComponentArray(0), maskArray, computeFiniteRange, device); + } + + return ArrayRangeComputeMagnitudeGeneric(input_, maskArray, computeFiniteRange, device); + } +}; + } // namespace internal } diff --git a/vtkm/cont/ArrayHandleTransform.h b/vtkm/cont/ArrayHandleTransform.h index 12994ea14..f391ec654 100644 --- a/vtkm/cont/ArrayHandleTransform.h +++ b/vtkm/cont/ArrayHandleTransform.h @@ -226,7 +226,7 @@ struct TransformFunctorManager } template - using TransformedValueType = decltype(std::declval()(ValueType{})); + using TransformedValueType = decltype(std::declval()(std::declval())); }; template +#include + +#include + namespace vtkm { namespace cont @@ -89,8 +93,16 @@ ArrayExtractComponentImpl::operator()( VTKM_CONT vtkm::cont::ArrayHandle ArrayRangeComputeImpl::operator()( const vtkm::cont::ArrayHandleUniformPointCoordinates& input, - vtkm::cont::DeviceAdapterId vtkmNotUsed(device)) const + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) const { + if (maskArray.GetNumberOfValues() != 0) + { + return vtkm::cont::internal::ArrayRangeComputeGeneric( + input, maskArray, computeFiniteRange, device); + } + vtkm::internal::ArrayPortalUniformPointCoordinates portal = input.ReadPortal(); // In this portal we know that the min value is the first entry and the diff --git a/vtkm/cont/ArrayHandleUniformPointCoordinates.h b/vtkm/cont/ArrayHandleUniformPointCoordinates.h index 72a33725f..abf5e00d8 100644 --- a/vtkm/cont/ArrayHandleUniformPointCoordinates.h +++ b/vtkm/cont/ArrayHandleUniformPointCoordinates.h @@ -88,6 +88,8 @@ struct VTKM_CONT_EXPORT ArrayRangeComputeImpl operator()( const vtkm::cont::ArrayHandleUniformPointCoordinates& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, vtkm::cont::DeviceAdapterId device) const; }; diff --git a/vtkm/cont/ArrayRangeCompute.cxx b/vtkm/cont/ArrayRangeCompute.cxx index f2e1a0f31..68095ee84 100644 --- a/vtkm/cont/ArrayRangeCompute.cxx +++ b/vtkm/cont/ArrayRangeCompute.cxx @@ -8,13 +8,13 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ +#include #include #include #include #include -#include #include #include #include @@ -42,50 +42,39 @@ using AllVec = vtkm::ListAppend, AllVecOfSize<3>, AllVecOfSize<4 using AllTypes = vtkm::ListAppend; -struct ComputeRangeFunctor -{ - // Used with UnknownArrayHandle::CastAndCallForTypes - template - void operator()(const vtkm::cont::ArrayHandle& array, - vtkm::cont::DeviceAdapterId device, - vtkm::cont::ArrayHandle& ranges) const - { - ranges = vtkm::cont::ArrayRangeComputeTemplate(array, device); +using CartesianProductStorage = vtkm::cont::StorageTagCartesianProduct; + +using StorageTagsList = vtkm::List; + +template +struct StorageTagToValueTypesMap; + +#define MAP_STORAGE_TAG_VALUE_TYPES(StorageTag, ValueTypesList) \ + template <> \ + struct StorageTagToValueTypesMap \ + { \ + using TypeList = ValueTypesList; \ } - // Used with vtkm::ListForEach to get components - template - void operator()(T, - const vtkm::cont::UnknownArrayHandle& array, - vtkm::cont::DeviceAdapterId device, - vtkm::cont::ArrayHandle& ranges, - bool& success) const - { - if (!success && array.IsBaseComponentType()) - { - vtkm::IdComponent numComponents = array.GetNumberOfComponentsFlat(); - ranges.Allocate(numComponents); - auto rangePortal = ranges.WritePortal(); - for (vtkm::IdComponent componentI = 0; componentI < numComponents; ++componentI) - { - vtkm::cont::ArrayHandleStride componentArray = array.ExtractComponent(componentI); - vtkm::cont::ArrayHandle componentRange = - vtkm::cont::ArrayRangeComputeTemplate(componentArray, device); - rangePortal.Set(componentI, componentRange.ReadPortal().Get(0)); - } - success = true; - } - } -}; +MAP_STORAGE_TAG_VALUE_TYPES(vtkm::cont::StorageTagBasic, AllTypes); +MAP_STORAGE_TAG_VALUE_TYPES(vtkm::cont::StorageTagSOA, AllVec); +MAP_STORAGE_TAG_VALUE_TYPES(vtkm::cont::StorageTagXGCCoordinates, vtkm::TypeListFieldVec3); +MAP_STORAGE_TAG_VALUE_TYPES(vtkm::cont::StorageTagUniformPoints, vtkm::List); +MAP_STORAGE_TAG_VALUE_TYPES(CartesianProductStorage, vtkm::TypeListFieldVec3); +MAP_STORAGE_TAG_VALUE_TYPES(vtkm::cont::StorageTagConstant, AllTypes); +MAP_STORAGE_TAG_VALUE_TYPES(vtkm::cont::StorageTagCounting, AllTypes); +MAP_STORAGE_TAG_VALUE_TYPES(vtkm::cont::StorageTagIndex, vtkm::List); -template -vtkm::cont::ArrayHandle ComputeForStorage(const vtkm::cont::UnknownArrayHandle& array, - vtkm::cont::DeviceAdapterId device) -{ - vtkm::cont::ArrayHandle ranges; - array.CastAndCallForTypes>(ComputeRangeFunctor{}, device, ranges); - return ranges; -} +#undef MAP_STORAGE_TAG_VALUE_TYPES } // anonymous namespace @@ -105,49 +94,44 @@ void ThrowArrayRangeComputeFailed() } // namespace internal vtkm::cont::ArrayHandle ArrayRangeCompute(const vtkm::cont::UnknownArrayHandle& array, + bool computeFiniteRange, vtkm::cont::DeviceAdapterId device) { - // First, try fast-paths of precompiled array types common(ish) in fields. + return ArrayRangeCompute( + array, vtkm::cont::ArrayHandle{}, computeFiniteRange, device); +} + +vtkm::cont::ArrayHandle ArrayRangeCompute( + const vtkm::cont::UnknownArrayHandle& array, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) +{ + // First, try (potentially fast-paths) for common(ish) array types. try { - if (array.IsStorageType()) + vtkm::cont::ArrayHandle ranges; + + auto computeForArrayHandle = [&](const auto& input) { + ranges = vtkm::cont::ArrayRangeComputeTemplate(input, maskArray, computeFiniteRange, device); + }; + + bool success = false; + auto computeForStorage = [&](auto storageTag) { + using STag = decltype(storageTag); + using VTypes = typename StorageTagToValueTypesMap::TypeList; + if (array.IsStorageType()) + { + array.CastAndCallForTypes>(computeForArrayHandle); + success = true; + } + }; + + vtkm::ListForEach(computeForStorage, StorageTagsList{}); + + if (success) { - return ComputeForStorage(array, device); - } - if (array.IsStorageType()) - { - return ComputeForStorage(array, device); - } - if (array.IsStorageType()) - { - return ComputeForStorage( - array, device); - } - if (array.IsStorageType()) - { - vtkm::cont::ArrayHandleUniformPointCoordinates uniformPoints; - array.AsArrayHandle(uniformPoints); - return vtkm::cont::ArrayRangeComputeTemplate(uniformPoints, device); - } - using CartesianProductStorage = - vtkm::cont::StorageTagCartesianProduct; - if (array.IsStorageType()) - { - return ComputeForStorage(array, device); - } - if (array.IsStorageType()) - { - return ComputeForStorage(array, device); - } - if (array.IsStorageType()) - { - return ComputeForStorage(array, device); - } - if (array.IsStorageType()) - { - return ArrayRangeComputeTemplate(array.AsArrayHandle(), device); + return ranges; } } catch (vtkm::cont::ErrorBadType&) @@ -155,11 +139,104 @@ vtkm::cont::ArrayHandle ArrayRangeCompute(const vtkm::cont::Unknown // If a cast/call failed, try falling back to a more general implementation. } - vtkm::cont::ArrayHandle ranges; + // fallback bool success = false; - vtkm::ListForEach(ComputeRangeFunctor{}, AllScalars{}, array, device, ranges, success); + vtkm::cont::ArrayHandle ranges; + auto computeForExtractComponent = [&](auto valueTypeObj) { + using VT = decltype(valueTypeObj); + if (!success && array.IsBaseComponentType()) + { + vtkm::IdComponent numComponents = array.GetNumberOfComponentsFlat(); + ranges.Allocate(numComponents); + auto rangePortal = ranges.WritePortal(); + for (vtkm::IdComponent i = 0; i < numComponents; ++i) + { + auto componentArray = array.ExtractComponent(i); + auto componentRange = vtkm::cont::ArrayRangeComputeTemplate( + componentArray, maskArray, computeFiniteRange, device); + rangePortal.Set(i, componentRange.ReadPortal().Get(0)); + } + success = true; + } + }; + + vtkm::ListForEach(computeForExtractComponent, AllScalars{}); + if (!success) + { + internal::ThrowArrayRangeComputeFailed(); + } + return ranges; } +vtkm::Range ArrayRangeComputeMagnitude(const vtkm::cont::UnknownArrayHandle& array, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) +{ + return ArrayRangeComputeMagnitude( + array, vtkm::cont::ArrayHandle{}, computeFiniteRange, device); +} + +vtkm::Range ArrayRangeComputeMagnitude(const vtkm::cont::UnknownArrayHandle& array, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) +{ + // First, try (potentially fast-paths) for common(ish) array types. + try + { + vtkm::Range range; + + auto computeForArrayHandle = [&](const auto& input) { + range = vtkm::cont::ArrayRangeComputeMagnitudeTemplate( + input, maskArray, computeFiniteRange, device); + }; + + bool success = false; + auto computeForStorage = [&](auto storageTag) { + using STag = decltype(storageTag); + using VTypes = typename StorageTagToValueTypesMap::TypeList; + if (array.IsStorageType()) + { + array.CastAndCallForTypes>(computeForArrayHandle); + success = true; + } + }; + + vtkm::ListForEach(computeForStorage, StorageTagsList{}); + + if (success) + { + return range; + } + } + catch (vtkm::cont::ErrorBadType&) + { + // If a cast/call failed, try falling back to a more general implementation. + } + + // fallback + bool success = false; + vtkm::Range range; + auto computeForExtractArrayFromComponents = [&](auto valueTypeObj) { + using VT = decltype(valueTypeObj); + if (!success && array.IsBaseComponentType()) + { + auto extractedArray = array.ExtractArrayFromComponents(); + range = vtkm::cont::ArrayRangeComputeMagnitudeTemplate( + extractedArray, maskArray, computeFiniteRange, device); + success = true; + } + }; + + vtkm::ListForEach(computeForExtractArrayFromComponents, AllScalars{}); + if (!success) + { + internal::ThrowArrayRangeComputeFailed(); + } + + return range; +} + } } // namespace vtkm::cont diff --git a/vtkm/cont/ArrayRangeCompute.h b/vtkm/cont/ArrayRangeCompute.h index e87b612ea..4a5d8e96b 100644 --- a/vtkm/cont/ArrayRangeCompute.h +++ b/vtkm/cont/ArrayRangeCompute.h @@ -11,18 +11,8 @@ #define vtk_m_cont_ArrayRangeCompute_h #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include @@ -31,30 +21,116 @@ namespace vtkm namespace cont { +/// @{ /// \brief Compute the range of the data in an array handle. /// /// Given an `ArrayHandle`, this function computes the range (min and max) of /// the values in the array. For arrays containing Vec values, the range is -/// computed for each component. +/// computed for each component, and in the case of nested Vecs, ranges are computed +/// for each of the leaf components. /// -/// This method optionally takes a `vtkm::cont::DeviceAdapterId` to control which -/// devices to try. +/// \param array The input array as a `vtkm::cont::UnknownArrayHandle`. +/// \param maskArray An array handle of type `vtkm::cont::ArrayHandle`. +/// This array should have the same number of elements as the input array +/// with each value representing the masking status of the corresponding +/// value in the input array (masked if 0 else unmasked). Ignored if empty. +/// \param computeFiniteRange Optional boolean parameter to specify if non-finite values in the +/// array should be ignored to compute the finite range of +/// the array. For Vec types, individual component values +/// are considered independantly. +/// \param device This optional parameter can be used to specify a device to run the +/// range computation on. The default value is `vtkm::cont::DeviceAdapterTagAny{}`. /// -/// The result is returned in an `ArrayHandle` of `Range` objects. There is +/// \return The result is returned in an `ArrayHandle` of `Range` objects. There is /// one value in the returned array for every component of the input's value -/// type. +/// type. For nested Vecs the results are stored in depth-first order. /// -/// Note that the ArrayRangeCompute.h header file contains only precompiled overloads -/// of ArrayRangeCompute. This is so that ArrayRangeCompute.h can be included in -/// code that does not use a device compiler. If you need to compute array ranges -/// for arbitrary `ArrayHandle`s not in this precompiled list, you need to use -/// `ArrayRangeComputeTemplate` (declared in `ArrayRangeComputeTemplate`), which -/// will compile for any `ArrayHandle` type not already handled. +/// \note `ArrayRangeCompute` takes an UnknownArrayHandle as the input. +/// The implementation uses precompiled and specicialized code for several of the +/// most commonly used value and storage types, with a fallback for other cases. +/// This is so that ArrayRangeCompute.h can be included in code that does not use a +/// device compiler. This should be sufficient for most cases, but if you need to +/// compute the range for an array type that is not explicitly handled by +/// `ArrayRangeCompute` and the fallback code is not performant, use the +/// templated version `ArrayRangeComputeTemplate`. Specializations can be +/// implemented by specializing the template class `ArrayRangeComputeImpl`. +/// Please refer to ArrayRangeComputeTemplate.h for details /// +/// \sa ArrayRangeComputeTemplate +/// + VTKM_CONT_EXPORT vtkm::cont::ArrayHandle ArrayRangeCompute( const vtkm::cont::UnknownArrayHandle& array, + bool computeFiniteRange = false, vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}); +VTKM_CONT_EXPORT vtkm::cont::ArrayHandle ArrayRangeCompute( + const vtkm::cont::UnknownArrayHandle& array, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange = false, + vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}); + +inline vtkm::cont::ArrayHandle ArrayRangeCompute( + const vtkm::cont::UnknownArrayHandle& array, + vtkm::cont::DeviceAdapterId device) +{ + return ArrayRangeCompute(array, false, device); +} + +/// @} + +/// @{ +/// \brief Compute the range of the magnitude of the Vec data in an array handle. +/// +/// Given an `ArrayHandle`, this function computes the range (min and max) of +/// the magnitude of the values in the array. +/// +/// \param array The input array as a `vtkm::cont::UnknownArrayHandle`. +/// \param maskArray An array handle of type `vtkm::cont::ArrayHandle`. +/// This array should have the same number of elements as the input array +/// with each value representing the masking status of the corresponding +/// value in the input array (masked if 0 else unmasked). Ignored if empty. +/// \param computeFiniteRange Optional boolean value to specify if non-finite values in the +/// array should be ignored to compute the finite range of +/// the array. A Vec with any non-finite component will be +/// ignored. +/// \param device This optional parameter can be used to specify a device to run the +/// range computation on. The default value is `vtkm::cont::DeviceAdapterTagAny{}`. +/// +/// \return The result is returned in a single `Range` objects. +/// +/// \note `ArrayRangeComputeMagnitude` takes an UnknownArrayHandle as the input. +/// The implementation uses precompiled and specicialized code for several of the +/// most commonly used value and storage types, with a fallback for other cases. +/// This is so that ArrayRangeCompute.h can be included in code that does not use a +/// device compiler. This should be sufficient for most cases, but if you need to +/// compute the range for an array type that is not explicitly handled by +/// `ArrayRangeComputeMagnitude` and the fallback code is not performant, use the +/// templated version `ArrayRangeComputeMagnitudeTemplate`. Specializations can be +/// implemented by specializing the template class `ArrayRangeComputeMagnitudeImpl`. +/// Please refer to ArrayRangeComputeTemplate.h for details +/// +/// \sa ArrayRangeComputeMagnitudeTemplate +/// +VTKM_CONT_EXPORT vtkm::Range ArrayRangeComputeMagnitude( + const vtkm::cont::UnknownArrayHandle& array, + bool computeFiniteRange = false, + vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}); + +VTKM_CONT_EXPORT vtkm::Range ArrayRangeComputeMagnitude( + const vtkm::cont::UnknownArrayHandle& array, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange = false, + vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}); + +inline vtkm::Range ArrayRangeComputeMagnitude(const vtkm::cont::UnknownArrayHandle& array, + vtkm::cont::DeviceAdapterId device) +{ + return ArrayRangeComputeMagnitude(array, false, device); +} + +/// @} + namespace internal { diff --git a/vtkm/cont/ArrayRangeComputeTemplate.h b/vtkm/cont/ArrayRangeComputeTemplate.h index 8e29f1166..93e3fa287 100644 --- a/vtkm/cont/ArrayRangeComputeTemplate.h +++ b/vtkm/cont/ArrayRangeComputeTemplate.h @@ -10,257 +10,531 @@ #ifndef vtk_m_cont_ArrayRangeComputeTemplate_h #define vtk_m_cont_ArrayRangeComputeTemplate_h -#include +#include +#include +#include +#include +#include #include #include +#include #include +#include #include -#include - -#include - namespace vtkm { namespace cont { -namespace detail -{ - -struct ArrayRangeComputeFunctor -{ - template - VTKM_CONT bool operator()(Device, - const vtkm::cont::ArrayHandle& handle, - const vtkm::Vec& initialValue, - vtkm::Vec& result) const - { - VTKM_IS_DEVICE_ADAPTER_TAG(Device); - using Algorithm = vtkm::cont::DeviceAdapterAlgorithm; - result = Algorithm::Reduce(handle, initialValue, vtkm::MinAndMax()); - return true; - } -}; - -} // namespace detail - namespace internal { +//------------------------------------------------------------------------------------------------- +struct ComputeRangeOptionsDecorator +{ + bool IgnoreInf = false; + + template + struct Functor + { + SrcPortal Src; + MaskPortal Mask; + bool IgnoreInf; + + using InValueType = typename SrcPortal::ValueType; + using InVecTraits = vtkm::VecTraits; + using ResultType = vtkm::Vec, 2>; + + VTKM_EXEC_CONT + ResultType operator()(vtkm::Id idx) const + { + if ((this->Mask.GetNumberOfValues() != 0) && (this->Mask.Get(idx) == 0)) + { + return { { vtkm::Range{}.Min }, { vtkm::Range{}.Max } }; + } + + const auto& inVal = this->Src.Get(idx); + ResultType outVal; + for (vtkm::IdComponent i = 0; i < InVecTraits::NUM_COMPONENTS; ++i) + { + auto val = static_cast(InVecTraits::GetComponent(inVal, i)); + if (vtkm::IsNan(val) || (this->IgnoreInf && !vtkm::IsFinite(val))) + { + outVal[0][i] = vtkm::Range{}.Min; + outVal[1][i] = vtkm::Range{}.Max; + } + else + { + outVal[0][i] = outVal[1][i] = val; + } + } + + return outVal; + } + }; + + template + Functor CreateFunctor(const SrcPortal& sp, const GhostPortal& gp) const + { + return { sp, gp, this->IgnoreInf }; + } +}; + +template +struct ArrayValueIsNested +{ + static constexpr bool Value = + !vtkm::internal::IsFlatVec::value; +}; + +template ::Value> +struct NestedToFlat; + +template +struct NestedToFlat +{ + static auto Transform(const ArrayHandleType& in) + { + return vtkm::cont::ArrayHandleCast, + ArrayHandleType>(in); + } +}; + +template +struct NestedToFlat +{ + static auto Transform(const ArrayHandleType& in) { return in; } +}; + +template +inline auto NestedToFlatTransform(const ArrayHandleType& input) +{ + return NestedToFlat::Transform(input); +} + +//------------------------------------------------------------------------------------------------- +/// \brief A generic implementation of `ArrayRangeCompute`. This is the implementation used +/// when `ArrayRangeComputeImpl` is not specialized. +/// template inline vtkm::cont::ArrayHandle ArrayRangeComputeGeneric( const vtkm::cont::ArrayHandle& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, vtkm::cont::DeviceAdapterId device) { VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "ArrayRangeCompute"); using VecTraits = vtkm::VecTraits; - using CT = typename VecTraits::ComponentType; - //We want to minimize the amount of code that we do in try execute as - //it is repeated for each + vtkm::cont::ArrayHandle range; range.Allocate(VecTraits::NUM_COMPONENTS); + //We want to minimize the amount of code that we do in try execute as + //it is repeated for each if (input.GetNumberOfValues() < 1) { - auto portal = range.WritePortal(); - for (vtkm::IdComponent i = 0; i < VecTraits::NUM_COMPONENTS; ++i) - { - portal.Set(i, vtkm::Range()); - } + range.Fill(vtkm::Range{}); } else { - //We used the limits, so that we don't need to sync the array handle - // - vtkm::Vec result; - vtkm::Vec initial; - initial[0] = T(std::numeric_limits::max()); - initial[1] = T(std::numeric_limits::lowest()); + // if input is an array of nested vectors, transform them to `VecFlat` using ArrayHandleCast + auto flattened = NestedToFlatTransform(input); + ComputeRangeOptionsDecorator decorator{ computeFiniteRange }; + auto decorated = + make_ArrayHandleDecorator(flattened.GetNumberOfValues(), decorator, flattened, maskArray); - const bool rangeComputed = vtkm::cont::TryExecuteOnDevice( - device, vtkm::cont::detail::ArrayRangeComputeFunctor{}, input, initial, result); - if (!rangeComputed) + using ResultType = vtkm::Vec, 2>; + using MinAndMaxFunctor = vtkm::MinAndMax; + ResultType identity{ { vtkm::Range{}.Min }, { vtkm::Range{}.Max } }; + + auto result = vtkm::cont::Algorithm::Reduce(device, decorated, identity, MinAndMaxFunctor{}); + + auto portal = range.WritePortal(); + for (vtkm::IdComponent i = 0; i < VecTraits::NUM_COMPONENTS; ++i) { - ThrowArrayRangeComputeFailed(); + portal.Set(i, vtkm::Range(result[0][i], result[1][i])); } - else + } + + return range; +} + +//------------------------------------------------------------------------------------------------- +struct ScalarMagnitudeFunctor +{ + template + VTKM_EXEC_CONT vtkm::Float64 operator()(const T& val) const + { + // spcilization of `vtkm::Magnitude` for scalars should avoid `sqrt` computation by using `abs` + // instead + return static_cast(vtkm::Magnitude(val)); + } +}; + +struct MagnitudeSquareFunctor +{ + template + VTKM_EXEC_CONT vtkm::Float64 operator()(const T& val) const + { + using VecTraits = vtkm::VecTraits; + vtkm::Float64 result = 0; + for (vtkm::IdComponent i = 0; i < VecTraits::GetNumberOfComponents(val); ++i) { - auto portal = range.WritePortal(); - for (vtkm::IdComponent i = 0; i < VecTraits::NUM_COMPONENTS; ++i) - { - portal.Set(i, - vtkm::Range(VecTraits::GetComponent(result[0], i), - VecTraits::GetComponent(result[1], i))); - } + auto comp = static_cast(VecTraits::GetComponent(val, i)); + result += comp * comp; } + return result; + } +}; + +template +vtkm::Range ArrayRangeComputeMagnitudeGenericImpl( + vtkm::VecTraitsTagSingleComponent, + const ArrayHandleType& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) +{ + auto mag = vtkm::cont::make_ArrayHandleTransform(input, ScalarMagnitudeFunctor{}); + auto rangeAH = ArrayRangeComputeGeneric(mag, maskArray, computeFiniteRange, device); + return rangeAH.ReadPortal().Get(0); +} + +template +vtkm::Range ArrayRangeComputeMagnitudeGenericImpl( + vtkm::VecTraitsTagMultipleComponents, + const ArrayHandleType& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) +{ + auto magsqr = vtkm::cont::make_ArrayHandleTransform(input, MagnitudeSquareFunctor{}); + auto rangeAH = ArrayRangeComputeGeneric(magsqr, maskArray, computeFiniteRange, device); + auto range = rangeAH.ReadPortal().Get(0); + if (range.IsNonEmpty()) + { + range.Min = vtkm::Sqrt(range.Min); + range.Max = vtkm::Sqrt(range.Max); } return range; } +/// \brief A generic implementation of `ArrayRangeComputeMagnitude`. This is the implementation used +/// when `ArrayRangeComputeMagnitudeImpl` is not specialized. +/// +template +inline vtkm::Range ArrayRangeComputeMagnitudeGeneric( + const vtkm::cont::ArrayHandle& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) +{ + VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "ArrayRangeComputeMagnitude"); + + using VecTraits = vtkm::VecTraits; + + //We want to minimize the amount of code that we do in try execute as + //it is repeated for each + if (input.GetNumberOfValues() < 1) + { + return vtkm::Range{}; + } + + auto flattened = NestedToFlatTransform(input); + return ArrayRangeComputeMagnitudeGenericImpl( + typename VecTraits::HasMultipleComponents{}, flattened, maskArray, computeFiniteRange, device); +} + +//------------------------------------------------------------------------------------------------- template struct ArrayRangeComputeImpl { template - vtkm::cont::ArrayHandle operator()(const vtkm::cont::ArrayHandle& input, - vtkm::cont::DeviceAdapterId device) const + vtkm::cont::ArrayHandle operator()( + const vtkm::cont::ArrayHandle& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) const { - return vtkm::cont::internal::ArrayRangeComputeGeneric(input, device); + return vtkm::cont::internal::ArrayRangeComputeGeneric( + input, maskArray, computeFiniteRange, device); + } +}; + +template +struct ArrayRangeComputeMagnitudeImpl +{ + template + vtkm::Range operator()(const vtkm::cont::ArrayHandle& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange, + vtkm::cont::DeviceAdapterId device) const + { + return vtkm::cont::internal::ArrayRangeComputeMagnitudeGeneric( + input, maskArray, computeFiniteRange, device); } }; } // namespace internal - -template -vtkm::cont::ArrayHandle ArrayRangeComputeTemplate( - const ArrayHandleType& input, +//------------------------------------------------------------------------------------------------- +/// @{ +/// \brief Templated version of ArrayRangeCompute +/// \sa ArrayRangeCompute +/// +template +inline vtkm::cont::ArrayHandle ArrayRangeComputeTemplate( + const vtkm::cont::ArrayHandle& input, + bool computeFiniteRange = false, vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}) { - VTKM_IS_ARRAY_HANDLE(ArrayHandleType); - return internal::ArrayRangeComputeImpl{}(input, device); + return ArrayRangeComputeTemplate( + input, vtkm::cont::ArrayHandle{}, computeFiniteRange, device); } +template +vtkm::cont::ArrayHandle ArrayRangeComputeTemplate( + const vtkm::cont::ArrayHandle& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange = false, + vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}) +{ + VTKM_ASSERT(maskArray.GetNumberOfValues() == 0 || + maskArray.GetNumberOfValues() == input.GetNumberOfValues()); + return internal::ArrayRangeComputeImpl{}(input, maskArray, computeFiniteRange, device); +} + +template +inline vtkm::cont::ArrayHandle ArrayRangeComputeTemplate( + const vtkm::cont::ArrayHandle& input, + vtkm::cont::DeviceAdapterId device) +{ + return ArrayRangeComputeTemplate(input, false, device); +} + +/// @} + +/// @{ +/// \brief Templated version of ArrayRangeComputeMagnitude +/// \sa ArrayRangeComputeMagnitude +/// +template +inline vtkm::Range ArrayRangeComputeMagnitudeTemplate( + const vtkm::cont::ArrayHandle& input, + bool computeFiniteRange = false, + vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}) +{ + return ArrayRangeComputeMagnitudeTemplate( + input, vtkm::cont::ArrayHandle{}, computeFiniteRange, device); +} + +template +vtkm::Range ArrayRangeComputeMagnitudeTemplate( + const vtkm::cont::ArrayHandle& input, + const vtkm::cont::ArrayHandle& maskArray, + bool computeFiniteRange = false, + vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}) +{ + VTKM_ASSERT(maskArray.GetNumberOfValues() == 0 || + maskArray.GetNumberOfValues() == input.GetNumberOfValues()); + return internal::ArrayRangeComputeMagnitudeImpl{}( + input, maskArray, computeFiniteRange, device); +} + +template +inline vtkm::Range ArrayRangeComputeMagnitudeTemplate(const vtkm::cont::ArrayHandle& input, + vtkm::cont::DeviceAdapterId device) +{ + return ArrayRangeComputeMagnitudeTemplate(input, false, device); +} +/// @} + +//----------------------------------------------------------------------------- template VTKM_DEPRECATED(2.1, "Use precompiled ArrayRangeCompute or ArrayRangeComputeTemplate.") inline vtkm::cont::ArrayHandle ArrayRangeCompute( const ArrayHandleType& input, vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}) { - return ArrayRangeComputeTemplate(input, device); + return ArrayRangeComputeTemplate(input, false, device); } } } // namespace vtkm::cont -#define VTK_M_ARRAY_RANGE_COMPUTE_ALL_SCALARS(modifiers, ...) \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device) +#define VTK_M_ARRAY_RANGE_COMPUTE_DCLR(...) \ + vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ + const vtkm::cont::ArrayHandle<__VA_ARGS__>&, \ + const vtkm::cont::ArrayHandle&, \ + bool, \ + vtkm::cont::DeviceAdapterId) -#define VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(modifiers, N, ...) \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& input, \ - vtkm::cont::DeviceAdapterId device); \ - modifiers vtkm::cont::ArrayHandle vtkm::cont::ArrayRangeComputeTemplate( \ - const vtkm::cont::ArrayHandle, __VA_ARGS__>& \ - input, \ - vtkm::cont::DeviceAdapterId device) +#define VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(...) \ + vtkm::Range vtkm::cont::ArrayRangeComputeMagnitudeTemplate( \ + const vtkm::cont::ArrayHandle<__VA_ARGS__>&, \ + const vtkm::cont::ArrayHandle&, \ + bool, \ + vtkm::cont::DeviceAdapterId) +#define VTK_M_ARRAY_RANGE_COMPUTE_INT_SCALARS(modifiers, ...) \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Int8, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Int8, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::UInt8, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::UInt8, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Int16, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Int16, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::UInt16, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::UInt16, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Int32, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Int32, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::UInt32, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::UInt32, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Int64, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Int64, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::UInt64, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::UInt64, __VA_ARGS__) + +#define VTK_M_ARRAY_RANGE_COMPUTE_FLOAT_SCALARS(modifiers, ...) \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Float32, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Float32, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Float64, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Float64, __VA_ARGS__) + +#define VTK_M_ARRAY_RANGE_COMPUTE_BOOL_SCALARS(modifiers, ...) \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(bool, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(bool, __VA_ARGS__) + +#define VTK_M_ARRAY_RANGE_COMPUTE_OTHER_SCALARS(modifiers, ...) \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(char, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(char, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(signed VTKM_UNUSED_INT_TYPE, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(signed VTKM_UNUSED_INT_TYPE, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(unsigned VTKM_UNUSED_INT_TYPE, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(unsigned VTKM_UNUSED_INT_TYPE, __VA_ARGS__) + +#define VTK_M_ARRAY_RANGE_COMPUTE_ALL_SCALARS(modifiers, ...) \ + VTK_M_ARRAY_RANGE_COMPUTE_INT_SCALARS(modifiers, __VA_ARGS__); \ + VTK_M_ARRAY_RANGE_COMPUTE_FLOAT_SCALARS(modifiers, __VA_ARGS__); \ + VTK_M_ARRAY_RANGE_COMPUTE_BOOL_SCALARS(modifiers, __VA_ARGS__); \ + VTK_M_ARRAY_RANGE_COMPUTE_OTHER_SCALARS(modifiers, __VA_ARGS__) + +#define VTK_M_ARRAY_RANGE_COMPUTE_INT_VECN(modifiers, N, ...) \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, __VA_ARGS__) + +#define VTK_M_ARRAY_RANGE_COMPUTE_FLOAT_VECN(modifiers, N, ...) \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, __VA_ARGS__) + +#define VTK_M_ARRAY_RANGE_COMPUTE_BOOL_VECN(modifiers, N, ...) \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, __VA_ARGS__) + +#define VTK_M_ARRAY_RANGE_COMPUTE_OTHER_VECN(modifiers, N, ...) \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, \ + __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, \ + __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_DCLR(vtkm::Vec, \ + __VA_ARGS__); \ + modifiers VTK_M_ARRAY_RANGE_COMPUTE_MAG_DCLR(vtkm::Vec, \ + __VA_ARGS__) + +#define VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(modifiers, N, ...) \ + VTK_M_ARRAY_RANGE_COMPUTE_INT_VECN(modifiers, N, __VA_ARGS__); \ + VTK_M_ARRAY_RANGE_COMPUTE_FLOAT_VECN(modifiers, N, __VA_ARGS__); \ + VTK_M_ARRAY_RANGE_COMPUTE_BOOL_VECN(modifiers, N, __VA_ARGS__); \ + VTK_M_ARRAY_RANGE_COMPUTE_OTHER_VECN(modifiers, N, __VA_ARGS__) + +namespace vtkm +{ +namespace cont +{ + +struct StorageTagSOA; + +template +struct StorageTagCartesianProduct; + +struct StorageTagConstant; + +struct StorageTagCounting; + +struct StorageTagXGCCoordinates; + +struct StorageTagStride; + +} +} // vtkm::cont + +//------------------------------------------------------------------------------------------------- VTKM_INSTANTIATION_BEGIN VTK_M_ARRAY_RANGE_COMPUTE_ALL_SCALARS(extern template VTKM_CONT_TEMPLATE_EXPORT, vtkm::cont::StorageTagBasic); VTKM_INSTANTIATION_END + VTKM_INSTANTIATION_BEGIN VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, 2, vtkm::cont::StorageTagBasic); VTKM_INSTANTIATION_END + VTKM_INSTANTIATION_BEGIN VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, 3, vtkm::cont::StorageTagBasic); VTKM_INSTANTIATION_END + VTKM_INSTANTIATION_BEGIN VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, 4, vtkm::cont::StorageTagBasic); VTKM_INSTANTIATION_END +//------------------------------------------------------------------------------------------------- VTKM_INSTANTIATION_BEGIN VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, 2, vtkm::cont::StorageTagSOA); VTKM_INSTANTIATION_END + VTKM_INSTANTIATION_BEGIN VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, 3, vtkm::cont::StorageTagSOA); VTKM_INSTANTIATION_END + VTKM_INSTANTIATION_BEGIN VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, 4, vtkm::cont::StorageTagSOA); VTKM_INSTANTIATION_END +//------------------------------------------------------------------------------------------------- VTKM_INSTANTIATION_BEGIN -VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN( +VTK_M_ARRAY_RANGE_COMPUTE_FLOAT_VECN( extern template VTKM_CONT_TEMPLATE_EXPORT, 3, vtkm::cont::StorageTagCartesianProduct); VTKM_INSTANTIATION_END +//------------------------------------------------------------------------------------------------- +VTKM_INSTANTIATION_BEGIN +VTK_M_ARRAY_RANGE_COMPUTE_FLOAT_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, + 3, + StorageTagXGCCoordinates); +VTKM_INSTANTIATION_END + +//------------------------------------------------------------------------------------------------- VTKM_INSTANTIATION_BEGIN VTK_M_ARRAY_RANGE_COMPUTE_ALL_SCALARS(extern template VTKM_CONT_TEMPLATE_EXPORT, vtkm::cont::StorageTagConstant); VTKM_INSTANTIATION_END + VTKM_INSTANTIATION_BEGIN VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, 2, vtkm::cont::StorageTagConstant); VTKM_INSTANTIATION_END + VTKM_INSTANTIATION_BEGIN VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, 3, vtkm::cont::StorageTagConstant); VTKM_INSTANTIATION_END + VTKM_INSTANTIATION_BEGIN VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, 4, vtkm::cont::StorageTagConstant); VTKM_INSTANTIATION_END +//------------------------------------------------------------------------------------------------- +VTKM_INSTANTIATION_BEGIN +VTK_M_ARRAY_RANGE_COMPUTE_INT_SCALARS(extern template VTKM_CONT_TEMPLATE_EXPORT, + vtkm::cont::StorageTagCounting); +VTK_M_ARRAY_RANGE_COMPUTE_FLOAT_SCALARS(extern template VTKM_CONT_TEMPLATE_EXPORT, + vtkm::cont::StorageTagCounting); +VTK_M_ARRAY_RANGE_COMPUTE_OTHER_SCALARS(extern template VTKM_CONT_TEMPLATE_EXPORT, + vtkm::cont::StorageTagCounting); +VTKM_INSTANTIATION_END + +VTKM_INSTANTIATION_BEGIN +VTK_M_ARRAY_RANGE_COMPUTE_INT_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, + 2, + vtkm::cont::StorageTagCounting); +VTK_M_ARRAY_RANGE_COMPUTE_FLOAT_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, + 2, + vtkm::cont::StorageTagCounting); +VTK_M_ARRAY_RANGE_COMPUTE_OTHER_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, + 2, + vtkm::cont::StorageTagCounting); +VTKM_INSTANTIATION_END + +VTKM_INSTANTIATION_BEGIN +VTK_M_ARRAY_RANGE_COMPUTE_INT_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, + 3, + vtkm::cont::StorageTagCounting); +VTK_M_ARRAY_RANGE_COMPUTE_FLOAT_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, + 3, + vtkm::cont::StorageTagCounting); +VTK_M_ARRAY_RANGE_COMPUTE_OTHER_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, + 3, + vtkm::cont::StorageTagCounting); +VTKM_INSTANTIATION_END + +VTKM_INSTANTIATION_BEGIN +VTK_M_ARRAY_RANGE_COMPUTE_INT_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, + 4, + vtkm::cont::StorageTagCounting); +VTK_M_ARRAY_RANGE_COMPUTE_FLOAT_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, + 4, + vtkm::cont::StorageTagCounting); +VTK_M_ARRAY_RANGE_COMPUTE_OTHER_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT, + 4, + vtkm::cont::StorageTagCounting); +VTKM_INSTANTIATION_END + +//------------------------------------------------------------------------------------------------- +VTKM_INSTANTIATION_BEGIN +VTK_M_ARRAY_RANGE_COMPUTE_ALL_SCALARS(extern template VTKM_CONT_TEMPLATE_EXPORT, + vtkm::cont::StorageTagStride); +VTKM_INSTANTIATION_END + #endif //vtk_m_cont_ArrayRangeComputeTemplate_h diff --git a/vtkm/cont/ArrayRangeComputeTemplateInstantiationsIncludes.h b/vtkm/cont/ArrayRangeComputeTemplateInstantiationsIncludes.h new file mode 100644 index 000000000..fde7a0dfe --- /dev/null +++ b/vtkm/cont/ArrayRangeComputeTemplateInstantiationsIncludes.h @@ -0,0 +1,22 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ +#ifndef vtk_m_cont_ArrayRangeComputeTemplateInstantiationsIncludes_h +#define vtk_m_cont_ArrayRangeComputeTemplateInstantiationsIncludes_h + +#include + +#include +#include +#include +#include +#include +#include + +#endif // vtk_m_cont_ArrayRangeComputeTemplateInstantiationsIncludes_h diff --git a/vtkm/cont/CMakeLists.txt b/vtkm/cont/CMakeLists.txt index c5de8ac6f..5ff482a1f 100644 --- a/vtkm/cont/CMakeLists.txt +++ b/vtkm/cont/CMakeLists.txt @@ -51,6 +51,7 @@ set(headers ArrayPortalToIterators.h ArrayRangeCompute.h ArrayRangeComputeTemplate.h + ArrayRangeComputeTemplateInstantiationsIncludes.h AssignerPartitionedDataSet.h AtomicArray.h BitField.h @@ -135,7 +136,6 @@ set(sources ArrayHandleBasic.cxx ArrayHandleSOA.cxx ArrayHandleStride.cxx - ArrayHandleUniformPointCoordinates.cxx AssignerPartitionedDataSet.cxx BitField.cxx BoundsCompute.cxx @@ -183,6 +183,8 @@ set(sources set(device_sources ArrayCopy.cxx ArrayGetValues.cxx + ArrayHandleIndex.cxx + ArrayHandleUniformPointCoordinates.cxx ArrayRangeCompute.cxx CellLocatorBoundingIntervalHierarchy.cxx CellLocatorUniformBins.cxx @@ -193,6 +195,7 @@ set(device_sources ConvertNumComponentsToOffsets.cxx Field.cxx internal/ArrayCopyUnknown.cxx + internal/ArrayRangeComputeUtils.cxx internal/Buffer.cxx internal/MapArrayPermutation.cxx MergePartitionedDataSet.cxx @@ -268,6 +271,7 @@ vtkm_install_headers(vtkm/cont # compiles by breaking them up into smaller units. vtkm_add_instantiations(array_range_instantiations INSTANTIATIONS_FILE ArrayRangeComputeTemplate.h + TEMPLATE_SOURCE ArrayRangeComputeTemplateInstantiationsIncludes.h ) list(APPEND device_sources ${array_range_instantiations}) diff --git a/vtkm/cont/internal/ArrayRangeComputeUtils.cxx b/vtkm/cont/internal/ArrayRangeComputeUtils.cxx new file mode 100644 index 000000000..0a0d0219e --- /dev/null +++ b/vtkm/cont/internal/ArrayRangeComputeUtils.cxx @@ -0,0 +1,52 @@ + +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#include + +#include +#include +#include +#include + +#include + +#include + +namespace +{ + +struct UnmaskedIndicesTransform +{ + VTKM_EXEC vtkm::Id2 operator()(vtkm::Pair in) const + { + if (in.first == 0) + { + return { std::numeric_limits::max(), std::numeric_limits::min() }; + } + return { in.second }; + } +}; + +} // namespace + +vtkm::Id2 vtkm::cont::internal::GetFirstAndLastUnmaskedIndices( + const vtkm::cont::ArrayHandle& maskArray, + vtkm::cont::DeviceAdapterId device) +{ + vtkm::Id2 initialValue = { std::numeric_limits::max(), + std::numeric_limits::min() }; + auto maskValsAndInds = vtkm::cont::make_ArrayHandleZip( + maskArray, vtkm::cont::ArrayHandleIndex(maskArray.GetNumberOfValues())); + auto unmaskedIndices = + vtkm::cont::make_ArrayHandleTransform(maskValsAndInds, UnmaskedIndicesTransform{}); + return vtkm::cont::Algorithm::Reduce( + device, unmaskedIndices, initialValue, vtkm::MinAndMax()); +} diff --git a/vtkm/cont/internal/ArrayRangeComputeUtils.h b/vtkm/cont/internal/ArrayRangeComputeUtils.h new file mode 100644 index 000000000..618df2fad --- /dev/null +++ b/vtkm/cont/internal/ArrayRangeComputeUtils.h @@ -0,0 +1,33 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ +#ifndef vtk_m_cont_internal_ArrayRangeComputeUtils_h +#define vtk_m_cont_internal_ArrayRangeComputeUtils_h + +#include + +#include +#include + +namespace vtkm +{ +namespace cont +{ +namespace internal +{ + +VTKM_CONT_EXPORT vtkm::Id2 GetFirstAndLastUnmaskedIndices( + const vtkm::cont::ArrayHandle& maskArray, + vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}); + +} +} +} // vtkm::cont::internal + +#endif // vtk_m_cont_internal_ArrayRangeComputeUtils_h diff --git a/vtkm/cont/internal/CMakeLists.txt b/vtkm/cont/internal/CMakeLists.txt index 55a05b82a..9146f36ce 100644 --- a/vtkm/cont/internal/CMakeLists.txt +++ b/vtkm/cont/internal/CMakeLists.txt @@ -12,6 +12,7 @@ set(headers ArrayCopyUnknown.h ArrayHandleExecutionManager.h ArrayPortalFromIterators.h + ArrayRangeComputeUtils.h ArrayTransfer.h Buffer.h CastInvalidValue.h diff --git a/vtkm/cont/testing/UnitTestArrayRangeCompute.cxx b/vtkm/cont/testing/UnitTestArrayRangeCompute.cxx index 05f3b81f2..bc7fd02c9 100644 --- a/vtkm/cont/testing/UnitTestArrayRangeCompute.cxx +++ b/vtkm/cont/testing/UnitTestArrayRangeCompute.cxx @@ -36,8 +36,10 @@ namespace constexpr vtkm::Id ARRAY_SIZE = 20; template -void VerifyRange(const vtkm::cont::ArrayHandle& array, - const vtkm::cont::ArrayHandle& computedRangeArray) +void VerifyRangeScalar(const vtkm::cont::ArrayHandle& array, + const vtkm::cont::ArrayHandle& computedRangeArray, + const vtkm::cont::ArrayHandle& maskArray, + bool finitesOnly) { using Traits = vtkm::VecTraits; vtkm::IdComponent numComponents = Traits::NUM_COMPONENTS; @@ -46,40 +48,237 @@ void VerifyRange(const vtkm::cont::ArrayHandle& array, auto computedRangePortal = computedRangeArray.ReadPortal(); auto portal = array.ReadPortal(); + auto maskPortal = maskArray.ReadPortal(); for (vtkm::IdComponent component = 0; component < numComponents; ++component) { vtkm::Range computedRange = computedRangePortal.Get(component); - vtkm::Range expectedRange; + vtkm::Range expectedRange{}; for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); ++index) { - T value = portal.Get(index); - expectedRange.Include(Traits::GetComponent(value, component)); + if (maskPortal.GetNumberOfValues() != 0 && (maskPortal.Get(index) == 0)) + { + continue; + } + auto value = static_cast(Traits::GetComponent(portal.Get(index), component)); + if (finitesOnly && !vtkm::IsFinite(value)) + { + continue; + } + expectedRange.Include(value); } + try + { + VTKM_TEST_ASSERT(!vtkm::IsNan(computedRange.Min)); + VTKM_TEST_ASSERT(!vtkm::IsNan(computedRange.Max)); + VTKM_TEST_ASSERT((!expectedRange.IsNonEmpty() && !computedRange.IsNonEmpty()) || + (test_equal(expectedRange, computedRange))); + } + catch (const vtkm::testing::Testing::TestFailure&) + { + std::cout << "Test array: \n"; + vtkm::cont::printSummary_ArrayHandle(array, std::cout, true); + std::cout << "Mask array: \n"; + vtkm::cont::printSummary_ArrayHandle(maskArray, std::cout, true); + std::cout << "Range type: " << (finitesOnly ? "Scalar, Finite" : "Scalar, NonFinite") << "\n"; + std::cout << "Computed range: \n"; + vtkm::cont::printSummary_ArrayHandle(computedRangeArray, std::cout, true); + std::cout << "Expected range: " << expectedRange << ", component: " << component << "\n"; + throw; + } + } +} + +template +void VerifyRangeVector(const vtkm::cont::ArrayHandle& array, + const vtkm::Range& computedRange, + const vtkm::cont::ArrayHandle& maskArray, + bool finitesOnly) +{ + auto portal = array.ReadPortal(); + auto maskPortal = maskArray.ReadPortal(); + vtkm::Range expectedRange{}; + for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); ++index) + { + if (maskPortal.GetNumberOfValues() != 0 && (maskPortal.Get(index) == 0)) + { + continue; + } + auto value = static_cast(vtkm::MagnitudeSquared(portal.Get(index))); + if (finitesOnly && !vtkm::IsFinite(value)) + { + continue; + } + expectedRange.Include(value); + } + + if (expectedRange.IsNonEmpty()) + { + expectedRange.Min = vtkm::Sqrt(expectedRange.Min); + expectedRange.Max = vtkm::Sqrt(expectedRange.Max); + } + + try + { VTKM_TEST_ASSERT(!vtkm::IsNan(computedRange.Min)); VTKM_TEST_ASSERT(!vtkm::IsNan(computedRange.Max)); - VTKM_TEST_ASSERT(test_equal(expectedRange, computedRange)); + VTKM_TEST_ASSERT((!expectedRange.IsNonEmpty() && !computedRange.IsNonEmpty()) || + (test_equal(expectedRange, computedRange))); } + catch (const vtkm::testing::Testing::TestFailure&) + { + std::cout << "Test array: \n"; + vtkm::cont::printSummary_ArrayHandle(array, std::cout, true); + std::cout << "Mask array: \n"; + vtkm::cont::printSummary_ArrayHandle(maskArray, std::cout, true); + std::cout << "Range type: " << (finitesOnly ? "Vector, Finite" : "Vector, NonFinite") << "\n"; + std::cout << "Computed range: " << computedRange << "\n"; + std::cout << "Expected range: " << expectedRange << "\n"; + throw; + } +} + +auto FillMaskArray(vtkm::Id length) +{ + vtkm::cont::ArrayHandle maskArray; + maskArray.Allocate(length); + + vtkm::cont::ArrayHandleRandomUniformBits randomBits(length + 1); + auto randomPortal = randomBits.ReadPortal(); + switch (randomPortal.Get(length) % 3) + { + case 0: // all masked + maskArray.Fill(0); + break; + case 1: // none masked + maskArray.Fill(1); + break; + case 2: // random masked + default: + { + auto maskPortal = maskArray.WritePortal(); + for (vtkm::Id i = 0; i < length; ++i) + { + vtkm::UInt8 maskVal = ((randomPortal.Get(i) % 8) == 0) ? 0 : 1; + maskPortal.Set(i, maskVal); + } + break; + } + } + + return maskArray; } template void CheckRange(const vtkm::cont::ArrayHandle& array) { - VerifyRange(array, vtkm::cont::ArrayRangeCompute(array)); + auto length = array.GetNumberOfValues(); + vtkm::cont::ArrayHandle emptyMaskArray; + + auto maskArray = FillMaskArray(length); + + vtkm::cont::ArrayHandle scalarRange; + std::cout << "\tchecking scalar range without mask\n"; + scalarRange = vtkm::cont::ArrayRangeCompute(array); + VerifyRangeScalar(array, scalarRange, emptyMaskArray, false); + std::cout << "\tchecking scalar range with mask\n"; + scalarRange = vtkm::cont::ArrayRangeCompute(array, maskArray); + VerifyRangeScalar(array, scalarRange, maskArray, false); + + vtkm::Range vectorRange; + std::cout << "\tchecking vector range without mask\n"; + vectorRange = vtkm::cont::ArrayRangeComputeMagnitude(array); + VerifyRangeVector(array, vectorRange, emptyMaskArray, false); + std::cout << "\tchecking vector range with mask\n"; + vectorRange = vtkm::cont::ArrayRangeComputeMagnitude(array, maskArray); + VerifyRangeVector(array, vectorRange, maskArray, false); +} + +template +void CheckRangeFiniteImpl(const ArrayHandleType& array, std::true_type) +{ + auto length = array.GetNumberOfValues(); + vtkm::cont::ArrayHandle emptyMaskArray; + + auto maskArray = FillMaskArray(length); + + vtkm::cont::ArrayHandle scalarRange; + std::cout << "\tchecking finite scalar range without mask\n"; + scalarRange = vtkm::cont::ArrayRangeCompute(array, true); + VerifyRangeScalar(array, scalarRange, emptyMaskArray, true); + std::cout << "\tchecking finite scalar range with mask\n"; + scalarRange = vtkm::cont::ArrayRangeCompute(array, maskArray, true); + VerifyRangeScalar(array, scalarRange, maskArray, true); + + vtkm::Range vectorRange; + std::cout << "\tchecking finite vector range without mask\n"; + vectorRange = vtkm::cont::ArrayRangeComputeMagnitude(array, true); + VerifyRangeVector(array, vectorRange, emptyMaskArray, true); + std::cout << "\tchecking finite vector range with mask\n"; + vectorRange = vtkm::cont::ArrayRangeComputeMagnitude(array, maskArray, true); + VerifyRangeVector(array, vectorRange, maskArray, true); +} + +template +void CheckRangeFiniteImpl(const ArrayHandleType&, std::false_type) +{ } template -void FillArray(vtkm::cont::ArrayHandle& array) +void CheckRangeFinite(const vtkm::cont::ArrayHandle& array) +{ + using ComponentType = typename vtkm::VecTraits::ComponentType; + auto tag = std::integral_constant < bool, + std::is_same::value || + std::is_same::value > {}; + CheckRangeFiniteImpl(array, tag); +} + +// Transform random values in range [0, 1) to the range [From, To). +// If the `AddNonFinites` flag is set, some values are transformed to non-finite values. +struct TransformRange +{ + vtkm::Float64 From, To; + bool AddNonFinites = false; + + VTKM_EXEC vtkm::Float64 operator()(vtkm::Float64 in) const + { + if (AddNonFinites) + { + if (in >= 0.3 && in <= 0.33) + { + return vtkm::NegativeInfinity64(); + } + if (in >= 0.9 && in <= 0.93) + { + return vtkm::Infinity64(); + } + } + return (in * (this->To - this->From)) + this->From; + } +}; + +template +void FillArray(vtkm::cont::ArrayHandle& array, bool addNonFinites) { using Traits = vtkm::VecTraits; vtkm::IdComponent numComponents = Traits::NUM_COMPONENTS; + // non-finites only applies to floating point types + addNonFinites = addNonFinites && + (std::is_same::value || + std::is_same::value); + array.AllocateAndFill(ARRAY_SIZE, vtkm::TypeTraits::ZeroInitialization()); for (vtkm::IdComponent component = 0; component < numComponents; ++component) { vtkm::cont::ArrayHandleRandomUniformReal randomArray(ARRAY_SIZE); auto dest = vtkm::cont::make_ArrayHandleExtractComponent(array, component); - vtkm::cont::ArrayCopyDevice(randomArray, dest); + auto transformFunctor = std::numeric_limits::is_signed + ? TransformRange{ -100.0, 100.0, addNonFinites } + : TransformRange{ 0.0, 200.0, addNonFinites }; + vtkm::cont::ArrayCopyDevice( + vtkm::cont::make_ArrayHandleTransform(randomArray, transformFunctor), dest); } } @@ -88,8 +287,10 @@ void TestBasicArray() { std::cout << "Checking basic array" << std::endl; vtkm::cont::ArrayHandleBasic array; - FillArray(array); + FillArray(array, false); CheckRange(array); + FillArray(array, true); + CheckRangeFinite(array); } template @@ -97,8 +298,10 @@ void TestSOAArray(vtkm::TypeTraitsVectorTag) { std::cout << "Checking SOA array" << std::endl; vtkm::cont::ArrayHandleSOA array; - FillArray(array); + FillArray(array, false); CheckRange(array); + FillArray(array, true); + CheckRangeFinite(array); } template @@ -112,8 +315,10 @@ void TestStrideArray() { std::cout << "Checking stride array" << std::endl; vtkm::cont::ArrayHandleBasic array; - FillArray(array); + FillArray(array, false); CheckRange(vtkm::cont::ArrayHandleStride(array, ARRAY_SIZE / 2, 2, 1)); + FillArray(array, true); + CheckRangeFinite(vtkm::cont::ArrayHandleStride(array, ARRAY_SIZE / 2, 2, 1)); } template @@ -122,23 +327,30 @@ void TestCastArray() std::cout << "Checking cast array" << std::endl; using CastType = typename vtkm::VecTraits::template ReplaceBaseComponentType; vtkm::cont::ArrayHandle array; - FillArray(array); + FillArray(array, false); CheckRange(vtkm::cont::make_ArrayHandleCast(array)); } +template +auto FillCartesianProductArray(bool addNonFinites) +{ + vtkm::cont::ArrayHandleBasic array0; + FillArray(array0, addNonFinites); + vtkm::cont::ArrayHandleBasic array1; + FillArray(array1, addNonFinites); + vtkm::cont::ArrayHandleBasic array2; + FillArray(array2, addNonFinites); + return vtkm::cont::make_ArrayHandleCartesianProduct(array0, array1, array2); +} + template void TestCartesianProduct(vtkm::TypeTraitsScalarTag) { std::cout << "Checking Cartesian product" << std::endl; - - vtkm::cont::ArrayHandleBasic array0; - FillArray(array0); - vtkm::cont::ArrayHandleBasic array1; - FillArray(array1); - vtkm::cont::ArrayHandleBasic array2; - FillArray(array2); - - CheckRange(vtkm::cont::make_ArrayHandleCartesianProduct(array0, array1, array2)); + auto array = FillCartesianProductArray(false); + CheckRange(array); + array = FillCartesianProductArray(true); + CheckRangeFinite(array); } template @@ -147,19 +359,27 @@ void TestCartesianProduct(vtkm::TypeTraitsVectorTag) // Skip test. } +template +auto FillCompositeVectorArray(bool addNonFinites) +{ + vtkm::cont::ArrayHandleBasic array0; + FillArray(array0, addNonFinites); + vtkm::cont::ArrayHandleBasic array1; + FillArray(array1, addNonFinites); + vtkm::cont::ArrayHandleBasic array2; + FillArray(array2, addNonFinites); + return vtkm::cont::make_ArrayHandleCompositeVector(array0, array1, array2); +} + template void TestComposite(vtkm::TypeTraitsScalarTag) { std::cout << "Checking composite vector array" << std::endl; - vtkm::cont::ArrayHandleBasic array0; - FillArray(array0); - vtkm::cont::ArrayHandleBasic array1; - FillArray(array1); - vtkm::cont::ArrayHandleBasic array2; - FillArray(array2); - - CheckRange(vtkm::cont::make_ArrayHandleCompositeVector(array0, array1, array2)); + auto array = FillCompositeVectorArray(false); + CheckRange(array); + array = FillCompositeVectorArray(true); + CheckRangeFinite(array); } template @@ -174,8 +394,10 @@ void TestGroup(vtkm::TypeTraitsScalarTag) std::cout << "Checking group vec array" << std::endl; vtkm::cont::ArrayHandleBasic array; - FillArray(array); + FillArray(array, false); CheckRange(vtkm::cont::make_ArrayHandleGroupVec<2>(array)); + FillArray(array, true); + CheckRangeFinite(vtkm::cont::make_ArrayHandleGroupVec<2>(array)); } template @@ -190,8 +412,10 @@ void TestView() std::cout << "Checking view array" << std::endl; vtkm::cont::ArrayHandleBasic array; - FillArray(array); + FillArray(array, false); CheckRange(vtkm::cont::make_ArrayHandleView(array, 2, ARRAY_SIZE - 5)); + FillArray(array, true); + CheckRangeFinite(vtkm::cont::make_ArrayHandleView(array, 2, ARRAY_SIZE - 5)); } template @@ -234,8 +458,10 @@ void TestXGCCoordinates() { std::cout << "Checking XGC coordinates array" << std::endl; vtkm::cont::ArrayHandle array; - FillArray(array); + FillArray(array, false); CheckRange(vtkm::cont::make_ArrayHandleXGCCoordinates(array, 4, true)); + FillArray(array, true); + CheckRangeFinite(vtkm::cont::make_ArrayHandleXGCCoordinates(array, 4, true)); } struct DoTestFunctor diff --git a/vtkm/filter/mesh_info/testing/UnitTestMeshQualityFilter.cxx b/vtkm/filter/mesh_info/testing/UnitTestMeshQualityFilter.cxx index 3e21dcd20..89bb917ae 100644 --- a/vtkm/filter/mesh_info/testing/UnitTestMeshQualityFilter.cxx +++ b/vtkm/filter/mesh_info/testing/UnitTestMeshQualityFilter.cxx @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/vtkm/filter/scalar_topology/worklet/contourtree_augmented/meshtypes/ContourTreeMesh.h b/vtkm/filter/scalar_topology/worklet/contourtree_augmented/meshtypes/ContourTreeMesh.h index 197f50f69..e3a716196 100644 --- a/vtkm/filter/scalar_topology/worklet/contourtree_augmented/meshtypes/ContourTreeMesh.h +++ b/vtkm/filter/scalar_topology/worklet/contourtree_augmented/meshtypes/ContourTreeMesh.h @@ -73,8 +73,6 @@ #include #include #include -#include -#include #include #include #include @@ -576,9 +574,7 @@ template inline void ContourTreeMesh::ComputeMaxNeighbors() { auto neighborCounts = make_ArrayHandleOffsetsToNumComponents(this->NeighborOffsets); - vtkm::cont::ArrayHandle rangeArray = - vtkm::cont::ArrayRangeComputeTemplate(neighborCounts); - this->MaxNeighbors = static_cast(rangeArray.ReadPortal().Get(0).Max); + this->MaxNeighbors = vtkm::cont::Algorithm::Reduce(neighborCounts, 0, vtkm::Maximum{}); } // Define the behavior for the execution object generate by the PrepareForExecution function