//============================================================================ // 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_ArrayHandleReverse_h #define vtk_m_cont_ArrayHandleReverse_h #include #include #include #include namespace vtkm { namespace cont { namespace internal { template class VTKM_ALWAYS_EXPORT ArrayPortalReverse { using Writable = vtkm::internal::PortalSupportsSets; public: using ValueType = typename PortalType::ValueType; VTKM_EXEC_CONT ArrayPortalReverse() : portal() { } VTKM_EXEC_CONT ArrayPortalReverse(const PortalType& p) : portal(p) { } template VTKM_EXEC_CONT ArrayPortalReverse(const ArrayPortalReverse& src) : portal(src.GetPortal()) { } VTKM_EXEC_CONT vtkm::Id GetNumberOfValues() const { return this->portal.GetNumberOfValues(); } VTKM_EXEC_CONT ValueType Get(vtkm::Id index) const { return this->portal.Get(portal.GetNumberOfValues() - index - 1); } template ::type> VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const { this->portal.Set(portal.GetNumberOfValues() - index - 1, value); } private: PortalType portal; }; } template class VTKM_ALWAYS_EXPORT StorageTagReverse { }; namespace internal { namespace detail { template struct ReverseTypeArgImpl; template struct ReverseTypeArgImpl { using StorageTag = Storage; using ArrayHandle = vtkm::cont::ArrayHandle; }; template struct ReverseTypeArgImpl { VTKM_STATIC_ASSERT_MSG((std::is_same::value), "Used array with wrong type in ArrayHandleReverse."); using StorageTag VTKM_DEPRECATED( 1.6, "Use storage tag instead of array handle in StorageTagReverse.") = typename Array::StorageTag; using ArrayHandle VTKM_DEPRECATED( 1.6, "Use storage tag instead of array handle in StorageTagReverse.") = vtkm::cont::ArrayHandle; }; template struct ReverseTypeArg : ReverseTypeArgImpl::type::value> { }; } // namespace detail template class Storage> { public: using ValueType = T; using ArrayHandleType = typename detail::ReverseTypeArg::ArrayHandle; using PortalType = ArrayPortalReverse; using PortalConstType = ArrayPortalReverse; VTKM_CONT Storage() : Array() { } VTKM_CONT Storage(const ArrayHandleType& a) : Array(a) { } VTKM_CONT PortalConstType GetPortalConst() const { return PortalConstType(this->Array.ReadPortal()); } VTKM_CONT PortalType GetPortal() { return PortalType(this->Array.WritePortal()); } VTKM_CONT vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); } VTKM_CONT void Allocate(vtkm::Id numberOfValues) { return this->Array.Allocate(numberOfValues); } VTKM_CONT void Shrink(vtkm::Id numberOfValues) { return this->Array.Shrink(numberOfValues); } VTKM_CONT void ReleaseResources() { // This request is ignored since it is asking to release the resources // of the delegate array, which may be used elsewhere. Should the behavior // be different? } VTKM_CONT const ArrayHandleType& GetArray() const { return this->Array; } private: ArrayHandleType Array; }; // class storage template class ArrayTransfer, Device> { private: using StorageTag = StorageTagReverse; using StorageType = vtkm::cont::internal::Storage; using ArrayHandleType = typename detail::ReverseTypeArg::ArrayHandle; public: using ValueType = T; using PortalControl = typename StorageType::PortalType; using PortalConstControl = typename StorageType::PortalConstType; using PortalExecution = ArrayPortalReverse::Portal>; using PortalConstExecution = ArrayPortalReverse::PortalConst>; VTKM_CONT ArrayTransfer(StorageType* storage) : Array(storage->GetArray()) { } VTKM_CONT vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); } VTKM_CONT PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token) { return PortalConstExecution(this->Array.PrepareForInput(Device(), token)); } VTKM_CONT PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token& token) { return PortalExecution(this->Array.PrepareForInPlace(Device(), token)); } VTKM_CONT PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token) { return PortalExecution(this->Array.PrepareForOutput(numberOfValues, Device(), token)); } VTKM_CONT void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const { // not need to implement } VTKM_CONT void Shrink(vtkm::Id numberOfValues) { this->Array.Shrink(numberOfValues); } VTKM_CONT void ReleaseResources() { this->Array.ReleaseResourcesExecution(); } private: ArrayHandleType Array; }; } // namespace internal /// \brief Reverse the order of an array, on demand. /// /// ArrayHandleReverse is a specialization of ArrayHandle. Given an ArrayHandle, /// it creates a new handle that returns the elements of the array in reverse /// order (i.e. from end to beginning). /// template class ArrayHandleReverse : public vtkm::cont::ArrayHandle> { public: VTKM_ARRAY_HANDLE_SUBCLASS( ArrayHandleReverse, (ArrayHandleReverse), (vtkm::cont::ArrayHandle>)); public: ArrayHandleReverse(const ArrayHandleType& handle) : Superclass(handle) { } }; /// make_ArrayHandleReverse is convenience function to generate an /// ArrayHandleReverse. /// template VTKM_CONT ArrayHandleReverse make_ArrayHandleReverse(const HandleType& handle) { return ArrayHandleReverse(handle); } } } // namespace vtkm::cont //============================================================================= // Specializations of serialization related classes /// @cond SERIALIZATION namespace vtkm { namespace cont { template struct SerializableTypeString> { static VTKM_CONT const std::string& Get() { static std::string name = "AH_Reverse<" + SerializableTypeString::Get() + ">"; return name; } }; template struct SerializableTypeString>> : SerializableTypeString>> { }; } } // vtkm::cont namespace mangled_diy_namespace { template struct Serialization> { private: using Type = vtkm::cont::ArrayHandleReverse; using BaseType = vtkm::cont::ArrayHandle; public: static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj) { vtkmdiy::save(bb, obj.GetStorage().GetArray()); } static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj) { AH array; vtkmdiy::load(bb, array); obj = vtkm::cont::make_ArrayHandleReverse(array); } }; template struct Serialization>> : Serialization>> { }; } // diy /// @endcond SERIALIZATION #endif // vtk_m_cont_ArrayHandleReverse_h