aboutsummaryrefslogtreecommitdiff
path: root/src/armnn/layers
diff options
context:
space:
mode:
Diffstat (limited to 'src/armnn/layers')
-rw-r--r--src/armnn/layers/StridedSliceLayer.cpp82
1 files changed, 81 insertions, 1 deletions
diff --git a/src/armnn/layers/StridedSliceLayer.cpp b/src/armnn/layers/StridedSliceLayer.cpp
index c348951178..f33d1d4162 100644
--- a/src/armnn/layers/StridedSliceLayer.cpp
+++ b/src/armnn/layers/StridedSliceLayer.cpp
@@ -2,6 +2,9 @@
// Copyright © 2018-2024 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
+// Copyright © 2018 The TensorFlow Authors. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+//
#include "StridedSliceLayer.hpp"
#include "LayerCloneBase.hpp"
@@ -44,6 +47,8 @@ StridedSliceLayer* StridedSliceLayer::Clone(Graph& graph) const
return CloneBase<StridedSliceLayer>(graph, m_Param, GetName());
}
+// Content in this function (fixes related to NewAxisMask and EllipsisMask) are paraphrased from:
+// tensorflow/tensorflow/lite/kernels/strided_slice.cc from the function BuildStridedSliceParams
std::vector<TensorShape> StridedSliceLayer::InferOutputShapes(
const std::vector<TensorShape>& inputShapes) const
{
@@ -57,8 +62,81 @@ std::vector<TensorShape> StridedSliceLayer::InferOutputShapes(
std::vector<unsigned int> outputShape;
unsigned int amountDimShrunk{0};
- for (unsigned int i = 0; i < inputShape.GetNumDimensions(); i++)
+ // Getting the actual number of output dimensions, including axes added with the NewAxisMask
+ unsigned int outputDims = inputShape.GetNumDimensions();
+ for(unsigned int i = 0; i < m_Param.m_Begin.size(); ++i)
+ {
+ // Adding to dimension count for every set bit of NewAxisMask not covered by the EllipsisMask
+ if(m_Param.m_NewAxisMask & (1 << i) && !(m_Param.m_EllipsisMask & (1 << i)))
+ {
+ ++outputDims;
+ }
+ }
+
+ // Modifying the EllipsisMask based on the NewAxisMask (expand for any newly added axes)
+ // and the NewAxisMask based on the EllipsisMask (offset based on the expanded ellipsis)
+ int realEllipsisMask = 0, realNewAxisMask = 0;
+ // The number of bits the ellipsis mask was expanded by
+ unsigned int ellipsisExpandedBy = 0;
+ for(unsigned int i = 0; i < outputDims; ++i)
+ {
+ if(m_Param.m_EllipsisMask & (1 << i))
+ {
+ // The end index of the expanded ellipsis mask (start is at i)
+ // End Index calculation - i+1 (for non-expanded ellipsis) + outputDims-inputDims (number of added dims)
+ unsigned int endIdx = std::min(i + 1u + outputDims - inputShape.GetNumDimensions(), outputDims);
+
+ // Calculation: the total size of the mask -1 for the already existing bit in the original mask
+ ellipsisExpandedBy = endIdx - i - 1;
+
+ // Setting mask bit to 1 for the entire expanded ellipsis
+ for(; i < endIdx; ++i)
+ {
+ realEllipsisMask |= (1 << i);
+ }
+ }
+
+ // Setting the real NewAxisMask based on the expanded ellipsis size
+ if(m_Param.m_NewAxisMask & (1 << (i - ellipsisExpandedBy)))
+ {
+ realNewAxisMask |= (1 << i);
+ }
+ }
+
+ // The backwards offset by which i is ahead of the actual inputTensor dimension
+ unsigned int inputDimOffset = 0;
+ // Iterating through the parameters and inferring output shape
+ for (unsigned int i = 0; i < outputDims; ++i)
{
+ // Add entire dimension if EllipsisMask is set
+ if(realEllipsisMask & (1 << i))
+ {
+ outputShape.push_back(inputShape[i - inputDimOffset]);
+ continue;
+ }
+ // Add dimension of length 1 if NewAxisMask is set
+ if(realNewAxisMask & (1 << i))
+ {
+ outputShape.push_back(1);
+ ++inputDimOffset;
+ continue;
+ }
+ // Fill the rest of the inferred shape (dimensions greater than the input shape)
+ if(i >= inputShape.GetNumDimensions())
+ {
+ // If EllipsisMask was set at any point, the TensorFlow behavior is to fill the rest of the tensor with 1
+ // Otherwise, the remaining dimensions from the inputShape (which were skipped over) are used
+ if(realEllipsisMask > 0)
+ {
+ outputShape.push_back(1);
+ }
+ else
+ {
+ outputShape.push_back(inputShape[i - inputDimOffset]);
+ }
+ continue;
+ }
+
int stride = m_Param.m_Stride[i];
int start = m_Param.GetStartForAxis(inputShape, i);
int stop = m_Param.GetStopForAxis(inputShape, i, start);
@@ -86,7 +164,9 @@ std::vector<TensorShape> StridedSliceLayer::InferOutputShapes(
int newSize = stride > 0 ? ((stop - start) + stride - 1) / stride :
((start - stop) - stride - 1) / -stride;
+ // Making sure the dimension size doesn't go out of bounds
newSize = std::max(0, newSize);
+ newSize = std::min(newSize, armnn::numeric_cast<int>(inputShape[i - inputDimOffset]));
outputShape.push_back(armnn::numeric_cast<unsigned int>(newSize));
}