diff --git a/docs/changelog/array-range-fast-paths.md b/docs/changelog/array-range-fast-paths.md new file mode 100644 index 000000000..7c2c47eae --- /dev/null +++ b/docs/changelog/array-range-fast-paths.md @@ -0,0 +1,18 @@ +# Fast paths for `ArrayRangeCompute` fixed + +The precompiled `ArrayRangeCompute` function was not following proper fast +paths for special arrays. For example, when computing the range of an +`ArrayHandleUniformPointCoordinates`, the ranges should be taken from the +origin and spacing of the special array. However, the precompiled version +was calling the generic range computation, which was doing an unnecessary +reduction over the entire array. These fast paths have been fixed. + +These mistakes in the code were caused by quirks in how templated method +overloading works. To prevent this mistake from happening again in the +precompiled `ArrayRangeCompute` function and elsewhere, all templated forms +of `ArrayRangeCompute` have been deprecated. Most will call +`ArrayRangeCompute` with no issues. For those that need the templated +version, `ArrayRangeComputeTemplate` replaces the old templated +`ArrayRangeCompute`. There is exactly one templated declaration of +`ArrayRangeComputeTemplate` that uses a class, `ArrayRangeComputeImpl`, +with partial specialization to ensure the correct form is used. diff --git a/vtkm/cont/ArrayHandleCartesianProduct.h b/vtkm/cont/ArrayHandleCartesianProduct.h index 649f770ea..037f9ee03 100644 --- a/vtkm/cont/ArrayHandleCartesianProduct.h +++ b/vtkm/cont/ArrayHandleCartesianProduct.h @@ -11,6 +11,8 @@ #define vtk_m_cont_ArrayHandleCartesianProduct_h #include +#include +#include #include #include @@ -486,6 +488,77 @@ struct ArrayExtractComponentImpl> } }; +template +struct ArrayRangeComputeImpl; + +template +struct VTKM_CONT_EXPORT ArrayRangeComputeImpl> +{ + template + VTKM_CONT vtkm::cont::ArrayHandle operator()( + const vtkm::cont::ArrayHandle, + vtkm::cont::StorageTagCartesianProduct>& input_, + vtkm::cont::DeviceAdapterId device) const + { + vtkm::cont::ArrayHandle result; + result.Allocate(3); + 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) + { + result.Allocate(result.GetNumberOfValues() + numSubComponents - 1, vtkm::CopyFlag::On); + resultPortal = result.WritePortal(); + } + 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; + } +}; + } // namespace internal } diff --git a/vtkm/cont/ArrayHandleConstant.h b/vtkm/cont/ArrayHandleConstant.h index 106f4354e..45d67e198 100644 --- a/vtkm/cont/ArrayHandleConstant.h +++ b/vtkm/cont/ArrayHandleConstant.h @@ -12,6 +12,9 @@ #include +#include +#include + namespace vtkm { namespace cont @@ -90,6 +93,36 @@ vtkm::cont::ArrayHandleConstant make_ArrayHandleConstant(T value, vtkm::Id nu { return vtkm::cont::ArrayHandleConstant(value, numberOfValues); } + +namespace internal +{ + +template +struct ArrayRangeComputeImpl; + +template <> +struct VTKM_CONT_EXPORT ArrayRangeComputeImpl +{ + template + VTKM_CONT vtkm::cont::ArrayHandle operator()( + const vtkm::cont::ArrayHandle& input, + vtkm::cont::DeviceAdapterId) const + { + auto value = vtkm::make_VecFlat(input.ReadPortal().Get(0)); + + vtkm::cont::ArrayHandle result; + result.Allocate(value.GetNumberOfComponents()); + auto resultPortal = result.WritePortal(); + for (vtkm::IdComponent index = 0; index < value.GetNumberOfComponents(); ++index) + { + resultPortal.Set(index, vtkm::Range{ value[index], value[index] }); + } + return result; + } +}; + +} // namespace internal + } } // vtkm::cont diff --git a/vtkm/cont/ArrayHandleCounting.h b/vtkm/cont/ArrayHandleCounting.h index 7f6f08e0d..2840eeaeb 100644 --- a/vtkm/cont/ArrayHandleCounting.h +++ b/vtkm/cont/ArrayHandleCounting.h @@ -12,6 +12,7 @@ #include +#include #include #include @@ -152,6 +153,52 @@ make_ArrayHandleCounting(CountingValueType start, CountingValueType step, vtkm:: { return vtkm::cont::ArrayHandleCounting(start, step, length); } + +namespace internal +{ + +template +struct ArrayRangeComputeImpl; + +template <> +struct VTKM_CONT_EXPORT ArrayRangeComputeImpl +{ + template + VTKM_CONT vtkm::cont::ArrayHandle operator()( + const vtkm::cont::ArrayHandle& input, + vtkm::cont::DeviceAdapterId) const + { + using Traits = vtkm::VecTraits; + vtkm::cont::ArrayHandle result; + result.Allocate(Traits::NUM_COMPONENTS); + auto portal = result.WritePortal(); + if (portal.GetNumberOfValues() > 0) + { + 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{}); + } + } + return result; + } +}; + +} // namespace internal + } } // namespace vtkm::cont diff --git a/vtkm/cont/ArrayHandleIndex.h b/vtkm/cont/ArrayHandleIndex.h index d5dcc0fc9..7bccba25b 100644 --- a/vtkm/cont/ArrayHandleIndex.h +++ b/vtkm/cont/ArrayHandleIndex.h @@ -10,6 +10,7 @@ #ifndef vtk_m_cont_ArrayHandleIndex_h #define vtk_m_cont_ArrayHandleIndex_h +#include #include namespace vtkm @@ -71,6 +72,29 @@ VTKM_CONT inline vtkm::cont::ArrayHandleIndex make_ArrayHandleIndex(vtkm::Id len { return vtkm::cont::ArrayHandleIndex(length); } + +namespace internal +{ + +template +struct ArrayRangeComputeImpl; + +template <> +struct VTKM_CONT_EXPORT ArrayRangeComputeImpl +{ + VTKM_CONT vtkm::cont::ArrayHandle operator()( + const vtkm::cont::ArrayHandle& input, + vtkm::cont::DeviceAdapterId) const + { + vtkm::cont::ArrayHandle result; + result.Allocate(1); + result.WritePortal().Set(0, vtkm::Range(0, input.GetNumberOfValues() - 1)); + return result; + } +}; + +} // namespace internal + } } // namespace vtkm::cont diff --git a/vtkm/cont/ArrayHandleUniformPointCoordinates.cxx b/vtkm/cont/ArrayHandleUniformPointCoordinates.cxx index d12e79b6a..a4b5f5668 100644 --- a/vtkm/cont/ArrayHandleUniformPointCoordinates.cxx +++ b/vtkm/cont/ArrayHandleUniformPointCoordinates.cxx @@ -86,6 +86,28 @@ ArrayExtractComponentImpl::operator()( } } +VTKM_CONT vtkm::cont::ArrayHandle +ArrayRangeComputeImpl::operator()( + const vtkm::cont::ArrayHandleUniformPointCoordinates& input, + vtkm::cont::DeviceAdapterId vtkmNotUsed(device)) const +{ + vtkm::internal::ArrayPortalUniformPointCoordinates portal = input.ReadPortal(); + + // In this portal we know that the min value is the first entry and the + // max value is the last entry. + vtkm::Vec3f minimum = portal.Get(0); + vtkm::Vec3f maximum = portal.Get(portal.GetNumberOfValues() - 1); + + vtkm::cont::ArrayHandle rangeArray; + rangeArray.Allocate(3); + vtkm::cont::ArrayHandle::WritePortalType outPortal = rangeArray.WritePortal(); + outPortal.Set(0, vtkm::Range(minimum[0], maximum[0])); + outPortal.Set(1, vtkm::Range(minimum[1], maximum[1])); + outPortal.Set(2, vtkm::Range(minimum[2], maximum[2])); + + return rangeArray; +} + } // namespace internal } diff --git a/vtkm/cont/ArrayHandleUniformPointCoordinates.h b/vtkm/cont/ArrayHandleUniformPointCoordinates.h index ebbf18975..a0f425d27 100644 --- a/vtkm/cont/ArrayHandleUniformPointCoordinates.h +++ b/vtkm/cont/ArrayHandleUniformPointCoordinates.h @@ -10,6 +10,7 @@ #ifndef vtk_m_cont_ArrayHandleUniformPointCoordinates_h #define vtk_m_cont_ArrayHandleUniformPointCoordinates_h +#include #include #include #include @@ -83,6 +84,17 @@ struct VTKM_CONT_EXPORT ArrayExtractComponentImpl +struct ArrayRangeComputeImpl; + +template <> +struct VTKM_CONT_EXPORT ArrayRangeComputeImpl +{ + VTKM_CONT vtkm::cont::ArrayHandle operator()( + const vtkm::cont::ArrayHandleUniformPointCoordinates& input, + vtkm::cont::DeviceAdapterId device) const; +}; + } // namespace internal } diff --git a/vtkm/cont/ArrayRangeCompute.cxx b/vtkm/cont/ArrayRangeCompute.cxx index 8ff99fdd2..f2e1a0f31 100644 --- a/vtkm/cont/ArrayRangeCompute.cxx +++ b/vtkm/cont/ArrayRangeCompute.cxx @@ -12,118 +12,16 @@ #include -namespace vtkm -{ -namespace cont -{ - -void ThrowArrayRangeComputeFailed() -{ - throw vtkm::cont::ErrorExecution("Failed to run ArrayRangeComputation on any device."); -} - -#define VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(T, Storage) \ - VTKM_CONT \ - vtkm::cont::ArrayHandle ArrayRangeCompute( \ - const vtkm::cont::ArrayHandle& input, vtkm::cont::DeviceAdapterId device) \ - { \ - return detail::ArrayRangeComputeImpl(input, device); \ - } \ - struct SwallowSemicolon -#define VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(T, N, Storage) \ - VTKM_CONT \ - vtkm::cont::ArrayHandle ArrayRangeCompute( \ - const vtkm::cont::ArrayHandle, Storage>& input, \ - vtkm::cont::DeviceAdapterId device) \ - { \ - return detail::ArrayRangeComputeImpl(input, device); \ - } \ - struct SwallowSemicolon - -#define VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_SCALAR_T(Storage) \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Int8, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::UInt8, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Int16, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::UInt16, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Int32, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::UInt32, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Int64, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::UInt64, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Float32, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Float64, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(char, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(signed VTKM_UNUSED_INT_TYPE, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(unsigned VTKM_UNUSED_INT_TYPE, Storage) - -#define VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(N, Storage) \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Int8, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::UInt8, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Int16, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::UInt16, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Int32, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::UInt32, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Int64, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::UInt64, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Float32, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Float64, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(char, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(signed VTKM_UNUSED_INT_TYPE, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(unsigned VTKM_UNUSED_INT_TYPE, N, Storage) - -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_SCALAR_T(vtkm::cont::StorageTagBasic); - -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(2, vtkm::cont::StorageTagBasic); -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(3, vtkm::cont::StorageTagBasic); -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(4, vtkm::cont::StorageTagBasic); - -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(2, vtkm::cont::StorageTagSOA); -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(3, vtkm::cont::StorageTagSOA); -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(4, vtkm::cont::StorageTagSOA); - -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_SCALAR_T(vtkm::cont::StorageTagStride); - -VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Float32, 3, vtkm::cont::StorageTagXGCCoordinates); -VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Float64, 3, vtkm::cont::StorageTagXGCCoordinates); - -#undef VTKM_ARRAY_RANGE_COMPUTE_IMPL_T -#undef VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC -#undef VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_SCALAR_T -#undef VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC - -// Special implementation for regular point coordinates, which are easy -// to determine. -VTKM_CONT -vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle& array, - vtkm::cont::DeviceAdapterId) -{ - vtkm::internal::ArrayPortalUniformPointCoordinates portal = array.ReadPortal(); - - // In this portal we know that the min value is the first entry and the - // max value is the last entry. - vtkm::Vec3f minimum = portal.Get(0); - vtkm::Vec3f maximum = portal.Get(portal.GetNumberOfValues() - 1); - - vtkm::cont::ArrayHandle rangeArray; - rangeArray.Allocate(3); - vtkm::cont::ArrayHandle::WritePortalType outPortal = rangeArray.WritePortal(); - outPortal.Set(0, vtkm::Range(minimum[0], maximum[0])); - outPortal.Set(1, vtkm::Range(minimum[1], maximum[1])); - outPortal.Set(2, vtkm::Range(minimum[2], maximum[2])); - - return rangeArray; -} - -vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle& input, - vtkm::cont::DeviceAdapterId) -{ - vtkm::cont::ArrayHandle result; - result.Allocate(1); - result.WritePortal().Set(0, vtkm::Range(0, input.GetNumberOfValues() - 1)); - return result; -} +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace { @@ -152,7 +50,7 @@ struct ComputeRangeFunctor vtkm::cont::DeviceAdapterId device, vtkm::cont::ArrayHandle& ranges) const { - ranges = vtkm::cont::ArrayRangeCompute(array, device); + ranges = vtkm::cont::ArrayRangeComputeTemplate(array, device); } // Used with vtkm::ListForEach to get components @@ -172,7 +70,7 @@ struct ComputeRangeFunctor { vtkm::cont::ArrayHandleStride componentArray = array.ExtractComponent(componentI); vtkm::cont::ArrayHandle componentRange = - vtkm::cont::ArrayRangeCompute(componentArray, device); + vtkm::cont::ArrayRangeComputeTemplate(componentArray, device); rangePortal.Set(componentI, componentRange.ReadPortal().Get(0)); } success = true; @@ -191,6 +89,21 @@ vtkm::cont::ArrayHandle ComputeForStorage(const vtkm::cont::Unknown } // anonymous namespace +namespace vtkm +{ +namespace cont +{ + +namespace internal +{ + +void ThrowArrayRangeComputeFailed() +{ + throw vtkm::cont::ErrorExecution("Failed to run ArrayRangeComputation on any device."); +} + +} // namespace internal + vtkm::cont::ArrayHandle ArrayRangeCompute(const vtkm::cont::UnknownArrayHandle& array, vtkm::cont::DeviceAdapterId device) { @@ -214,7 +127,7 @@ vtkm::cont::ArrayHandle ArrayRangeCompute(const vtkm::cont::Unknown { vtkm::cont::ArrayHandleUniformPointCoordinates uniformPoints; array.AsArrayHandle(uniformPoints); - return vtkm::cont::ArrayRangeCompute(uniformPoints, device); + return vtkm::cont::ArrayRangeComputeTemplate(uniformPoints, device); } using CartesianProductStorage = vtkm::cont::StorageTagCartesianProduct ArrayRangeCompute(const vtkm::cont::Unknown } if (array.IsStorageType()) { - return ArrayRangeCompute(array.AsArrayHandle(), device); + return ArrayRangeComputeTemplate(array.AsArrayHandle(), device); } } catch (vtkm::cont::ErrorBadType&) diff --git a/vtkm/cont/ArrayRangeCompute.h b/vtkm/cont/ArrayRangeCompute.h index dfbc01f80..e87b612ea 100644 --- a/vtkm/cont/ArrayRangeCompute.h +++ b/vtkm/cont/ArrayRangeCompute.h @@ -31,7 +31,6 @@ 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 @@ -48,179 +47,27 @@ namespace cont /// 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 include -/// ArrayRangeComputeTemplate.h. This contains a templated version of ArrayRangeCompute -/// that will compile for any `ArrayHandle` type not already handled. +/// 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. /// - VTKM_CONT_EXPORT vtkm::cont::ArrayHandle ArrayRangeCompute( const vtkm::cont::UnknownArrayHandle& array, vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}); -#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(T, Storage) \ - VTKM_CONT_EXPORT \ - VTKM_CONT \ - vtkm::cont::ArrayHandle ArrayRangeCompute( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny()) -#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(T, N, Storage) \ - VTKM_CONT_EXPORT \ - VTKM_CONT \ - vtkm::cont::ArrayHandle ArrayRangeCompute( \ - const vtkm::cont::ArrayHandle, Storage>& input, \ - vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny()) - -#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_SCALAR_T(Storage) \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int8, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt8, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int16, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt16, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int32, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt32, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int64, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt64, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Float32, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Float64, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(char, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(signed VTKM_UNUSED_INT_TYPE, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(unsigned VTKM_UNUSED_INT_TYPE, Storage) - -#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(N, Storage) \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int8, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt8, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int16, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt16, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int32, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt32, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int64, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt64, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float32, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(char, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(signed VTKM_UNUSED_INT_TYPE, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(unsigned VTKM_UNUSED_INT_TYPE, N, Storage) - -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_SCALAR_T(vtkm::cont::StorageTagBasic); - -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(2, vtkm::cont::StorageTagBasic); -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(3, vtkm::cont::StorageTagBasic); -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(4, vtkm::cont::StorageTagBasic); - -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(2, vtkm::cont::StorageTagSOA); -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(3, vtkm::cont::StorageTagSOA); -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(4, vtkm::cont::StorageTagSOA); - -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_SCALAR_T(vtkm::cont::StorageTagStride); - -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float32, 3, vtkm::cont::StorageTagXGCCoordinates); -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, 3, vtkm::cont::StorageTagXGCCoordinates); - -#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T -#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC -#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_SCALAR_T -#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC - -VTKM_CONT_EXPORT VTKM_CONT vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle& array, - vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny()); - -// Implementation of cartesian products -template -VTKM_CONT inline vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle, - vtkm::cont::StorageTagCartesianProduct>& input_, - vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny()) +namespace internal { - vtkm::cont::ArrayHandle result; - result.Allocate(3); - - vtkm::cont::ArrayHandle componentRangeArray; - vtkm::Range componentRange; - - vtkm::cont::ArrayHandleCartesianProduct, - vtkm::cont::ArrayHandle, - vtkm::cont::ArrayHandle> - input = input_; - vtkm::cont::ArrayHandle firstArray = input.GetFirstArray(); - componentRangeArray = vtkm::cont::ArrayRangeCompute(firstArray, device); - componentRange = componentRangeArray.ReadPortal().Get(0); - result.WritePortal().Set(0, componentRange); - - vtkm::cont::ArrayHandle secondArray = input.GetSecondArray(); - componentRangeArray = vtkm::cont::ArrayRangeCompute(secondArray, device); - componentRange = componentRangeArray.ReadPortal().Get(0); - result.WritePortal().Set(1, componentRange); - - vtkm::cont::ArrayHandle thirdArray = input.GetThirdArray(); - componentRangeArray = vtkm::cont::ArrayRangeCompute(thirdArray, device); - componentRange = componentRangeArray.ReadPortal().Get(0); - result.WritePortal().Set(2, componentRange); - - return result; -} - -// Implementation of constant arrays -template -VTKM_CONT inline vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle& input, - vtkm::cont::DeviceAdapterId vtkmNotUsed(device) = vtkm::cont::DeviceAdapterTagAny{}) -{ - using Traits = vtkm::VecTraits; - const T value = vtkm::cont::ArrayHandleConstant(input).GetValue(); - vtkm::IdComponent numComponents = Traits::GetNumberOfComponents(value); - vtkm::cont::ArrayHandle result; - result.Allocate(numComponents); - auto portal = result.WritePortal(); - for (vtkm::IdComponent cIndex = 0; cIndex < numComponents; ++cIndex) - { - auto component = Traits::GetComponent(value, cIndex); - portal.Set(cIndex, vtkm::Range(component, component)); - } - return result; -} - -// Implementation of counting arrays -template -VTKM_CONT inline vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle& input, - vtkm::cont::DeviceAdapterId vtkmNotUsed(device) = vtkm::cont::DeviceAdapterTagAny{}) -{ - using Traits = vtkm::VecTraits; - vtkm::cont::ArrayHandle result; - result.Allocate(Traits::NUM_COMPONENTS); - auto portal = result.WritePortal(); - if (portal.GetNumberOfValues() > 0) - { - 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{}); - } - } - return result; -} - -// Implementation of index arrays -VTKM_CONT_EXPORT vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle& input, - vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}); -///@} VTKM_CONT_EXPORT void ThrowArrayRangeComputeFailed(); + +} // namespace internal + +VTKM_DEPRECATED(2.1, "Moved to vtkm::cont::internal.") +inline void ThrowArrayRangeComputeFailed() +{ + internal::ThrowArrayRangeComputeFailed(); +} + } } // namespace vtkm::cont diff --git a/vtkm/cont/ArrayRangeComputeTemplate.h b/vtkm/cont/ArrayRangeComputeTemplate.h index 2e593e1aa..aeab8c3c5 100644 --- a/vtkm/cont/ArrayRangeComputeTemplate.h +++ b/vtkm/cont/ArrayRangeComputeTemplate.h @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -42,8 +43,13 @@ struct ArrayRangeComputeFunctor } }; +} // namespace detail + +namespace internal +{ + template -inline vtkm::cont::ArrayHandle ArrayRangeComputeImpl( +inline vtkm::cont::ArrayHandle ArrayRangeComputeGeneric( const vtkm::cont::ArrayHandle& input, vtkm::cont::DeviceAdapterId device) { @@ -74,7 +80,7 @@ inline vtkm::cont::ArrayHandle ArrayRangeComputeImpl( initial[1] = T(std::numeric_limits::lowest()); const bool rangeComputed = vtkm::cont::TryExecuteOnDevice( - device, detail::ArrayRangeComputeFunctor{}, input, initial, result); + device, vtkm::cont::detail::ArrayRangeComputeFunctor{}, input, initial, result); if (!rangeComputed) { ThrowArrayRangeComputeFailed(); @@ -93,17 +99,38 @@ inline vtkm::cont::ArrayHandle ArrayRangeComputeImpl( return range; } -} // namespace detail +template +struct ArrayRangeComputeImpl +{ + template + vtkm::cont::ArrayHandle operator()(const vtkm::cont::ArrayHandle& input, + vtkm::cont::DeviceAdapterId device) const + { + return vtkm::cont::internal::ArrayRangeComputeGeneric(input, device); + } +}; + +} // namespace internal template -inline vtkm::cont::ArrayHandle ArrayRangeCompute( +inline vtkm::cont::ArrayHandle ArrayRangeComputeTemplate( const ArrayHandleType& input, vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}) { VTKM_IS_ARRAY_HANDLE(ArrayHandleType); - return detail::ArrayRangeComputeImpl(input, device); + return internal::ArrayRangeComputeImpl{}(input, 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); +} + } } // namespace vtkm::cont diff --git a/vtkm/cont/testing/UnitTestArrayRangeCompute.cxx b/vtkm/cont/testing/UnitTestArrayRangeCompute.cxx index a5a2e245c..05f3b81f2 100644 --- a/vtkm/cont/testing/UnitTestArrayRangeCompute.cxx +++ b/vtkm/cont/testing/UnitTestArrayRangeCompute.cxx @@ -65,7 +65,6 @@ template void CheckRange(const vtkm::cont::ArrayHandle& array) { VerifyRange(array, vtkm::cont::ArrayRangeCompute(array)); - VerifyRange(array, vtkm::cont::ArrayRangeCompute(vtkm::cont::UnknownArrayHandle{ array })); } template 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 2971fb492..197f50f69 100644 --- a/vtkm/filter/scalar_topology/worklet/contourtree_augmented/meshtypes/ContourTreeMesh.h +++ b/vtkm/filter/scalar_topology/worklet/contourtree_augmented/meshtypes/ContourTreeMesh.h @@ -576,7 +576,8 @@ template inline void ContourTreeMesh::ComputeMaxNeighbors() { auto neighborCounts = make_ArrayHandleOffsetsToNumComponents(this->NeighborOffsets); - vtkm::cont::ArrayHandle rangeArray = vtkm::cont::ArrayRangeCompute(neighborCounts); + vtkm::cont::ArrayHandle rangeArray = + vtkm::cont::ArrayRangeComputeTemplate(neighborCounts); this->MaxNeighbors = static_cast(rangeArray.ReadPortal().Get(0).Max); } diff --git a/vtkm/filter/vector_analysis/worklet/OrientCellNormals.h b/vtkm/filter/vector_analysis/worklet/OrientCellNormals.h index eb1702392..c76ee9f07 100644 --- a/vtkm/filter/vector_analysis/worklet/OrientCellNormals.h +++ b/vtkm/filter/vector_analysis/worklet/OrientCellNormals.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include