//============================================================================ // 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_ArrayHandleConcatenate_h #define vtk_m_cont_ArrayHandleConcatenate_h #include namespace vtkm { namespace cont { namespace internal { template class VTKM_ALWAYS_EXPORT ArrayPortalConcatenate { using WritableP1 = vtkm::internal::PortalSupportsSets; using WritableP2 = vtkm::internal::PortalSupportsSets; using Writable = std::integral_constant; public: using ValueType = typename PortalType1::ValueType; VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT ArrayPortalConcatenate() : portal1() , portal2() { } VTKM_EXEC_CONT ArrayPortalConcatenate(const PortalType1& p1, const PortalType2& p2) : portal1(p1) , portal2(p2) { } // Copy constructor template VTKM_EXEC_CONT ArrayPortalConcatenate(const ArrayPortalConcatenate& src) : portal1(src.GetPortal1()) , portal2(src.GetPortal2()) { } VTKM_EXEC_CONT vtkm::Id GetNumberOfValues() const { return this->portal1.GetNumberOfValues() + this->portal2.GetNumberOfValues(); } VTKM_EXEC_CONT ValueType Get(vtkm::Id index) const { if (index < this->portal1.GetNumberOfValues()) { return this->portal1.Get(index); } else { return this->portal2.Get(index - this->portal1.GetNumberOfValues()); } } template ::type> VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const { if (index < this->portal1.GetNumberOfValues()) { this->portal1.Set(index, value); } else { this->portal2.Set(index - this->portal1.GetNumberOfValues(), value); } } VTKM_EXEC_CONT const PortalType1& GetPortal1() const { return this->portal1; } VTKM_EXEC_CONT const PortalType2& GetPortal2() const { return this->portal2; } private: PortalType1 portal1; PortalType2 portal2; }; // class ArrayPortalConcatenate } // namespace internal template class StorageTagConcatenate { }; namespace internal { template class Storage> { public: using ValueType = typename ArrayHandleType1::ValueType; using PortalType = ArrayPortalConcatenate; using PortalConstType = ArrayPortalConcatenate; VTKM_CONT Storage() : valid(false) { } VTKM_CONT Storage(const ArrayHandleType1& a1, const ArrayHandleType2& a2) : array1(a1) , array2(a2) , valid(true){}; VTKM_CONT PortalConstType GetPortalConst() const { VTKM_ASSERT(this->valid); return PortalConstType(this->array1.GetPortalConstControl(), this->array2.GetPortalConstControl()); } VTKM_CONT PortalType GetPortal() { VTKM_ASSERT(this->valid); return PortalType(this->array1.GetPortalControl(), this->array2.GetPortalControl()); } VTKM_CONT vtkm::Id GetNumberOfValues() const { VTKM_ASSERT(this->valid); return this->array1.GetNumberOfValues() + this->array2.GetNumberOfValues(); } VTKM_CONT void Allocate(vtkm::Id vtkmNotUsed(numberOfValues)) { throw vtkm::cont::ErrorInternal("ArrayHandleConcatenate should not be allocated explicitly. "); } VTKM_CONT void Shrink(vtkm::Id numberOfValues) { VTKM_ASSERT(this->valid); if (numberOfValues < this->array1.GetNumberOfValues()) { this->array1.Shrink(numberOfValues); this->array2.Shrink(0); } else this->array2.Shrink(numberOfValues - this->array1.GetNumberOfValues()); } VTKM_CONT void ReleaseResources() { VTKM_ASSERT(this->valid); this->array1.ReleaseResources(); this->array2.ReleaseResources(); } VTKM_CONT const ArrayHandleType1& GetArray1() const { VTKM_ASSERT(this->valid); return this->array1; } VTKM_CONT const ArrayHandleType2& GetArray2() const { VTKM_ASSERT(this->valid); return this->array2; } private: ArrayHandleType1 array1; ArrayHandleType2 array2; bool valid; }; // class Storage template class ArrayTransfer, Device> { public: using ValueType = typename ArrayHandleType1::ValueType; private: using StorageTag = StorageTagConcatenate; using StorageType = vtkm::cont::internal::Storage; public: using PortalControl = typename StorageType::PortalType; using PortalConstControl = typename StorageType::PortalConstType; using PortalExecution = ArrayPortalConcatenate::Portal, typename ArrayHandleType2::template ExecutionTypes::Portal>; using PortalConstExecution = ArrayPortalConcatenate::PortalConst, typename ArrayHandleType2::template ExecutionTypes::PortalConst>; VTKM_CONT ArrayTransfer(StorageType* storage) : array1(storage->GetArray1()) , array2(storage->GetArray2()) { } VTKM_CONT vtkm::Id GetNumberOfValues() const { return this->array1.GetNumberOfValues() + this->array2.GetNumberOfValues(); } VTKM_CONT PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData)) { return PortalConstExecution(this->array1.PrepareForInput(Device()), this->array2.PrepareForInput(Device())); } VTKM_CONT PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData)) { return PortalExecution(this->array1.PrepareForInPlace(Device()), this->array2.PrepareForInPlace(Device())); } VTKM_CONT PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues)) { throw vtkm::cont::ErrorInternal("ArrayHandleConcatenate is derived and read-only. "); } VTKM_CONT void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const { // not need to implement } VTKM_CONT void Shrink(vtkm::Id numberOfValues) { if (numberOfValues < this->array1.GetNumberOfValues()) { this->array1.Shrink(numberOfValues); this->array2.Shrink(0); } else this->array2.Shrink(numberOfValues - this->array1.GetNumberOfValues()); } VTKM_CONT void ReleaseResources() { this->array1.ReleaseResourcesExecution(); this->array2.ReleaseResourcesExecution(); } private: ArrayHandleType1 array1; ArrayHandleType2 array2; }; } } } // namespace vtkm::cont::internal namespace vtkm { namespace cont { template class ArrayHandleConcatenate : public vtkm::cont::ArrayHandle> { public: VTKM_ARRAY_HANDLE_SUBCLASS( ArrayHandleConcatenate, (ArrayHandleConcatenate), (vtkm::cont::ArrayHandle>)); protected: using StorageType = vtkm::cont::internal::Storage; public: VTKM_CONT ArrayHandleConcatenate(const ArrayHandleType1& array1, const ArrayHandleType2& array2) : Superclass(StorageType(array1, array2)) { } }; template VTKM_CONT ArrayHandleConcatenate make_ArrayHandleConcatenate( const ArrayHandleType1& array1, const ArrayHandleType2& array2) { return ArrayHandleConcatenate(array1, array2); } } } // 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_Concatenate<" + SerializableTypeString::Get() + "," + SerializableTypeString::Get() + ">"; return name; } }; template struct SerializableTypeString< vtkm::cont::ArrayHandle>> : SerializableTypeString> { }; } } // vtkm::cont namespace mangled_diy_namespace { template struct Serialization> { private: using Type = vtkm::cont::ArrayHandleConcatenate; using BaseType = vtkm::cont::ArrayHandle; public: static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj) { auto storage = obj.GetStorage(); vtkmdiy::save(bb, storage.GetArray1()); vtkmdiy::save(bb, storage.GetArray2()); } static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj) { AH1 array1; AH2 array2; vtkmdiy::load(bb, array1); vtkmdiy::load(bb, array2); obj = vtkm::cont::make_ArrayHandleConcatenate(array1, array2); } }; template struct Serialization< vtkm::cont::ArrayHandle>> : Serialization> { }; } // diy /// @endcond SERIALIZATION #endif //vtk_m_cont_ArrayHandleConcatenate_h