//============================================================================ // 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 #include #include #include #include #include namespace { using AllScalars = vtkm::TypeListBaseC; template struct VecTransform { template using type = vtkm::Vec; }; template using AllVecOfSize = vtkm::ListTransform::template type>; 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); } // 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; } } }; 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; } } // 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) { // First, try fast-paths of precompiled array types common(ish) in fields. try { if (array.IsStorageType()) { 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); } } catch (vtkm::cont::ErrorBadType&) { // If a cast/call failed, try falling back to a more general implementation. } vtkm::cont::ArrayHandle ranges; bool success = false; vtkm::ListForEach(ComputeRangeFunctor{}, AllScalars{}, array, device, ranges, success); return ranges; } } } // namespace vtkm::cont