aboutsummaryrefslogtreecommitdiff
path: root/src/armnn/Tensor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/armnn/Tensor.cpp')
-rw-r--r--src/armnn/Tensor.cpp258
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
// ---