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