ArmNN
 21.02
Pad.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 "Pad.hpp"
7 
8 #include "BaseIterator.hpp"
9 #include "Decoders.hpp"
10 #include "Encoders.hpp"
11 
13 
14 #include <cmath>
15 #include <cstddef>
16 #include <functional>
17 #include <limits>
18 #include <cassert>
19 
20 namespace
21 {
22 
23 void FillOutputWithPadValue(armnn::Encoder<float>& outputData,
24  const float padValue,
25  const unsigned int numOutputElements)
26 {
27  for (unsigned int i = 0; i < numOutputElements; ++i)
28  {
29  outputData[i];
30  outputData.Set(padValue);
31  }
32 }
33 
34 } // anonymous namespace
35 
36 namespace armnn
37 {
38 
39 void Pad(const TensorInfo& inputInfo,
40  const TensorInfo& outputInfo,
41  const PadQueueDescriptor& data)
42 {
43  auto padList = data.m_Parameters.m_PadList;
44  auto padValue = data.m_Parameters.m_PadValue;
45 
46  unsigned int numOutputElements = outputInfo.GetNumElements();
47 
48  TensorShape outputShape = outputInfo.GetShape();
49  TensorShape inputShape = inputInfo.GetShape();
50 
51  unsigned int numInputDimensions = inputShape.GetNumDimensions();
52 
53 #ifndef NDEBUG
54 
55  unsigned int numOutputDimensions = outputShape.GetNumDimensions();
56  assert(numInputDimensions == numOutputDimensions);
57 
58 #endif
59 
60  unsigned int inputBatches = 0;
61  unsigned int inputChannels = 0;
62  unsigned int inputHeight = 0;
63  unsigned int inputWidth = 0;
64 
65  unsigned int outputChannels = 0;
66  unsigned int outputHeight = 0;
67  unsigned int outputWidth = 0;
68 
69  auto inputData = MakeDecoder<float>(inputInfo, data.m_Inputs[0]->Map());
70  auto outData = MakeEncoder<float>(outputInfo, data.m_Outputs[0]->Map());
71 
72  // Fill the output tensor with Pad value first
73  if (outputInfo.IsQuantized())
74  {
75  // For Quantized types Pad Value should not be quantized with scale and offset of the tensor info
76  auto temporaryInfo = TensorInfo(outputInfo.GetShape(), outputInfo.GetDataType(), 1.0f, 0);
77  auto outputData = MakeEncoder<float>(temporaryInfo, data.m_Outputs[0]->Map());
78  FillOutputWithPadValue(*outputData, padValue, numOutputElements);
79  }
80  else
81  {
82  FillOutputWithPadValue(*outData, padValue, numOutputElements);
83  }
84 
85  Decoder<float>& input = *inputData;
86  Encoder<float>& output = *outData;
87 
88  switch(numInputDimensions) {
89 
90  case 1:
91  inputWidth = inputShape[0];
92  for (unsigned int w = 0; w < inputWidth ; w++)
93  {
94  input[w];
95  auto inputValue = input.Get();
96  auto outputIndex = w + std::get<0>(padList[0]);
97  output[outputIndex];
98  output.Set(inputValue);
99  }
100 
101  break;
102  case 2 :
103  inputHeight = inputShape[0];
104  inputWidth = inputShape[1];
105  outputWidth = outputShape[1];
106 
107  for (unsigned int h = 0; h < inputHeight; h++)
108  {
109  for (unsigned int w = 0; w < inputWidth ; w++)
110  {
111  input[h * inputWidth + w];
112  auto inputValue = input.Get();
113  auto outputIndex = (h + std::get<0>(padList[0])) * outputWidth + (w + std::get<0>(padList[1]));
114  output[outputIndex];
115  output.Set(inputValue);
116  }
117  }
118 
119  break;
120  case 3 :
121  inputChannels = inputShape[0];
122  inputHeight = inputShape[1];
123  inputWidth = inputShape[2];
124  outputHeight = outputShape[1];
125  outputWidth = outputShape[2];
126 
127  for (unsigned int c = 0; c < inputChannels; c++)
128  {
129  for (unsigned int h = 0; h < inputHeight; h++)
130  {
131  for (unsigned int w = 0; w < inputWidth ; w++)
132  {
133  input[c * inputHeight * inputWidth + h * inputWidth + w];
134  auto inputValue = input.Get();
135  auto outputIndex = (c + std::get<0>(padList[0])) * outputHeight * outputWidth
136  + (h + std::get<0>(padList[1])) * outputWidth
137  + (w + std::get<0>(padList[2]));
138  output[outputIndex];
139  output.Set(inputValue);
140  }
141  }
142  }
143 
144  break;
145  case 4 :
146  inputBatches = inputShape[0];
147  inputChannels = inputShape[1];
148  inputHeight = inputShape[2];
149  inputWidth = inputShape[3];
150  outputChannels = outputShape[1];
151  outputHeight = outputShape[2];
152  outputWidth = outputShape[3];
153 
154  for (unsigned int b = 0; b < inputBatches; b++)
155  {
156  for (unsigned int c = 0; c < inputChannels; c++)
157  {
158  for (unsigned int h = 0; h < inputHeight; h++)
159  {
160  for (unsigned int w = 0; w < inputWidth ; w++)
161  {
162  input[b * inputChannels * inputHeight * inputWidth
163  + c * inputHeight * inputWidth
164  + h * inputWidth
165  + w];
166  auto inputValue = input.Get();
167  auto outputIndex = (b + std::get<0>(padList[0]))
168  * outputChannels * outputHeight * outputWidth
169  + (c + std::get<0>(padList[1])) * outputHeight * outputWidth
170  + (h + std::get<0>(padList[2])) * outputWidth
171  + (w + std::get<0>(padList[3]));
172  output[outputIndex];
173  output.Set(inputValue);
174  }
175  }
176  }
177  }
178 
179  break;
180  default :
181  break;
182  }
183 }
184 
185 } //namespace armnn
const TensorShape & GetShape() const
Definition: Tensor.hpp:187
float m_PadValue
Optional value to use for padding, defaults to 0.
virtual void Set(IType right)=0
std::vector< std::pair< unsigned int, unsigned int > > m_PadList
Specifies the padding for input dimension.
Copyright (c) 2021 ARM Limited and Contributors.
virtual IType Get() const =0
std::vector< ITensorHandle * > m_Outputs
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
Definition: Tensor.cpp:174
std::vector< ITensorHandle * > m_Inputs
void Pad(const TensorInfo &inputInfo, const TensorInfo &outputInfo, const PadQueueDescriptor &data)
Definition: Pad.cpp:39
unsigned int GetNumElements() const
Definition: Tensor.hpp:192