//============================================================================ // 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 { template class Storage> { using SourceStorage = Storage; public: using ArrayHandleType = vtkm::cont::ArrayHandle; using ReadPortalType = ArrayPortalReverse; using WritePortalType = ArrayPortalReverse; VTKM_CONT static std::vector CreateBuffers() { return SourceStorage::CreateBuffers(); } VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, const std::vector& buffers, vtkm::CopyFlag preserve, vtkm::cont::Token& token) { SourceStorage::ResizeBuffers(numValues, buffers, preserve, token); } VTKM_CONT static vtkm::IdComponent GetNumberOfComponentsFlat( const std::vector& buffers) { return SourceStorage::GetNumberOfComponentsFlat(buffers); } VTKM_CONT static vtkm::Id GetNumberOfValues( const std::vector& buffers) { return SourceStorage::GetNumberOfValues(buffers); } VTKM_CONT static void Fill(const std::vector& buffers, const T& fillValue, vtkm::Id startIndex, vtkm::Id endIndex, vtkm::cont::Token& token) { vtkm::Id numValues = GetNumberOfValues(buffers); SourceStorage::Fill(buffers, fillValue, numValues - endIndex, numValues - startIndex, token); } VTKM_CONT static ReadPortalType CreateReadPortal( const std::vector& buffers, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) { return ReadPortalType(SourceStorage::CreateReadPortal(buffers, device, token)); } VTKM_CONT static WritePortalType CreateWritePortal( const std::vector& buffers, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) { return WritePortalType(SourceStorage::CreateWritePortal(buffers, device, token)); } }; // class storage } // 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>)); ArrayHandleReverse(const ArrayHandleType& handle) : Superclass(handle.GetBuffers()) { } VTKM_CONT ArrayHandleType GetSourceArray() const { return vtkm::cont::ArrayHandle( this->GetBuffers()); } }; /// make_ArrayHandleReverse is convenience function to generate an /// ArrayHandleReverse. /// template VTKM_CONT ArrayHandleReverse make_ArrayHandleReverse(const HandleType& handle) { return ArrayHandleReverse(handle); } namespace internal { // Superclass will inherit the ArrayExtractComponentImplInefficient property if // the sub-storage is inefficient (thus making everything inefficient). template struct ArrayExtractComponentImpl> : vtkm::cont::internal::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::ArrayHandleReverse> srcArray(src); StrideArrayType subArray = ArrayExtractComponentImpl{}(srcArray.GetSourceArray(), componentIndex, allowCopy); // Reverse the array by starting at the end and striding backward return StrideArrayType(subArray.GetBasicArray(), srcArray.GetNumberOfValues(), -subArray.GetStride(), subArray.GetOffset() + (subArray.GetStride() * (subArray.GetNumberOfValues() - 1)), subArray.GetModulo(), subArray.GetDivisor()); } }; } // namespace internal } } // 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 Type& obj) { vtkmdiy::save(bb, obj.GetSourceArray()); } 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