//============================================================================ // 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_ArrayRangeComputeTemplate_h #define vtk_m_cont_ArrayRangeComputeTemplate_h #include #include #include #include #ifndef VTKM_NO_DEPRECATED_VIRTUAL #include #endif #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; } }; template inline vtkm::cont::ArrayHandle ArrayRangeComputeImpl( const vtkm::cont::ArrayHandle& input, 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); if (input.GetNumberOfValues() < 1) { auto portal = range.WritePortal(); for (vtkm::IdComponent i = 0; i < VecTraits::NUM_COMPONENTS; ++i) { portal.Set(i, 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()); const bool rangeComputed = vtkm::cont::TryExecuteOnDevice( device, detail::ArrayRangeComputeFunctor{}, input, initial, result); if (!rangeComputed) { ThrowArrayRangeComputeFailed(); } else { 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))); } } } return range; } } // namespace detail #ifndef VTKM_NO_DEPRECATED_VIRTUAL VTKM_DEPRECATED_SUPPRESS_BEGIN VTKM_CONT inline vtkm::cont::ArrayHandle ArrayRangeCompute( const vtkm::cont::ArrayHandleVirtual& input, vtkm::cont::DeviceAdapterId device) { using UniformHandleType = ArrayHandleUniformPointCoordinates; using RectilinearHandleType = vtkm::cont::ArrayHandleCartesianProduct, vtkm::cont::ArrayHandle, vtkm::cont::ArrayHandle>; if (input.IsType()) { using T = typename UniformHandleType::ValueType; using S = typename UniformHandleType::StorageTag; const vtkm::cont::internal::detail::StorageVirtual* storage = input.GetStorage().GetStorageVirtual(); const auto* castStorage = storage->Cast>(); return ArrayRangeCompute(castStorage->GetHandle(), device); } else if (input.IsType()) { using T = typename RectilinearHandleType::ValueType; using S = typename RectilinearHandleType::StorageTag; const vtkm::cont::internal::detail::StorageVirtual* storage = input.GetStorage().GetStorageVirtual(); const auto* castStorage = storage->Cast>(); return ArrayRangeCompute(castStorage->GetHandle(), device); } else { return detail::ArrayRangeComputeImpl(input, device); } } VTKM_DEPRECATED_SUPPRESS_END #endif //VTKM_NO_DEPRECATED_VIRTUAL template inline vtkm::cont::ArrayHandle ArrayRangeCompute( const ArrayHandleType& input, vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}) { VTKM_IS_ARRAY_HANDLE(ArrayHandleType); return detail::ArrayRangeComputeImpl(input, device); } } } // namespace vtkm::cont #endif //vtk_m_cont_ArrayRangeComputeTemplate_h