diff options
Diffstat (limited to 'src/armnn/Tensor.cpp')
-rw-r--r-- | src/armnn/Tensor.cpp | 258 |
1 files changed, 232 insertions, 26 deletions
diff --git a/src/armnn/Tensor.cpp b/src/armnn/Tensor.cpp index 7cb2f0ea13..6ad46c59c9 100644 --- a/src/armnn/Tensor.cpp +++ b/src/armnn/Tensor.cpp @@ -12,6 +12,8 @@ #include <boost/numeric/conversion/cast.hpp> +#include <iostream> + #include <sstream> namespace armnn @@ -22,81 +24,147 @@ namespace armnn // --- TensorShape::TensorShape() - : m_NumDimensions(0) + : m_NumDimensions(0), m_Dimensionality(Dimensionality::Specified) { } -TensorShape::TensorShape(unsigned int numDimensions) - : m_NumDimensions(numDimensions) +TensorShape::TensorShape(unsigned int numDimensions, bool initDimensionsSpecificity) + : m_NumDimensions(numDimensions), m_Dimensionality(Dimensionality::Specified) { - if (numDimensions < 1) - { - throw InvalidArgumentException("Tensor numDimensions must be greater than 0"); - } - - if (numDimensions > MaxNumOfTensorDimensions) - { - throw InvalidArgumentException("Tensor numDimensions must be less than or equal to MaxNumOfTensorDimensions"); - } + CheckValidNumDimensions(numDimensions); std::fill(m_Dimensions.begin(), m_Dimensions.begin() + m_NumDimensions, 0); + std::fill(m_DimensionsSpecificity.begin(), m_DimensionsSpecificity.begin() + m_NumDimensions, + initDimensionsSpecificity); } TensorShape::TensorShape(const unsigned int numDimensions, const unsigned int* const dimensionSizes) - : m_NumDimensions(numDimensions) + : m_NumDimensions(numDimensions), m_Dimensionality(Dimensionality::Specified) { - if (numDimensions < 1) - { - throw InvalidArgumentException("Tensor numDimensions must be greater than 0"); - } + CheckValidNumDimensions(numDimensions); - if (numDimensions > MaxNumOfTensorDimensions) + if (dimensionSizes == nullptr) { - throw InvalidArgumentException("Tensor numDimensions must be less than or equal to MaxNumOfTensorDimensions"); + throw InvalidArgumentException("Tensor dimensionSizes must not be NULL"); } + std::copy(dimensionSizes, dimensionSizes + numDimensions, m_Dimensions.begin()); + std::fill(m_DimensionsSpecificity.begin(), m_DimensionsSpecificity.begin() + m_NumDimensions, true); +} + +TensorShape::TensorShape(std::initializer_list<unsigned int> dimensionSizeList) + : TensorShape(boost::numeric_cast<unsigned int>(dimensionSizeList.size()), dimensionSizeList.begin()) +{ +} + +TensorShape::TensorShape(unsigned int numDimensions, + const unsigned int* const dimensionSizes, + const bool* const dimensionsSpecificity) + : m_NumDimensions(numDimensions), m_Dimensionality(Dimensionality::Specified) +{ + CheckValidNumDimensions(numDimensions); + if (dimensionSizes == nullptr) { throw InvalidArgumentException("Tensor dimensionSizes must not be NULL"); } + if (dimensionsSpecificity == nullptr) + { + throw InvalidArgumentException("Tensor dimensionsSpecificity must not be NULL"); + } + std::copy(dimensionSizes, dimensionSizes + numDimensions, m_Dimensions.begin()); + std::copy(dimensionsSpecificity, dimensionsSpecificity + numDimensions, m_DimensionsSpecificity.begin()); } -TensorShape::TensorShape(std::initializer_list<unsigned int> dimensionSizeList) - : TensorShape(boost::numeric_cast<unsigned int>(dimensionSizeList.size()), dimensionSizeList.begin()) +TensorShape::TensorShape(std::initializer_list<unsigned int> dimensionSizeList, + std::initializer_list<bool> dimensionsSpecificityList) { + auto numDimensions = static_cast<unsigned int>(dimensionSizeList.size()); + if (dimensionsSpecificityList.size() != numDimensions) + { + throw InvalidArgumentException("Tensors dimensionSizeList and dimensionsSpecificityList must be same size"); + } + + *this = TensorShape(numDimensions, dimensionSizeList.begin(), dimensionsSpecificityList.begin()); +} + +TensorShape::TensorShape(Dimensionality dimensionality) +: m_Dimensionality(dimensionality) +{ + switch (dimensionality) + { + case Dimensionality::Specified: + throw InvalidArgumentException("Use other constructor to specify the rest of the values, this one is only " + "for tensors that have an unknown number of dimensions or that are scalar"); + break; + case Dimensionality::NotSpecified: + m_NumDimensions = 0; + m_Dimensions = {0}; + m_DimensionsSpecificity = {false}; + break; + case Dimensionality::Scalar: + m_NumDimensions = 1; + m_Dimensions = {1}; + m_DimensionsSpecificity = {true}; + break; + default: + throw InvalidArgumentException("Invalid Dimensionality value"); + } } TensorShape::TensorShape(const TensorShape& other) - : m_NumDimensions(other.m_NumDimensions) + : m_NumDimensions(other.m_NumDimensions), m_Dimensionality(other.m_Dimensionality) { std::copy(other.m_Dimensions.cbegin(), other.m_Dimensions.cbegin() + other.m_NumDimensions, m_Dimensions.begin()); + std::copy(other.m_DimensionsSpecificity.cbegin(), other.m_DimensionsSpecificity.cbegin() + other.m_NumDimensions, + m_DimensionsSpecificity.begin()); } TensorShape& TensorShape::operator =(const TensorShape& other) { m_NumDimensions = other.m_NumDimensions; + m_Dimensionality = other.m_Dimensionality; std::copy(other.m_Dimensions.cbegin(), other.m_Dimensions.cbegin() + other.m_NumDimensions, m_Dimensions.begin()); + std::copy(other.m_DimensionsSpecificity.cbegin(), other.m_DimensionsSpecificity.cbegin() + other.m_NumDimensions, + m_DimensionsSpecificity.begin()); return *this; } +// read unsigned int TensorShape::operator[](unsigned int i) const { + CheckUnspecifiedNumDimensions(); CheckDimensionIndex(i); + CheckDimensionSpecified(i); + return m_Dimensions.at(i); } +// read and write unsigned int& TensorShape::operator[](unsigned int i) { + if (Dimensionality::Scalar == m_Dimensionality) + { + std::stringstream errorMessage; + errorMessage << "TensorShape with Dimensionality::Scalar must be const to use operator[]"; + throw InvalidArgumentException(errorMessage.str(), CHECK_LOCATION()); + } + CheckUnspecifiedNumDimensions(); CheckDimensionIndex(i); + CheckDimensionSpecified(i); + return m_Dimensions.at(i); } bool TensorShape::operator==(const TensorShape& other) const { return ((m_NumDimensions == other.m_NumDimensions) && - std::equal(m_Dimensions.cbegin(), m_Dimensions.cbegin() + m_NumDimensions, other.m_Dimensions.cbegin())); + (m_Dimensionality == other.m_Dimensionality) && + std::equal(m_Dimensions.cbegin(), m_Dimensions.cbegin() + m_NumDimensions, other.m_Dimensions.cbegin()) && + std::equal(m_DimensionsSpecificity.cbegin(), m_DimensionsSpecificity.cbegin() + m_NumDimensions, + other.m_DimensionsSpecificity.cbegin())); } bool TensorShape::operator!=(const TensorShape& other) const @@ -104,20 +172,104 @@ bool TensorShape::operator!=(const TensorShape& other) const return !(*this == other); } +unsigned int TensorShape::GetNumDimensions() const +{ + CheckUnspecifiedNumDimensions(); + + return m_NumDimensions; +} + unsigned int TensorShape::GetNumElements() const { + CheckUnspecifiedNumDimensions(); + if (m_NumDimensions == 0) { return 0; } unsigned int count = 1; - for (unsigned int i = 0; i < m_NumDimensions; i++) + bool atLeastOneDimensionSpecified = false; + for (unsigned int i = 0; i < m_NumDimensions; ++i) + { + if (m_DimensionsSpecificity[i] && m_Dimensions[i] != 0) + { + atLeastOneDimensionSpecified = true; + count *= m_Dimensions[i]; + } + } + + if (atLeastOneDimensionSpecified) + { + return count; + } + else { - count *= m_Dimensions[i]; + return 0; } +} - return count; +bool TensorShape:: GetDimensionSpecificity(unsigned int i) const +{ + CheckUnspecifiedNumDimensions(); + CheckDimensionIndex(i); + + return m_DimensionsSpecificity[i]; +} + +void TensorShape::SetNumDimensions(unsigned int numDimensions, bool initDimensionsSpecificity) +{ + CheckScalar(); + CheckSpecifiedNumDimensions(); + CheckValidNumDimensions(numDimensions); + + m_NumDimensions = numDimensions; + m_Dimensionality = Dimensionality::Specified; + std::fill(m_Dimensions.begin(), m_Dimensions.begin() + m_NumDimensions, 0); + std::fill(m_DimensionsSpecificity.begin(), m_DimensionsSpecificity.begin() + m_NumDimensions, + initDimensionsSpecificity); +} + +void TensorShape::SetDimensionSize(unsigned int i, unsigned int dimensionSize) +{ + CheckScalar(); + CheckUnspecifiedNumDimensions(); + CheckDimensionIndex(i); + + m_Dimensions[i] = dimensionSize; + m_DimensionsSpecificity[i] = true; +} + +bool TensorShape::AreAllDimensionsSpecified() const +{ + CheckUnspecifiedNumDimensions(); + + bool areAllDimensionsSpecified = true; + for (unsigned int i = 0; i < m_NumDimensions; ++i) + { + if (!m_DimensionsSpecificity[i]) + { + areAllDimensionsSpecified = false; + break; + } + } + return areAllDimensionsSpecified; +} + +bool TensorShape::IsAtLeastOneDimensionSpecified() const +{ + CheckUnspecifiedNumDimensions(); + + bool isAtLeastOneDimensionSpecified = false; + for (unsigned int i = 0; i < m_NumDimensions; ++i) + { + if (m_DimensionsSpecificity[i]) + { + isAtLeastOneDimensionSpecified = true; + break; + } + } + return isAtLeastOneDimensionSpecified; } void TensorShape::CheckDimensionIndex(unsigned int i) const @@ -130,6 +282,60 @@ void TensorShape::CheckDimensionIndex(unsigned int i) const } } +void TensorShape::CheckValidNumDimensions(unsigned int numDimensions) +{ + if (numDimensions < 1) + { + throw InvalidArgumentException("Tensor numDimensions must be greater than 0", CHECK_LOCATION()); + } + + if (numDimensions > MaxNumOfTensorDimensions) + { + throw InvalidArgumentException("Tensor numDimensions must be less than or equal to MaxNumOfTensorDimensions" + , CHECK_LOCATION()); + } +} + +void TensorShape::CheckDimensionSpecified(unsigned int i) const +{ + if (!m_DimensionsSpecificity[i]) + { + std::stringstream errorMessage; + errorMessage << "Dimension index: " << i << " not specified. Tensor shape not inferred yet."; + throw InvalidArgumentException(errorMessage.str(), CHECK_LOCATION()); + } +} + +void TensorShape::CheckScalar() const +{ + if (Dimensionality::Scalar == m_Dimensionality) + { + std::stringstream errorMessage; + errorMessage << "Invalid action on a tensor shape that holds a scalar value."; + throw InvalidArgumentException(errorMessage.str(), CHECK_LOCATION()); + } +} + +void TensorShape::CheckUnspecifiedNumDimensions() const +{ + if (Dimensionality::NotSpecified == m_Dimensionality) + { + std::stringstream errorMessage; + errorMessage << "Invalid action on a tensor shape that has unknown number of dimensions."; + throw InvalidArgumentException(errorMessage.str(), CHECK_LOCATION()); + } +} + +void TensorShape::CheckSpecifiedNumDimensions() const +{ + if (Dimensionality::Specified == m_Dimensionality) + { + std::stringstream errorMessage; + errorMessage << "Invalid action on a tensor shape that has known number of dimensions."; + throw InvalidArgumentException(errorMessage.str(), CHECK_LOCATION()); + } +} + // --- // --- TensorInfo // --- |