Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 1 | // |
| 2 | // Copyright © 2017 Arm Ltd. All rights reserved. |
| 3 | // SPDX-License-Identifier: MIT |
| 4 | // |
| 5 | |
| 6 | #include "Pad.hpp" |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 7 | |
| 8 | #include "BaseIterator.hpp" |
| 9 | #include "Decoders.hpp" |
David Monahan | 3475781 | 2019-06-19 11:47:21 +0100 | [diff] [blame] | 10 | #include "Encoders.hpp" |
| 11 | |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 12 | #include <armnnUtils/TensorUtils.hpp> |
| 13 | |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 14 | #include <cmath> |
| 15 | #include <cstddef> |
| 16 | #include <functional> |
| 17 | #include <limits> |
| 18 | #include <cassert> |
| 19 | |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 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 | |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 36 | namespace armnn |
| 37 | { |
David Monahan | 3475781 | 2019-06-19 11:47:21 +0100 | [diff] [blame] | 38 | |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 39 | void Pad(const TensorInfo& inputInfo, |
| 40 | const TensorInfo& outputInfo, |
Finn Williams | 0109794 | 2021-04-26 12:06:34 +0100 | [diff] [blame] | 41 | const ITensorHandle* inputHandle, |
| 42 | ITensorHandle* outputHandle, |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 43 | const PadQueueDescriptor& data) |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 44 | { |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 45 | auto padList = data.m_Parameters.m_PadList; |
| 46 | auto padValue = data.m_Parameters.m_PadValue; |
| 47 | |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 48 | unsigned int numOutputElements = outputInfo.GetNumElements(); |
| 49 | |
| 50 | TensorShape outputShape = outputInfo.GetShape(); |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 51 | TensorShape inputShape = inputInfo.GetShape(); |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 52 | |
| 53 | unsigned int numInputDimensions = inputShape.GetNumDimensions(); |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 54 | |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 55 | #ifndef NDEBUG |
Mohamed Nour Abouelseoud | dd6acea | 2018-10-18 12:26:19 +0100 | [diff] [blame] | 56 | |
| 57 | unsigned int numOutputDimensions = outputShape.GetNumDimensions(); |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 58 | assert(numInputDimensions == numOutputDimensions); |
Mohamed Nour Abouelseoud | dd6acea | 2018-10-18 12:26:19 +0100 | [diff] [blame] | 59 | |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 60 | #endif |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 61 | |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 62 | unsigned int inputBatches = 0; |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 63 | unsigned int inputChannels = 0; |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 64 | unsigned int inputHeight = 0; |
| 65 | unsigned int inputWidth = 0; |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 66 | |
| 67 | unsigned int outputChannels = 0; |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 68 | unsigned int outputHeight = 0; |
| 69 | unsigned int outputWidth = 0; |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 70 | |
Finn Williams | 0109794 | 2021-04-26 12:06:34 +0100 | [diff] [blame] | 71 | auto inputData = MakeDecoder<float>(inputInfo, inputHandle->Map()); |
| 72 | auto outData = MakeEncoder<float>(outputInfo, outputHandle->Map()); |
David Monahan | 3475781 | 2019-06-19 11:47:21 +0100 | [diff] [blame] | 73 | |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 74 | // Fill the output tensor with Pad value first |
| 75 | if (outputInfo.IsQuantized()) |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 76 | { |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 77 | // For Quantized types Pad Value should not be quantized with scale and offset of the tensor info |
| 78 | auto temporaryInfo = TensorInfo(outputInfo.GetShape(), outputInfo.GetDataType(), 1.0f, 0); |
Finn Williams | 0109794 | 2021-04-26 12:06:34 +0100 | [diff] [blame] | 79 | auto outputData = MakeEncoder<float>(temporaryInfo, outputHandle->Map()); |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 80 | FillOutputWithPadValue(*outputData, padValue, numOutputElements); |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 81 | } |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 82 | else |
| 83 | { |
| 84 | FillOutputWithPadValue(*outData, padValue, numOutputElements); |
| 85 | } |
| 86 | |
| 87 | Decoder<float>& input = *inputData; |
| 88 | Encoder<float>& output = *outData; |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 89 | |
| 90 | switch(numInputDimensions) { |
Mohamed Nour Abouelseoud | dd6acea | 2018-10-18 12:26:19 +0100 | [diff] [blame] | 91 | |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 92 | case 1: |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 93 | inputWidth = inputShape[0]; |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 94 | for (unsigned int w = 0; w < inputWidth ; w++) |
| 95 | { |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 96 | input[w]; |
| 97 | auto inputValue = input.Get(); |
| 98 | auto outputIndex = w + std::get<0>(padList[0]); |
| 99 | output[outputIndex]; |
| 100 | output.Set(inputValue); |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 101 | } |
| 102 | |
| 103 | break; |
| 104 | case 2 : |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 105 | inputHeight = inputShape[0]; |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 106 | inputWidth = inputShape[1]; |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 107 | outputWidth = outputShape[1]; |
| 108 | |
| 109 | for (unsigned int h = 0; h < inputHeight; h++) |
| 110 | { |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 111 | for (unsigned int w = 0; w < inputWidth ; w++) |
| 112 | { |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 113 | input[h * inputWidth + w]; |
| 114 | auto inputValue = input.Get(); |
| 115 | auto outputIndex = (h + std::get<0>(padList[0])) * outputWidth + (w + std::get<0>(padList[1])); |
| 116 | output[outputIndex]; |
| 117 | output.Set(inputValue); |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 118 | } |
| 119 | } |
| 120 | |
| 121 | break; |
| 122 | case 3 : |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 123 | inputChannels = inputShape[0]; |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 124 | inputHeight = inputShape[1]; |
| 125 | inputWidth = inputShape[2]; |
| 126 | outputHeight = outputShape[1]; |
| 127 | outputWidth = outputShape[2]; |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 128 | |
| 129 | for (unsigned int c = 0; c < inputChannels; c++) |
| 130 | { |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 131 | for (unsigned int h = 0; h < inputHeight; h++) |
| 132 | { |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 133 | for (unsigned int w = 0; w < inputWidth ; w++) |
| 134 | { |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 135 | input[c * inputHeight * inputWidth + h * inputWidth + w]; |
| 136 | auto inputValue = input.Get(); |
| 137 | auto outputIndex = (c + std::get<0>(padList[0])) * outputHeight * outputWidth |
| 138 | + (h + std::get<0>(padList[1])) * outputWidth |
| 139 | + (w + std::get<0>(padList[2])); |
| 140 | output[outputIndex]; |
| 141 | output.Set(inputValue); |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 142 | } |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | break; |
| 147 | case 4 : |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 148 | inputBatches = inputShape[0]; |
| 149 | inputChannels = inputShape[1]; |
| 150 | inputHeight = inputShape[2]; |
| 151 | inputWidth = inputShape[3]; |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 152 | outputChannels = outputShape[1]; |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 153 | outputHeight = outputShape[2]; |
| 154 | outputWidth = outputShape[3]; |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 155 | |
| 156 | for (unsigned int b = 0; b < inputBatches; b++) |
| 157 | { |
| 158 | for (unsigned int c = 0; c < inputChannels; c++) |
| 159 | { |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 160 | for (unsigned int h = 0; h < inputHeight; h++) |
| 161 | { |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 162 | for (unsigned int w = 0; w < inputWidth ; w++) |
| 163 | { |
Sadik Armagan | 041b3c0 | 2020-06-04 10:32:18 +0100 | [diff] [blame] | 164 | input[b * inputChannels * inputHeight * inputWidth |
| 165 | + c * inputHeight * inputWidth |
| 166 | + h * inputWidth |
| 167 | + w]; |
| 168 | auto inputValue = input.Get(); |
| 169 | auto outputIndex = (b + std::get<0>(padList[0])) |
| 170 | * outputChannels * outputHeight * outputWidth |
| 171 | + (c + std::get<0>(padList[1])) * outputHeight * outputWidth |
| 172 | + (h + std::get<0>(padList[2])) * outputWidth |
| 173 | + (w + std::get<0>(padList[3])); |
| 174 | output[outputIndex]; |
| 175 | output.Set(inputValue); |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 176 | } |
| 177 | } |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | break; |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 182 | default : |
| 183 | break; |
| 184 | } |
Mohamed Nour Abouelseoud | 7420e55 | 2018-10-12 12:26:24 +0100 | [diff] [blame] | 185 | } |
| 186 | |
Mohamed Nour Abouelseoud | dd6acea | 2018-10-18 12:26:19 +0100 | [diff] [blame] | 187 | } //namespace armnn |