ArmNN
 20.05
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>
11 
12 #include <boost/numeric/conversion/cast.hpp>
13 
14 #include <cstring>
15 
16 namespace armnn
17 {
18 
19 namespace
20 {
21 
22 void PadParams(StridedSliceDescriptor& p, unsigned int dimCount)
23 {
24  ARMNN_ASSERT_MSG(dimCount <= 4, "Expected input with at most 4 dimensions");
25 
26  const unsigned int beginIndicesCount =
27  boost::numeric_cast<unsigned int>(p.m_Begin.size());
28 
29  ARMNN_ASSERT(dimCount >= beginIndicesCount);
30  const unsigned int padCount = dimCount - beginIndicesCount;
31 
32  p.m_Begin.resize(dimCount);
33  p.m_End.resize(dimCount);
34  p.m_Stride.resize(dimCount);
35 
36  for (unsigned int i = beginIndicesCount; i > 0; --i)
37  {
38  p.m_Stride[i + padCount - 1] = p.m_Stride[i - 1];
39  p.m_Begin[i + padCount - 1] = p.m_Begin[i - 1];
40  p.m_End[i + padCount - 1] = p.m_End[i - 1];
41  }
42 
43  for (unsigned int i = 0; i < padCount; ++i)
44  {
45  p.m_Stride[i] = 1;
46  p.m_Begin[i] = 0;
47  p.m_End[i] = 0;
48  }
49 
50  p.m_ShrinkAxisMask <<= padCount;
51  p.m_EllipsisMask <<= padCount;
52  p.m_NewAxisMask <<= padCount;
53  p.m_BeginMask <<= padCount;
54  p.m_EndMask <<= padCount;
55  p.m_BeginMask |= (1 << padCount) - 1;
56  p.m_EndMask |= (1 << padCount) - 1;
57 }
58 
59 bool LoopCondition(int index, int stop, int stride)
60 {
61  return stride > 0 ? index >= stop : index <= stop;
62 }
63 
64 TensorShape ExtendShape(const TensorShape& inputShape,
65  unsigned int newNumDimensions)
66 {
67  if (inputShape.GetNumDimensions() >= newNumDimensions)
68  {
69  return inputShape;
70  }
71 
72  std::vector<unsigned int> newSizes(newNumDimensions, 0);
73 
74  unsigned int diff = newNumDimensions - inputShape.GetNumDimensions();
75 
76  for (unsigned int i = 0; i < diff; i++)
77  {
78  newSizes[i] = 1;
79  }
80 
81  for (unsigned int i = diff; i < newNumDimensions; i++)
82  {
83  newSizes[i] = inputShape[i - diff];
84  }
85 
86  return TensorShape(newNumDimensions, newSizes.data());
87 }
88 
89 } // Anonymous namespace
90 
91 void StridedSlice(const TensorInfo& inputInfo,
92  const StridedSliceDescriptor& params,
93  const void* inputData,
94  void* outputData,
95  unsigned int dataTypeSize)
96 {
97  const unsigned char* input = reinterpret_cast<const unsigned char*>(inputData);
98  unsigned char* output = reinterpret_cast<unsigned char*>(outputData);
99 
100  const TensorShape inputShape = ExtendShape(inputInfo.GetShape(), 4);
101 
102  StridedSliceDescriptor paddedParams = params;
103 
104  // Pad parameters to 4 dimensions
105  PadParams(paddedParams, 4);
106 
107  const int start0 = paddedParams.GetStartForAxis(inputShape, 0);
108  const int stop0 = paddedParams.GetStopForAxis (inputShape, 0, start0);
109 
110  const int start1 = paddedParams.GetStartForAxis(inputShape, 1);
111  const int stop1 = paddedParams.GetStopForAxis (inputShape, 1, start1);
112 
113  const int start2 = paddedParams.GetStartForAxis(inputShape, 2);
114  const int stop2 = paddedParams.GetStopForAxis (inputShape, 2, start2);
115 
116  const int start3 = paddedParams.GetStartForAxis(inputShape, 3);
117  const int stop3 = paddedParams.GetStopForAxis (inputShape, 3, start3);
118 
119  const int step = boost::numeric_cast<int>(dataTypeSize);
120 
121  for (int in0 = start0;
122  !LoopCondition(in0, stop0, paddedParams.m_Stride[0]);
123  in0 += paddedParams.m_Stride[0])
124  {
125  for (int in1 = start1;
126  !LoopCondition(in1, stop1, paddedParams.m_Stride[1]);
127  in1 += paddedParams.m_Stride[1])
128  {
129  for (int in2 = start2;
130  !LoopCondition(in2, stop2, paddedParams.m_Stride[2]);
131  in2 += paddedParams.m_Stride[2])
132  {
133  for (int in3 = start3;
134  !LoopCondition(in3, stop3, paddedParams.m_Stride[3]);
135  in3 += paddedParams.m_Stride[3])
136  {
137  int dim1 = boost::numeric_cast<int>(inputShape[1]);
138  int dim2 = boost::numeric_cast<int>(inputShape[2]);
139  int dim3 = boost::numeric_cast<int>(inputShape[3]);
140 
141  int inputOffset = (((in0 * dim1 + in1) * dim2 + in2) * dim3 + in3) * step;
142  ::memcpy(output, input + inputOffset, dataTypeSize);
143  output += step;
144  }
145  }
146  }
147  }
148 }
149 
150 } // namespace armnn
const TensorShape & GetShape() const
Definition: Tensor.hpp:88
Copyright (c) 2020 ARM Limited.
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
Definition: NumericCast.hpp:33
void StridedSlice(const TensorInfo &inputInfo, const StridedSliceDescriptor &params, const void *inputData, void *outputData, unsigned int dataTypeSize)
A StridedSliceDescriptor for the StridedSliceLayer.