blob: 6d0d004336240844bbbe539a65c7d0ed9dbdbabf [file] [log] [blame]
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "SpaceToBatchNd.hpp"
7
Matthew Bentham8800c002018-11-19 13:19:28 +00008#include <backendsCommon/DataLayoutIndexed.hpp>
9
Nattapat Chaimanowong3ea76d52018-11-09 14:10:38 +000010namespace armnn
11{
12
13unsigned int GetOffset(const TensorShape& shape,
14 unsigned int b,
15 unsigned int h,
16 unsigned int w,
17 unsigned int c,
18 const DataLayoutIndexed& dataLayout)
19{
20 if (dataLayout.GetDataLayout() == DataLayout::NHWC)
21 {
22 return ((b * shape[dataLayout.GetHeightIndex()] + h) * shape[dataLayout.GetWidthIndex()] + w) *
23 shape[dataLayout.GetChannelsIndex()] + c;
24 }
25 else
26 {
27 return ((b * shape[dataLayout.GetChannelsIndex()] + c) * shape[dataLayout.GetHeightIndex()] + h) *
28 shape[dataLayout.GetWidthIndex()] + w;
29 }
30}
31
32template<typename T>
33void SpaceToBatchNd(const TensorInfo& inputInfo,
34 const TensorInfo& outputInfo,
35 const SpaceToBatchNdDescriptor& params,
36 const T* inputData,
37 T* outputData)
38{
39 DataLayoutIndexed dataLayout = params.m_DataLayout;
40
41 const TensorShape& inputShape = inputInfo.GetShape();
42 const TensorShape& outputShape = outputInfo.GetShape();
43
44 const unsigned int channels = inputShape[dataLayout.GetChannelsIndex()];
45
46 const unsigned int inputBatchSize = inputShape[0];
47 const unsigned int inputHeight = inputShape[dataLayout.GetHeightIndex()];
48 const unsigned int inputWidth = inputShape[dataLayout.GetWidthIndex()];
49
50 const unsigned int outputBatchSize = outputShape[0];
51 const unsigned int outputHeight = outputShape[dataLayout.GetHeightIndex()];
52 const unsigned int outputWidth = outputShape[dataLayout.GetWidthIndex()];
53
54 const unsigned int blockHeight = params.m_BlockShape[0];
55 const unsigned int blockWidth = params.m_BlockShape[1];
56
57 const unsigned int paddingTop = params.m_PadList[0].first;
58 const unsigned int paddingLeft = params.m_PadList[1].first;
59
60 for (unsigned int outB = 0; outB < outputBatchSize; outB++)
61 {
62 unsigned int inB = outB % inputBatchSize;
63
64 unsigned int shiftW = (outB / inputBatchSize) % blockWidth;
65 unsigned int shiftH = (outB / inputBatchSize) / blockWidth;
66
67 for (unsigned int outH = 0; outH < outputHeight; outH++)
68 {
69 for (unsigned int outW = 0; outW < outputWidth; outW++)
70 {
71 if (outH * blockHeight + shiftH < paddingTop ||
72 outH * blockHeight + shiftH >= paddingTop + inputHeight ||
73 outW * blockWidth + shiftW < paddingLeft ||
74 outW * blockWidth + shiftW >= paddingLeft + inputWidth)
75 {
76 for (unsigned int c = 0; c < channels; c++)
77 {
78 unsigned int outOffset = GetOffset(outputShape,
79 outB,
80 outH,
81 outW,
82 c,
83 dataLayout);
84 outputData[outOffset] = 0;
85 }
86 }
87 else
88 {
89 for (unsigned int c = 0; c < channels; c++)
90 {
91 unsigned int inOffset = GetOffset(inputShape,
92 inB,
93 (outH * blockHeight + shiftH) - paddingTop,
94 (outW * blockWidth + shiftW) - paddingLeft,
95 c,
96 dataLayout);
97
98 unsigned int outOffset = GetOffset(outputShape,
99 outB,
100 outH,
101 outW,
102 c,
103 dataLayout);
104
105 outputData[outOffset] = inputData[inOffset];
106 }
107 }
108 }
109 }
110 }
111}
112
113template void SpaceToBatchNd<float>(const TensorInfo& inputInfo,
114 const TensorInfo& outputInfo,
115 const SpaceToBatchNdDescriptor& params,
116 const float* inputData,
117 float* outData);
118
119template void SpaceToBatchNd<uint8_t>(const TensorInfo& inputInfo,
120 const TensorInfo& outputInfo,
121 const SpaceToBatchNdDescriptor& params,
122 const uint8_t* inputData,
123 uint8_t* outData);
124
125} //namespace armnn