// // Copyright © 2017 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once #include "TensorFwd.hpp" #include "Exceptions.hpp" #include "Types.hpp" #include #include #include namespace armnn { class TensorShape { public: /// Empty (invalid) constructor. TensorShape(); TensorShape(unsigned int numDimensions); TensorShape(unsigned int numDimensions, const unsigned int* dimensionSizes); TensorShape(std::initializer_list dimensionSizeList); TensorShape(const TensorShape& other); TensorShape& operator=(const TensorShape& other); unsigned int operator[](unsigned int i) const; unsigned int& operator[](unsigned int i); bool operator==(const TensorShape& other) const; bool operator!=(const TensorShape& other) const; unsigned int GetNumDimensions() const { return m_NumDimensions; } unsigned int GetNumElements() const; private: std::array m_Dimensions; unsigned int m_NumDimensions; void CheckDimensionIndex(unsigned int i) const; }; class TensorInfo { public: /// Empty (invalid) constructor. TensorInfo(); TensorInfo(const TensorShape& shape, DataType dataType, float quantizationScale = 0.0f, int32_t quantizationOffset = 0); TensorInfo(unsigned int numDimensions, const unsigned int* dimensionSizes, DataType dataType, float quantizationScale = 0.0f, int32_t quantizationOffset = 0); TensorInfo(const TensorInfo& other); TensorInfo& operator=(const TensorInfo& other); bool operator==(const TensorInfo& other) const; bool operator!=(const TensorInfo& other) const; const TensorShape& GetShape() const { return m_Shape; } TensorShape& GetShape() { return m_Shape; } void SetShape(const TensorShape& newShape) { m_Shape = newShape; } unsigned int GetNumDimensions() const { return m_Shape.GetNumDimensions(); } unsigned int GetNumElements() const { return m_Shape.GetNumElements(); } DataType GetDataType() const { return m_DataType; } void SetDataType(DataType type) { m_DataType = type; } float GetQuantizationScale() const { return m_Quantization.m_Scale; } int32_t GetQuantizationOffset() const { return m_Quantization.m_Offset; } void SetQuantizationScale(float scale) { m_Quantization.m_Scale = scale; } void SetQuantizationOffset(int32_t offset) { m_Quantization.m_Offset = offset; } bool IsQuantized() const { return m_DataType == DataType::QuantisedAsymm8 || m_DataType == DataType::QuantisedSymm16; } /// Check that the types are the same and, if quantize, that the quantization parameters are the same. bool IsTypeSpaceMatch(const TensorInfo& other) const; unsigned int GetNumBytes() const; private: TensorShape m_Shape; DataType m_DataType; /// Scale and offset values are used for quantization. struct Quantization { Quantization() : m_Scale(0.f), m_Offset(0) {} bool operator==(const Quantization& o) const {return ((m_Scale == o.m_Scale) && (m_Offset == o.m_Offset));} float m_Scale; int32_t m_Offset; } m_Quantization; }; using BindingPointInfo = std::pair; template class BaseTensor { public: /// Empty (invalid) constructor. BaseTensor(); /// Constructor from a raw memory pointer. /// @param memoryArea - Region of CPU-addressable memory where tensor data will be stored. Must be valid while /// workloads are on the fly. Tensor instances do not claim ownership of referenced memory regions, that is, /// no attempt will be made by ArmNN to free these memory regions automatically. BaseTensor(const TensorInfo& info, MemoryType memoryArea); /// Tensors are copyable. BaseTensor(const BaseTensor& other); /// Tensors are copyable. BaseTensor& operator=(const BaseTensor&); const TensorInfo& GetInfo() const { return m_Info; } TensorInfo& GetInfo() { return m_Info; } const TensorShape& GetShape() const { return m_Info.GetShape(); } TensorShape& GetShape() { return m_Info.GetShape(); } DataType GetDataType() const { return m_Info.GetDataType(); } unsigned int GetNumDimensions() const { return m_Info.GetNumDimensions(); } unsigned int GetNumBytes() const { return m_Info.GetNumBytes(); } unsigned int GetNumElements() const { return m_Info.GetNumElements(); } MemoryType GetMemoryArea() const { return m_MemoryArea; } protected: // Protected destructor to stop users from making these // (could still new one on the heap and then leak it...) ~BaseTensor() {} MemoryType m_MemoryArea; private: TensorInfo m_Info; }; /// A tensor defined by a TensorInfo (shape and data type) and a mutable backing store. class Tensor : public BaseTensor { public: /// Brings in the constructors and assignment operator. using BaseTensor::BaseTensor; }; /// A tensor defined by a TensorInfo (shape and data type) and an immutable backing store. class ConstTensor : public BaseTensor { public: /// Brings in the constructors and assignment operator. using BaseTensor::BaseTensor; ConstTensor() : BaseTensor() {} // This needs to be redefined explicitly?? /// Can be implicitly constructed from non-const Tensor. ConstTensor(const Tensor& other) : BaseTensor(other.GetInfo(), other.GetMemoryArea()) {} /// Constructor from a backing container. /// @param container - An stl-like container type which implements data() and size() methods. /// Presence of data() and size() is a strong indicator of the continuous memory layout of the container, /// which is a requirement for Tensor data. Tensor instances do not claim ownership of referenced memory regions, /// that is, no attempt will be made by ArmNN to free these memory regions automatically. template < template class ContainerType, typename T, typename...ContainerArgs > ConstTensor(const TensorInfo& info, const ContainerType& container) : BaseTensor(info, container.data()) { if (container.size() * sizeof(T) != info.GetNumBytes()) { throw InvalidArgumentException("Container size is not correct"); } } }; using InputTensors = std::vector>; using OutputTensors = std::vector>; } // namespace armnn