blob: 6a9bf90c08c3e9dbaa19467d0a89e10a1fbe5d20 [file] [log] [blame]
Aron Virginas-Tarf03fcf02019-07-09 17:44:24 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "OutputShapeUtils.hpp"
7
Aron Virginas-Tar2b173122019-07-15 14:29:09 +01008#include <DataLayoutIndexed.hpp>
9
Aron Virginas-Tarf03fcf02019-07-09 17:44:24 +010010#include <algorithm>
Sadik Armagan310d8ff2019-07-11 10:53:38 +010011#include <vector>
Aron Virginas-Tarf03fcf02019-07-09 17:44:24 +010012
Sadik Armagan5e9521c2019-07-12 13:55:57 +010013namespace
14{
15
16using namespace armnn;
17
18TensorShape CalculateMaxShape(const TensorShape& inShape0, const TensorShape& inShape1)
19{
20 // NOTE: The inferred output size will be the maximum size along each dimension
21 // of inShape0 and inShape1, starting with the trailing dimensions, and working its way forward.
22 //
23 // Example: inShape0={4, 1, 2}, inShape1={5, 4, 3, 1} => outputShape={5, 4, 3, 2}
24
25 const unsigned int numInput0Dims = inShape0.GetNumDimensions();
26 const unsigned int numInput1Dims = inShape1.GetNumDimensions();
27
28 const unsigned int maxNumDims = std::max(numInput0Dims, numInput1Dims);
29
30 TensorShape outputShape = TensorShape(maxNumDims);
31 for (unsigned int reverseIdx = 1u; reverseIdx <= maxNumDims; ++reverseIdx)
32 {
33 const int input0Idx = numInput0Dims - reverseIdx;
34 const int input1Idx = numInput1Dims - reverseIdx;
35
36 const unsigned int input0DimSize = input0Idx >= 0 ? inShape0[input0Idx] : 0u;
37 const unsigned int input1DimSize = input1Idx >= 0 ? inShape1[input1Idx] : 0u;
38
39 const unsigned int outputIdx = maxNumDims - reverseIdx;
40 outputShape[outputIdx] = std::max(input0DimSize, input1DimSize);
41 }
42
43 return outputShape;
44}
45
46} // namespace annonymous
47
48
Aron Virginas-Tarf03fcf02019-07-09 17:44:24 +010049namespace armnn_driver
50{
51
52using namespace armnn;
53
Aron Virginas-Tar366e0a62019-07-10 13:01:41 +010054bool IsDynamicOutput(const TensorInfo& outputInfo)
55{
56 return outputInfo.GetNumElements() == 0u;
57}
58
Aron Virginas-Tar2b173122019-07-15 14:29:09 +010059TensorShape InferConvolution2dOutputShape(const TensorShape& inputShape,
60 const TensorShape& kernelShape,
61 const Convolution2dDescriptor& descriptor)
62{
63 if (inputShape.GetNumDimensions() != 4)
64 {
65 throw InvalidArgumentException("Input shape for Convolution2d must be 4D");
66 }
67
68 armnnUtils::DataLayoutIndexed dataLayoutIndex(descriptor.m_DataLayout);
69
70 const unsigned int cIndex = dataLayoutIndex.GetChannelsIndex();
71 const unsigned int wIndex = dataLayoutIndex.GetWidthIndex();
72 const unsigned int hIndex = dataLayoutIndex.GetHeightIndex();
73
74 const unsigned int wInput = inputShape[wIndex];
75 const unsigned int hInput = inputShape[hIndex];
76
77 const unsigned int wKernel = kernelShape[wIndex];
78 const unsigned int wDilated = wKernel + (descriptor.m_DilationX - 1) * (wKernel - 1);
79
80 const unsigned int wRead = (wInput + descriptor.m_PadLeft + descriptor.m_PadRight) - wDilated;
81 const unsigned int wOutput = 1 + (wRead / descriptor.m_StrideX);
82
83 const unsigned int hKernel = kernelShape[hIndex];
84 const unsigned int hDilated = hKernel + (descriptor.m_DilationY - 1) * (hKernel - 1);
85
86 const unsigned int hRead = (hInput + descriptor.m_PadTop + descriptor.m_PadBottom) - hDilated;
87 const unsigned int hOutput = 1 + (hRead / descriptor.m_StrideY);
88
89 const unsigned int batches = inputShape[0];
90 const unsigned int channels = kernelShape[0];
91
92 TensorShape outputShape(4);
93 outputShape[0] = batches;
94 outputShape[cIndex] = channels;
95 outputShape[wIndex] = wOutput;
96 outputShape[hIndex] = hOutput;
97
98 return outputShape;
99}
100
Narumol Prangnawarat95b1ef62019-07-15 12:02:20 +0100101TensorShape InferMaximumOutputShape(const armnn::TensorShape& input0Shape,
102 const armnn::TensorShape& input1Shape)
103{
104 return CalculateMaxShape(input0Shape, input1Shape);
105}
106
Sadik Armagan310d8ff2019-07-11 10:53:38 +0100107TensorShape InferPadOutputShape(const TensorShape& inputShape,
108 const std::vector<std::pair<unsigned int, unsigned int>>& padList)
109{
110 const unsigned int numDims = inputShape.GetNumDimensions();
111
112 std::vector<unsigned int> outputDims;
113 TensorShape outputShape = TensorShape(numDims);
114 for (unsigned int dim = 0; dim < numDims; ++dim)
115 {
116 unsigned int dimSize = inputShape[dim];
117 const std::pair<unsigned int, unsigned int>& dimPadding = padList[dim];
118 dimSize += dimPadding.first;
119 dimSize += dimPadding.second;
120 outputShape[dim] = dimSize;
121 }
122 return outputShape;
123}
124
Aron Virginas-Tarf03fcf02019-07-09 17:44:24 +0100125TensorShape InferPreluOutputShape(const TensorShape& inputShape, const TensorShape& alphaShape)
126{
Sadik Armagan5e9521c2019-07-12 13:55:57 +0100127 return CalculateMaxShape(inputShape, alphaShape);
128}
Aron Virginas-Tarf03fcf02019-07-09 17:44:24 +0100129
Sadik Armagan5e9521c2019-07-12 13:55:57 +0100130TensorShape InferSubOutputShape(const TensorShape& input0Shape, const TensorShape& input1Shape)
131{
132 return CalculateMaxShape(input0Shape, input1Shape);
Aron Virginas-Tarf03fcf02019-07-09 17:44:24 +0100133}
134
135} // namespace armnn_driver