ArmNN
 24.02
StridedSlice.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "StridedSlice.hpp"
7 
8 #include <ResolveType.hpp>
9 
10 #include <armnn/utility/Assert.hpp>
12 
13 #include <cstring>
14 
15 namespace armnn
16 {
17 
18 namespace
19 {
20 
21 void PadParams(StridedSliceDescriptor& p, unsigned int dimCount)
22 {
23  ARMNN_ASSERT_MSG(dimCount <= 4, "Expected input with at most 4 dimensions");
24 
25  const unsigned int beginIndicesCount =
26  armnn::numeric_cast<unsigned int>(p.m_Begin.size());
27 
28  ARMNN_ASSERT(dimCount >= beginIndicesCount);
29  const unsigned int padCount = dimCount - beginIndicesCount;
30 
31  p.m_Begin.resize(dimCount);
32  p.m_End.resize(dimCount);
33  p.m_Stride.resize(dimCount);
34 
35  for (unsigned int i = beginIndicesCount; i > 0; --i)
36  {
37  p.m_Stride[i + padCount - 1] = p.m_Stride[i - 1];
38  p.m_Begin[i + padCount - 1] = p.m_Begin[i - 1];
39  p.m_End[i + padCount - 1] = p.m_End[i - 1];
40  }
41 
42  for (unsigned int i = 0; i < padCount; ++i)
43  {
44  p.m_Stride[i] = 1;
45  p.m_Begin[i] = 0;
46  p.m_End[i] = 0;
47  }
48 
49  p.m_ShrinkAxisMask <<= padCount;
50  p.m_EllipsisMask <<= padCount;
51  p.m_NewAxisMask <<= padCount;
52  p.m_BeginMask <<= padCount;
53  p.m_EndMask <<= padCount;
54  p.m_BeginMask |= (1 << padCount) - 1;
55  p.m_EndMask |= (1 << padCount) - 1;
56 }
57 
58 bool LoopCondition(int index, int stop, int stride)
59 {
60  return stride > 0 ? index >= stop : index <= stop;
61 }
62 
63 TensorShape ExtendShape(const TensorShape& inputShape,
64  unsigned int newNumDimensions)
65 {
66  if (inputShape.GetNumDimensions() >= newNumDimensions)
67  {
68  return inputShape;
69  }
70 
71  std::vector<unsigned int> newSizes(newNumDimensions, 0);
72 
73  unsigned int diff = newNumDimensions - inputShape.GetNumDimensions();
74 
75  for (unsigned int i = 0; i < diff; i++)
76  {
77  newSizes[i] = 1;
78  }
79 
80  for (unsigned int i = diff; i < newNumDimensions; i++)
81  {
82  newSizes[i] = inputShape[i - diff];
83  }
84 
85  return TensorShape(newNumDimensions, newSizes.data());
86 }
87 
88 } // Anonymous namespace
89 
90 void StridedSlice(const TensorInfo& inputInfo,
91  const StridedSliceDescriptor& params,
92  const void* inputData,
93  void* outputData,
94  unsigned int dataTypeSize)
95 {
96  if (inputData == nullptr)
97  {
98  throw armnn::InvalidArgumentException("Slice: Null inputData pointer");
99  }
100  if (outputData == nullptr)
101  {
102  throw armnn::InvalidArgumentException("Slice: Null outputData pointer");
103  }
104 
105  const unsigned char* input = reinterpret_cast<const unsigned char*>(inputData);
106  unsigned char* output = reinterpret_cast<unsigned char*>(outputData);
107 
108  const TensorShape inputShape = ExtendShape(inputInfo.GetShape(), 4);
109 
110  StridedSliceDescriptor paddedParams = params;
111 
112  // Pad parameters to 4 dimensions
113  PadParams(paddedParams, 4);
114 
115  const int start0 = paddedParams.GetStartForAxis(inputShape, 0);
116  const int stop0 = paddedParams.GetStopForAxis (inputShape, 0, start0);
117 
118  const int start1 = paddedParams.GetStartForAxis(inputShape, 1);
119  const int stop1 = paddedParams.GetStopForAxis (inputShape, 1, start1);
120 
121  const int start2 = paddedParams.GetStartForAxis(inputShape, 2);
122  const int stop2 = paddedParams.GetStopForAxis (inputShape, 2, start2);
123 
124  const int start3 = paddedParams.GetStartForAxis(inputShape, 3);
125  const int stop3 = paddedParams.GetStopForAxis (inputShape, 3, start3);
126 
127  const int step = armnn::numeric_cast<int>(dataTypeSize);
128 
129  for (int in0 = start0;
130  !LoopCondition(in0, stop0, paddedParams.m_Stride[0]);
131  in0 += paddedParams.m_Stride[0])
132  {
133  for (int in1 = start1;
134  !LoopCondition(in1, stop1, paddedParams.m_Stride[1]);
135  in1 += paddedParams.m_Stride[1])
136  {
137  for (int in2 = start2;
138  !LoopCondition(in2, stop2, paddedParams.m_Stride[2]);
139  in2 += paddedParams.m_Stride[2])
140  {
141  for (int in3 = start3;
142  !LoopCondition(in3, stop3, paddedParams.m_Stride[3]);
143  in3 += paddedParams.m_Stride[3])
144  {
145  int dim1 = armnn::numeric_cast<int>(inputShape[1]);
146  int dim2 = armnn::numeric_cast<int>(inputShape[2]);
147  int dim3 = armnn::numeric_cast<int>(inputShape[3]);
148 
149  int inputOffset = (((in0 * dim1 + in1) * dim2 + in2) * dim3 + in3) * step;
150  ::memcpy(output, input + inputOffset, dataTypeSize);
151  output += step;
152  }
153  }
154  }
155  }
156 }
157 
158 } // namespace armnn
ARMNN_ASSERT
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
armnn::TensorInfo
Definition: Tensor.hpp:152
ResolveType.hpp
ARMNN_ASSERT_MSG
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15
NumericCast.hpp
armnn::StridedSliceDescriptor::GetStopForAxis
int GetStopForAxis(const TensorShape &inputShape, unsigned int axis, int startForAxis) const
Definition: Descriptors.cpp:419
Assert.hpp
armnn::TensorShape
Definition: Tensor.hpp:20
armnn::InvalidArgumentException
Definition: Exceptions.hpp:80
armnn::StridedSliceDescriptor::m_Stride
std::vector< int > m_Stride
Stride values for the input that will be sliced.
Definition: Descriptors.hpp:1346
armnn::StridedSliceDescriptor
A StridedSliceDescriptor for the StridedSliceLayer.
Definition: Descriptors.hpp:1303
armnn::TensorInfo::GetShape
const TensorShape & GetShape() const
Definition: Tensor.hpp:193
armnn::StridedSliceDescriptor::GetStartForAxis
int GetStartForAxis(const TensorShape &inputShape, unsigned int axis) const
Definition: Descriptors.cpp:392
armnn
Copyright (c) 2021 ARM Limited and Contributors.
Definition: 01_00_quick_start.dox:6
armnn::StridedSlice
void StridedSlice(const TensorInfo &inputInfo, const StridedSliceDescriptor &params, const void *inputData, void *outputData, unsigned int dataTypeSize)
Definition: StridedSlice.cpp:90
StridedSlice.hpp