blob: fd442a88e809d223f00670ad090943cd2b688546 [file] [log] [blame]
Keith Davis9515c7e2019-06-21 09:33:59 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5#pragma once
6
7#include "ResolveType.hpp"
8#include "DataLayoutIndexed.hpp"
9#include "EndToEndTestImpl.hpp"
10
11#include "armnn/INetwork.hpp"
12
13#include "backendsCommon/test/CommonTestUtils.hpp"
14
15#include <Permute.hpp>
16#include <boost/test/unit_test.hpp>
17
18#include <vector>
19
20namespace
21{
22template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
23void PermuteDataToNCHW(const std::vector<armnn::BackendId>& backends,
24 const armnn::DataLayout& dataLayout,
25 TensorInfo& tensorInfo,
26 std::vector<T>& data)
27{
28 const armnn::PermutationVector NHWCToNCHW = {0, 2, 3, 1};
29
30 tensorInfo = armnnUtils::Permuted(tensorInfo, NHWCToNCHW);
31
32 std::vector<T> tmp(data.size());
33 armnnUtils::Permute(tensorInfo.GetShape(), NHWCToNCHW, data.data(), tmp.data(), sizeof(T));
34
35 data = tmp;
36}
37
38template<typename armnn::DataType DataType>
39armnn::INetworkPtr CreateSpaceToDepthNetwork(const armnn::TensorShape& inputShape,
40 const armnn::TensorShape& outputShape,
41 const armnn::DataLayout dataLayout,
42 unsigned int blockSize,
43 const float qScale = 1.0f,
44 const int32_t qOffset = 0)
45{
46 using namespace armnn;
47 // Builds up the structure of the network.
48 INetworkPtr net(INetwork::Create());
49
50 TensorInfo inputTensorInfo(inputShape, DataType, qScale, qOffset);
51
52 armnnUtils::DataLayoutIndexed dimensionIndices(dataLayout);
53 if (inputShape[dimensionIndices.GetHeightIndex()] % blockSize!=0
54 || inputShape[dimensionIndices.GetWidthIndex()] % blockSize!=0)
55 {
56 throw InvalidArgumentException("Input shape must be divisible by block size in all spatial dimensions");
57 }
58
59 SpaceToDepthDescriptor spaceToDepthDesc;
60 spaceToDepthDesc.m_BlockSize = blockSize;
61 spaceToDepthDesc.m_DataLayout = dataLayout;
62
63 IConnectableLayer* SpaceToDepth = net->AddSpaceToDepthLayer(spaceToDepthDesc, "SpaceToDepth");
64 IConnectableLayer* input = net->AddInputLayer(0, "input");
65 Connect(input, SpaceToDepth, inputTensorInfo, 0, 0);
66
67 TensorInfo outputTensorInfo(outputShape, DataType, qScale, qOffset);
68 IConnectableLayer* output = net->AddOutputLayer(0, "output");
69 Connect(SpaceToDepth, output, outputTensorInfo, 0, 0);
70
71 return net;
72}
73
74void SpaceToDepthEndToEnd(const std::vector<armnn::BackendId>& backends,
75 const armnn::DataLayout& dataLayout,
76 TensorInfo& inputTensorInfo,
77 TensorInfo& outputTensorInfo,
78 std::vector<float>& inputData,
79 std::vector<float>& expectedOutputData,
80 const unsigned int blockSize)
81{
82 using namespace armnn;
83
James Conroy60597842019-07-02 10:57:56 +010084 if (dataLayout == armnn::DataLayout::NCHW)
85 {
Keith Davis9515c7e2019-06-21 09:33:59 +010086 PermuteDataToNCHW<armnn::DataType::Float32>(backends, dataLayout, inputTensorInfo, inputData);
87 PermuteDataToNCHW<armnn::DataType::Float32>(backends, dataLayout, outputTensorInfo, expectedOutputData);
88 }
89
90 // Builds up the structure of the network
James Conroy60597842019-07-02 10:57:56 +010091 INetworkPtr net = CreateSpaceToDepthNetwork<armnn::DataType::Float32>(
92 inputTensorInfo.GetShape(),
93 outputTensorInfo.GetShape(),
94 dataLayout,
95 blockSize);
Keith Davis9515c7e2019-06-21 09:33:59 +010096
97 BOOST_TEST_CHECKPOINT("Create a network");
98
99 std::map<int, std::vector<float>> inputTensorData = { { 0, inputData } };
100 std::map<int, std::vector<float>> expectedOutputTensorData = { { 0, expectedOutputData } };
101
James Conroy60597842019-07-02 10:57:56 +0100102 EndToEndLayerTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>(
103 move(net),
104 inputTensorData,
105 expectedOutputTensorData,
106 backends);
107}
108
109void SpaceToDepthNHWCEndToEndTest1(const std::vector<armnn::BackendId>& defaultBackends)
110{
111 const unsigned int blockSize = 2;
112
113 armnn::TensorShape inputShape{1, 2, 2, 1};
114 armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32);
115
116 armnn::TensorShape outputShape{1, 1, 1, 4};
117 armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32);
118
119 std::vector<float> inputData = std::vector<float>(
120 {
121 1.0f, 2.0f, 3.0f, 4.0f
122 });
123
124 std::vector<float> expectedOutputData = std::vector<float>(
125 {
126 1.0f, 2.0f, 3.0f, 4.0f
127 });
128
129 SpaceToDepthEndToEnd(defaultBackends,
130 armnn::DataLayout::NHWC,
131 inputTensorInfo,
132 outputTensorInfo,
133 inputData,
134 expectedOutputData,
135 blockSize);
136}
137
138void SpaceToDepthNCHWEndToEndTest1(const std::vector<armnn::BackendId>& defaultBackends)
139{
140 const unsigned int blockSize = 2;
141
142 armnn::TensorShape inputShape{1, 2, 2, 1};
143 armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32);
144
145 armnn::TensorShape outputShape{1, 1, 1, 4};
146 armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32);
147
148 std::vector<float> inputData = std::vector<float>(
149 {
150 1.0f, 2.0f, 3.0f, 4.0f
151 });
152
153 std::vector<float> expectedOutputData = std::vector<float>(
154 {
155 1.0f, 2.0f, 3.0f, 4.0f
156 });
157
158 SpaceToDepthEndToEnd(defaultBackends,
159 armnn::DataLayout::NCHW,
160 inputTensorInfo,
161 outputTensorInfo,
162 inputData,
163 expectedOutputData,
164 blockSize);
165}
166
167void SpaceToDepthNHWCEndToEndTest2(const std::vector<armnn::BackendId>& defaultBackends)
168{
169 const unsigned int blockSize = 2;
170
171 armnn::TensorShape inputShape{1, 2, 2, 2};
172 armnn::TensorShape outputShape{1, 1, 1, 8};
173
174 armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32);
175 armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32);
176
177 std::vector<float> inputData = std::vector<float>(
178 {
179 1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f
180 });
181
182 std::vector<float> expectedOutputData = std::vector<float>(
183 {
184 1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f
185 });
186
187 SpaceToDepthEndToEnd(defaultBackends,
188 armnn::DataLayout::NHWC,
189 inputTensorInfo,
190 outputTensorInfo,
191 inputData,
192 expectedOutputData,
193 blockSize);
194}
195
196void SpaceToDepthNCHWEndToEndTest2(const std::vector<armnn::BackendId>& defaultBackends)
197{
198 const unsigned int blockSize = 2;
199
200 armnn::TensorShape inputShape{1, 2, 2, 2};
201 armnn::TensorShape outputShape{1, 1, 1, 8};
202
203 armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32);
204 armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32);
205
206
207 std::vector<float> inputData = std::vector<float>(
208 {
209 1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f
210 });
211
212 std::vector<float> expectedOutputData = std::vector<float>(
213 {
214 1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f
215 });
216
217 SpaceToDepthEndToEnd(defaultBackends,
218 armnn::DataLayout::NCHW,
219 inputTensorInfo,
220 outputTensorInfo,
221 inputData,
222 expectedOutputData,
223 blockSize);
Keith Davis9515c7e2019-06-21 09:33:59 +0100224}
225
226} // anonymous namespace