//============================================================================ // 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_ArrayHandleView_h #define vtk_m_cont_ArrayHandleView_h #include #include #include #include #include namespace vtkm { namespace internal { struct ViewIndices { vtkm::Id StartIndex = 0; vtkm::Id NumberOfValues = 0; ViewIndices() = default; ViewIndices(vtkm::Id start, vtkm::Id numValues) : StartIndex(start) , NumberOfValues(numValues) { } }; template class ArrayPortalView { using Writable = vtkm::internal::PortalSupportsSets; public: using ValueType = typename TargetPortalType::ValueType; VTKM_EXEC_CONT ArrayPortalView() {} VTKM_EXEC_CONT ArrayPortalView(const TargetPortalType& targetPortal, ViewIndices indices) : TargetPortal(targetPortal) , Indices(indices) { } template VTKM_EXEC_CONT ArrayPortalView(const ArrayPortalView& otherPortal) : TargetPortal(otherPortal.GetTargetPortal()) , Indices(otherPortal.GetStartIndex(), otherPortal.GetNumberOfValues()) { } VTKM_EXEC_CONT vtkm::Id GetNumberOfValues() const { return this->Indices.NumberOfValues; } VTKM_EXEC_CONT ValueType Get(vtkm::Id index) const { return this->TargetPortal.Get(index + this->GetStartIndex()); } template ::type> VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const { this->TargetPortal.Set(index + this->GetStartIndex(), value); } VTKM_EXEC_CONT const TargetPortalType& GetTargetPortal() const { return this->TargetPortal; } VTKM_EXEC_CONT vtkm::Id GetStartIndex() const { return this->Indices.StartIndex; } private: TargetPortalType TargetPortal; ViewIndices Indices; }; } // namespace internal namespace cont { template struct VTKM_ALWAYS_EXPORT StorageTagView { }; namespace internal { namespace detail { template struct ViewTypeArgImpl; template struct ViewTypeArgImpl { using StorageTag = Storage; using ArrayHandle = vtkm::cont::ArrayHandle; }; template struct ViewTypeArgImpl { VTKM_STATIC_ASSERT_MSG((std::is_same::value), "Used array with wrong type in ArrayHandleView."); using StorageTag VTKM_DEPRECATED(1.6, "Use storage tag instead of array handle in StorageTagView.") = typename Array::StorageTag; using ArrayHandle VTKM_DEPRECATED(1.6, "Use storage tag instead of array handle in StorageTagView.") = vtkm::cont::ArrayHandle; }; template struct ViewTypeArg : ViewTypeArgImpl::type::value> { }; } // namespace detail template class Storage> { using ArrayHandleType = typename detail::ViewTypeArg::ArrayHandle; using SourceStorage = Storage; public: VTKM_STORAGE_NO_RESIZE; using ReadPortalType = vtkm::internal::ArrayPortalView; using WritePortalType = vtkm::internal::ArrayPortalView; VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers() { return SourceStorage::GetNumberOfBuffers() + 1; } VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers) { return buffers[0].GetMetaData().NumberOfValues; } VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) { vtkm::internal::ViewIndices indices = buffers[0].GetMetaData(); return ReadPortalType(SourceStorage::CreateReadPortal(buffers + 1, device, token), indices); } VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) { vtkm::internal::ViewIndices indices = buffers[0].GetMetaData(); return WritePortalType(SourceStorage::CreateWritePortal(buffers + 1, device, token), indices); } VTKM_CONT static std::vector CreateBuffers(vtkm::Id startIndex, vtkm::Id numValues, const ArrayHandleType& array) { return vtkm::cont::internal::CreateBuffers(vtkm::internal::ViewIndices(startIndex, numValues), array); } VTKM_CONT static ArrayHandleType GetSourceArray(const vtkm::cont::internal::Buffer* buffers) { return ArrayHandleType(buffers + 1); } VTKM_CONT static vtkm::Id GetStartIndex(const vtkm::cont::internal::Buffer* buffers) { return buffers[0].GetMetaData().StartIndex; } }; } // namespace internal template class ArrayHandleView : public vtkm::cont::ArrayHandle> { VTKM_IS_ARRAY_HANDLE(ArrayHandleType); public: VTKM_ARRAY_HANDLE_SUBCLASS( ArrayHandleView, (ArrayHandleView), (vtkm::cont::ArrayHandle>)); private: using StorageType = vtkm::cont::internal::Storage; public: VTKM_CONT ArrayHandleView(const ArrayHandleType& array, vtkm::Id startIndex, vtkm::Id numValues) : Superclass(StorageType::CreateBuffers(startIndex, numValues, array)) { } VTKM_CONT ArrayHandleType GetSourceArray() const { return this->GetStorage().GetSourceArray(this->GetBuffers()); } VTKM_CONT vtkm::Id GetStartIndex() const { return this->GetStorage().GetStartIndex(this->GetBuffers()); } }; template ArrayHandleView make_ArrayHandleView(const ArrayHandleType& array, vtkm::Id startIndex, vtkm::Id numValues) { VTKM_IS_ARRAY_HANDLE(ArrayHandleType); return ArrayHandleView(array, startIndex, numValues); } namespace internal { template struct ArrayExtractComponentImpl> { template using StrideArrayType = vtkm::cont::ArrayHandleStride::BaseComponentType>; template StrideArrayType operator()( const vtkm::cont::ArrayHandle>& src, vtkm::IdComponent componentIndex, vtkm::CopyFlag allowCopy) const { vtkm::cont::ArrayHandleView> srcArray(src); StrideArrayType subArray = ArrayExtractComponentImpl{}(srcArray.GetSourceArray(), componentIndex, allowCopy); // Narrow the array by adjusting the size and offset. return StrideArrayType(subArray.GetBasicArray(), srcArray.GetNumberOfValues(), subArray.GetStride(), subArray.GetOffset() + (subArray.GetStride() * srcArray.GetStartIndex()), subArray.GetModulo(), subArray.GetDivisor()); } }; } // namespace internal } } // namespace vtkm::cont #endif //vtk_m_cont_ArrayHandleView_h