1 //
2 // Copyright © 2019 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #pragma once
7
8 #include <CommonTestUtils.hpp>
9
10 #include <armnnUtils/QuantizeHelper.hpp>
11 #include <ResolveType.hpp>
12
13
14 namespace
15 {
16
CreateArgMinMaxNetwork(const armnn::TensorInfo & inputTensorInfo,const armnn::TensorInfo & outputTensorInfo,armnn::ArgMinMaxFunction function,int axis)17 armnn::INetworkPtr CreateArgMinMaxNetwork(const armnn::TensorInfo& inputTensorInfo,
18 const armnn::TensorInfo& outputTensorInfo,
19 armnn::ArgMinMaxFunction function,
20 int axis)
21 {
22 armnn::INetworkPtr network(armnn::INetwork::Create());
23
24 armnn::ArgMinMaxDescriptor descriptor;
25 descriptor.m_Function = function;
26 descriptor.m_Axis = axis;
27
28 armnn::IConnectableLayer* inputLayer = network->AddInputLayer(0, "Input");
29 armnn::IConnectableLayer* argMinMaxLayer = network->AddArgMinMaxLayer(descriptor, "ArgMinMax");
30 armnn::IConnectableLayer* outputLayer = network->AddOutputLayer(0, "Output");
31
32 Connect(inputLayer, argMinMaxLayer, inputTensorInfo, 0, 0);
33 Connect(argMinMaxLayer, outputLayer, outputTensorInfo, 0, 0);
34
35 return network;
36 }
37
38 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
ArgMinMaxEndToEndImpl(const armnn::TensorShape & inputShape,const armnn::TensorShape & outputShape,const std::vector<float> & inputData,const std::vector<int32_t> & expectedOutputData,armnn::ArgMinMaxFunction function,int axis,const std::vector<armnn::BackendId> & backends)39 void ArgMinMaxEndToEndImpl(const armnn::TensorShape& inputShape,
40 const armnn::TensorShape& outputShape,
41 const std::vector<float>& inputData,
42 const std::vector<int32_t>& expectedOutputData,
43 armnn::ArgMinMaxFunction function,
44 int axis,
45 const std::vector<armnn::BackendId>& backends)
46 {
47 const float qScale = armnn::IsQuantizedType<T>() ? 2.0f : 1.0f;
48 const int32_t qOffset = armnn::IsQuantizedType<T>() ? 2 : 0;
49
50 armnn::TensorInfo inputTensorInfo(inputShape, ArmnnType, qScale, qOffset, true);
51 armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Signed32);
52
53 // quantize data
54 std::vector<T> qInputData = armnnUtils::QuantizedVector<T>(inputData, qScale, qOffset);
55
56 armnn::INetworkPtr network = CreateArgMinMaxNetwork(inputTensorInfo,
57 outputTensorInfo,
58 function,
59 axis);
60
61 EndToEndLayerTestImpl<ArmnnType, armnn::DataType::Signed32>(std::move(network),
62 { { 0, qInputData } },
63 { { 0, expectedOutputData } },
64 backends);
65 }
66
67 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
ArgMaxEndToEndSimple(const std::vector<armnn::BackendId> & backends)68 void ArgMaxEndToEndSimple(const std::vector<armnn::BackendId>& backends)
69 {
70 const armnn::TensorShape inputShape{ 1, 1, 1, 5 };
71 const armnn::TensorShape outputShape{ 1, 1, 1 };
72
73 std::vector<float> inputData({ 6.0f, 2.0f, 8.0f, 10.0f, 9.0f });
74 std::vector<int32_t> expectedOutputData({ 3 });
75
76 ArgMinMaxEndToEndImpl<ArmnnType>(inputShape,
77 outputShape,
78 inputData,
79 expectedOutputData,
80 armnn::ArgMinMaxFunction::Max,
81 -1,
82 backends);
83 }
84
85 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
ArgMinEndToEndSimple(const std::vector<armnn::BackendId> & backends)86 void ArgMinEndToEndSimple(const std::vector<armnn::BackendId>& backends)
87 {
88 const armnn::TensorShape inputShape{ 1, 1, 1, 5 };
89 const armnn::TensorShape outputShape{ 1, 1, 1 };
90
91 std::vector<float> inputData({ 6.0f, 2.0f, 8.0f, 10.0f, 9.0f });
92 std::vector<int32_t> expectedOutputData({ 1 });
93
94 ArgMinMaxEndToEndImpl<ArmnnType>(inputShape,
95 outputShape,
96 inputData,
97 expectedOutputData,
98 armnn::ArgMinMaxFunction::Min,
99 3,
100 backends);
101 }
102
103 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
ArgMaxAxis0EndToEnd(const std::vector<armnn::BackendId> & backends)104 void ArgMaxAxis0EndToEnd(const std::vector<armnn::BackendId>& backends)
105 {
106 const armnn::TensorShape inputShape{ 3, 2, 1, 4 };
107 const armnn::TensorShape outputShape{ 2, 1, 4 };
108
109 std::vector<float> inputData({ 1.0f, 2.0f, 3.0f, 4.0f,
110 8.0f, 7.0f, 6.0f, 6.0f,
111 100.0f, 20.0f, 300.0f, 40.0f,
112 500.0f, 476.0f, 450.0f, 426.0f,
113 50.0f, 60.0f, 70.0f, 80.0f,
114 10.0f, 200.0f, 30.0f, 400.0f });
115
116 std::vector<int32_t> expectedOutputData({ 1, 2, 1, 2,
117 1, 1, 1, 1 });
118
119 ArgMinMaxEndToEndImpl<ArmnnType>(inputShape,
120 outputShape,
121 inputData,
122 expectedOutputData,
123 armnn::ArgMinMaxFunction::Max,
124 0,
125 backends);
126 }
127
128 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
ArgMinAxis0EndToEnd(const std::vector<armnn::BackendId> & backends)129 void ArgMinAxis0EndToEnd(const std::vector<armnn::BackendId>& backends)
130 {
131 const armnn::TensorShape inputShape{ 3, 2, 1, 4 };
132 const armnn::TensorShape outputShape{ 2, 1, 4 };
133
134 std::vector<float> inputData({ 1.0f, 2.0f, 3.0f, 4.0f,
135 8.0f, 7.0f, 6.0f, 6.0f,
136 100.0f, 20.0f, 300.0f, 40.0f,
137 500.0f, 476.0f, 450.0f, 426.0f,
138 50.0f, 60.0f, 70.0f, 80.0f,
139 10.0f, 200.0f, 30.0f, 400.0f });
140
141 std::vector<int32_t> expectedOutputData({ 0, 0, 0, 0,
142 0, 0, 0, 0 });
143
144 ArgMinMaxEndToEndImpl<ArmnnType>(inputShape,
145 outputShape,
146 inputData,
147 expectedOutputData,
148 armnn::ArgMinMaxFunction::Min,
149 0,
150 backends);
151 }
152
153 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
ArgMaxAxis1EndToEnd(const std::vector<armnn::BackendId> & backends)154 void ArgMaxAxis1EndToEnd(const std::vector<armnn::BackendId>& backends)
155 {
156 const armnn::TensorShape inputShape{ 1, 3, 2, 4 };
157 const armnn::TensorShape outputShape{ 1, 2, 4 };
158
159 std::vector<float> inputData({ 1.0f, 2.0f, 3.0f, 4.0f,
160 8.0f, 7.0f, 6.0f, 6.0f,
161 100.0f, 20.0f, 300.0f, 40.0f,
162 500.0f, 476.0f, 450.0f, 426.0f,
163 50.0f, 60.0f, 70.0f, 80.0f,
164 10.0f, 200.0f, 30.0f, 400.0f });
165
166 std::vector<int32_t> expectedOutputData({ 1, 2, 1, 2,
167 1, 1, 1, 1 });
168
169 ArgMinMaxEndToEndImpl<ArmnnType>(inputShape,
170 outputShape,
171 inputData,
172 expectedOutputData,
173 armnn::ArgMinMaxFunction::Max,
174 1,
175 backends);
176 }
177
178 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
ArgMinAxis1EndToEnd(const std::vector<armnn::BackendId> & backends)179 void ArgMinAxis1EndToEnd(const std::vector<armnn::BackendId>& backends)
180 {
181 const armnn::TensorShape inputShape{ 1, 3, 2, 4 };
182 const armnn::TensorShape outputShape{ 1, 2, 4 };
183
184 std::vector<float> inputData({ 1.0f, 2.0f, 3.0f, 4.0f,
185 8.0f, 7.0f, 6.0f, 6.0f,
186 100.0f, 20.0f, 300.0f, 40.0f,
187 500.0f, 476.0f, 450.0f, 426.0f,
188 50.0f, 60.0f, 70.0f, 80.0f,
189 10.0f, 200.0f, 30.0f, 400.0f });
190
191 std::vector<int32_t> expectedOutputData({ 0, 0, 0, 0,
192 0, 0, 0, 0 });
193
194 ArgMinMaxEndToEndImpl<ArmnnType>(inputShape,
195 outputShape,
196 inputData,
197 expectedOutputData,
198 armnn::ArgMinMaxFunction::Min,
199 1,
200 backends);
201 }
202
203 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
ArgMaxAxis2EndToEnd(const std::vector<armnn::BackendId> & backends)204 void ArgMaxAxis2EndToEnd(const std::vector<armnn::BackendId>& backends)
205 {
206 const armnn::TensorShape inputShape{ 1, 3, 2, 4 };
207 const armnn::TensorShape outputShape{ 1, 3, 4 };
208
209 std::vector<float> inputData({ 1.0f, 2.0f, 3.0f, 4.0f,
210 8.0f, 7.0f, 6.0f, 6.0f,
211 100.0f, 20.0f, 300.0f, 40.0f,
212 500.0f, 476.0f, 450.0f, 426.0f,
213 10.0f, 200.0f, 30.0f, 400.0f,
214 50.0f, 60.0f, 70.0f, 80.0f });
215
216 std::vector<int32_t> expectedOutputData({ 1, 1, 1, 1,
217 1, 1, 1, 1,
218 1, 0, 1, 0});
219
220 ArgMinMaxEndToEndImpl<ArmnnType>(inputShape,
221 outputShape,
222 inputData,
223 expectedOutputData,
224 armnn::ArgMinMaxFunction::Max,
225 2,
226 backends);
227 }
228
229 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
ArgMinAxis2EndToEnd(const std::vector<armnn::BackendId> & backends)230 void ArgMinAxis2EndToEnd(const std::vector<armnn::BackendId>& backends)
231 {
232 const armnn::TensorShape inputShape{ 1, 3, 2, 4 };
233 const armnn::TensorShape outputShape{ 1, 3, 4 };
234
235 std::vector<float> inputData({ 1.0f, 2.0f, 3.0f, 4.0f,
236 8.0f, 7.0f, 6.0f, 6.0f,
237 100.0f, 20.0f, 300.0f, 40.0f,
238 500.0f, 476.0f, 450.0f, 426.0f,
239 10.0f, 200.0f, 30.0f, 400.0f,
240 50.0f, 60.0f, 70.0f, 80.0f });
241
242 std::vector<int32_t> expectedOutputData({ 0, 0, 0, 0,
243 0, 0, 0, 0,
244 0, 1, 0, 1 });
245
246 ArgMinMaxEndToEndImpl<ArmnnType>(inputShape,
247 outputShape,
248 inputData,
249 expectedOutputData,
250 armnn::ArgMinMaxFunction::Min,
251 2,
252 backends);
253 }
254
255 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
ArgMaxAxis3EndToEnd(const std::vector<armnn::BackendId> & backends)256 void ArgMaxAxis3EndToEnd(const std::vector<armnn::BackendId>& backends)
257 {
258 const armnn::TensorShape inputShape{ 1, 3, 2, 4 };
259 const armnn::TensorShape outputShape{ 1, 3, 2 };
260
261 std::vector<float> inputData({ 1.0f, 3.0f, 6.0f, 7.0f,
262 8.0f, 7.0f, 6.0f, 6.0f,
263 100.0f, 20.0f, 300.0f, 40.0f,
264 500.0f, 476.0f, 450.0f, 426.0f,
265 10.0f, 200.0f, 30.0f, 400.0f,
266 50.0f, 60.0f, 70.0f, 80.0f });
267
268 std::vector<int32_t> expectedOutputData({ 3, 0,
269 2, 0,
270 3, 3});
271
272 ArgMinMaxEndToEndImpl<ArmnnType>(inputShape,
273 outputShape,
274 inputData,
275 expectedOutputData,
276 armnn::ArgMinMaxFunction::Max,
277 3,
278 backends);
279 }
280
281 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
ArgMinAxis3EndToEnd(const std::vector<armnn::BackendId> & backends)282 void ArgMinAxis3EndToEnd(const std::vector<armnn::BackendId>& backends)
283 {
284 const armnn::TensorShape inputShape{ 1, 3, 2, 4 };
285 const armnn::TensorShape outputShape{ 1, 3, 2 };
286
287 std::vector<float> inputData({ 1.0f, 3.0f, 6.0f, 7.0f,
288 18.0f, 16.0f, 14.0f, 12.0f,
289 100.0f, 20.0f, 300.0f, 40.0f,
290 500.0f, 476.0f, 450.0f, 426.0f,
291 10.0f, 200.0f, 30.0f, 400.0f,
292 50.0f, 60.0f, 70.0f, 80.0f });
293
294 std::vector<int32_t> expectedOutputData({ 0, 3,
295 1, 3,
296 0, 0 });
297
298 ArgMinMaxEndToEndImpl<ArmnnType>(inputShape,
299 outputShape,
300 inputData,
301 expectedOutputData,
302 armnn::ArgMinMaxFunction::Min,
303 3,
304 backends);
305 }
306
307 } // anonymous namespace
308