IVGCVSW-3013 Add unit tests for QSymm16 LSTM
[platform/upstream/armnn.git] / src / backends / backendsCommon / test / LayerTests.cpp
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #include "LayerTests.hpp"
6 #include "WorkloadTestUtils.hpp"
7 #include "TensorUtils.hpp"
8 #include <ResolveType.hpp>
9
10 #include "test/TensorHelpers.hpp"
11 #include "TensorCopyUtils.hpp"
12 #include "Permute.hpp"
13
14 #include <boost/test/unit_test.hpp>
15 #include <boost/assert.hpp>
16
17 #include <armnn/LayerSupport.hpp>
18
19 #include <backendsCommon/CpuTensorHandle.hpp>
20 #include <backendsCommon/IBackendInternal.hpp>
21 #include <backendsCommon/WorkloadFactory.hpp>
22
23 #include <reference/workloads/RefWorkloads.hpp>
24
25 #include <algorithm>
26 #include <boost/cast.hpp>
27
28 #include "WorkloadTestUtils.hpp"
29 #include "Conv2dTestImpl.hpp"
30 #include "BatchNormTestImpl.hpp"
31 #include "ActivationTestImpl.hpp"
32 #include "Pooling2dTestImpl.hpp"
33 #include "ReshapeTestImpl.hpp"
34 #include "FullyConnectedTestImpl.hpp"
35 #include "GatherTestImpl.hpp"
36 #include "SpaceToBatchNdTestImpl.hpp"
37 #include "SplitterTestImpl.hpp"
38 #include "SoftmaxTestImpl.hpp"
39 #include "StridedSliceTestImpl.hpp"
40 #include "NormTestImpl.hpp"
41 #include "PermuteTestImpl.hpp"
42 #include "LstmTestImpl.hpp"
43 #include "ConvertFp16ToFp32TestImpl.hpp"
44 #include "ConvertFp32ToFp16TestImpl.hpp"
45 #include "DebugTestImpl.hpp"
46 #include "DequantizeTestImpl.hpp"
47 #include "QuantizeTestImpl.hpp"
48
49 // 3-channel 16x8 image used as common input data for a number of Conv2d tests.
50 static std::vector<float> ConvInput3x8x16({
51     0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
52     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
53     0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
54     0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
55     0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
56     0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
57     0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
58     0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
59     0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60     0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61     0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62     0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63     0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64     0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
65     0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
66     0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
68     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
69     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
70     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
71     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
72     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
73     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
74     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
75 });
76
77 // 2-channel bias used by a number of Conv2d tests.
78 static std::vector<float> Bias2({0, 2});
79
80 // Helper function that returns either Bias2 or an empty vector depending on whether bias is enabled.
81 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
82 boost::multi_array<T, 1> GetBias2(bool biasEnabled, float qScale, int32_t qOffset)
83 {
84     if(biasEnabled)
85     {
86         armnn::TensorInfo biasDesc({static_cast<unsigned int>(Bias2.size())}, ArmnnType);
87         boost::multi_array<T, 1> bias = MakeTensor<T, 1>(biasDesc, QuantizedVector<T>(qScale, qOffset, Bias2));
88         return bias;
89     }
90     else
91     {
92         return boost::multi_array<T, 1>();
93     }
94 }
95
96 template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T = armnn::ResolveType<ArmnnType>>
97 LayerTestResult<T, 4> SimpleConvolution2d3x5TestCommon(
98     armnn::IWorkloadFactory& workloadFactory,
99     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
100     float qScale,
101     int32_t qOffset,
102     bool biasEnabled,
103     const armnn::DataLayout layout)
104 {
105     // Use common single-batch 3-channel 16x8 image.
106     armnn::TensorInfo inputDesc({1, 3, 8, 16}, ArmnnType);
107     boost::multi_array<T, 4> input = MakeTensor<T, 4>(inputDesc, QuantizedVector<T>(qScale, qOffset, ConvInput3x8x16));
108
109     // Use a 2-element batch with 3-channel 3x5 kernels.
110     armnn::TensorInfo kernelDesc({2, 3, 5, 3}, ArmnnType);
111     boost::multi_array<T, 4> kernel = MakeTensor<T, 4>(kernelDesc, std::vector<T>(
112         QuantizedVector<T>(qScale, qOffset, {
113             1, 1, 1,
114             1, -1, 1,
115             1, 1, 1,
116             1, 1, 1,
117             1, 1, 1,
118
119             0, 0, 0,
120             0, 0, 0,
121             0, 0, 0,
122             0, 0, 0,
123             0, 0, 0,
124
125             2, 2, 2,
126             2, 2, 2,
127             2, 2, 2,
128             2, 2, 2,
129             2, 2, 2,
130
131
132             0, 0, 0,
133             0, 0, 0,
134             0, 0, 0,
135             0, 0, 0,
136             0, 0, 0,
137
138             1, 1, 1,
139             1, 1, 1,
140             1, 1, 1,
141             1, 1, 1,
142             1, 1, 1,
143
144             0, 0, 0,
145             0, 0, 0,
146             0, 0, 0,
147             0, 0, 0,
148             0, 0, 0
149         })));
150
151     // Expected output is 2 batch elements of a 1-channel 14x4 image.
152     armnn::TensorInfo outputDesc({1, 2, 4, 14}, ArmnnType);
153     boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputDesc, std::vector<T>(
154         QuantizedVector<T>(qScale, qOffset, {
155             -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
156             -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
157             -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f,
158             -23.5f, -23.5f, -23.5f,
159             -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f,
160             -23.5f, -23.5f, -23.5f,
161
162             5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
163             5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
164             5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
165             5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
166         })));
167
168     return SimpleConvolution2dTestImpl<ArmnnType, ArmnnBType>(
169         workloadFactory,
170         memoryManager,
171         input,
172         kernel,
173         GetBias2<ArmnnBType>(biasEnabled, qScale, qOffset),
174         expectedOutput,
175         qScale,
176         qOffset,
177         layout);
178 }
179
180 template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
181          typename T = armnn::ResolveType<ArmnnType>>
182 LayerTestResult<T, 4> SimpleConvolution2d3x3TestCommon(
183     armnn::IWorkloadFactory& workloadFactory,
184     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
185     float qScale,
186     int32_t qOffset,
187     bool biasEnabled,
188     const armnn::DataLayout layout)
189 {
190     // Use a 3x3 kernel, which exercises ArmCompute's direct convolution path.
191
192     // Use common single-batch 3-channel 16x8 image.
193     armnn::TensorInfo inputDesc({1, 3, 8, 16}, ArmnnType);
194     boost::multi_array<T, 4> input = MakeTensor<T, 4>(inputDesc, QuantizedVector<T>(qScale, qOffset, ConvInput3x8x16));
195
196     // Use a 2-element batch of 3-channel 3x3 kernels.
197     armnn::TensorInfo kernelDesc({2, 3, 3, 3}, ArmnnType);
198     boost::multi_array<T, 4> kernel = MakeTensor<T, 4>(kernelDesc, std::vector<T>(
199         QuantizedVector<T>(qScale, qOffset, {
200             1, 1, 1,
201             1, -1, 1,
202             1, 1, 1,
203
204             0, 0, 0,
205             0, 0, 0,
206             0, 0, 0,
207
208             2, 2, 2,
209             2, 2, 2,
210             2, 2, 2,
211
212
213             0, 0, 0,
214             0, 0, 0,
215             0, 0, 0,
216
217             1, 1, 1,
218             1, 1, 1,
219             1, 1, 1,
220
221             0, 0, 0,
222             0, 0, 0,
223             0, 0, 0
224         })));
225
226     // Expected output is 1 batch of a 2-channel 14x6 image.
227     armnn::TensorInfo outputDesc({1, 2, 6, 14}, ArmnnType);
228     boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputDesc, std::vector<T>(
229         QuantizedVector<T>(qScale, qOffset, {
230             -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
231             -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16,
232             -14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,
233             -14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,
234             -14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,
235             -14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,
236
237             3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
238             3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
239             3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
240             3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
241             3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
242             3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
243         })));
244
245     return SimpleConvolution2dTestImpl<ArmnnType, ArmnnBType>(
246         workloadFactory,
247         memoryManager,
248         input,
249         kernel,
250         GetBias2<ArmnnBType>(biasEnabled, qScale, qOffset),
251         expectedOutput,
252         qScale,
253         qOffset,
254         layout);
255 }
256
257 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
258 LayerTestResult<T, 4> SimpleConvolution2d3x3NhwcTestCommon(
259     armnn::IWorkloadFactory& workloadFactory,
260     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
261     float qScale,
262     int32_t qOffset,
263     bool biasEnabled,
264     armnn::DataLayout dataLayout)
265 {
266     // Use common single-batch 5x5 image.
267
268     armnn::TensorInfo inputDesc({1, 3, 4, 1}, ArmnnType);
269     boost::multi_array<T, 4> input = MakeTensor<T, 4>(inputDesc,
270                                                       {
271                                                        1, 5, 2, 3,
272                                                        8, 7, 3, 6,
273                                                        3, 3, 9, 1
274                                                        });
275
276
277     // Use a 2-element batch of 3-channel 3x3 kernels.
278     armnn::TensorInfo kernelDesc({1, 3, 3, 1}, ArmnnType);
279     boost::multi_array<T, 4> kernel = MakeTensor<T, 4>(kernelDesc, {
280                                                                     4, 5, 6,
281                                                                     0, 0, 0,
282                                                                     3, 2, 1
283                                                                     });
284
285     // Expected output is 1 batch of a 5x5 image.
286     armnn::TensorInfo outputDesc({1, 3, 4, 1}, ArmnnType);
287
288     const std::vector<float> outputData =
289             {
290                     23, 41, 33, 21,
291                     44, 65, 76, 52,
292                     82, 85, 79, 42
293             };
294
295     boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputDesc, outputData);
296
297     return SimpleConvolution2dNhwcTestImpl<ArmnnType, ArmnnType>(
298         workloadFactory,
299         memoryManager,
300         input,
301         kernel,
302         boost::multi_array<T, 1>(),
303         expectedOutput,
304         dataLayout,
305         qScale,
306         qOffset);
307 }
308
309 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
310 LayerTestResult<T, 4> SimpleConvolution2d3x3Stride2x2TestCommon(
311         armnn::IWorkloadFactory& workloadFactory,
312         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
313         float qScale,
314         int32_t qOffset,
315         bool biasEnabled,
316         const armnn::DataLayout& dataLayout)
317 {
318     // Input is a single-batch, 1 channel, 5x5 image.
319     armnn::TensorInfo inputDesc({1, 5, 5, 1}, ArmnnType);
320     boost::multi_array<T, 4> input = MakeTensor<T, 4>(inputDesc,
321             {
322                 1, 5, 2, 3, 5,
323                 8, 7, 3, 6, 3,
324                 3, 3, 9, 1, 9,
325                 4, 1, 8, 1, 3,
326                 6, 8, 1, 9, 2
327             });
328
329     // Use a 3x3 kernel.
330     armnn::TensorInfo kernelDesc({1, 3, 3, 1}, ArmnnType);
331     boost::multi_array<T, 4> kernel = MakeTensor<T, 4>(kernelDesc,
332             {
333                 4, 5, 6,
334                 0, 0, 0,
335                 3, 2, 1
336             });
337
338     // Expected output is a single-batch, 1 channel, 3x3 image.
339     armnn::TensorInfo outputDesc({1, 3, 3, 1}, ArmnnType);
340
341     const std::vector<T> outputData =
342             {
343                 23, 33, 24,
344                 91, 99, 48,
345                 26, 50, 19
346             };
347
348     boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputDesc, outputData);
349
350     uint32_t padLeft = 1;
351     uint32_t padTop = 1;
352     uint32_t padRight = 1;
353     uint32_t padBottom = 1;
354     uint32_t strideX  = 2;
355     uint32_t strideY  = 2;
356
357     return SimpleConvolution2dNhwcTestImpl<ArmnnType, ArmnnType>(
358         workloadFactory,
359         memoryManager,
360         input,
361         kernel,
362         boost::multi_array<T, 1>(),
363         expectedOutput,
364         dataLayout,
365         qScale,
366         qOffset,
367         padLeft,
368         padTop,
369         padRight,
370         padBottom,
371         strideX,
372         strideY);
373 }
374
375 LayerTestResult<float, 4> SimpleConvolution2d3x5Test(
376     armnn::IWorkloadFactory& workloadFactory,
377     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
378     bool biasEnabled,
379     const armnn::DataLayout layout)
380 {
381     return SimpleConvolution2d3x5TestCommon<armnn::DataType::Float32, armnn::DataType::Float32>(
382         workloadFactory, memoryManager, 0.f, 0, biasEnabled, layout);
383 }
384
385 LayerTestResult<uint8_t, 4> SimpleConvolution2d3x5Uint8Test(
386     armnn::IWorkloadFactory& workloadFactory,
387     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
388     bool biasEnabled,
389     const armnn::DataLayout layout)
390 {
391     return SimpleConvolution2d3x5TestCommon<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>(
392         workloadFactory, memoryManager, 0.5f, 50, biasEnabled, layout);
393 }
394
395 LayerTestResult<float, 4> SimpleConvolution2d3x3Test(
396     armnn::IWorkloadFactory& workloadFactory,
397     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
398     bool biasEnabled,
399     const armnn::DataLayout layout)
400 {
401     return SimpleConvolution2d3x3TestCommon<armnn::DataType::Float32, armnn::DataType::Float32>(
402         workloadFactory, memoryManager, 0.f, 0, biasEnabled, layout);
403 }
404
405 LayerTestResult<float, 4> SimpleConvolution2d3x3NhwcTest(
406     armnn::IWorkloadFactory& workloadFactory,
407     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
408     bool biasEnabled)
409 {
410     return SimpleConvolution2d3x3NhwcTestCommon<armnn::DataType::Float32>(
411         workloadFactory,
412         memoryManager,
413         0.f,
414         0,
415         biasEnabled,
416         armnn::DataLayout::NHWC);
417 }
418
419 LayerTestResult<float, 4> SimpleConvolution2d3x3Stride2x2Test(
420         armnn::IWorkloadFactory& workloadFactory,
421         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
422         bool biasEnabled,
423         const armnn::DataLayout layout)
424 {
425     return SimpleConvolution2d3x3Stride2x2TestCommon<armnn::DataType::Float32>(
426         workloadFactory,
427         memoryManager,
428         0.f,
429         0,
430         biasEnabled,
431         layout);
432 }
433
434 LayerTestResult<uint8_t, 4> SimpleConvolution2d3x3Uint8Test(
435     armnn::IWorkloadFactory& workloadFactory,
436     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
437     bool biasEnabled,
438     const armnn::DataLayout layout)
439 {
440     return SimpleConvolution2d3x3TestCommon<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>(
441         workloadFactory, memoryManager, 0.5f, 50, biasEnabled, layout);
442 }
443
444 template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
445          typename T = armnn::ResolveType<ArmnnType>>
446 LayerTestResult<T, 4> Convolution2dAsymmetricPaddingLargerThanHalfKernelSizeTestCommon(
447     armnn::IWorkloadFactory& workloadFactory,
448     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
449     const armnn::DataLayout layout,
450     float qScale,
451     int32_t qOffset)
452 {
453     // Use a single-batch 1-channel 3x3 image as input.
454     armnn::TensorInfo inputDesc({1, 1, 3, 3}, ArmnnType);
455     boost::multi_array<T, 4> input = MakeTensor<T, 4>(inputDesc, std::vector<T>(
456         QuantizedVector<T>(qScale, qOffset, {
457             11,21,31,
458             12,22,32,
459             13,23,33
460         })));
461
462     // Use 1 batch of a 1-channel 2x2 kernel.
463     armnn::TensorInfo kernelDesc({1, 1, 2, 2}, ArmnnType);
464     boost::multi_array<T, 4> kernel = MakeTensor<T, 4>(kernelDesc, std::vector<T>(
465         QuantizedVector<T>(qScale, qOffset, {
466             -11,-21,
467             -12,-22,
468         })));
469
470 // Expected output is 1 batch of a 1-channel 6x8 image.
471 // Manually calculated like this:
472 //[-11*0 -21*0  -12*0 -22*0  ; -11*0  -21*0  -12*0  -22*0  ; -11*0  -21*0  -12*0  -22*0  ; -11*0  -21*0 -12*0  -22*0 ..]
473 //[-11*0 -21*0  -12*0 -22*11 ; -11*0  -21*0  -12*11 -22*21 ; -11*0  -21*0  -12*21 -22*31 ; -11*0  -21*0 -12*31 -22*0 ..]
474 //[-11*0 -21*11 -12*0 -22*12 ; -11*11 -21*21 -12*12 -22*22 ; -11*21 -21*31 -12*22 -22*32 ; -11*31 -21*0 -12*32 -22*0 ..]
475 //[-11*0 -21*12 -12*0 -22*13 ; -11*12 -21*22 -12*13 -22*23 ; -11*22 -21*32 -12*23 -22*33 ; -11*32 -21*0 -12*33 -22*0 ..]
476 //[-11*0 -21*13 -12*0 -22*0  ; -11*13 -21*23 -12*0  -22*0  ; -11*23 -21*33 -12*0  -22*0  ; -11*33 -21*0 -12*0  -22*0 ..]
477 //[-11*0 -21*0  -12*0 -22*0  ; -11*0  -21*0  -12*0  -22*0  ; -11*0  -21*0  -12*0  -22*0  ; -11*0  -21*0 -12*0  -22*0 ..]
478 //[..... .....  ..... .....  ; .....  .....  .....  .....  ; .....  .....  .....  .....  ; .....  ..... .....  ..... ..]
479     armnn::TensorInfo outputDesc({1, 1, 8, 6}, ArmnnType);
480     boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputDesc, std::vector<T>(
481         QuantizedVector<T>(qScale, qOffset, {
482                0,    0,      0,    0,    0,    0,
483             -242,  -594,  -934, -372,    0,    0,
484             -495, -1190, -1850, -725,    0,    0,
485             -538, -1256, -1916, -748,    0,    0,
486             -273, -626,  -946,  -363,    0,    0,
487                0,    0,     0,     0,    0,    0,
488                0,    0,     0,     0,    0,    0,
489                0,    0,     0,     0,    0,    0
490         })));
491
492     return SimpleConvolution2dTestImpl<ArmnnType, ArmnnBType>(
493         workloadFactory,
494         memoryManager,
495         input,
496         kernel,
497         GetBias2<ArmnnBType>(false, qScale, qOffset),
498         expectedOutput,
499         qScale,
500         qOffset,
501         layout,
502         1,  // Padding left.
503         2,  // Padding top.
504         3,  // Padding right.
505         4); // Padding bottom.
506 }
507
508 template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
509          typename T = armnn::ResolveType<ArmnnType>>
510 LayerTestResult<T, 4> SimpleConvolution2dAsymmetricPaddingTestCommon(
511     armnn::IWorkloadFactory& workloadFactory,
512     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
513     const armnn::DataLayout layout,
514     float qScale,
515     int32_t qOffset)
516 {
517     // Use a single-batch 1-channel 5x5 image as input.
518     armnn::TensorInfo inputDesc({ 1, 1, 5, 5 }, ArmnnType);
519     boost::multi_array<T, 4> input = MakeTensor<T, 4>(inputDesc, std::vector<T>(
520         QuantizedVector<T>(qScale, qOffset, {
521             11,21,31,41,51,
522             12,22,32,42,52,
523             13,23,33,43,53,
524             14,24,34,44,54,
525             15,25,35,45,55,
526         })));
527
528     // Use 1 batch of a 1-channel 4x4 kernel.
529     armnn::TensorInfo kernelDesc({ 1, 1, 4, 4 }, ArmnnType);
530     boost::multi_array<T, 4> kernel = MakeTensor<T, 4>(kernelDesc, std::vector<T>(
531         QuantizedVector<T>(qScale, qOffset, {
532             -11,-21,-31,-41,
533             -12,-22,-32,-42,
534             -13,-23,-33,-43,
535             -14,-24,-34,-44,
536         })));
537
538     // Expected output is 1 batch of a 1-channel 5x5 image.
539     armnn::TensorInfo outputDesc({ 1, 1, 5, 5 }, ArmnnType);
540     std::vector<T> myVec(outputDesc.GetNumElements(), 0);
541     boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputDesc, std::vector<T>(
542         QuantizedVector<T>(qScale, qOffset, {
543             -7140, -10580, -13940,  -9300, -5230,
544             -9590, -14120, -18520, -12290, -6860,
545             -9980, -14560, -18960, -12560, -7000,
546             -7518, -10904, -14144,  -9318, -5152,
547             -5032,  -7256,  -9376,  -6142, -3368,
548         })));
549
550     return SimpleConvolution2dTestImpl<ArmnnType, ArmnnBType>(
551         workloadFactory,
552         memoryManager,
553         input,
554         kernel,
555         GetBias2<ArmnnBType>(false, qScale, qOffset),
556         expectedOutput,
557         qScale,
558         qOffset,
559         layout,
560         1,  // Padding left.
561         1,  // Padding top.
562         2,  // Padding right.
563         2); // Padding bottom.
564 }
565
566 template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
567          typename T = armnn::ResolveType<ArmnnType>>
568 LayerTestResult<T, 4> DepthwiseConvolution2dAsymmetricTestCommon(
569     armnn::IWorkloadFactory& workloadFactory,
570     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
571     float qScale,
572     int32_t qOffset,
573     bool biasEnabled,
574     const armnn::DataLayout layout)
575 {
576     // Use a single-batch 2-channel 5x5 image as input.
577     armnn::TensorInfo inputTensorInfo({ 1, 2, 5, 5 }, ArmnnType);
578     auto input = MakeTensor<T, 4>(inputTensorInfo, std::vector<T>(
579         QuantizedVector<T>(inputTensorInfo.GetQuantizationScale(), inputTensorInfo.GetQuantizationOffset(), {
580              0,  1,  2,  3,  4,
581              5,  6,  7,  8,  9,
582             10, 11, 12, 13, 14,
583             15, 16, 17, 18, 19,
584             20, 21, 22, 23, 24,
585
586             25, 26, 27, 28, 29,
587             30, 31, 32, 33, 34,
588             35, 36, 37, 38, 39,
589             40, 41, 42, 43, 44,
590             45, 46, 47, 48, 49
591         })));
592
593     // Use a depth multiplier of 1 on a 2-channel 4x4 kernel.
594     armnn::TensorInfo kernelTensorInfo({ 1, 2, 4, 4 }, ArmnnType);
595     auto kernel = MakeTensor<T, 4>(kernelTensorInfo, std::vector<T>(
596         QuantizedVector<T>(kernelTensorInfo.GetQuantizationScale(), kernelTensorInfo.GetQuantizationOffset(), {
597             32, 31, 30, 29,
598             28, 27, 26, 25,
599             24, 23, 22, 21,
600             20, 19, 18, 17,
601
602             16, 15, 14, 13,
603             12, 11, 10,  9,
604              8,  7,  6,  5,
605              4,  3,  2,  1
606         })));
607
608     // Expected output is 1 batch of a 2-channel 5x5 image.
609     // Calculated using the python tensorflow library with strideX=1, strideY=1.
610     armnn::TensorInfo outputTensorInfo({ 1, 2, 5, 5 }, ArmnnType);
611     boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputTensorInfo, std::vector<T>(
612         QuantizedVector<T>(outputTensorInfo.GetQuantizationScale(), outputTensorInfo.GetQuantizationOffset(), {
613             1062, 1580, 1850, 1530, 1117,
614             2140, 3108, 3500, 2842, 2042,
615             3580, 5068, 5460, 4342, 3062,
616             3618, 5072, 5390, 4248, 2971,
617             3074, 4282, 4510, 3533, 2457,
618             1550, 2284, 2362, 1955, 1428,
619             2910, 4206, 4342, 3528, 2536,
620             3390, 4886, 5022, 4068, 2916,
621             3566, 5056, 5182, 4133, 2922,
622             3100, 4352, 4452, 3517, 2465
623         })));
624
625     return DepthwiseConvolution2dAsymmetricTestImpl<ArmnnType, ArmnnBType>(
626         workloadFactory,
627         memoryManager,
628         input,
629         kernel,
630         GetBias2<ArmnnBType>(biasEnabled, qScale, qOffset),
631         expectedOutput,
632         qScale,
633         qOffset,
634         layout,
635         1,  // Padding left.
636         1,  // Padding top.
637         2,  // Padding right.
638         2,  // Padding bottom.
639         1,  // strideX
640         1); // strideY
641 }
642
643 template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
644          typename T = armnn::ResolveType<ArmnnType>>
645 LayerTestResult<T, 4> DepthwiseConvolution2dNhwcTestCommon(
646     armnn::IWorkloadFactory& workloadFactory,
647     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
648     float qScale,
649     int32_t qOffset,
650     bool biasEnabled)
651 {
652     armnn::TensorInfo inputTensorInfo({ 1, 5, 5, 2}, ArmnnType);
653     auto input = MakeTensor<T, 4>(inputTensorInfo, std::vector<T>(
654         QuantizedVector<T>(inputTensorInfo.GetQuantizationScale(), inputTensorInfo.GetQuantizationOffset(), {
655             0, 25,
656             1, 26,
657             2, 27,
658             3, 28,
659             4, 29,
660
661             5, 30,
662             6, 31,
663             7, 32,
664             8, 33,
665             9, 34,
666
667             10, 35,
668             11, 36,
669             12, 37,
670             13, 38,
671             14, 39,
672
673             15, 40,
674             16, 41,
675             17, 42,
676             18, 43,
677             19, 44,
678
679             20, 45,
680             21, 46,
681             22, 47,
682             23, 48,
683             24, 49
684         })));
685
686     armnn::TensorInfo kernelTensorInfo({ 1, 2, 4, 4 }, ArmnnType);
687     auto kernel = MakeTensor<T, 4>(kernelTensorInfo, std::vector<T>(
688         QuantizedVector<T>(kernelTensorInfo.GetQuantizationScale(), kernelTensorInfo.GetQuantizationOffset(), {
689              32, 31, 30, 29,
690              28, 27, 26, 25,
691              24, 23, 22, 21,
692              20, 19, 18, 17,
693
694              16, 15, 14, 13,
695              12, 11, 10,  9,
696               8,  7,  6,  5,
697               4,  3,  2,  1
698         })));
699
700     armnn::TensorInfo outputTensorInfo({ 1, 5, 5, 2}, ArmnnType);
701     boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputTensorInfo, std::vector<T>(
702         QuantizedVector<T>(outputTensorInfo.GetQuantizationScale(), outputTensorInfo.GetQuantizationOffset(), {
703         1062, 1550,
704         1580, 2284,
705         1850, 2362,
706         1530, 1955,
707         1117, 1428,
708
709         2140, 2910,
710         3108, 4206,
711         3500, 4342,
712         2842, 3528,
713         2042, 2536,
714
715         3580, 3390,
716         5068, 4886,
717         5460, 5022,
718         4342, 4068,
719         3062, 2916,
720
721         3618, 3566,
722         5072, 5056,
723         5390, 5182,
724         4248, 4133,
725         2971, 2922,
726
727         3074, 3100,
728         4282, 4352,
729         4510, 4452,
730         3533, 3517,
731         2457, 2465
732         })));
733
734     return DepthwiseConvolution2dNhwcTestImpl<ArmnnType, ArmnnBType>(
735         workloadFactory,
736         memoryManager,
737         input,
738         kernel,
739         GetBias2<ArmnnBType>(biasEnabled, qScale, qOffset),
740         expectedOutput,
741         qScale,
742         qOffset,
743         1,  // Padding left.
744         1,  // Padding top.
745         2,  // Padding right.
746         2,  // Padding bottom.
747         1,  // strideX
748         1);  // strideY
749 }
750
751 LayerTestResult<float, 4>
752 Convolution2dAsymmetricPaddingLargerThanHalfKernelSizeTest(
753     armnn::IWorkloadFactory& workloadFactory,
754     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
755     const armnn::DataLayout layout)
756 {
757     return Convolution2dAsymmetricPaddingLargerThanHalfKernelSizeTestCommon
758         <armnn::DataType::Float32, armnn::DataType::Float32>(
759             workloadFactory, memoryManager, layout, 0.0f, 0);
760 }
761
762 LayerTestResult<float, 4> Convolution2dAsymmetricPaddingTest(
763     armnn::IWorkloadFactory& workloadFactory,
764     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
765     const armnn::DataLayout layout)
766 {
767     return SimpleConvolution2dAsymmetricPaddingTestCommon<armnn::DataType::Float32, armnn::DataType::Float32>(
768         workloadFactory, memoryManager, layout, 0.0f, 0);
769 }
770
771 LayerTestResult<float, 4> DepthwiseConvolution2dTest(
772     armnn::IWorkloadFactory& workloadFactory,
773     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
774     bool biasEnabled,
775     const armnn::DataLayout layout)
776 {
777     return DepthwiseConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>(
778         workloadFactory, memoryManager, 0.0f, 0, biasEnabled, layout);
779 }
780
781 LayerTestResult<float, 4> DepthwiseConvolution2dDepthNhwcTest(
782     armnn::IWorkloadFactory& workloadFactory,
783     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
784     bool biasEnabled)
785 {
786     return DepthwiseConvolution2dNhwcTestCommon<armnn::DataType::Float32, armnn::DataType::Float32>(
787         workloadFactory, memoryManager, 0.0f, 0, biasEnabled);
788 }
789
790 LayerTestResult<float, 4> DepthwiseConvolution2dDepthMul1Test(
791     armnn::IWorkloadFactory& workloadFactory,
792     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
793     bool biasEnabled,
794     const armnn::DataLayout layout)
795 {
796     return DepthwiseConvolution2dDepthMul1TestImpl<armnn::DataType::Float32, armnn::DataType::Float32>(
797         workloadFactory, memoryManager, 0.0f, 0, biasEnabled, layout);
798 }
799
800 LayerTestResult<float, 4> DepthwiseConvolution2dAsymmetricTest(
801     armnn::IWorkloadFactory& workloadFactory,
802     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
803     bool biasEnabled,
804     const armnn::DataLayout layout)
805 {
806     return DepthwiseConvolution2dAsymmetricTestCommon<armnn::DataType::Float32, armnn::DataType::Float32>(
807         workloadFactory, memoryManager, 0.0f, 0, biasEnabled, layout);
808 }
809
810 LayerTestResult<uint8_t, 4> DepthwiseConvolution2dUint8Test(
811     armnn::IWorkloadFactory& workloadFactory,
812     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
813     bool biasEnabled,
814     const armnn::DataLayout layout)
815 {
816     return DepthwiseConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>(
817         workloadFactory, memoryManager, 0.5f, 50, biasEnabled, layout);
818 }
819
820 LayerTestResult<uint8_t, 4> DepthwiseConvolution2dDepthMul1Uint8Test(
821     armnn::IWorkloadFactory& workloadFactory,
822     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
823     bool biasEnabled,
824     const armnn::DataLayout layout)
825 {
826     return DepthwiseConvolution2dDepthMul1TestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>(
827         workloadFactory, memoryManager, 0.5f, 50, biasEnabled, layout);
828 }
829
830 LayerTestResult<float, 4> Convolution1dTest(
831     armnn::IWorkloadFactory& workloadFactory,
832     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
833     bool biasEnabled)
834 {
835     return Convolution1dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>(
836         workloadFactory, memoryManager, 0.0f, 0, biasEnabled);
837 }
838
839 LayerTestResult<uint8_t, 4> Convolution1dUint8Test(
840     armnn::IWorkloadFactory& workloadFactory,
841     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
842     bool biasEnabled)
843 {
844     return Convolution1dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>(
845         workloadFactory, memoryManager, 0.1f, 128, biasEnabled);
846 }
847
848 LayerTestResult<float,4> CompareConvolution2dTest(
849     armnn::IWorkloadFactory& workloadFactory,
850     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
851     armnn::IWorkloadFactory& refWorkloadFactory)
852 {
853     return CompareConvolution2dTestImpl<armnn::DataType::Float32>(
854         workloadFactory, memoryManager, refWorkloadFactory);
855 }
856
857 LayerTestResult<float, 4> CompareDepthwiseConvolution2dFloatTest(
858     armnn::IWorkloadFactory& workloadFactory,
859     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
860     armnn::IWorkloadFactory& refWorkloadFactory,
861     const armnn::DataLayout layout)
862 {
863     return CompareDepthwiseConvolution2dTestImpl<armnn::DataType::Float32>(
864         workloadFactory, memoryManager, refWorkloadFactory, layout);
865 }
866
867 LayerTestResult<uint8_t, 4> CompareDepthwiseConvolution2dUint8Test(
868     armnn::IWorkloadFactory& workloadFactory,
869     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
870     armnn::IWorkloadFactory& refWorkloadFactory,
871     const armnn::DataLayout layout)
872 {
873     return CompareDepthwiseConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8>(
874         workloadFactory, memoryManager, refWorkloadFactory, layout);
875 }
876
877 LayerTestResult<float,4> SimpleNormalizationAcrossTest(
878     armnn::IWorkloadFactory& workloadFactory,
879     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
880 {
881     auto normMethod = armnn::NormalizationAlgorithmMethod::LocalBrightness;
882     auto normChannel = armnn::NormalizationAlgorithmChannel::Across;
883     return SimpleNormalizationTestImpl(workloadFactory, memoryManager, normChannel, normMethod);
884 }
885
886 LayerTestResult<float,4> SimpleNormalizationWithinTest(
887     armnn::IWorkloadFactory& workloadFactory,
888     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
889 {
890     auto normMethod = armnn::NormalizationAlgorithmMethod::LocalBrightness;
891     auto normChannel = armnn::NormalizationAlgorithmChannel::Within;
892     return SimpleNormalizationTestImpl(workloadFactory, memoryManager, normChannel, normMethod);
893 }
894
895 LayerTestResult<float,4> SimpleNormalizationAcrossNhwcTest(
896     armnn::IWorkloadFactory& workloadFactory,
897     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
898 {
899     auto normMethod = armnn::NormalizationAlgorithmMethod::LocalBrightness;
900     auto normChannel = armnn::NormalizationAlgorithmChannel::Across;
901     return SimpleNormalizationNhwcTestImpl(workloadFactory, memoryManager, normChannel, normMethod);
902 }
903
904 LayerTestResult<float,2> SimpleSoftmaxTest(
905     armnn::IWorkloadFactory& workloadFactory,
906     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
907     float beta)
908 {
909     return SimpleSoftmaxTestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, beta);
910 }
911
912 LayerTestResult<float,3> Simple3dSoftmaxTest(
913         armnn::IWorkloadFactory& workloadFactory,
914         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
915         float beta)
916 {
917     return Simple3dSoftmaxTestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, beta);
918 }
919
920 LayerTestResult<float,4> Simple4dSoftmaxTest(
921         armnn::IWorkloadFactory& workloadFactory,
922         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
923         float beta)
924 {
925     return Simple4dSoftmaxTestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, beta);
926 }
927
928 LayerTestResult<uint8_t,2> SimpleSoftmaxUint8Test(
929     armnn::IWorkloadFactory& workloadFactory,
930     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
931     float beta)
932 {
933     return SimpleSoftmaxTestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, beta);
934 }
935
936 LayerTestResult<uint8_t,3> Simple3dSoftmaxUint8Test(
937         armnn::IWorkloadFactory& workloadFactory,
938         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
939         float beta)
940 {
941     return Simple3dSoftmaxTestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, beta);
942 }
943
944 LayerTestResult<uint8_t,4> Simple4dSoftmaxUint8Test(
945         armnn::IWorkloadFactory& workloadFactory,
946         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
947         float beta)
948 {
949     return Simple4dSoftmaxTestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, beta);
950 }
951
952 LayerTestResult<float,4> CompareNormalizationTest(
953     armnn::IWorkloadFactory& workloadFactory,
954     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
955     armnn::IWorkloadFactory& refWorkloadFactory,
956     armnn::NormalizationAlgorithmChannel normChannel,
957     armnn::NormalizationAlgorithmMethod normMethod)
958 {
959     return CompareNormalizationTestImpl(workloadFactory, memoryManager, refWorkloadFactory, normChannel, normMethod);
960 }
961
962 LayerTestResult<float,2> CompareSoftmaxTest(
963     armnn::IWorkloadFactory& workloadFactory,
964     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
965     armnn::IWorkloadFactory& refWorkloadFactory,
966     float beta)
967 {
968     return CompareSoftmaxTestImpl<armnn::DataType::Float32>(
969         workloadFactory, memoryManager, refWorkloadFactory, beta);
970 }
971
972 LayerTestResult<uint8_t,2> CompareSoftmaxUint8Test(
973     armnn::IWorkloadFactory& workloadFactory,
974     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
975     armnn::IWorkloadFactory& refWorkloadFactory,
976     float beta)
977 {
978     return CompareSoftmaxTestImpl<armnn::DataType::QuantisedAsymm8>(
979         workloadFactory, memoryManager, refWorkloadFactory, beta);
980 }
981
982 std::vector<LayerTestResult<float,3>> SplitterTest(
983     armnn::IWorkloadFactory& workloadFactory,
984     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
985 {
986     return SplitterTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
987 }
988
989 std::vector<LayerTestResult<uint8_t,3>> SplitterUint8Test(
990     armnn::IWorkloadFactory& workloadFactory,
991     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
992 {
993     return SplitterTestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 1.0f, 0);
994 }
995
996 LayerTestResult<float, 3> CopyViaSplitterTest(
997     armnn::IWorkloadFactory& workloadFactory,
998     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
999 {
1000     return CopyViaSplitterTestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
1001 }
1002
1003 LayerTestResult<uint8_t, 3> CopyViaSplitterUint8Test(
1004     armnn::IWorkloadFactory& workloadFactory,
1005     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1006 {
1007     return CopyViaSplitterTestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 1.0f, 0);
1008 }
1009
1010 LayerTestResult<float, 2> LstmLayerFloat32WithCifgWithPeepholeNoProjectionTest(
1011     armnn::IWorkloadFactory& workloadFactory,
1012     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1013 {
1014     armnn::TensorInfo inputDesc({ 2, 2 }, armnn::DataType::Float32);
1015     boost::multi_array<float, 2> input = MakeTensor<float, 2>(inputDesc, std::vector<float>(
1016             { 2., 3., 3., 4. }));
1017
1018     armnn::TensorInfo outputDesc({ 2, 4 }, armnn::DataType::Float32);
1019     boost::multi_array<float, 2> expectedOutput = MakeTensor<float, 2>(outputDesc, std::vector<float>(
1020             {-0.36444446f, -0.00352185f, 0.12886585f, -0.05163646f,
1021              -0.42734814f, -0.00478661f,  0.13455015f, -0.03560682f}));
1022     return LstmLayerWithCifgWithPeepholeNoProjectionTestImpl<armnn::DataType::Float32>(
1023         workloadFactory, memoryManager, input, expectedOutput);
1024 }
1025
1026 LayerTestResult<float, 2> LstmLayerFloat32NoCifgWithPeepholeWithProjectionTest(
1027     armnn::IWorkloadFactory& workloadFactory,
1028     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1029 {
1030     armnn::TensorInfo inputDesc({ 2, 5 }, armnn::DataType::Float32);
1031     boost::multi_array<float, 2> input = MakeTensor<float, 2>(inputDesc, std::vector<float>(
1032             {0.787926f, 0.151646f, 0.071352f, 0.118426f, 0.458058f,
1033              0.295743f, 0.544053f, 0.690064f, 0.858138f, 0.497181f}));
1034
1035     armnn::TensorInfo outputDesc({ 2, 16 }, armnn::DataType::Float32);
1036     boost::multi_array<float, 2> expectedOutput = MakeTensor<float, 2>(outputDesc, std::vector<float>(
1037             {-0.00396806f, 0.029352f,     -0.00279226f, 0.0159977f,   -0.00835576f,
1038              -0.0211779f,  0.0283512f,    -0.0114597f,  0.00907307f,  -0.0244004f,
1039              -0.0152191f,  -0.0259063f,   0.00914318f,  0.00415118f,  0.017147f,
1040              0.0134203f, -0.013869f,    0.0287268f,   -0.00334693f, 0.00733398f,  -0.0287926f,
1041              -0.0186926f,   0.0193662f,   -0.0115437f,  0.00422612f,  -0.0345232f,
1042              0.00223253f,   -0.00957321f, 0.0210624f,   0.013331f,    0.0150954f,
1043              0.02168f}));
1044     return LstmLayerNoCifgWithPeepholeWithProjectionTestImpl<armnn::DataType::Float32>(
1045         workloadFactory, memoryManager, input, expectedOutput);
1046 }
1047
1048 LayerTestResult<float, 2> LstmLayerFloat32NoCifgNoPeepholeNoProjectionTest(
1049     armnn::IWorkloadFactory& workloadFactory,
1050     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1051 {
1052     armnn::TensorInfo inputDesc({2, 2}, armnn::DataType::Float32);
1053     boost::multi_array<float, 2> input = MakeTensor<float, 2>(inputDesc, std::vector<float>(
1054             {2., 3., 3., 4.}));
1055
1056
1057     armnn::TensorInfo outputDesc({2, 4}, armnn::DataType::Float32);
1058     boost::multi_array<float, 2> expectedOutput = MakeTensor<float, 2>(outputDesc, std::vector<float>(
1059             {{-0.02973187f, 0.1229473f,   0.20885126f, -0.15358765f,
1060               -0.0185422f,   0.11281417f,  0.24466537f, -0.1826292f}}));
1061
1062     return LstmNoCifgNoPeepholeNoProjectionTestImpl<armnn::DataType::Float32>(
1063         workloadFactory, memoryManager, input, expectedOutput);
1064 }
1065
1066 LayerTestResult<int16_t, 2> LstmLayerInt16NoCifgNoPeepholeNoProjectionTest(
1067     armnn::IWorkloadFactory& workloadFactory,
1068     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1069 {
1070     const float qScale = 1.0f;
1071     const int32_t qOffset = 0;
1072
1073     const armnn::DataType datatype = armnn::DataType::QuantisedSymm16;
1074     const armnn::DataType constantDatatype = armnn::DataType::QuantisedAsymm8;
1075
1076     armnn::TensorInfo inputDesc({2, 2}, datatype);
1077     boost::multi_array<int16_t , 2> input = MakeTensor<int16_t , 2>(inputDesc, QuantizedVector<int16_t>(qScale, qOffset,
1078             std::vector<float>{2., 3., 3., 4.}));
1079
1080     armnn::TensorInfo outputDesc({2, 4}, datatype);
1081     boost::multi_array<int16_t, 2> expectedOutput = MakeTensor<int16_t, 2>(outputDesc, QuantizedVector<int16_t>(qScale,
1082             qOffset, std::vector<float>({{-0.02973187f, 0.1229473f,   0.20885126f, -0.15358765f,
1083                                           -0.0185422f,  0.11281417f,  0.24466537f, -0.1826292f}})));
1084
1085     return LstmNoCifgNoPeepholeNoProjectionTestImpl<datatype>(
1086         workloadFactory, memoryManager, input, expectedOutput, qScale, qOffset, constantDatatype);
1087
1088 }
1089
1090 LayerTestResult<int16_t, 2> LstmLayerInt16WithCifgWithPeepholeNoProjectionTest(
1091     armnn::IWorkloadFactory& workloadFactory,
1092     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1093 {
1094     const float qScale = 1.0f;
1095     const int32_t qOffset = 0;
1096
1097     const armnn::DataType datatype = armnn::DataType::QuantisedSymm16;
1098     const armnn::DataType constantDatatype = armnn::DataType::QuantisedAsymm8;
1099
1100     armnn::TensorInfo inputDesc({ 2, 2 }, datatype);
1101     boost::multi_array<int16_t, 2> input = MakeTensor<int16_t, 2>(inputDesc, QuantizedVector<int16_t>(qScale, qOffset,
1102             std::vector<float>({ 2., 3., 3., 4. })));
1103
1104     armnn::TensorInfo outputDesc({ 2, 4 }, datatype);
1105     boost::multi_array<int16_t, 2> expectedOutput = MakeTensor<int16_t, 2>(outputDesc, QuantizedVector<int16_t>(qScale,
1106             qOffset, std::vector<float>(
1107             {-0.36444446f, -0.00352185f, 0.12886585f, -0.05163646f,
1108              -0.42734814f, -0.00478661f, 0.13455015f, -0.03560682f})));
1109
1110     return LstmLayerWithCifgWithPeepholeNoProjectionTestImpl<datatype>(
1111         workloadFactory, memoryManager, input, expectedOutput, qScale, qOffset, constantDatatype);
1112 }
1113
1114 LayerTestResult<int16_t, 2> LstmLayerInt16NoCifgWithPeepholeWithProjectionTest(
1115     armnn::IWorkloadFactory& workloadFactory,
1116     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1117 {
1118     const float qScale = 2.0f;
1119     const int32_t qOffset = 0;
1120
1121     const armnn::DataType datatype = armnn::DataType::QuantisedSymm16;
1122     const armnn::DataType constantDatatype = armnn::DataType::QuantisedAsymm8;
1123
1124     armnn::TensorInfo inputDesc({ 2, 5 }, datatype);
1125     boost::multi_array<int16_t, 2> input = MakeTensor<int16_t, 2>(inputDesc, QuantizedVector<int16_t>(qScale,
1126             qOffset, std::vector<float>(
1127             {0.787926f, 0.151646f, 0.071352f, 0.118426f, 0.458058f,
1128              0.295743f, 0.544053f, 0.690064f, 0.858138f, 0.497181f})));
1129
1130     armnn::TensorInfo outputDesc({ 2, 16 }, datatype);
1131     boost::multi_array<int16_t, 2> expectedOutput = MakeTensor<int16_t, 2>(outputDesc, QuantizedVector<int16_t>(qScale,
1132             qOffset, std::vector<float>(
1133             {-0.00396806f,  0.029352f,   -0.00279226f, 0.0159977f,  -0.00835576f,
1134              -0.0211779f,   0.0283512f,  -0.0114597f,  0.00907307f, -0.0244004f,
1135              -0.0152191f,  -0.0259063f,   0.00914318f, 0.00415118f,  0.017147f,
1136               0.0134203f,  -0.013869f,    0.0287268f, -0.00334693f,  0.00733398f, -0.0287926f,
1137              -0.0186926f,   0.0193662f,  -0.0115437f,  0.00422612f, -0.0345232f,
1138               0.00223253f, -0.00957321f,  0.0210624f,  0.013331f,    0.0150954f,   0.02168f})));
1139
1140     return LstmLayerNoCifgWithPeepholeWithProjectionTestImpl<datatype>(
1141         workloadFactory, memoryManager, input, expectedOutput, qScale, qOffset, constantDatatype);
1142 }
1143
1144 LayerTestResult<int16_t, 2> LstmLayerInt16NoCifgNoPeepholeNoProjectionInt16ConstantTest(
1145     armnn::IWorkloadFactory& workloadFactory,
1146     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1147 {
1148     const float qScale = 1.0f;
1149     const int32_t qOffset = 0;
1150
1151     const armnn::DataType datatype = armnn::DataType::QuantisedSymm16; // datatype & constants set to QSymm16
1152
1153     armnn::TensorInfo inputDesc({2, 2}, datatype);
1154     boost::multi_array<int16_t , 2> input = MakeTensor<int16_t , 2>(inputDesc, QuantizedVector<int16_t>(qScale,
1155             qOffset, std::vector<float>{2., 3., 3., 4.}));
1156
1157     armnn::TensorInfo outputDesc({2, 4}, datatype);
1158     boost::multi_array<int16_t, 2> expectedOutput = MakeTensor<int16_t, 2>(outputDesc, QuantizedVector<int16_t>(qScale,
1159             qOffset, std::vector<float>({{-0.02973187f, 0.1229473f,   0.20885126f, -0.15358765f,
1160                                           -0.0185422f,  0.11281417f,  0.24466537f, -0.1826292f}})));
1161
1162     return LstmNoCifgNoPeepholeNoProjectionTestImpl<datatype>(
1163         workloadFactory, memoryManager, input, expectedOutput, qScale, qOffset, datatype);
1164 }
1165
1166 LayerTestResult<float,3> MergerTest(
1167     armnn::IWorkloadFactory& workloadFactory,
1168     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1169 {
1170     unsigned int outputWidth = 3;
1171     unsigned int outputHeight = 6;
1172     unsigned int outputChannels = 3;
1173
1174     unsigned int inputWidth1 = 3;
1175     unsigned int inputHeight1 = 6;
1176     unsigned int inputChannels1 = 2;
1177
1178     unsigned int inputWidth2 = 3;
1179     unsigned int inputHeight2 = 6;
1180     unsigned int inputChannels2 = 1;
1181
1182     // Define the tensor descriptors.
1183     armnn::TensorInfo outputTensorInfo({ outputChannels, outputHeight, outputWidth }, armnn::DataType::Float32);
1184     armnn::TensorInfo inputTensorInfo1({ inputChannels1, inputHeight1, inputWidth1 }, armnn::DataType::Float32);
1185     armnn::TensorInfo inputTensorInfo2({ inputChannels2, inputHeight2, inputWidth2 }, armnn::DataType::Float32);
1186
1187     LayerTestResult<float,3> ret(outputTensorInfo);
1188
1189     ret.outputExpected = MakeTensor<float, 3>(outputTensorInfo, std::vector<float>(
1190     {
1191             1.0f, 2.0f, 3.0f,
1192             4.0f, 5.0f, 6.0f,
1193             7.0f, 8.0f, 9.0f,
1194             10.0f, 11.0f, 12.0f,
1195             13.0f, 14.0f, 15.0f,
1196             16.0f, 17.0f, 18.0f,
1197
1198             19.0f, 20.0f, 21.0f,
1199             22.0f, 23.0f, 24.0f,
1200             25.0f, 26.0f, 27.0f,
1201             28.0f, 29.0f, 30.0f,
1202             31.0f, 32.0f, 33.0f,
1203             34.0f, 35.0f, 36.0f,
1204
1205             37.0f, 38.0f, 39.0f,
1206             40.0f, 41.0f, 42.0f,
1207             43.0f, 44.0f, 45.0f,
1208             46.0f, 47.0f, 48.0f,
1209             49.0f, 50.0f, 51.0f,
1210             52.0f, 53.0f, 54.0f,
1211         })
1212     );
1213
1214     auto input1 = MakeTensor<float, 3>(inputTensorInfo1, std::vector<float>(
1215         {
1216             1.0f, 2.0f, 3.0f,
1217             4.0f, 5.0f, 6.0f,
1218             7.0f, 8.0f, 9.0f,
1219             10.0f, 11.0f, 12.0f,
1220             13.0f, 14.0f, 15.0f,
1221             16.0f, 17.0f, 18.0f,
1222
1223             19.0f, 20.0f, 21.0f,
1224             22.0f, 23.0f, 24.0f,
1225             25.0f, 26.0f, 27.0f,
1226             28.0f, 29.0f, 30.0f,
1227             31.0f, 32.0f, 33.0f,
1228             34.0f, 35.0f, 36.0f,
1229         })
1230     );
1231
1232     auto input2 = MakeTensor<float, 3>(inputTensorInfo2, std::vector<float>(
1233         {
1234             37.0f, 38.0f, 39.0f,
1235             40.0f, 41.0f, 42.0f,
1236             43.0f, 44.0f, 45.0f,
1237             46.0f, 47.0f, 48.0f,
1238             49.0f, 50.0f, 51.0f,
1239             52.0f, 53.0f, 54.0f,
1240         })
1241     );
1242
1243     std::vector<unsigned int> wOrigin1 = {0, 0, 0}; //Extent of the window is defined by size of input[0].
1244     armnn::MergerQueueDescriptor::ViewOrigin window1(wOrigin1);
1245
1246     std::vector<unsigned int> wOrigin2 = {2, 0, 0}; //Extent of the window is defined by size of input[1].
1247     armnn::MergerQueueDescriptor::ViewOrigin window2(wOrigin2);
1248
1249     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
1250
1251     bool subTensorsSupported = workloadFactory.SupportsSubTensors();
1252
1253     std::unique_ptr<armnn::ITensorHandle> inputHandle1 =
1254         subTensorsSupported ?
1255             workloadFactory.CreateSubTensorHandle(*outputHandle, inputTensorInfo1.GetShape(), wOrigin1.data()) :
1256             workloadFactory.CreateTensorHandle(inputTensorInfo1);
1257
1258     std::unique_ptr<armnn::ITensorHandle> inputHandle2  =
1259         subTensorsSupported ?
1260             workloadFactory.CreateSubTensorHandle(*outputHandle, inputTensorInfo2.GetShape(), wOrigin2.data()) :
1261             workloadFactory.CreateTensorHandle(inputTensorInfo2);
1262
1263     armnn::MergerQueueDescriptor data;
1264     armnn::WorkloadInfo info;
1265     AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get());
1266     AddInputToWorkload(data, info, inputTensorInfo2, inputHandle2.get());
1267     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
1268
1269     data.m_ViewOrigins.push_back(window1);
1270     data.m_ViewOrigins.push_back(window2);
1271
1272     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateMerger(data, info);
1273
1274     inputHandle1->Allocate();
1275     inputHandle2->Allocate();
1276     outputHandle->Allocate();
1277
1278     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0]);
1279     CopyDataToITensorHandle(inputHandle2.get(), &input2[0][0][0]);
1280
1281     workload->PostAllocationConfigure();
1282     workload->Execute();
1283
1284     CopyDataFromITensorHandle(&ret.output[0][0][0], outputHandle.get());
1285
1286     return ret;
1287 }
1288
1289 LayerTestResult<float,4> AdditionTest(
1290     armnn::IWorkloadFactory& workloadFactory,
1291     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1292 {
1293     unsigned int batchSize = 2;
1294     unsigned int channels  = 2;
1295     unsigned int height    = 2;
1296     unsigned int width     = 3;
1297
1298     armnn::TensorInfo inputTensorInfo1, inputTensorInfo2;
1299     armnn::TensorInfo outputTensorInfo;
1300
1301     unsigned int shape[] = {batchSize, channels, height, width};
1302
1303     inputTensorInfo1 = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
1304     inputTensorInfo2 = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
1305     outputTensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
1306
1307
1308     auto input1 = MakeTensor<float, 4>(inputTensorInfo1, std::vector<float>(
1309         {
1310             0.0f, 2.0f, 1.0f,
1311             0.2f, 1.0f, 2.0f,
1312
1313             1.0f, 2.0f, 1.0f,
1314             0.2f, 1.0f, 2.0f,
1315
1316             0.0f, 2.0f, 1.0f,
1317             4.2f, 1.0f, 2.0f,
1318
1319             0.0f, 0.0f, 1.0f,
1320             0.2f, 1.0f, 2.0f,
1321         }));
1322
1323     auto input2 = MakeTensor<float, 4>(inputTensorInfo2, std::vector<float>(
1324         {
1325             1.0f, 2.0f, 1.0f,
1326             0.0f, 1.0f, 2.0f,
1327
1328             1.0f, 2.0f, -2.0f,
1329             0.2f, 1.0f, 2.0f,
1330
1331             0.0f, 2.0f, 1.0f,
1332             4.2f, 0.0f, -3.0f,
1333
1334             0.0f, 0.0f, 1.0f,
1335             0.7f, 1.0f, 5.0f,
1336         }));
1337
1338     LayerTestResult<float,4> ret(outputTensorInfo);
1339     ret.outputExpected = MakeTensor<float, 4>(outputTensorInfo, std::vector<float>(
1340         {
1341             1.0f, 4.0f, 2.0f,
1342             0.2f, 2.0f, 4.0f,
1343
1344             2.0f, 4.0f, -1.0f,
1345             0.4f, 2.0f, 4.0f,
1346
1347             0.0f, 4.0f, 2.0f,
1348             8.4f, 1.0f, -1.0f,
1349
1350             0.0f, 0.0f, 2.0f,
1351             0.9f, 2.0f, 7.0f,
1352         }));
1353
1354     std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
1355     std::unique_ptr<armnn::ITensorHandle> inputHandle2 = workloadFactory.CreateTensorHandle(inputTensorInfo2);
1356     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
1357
1358     armnn::AdditionQueueDescriptor data;
1359     armnn::WorkloadInfo info;
1360     AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get());
1361     AddInputToWorkload(data, info, inputTensorInfo2, inputHandle2.get());
1362     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
1363
1364     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateAddition(data, info);
1365
1366     inputHandle1->Allocate();
1367     inputHandle2->Allocate();
1368     outputHandle->Allocate();
1369
1370     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
1371     CopyDataToITensorHandle(inputHandle2.get(), &input2[0][0][0][0]);
1372
1373     workload->PostAllocationConfigure();
1374     workload->Execute();
1375
1376     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
1377
1378     return ret;
1379 }
1380
1381 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
1382 LayerTestResult<T, 4> AdditionBroadcastTestImpl(
1383     armnn::IWorkloadFactory& workloadFactory,
1384     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1385     float qScale,
1386     int32_t qOffset)
1387 {
1388     armnn::TensorInfo inputTensorInfo1 = armnn::TensorInfo({1, 3, 2, 1}, ArmnnType);
1389     armnn::TensorInfo inputTensorInfo2 = armnn::TensorInfo({1, 1, 2, 3}, ArmnnType);
1390     armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 2, 3}, ArmnnType);
1391
1392     if (armnn::IsQuantizedType<T>())
1393     {
1394         inputTensorInfo1.SetQuantizationScale(qScale);
1395         inputTensorInfo1.SetQuantizationOffset(qOffset);
1396         inputTensorInfo2.SetQuantizationScale(qScale);
1397         inputTensorInfo2.SetQuantizationOffset(qOffset);
1398         outputTensorInfo.SetQuantizationScale(qScale);
1399         outputTensorInfo.SetQuantizationOffset(qOffset);
1400     }
1401
1402     auto input1 = MakeTensor<T, 4>(inputTensorInfo1, QuantizedVector<T>(qScale, qOffset,
1403         {
1404             0.0f,
1405             1.0f,
1406
1407             2.0f,
1408             3.0f,
1409
1410             4.0f,
1411             5.0f,
1412         }));
1413
1414     auto input2 = MakeTensor<T, 4>(inputTensorInfo2, QuantizedVector<T>(qScale, qOffset,
1415         {
1416             0.5f, 1.5f, 2.5f,
1417             3.5f, 4.5f, 5.5f,
1418         }));
1419
1420     LayerTestResult<T,4> ret(outputTensorInfo);
1421     ret.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset,
1422         {
1423             0.5f, 1.5f, 2.5f,
1424             4.5f, 5.5f, 6.5f,
1425
1426             2.5f, 3.5f, 4.5f,
1427             6.5f, 7.5f, 8.5f,
1428
1429             4.5f, 5.5f, 6.5f,
1430             8.5f, 9.5f, 10.5f,
1431         }));
1432
1433     std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
1434     std::unique_ptr<armnn::ITensorHandle> inputHandle2 = workloadFactory.CreateTensorHandle(inputTensorInfo2);
1435     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
1436
1437     armnn::AdditionQueueDescriptor data;
1438     armnn::WorkloadInfo info;
1439     AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get());
1440     AddInputToWorkload(data, info, inputTensorInfo2, inputHandle2.get());
1441     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
1442
1443     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateAddition(data, info);
1444
1445     inputHandle1->Allocate();
1446     inputHandle2->Allocate();
1447     outputHandle->Allocate();
1448
1449     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
1450     CopyDataToITensorHandle(inputHandle2.get(), &input2[0][0][0][0]);
1451
1452     workload->PostAllocationConfigure();
1453     workload->Execute();
1454
1455     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
1456
1457     return ret;
1458 }
1459
1460 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
1461 LayerTestResult<T, 4> AdditionBroadcast1ElementTestImpl(
1462     armnn::IWorkloadFactory& workloadFactory,
1463     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1464     float qScale,
1465     int32_t qOffset)
1466 {
1467     armnn::TensorInfo inputTensorInfo1 = armnn::TensorInfo({1, 3, 2, 3}, ArmnnType);
1468     armnn::TensorInfo inputTensorInfo2 = armnn::TensorInfo({1, 1, 1, 1}, ArmnnType);
1469     armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 2, 3}, ArmnnType);
1470
1471     if (armnn::IsQuantizedType<T>())
1472     {
1473         inputTensorInfo1.SetQuantizationScale(qScale);
1474         inputTensorInfo1.SetQuantizationOffset(qOffset);
1475         inputTensorInfo2.SetQuantizationScale(qScale);
1476         inputTensorInfo2.SetQuantizationOffset(qOffset);
1477         outputTensorInfo.SetQuantizationScale(qScale);
1478         outputTensorInfo.SetQuantizationOffset(qOffset);
1479     }
1480
1481     auto input1 = MakeTensor<T, 4>(inputTensorInfo1, QuantizedVector<T>(qScale, qOffset,
1482         {
1483              0.0f,  1.0f,  2.0f,
1484              3.0f,  4.0f,  5.0f,
1485              6.0f,  7.0f,  8.0f,
1486              9.0f, 10.0f, 11.0f,
1487             12.0f, 13.0f, 14.0f,
1488             15.0f, 16.0f, 17.0f,
1489         }));
1490
1491     auto input2 = MakeTensor<T, 4>(inputTensorInfo2, QuantizedVector<T>(qScale, qOffset,
1492         {
1493             0.5f,
1494         }));
1495
1496     LayerTestResult<T,4> ret(outputTensorInfo);
1497     ret.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset,
1498         {
1499              0.5f,  1.5f,  2.5f,
1500              3.5f,  4.5f,  5.5f,
1501              6.5f,  7.5f,  8.5f,
1502              9.5f, 10.5f, 11.5f,
1503             12.5f, 13.5f, 14.5f,
1504             15.5f, 16.5f, 17.5f,
1505         }));
1506
1507     std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
1508     std::unique_ptr<armnn::ITensorHandle> inputHandle2 = workloadFactory.CreateTensorHandle(inputTensorInfo2);
1509     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
1510
1511     armnn::AdditionQueueDescriptor data;
1512     armnn::WorkloadInfo info;
1513     AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get());
1514     AddInputToWorkload(data, info, inputTensorInfo2, inputHandle2.get());
1515     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
1516
1517     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateAddition(data, info);
1518
1519     inputHandle1->Allocate();
1520     inputHandle2->Allocate();
1521     outputHandle->Allocate();
1522
1523     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
1524     CopyDataToITensorHandle(inputHandle2.get(), &input2[0][0][0][0]);
1525
1526     workload->PostAllocationConfigure();
1527     workload->Execute();
1528
1529     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
1530
1531     return ret;
1532 }
1533
1534 LayerTestResult<float, 4> AdditionBroadcastTest(
1535     armnn::IWorkloadFactory& workloadFactory,
1536     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1537 {
1538     return AdditionBroadcastTestImpl<armnn::DataType::Float32>(
1539         workloadFactory, memoryManager, 0.0f, 0);
1540 }
1541
1542 LayerTestResult<uint8_t, 4> AdditionBroadcastUint8Test(
1543     armnn::IWorkloadFactory& workloadFactory,
1544     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1545 {
1546     return AdditionBroadcastTestImpl<armnn::DataType::QuantisedAsymm8>(
1547         workloadFactory, memoryManager, 2.f, 0);
1548 }
1549
1550 LayerTestResult<int16_t, 4> AdditionBroadcastInt16Test(
1551     armnn::IWorkloadFactory& workloadFactory,
1552     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1553 {
1554     return AdditionBroadcastTestImpl<armnn::DataType::QuantisedSymm16>(
1555         workloadFactory, memoryManager, 2.f, 0);
1556 }
1557
1558 LayerTestResult<float, 4> AdditionBroadcast1ElementTest(
1559     armnn::IWorkloadFactory& workloadFactory,
1560     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1561 {
1562     return AdditionBroadcast1ElementTestImpl<armnn::DataType::Float32>(
1563         workloadFactory, memoryManager, 0.0f, 0);
1564 }
1565
1566 LayerTestResult<uint8_t, 4> AdditionBroadcast1ElementUint8Test(
1567     armnn::IWorkloadFactory& workloadFactory,
1568     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1569 {
1570     return AdditionBroadcast1ElementTestImpl<armnn::DataType::QuantisedAsymm8>(
1571         workloadFactory, memoryManager, 0.1333333f, 128);
1572 }
1573
1574 LayerTestResult<int16_t, 4> AdditionBroadcast1ElementInt16Test(
1575     armnn::IWorkloadFactory& workloadFactory,
1576     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1577 {
1578     return AdditionBroadcast1ElementTestImpl<armnn::DataType::QuantisedSymm16>(
1579         workloadFactory, memoryManager, 0.1333333f, 0);
1580 }
1581
1582 LayerTestResult<float,4> CompareAdditionTest(
1583     armnn::IWorkloadFactory& workloadFactory,
1584     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1585     armnn::IWorkloadFactory& refWorkloadFactory)
1586 {
1587     unsigned int batchSize = 4;
1588     unsigned int channels  = 1;
1589     unsigned int height    = 2;
1590     unsigned int width     = 3;
1591
1592     armnn::TensorInfo inputTensorInfo1, inputTensorInfo2;
1593     armnn::TensorInfo outputTensorInfo;
1594
1595     unsigned int shape[] = {batchSize, channels, height, width};
1596
1597     inputTensorInfo1 = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
1598     inputTensorInfo2 = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
1599     outputTensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
1600
1601     auto input1 = MakeRandomTensor<float, 4>(inputTensorInfo1, 1232);
1602     auto input2 = MakeRandomTensor<float, 4>(inputTensorInfo2, 456);
1603
1604     LayerTestResult<float,4> ret(outputTensorInfo);
1605
1606     std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
1607     std::unique_ptr<armnn::ITensorHandle> inputHandle2 = workloadFactory.CreateTensorHandle(inputTensorInfo2);
1608     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
1609
1610     std::unique_ptr<armnn::ITensorHandle> inputHandle1Ref = refWorkloadFactory.CreateTensorHandle(inputTensorInfo1);
1611     std::unique_ptr<armnn::ITensorHandle> inputHandle2Ref = refWorkloadFactory.CreateTensorHandle(inputTensorInfo2);
1612     std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refWorkloadFactory.CreateTensorHandle(outputTensorInfo);
1613
1614     armnn::AdditionQueueDescriptor data;
1615     armnn::WorkloadInfo info;
1616     AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get());
1617     AddInputToWorkload(data, info, inputTensorInfo2, inputHandle2.get());
1618     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
1619
1620     armnn::AdditionQueueDescriptor refData = data;
1621     armnn::WorkloadInfo refInfo = info;
1622     SetWorkloadInput(refData, refInfo, 0, inputTensorInfo1, inputHandle1Ref.get());
1623     SetWorkloadInput(refData, refInfo, 1, inputTensorInfo2, inputHandle2Ref.get());
1624     SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
1625
1626     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateAddition(data, info);
1627     std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreateAddition(refData, refInfo);
1628
1629     inputHandle1->Allocate();
1630     inputHandle2->Allocate();
1631     outputHandle->Allocate();
1632     inputHandle1Ref->Allocate();
1633     inputHandle2Ref->Allocate();
1634     outputHandleRef->Allocate();
1635
1636     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
1637     CopyDataToITensorHandle(inputHandle2.get(), &input2[0][0][0][0]);
1638     CopyDataToITensorHandle(inputHandle1Ref.get(), &input1[0][0][0][0]);
1639     CopyDataToITensorHandle(inputHandle2Ref.get(), &input2[0][0][0][0]);
1640
1641     workload->PostAllocationConfigure();
1642     workload->Execute();
1643     workloadRef->PostAllocationConfigure();
1644     workloadRef->Execute();
1645
1646     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
1647     CopyDataFromITensorHandle(&ret.outputExpected[0][0][0][0], outputHandleRef.get());
1648
1649     return ret;
1650 }
1651
1652 namespace {
1653 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
1654 LayerTestResult<T, 4> DivisionTestHelper(
1655     armnn::IWorkloadFactory& workloadFactory,
1656     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1657     const unsigned int shape0[4],
1658     const std::vector<T>& values0,
1659     float scale0,
1660     int32_t offset0,
1661     const unsigned int shape1[4],
1662     const std::vector<T> & values1,
1663     float scale1,
1664     int32_t offset1,
1665     const unsigned int outShape[4],
1666     const std::vector<T> & outValues,
1667     float outScale,
1668     int32_t outOffset)
1669 {
1670     armnn::TensorInfo inputTensorInfo0(4, shape0, ArmnnType);
1671     armnn::TensorInfo inputTensorInfo1(4, shape1, ArmnnType);
1672     armnn::TensorInfo outputTensorInfo(4, outShape, ArmnnType);
1673
1674     inputTensorInfo0.SetQuantizationScale(scale0);
1675     inputTensorInfo0.SetQuantizationOffset(offset0);
1676
1677     inputTensorInfo1.SetQuantizationScale(scale1);
1678     inputTensorInfo1.SetQuantizationOffset(offset1);
1679
1680     outputTensorInfo.SetQuantizationScale(outScale);
1681     outputTensorInfo.SetQuantizationOffset(outOffset);
1682
1683     auto input0 = MakeTensor<T, 4>(inputTensorInfo0, values0);
1684     auto input1 = MakeTensor<T, 4>(inputTensorInfo1, values1);
1685
1686     LayerTestResult<T, 4> result(outputTensorInfo);
1687     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, outValues);
1688
1689     std::unique_ptr<armnn::ITensorHandle> inputHandle0 = workloadFactory.CreateTensorHandle(inputTensorInfo0);
1690     std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
1691     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
1692
1693     armnn::DivisionQueueDescriptor data;
1694     armnn::WorkloadInfo info;
1695     AddInputToWorkload(data,  info, inputTensorInfo0, inputHandle0.get());
1696     AddInputToWorkload(data,  info, inputTensorInfo1, inputHandle1.get());
1697     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
1698
1699     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateDivision(data, info);
1700
1701     inputHandle0->Allocate();
1702     inputHandle1->Allocate();
1703     outputHandle->Allocate();
1704
1705     CopyDataToITensorHandle(inputHandle0.get(), &input0[0][0][0][0]);
1706     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
1707
1708     workload->PostAllocationConfigure();
1709     workload->Execute();
1710
1711     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
1712
1713     return result;
1714 }
1715 } // anonymous namespace
1716
1717 LayerTestResult<float,4> DivisionByZeroTest(
1718     armnn::IWorkloadFactory& workloadFactory,
1719     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1720 {
1721     const unsigned int width = 2;
1722     const unsigned int height = 2;
1723     const unsigned int channelCount = 2;
1724     const unsigned int batchSize = 2;
1725
1726     unsigned int shape[] = { batchSize, channelCount, height, width };
1727
1728     std::vector<float> input0({
1729                                 1.f,  1.f,  1.f,  1.f,  0.f, 0.f, 0.f, 0.f,
1730                                -1.f, -1.f, -1.f, -1.f,  5.f, 5.f, 5.f, 5.f });
1731
1732     std::vector<float> input1({
1733                                0.f, 0.f, -0.f, -0.f,  0.f, 0.f, -0.f, -0.f,
1734                                0.f, 0.f, -0.f, -0.f,  5.f, 5.f,  5.f,  5.f });
1735
1736     std::vector<float> output({
1737                                INFINITY, INFINITY, -INFINITY, -INFINITY,  NAN, NAN, -NAN, -NAN,
1738                                -INFINITY, -INFINITY, INFINITY, INFINITY,  1, 1, 1, 1 });
1739
1740     return DivisionTestHelper<armnn::DataType::Float32>(workloadFactory,
1741                                                         memoryManager,
1742                                                         shape, input0, 1.0f, 0,
1743                                                         shape, input1, 1.0f, 0,
1744                                                         shape, output, 1.0f, 0);
1745 }
1746
1747 LayerTestResult<float,4> DivisionTest(
1748     armnn::IWorkloadFactory& workloadFactory,
1749     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1750 {
1751     const unsigned int width = 2;
1752     const unsigned int height = 2;
1753     const unsigned int channelCount = 2;
1754     const unsigned int batchSize = 2;
1755
1756     unsigned int shape[] = { batchSize, channelCount, height, width };
1757
1758     std::vector<float> input0({
1759                                       2,  2,  2,  2,    3,  3,  3,  3,
1760                                       4,  4,  4,  4,    5,  5,  5,  5 });
1761
1762     std::vector<float> input1({
1763                                       1,  1,  1,  1,    2,  2,  2,  2,
1764                                       4,  4,  4,  4,    4,  4,  4,  4 });
1765
1766     std::vector<float> output({
1767                                       2,  2,  2,  2,    1.5,  1.5,  1.5,  1.5,
1768                                       1, 1, 1, 1,  1.25, 1.25, 1.25, 1.25 });
1769
1770
1771     return DivisionTestHelper<armnn::DataType::Float32>(workloadFactory,
1772                                                         memoryManager,
1773                                                         shape, input0, 1.0f, 0,
1774                                                         shape, input1, 1.0f, 0,
1775                                                         shape, output, 1.0f, 0);
1776 }
1777
1778 LayerTestResult<float, 4> DivisionBroadcast1ElementTest(
1779     armnn::IWorkloadFactory& workloadFactory,
1780     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1781 {
1782     unsigned int shape0[] = { 1, 2, 2, 2 };
1783     std::vector<float> input0({ 2, 4, 6, 8, 10, 12, 14, 16});
1784
1785     unsigned int shape1[] = { 1, 1, 1, 1 };
1786     std::vector<float> input1({ 2 });
1787
1788     std::vector<float> output({ 1, 2, 3, 4, 5, 6, 7, 8});
1789
1790
1791     return DivisionTestHelper<armnn::DataType::Float32>(workloadFactory,
1792                                                         memoryManager,
1793                                                         shape0, input0, 1.0f, 0,
1794                                                         shape1, input1, 1.0f, 0,
1795                                                         shape0, output, 1.0f, 0);
1796 }
1797
1798 LayerTestResult<float, 4> DivisionBroadcast1DVectorTest(
1799     armnn::IWorkloadFactory& workloadFactory,
1800     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1801 {
1802     unsigned int shape0[] = { 1, 3, 3, 2 };
1803     std::vector<float> input0({
1804                                       1,   4,       3,  8,      5, 12,
1805                                       7,   16,      9, 20,     11, 24,
1806                                       13,  28,     15, 32,     17, 36});
1807
1808     unsigned int shape1[] = { 1, 1, 1, 2 };
1809     std::vector<float> input1({ 1, 2 });
1810
1811     std::vector<float> output({
1812                                       1,   2,      3,  4,      5,  6,
1813                                       7,   8,      9, 10,     11, 12,
1814                                       13, 14,     15, 16,     17, 18});
1815
1816     return DivisionTestHelper<armnn::DataType::Float32>(workloadFactory,
1817                                                         memoryManager,
1818                                                         shape0, input0, 1.0f, 0,
1819                                                         shape1, input1, 1.0f, 0,
1820                                                         shape0, output, 1.0f, 0);
1821 }
1822
1823 LayerTestResult<uint8_t,4> DivisionUint8Test(
1824     armnn::IWorkloadFactory& workloadFactory,
1825     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1826 {
1827     const unsigned int width = 2;
1828     const unsigned int height = 2;
1829     const unsigned int channelCount = 2;
1830     const unsigned int batchSize = 2;
1831
1832     unsigned int shape[] = { batchSize, channelCount, height, width };
1833
1834     std::vector<uint8_t> input0({2,  2,  2,  2,    3,  3,  3,  3,
1835                                  4,  4,  4,  4,    5,  5,  5,  5 });
1836
1837     std::vector<uint8_t> input1({1,  1,  1,  1,    2,  2,  2,  2,
1838                                  4,  4,  4,  4,    4,  4,  4,  4 });
1839
1840     std::vector<uint8_t> output({8,  8,  8,  8,    6,  6,  6,  6,
1841                                  4,  4,  4,  4,    5,  5,  5,  5});
1842
1843
1844     return DivisionTestHelper<armnn::DataType::QuantisedAsymm8>(workloadFactory,
1845                                                                 memoryManager,
1846                                                                 shape, input0, 1.0f,  0,
1847                                                                 shape, input1, 1.0f,  0,
1848                                                                 shape, output, 0.25f, 0);
1849 }
1850
1851 LayerTestResult<uint8_t, 4> DivisionBroadcast1ElementUint8Test(
1852     armnn::IWorkloadFactory& workloadFactory,
1853     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1854 {
1855     unsigned int shape0[] = { 1, 2, 2, 2 };
1856     std::vector<uint8_t> input0({ 2, 4, 6, 8, 10, 12, 14, 16});
1857
1858     unsigned int shape1[] = { 1, 1, 1, 1 };
1859     std::vector<uint8_t> input1({ 2 });
1860
1861     std::vector<uint8_t> output({ 1, 2, 3, 4, 5, 6, 7, 8});
1862
1863     return DivisionTestHelper<armnn::DataType::QuantisedAsymm8>(workloadFactory,
1864                                                                 memoryManager,
1865                                                                 shape0, input0, 1.0f, 0,
1866                                                                 shape1, input1, 1.0f, 0,
1867                                                                 shape0, output, 1.0f, 0);
1868 }
1869
1870 LayerTestResult<uint8_t, 4> DivisionBroadcast1DVectorUint8Test(
1871     armnn::IWorkloadFactory& workloadFactory,
1872     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1873 {
1874     unsigned int shape0[] = { 1, 3, 3, 2 };
1875     std::vector<uint8_t> input0({1,   4,     3,  8,      5,  12,
1876                                  7,   16,    9,  20,     11, 24,
1877                                  13,  28,    15, 32,     17, 36});
1878
1879     unsigned int shape1[] = { 1, 1, 1, 2 };
1880     std::vector<uint8_t> input1({ 1, 2 });
1881
1882     std::vector<uint8_t> output({1,   2,      3,  4,      5,  6,
1883                                  7,   8,      9, 10,     11, 12,
1884                                  13, 14,     15, 16,     17, 18});
1885
1886     return DivisionTestHelper<armnn::DataType::QuantisedAsymm8>(workloadFactory,
1887                                                                 memoryManager,
1888                                                                 shape0, input0, 1.0f, 0,
1889                                                                 shape1, input1, 1.0f, 0,
1890                                                                 shape0, output, 1.0f, 0);
1891 }
1892
1893 LayerTestResult<int16_t,4> DivisionInt16Test(
1894     armnn::IWorkloadFactory& workloadFactory,
1895     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1896 {
1897     unsigned int shape[] = { 2, 2, 2, 2 };
1898
1899     std::vector<int16_t> input0({2,  2,  2,  2,    3,  3,  3,  3,
1900                                  4,  4,  4,  4,    5,  5,  5,  5 });
1901
1902     std::vector<int16_t> input1({1,  1,  1,  1,    2,  2,  2,  2,
1903                                  4,  4,  4,  4,    4,  4,  4,  4 });
1904
1905     std::vector<int16_t> output({8,  8,  8,  8,    6,  6,  6,  6,
1906                                  4,  4,  4,  4,    5,  5,  5,  5});
1907
1908
1909     return DivisionTestHelper<armnn::DataType::QuantisedSymm16>(workloadFactory,
1910                                                                 memoryManager,
1911                                                                 shape, input0, 1.0f,  0,
1912                                                                 shape, input1, 1.0f,  0,
1913                                                                 shape, output, 0.25f, 0);
1914 }
1915
1916 LayerTestResult<int16_t, 4> DivisionBroadcast1ElementInt16Test(
1917     armnn::IWorkloadFactory& workloadFactory,
1918     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1919 {
1920     unsigned int shape0[] = { 1, 2, 2, 2 };
1921     std::vector<int16_t> input0({ 2, 4, 6, 8, 10, 12, 14, 16});
1922
1923     unsigned int shape1[] = { 1, 1, 1, 1 };
1924     std::vector<int16_t> input1({ 2 });
1925
1926     std::vector<int16_t> output({ 1, 2, 3, 4, 5, 6, 7, 8});
1927
1928     return DivisionTestHelper<armnn::DataType::QuantisedSymm16>(workloadFactory,
1929                                                                 memoryManager,
1930                                                                 shape0, input0, 1.0f, 0,
1931                                                                 shape1, input1, 1.0f, 0,
1932                                                                 shape0, output, 1.0f, 0);
1933 }
1934
1935 LayerTestResult<int16_t, 4> DivisionBroadcast1DVectorInt16Test(
1936     armnn::IWorkloadFactory& workloadFactory,
1937     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
1938 {
1939     unsigned int shape0[] = { 1, 3, 3, 2 };
1940     std::vector<int16_t> input0({1,   4,     3,  8,      5,  12,
1941                                  7,   16,    9,  20,     11, 24,
1942                                  13,  28,    15, 32,     17, 36});
1943
1944     unsigned int shape1[] = { 1, 1, 1, 2 };
1945     std::vector<int16_t> input1({ 1, 2 });
1946
1947     std::vector<int16_t> output({1,   2,      3,  4,      5,  6,
1948                                  7,   8,      9, 10,     11, 12,
1949                                  13, 14,     15, 16,     17, 18});
1950
1951     return DivisionTestHelper<armnn::DataType::QuantisedSymm16>(workloadFactory,
1952                                                                 memoryManager,
1953                                                                 shape0, input0, 1.0f, 0,
1954                                                                 shape1, input1, 1.0f, 0,
1955                                                                 shape0, output, 1.0f, 0);
1956 }
1957
1958 template<typename DescriptorType>
1959 std::unique_ptr<armnn::IWorkload> CreateWorkload(
1960     const armnn::IWorkloadFactory& workloadFactory,
1961     const armnn::WorkloadInfo& info,
1962     const DescriptorType& descriptor)
1963 {
1964     return CreateWorkload(workloadFactory, info, descriptor);
1965 };
1966
1967 template<>
1968 std::unique_ptr<armnn::IWorkload> CreateWorkload<armnn::MaximumQueueDescriptor>(
1969     const armnn::IWorkloadFactory& workloadFactory,
1970     const armnn::WorkloadInfo& info,
1971     const armnn::MaximumQueueDescriptor& descriptor)
1972 {
1973     return workloadFactory.CreateMaximum(descriptor, info);
1974 }
1975
1976 template<>
1977 std::unique_ptr<armnn::IWorkload> CreateWorkload<armnn::MinimumQueueDescriptor>(
1978     const armnn::IWorkloadFactory& workloadFactory,
1979     const armnn::WorkloadInfo& info,
1980     const armnn::MinimumQueueDescriptor& descriptor)
1981 {
1982     return workloadFactory.CreateMinimum(descriptor, info);
1983 }
1984
1985 template<>
1986 std::unique_ptr<armnn::IWorkload> CreateWorkload<armnn::EqualQueueDescriptor>(
1987         const armnn::IWorkloadFactory& workloadFactory,
1988         const armnn::WorkloadInfo& info,
1989         const armnn::EqualQueueDescriptor& descriptor)
1990 {
1991     return workloadFactory.CreateEqual(descriptor, info);
1992 }
1993
1994 template<>
1995 std::unique_ptr<armnn::IWorkload> CreateWorkload<armnn::GreaterQueueDescriptor>(
1996         const armnn::IWorkloadFactory& workloadFactory,
1997         const armnn::WorkloadInfo& info,
1998         const armnn::GreaterQueueDescriptor& descriptor)
1999 {
2000     return workloadFactory.CreateGreater(descriptor, info);
2001 }
2002
2003 namespace {
2004
2005 template <typename Descriptor,
2006           armnn::DataType ArmnnTypeInput,
2007           armnn::DataType ArmnnTypeOutput,
2008           typename TInput = armnn::ResolveType<ArmnnTypeInput>,
2009           typename TOutput = armnn::ResolveType<ArmnnTypeOutput>>
2010 LayerTestResult<TOutput, 4> ElementwiseTestHelper(
2011     armnn::IWorkloadFactory & workloadFactory,
2012     const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,
2013     const unsigned int shape0[4], std::vector<TInput> values0,
2014     const unsigned int shape1[4], std::vector<TInput> values1,
2015     const unsigned int outShape[4], std::vector<TOutput> outValues,
2016     float qScale = 0.0f, int qOffset = 0)
2017 {
2018     const size_t dimensionCount = 4;
2019     armnn::TensorInfo inputTensorInfo0{dimensionCount, shape0, ArmnnTypeInput};
2020     armnn::TensorInfo inputTensorInfo1{dimensionCount, shape1, ArmnnTypeInput};
2021     armnn::TensorInfo outputTensorInfo{dimensionCount, outShape, ArmnnTypeOutput};
2022
2023     auto input0 = MakeTensor<TInput, 4>(inputTensorInfo0, values0);
2024     auto input1 = MakeTensor<TInput, 4>(inputTensorInfo1, values1);
2025
2026     if (armnn::IsQuantizedType<TInput>())
2027     {
2028         inputTensorInfo0.SetQuantizationScale(qScale);
2029         inputTensorInfo0.SetQuantizationOffset(qOffset);
2030
2031         inputTensorInfo1.SetQuantizationScale(qScale);
2032         inputTensorInfo1.SetQuantizationOffset(qOffset);
2033
2034         outputTensorInfo.SetQuantizationScale(qScale);
2035         outputTensorInfo.SetQuantizationOffset(qOffset);
2036     }
2037
2038     LayerTestResult<TOutput,4> ret(outputTensorInfo);
2039
2040     if(ArmnnTypeOutput == armnn::DataType::Boolean)
2041     {
2042         ret.compareBoolean = true;
2043     }
2044
2045     std::unique_ptr<armnn::ITensorHandle> inputHandle0 = workloadFactory.CreateTensorHandle(inputTensorInfo0);
2046     std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
2047     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
2048
2049     Descriptor data;
2050     armnn::WorkloadInfo info;
2051     AddInputToWorkload(data, info, inputTensorInfo0, inputHandle0.get());
2052     AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get());
2053     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
2054     auto workload = CreateWorkload<Descriptor>(workloadFactory, info, data);
2055
2056     inputHandle0->Allocate();
2057     inputHandle1->Allocate();
2058     outputHandle->Allocate();
2059
2060     CopyDataToITensorHandle(inputHandle0.get(), &input0[0][0][0][0]);
2061     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
2062
2063     workload->PostAllocationConfigure();
2064     ExecuteWorkload(*workload, memoryManager);
2065
2066     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
2067
2068     ret.outputExpected = MakeTensor<TOutput, 4>(outputTensorInfo, outValues);
2069     return ret;
2070 }
2071
2072 template <typename Descriptor, armnn::DataType ArmnnT, typename T = armnn::ResolveType<ArmnnT>>
2073 LayerTestResult<T, 4> ElementwiseTestHelper(
2074     armnn::IWorkloadFactory & workloadFactory,
2075     const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,
2076     const unsigned int shape0[4], std::vector<T> values0,
2077     const unsigned int shape1[4], std::vector<T> values1,
2078     const unsigned int outShape[4], std::vector<T> outValues,
2079     float qScale = 0.0f, int qOffset = 0)
2080 {
2081     return ElementwiseTestHelper<Descriptor, ArmnnT, ArmnnT>
2082         (workloadFactory,
2083          memoryManager,
2084          shape0,
2085          values0,
2086          shape1,
2087          values1,
2088          outShape,
2089          outValues,
2090          qScale,
2091          qOffset);
2092 }
2093 }
2094
2095 LayerTestResult<uint8_t, 4> EqualSimpleTest(armnn::IWorkloadFactory& workloadFactory,
2096                                             const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2097 {
2098     const unsigned int width = 2;
2099     const unsigned int height = 2;
2100     const unsigned int channelCount = 2;
2101     const unsigned int batchSize = 2;
2102
2103     unsigned int shape[] = { batchSize, channelCount, height, width };
2104
2105     std::vector<float> input0({ 1, 1, 1, 1,  5, 5, 5, 5,
2106                                 3, 3, 3, 3,  4, 4, 4, 4 });
2107
2108     std::vector<float> input1({ 1, 1, 1, 1,  3, 3, 3, 3,
2109                                 5, 5, 5, 5,  4, 4, 4, 4 });
2110
2111     std::vector<uint8_t> output({ 1, 1, 1, 1,  0, 0, 0, 0,
2112                                   0, 0, 0, 0,  1, 1, 1, 1 });
2113
2114     return ElementwiseTestHelper<armnn::EqualQueueDescriptor, armnn::DataType::Float32, armnn::DataType::Boolean>(
2115         workloadFactory,
2116         memoryManager,
2117         shape,
2118         input0,
2119         shape,
2120         input1,
2121         shape,
2122         output);
2123 }
2124
2125 LayerTestResult<uint8_t, 4> EqualBroadcast1ElementTest(
2126         armnn::IWorkloadFactory& workloadFactory,
2127         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2128 {
2129     unsigned int shape0[] = { 1, 2, 2, 2 };
2130     std::vector<float> input0({ 1, 2, 3, 4, 5, 6, 7, 8});
2131
2132     unsigned int shape1[] = { 1, 1, 1, 1 };
2133     std::vector<float> input1({ 1 });
2134
2135     std::vector<uint8_t> output({ 1, 0, 0, 0, 0, 0, 0, 0});
2136
2137     return ElementwiseTestHelper<armnn::EqualQueueDescriptor, armnn::DataType::Float32, armnn::DataType::Boolean>(
2138         workloadFactory,
2139         memoryManager,
2140         shape0,
2141         input0,
2142         shape1,
2143         input1,
2144         shape0,
2145         output);
2146 }
2147
2148 LayerTestResult<uint8_t, 4> EqualBroadcast1DVectorTest(
2149         armnn::IWorkloadFactory& workloadFactory,
2150         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2151 {
2152     const unsigned int shape0[] = { 1, 2, 2, 3 };
2153     const unsigned int shape1[] = { 1, 1, 1, 3 };
2154
2155     std::vector<float> input0({ 1, 2, 3, 4, 5, 6,
2156                                 7, 8, 9, 10, 11, 12 });
2157
2158     std::vector<float> input1({ 1, 2, 3});
2159
2160     std::vector<uint8_t> output({ 1, 1, 1, 0, 0, 0,
2161                                   0, 0, 0, 0, 0, 0 });
2162
2163     return ElementwiseTestHelper<armnn::EqualQueueDescriptor, armnn::DataType::Float32, armnn::DataType::Boolean>(
2164         workloadFactory,
2165         memoryManager,
2166         shape0,
2167         input0,
2168         shape1,
2169         input1,
2170         shape0,
2171         output);
2172 }
2173
2174 LayerTestResult<uint8_t, 4> EqualUint8Test(
2175         armnn::IWorkloadFactory& workloadFactory,
2176         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2177 {
2178     unsigned int shape[] = { 2, 2, 2, 2 };
2179
2180     // See dequantized values to the right.
2181     std::vector<uint8_t> input0({ 1, 1, 1, 1, 6, 6, 6, 6,
2182                                   3, 3, 3, 3, 7, 7, 7, 7 });
2183
2184     std::vector<uint8_t> input1({ 2, 2, 2, 2, 6, 6, 6, 6,
2185                                   3, 3, 3, 3, 5, 5, 5, 5 });
2186
2187     std::vector<uint8_t> output({ 0, 0, 0, 0, 1, 1, 1, 1,
2188                                   1, 1, 1, 1, 0, 0, 0, 0 });
2189
2190     return ElementwiseTestHelper<armnn::EqualQueueDescriptor,
2191                                  armnn::DataType::QuantisedAsymm8,
2192                                  armnn::DataType::Boolean>(
2193         workloadFactory,
2194         memoryManager,
2195         shape,
2196         input0,
2197         shape,
2198         input1,
2199         shape,
2200         output,
2201         1.0f,
2202         0);
2203 }
2204
2205 LayerTestResult<uint8_t, 4> EqualBroadcast1ElementUint8Test(
2206         armnn::IWorkloadFactory& workloadFactory,
2207         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2208 {
2209     const unsigned int shape0[] = { 1, 2, 2, 3 };
2210     const unsigned int shape1[] = { 1, 1, 1, 1 };
2211
2212     std::vector<uint8_t> input0({ 1, 2, 3, 4, 5, 6,
2213                                   7, 8, 9, 10, 11, 12 });
2214
2215     std::vector<uint8_t> input1({ 1 });
2216
2217     std::vector<uint8_t> output({ 1, 0, 0, 0, 0, 0,
2218                                   0, 0, 0, 0, 0, 0 });
2219
2220     return ElementwiseTestHelper<armnn::EqualQueueDescriptor,
2221                                  armnn::DataType::QuantisedAsymm8,
2222                                  armnn::DataType::Boolean>(
2223         workloadFactory,
2224         memoryManager,
2225         shape0,
2226         input0,
2227         shape1,
2228         input1,
2229         shape0,
2230         output,
2231         1.0f,
2232         0);
2233 }
2234
2235 LayerTestResult<uint8_t, 4> EqualBroadcast1DVectorUint8Test(
2236         armnn::IWorkloadFactory& workloadFactory,
2237         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2238 {
2239     const unsigned int shape0[] = { 1, 2, 2, 3 };
2240     const unsigned int shape1[] = { 1, 1, 1, 3 };
2241
2242     std::vector<uint8_t> input0({ 1, 2, 3, 4, 5, 6,
2243                                   7, 8, 9, 10, 11, 12 });
2244
2245     std::vector<uint8_t> input1({ 1, 1, 3});
2246
2247     std::vector<uint8_t> output({ 1, 0, 1, 0, 0, 0,
2248                                   0, 0, 0, 0, 0, 0 });
2249
2250     return ElementwiseTestHelper<armnn::EqualQueueDescriptor,
2251                                  armnn::DataType::QuantisedAsymm8,
2252                                  armnn::DataType::Boolean>(
2253         workloadFactory,
2254         memoryManager,
2255         shape0,
2256         input0,
2257         shape1,
2258         input1,
2259         shape0,
2260         output,
2261         1.0f,
2262         0);
2263 }
2264
2265 LayerTestResult<uint8_t, 4> GreaterSimpleTest(armnn::IWorkloadFactory& workloadFactory,
2266                                             const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2267 {
2268     const unsigned int width = 2;
2269     const unsigned int height = 2;
2270     const unsigned int channelCount = 2;
2271     const unsigned int batchSize = 2;
2272
2273     unsigned int shape[] = { batchSize, channelCount, height, width };
2274
2275     std::vector<float> input0({ 1, 1, 1, 1,  5, 5, 5, 5,
2276                                 3, 3, 3, 3,  4, 4, 4, 4 });
2277
2278     std::vector<float> input1({ 1, 1, 1, 1,  3, 3, 3, 3,
2279                                 5, 5, 5, 5,  4, 4, 4, 4 });
2280
2281     std::vector<uint8_t> output({ 0, 0, 0, 0,  1, 1, 1, 1,
2282                                   0, 0, 0, 0,  0, 0, 0, 0 });
2283
2284     return ElementwiseTestHelper<armnn::GreaterQueueDescriptor, armnn::DataType::Float32, armnn::DataType::Boolean>(
2285         workloadFactory,
2286         memoryManager,
2287         shape,
2288         input0,
2289         shape,
2290         input1,
2291         shape,
2292         output);
2293 }
2294
2295 LayerTestResult<uint8_t, 4> GreaterBroadcast1ElementTest(
2296         armnn::IWorkloadFactory& workloadFactory,
2297         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2298 {
2299     unsigned int shape0[] = { 1, 2, 2, 2 };
2300     std::vector<float> input0({ 1, 2, 3, 4, 5, 6, 7, 8});
2301
2302     unsigned int shape1[] = { 1, 1, 1, 1 };
2303     std::vector<float> input1({ 1 });
2304
2305     std::vector<uint8_t> output({ 0, 1, 1, 1, 1, 1, 1, 1});
2306
2307     return ElementwiseTestHelper<armnn::GreaterQueueDescriptor, armnn::DataType::Float32, armnn::DataType::Boolean>(
2308         workloadFactory,
2309         memoryManager,
2310         shape0,
2311         input0,
2312         shape1,
2313         input1,
2314         shape0,
2315         output);
2316 }
2317
2318 LayerTestResult<uint8_t, 4> GreaterBroadcast1DVectorTest(
2319         armnn::IWorkloadFactory& workloadFactory,
2320         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2321 {
2322     const unsigned int shape0[] = { 1, 2, 2, 3 };
2323     const unsigned int shape1[] = { 1, 1, 1, 3 };
2324
2325     std::vector<float> input0({ 1, 2.9f, 2.1f, 4, 5, 6,
2326                                 7, 8, 9, 10, 11, 12 });
2327
2328     std::vector<float> input1({ 1, 3, 2});
2329
2330     std::vector<uint8_t> output({ 0, 0, 1, 1, 1, 1,
2331                                   1, 1, 1, 1, 1, 1 });
2332
2333     return ElementwiseTestHelper<armnn::GreaterQueueDescriptor, armnn::DataType::Float32, armnn::DataType::Boolean>(
2334         workloadFactory,
2335         memoryManager,
2336         shape0,
2337         input0,
2338         shape1,
2339         input1,
2340         shape0,
2341         output);
2342 }
2343
2344 LayerTestResult<uint8_t, 4> GreaterUint8Test(
2345         armnn::IWorkloadFactory& workloadFactory,
2346         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2347 {
2348     unsigned int shape[] = { 2, 2, 2, 2 };
2349
2350     // See dequantized values to the right.
2351     std::vector<uint8_t> input0({ 1, 1, 1, 1, 6, 6, 6, 6,
2352                                   3, 3, 3, 3, 5, 5, 5, 5 });
2353
2354     std::vector<uint8_t> input1({ 2, 2, 2, 2, 6, 6, 6, 6,
2355                                   2, 2, 2, 2, 5, 5, 5, 5 });
2356
2357     std::vector<uint8_t> output({ 0, 0, 0, 0, 0, 0, 0, 0,
2358                                   1, 1, 1, 1, 0, 0, 0, 0 });
2359
2360     return ElementwiseTestHelper<armnn::GreaterQueueDescriptor,
2361                                  armnn::DataType::QuantisedAsymm8,
2362                                  armnn::DataType::Boolean>(
2363         workloadFactory,
2364         memoryManager,
2365         shape,
2366         input0,
2367         shape,
2368         input1,
2369         shape,
2370         output,
2371         1.0f,
2372         0);
2373 }
2374
2375 LayerTestResult<uint8_t, 4> GreaterBroadcast1ElementUint8Test(
2376         armnn::IWorkloadFactory& workloadFactory,
2377         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2378 {
2379     const unsigned int shape0[] = { 1, 2, 2, 3 };
2380     const unsigned int shape1[] = { 1, 1, 1, 1 };
2381
2382     std::vector<uint8_t> input0({ 1, 2, 3, 4, 5, 6,
2383                                   7, 8, 9, 10, 11, 12 });
2384
2385     std::vector<uint8_t> input1({ 1 });
2386
2387     std::vector<uint8_t> output({ 0, 1, 1, 1, 1, 1,
2388                                   1, 1, 1, 1, 1, 1 });
2389
2390     return ElementwiseTestHelper<armnn::GreaterQueueDescriptor,
2391                                  armnn::DataType::QuantisedAsymm8,
2392                                  armnn::DataType::Boolean>(
2393         workloadFactory,
2394         memoryManager,
2395         shape0,
2396         input0,
2397         shape1,
2398         input1,
2399         shape0,
2400         output,
2401         1.0f,
2402         0);
2403 }
2404
2405 LayerTestResult<uint8_t, 4> GreaterBroadcast1DVectorUint8Test(
2406         armnn::IWorkloadFactory& workloadFactory,
2407         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2408 {
2409     const unsigned int shape0[] = { 1, 2, 2, 3 };
2410     const unsigned int shape1[] = { 1, 1, 1, 3 };
2411
2412     std::vector<uint8_t> input0({ 1, 2, 3, 4, 5, 6,
2413                                   7, 8, 9, 10, 11, 12 });
2414
2415     std::vector<uint8_t> input1({ 1, 1, 3});
2416
2417     std::vector<uint8_t> output({ 0, 1, 0, 1, 1, 1,
2418                                   1, 1, 1, 1, 1, 1 });
2419
2420     return ElementwiseTestHelper<armnn::GreaterQueueDescriptor,
2421                                  armnn::DataType::QuantisedAsymm8,
2422                                  armnn::DataType::Boolean>(
2423         workloadFactory,
2424         memoryManager,
2425         shape0,
2426         input0,
2427         shape1,
2428         input1,
2429         shape0,
2430         output,
2431         1.0f,
2432         0);
2433 }
2434
2435 LayerTestResult<float, 4> MaximumSimpleTest(armnn::IWorkloadFactory& workloadFactory,
2436                                            const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2437 {
2438     const unsigned int width = 2;
2439     const unsigned int height = 2;
2440     const unsigned int channelCount = 2;
2441     const unsigned int batchSize = 2;
2442
2443     unsigned int shape[] = { batchSize, channelCount, height, width };
2444
2445     std::vector<float> input0({ 1, 1, 1, 1,  5, 5, 5, 5,
2446                                 3, 3, 3, 3,  4, 4, 4, 4 });
2447
2448     std::vector<float> input1({ 2, 2, 2, 2,  3, 3, 3, 3,
2449                                 4, 4, 4, 4,  5, 5, 5, 5 });
2450
2451     std::vector<float> output({ 2, 2, 2, 2,  5, 5, 5, 5,
2452                                 4, 4, 4, 4,  5, 5, 5, 5 });
2453
2454     return ElementwiseTestHelper<armnn::MaximumQueueDescriptor, armnn::DataType::Float32>(
2455         workloadFactory,
2456         memoryManager,
2457         shape,
2458         input0,
2459         shape,
2460         input1,
2461         shape,
2462         output);
2463 }
2464
2465 LayerTestResult<float, 4> MaximumBroadcast1ElementTest(
2466         armnn::IWorkloadFactory& workloadFactory,
2467         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2468 {
2469     unsigned int shape0[] = { 1, 2, 2, 2 };
2470     std::vector<float> input0({ 1, 2, 3, 4, 5, 6, 7, 8});
2471
2472     unsigned int shape1[] = { 1, 1, 1, 1 };
2473     std::vector<float> input1({ 2 });
2474
2475     std::vector<float> output({ 2, 2, 3, 4, 5, 6, 7, 8});
2476
2477     return ElementwiseTestHelper<armnn::MaximumQueueDescriptor, armnn::DataType::Float32>(
2478         workloadFactory,
2479         memoryManager,
2480         shape0,
2481         input0,
2482         shape1,
2483         input1,
2484         shape0,
2485         output);
2486 }
2487
2488 LayerTestResult<float, 4> MaximumBroadcast1DVectorTest(
2489         armnn::IWorkloadFactory& workloadFactory,
2490         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2491 {
2492     const unsigned int shape0[] = { 1, 2, 2, 3 };
2493     const unsigned int shape1[] = { 1, 1, 1, 3 };
2494
2495     std::vector<float> input0({ 1, 2, 3, 4, 5, 6,
2496                                   7, 8, 9, 10, 11, 12 });
2497
2498     std::vector<float> input1({ 1, 2, 3});
2499
2500     std::vector<float> output({ 1, 2, 3, 4, 5, 6,
2501                                 7, 8, 9, 10, 11, 12 });
2502
2503     return ElementwiseTestHelper<armnn::MaximumQueueDescriptor, armnn::DataType::Float32>(
2504         workloadFactory,
2505         memoryManager,
2506         shape0,
2507         input0,
2508         shape1,
2509         input1,
2510         shape0,
2511         output);
2512 }
2513
2514 LayerTestResult<uint8_t, 4> MaximumUint8Test(
2515         armnn::IWorkloadFactory& workloadFactory,
2516         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2517 {
2518     unsigned int shape[] = { 2, 2, 2, 2 };
2519
2520     // See dequantized values to the right.
2521     std::vector<uint8_t> input0({ 1, 1, 1, 1, 6, 6, 6, 6,
2522                                   3, 3, 3, 3, 4, 4, 4, 4 });
2523
2524     std::vector<uint8_t> input1({ 2, 2, 2, 2, 3, 3, 3, 3,
2525                                   4, 4, 4, 4, 5, 5, 5, 5 });
2526
2527     std::vector<uint8_t> output({ 2, 2, 2, 2, 6, 6, 6, 6,
2528                                   4, 4, 4, 4, 5, 5, 5, 5 });
2529
2530     return ElementwiseTestHelper<armnn::MaximumQueueDescriptor, armnn::DataType::QuantisedAsymm8>(
2531         workloadFactory,
2532         memoryManager,
2533         shape,
2534         input0,
2535         shape,
2536         input1,
2537         shape,
2538         output,
2539         1.0f,
2540         0);
2541 }
2542
2543 LayerTestResult<uint8_t, 4> MaximumBroadcast1ElementUint8Test(
2544         armnn::IWorkloadFactory& workloadFactory,
2545         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2546 {
2547     const unsigned int shape0[] = { 1, 2, 2, 3 };
2548     const unsigned int shape1[] = { 1, 1, 1, 1 };
2549
2550     std::vector<uint8_t> input0({ 1, 2, 3, 4,  5, 6,
2551                                   7, 8, 9, 10, 11, 12 });
2552
2553     std::vector<uint8_t> input1({2});
2554
2555     std::vector<uint8_t> output({ 2, 2, 3, 4, 5, 6,
2556                                   7, 8, 9, 10, 11, 12 });
2557
2558     return ElementwiseTestHelper<armnn::MaximumQueueDescriptor, armnn::DataType::QuantisedAsymm8>(
2559         workloadFactory,
2560         memoryManager,
2561         shape0,
2562         input0,
2563         shape1,
2564         input1,
2565         shape0,
2566         output,
2567         1.0f,
2568         0);
2569 }
2570
2571 LayerTestResult<uint8_t, 4> MaximumBroadcast1DVectorUint8Test(
2572         armnn::IWorkloadFactory& workloadFactory,
2573         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2574 {
2575     const unsigned int shape0[] = { 1, 2, 2, 3 };
2576     const unsigned int shape1[] = { 1, 1, 1, 3 };
2577
2578     std::vector<uint8_t> input0({ 1, 2, 3, 4, 5, 6,
2579                                   7, 8, 9, 10, 11, 12 });
2580
2581     std::vector<uint8_t> input1({ 1, 10, 3});
2582
2583     std::vector<uint8_t> output({ 1, 10, 3, 4, 10, 6,
2584                                   7, 10, 9, 10, 11, 12 });
2585
2586     return ElementwiseTestHelper<armnn::MaximumQueueDescriptor, armnn::DataType::QuantisedAsymm8>(
2587         workloadFactory,
2588         memoryManager,
2589         shape0,
2590         input0,
2591         shape1,
2592         input1,
2593         shape0,
2594         output,
2595         1.0f,
2596         0);
2597 }
2598
2599 LayerTestResult<int16_t, 4> MaximumInt16Test(
2600     armnn::IWorkloadFactory& workloadFactory,
2601     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2602 {
2603     unsigned int shape[] = { 2, 2, 2, 2 };
2604
2605     std::vector<int16_t> input0({ 1, 1, 1, 1, 6, 6, 6, 6,
2606                                   3, 3, 3, 3, 4, 4, 4, 4 });
2607
2608     std::vector<int16_t> input1({ 2, 2, 2, 2, 3, 3, 3, 3,
2609                                   4, 4, 4, 4, 5, 5, 5, 5 });
2610
2611     std::vector<int16_t> output({ 2, 2, 2, 2, 6, 6, 6, 6,
2612                                   4, 4, 4, 4, 5, 5, 5, 5 });
2613
2614     return ElementwiseTestHelper<armnn::MaximumQueueDescriptor, armnn::DataType::QuantisedSymm16>(
2615         workloadFactory,
2616         memoryManager,
2617         shape,
2618         input0,
2619         shape,
2620         input1,
2621         shape,
2622         output,
2623         1.0f,
2624         0);
2625 }
2626
2627 LayerTestResult<int16_t, 4> MaximumBroadcast1ElementInt16Test(
2628     armnn::IWorkloadFactory& workloadFactory,
2629     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2630 {
2631     const unsigned int shape0[] = { 1, 2, 2, 3 };
2632     const unsigned int shape1[] = { 1, 1, 1, 1 };
2633
2634     std::vector<int16_t> input0({ 1, 2, 3, 4,  5, 6,
2635                                   7, 8, 9, 10, 11, 12 });
2636
2637     std::vector<int16_t> input1({2});
2638
2639     std::vector<int16_t> output({ 2, 2, 3, 4, 5, 6,
2640                                   7, 8, 9, 10, 11, 12 });
2641
2642     return ElementwiseTestHelper<armnn::MaximumQueueDescriptor, armnn::DataType::QuantisedSymm16>(
2643         workloadFactory,
2644         memoryManager,
2645         shape0,
2646         input0,
2647         shape1,
2648         input1,
2649         shape0,
2650         output,
2651         1.0f,
2652         0);
2653 }
2654
2655 LayerTestResult<int16_t, 4> MaximumBroadcast1DVectorInt16Test(
2656     armnn::IWorkloadFactory& workloadFactory,
2657     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2658 {
2659     const unsigned int shape0[] = { 1, 2, 2, 3 };
2660     const unsigned int shape1[] = { 1, 1, 1, 3 };
2661
2662     std::vector<int16_t> input0({ 1, 2, 3, 4, 5, 6,
2663                                   7, 8, 9, 10, 11, 12 });
2664
2665     std::vector<int16_t> input1({ 1, 10, 3});
2666
2667     std::vector<int16_t> output({ 1, 10, 3, 4, 10, 6,
2668                                   7, 10, 9, 10, 11, 12 });
2669
2670     return ElementwiseTestHelper<armnn::MaximumQueueDescriptor, armnn::DataType::QuantisedSymm16>(
2671         workloadFactory,
2672         memoryManager,
2673         shape0,
2674         input0,
2675         shape1,
2676         input1,
2677         shape0,
2678         output,
2679         1.0f,
2680         0);
2681 }
2682
2683 LayerTestResult<float, 4> MinimumBroadcast1ElementTest1(
2684     armnn::IWorkloadFactory& workloadFactory,
2685     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2686 {
2687     unsigned int shape0[] = { 1, 2, 2, 2 };
2688     std::vector<float> input0({ 1, 2, 3, 4, 5, 6, 7, 8});
2689
2690     unsigned int shape1[] = { 1, 1, 1, 1 };
2691     std::vector<float> input1({ 2 });
2692
2693     std::vector<float> output({ 1, 2, 2, 2, 2, 2, 2, 2});
2694
2695     return ElementwiseTestHelper<armnn::MinimumQueueDescriptor, armnn::DataType::Float32>(
2696         workloadFactory,
2697         memoryManager,
2698         shape0,
2699         input0,
2700         shape1,
2701         input1,
2702         shape0,
2703         output);
2704 }
2705
2706
2707 LayerTestResult<float, 4> MinimumBroadcast1ElementTest2(
2708     armnn::IWorkloadFactory& workloadFactory,
2709     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2710 {
2711     unsigned int shape0[] = { 1, 2, 2, 2 };
2712     std::vector<float> input0({ 1, 6, 3, 2, 8, 9, 1, 10});
2713
2714     unsigned int shape1[] = { 1, 1, 1, 1 };
2715     std::vector<float> input1({ 5 });
2716
2717     std::vector<float> output({ 1, 5, 3, 2, 5, 5, 1, 5});
2718
2719     return ElementwiseTestHelper<armnn::MinimumQueueDescriptor, armnn::DataType::Float32>(
2720         workloadFactory,
2721         memoryManager,
2722         shape0,
2723         input0,
2724         shape1,
2725         input1,
2726         shape0,
2727         output);
2728 }
2729
2730 LayerTestResult<uint8_t, 4> MinimumBroadcast1DVectorUint8Test(
2731     armnn::IWorkloadFactory & workloadFactory,
2732     const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager)
2733 {
2734     const unsigned int shape0[] = { 1, 2, 2, 3 };
2735     const unsigned int shape1[] = { 1, 1, 1, 3 };
2736
2737     std::vector<uint8_t> input0({ 1, 2, 3, 3, 2, 1,
2738                                   7, 1, 2, 3, 4, 5 });
2739
2740     std::vector<uint8_t> input1({ 1, 2, 3});
2741
2742     std::vector<uint8_t> output({ 1, 2, 3, 1, 2, 1,
2743                                   1, 1, 2, 1, 2, 3 });
2744
2745     return ElementwiseTestHelper<armnn::MinimumQueueDescriptor, armnn::DataType::QuantisedAsymm8>(
2746         workloadFactory,
2747         memoryManager,
2748         shape0,
2749         input0,
2750         shape1,
2751         input1,
2752         shape0,
2753         output,
2754         1.0f,
2755         0);
2756 }
2757
2758 LayerTestResult<int16_t, 4> MinimumInt16Test(
2759     armnn::IWorkloadFactory& workloadFactory,
2760     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2761 {
2762     unsigned int shape[] = { 2, 2, 2, 2 };
2763
2764     std::vector<int16_t> input0({ 1, 1, 1, 1, 6, 6, 6, 6,
2765                                   3, 3, 3, 3, 4, 4, 4, 4 });
2766
2767     std::vector<int16_t> input1({ 2, 2, 2, 2, 3, 3, 3, 3,
2768                                   4, 4, 4, 4, 5, 5, 5, 5 });
2769
2770     std::vector<int16_t> output({ 1, 1, 1, 1, 3, 3, 3, 3,
2771                                   3, 3, 3, 3, 4, 4, 4, 4 });
2772
2773     return ElementwiseTestHelper<armnn::MinimumQueueDescriptor, armnn::DataType::QuantisedSymm16>(
2774         workloadFactory,
2775         memoryManager,
2776         shape,
2777         input0,
2778         shape,
2779         input1,
2780         shape,
2781         output,
2782         1.0f,
2783         0);
2784 }
2785
2786 LayerTestResult<int16_t, 4> MinimumBroadcast1ElementInt16Test(
2787     armnn::IWorkloadFactory& workloadFactory,
2788     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2789 {
2790     const unsigned int shape0[] = { 1, 2, 2, 3 };
2791     const unsigned int shape1[] = { 1, 1, 1, 1 };
2792
2793     std::vector<int16_t> input0({ 1, 2, 3, 4,  5, 6,
2794                                   7, 8, 9, 10, 11, 12 });
2795
2796     std::vector<int16_t> input1({2});
2797
2798     std::vector<int16_t> output({ 1, 2, 2, 2, 2, 2,
2799                                   2, 2, 2, 2, 2, 2 });
2800
2801     return ElementwiseTestHelper<armnn::MinimumQueueDescriptor, armnn::DataType::QuantisedSymm16>(
2802         workloadFactory,
2803         memoryManager,
2804         shape0,
2805         input0,
2806         shape1,
2807         input1,
2808         shape0,
2809         output,
2810         1.0f,
2811         0);
2812 }
2813
2814 LayerTestResult<int16_t, 4> MinimumBroadcast1DVectorInt16Test(
2815     armnn::IWorkloadFactory& workloadFactory,
2816     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2817 {
2818     const unsigned int shape0[] = { 1, 2, 2, 3 };
2819     const unsigned int shape1[] = { 1, 1, 1, 3 };
2820
2821     std::vector<int16_t> input0({ 1, 2, 3, 4, 5, 6,
2822                                   7, 8, 9, 10, 11, 12 });
2823
2824     std::vector<int16_t> input1({ 1, 10, 3});
2825
2826     std::vector<int16_t> output({ 1, 2, 3, 1, 5, 3,
2827                                   1, 8, 3, 1, 10, 3 });
2828
2829     return ElementwiseTestHelper<armnn::MinimumQueueDescriptor, armnn::DataType::QuantisedSymm16>(
2830         workloadFactory,
2831         memoryManager,
2832         shape0,
2833         input0,
2834         shape1,
2835         input1,
2836         shape0,
2837         output,
2838         1.0f,
2839         0);
2840 }
2841
2842 namespace {
2843 LayerTestResult<float,4> MultiplicationTestHelper(
2844     armnn::IWorkloadFactory& workloadFactory,
2845     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
2846     const unsigned int shape0[4],
2847     const std::vector<float> & values0,
2848     const unsigned int shape1[4],
2849     const std::vector<float> & values1,
2850     const unsigned int outShape[4],
2851     const std::vector<float> & outValues)
2852 {
2853     const size_t dimensionCount = 4;
2854     armnn::TensorInfo inputTensorInfo0{dimensionCount, shape0, armnn::DataType::Float32};
2855     armnn::TensorInfo inputTensorInfo1{dimensionCount, shape1, armnn::DataType::Float32};
2856     armnn::TensorInfo outputTensorInfo{dimensionCount, outShape, armnn::DataType::Float32};
2857
2858     auto input0 = MakeTensor<float, 4>(inputTensorInfo0, values0);
2859     auto input1 = MakeTensor<float, 4>(inputTensorInfo1, values1);
2860
2861     LayerTestResult<float,4> ret(outputTensorInfo);
2862
2863     std::unique_ptr<armnn::ITensorHandle> inputHandle0 = workloadFactory.CreateTensorHandle(inputTensorInfo0);
2864     std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
2865     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
2866
2867     armnn::MultiplicationQueueDescriptor data;
2868     armnn::WorkloadInfo info;
2869     AddInputToWorkload(data, info, inputTensorInfo0, inputHandle0.get());
2870     AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get());
2871     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
2872
2873     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateMultiplication(data, info);
2874
2875     inputHandle0->Allocate();
2876     inputHandle1->Allocate();
2877     outputHandle->Allocate();
2878
2879     CopyDataToITensorHandle(inputHandle0.get(), &input0[0][0][0][0]);
2880     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
2881
2882     workload->PostAllocationConfigure();
2883     workload->Execute();
2884
2885     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
2886
2887     ret.outputExpected = MakeTensor<float, 4>(outputTensorInfo, outValues);
2888     return ret;
2889 }
2890 } // anonymous namespace
2891
2892
2893 LayerTestResult<float,4> MultiplicationTest(
2894     armnn::IWorkloadFactory& workloadFactory,
2895     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2896 {
2897     const unsigned int width = 2;
2898     const unsigned int height = 2;
2899     const unsigned int channelCount = 2;
2900     const unsigned int batchSize = 2;
2901
2902     unsigned int shape[] = { batchSize, channelCount, height, width };
2903
2904     std::vector<float> input0({
2905         1,  1,  1,  1,    2,  2,  2,  2,
2906         3,  3,  3,  3,    4,  4,  4,  4 });
2907
2908     std::vector<float> input1({
2909         2,  2,  2,  2,    3,  3,  3,  3,
2910         4,  4,  4,  4,    5,  5,  5,  5 });
2911
2912     std::vector<float> output({
2913         2,  2,  2,  2,    6,  6,  6,  6,
2914         12, 12, 12, 12,  20, 20, 20, 20 });
2915
2916     return MultiplicationTestHelper(workloadFactory,
2917                                     memoryManager,
2918                                     shape,
2919                                     input0,
2920                                     shape,
2921                                     input1,
2922                                     shape,
2923                                     output);
2924 }
2925
2926 LayerTestResult<float, 4> MultiplicationBroadcast1ElementTest(
2927     armnn::IWorkloadFactory& workloadFactory,
2928     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2929 {
2930     unsigned int shape0[] = { 1, 2, 2, 2 };
2931     std::vector<float> input0({ 1, 2, 3, 4, 5, 6, 7, 8});
2932
2933     unsigned int shape1[] = { 1, 1, 1, 1 };
2934     std::vector<float> input1({ 2 });
2935
2936     std::vector<float> output({ 2, 4, 6, 8, 10, 12, 14, 16});
2937
2938     return MultiplicationTestHelper(workloadFactory,
2939                                     memoryManager,
2940                                     shape0,
2941                                     input0,
2942                                     shape1,
2943                                     input1,
2944                                     shape0,
2945                                     output);
2946 }
2947
2948 LayerTestResult<float, 4> MultiplicationBroadcast1DVectorTest(
2949     armnn::IWorkloadFactory& workloadFactory,
2950     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
2951 {
2952     unsigned int shape0[] = { 1, 3, 3, 2 };
2953     std::vector<float> input0({
2954         1,   2,      3,  4,      5,  6,
2955         7,   8,      9, 10,     11, 12,
2956         13, 14,     15, 16,     17, 18});
2957
2958     unsigned int shape1[] = { 1, 1, 1, 2 };
2959     std::vector<float> input1({ 1, 2 });
2960
2961     std::vector<float> output({
2962         1,   4,       3,  8,      5, 12,
2963         7,   16,      9, 20,     11, 24,
2964         13,  28,     15, 32,     17, 36});
2965
2966     return MultiplicationTestHelper(workloadFactory,
2967                                     memoryManager,
2968                                     shape0,
2969                                     input0,
2970                                     shape1,
2971                                     input1,
2972                                     shape0,
2973                                     output);
2974 }
2975
2976 LayerTestResult<float,4> CompareMultiplicationTest(
2977     armnn::IWorkloadFactory& workloadFactory,
2978     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
2979     armnn::IWorkloadFactory& refWorkloadFactory)
2980 {
2981     const unsigned int width = 16;
2982     const unsigned int height = 32;
2983     const unsigned int channelCount = 2;
2984     const unsigned int batchSize = 5;
2985
2986     armnn::TensorInfo inputTensorInfo0;
2987     armnn::TensorInfo inputTensorInfo1;
2988     armnn::TensorInfo outputTensorInfo;
2989
2990     constexpr unsigned int shape[] = { batchSize, channelCount, height, width };
2991
2992     inputTensorInfo0 = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
2993     inputTensorInfo1 = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
2994     outputTensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
2995
2996     LayerTestResult<float,4> comparisonResult(outputTensorInfo);
2997
2998     auto input0 = MakeRandomTensor<float, 4>(inputTensorInfo0, 803506992);
2999     auto input1 = MakeRandomTensor<float, 4>(inputTensorInfo1, 54902257);
3000
3001     std::unique_ptr<armnn::ITensorHandle> inputHandle0 = workloadFactory.CreateTensorHandle(inputTensorInfo0);
3002     std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
3003     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
3004
3005     std::unique_ptr<armnn::ITensorHandle> inputHandle0Ref = refWorkloadFactory.CreateTensorHandle(inputTensorInfo0);
3006     std::unique_ptr<armnn::ITensorHandle> inputHandle1Ref = refWorkloadFactory.CreateTensorHandle(inputTensorInfo1);
3007     std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refWorkloadFactory.CreateTensorHandle(outputTensorInfo);
3008
3009     armnn::MultiplicationQueueDescriptor data;
3010     armnn::WorkloadInfo info;
3011     AddInputToWorkload(data, info, inputTensorInfo0, inputHandle0.get());
3012     AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get());
3013     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
3014
3015     armnn::MultiplicationQueueDescriptor refData = data;
3016     armnn::WorkloadInfo refInfo = info;
3017     SetWorkloadInput(refData, refInfo, 0, inputTensorInfo0, inputHandle0Ref.get());
3018     SetWorkloadInput(refData, refInfo, 1, inputTensorInfo1, inputHandle1Ref.get());
3019     SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
3020
3021     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateMultiplication(data, info);
3022     std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreateMultiplication(refData, refInfo);
3023
3024     inputHandle0->Allocate();
3025     inputHandle1->Allocate();
3026     outputHandle->Allocate();
3027     inputHandle0Ref->Allocate();
3028     inputHandle1Ref->Allocate();
3029     outputHandleRef->Allocate();
3030
3031     CopyDataToITensorHandle(inputHandle0.get(), &input0[0][0][0][0]);
3032     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
3033     CopyDataToITensorHandle(inputHandle0Ref.get(), &input0[0][0][0][0]);
3034     CopyDataToITensorHandle(inputHandle1Ref.get(), &input1[0][0][0][0]);
3035
3036     workload->PostAllocationConfigure();
3037     workload->Execute();
3038     workloadRef->PostAllocationConfigure();
3039     workloadRef->Execute();
3040     CopyDataFromITensorHandle(&comparisonResult.output[0][0][0][0], outputHandle.get());
3041     CopyDataFromITensorHandle(&comparisonResult.outputExpected[0][0][0][0], outputHandleRef.get());
3042
3043     return comparisonResult;
3044 }
3045
3046 LayerTestResult<float,4> CompareBatchNormTest(
3047     armnn::IWorkloadFactory& workloadFactory,
3048     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3049     armnn::IWorkloadFactory& refWorkloadFactory)
3050 {
3051     const unsigned int width     = 2;
3052     const unsigned int height    = 3;
3053     const unsigned int channels  = 5;
3054     const unsigned int batchSize = 3;
3055
3056     armnn::TensorInfo inputTensorInfo;
3057     armnn::TensorInfo outputTensorInfo;
3058     armnn::TensorInfo tensorInfo;
3059
3060     constexpr unsigned int shape[]       = {batchSize, channels, height, width};
3061     constexpr unsigned int tensorShape[] = {channels};
3062
3063     inputTensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
3064     outputTensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
3065     tensorInfo = armnn::TensorInfo(1, tensorShape, armnn::DataType::Float32);
3066
3067     auto input = MakeRandomTensor<float, 4>(inputTensorInfo, 21312);
3068
3069     auto mean     = MakeRandomTensor<float, 1>(tensorInfo, 123);
3070     auto variance = MakeRandomTensor<float, 1>(tensorInfo, 234, 0.0f);
3071     auto beta     = MakeRandomTensor<float, 1>(tensorInfo, 123);
3072     auto gamma    = MakeRandomTensor<float, 1>(tensorInfo, 345);
3073
3074     LayerTestResult<float,4> ret(outputTensorInfo);
3075
3076     std::unique_ptr<armnn::ITensorHandle> inputHandle  = workloadFactory.CreateTensorHandle(inputTensorInfo);
3077     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
3078
3079     std::unique_ptr<armnn::ITensorHandle> inputHandleRef  = refWorkloadFactory.CreateTensorHandle(inputTensorInfo);
3080     std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refWorkloadFactory.CreateTensorHandle(outputTensorInfo);
3081
3082     armnn::BatchNormalizationQueueDescriptor data;
3083     armnn::WorkloadInfo info;
3084     armnn::ScopedCpuTensorHandle meanTensor(tensorInfo);
3085     armnn::ScopedCpuTensorHandle varianceTensor(tensorInfo);
3086     armnn::ScopedCpuTensorHandle betaTensor(tensorInfo);
3087     armnn::ScopedCpuTensorHandle gammaTensor(tensorInfo);
3088
3089     AllocateAndCopyDataToITensorHandle(&meanTensor, &mean[0]);
3090     AllocateAndCopyDataToITensorHandle(&varianceTensor, &variance[0]);
3091     AllocateAndCopyDataToITensorHandle(&betaTensor, &beta[0]);
3092     AllocateAndCopyDataToITensorHandle(&gammaTensor, &gamma[0]);
3093
3094     AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
3095     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
3096     data.m_Mean             = &meanTensor;
3097     data.m_Variance         = &varianceTensor;
3098     data.m_Beta             = &betaTensor;
3099     data.m_Gamma            = &gammaTensor;
3100     data.m_Parameters.m_Eps = 0.01f;
3101
3102     armnn::BatchNormalizationQueueDescriptor refData = data;
3103     armnn::WorkloadInfo refInfo = info;
3104     SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
3105     SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
3106
3107     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateBatchNormalization(data, info);
3108     std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreateBatchNormalization(refData, refInfo);
3109
3110     inputHandle->Allocate();
3111     outputHandle->Allocate();
3112     inputHandleRef->Allocate();
3113     outputHandleRef->Allocate();
3114
3115     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
3116     CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0][0][0]);
3117
3118     workload->PostAllocationConfigure();
3119     workload->Execute();
3120     workloadRef->PostAllocationConfigure();
3121     workloadRef->Execute();
3122
3123     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
3124     CopyDataFromITensorHandle(&ret.outputExpected[0][0][0][0], outputHandleRef.get());
3125
3126     return ret;
3127 }
3128
3129 template<typename T>
3130 void PermuteTensorData(
3131         armnn::IWorkloadFactory& workloadFactory,
3132         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3133         const armnn::PermutationVector& mappings,
3134         armnn::TensorInfo & inputTensorInfo,
3135         const T * inputData,
3136         std::vector<T>& outputData)
3137 {
3138     BOOST_ASSERT_MSG(inputData != nullptr, "inputData must not be null");
3139     if (inputData == nullptr)
3140     {
3141         // Nullptr is an error in the test. By returning without doing the concatenation
3142         // I expect the caller to fail the test. It still makes sense to report this as
3143         // an assert for Debug builds.
3144         return;
3145     }
3146
3147     armnn::TensorInfo outputTensorInfo = armnnUtils::Permuted(inputTensorInfo, mappings);
3148
3149     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
3150     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
3151
3152     armnn::PermuteQueueDescriptor queueDescriptor;
3153     queueDescriptor.m_Parameters = armnn::PermuteDescriptor{mappings};
3154     armnn::WorkloadInfo workloadInfo;
3155     AddInputToWorkload(queueDescriptor, workloadInfo, inputTensorInfo, inputHandle.get());
3156     AddOutputToWorkload(queueDescriptor, workloadInfo, outputTensorInfo, outputHandle.get());
3157
3158     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePermute(queueDescriptor, workloadInfo);
3159
3160     inputHandle->Allocate();
3161     outputHandle->Allocate();
3162
3163     CopyDataToITensorHandle(inputHandle.get(), inputData);
3164
3165     workload->PostAllocationConfigure();
3166     workload->Execute();
3167
3168     outputData.resize(outputTensorInfo.GetNumElements());
3169     CopyDataFromITensorHandle(&outputData[0], outputHandle.get());
3170     inputTensorInfo = outputTensorInfo;
3171 }
3172
3173 armnn::OriginsDescriptor CreateMergerDescriptorForConcatenation(
3174         const std::vector<armnn::TensorInfo> & inputTensorInfos,
3175         unsigned int concatDim)
3176 {
3177     std::vector<armnn::TensorShape> shapes;
3178     shapes.reserve(inputTensorInfos.size());
3179     for (const armnn::TensorInfo& it: inputTensorInfos)
3180     {
3181         shapes.push_back(it.GetShape());
3182     }
3183
3184     return armnn::CreateMergerDescriptorForConcatenation(shapes.begin(),
3185                                                          shapes.end(),
3186                                                          concatDim);
3187 }
3188
3189 //
3190 // Concatenation is only supported for N and C dimensions for NCHW and the inner most dimension
3191 // In case of <4 dimensions we need to make sure that the concat dimensions are at least
3192 // the 3rd slowest iterating one or the inner most dimension.
3193 //
3194
3195 bool NeedPermuteForConcat(
3196         const std::vector<armnn::TensorInfo> & inputTensorInfos,
3197         unsigned int concatDim)
3198 {
3199     // See note above. Additionally we expect the input shapes to have the
3200     // same number of dimensions.
3201     unsigned int nDimensions = 0;
3202
3203     // Determine the number of dimensions as well as sanity check them
3204     // agains test implementation issues.
3205     for (auto && tensorInfo : inputTensorInfos)
3206     {
3207         if (!nDimensions)
3208         {
3209             nDimensions = tensorInfo.GetShape().GetNumDimensions();
3210         }
3211         else
3212         {
3213             BOOST_ASSERT_MSG(nDimensions == tensorInfo.GetShape().GetNumDimensions(),
3214                 "Input shapes must have the same number of dimensions");
3215         }
3216     }
3217
3218     return (nDimensions < 3 || (nDimensions == 3 && (nDimensions-concatDim) < 3 && (nDimensions-concatDim) != 1));
3219 }
3220
3221 armnn::TensorShape ExpandTensorShapeTo3dForPermute(const armnn::TensorShape & inputShape)
3222 {
3223     unsigned int numDims = inputShape.GetNumDimensions();
3224     if (numDims >= 3)
3225     {
3226         // Nothing to do if the inputShape has at least 3 dimensions.
3227         return inputShape;
3228     }
3229
3230     std::vector<unsigned int> newDims(size_t(3), 1u);
3231     unsigned int expandedBy = 3 - numDims;
3232     for (unsigned int i=0; i<numDims; ++i)
3233     {
3234         newDims[expandedBy+i] = inputShape[i];
3235     }
3236     return armnn::TensorShape(3u, &newDims[0]);
3237 }
3238
3239 void Generate3dPermuteVectorForConcat(
3240         unsigned int numDimensions,
3241         unsigned int & concatDim,
3242         std::pair<armnn::PermutationVector, armnn::PermutationVector> & permutations)
3243 {
3244     BOOST_ASSERT_MSG(numDimensions <= 3,
3245        "Only dimensions 1,2 and 3 are supported by this helper");
3246     unsigned int expandedBy = 3 - numDimensions;
3247     unsigned int expandedConcatAxis = concatDim + expandedBy;
3248
3249     if (expandedConcatAxis == 2)
3250     {
3251         concatDim = 0;
3252         armnn::PermutationVector forwardPermutation({1, 2, 0});
3253         armnn::PermutationVector reversePermutation({2, 0, 1});
3254         permutations = std::make_pair(forwardPermutation, reversePermutation);
3255     }
3256     else if (expandedConcatAxis == 1)
3257     {
3258         concatDim = 0;
3259         armnn::PermutationVector forwardPermutation({2, 0, 1});
3260         armnn::PermutationVector reversePermutation({1, 2, 0});
3261         permutations = std::make_pair(forwardPermutation, reversePermutation);
3262     }
3263     else
3264     {
3265         BOOST_ASSERT(expandedConcatAxis == 0);
3266         concatDim = 0;
3267     }
3268 }
3269
3270 //
3271 // Permute the input tensors so we can do a supported concatenation.
3272 // Also treat lower than 3d tensors as 3d by adding dummy 1 dimensions
3273 // at the front. Finally this function tells what the output shape
3274 // of the permuted concatenated tensor is going to be.
3275 //
3276 template <typename T>
3277 void PermuteInputsForConcat(
3278         armnn::IWorkloadFactory& workloadFactory,
3279         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3280         std::vector<armnn::TensorInfo> & inputTensorInfos,
3281         std::vector<T *> & inputData,
3282         std::vector<std::vector<T>> & inputDataStorage,
3283         armnn::PermutationVector & permuteVector,
3284         unsigned int & concatDim,
3285         armnn::TensorInfo & outputTensorInfo)
3286 {
3287     BOOST_ASSERT_MSG(inputTensorInfos.size() > 1,
3288         "Expecting more than one tensor to be concatenated here");
3289
3290     unsigned int numDims = 0;
3291     unsigned int nthInput = 0;
3292     const armnn::PermutationVector identity({0, 1, 2});
3293
3294     std::pair<armnn::PermutationVector, armnn::PermutationVector> permutations =
3295         std::make_pair(identity, identity);
3296
3297     inputDataStorage.resize(inputData.size());
3298
3299     for (auto && tensorInfo : inputTensorInfos)
3300     {
3301         if (numDims == 0)
3302         {
3303             numDims = tensorInfo.GetShape().GetNumDimensions();
3304             Generate3dPermuteVectorForConcat(numDims, concatDim, permutations);
3305
3306             // Store the reverese permutation.
3307             permuteVector = permutations.second;
3308             BOOST_ASSERT_MSG(!permuteVector.IsEqual(identity),
3309                 "Test logic error, we don't need permutation, so we shouldn't arrive here");
3310         }
3311         else
3312         {
3313             BOOST_ASSERT_MSG(numDims == tensorInfo.GetShape().GetNumDimensions(),
3314                 "All inputs must have the same number of dimensions");
3315         }
3316
3317         armnn::TensorInfo newTensorInfo = tensorInfo;
3318         newTensorInfo.SetShape(ExpandTensorShapeTo3dForPermute(tensorInfo.GetShape()));
3319
3320         PermuteTensorData<T>(workloadFactory,
3321                              memoryManager,
3322                              permutations.first,
3323                              newTensorInfo,
3324                              inputData[nthInput],
3325                              inputDataStorage[nthInput]);
3326
3327         inputData[nthInput] = inputDataStorage[nthInput].data();
3328         inputTensorInfos[nthInput] = newTensorInfo;
3329
3330         ++nthInput;
3331     }
3332
3333     outputTensorInfo.SetShape(
3334         armnnUtils::Permuted(
3335             ExpandTensorShapeTo3dForPermute(outputTensorInfo.GetShape()),
3336             permutations.first));
3337 }
3338
3339
3340 //
3341 // This is the pair of PermuteInputsForConcat(...) which permutes back
3342 // the output of the concatenation so we can check it against an expected
3343 // output.
3344 //
3345 template <typename T>
3346 void PermuteOutputForConcat(
3347         armnn::IWorkloadFactory& workloadFactory,
3348         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3349         const armnn::TensorInfo & tensorInfo,
3350         const armnn::PermutationVector & permuteVector,
3351         std::unique_ptr<armnn::ITensorHandle> && inputDataHandle,
3352         T * data)
3353 {
3354     BOOST_ASSERT_MSG(data != nullptr, "data must not be null");
3355     if (data == nullptr)
3356     {
3357         // Nullptr is an error in the test. By returning without doing the permutation
3358         // I expect the caller to fail the test. It still makes sense to report this as
3359         // an assert for Debug builds.
3360         return;
3361     }
3362
3363     armnn::TensorInfo resultTensorInfo = tensorInfo;
3364     std::vector<T> inputData(tensorInfo.GetNumElements());
3365     std::vector<T> outputData;
3366
3367     CopyDataFromITensorHandle(&inputData[0], inputDataHandle.get());
3368
3369     PermuteTensorData<T>(workloadFactory,
3370                          memoryManager,
3371                          permuteVector,
3372                          resultTensorInfo,
3373                          &inputData[0],
3374                          outputData);
3375
3376     ::memcpy(data, &outputData[0], sizeof(T)*outputData.size());
3377 }
3378
3379 template <typename T>
3380 void Concatenate(
3381     armnn::IWorkloadFactory& workloadFactory,
3382     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3383     std::initializer_list<const armnn::TensorInfo> inputTensorInfosOrig,
3384     std::initializer_list<T *> inputsOrig,
3385     const armnn::TensorInfo& outputTensorInfoOrig,
3386     T * output,
3387     unsigned int concatDim,
3388     bool useSubtensor)
3389 {
3390     BOOST_ASSERT_MSG(output != nullptr, "output must not be null");
3391     if (output == nullptr)
3392     {
3393         // Nullptr is an error in the test. By returning without doing the permutation
3394         // I expect the caller to fail the test. It still makes sense to report this as
3395         // an assert for Debug builds.
3396         return;
3397     }
3398
3399     // Saves a copy of the parameters which we might need to change.
3400     std::vector<armnn::TensorInfo> inputTensorInfos(inputTensorInfosOrig.begin(), inputTensorInfosOrig.end());
3401     std::vector<T *> inputs            = inputsOrig;
3402     armnn::TensorInfo outputTensorInfo = outputTensorInfoOrig;
3403
3404     armnn::PermutationVector permuteVector{0, 1, 2};
3405
3406     // Holds and automatically releases memory for the reshaped input data.
3407     std::vector<std::vector<T>> tmpInputDataStorage;
3408
3409     const size_t inputCount = inputTensorInfos.size();
3410
3411     bool needPermuteForConcat = NeedPermuteForConcat(inputTensorInfos, concatDim);
3412
3413     if (needPermuteForConcat)
3414     {
3415         //
3416         // We need to permute the inputs, because concatenation along
3417         // the requested axis is not supported.
3418         //
3419         PermuteInputsForConcat<T>(workloadFactory,
3420                                   memoryManager,
3421                                   inputTensorInfos,
3422                                   inputs,
3423                                   tmpInputDataStorage,
3424                                   permuteVector,
3425                                   concatDim,
3426                                   outputTensorInfo);
3427     }
3428
3429     armnn::WorkloadInfo workloadInfo;
3430
3431     std::vector<std::unique_ptr<armnn::ITensorHandle>> inputHandles;
3432     inputHandles.reserve(inputCount);
3433
3434     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
3435
3436     armnn::MergerQueueDescriptor queueDescriptor;
3437     armnn::OriginsDescriptor viewsDescriptor = CreateMergerDescriptorForConcatenation(inputTensorInfos, concatDim);
3438     queueDescriptor.m_Parameters = viewsDescriptor;
3439
3440     if (useSubtensor)
3441     {
3442         queueDescriptor.m_ViewOrigins.reserve(viewsDescriptor.GetNumViews());
3443         for (unsigned int i = 0; i < viewsDescriptor.GetNumViews(); ++i)
3444         {
3445             queueDescriptor.m_ViewOrigins.emplace_back(std::vector<unsigned int>(viewsDescriptor.GetViewOrigin(i),
3446                 viewsDescriptor.GetViewOrigin(i) + viewsDescriptor.GetNumDimensions()));
3447         }
3448
3449         outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
3450
3451         const bool subTensorsSupported = workloadFactory.SupportsSubTensors();
3452         for (unsigned int i = 0; i < inputCount; ++i)
3453         {
3454             const armnn::TensorInfo& inputTensorInfo = inputTensorInfos[i];
3455             std::unique_ptr<armnn::ITensorHandle> inputHandle =
3456                 subTensorsSupported ?
3457                     workloadFactory.CreateSubTensorHandle(*outputHandle,
3458                                                           inputTensorInfo.GetShape(),
3459                                                           queueDescriptor.m_ViewOrigins[i].m_Origin.data()) :
3460                     workloadFactory.CreateTensorHandle(inputTensorInfo);
3461
3462             inputHandles.emplace_back(std::move(inputHandle));
3463         }
3464
3465     }
3466     else
3467     {
3468         for (unsigned int i = 0; i < inputCount; ++i)
3469         {
3470             std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfos[i]);
3471             inputHandles.emplace_back(std::move(inputHandle));
3472         }
3473     }
3474
3475     for (unsigned int i = 0; i < inputCount; ++i)
3476     {
3477         AddInputToWorkload(queueDescriptor, workloadInfo, inputTensorInfos[i], inputHandles[i].get());
3478     }
3479
3480     AddOutputToWorkload(queueDescriptor, workloadInfo, outputTensorInfo, outputHandle.get());
3481
3482     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateMerger(queueDescriptor, workloadInfo);
3483
3484     for (auto& inputHandle : inputHandles)
3485     {
3486         inputHandle->Allocate();
3487     }
3488
3489     outputHandle->Allocate();
3490
3491     unsigned int nextInputId = 0;
3492     for (auto& inputHandle : inputHandles)
3493     {
3494         CopyDataToITensorHandle(inputHandle.get(), inputs[nextInputId]);
3495         ++nextInputId;
3496     }
3497
3498     workload->PostAllocationConfigure();
3499     workload->Execute();
3500
3501     if (needPermuteForConcat)
3502     {
3503         PermuteOutputForConcat<T>(workloadFactory,
3504                                   memoryManager,
3505                                   outputTensorInfo,
3506                                   permuteVector,
3507                                   std::move(outputHandle),
3508                                   output);
3509     }
3510     else
3511     {
3512         CopyDataFromITensorHandle(output, outputHandle.get());
3513     }
3514 }
3515
3516 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
3517 LayerTestResult<T, 1> Concatenation1dTestImpl(
3518     armnn::IWorkloadFactory& workloadFactory,
3519     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3520     float qScale,
3521     int32_t qOffset)
3522 {
3523     armnn::TensorInfo inputTensorInfo({ 3 }, ArmnnType);
3524
3525     auto input0 = MakeTensor<T, 1>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, { 1.0f, 2.0f, 3.0f }));
3526     auto input1 = MakeTensor<T, 1>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, { 4.0f, 5.0f, 6.0f }));
3527     auto input2 = MakeTensor<T, 1>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, { 7.0f, 8.0f, 9.0f }));
3528
3529     armnn::TensorInfo outputTensorInfo({ 9 }, ArmnnType);
3530
3531     LayerTestResult<T, 1> result(outputTensorInfo);
3532
3533     std::vector<T> output;
3534     output.resize(outputTensorInfo.GetNumElements());
3535     Concatenate<T>(workloadFactory, memoryManager,
3536                    { inputTensorInfo, inputTensorInfo, inputTensorInfo },
3537                    { input0.data(), input1.data(), input2.data() },
3538                    outputTensorInfo,
3539                    output.data(),
3540                    0,
3541                    true);
3542
3543     result.output = MakeTensor<T, 1>(outputTensorInfo, output);
3544     result.outputExpected = MakeTensor<T, 1>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
3545         1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f
3546     }));
3547
3548     return result;
3549 }
3550
3551 LayerTestResult<float, 1> Concatenation1dTest(
3552     armnn::IWorkloadFactory& workloadFactory,
3553     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
3554 {
3555     return Concatenation1dTestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
3556 }
3557
3558 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
3559 LayerTestResult<T, 2> Concatenation2dTestImpl(
3560     armnn::IWorkloadFactory& workloadFactory,
3561     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3562     const armnn::TensorInfo& outputTensorInfo,
3563     unsigned int dimension,
3564     const float qScale,
3565     const int32_t qOffset)
3566 {
3567     armnn::TensorInfo inputTensorInfo({ 2, 3 }, ArmnnType);
3568
3569     auto input0 = MakeTensor<T, 2>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
3570         // Batch 0
3571         1.0f, 2.0f, 3.0f,
3572
3573         // Batch 1
3574         10.0f, 11.0f, 12.0f,
3575     }));
3576
3577     auto input1 = MakeTensor<T, 2>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
3578         // Batch 0
3579         4.0f, 5.0f, 6.0f,
3580
3581         // Batch 1
3582         13.0f, 14.0f, 15.0f,
3583     }));
3584
3585     auto input2 = MakeTensor<T, 2>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
3586         // Batch 0
3587         7.0f, 8.0f, 9.0f,
3588
3589         // Batch 1
3590         16.0f, 17.0f, 18.0f,
3591     }));
3592
3593     LayerTestResult<T, 2> result(outputTensorInfo);
3594
3595     std::vector<T> output;
3596     output.resize(outputTensorInfo.GetNumElements());
3597     Concatenate<T>(workloadFactory, memoryManager,
3598                    { inputTensorInfo, inputTensorInfo, inputTensorInfo },
3599                    { input0.data(), input1.data(), input2.data() },
3600                    outputTensorInfo,
3601                    output.data(),
3602                    dimension,
3603                    true);
3604
3605     result.output = MakeTensor<T, 2>(outputTensorInfo, output);
3606     return result;
3607 }
3608
3609 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
3610 LayerTestResult<T, 2> Concatenation2dDim0TestImpl(
3611     armnn::IWorkloadFactory& workloadFactory,
3612     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3613     float qScale,
3614     int32_t qOffset)
3615 {
3616     armnn::TensorInfo outputTensorInfo({ 6, 3 }, ArmnnType);
3617
3618     LayerTestResult<T, 2> result = Concatenation2dTestImpl<ArmnnType>(
3619         workloadFactory, memoryManager, outputTensorInfo, 0, qScale, qOffset);
3620
3621     result.outputExpected = MakeTensor<T, 2>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
3622         // Batch 0
3623         1.0f, 2.0f, 3.0f,
3624
3625         // Batch 1
3626         10.0f, 11.0f, 12.0f,
3627
3628         // Batch 2
3629         4.0f, 5.0f, 6.0f,
3630
3631         // Batch 3
3632         13.0f, 14.0f, 15.0f,
3633
3634         // Batch 4
3635         7.0f, 8.0f, 9.0f,
3636
3637         // Batch 5
3638         16.0f, 17.0f, 18.0f,
3639     }));
3640
3641     return result;
3642 }
3643
3644 LayerTestResult<float, 2> Concatenation2dDim0Test(
3645     armnn::IWorkloadFactory& workloadFactory,
3646     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
3647 {
3648     return Concatenation2dDim0TestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
3649 }
3650
3651 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
3652 LayerTestResult<T, 2> Concatenation2dDim1TestImpl(
3653     armnn::IWorkloadFactory& workloadFactory,
3654     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3655     float qScale,
3656     int32_t qOffset)
3657 {
3658     armnn::TensorInfo outputTensorInfo({ 2, 9 }, ArmnnType);
3659
3660     LayerTestResult<T, 2> result = Concatenation2dTestImpl<ArmnnType>(
3661         workloadFactory, memoryManager, outputTensorInfo, 1, qScale, qOffset);
3662
3663     result.outputExpected = MakeTensor<T, 2>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
3664         // Batch 0
3665         1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f,
3666
3667         // Batch 1
3668         10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f
3669     }));
3670
3671     return result;
3672 }
3673
3674 LayerTestResult<float, 2> Concatenation2dDim1Test(
3675     armnn::IWorkloadFactory& workloadFactory,
3676     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
3677 {
3678     return Concatenation2dDim1TestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
3679 }
3680
3681 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
3682 LayerTestResult<T, 2> Concatenation2dDim0DiffInputDimsTestImpl(
3683     armnn::IWorkloadFactory& workloadFactory,
3684     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3685     float qScale,
3686     int32_t qOffset)
3687 {
3688     armnn::TensorInfo input0TensorInfo({ 2, 3 }, ArmnnType);
3689     auto input0 = MakeTensor<T, 2>(input0TensorInfo, QuantizedVector<T>(qScale, qOffset, {
3690         // Batch 0
3691         1.0f, 2.0f, 3.0f,
3692
3693         // Batch 1
3694         10.0f, 11.0f, 12.0f,
3695     }));
3696
3697     armnn::TensorInfo input1TensorInfo({ 3, 3 }, ArmnnType);
3698     auto input1 = MakeTensor<T, 2>(input1TensorInfo, QuantizedVector<T>(qScale, qOffset, {
3699         // Batch 0
3700         4.0f, 5.0f, 6.0f,
3701
3702         // Batch 1
3703         13.0f, 14.0f, 15.0f,
3704
3705         // Batch 0
3706         7.0f, 8.0f, 9.0f,
3707     }));
3708
3709     armnn::TensorInfo input2TensorInfo({ 1, 3 }, ArmnnType);
3710     auto input2 = MakeTensor<T, 2>(input2TensorInfo, QuantizedVector<T>(qScale, qOffset, {
3711         // Batch 1
3712         16.0f, 17.0f, 18.0f,
3713     }));
3714
3715     armnn::TensorInfo outputTensorInfo({ 6, 3 }, ArmnnType);
3716     LayerTestResult<T, 2> result(outputTensorInfo);
3717
3718     std::vector<T> output;
3719     output.resize(outputTensorInfo.GetNumElements());
3720     Concatenate<T>(workloadFactory, memoryManager,
3721                    { input0TensorInfo, input1TensorInfo, input2TensorInfo },
3722                    { input0.data(), input1.data(), input2.data() },
3723                    outputTensorInfo,
3724                    output.data(),
3725                    0,
3726                    true);
3727
3728     result.output = MakeTensor<T, 2>(outputTensorInfo, output);
3729     result.outputExpected = MakeTensor<T, 2>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
3730         // Batch 0
3731         1.0f, 2.0f, 3.0f,
3732
3733         // Batch 1
3734         10.0f, 11.0f, 12.0f,
3735
3736         // Batch 2
3737         4.0f, 5.0f, 6.0f,
3738
3739         // Batch 3
3740         13.0f, 14.0f, 15.0f,
3741
3742         // Batch 4
3743         7.0f, 8.0f, 9.0f,
3744
3745         // Batch 5
3746         16.0f, 17.0f, 18.0f,
3747     }));
3748
3749     return result;
3750 }
3751
3752 LayerTestResult<float, 2> Concatenation2dDim0DiffInputDimsTest(
3753     armnn::IWorkloadFactory& workloadFactory,
3754     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
3755 {
3756     return Concatenation2dDim0DiffInputDimsTestImpl<armnn::DataType::Float32>(
3757         workloadFactory, memoryManager, 0.0f, 0);
3758 }
3759
3760 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
3761 LayerTestResult<T, 2> Concatenation2dDim1DiffInputDimsTestImpl(
3762     armnn::IWorkloadFactory& workloadFactory,
3763     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3764     float qScale,
3765     int32_t qOffset)
3766 {
3767     armnn::TensorInfo input0TensorInfo({ 2, 3 }, ArmnnType);
3768     auto input0 = MakeTensor<T, 2>(input0TensorInfo, QuantizedVector<T>(qScale, qOffset, {
3769         // Batch 0
3770         1.0f, 2.0f, 3.0f,
3771
3772         // Batch 1
3773         10.0f, 11.0f, 12.0f,
3774     }));
3775
3776     armnn::TensorInfo input1TensorInfo({ 2, 5 }, ArmnnType);
3777     auto input1 = MakeTensor<T, 2>(input1TensorInfo, QuantizedVector<T>(qScale, qOffset, {
3778         // Batch 0
3779         4.0f, 5.0f, 6.0f, 7.0f, 8.0f,
3780
3781         // Batch 1
3782         13.0f, 14.0f, 15.0f, 16.0f, 17.0f,
3783     }));
3784
3785     armnn::TensorInfo input2TensorInfo({ 2, 1 }, ArmnnType);
3786     auto input2 = MakeTensor<T, 2>(input2TensorInfo, QuantizedVector<T>(qScale, qOffset, {
3787         // Batch 0
3788         9.0f,
3789
3790         // Batch 1
3791         18.0f
3792     }));
3793
3794     armnn::TensorInfo outputTensorInfo({ 2, 9 }, ArmnnType);
3795     LayerTestResult<T, 2> result(outputTensorInfo);
3796
3797     std::vector<T> output;
3798     output.resize(outputTensorInfo.GetNumElements());
3799     Concatenate<T>(workloadFactory, memoryManager,
3800                    { input0TensorInfo, input1TensorInfo, input2TensorInfo },
3801                    { input0.data(), input1.data(), input2.data() },
3802                    outputTensorInfo,
3803                    output.data(),
3804                    1,
3805                    true);
3806
3807     result.output = MakeTensor<T, 2>(outputTensorInfo, output);
3808     result.outputExpected = MakeTensor<T, 2>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
3809         // Batch 0
3810         1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f,
3811
3812         // Batch 1
3813         10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f,
3814     }));
3815
3816     return result;
3817 }
3818
3819 LayerTestResult<float, 2> Concatenation2dDim1DiffInputDimsTest(
3820     armnn::IWorkloadFactory& workloadFactory,
3821     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
3822 {
3823     return Concatenation2dDim1DiffInputDimsTestImpl<armnn::DataType::Float32>(
3824         workloadFactory, memoryManager, 0.0f, 0);
3825 }
3826
3827 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
3828 LayerTestResult<T, 3> Concatenation3dTestImpl(
3829     armnn::IWorkloadFactory& workloadFactory,
3830     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3831     const armnn::TensorInfo& outputTensorInfo,
3832     unsigned int dimension,
3833     bool useSubtensor,
3834     float qScale,
3835     int32_t qOffset)
3836 {
3837     armnn::TensorInfo inputTensorInfo({ 2, 3, 2 }, ArmnnType);
3838
3839     auto input0 = MakeTensor<T, 3>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
3840         // Batch 0, Channel 0
3841         1.0f, 2.0f,
3842
3843         // Batch 0, Channel 1
3844         3.0f, 4.0f,
3845
3846         // Batch 0, Channel 2
3847         5.0f, 6.0f,
3848
3849         // Batch 1, Channel 0
3850         19.0f, 20.0f,
3851
3852         // Batch 1, Channel 1
3853         21.0f, 22.0f,
3854
3855         // Batch 1, Channel 2
3856         23.0f, 24.0f
3857     }));
3858
3859     auto input1 = MakeTensor<T, 3>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
3860         // Batch 0, Channel 0
3861         7.0f, 8.0f,
3862
3863         // Batch 0, Channel 1
3864         9.0f, 10.0f,
3865
3866         // Batch 0, Channel 2
3867         11.0f, 12.0f,
3868
3869         // Batch 1, Channel 0
3870         25.0f, 26.0f,
3871
3872         // Batch 1, Channel 1
3873         27.0f, 28.0f,
3874
3875         // Batch 1, Channel 2
3876         29.0f, 30.0f
3877     }));
3878
3879     auto input2 = MakeTensor<T, 3>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
3880         // Batch 0, Channel 0
3881         13.0f, 14.0f,
3882
3883         // Batch 0, Channel 1
3884         15.0f, 16.0f,
3885
3886         // Batch 0, Channel 2
3887         17.0f, 18.0f,
3888
3889         // Batch 1, Channel 0
3890         31.0f, 32.0f,
3891
3892         // Batch 1, Channel 1
3893         33.0f, 34.0f,
3894
3895         // Batch 1, Channel 2
3896         35.0f, 36.0f
3897     }));
3898
3899     LayerTestResult<T, 3> result(outputTensorInfo);
3900
3901     std::vector<T> output;
3902     output.resize(outputTensorInfo.GetNumElements());
3903     Concatenate<T>(workloadFactory, memoryManager,
3904                    { inputTensorInfo, inputTensorInfo, inputTensorInfo },
3905                    { input0.data(), input1.data(), input2.data() },
3906                    outputTensorInfo,
3907                    output.data(),
3908                    dimension,
3909                    useSubtensor);
3910
3911     result.output = MakeTensor<T, 3>(outputTensorInfo, output);
3912     return result;
3913 }
3914
3915 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
3916 LayerTestResult<T, 3> Concatenation3dDim0TestImpl(
3917     armnn::IWorkloadFactory& workloadFactory,
3918     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3919     float qScale,
3920     int32_t qOffset)
3921 {
3922     armnn::TensorInfo outputTensorInfo({ 6, 3, 2 }, ArmnnType);
3923
3924     LayerTestResult<T, 3> result = Concatenation3dTestImpl<ArmnnType>(
3925         workloadFactory, memoryManager, outputTensorInfo, 0, true, qScale, qOffset);
3926
3927     result.outputExpected = MakeTensor<T, 3>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
3928         // Batch 0, Channel 0
3929         1.0f, 2.0f,
3930
3931         // Batch 0, Channel 1
3932         3.0f, 4.0f,
3933
3934         // Batch 0, Channel 2
3935         5.0f, 6.0f,
3936
3937         // Batch 1, Channel 0
3938         19.0f, 20.0f,
3939
3940         // Batch 1, Channel 1
3941         21.0f, 22.0f,
3942
3943         // Batch 1, Channel 2
3944         23.0f, 24.0f,
3945
3946         // Batch 2, Channel 0
3947         7.0f, 8.0f,
3948
3949         // Batch 2, Channel 1
3950         9.0f, 10.0f,
3951
3952         // Batch 2, Channel 2
3953         11.0f, 12.0f,
3954
3955         // Batch 3, Channel 0
3956         25.0f, 26.0f,
3957
3958         // Batch 3, Channel 1
3959         27.0f, 28.0f,
3960
3961         // Batch 3, Channel 2
3962         29.0f, 30.0f,
3963
3964         // Batch 4, Channel 0
3965         13.0f, 14.0f,
3966
3967         // Batch 4, Channel 1
3968         15.0f, 16.0f,
3969
3970         // Batch 4, Channel 2
3971         17.0f, 18.0f,
3972
3973         // Batch 5, Channel 0
3974         31.0f, 32.0f,
3975
3976         // Batch 5, Channel 1
3977         33.0f, 34.0f,
3978
3979         // Batch 5, Channel 2
3980         35.0f, 36.0f
3981     }));
3982
3983     return result;
3984 }
3985
3986 LayerTestResult<float, 3> Concatenation3dDim0Test(
3987     armnn::IWorkloadFactory& workloadFactory,
3988     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
3989 {
3990     return Concatenation3dDim0TestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
3991 }
3992
3993 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
3994 LayerTestResult<T, 3> Concatenation3dDim1TestImpl(
3995     armnn::IWorkloadFactory& workloadFactory,
3996     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3997     float qScale,
3998     int32_t qOffset)
3999 {
4000     armnn::TensorInfo outputTensorInfo({ 2, 9, 2 }, ArmnnType);
4001
4002     LayerTestResult<T, 3> result = Concatenation3dTestImpl<ArmnnType>(
4003         workloadFactory, memoryManager, outputTensorInfo, 1, true, qScale, qOffset);
4004
4005     result.outputExpected = MakeTensor<T, 3>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4006         // Batch 0, Channel 0
4007         1.0f, 2.0f,
4008
4009         // Batch 0, Channel 1
4010         3.0f, 4.0f,
4011
4012         // Batch 0, Channel 2
4013         5.0f, 6.0f,
4014
4015         // Batch 0, Channel 3
4016         7.0f, 8.0f,
4017
4018         // Batch 0, Channel 4
4019         9.0f, 10.0f,
4020
4021         // Batch 0, Channel 5
4022         11.0f, 12.0f,
4023
4024         // Batch 0, Channel 6
4025         13.0f, 14.0f,
4026
4027         // Batch 0, Channel 7
4028         15.0f, 16.0f,
4029
4030         // Batch 0, Channel 8
4031         17.0f, 18.0f,
4032
4033         // Batch 1, Channel 0
4034         19.0f, 20.0f,
4035
4036         // Batch 1, Channel 1
4037         21.0f, 22.0f,
4038
4039         // Batch 1, Channel 2
4040         23.0f, 24.0f,
4041
4042         // Batch 1, Channel 3
4043         25.0f, 26.0f,
4044
4045         // Batch 1, Channel 4
4046         27.0f, 28.0f,
4047
4048         // Batch 1, Channel 5
4049         29.0f, 30.0f,
4050
4051         // Batch 1, Channel 6
4052         31.0f, 32.0f,
4053
4054         // Batch 1, Channel 7
4055         33.0f, 34.0f,
4056
4057         // Batch 1, Channel 8
4058         35.0f, 36.0f
4059     }));
4060
4061     return result;
4062 }
4063
4064 LayerTestResult<float, 3> Concatenation3dDim1Test(
4065     armnn::IWorkloadFactory& workloadFactory,
4066     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
4067 {
4068     return Concatenation3dDim1TestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
4069 }
4070
4071 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
4072 LayerTestResult<T, 3> Concatenation3dDim2TestImpl(
4073     armnn::IWorkloadFactory& workloadFactory,
4074     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4075     bool useSubtensor,
4076     float qScale,
4077     int32_t qOffset)
4078 {
4079     armnn::TensorInfo outputTensorInfo({ 2, 3, 6 }, ArmnnType);
4080
4081     LayerTestResult<T, 3> result = Concatenation3dTestImpl<ArmnnType>(
4082         workloadFactory, memoryManager, outputTensorInfo, 2, useSubtensor, qScale, qOffset);
4083
4084     result.outputExpected = MakeTensor<T, 3>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4085         // Batch 0, Channel 0
4086         1.0f, 2.0f, 7.0f, 8.0f, 13.0f, 14.0f,
4087
4088         // Batch 0, Channel 1
4089         3.0f, 4.0f, 9.0f, 10.0f, 15.0f, 16.0f,
4090
4091         // Batch 0, Channel 2
4092         5.0f, 6.0f, 11.0f, 12.0f, 17.0f, 18.0f,
4093
4094         // Batch 1, Channel 0
4095         19.0f, 20.0f, 25.0f, 26.0f, 31.0f, 32.0f,
4096
4097         // Batch 1, Channel 1
4098         21.0f, 22.0f, 27.0f, 28.0f, 33.0f, 34.0f,
4099
4100         // Batch 1, Channel 2
4101         23.0f, 24.0f, 29.0f, 30.0f, 35.0f, 36.0f,
4102     }));
4103
4104     return result;
4105 }
4106
4107 LayerTestResult<float, 3> Concatenation3dDim2Test(
4108     armnn::IWorkloadFactory& workloadFactory,
4109     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4110     bool useSubtensor)
4111 {
4112     return Concatenation3dDim2TestImpl<armnn::DataType::Float32>(
4113         workloadFactory, memoryManager, useSubtensor, 0.0f, 0);
4114 }
4115
4116 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
4117 LayerTestResult<T, 3> Concatenation3dDim0DiffInputDimsTestImpl(
4118     armnn::IWorkloadFactory& workloadFactory,
4119     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4120     float qScale,
4121     int32_t qOffset)
4122 {
4123     armnn::TensorInfo input0TensorInfo({ 2, 3, 2 }, ArmnnType);
4124     auto input0 = MakeTensor<T, 3>(input0TensorInfo, QuantizedVector<T>(qScale, qOffset, {
4125             // Batch 0, Channel 0
4126             1.0f, 2.0f,
4127
4128             // Batch 0, Channel 1
4129             3.0f, 4.0f,
4130
4131             // Batch 0, Channel 2
4132             5.0f, 6.0f,
4133
4134             // Batch 1, Channel 0
4135             19.0f, 20.0f,
4136
4137             // Batch 1, Channel 1
4138             21.0f, 22.0f,
4139
4140             // Batch 1, Channel 2
4141             23.0f, 24.0f
4142     }));
4143
4144     armnn::TensorInfo input1TensorInfo({ 1, 3, 2 }, ArmnnType);
4145     auto input1 = MakeTensor<T, 3>(input1TensorInfo, QuantizedVector<T>(qScale, qOffset, {
4146             // Batch 0, Channel 0
4147             7.0f, 8.0f,
4148
4149             // Batch 0, Channel 1
4150             9.0f, 10.0f,
4151
4152             // Batch 0, Channel 2
4153             11.0f, 12.0f,
4154     }));
4155
4156     armnn::TensorInfo input2TensorInfo({ 3, 3, 2 }, ArmnnType);
4157     auto input2 = MakeTensor<T, 3>(input2TensorInfo, QuantizedVector<T>(qScale, qOffset, {
4158             // Batch 0, Channel 0
4159             25.0f, 26.0f,
4160
4161             // Batch 0, Channel 1
4162             27.0f, 28.0f,
4163
4164             // Batch 0, Channel 2
4165             29.0f, 30.0f,
4166
4167             // Batch 1, Channel 0
4168             13.0f, 14.0f,
4169
4170             // Batch 1, Channel 1
4171             15.0f, 16.0f,
4172
4173             // Batch 1, Channel 2
4174             17.0f, 18.0f,
4175
4176             // Batch 2, Channel 0
4177             31.0f, 32.0f,
4178
4179             // Batch 2, Channel 1
4180             33.0f, 34.0f,
4181
4182             // Batch 2, Channel 2
4183             35.0f, 36.0f
4184     }));
4185
4186     armnn::TensorInfo outputTensorInfo({ 6, 3, 2 }, ArmnnType);
4187     LayerTestResult<T, 3> result(outputTensorInfo);
4188
4189     std::vector<T> output;
4190     output.resize(outputTensorInfo.GetNumElements());
4191     Concatenate<T>(workloadFactory, memoryManager,
4192                    { input0TensorInfo, input1TensorInfo, input2TensorInfo },
4193                    { input0.data(), input1.data(), input2.data() },
4194                    outputTensorInfo,
4195                    output.data(),
4196                    0,
4197                    true);
4198
4199     result.output = MakeTensor<T, 3>(outputTensorInfo, output);
4200     result.outputExpected = MakeTensor<T, 3>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4201         // Batch 0, Channel 0
4202         1.0f, 2.0f,
4203
4204         // Batch 0, Channel 1
4205         3.0f, 4.0f,
4206
4207         // Batch 0, Channel 2
4208         5.0f, 6.0f,
4209
4210         // Batch 1, Channel 0
4211         19.0f, 20.0f,
4212
4213         // Batch 1, Channel 1
4214         21.0f, 22.0f,
4215
4216         // Batch 1, Channel 2
4217         23.0f, 24.0f,
4218
4219         // Batch 2, Channel 0
4220         7.0f, 8.0f,
4221
4222         // Batch 2, Channel 1
4223         9.0f, 10.0f,
4224
4225         // Batch 2, Channel 2
4226         11.0f, 12.0f,
4227
4228         // Batch 3, Channel 0
4229         25.0f, 26.0f,
4230
4231         // Batch 3, Channel 1
4232         27.0f, 28.0f,
4233
4234         // Batch 3, Channel 2
4235         29.0f, 30.0f,
4236
4237         // Batch 4, Channel 0
4238         13.0f, 14.0f,
4239
4240         // Batch 4, Channel 1
4241         15.0f, 16.0f,
4242
4243         // Batch 4, Channel 2
4244         17.0f, 18.0f,
4245
4246         // Batch 5, Channel 0
4247         31.0f, 32.0f,
4248
4249         // Batch 5, Channel 1
4250         33.0f, 34.0f,
4251
4252         // Batch 5, Channel 2
4253         35.0f, 36.0f
4254     }));
4255
4256     return result;
4257 }
4258
4259 LayerTestResult<float, 3> Concatenation3dDim0DiffInputDimsTest(
4260     armnn::IWorkloadFactory& workloadFactory,
4261     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
4262 {
4263     return Concatenation3dDim0DiffInputDimsTestImpl<armnn::DataType::Float32>(
4264         workloadFactory, memoryManager, 0.0f, 0);
4265 }
4266
4267 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
4268 LayerTestResult<T, 3> Concatenation3dDim1DiffInputDimsTestImpl(
4269     armnn::IWorkloadFactory& workloadFactory,
4270     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4271     float qScale,
4272     int32_t qOffset)
4273 {
4274     armnn::TensorInfo input0TensorInfo({ 2, 3, 2 }, ArmnnType);
4275     auto input0 = MakeTensor<T, 3>(input0TensorInfo, QuantizedVector<T>(qScale, qOffset, {
4276         // Batch 0, Channel 0
4277         1.0f, 2.0f,
4278
4279         // Batch 0, Channel 1
4280         3.0f, 4.0f,
4281
4282         // Batch 0, Channel 2
4283         5.0f, 6.0f,
4284
4285         // Batch 1, Channel 0
4286         19.0f, 20.0f,
4287
4288         // Batch 1, Channel 1
4289         21.0f, 22.0f,
4290
4291         // Batch 1, Channel 2
4292         23.0f, 24.0f
4293     }));
4294
4295     armnn::TensorInfo input1TensorInfo({ 2, 4, 2 }, ArmnnType);
4296     auto input1 = MakeTensor<T, 3>(input1TensorInfo, QuantizedVector<T>(qScale, qOffset, {
4297         // Batch 0, Channel 0
4298         7.0f, 8.0f,
4299
4300         // Batch 0, Channel 1
4301         9.0f, 10.0f,
4302
4303         // Batch 0, Channel 2
4304         11.0f, 12.0f,
4305
4306         // Batch 0, Channel 3
4307         25.0f, 26.0f,
4308
4309         // Batch 1, Channel 0
4310         27.0f, 28.0f,
4311
4312         // Batch 1, Channel 1
4313         29.0f, 30.0f,
4314
4315         // Batch 1, Channel 2
4316         13.0f, 14.0f,
4317
4318         // Batch 1, Channel 3
4319         15.0f, 16.0f,
4320     }));
4321
4322     armnn::TensorInfo input2TensorInfo({ 2, 1, 2 }, ArmnnType);
4323     auto input2 = MakeTensor<T, 3>(input2TensorInfo, QuantizedVector<T>(qScale, qOffset, {
4324         // Batch 0, Channel 0
4325         17.0f, 18.0f,
4326
4327         // Batch 1, Channel 0
4328         31.0f, 32.0f,
4329     }));
4330
4331     armnn::TensorInfo outputTensorInfo({ 2, 8, 2 }, ArmnnType);
4332     LayerTestResult<T, 3> result(outputTensorInfo);
4333
4334     std::vector<T> output;
4335     output.resize(outputTensorInfo.GetNumElements());
4336     Concatenate<T>(workloadFactory, memoryManager,
4337                    { input0TensorInfo, input1TensorInfo, input2TensorInfo },
4338                    { input0.data(), input1.data(), input2.data() },
4339                    outputTensorInfo,
4340                    output.data(),
4341                    1,
4342                    true);
4343
4344     result.output = MakeTensor<T, 3>(outputTensorInfo, output);
4345     result.outputExpected = MakeTensor<T, 3>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4346         // Batch 0, Channel 0
4347         1.0f, 2.0f,
4348
4349         // Batch 0, Channel 1
4350         3.0f, 4.0f,
4351
4352         // Batch 0, Channel 2
4353         5.0f, 6.0f,
4354
4355         // Batch 0, Channel 3
4356         7.0f, 8.0f,
4357
4358         // Batch 0, Channel 4
4359         9.0f, 10.0f,
4360
4361         // Batch 0, Channel 5
4362         11.0f, 12.0f,
4363
4364         // Batch 0, Channel 6
4365         25.0f, 26.0f,
4366
4367         // Batch 0, Channel 7
4368         17.0f, 18.0f,
4369
4370         // Batch 1, Channel 0
4371         19.0f, 20.0f,
4372
4373         // Batch 1, Channel 1
4374         21.0f, 22.0f,
4375
4376         // Batch 1, Channel 2
4377         23.0f, 24.0f,
4378
4379         // Batch 1, Channel 3
4380         27.0f, 28.0f,
4381
4382         // Batch 1, Channel 4
4383         29.0f, 30.0f,
4384
4385         // Batch 1, Channel 5
4386         13.0f, 14.0f,
4387
4388         // Batch 1, Channel 6
4389         15.0f, 16.0f,
4390
4391         // Batch 1, Channel 7
4392         31.0f, 32.0f,
4393     }));
4394
4395     return result;
4396 }
4397
4398 LayerTestResult<float, 3> Concatenation3dDim1DiffInputDimsTest(
4399     armnn::IWorkloadFactory& workloadFactory,
4400     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
4401 {
4402     return Concatenation3dDim1DiffInputDimsTestImpl<armnn::DataType::Float32>(
4403         workloadFactory, memoryManager, 0.0f, 0);
4404 }
4405
4406 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
4407 LayerTestResult<T, 3> Concatenation3dDim2DiffInputDimsTestImpl(
4408     armnn::IWorkloadFactory& workloadFactory,
4409     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4410     bool useSubtensor,
4411     float qScale,
4412     int32_t qOffset)
4413 {
4414     armnn::TensorInfo input0TensorInfo({ 2, 3, 2 }, ArmnnType);
4415     auto input0 = MakeTensor<T, 3>(input0TensorInfo, QuantizedVector<T>(qScale, qOffset, {
4416         // Batch 0, Channel 0
4417         1.0f, 2.0f,
4418
4419         // Batch 0, Channel 1
4420         3.0f, 4.0f,
4421
4422         // Batch 0, Channel 2
4423         5.0f, 6.0f,
4424
4425         // Batch 1, Channel 0
4426         19.0f, 20.0f,
4427
4428         // Batch 1, Channel 1
4429         21.0f, 22.0f,
4430
4431         // Batch 1, Channel 2
4432         23.0f, 24.0f
4433     }));
4434
4435     armnn::TensorInfo input1TensorInfo({ 2, 3, 1 }, ArmnnType);
4436     auto input1 = MakeTensor<T, 3>(input1TensorInfo, QuantizedVector<T>(qScale, qOffset, {
4437         // Batch 0, Channel 0
4438         7.0f,
4439
4440         // Batch 0, Channel 1
4441         9.0f,
4442
4443         // Batch 0, Channel 2
4444         11.0f,
4445
4446         // Batch 1, Channel 0
4447         25.0f,
4448
4449         // Batch 1, Channel 1
4450         27.0f,
4451
4452         // Batch 1, Channel 2
4453         29.0f
4454     }));
4455
4456     armnn::TensorInfo input2TensorInfo({ 2, 3, 3 }, ArmnnType);
4457     auto input2 = MakeTensor<T, 3>(input2TensorInfo, QuantizedVector<T>(qScale, qOffset, {
4458         // Batch 0, Channel 0
4459         13.0f, 14.0f, 50.0f,
4460
4461         // Batch 0, Channel 1
4462         15.0f, 16.0f, 51.0f,
4463
4464         // Batch 0, Channel 2
4465         17.0f, 18.0f, 52.0f,
4466
4467         // Batch 1, Channel 0
4468         31.0f, 32.0f, 53.0f,
4469
4470         // Batch 1, Channel 1
4471         33.0f, 34.0f, 54.0f,
4472
4473         // Batch 1, Channel 2
4474         35.0f, 36.0f, 55.0f,
4475     }));
4476
4477     armnn::TensorInfo outputTensorInfo({ 2, 3, 6 }, ArmnnType);
4478     LayerTestResult<T, 3> result(outputTensorInfo);
4479
4480     std::vector<T> output;
4481     output.resize(outputTensorInfo.GetNumElements());
4482     Concatenate<T>(workloadFactory, memoryManager,
4483                    { input0TensorInfo, input1TensorInfo, input2TensorInfo },
4484                    { input0.data(), input1.data(), input2.data() },
4485                    outputTensorInfo,
4486                    output.data(),
4487                    2,
4488                    useSubtensor);
4489
4490     result.output = MakeTensor<T, 3>(outputTensorInfo, output);
4491     result.outputExpected = MakeTensor<T, 3>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4492         // Batch 0, Channel 0
4493         1.0f, 2.0f, 7.0f, 13.0f, 14.0f, 50.0f,
4494
4495         // Batch 0, Channel 1
4496         3.0f, 4.0f, 9.0f, 15.0f, 16.0f, 51.0f,
4497
4498         // Batch 0, Channel 2
4499         5.0f, 6.0f, 11.0f, 17.0f, 18.0f, 52.0f,
4500
4501         // Batch 1, Channel 0
4502         19.0f, 20.0f, 25.0f, 31.0f, 32.0f, 53.0f,
4503
4504         // Batch 1, Channel 1
4505         21.0f, 22.0f, 27.0f, 33.0f, 34.0f, 54.0f,
4506
4507         // Batch 1, Channel 2
4508         23.0f, 24.0f, 29.0f, 35.0f, 36.0f, 55.0f,
4509     }));
4510
4511     return result;
4512 }
4513
4514 LayerTestResult<float, 3> Concatenation3dDim2DiffInputDimsTest(
4515     armnn::IWorkloadFactory& workloadFactory,
4516     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4517     bool useSubtensor)
4518 {
4519     return Concatenation3dDim2DiffInputDimsTestImpl<armnn::DataType::Float32>(
4520         workloadFactory, memoryManager, useSubtensor, 0.0f, 0);
4521 }
4522
4523 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
4524 LayerTestResult<T, 4> Concatenation4dTestImpl(
4525     armnn::IWorkloadFactory& workloadFactory,
4526     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4527     const armnn::TensorInfo& outputTensorInfo,
4528     unsigned int dimension,
4529     bool useSubtensor,
4530     float qScale,
4531     int32_t qOffset)
4532 {
4533     armnn::TensorInfo inputTensorInfo({ 1, 3, 2, 2 }, ArmnnType);
4534
4535     auto input0 = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4536         1.0f, 2.0f,
4537         3.0f, 4.0f,
4538         5.0f, 6.0f,
4539         7.0f, 8.0f,
4540         9.0f, 10.0f,
4541         11.0f, 12.0f
4542     }));
4543
4544     auto input1 = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4545         11.0f, 12.0f,
4546         13.0f, 14.0f,
4547         15.0f, 16.0f,
4548         17.0f, 18.0f,
4549         19.0f, 20.0f,
4550         21.0f, 22.0f
4551     }));
4552
4553     auto input2 = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4554         21.0f, 22.0f,
4555         23.0f, 24.0f,
4556         25.0f, 26.0f,
4557         27.0f, 28.0f,
4558         29.0f, 30.0f,
4559         31.0f, 32.0f
4560     }));
4561
4562     LayerTestResult<T, 4> result(outputTensorInfo);
4563
4564     std::vector<T> output;
4565     output.resize(outputTensorInfo.GetNumElements());
4566
4567     Concatenate<T>(workloadFactory,
4568                    memoryManager,
4569                    {inputTensorInfo, inputTensorInfo, inputTensorInfo},
4570                    {input0.data(), input1.data(), input2.data()},
4571                    outputTensorInfo,
4572                    output.data(),
4573                    dimension,
4574                    useSubtensor);
4575
4576     result.output = MakeTensor<T, 4>(outputTensorInfo, output);
4577     return result;
4578 }
4579
4580 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
4581 LayerTestResult<T, 4> Concatenation4dDim0TestImpl(
4582     armnn::IWorkloadFactory& workloadFactory,
4583     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4584     float qScale,
4585     int32_t qOffset)
4586 {
4587     armnn::TensorInfo outputTensorInfo({ 3, 3, 2, 2 }, ArmnnType);
4588
4589     LayerTestResult<T, 4> result = Concatenation4dTestImpl<ArmnnType>(
4590         workloadFactory, memoryManager, outputTensorInfo, 0, true, qScale, qOffset);
4591
4592     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4593         1.0f, 2.0f,
4594         3.0f, 4.0f,
4595         5.0f, 6.0f,
4596         7.0f, 8.0f,
4597         9.0f, 10.0f,
4598         11.0f, 12.0f,
4599
4600         11.0f, 12.0f,
4601         13.0f, 14.0f,
4602         15.0f, 16.0f,
4603         17.0f, 18.0f,
4604         19.0f, 20.0f,
4605         21.0f, 22.0f,
4606
4607         21.0f, 22.0f,
4608         23.0f, 24.0f,
4609         25.0f, 26.0f,
4610         27.0f, 28.0f,
4611         29.0f, 30.0f,
4612         31.0f, 32.0f
4613     }));
4614     return result;
4615 }
4616
4617 LayerTestResult<float, 4> Concatenation4dDim0Test(
4618     armnn::IWorkloadFactory& workloadFactory,
4619     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
4620 {
4621     return Concatenation4dDim0TestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
4622 }
4623
4624 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
4625 LayerTestResult<T, 4> Concatenation4dDim1TestImpl(
4626     armnn::IWorkloadFactory& workloadFactory,
4627     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4628     float qScale,
4629     int32_t qOffset)
4630 {
4631     armnn::TensorInfo outputTensorInfo({ 1, 9, 2, 2 }, ArmnnType);
4632
4633     LayerTestResult<T, 4> result = Concatenation4dTestImpl<ArmnnType>(
4634         workloadFactory, memoryManager, outputTensorInfo, 1, true, qScale, qOffset);
4635
4636     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4637         1.0f, 2.0f,
4638         3.0f, 4.0f,
4639         5.0f, 6.0f,
4640         7.0f, 8.0f,
4641         9.0f, 10.0f,
4642         11.0f, 12.0f,
4643
4644         11.0f, 12.0f,
4645         13.0f, 14.0f,
4646         15.0f, 16.0f,
4647         17.0f, 18.0f,
4648         19.0f, 20.0f,
4649         21.0f, 22.0f,
4650
4651         21.0f, 22.0f,
4652         23.0f, 24.0f,
4653         25.0f, 26.0f,
4654         27.0f, 28.0f,
4655         29.0f, 30.0f,
4656         31.0f, 32.0f
4657     }));
4658
4659     return result;
4660 }
4661
4662 LayerTestResult<float, 4> Concatenation4dDim1Test(
4663     armnn::IWorkloadFactory& workloadFactory,
4664     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
4665 {
4666     return Concatenation4dDim1TestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
4667 }
4668
4669 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
4670 LayerTestResult<T, 4> Concatenation4dDim2TestImpl(
4671     armnn::IWorkloadFactory& workloadFactory,
4672     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4673     float qScale,
4674     int32_t qOffset)
4675 {
4676     armnn::TensorInfo outputTensorInfo({ 1, 3, 6, 2 }, ArmnnType);
4677
4678     LayerTestResult<T, 4> result = Concatenation4dTestImpl<ArmnnType>(
4679         workloadFactory, memoryManager, outputTensorInfo, 2, true, qScale, qOffset);
4680
4681     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4682         1.0f, 2.0f,
4683         3.0f, 4.0f,
4684         11.0f, 12.0f,
4685         13.0f, 14.0f,
4686         21.0f, 22.0f,
4687         23.0f, 24.0f,
4688
4689         5.0f, 6.0f,
4690         7.0f, 8.0f,
4691         15.0f, 16.0f,
4692         17.0f, 18.0f,
4693         25.0f, 26.0f,
4694         27.0f, 28.0f,
4695
4696         9.0f, 10.0f,
4697         11.0f, 12.0f,
4698         19.0f, 20.0f,
4699         21.0f, 22.0f,
4700         29.0f, 30.0f,
4701         31.0f, 32.0f
4702     }));
4703
4704     return result;
4705 }
4706
4707 LayerTestResult<float, 4> Concatenation4dDim2Test(
4708     armnn::IWorkloadFactory& workloadFactory,
4709     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
4710 {
4711     return Concatenation4dDim2TestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
4712 }
4713
4714 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
4715 LayerTestResult<T, 4> Concatenation4dDim3TestImpl(
4716     armnn::IWorkloadFactory& workloadFactory,
4717     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4718     float qScale,
4719     int32_t qOffset,
4720     bool useSubtensor)
4721 {
4722     armnn::TensorInfo outputTensorInfo({ 1, 3, 2, 6 }, ArmnnType);
4723
4724     LayerTestResult<T, 4> result = Concatenation4dTestImpl<ArmnnType>(
4725         workloadFactory, memoryManager, outputTensorInfo, 3, useSubtensor, qScale, qOffset);
4726
4727     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4728         1.0f, 2.0f,
4729         11.0f, 12.0f,
4730         21.0f, 22.0f,
4731         3.0f, 4.0f,
4732         13.0f, 14.0f,
4733         23.0f, 24.0f,
4734
4735         5.0f, 6.0f,
4736         15.0f, 16.0f,
4737         25.0f, 26.0f,
4738         7.0f, 8.0f,
4739         17.0f, 18.0f,
4740         27.0f, 28.0f,
4741
4742         9.0f, 10.0f,
4743         19.0f, 20.0f,
4744         29.0f, 30.0f,
4745         11.0f, 12.0f,
4746         21.0f, 22.0f,
4747         31.0f, 32.0f
4748     }));
4749
4750     return result;
4751 }
4752
4753 LayerTestResult<float, 4> Concatenation4dDim3Test(
4754     armnn::IWorkloadFactory& workloadFactory,
4755     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4756     bool useSubtensor)
4757 {
4758     return Concatenation4dDim3TestImpl<armnn::DataType::Float32>(
4759         workloadFactory, memoryManager, 0.0f, 0, useSubtensor);
4760 }
4761
4762 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
4763 LayerTestResult<T, 4> Concatenation4dDiffShapeDim0TestImpl(
4764     armnn::IWorkloadFactory& workloadFactory,
4765     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4766     float qScale,
4767     int32_t qOffset)
4768 {
4769     unsigned int dimension = 0;
4770     armnn::TensorInfo inputTensorInfo0({ 1, 3, 2, 2 }, ArmnnType);
4771
4772     auto input0 = MakeTensor<T, 4>(inputTensorInfo0, QuantizedVector<T>(qScale, qOffset, {
4773         1.0f, 2.0f,
4774         3.0f, 4.0f,
4775         5.0f, 6.0f,
4776         7.0f, 8.0f,
4777         9.0f, 10.0f,
4778         11.0f, 12.0f
4779     }));
4780
4781     armnn::TensorInfo inputTensorInfo1({ 2, 3, 2, 2 }, ArmnnType);
4782
4783     auto input1 = MakeTensor<T, 4>(inputTensorInfo1, QuantizedVector<T>(qScale, qOffset, {
4784         11.0f, 12.0f,
4785         13.0f, 14.0f,
4786         15.0f, 16.0f,
4787         17.0f, 18.0f,
4788         19.0f, 20.0f,
4789         21.0f, 22.0f,
4790
4791         21.0f, 22.0f,
4792         23.0f, 24.0f,
4793         25.0f, 26.0f,
4794         27.0f, 28.0f,
4795         29.0f, 30.0f,
4796         31.0f, 32.0f
4797
4798     }));
4799
4800     armnn::TensorInfo outputTensorInfo({ 3, 3, 2, 2 }, ArmnnType);
4801
4802     LayerTestResult<T, 4> result(outputTensorInfo);
4803
4804     std::vector<T> output;
4805     output.resize(outputTensorInfo.GetNumElements());
4806     Concatenate<T>(workloadFactory,
4807                    memoryManager,
4808                    {inputTensorInfo0, inputTensorInfo1},
4809                    {input0.data(), input1.data()},
4810                    outputTensorInfo,
4811                    output.data(),
4812                    dimension,
4813                    true);
4814
4815     result.output = MakeTensor<T, 4>(outputTensorInfo, output);
4816     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4817         1.0f, 2.0f,
4818         3.0f, 4.0f,
4819         5.0f, 6.0f,
4820         7.0f, 8.0f,
4821         9.0f, 10.0f,
4822         11.0f, 12.0f,
4823
4824         11.0f, 12.0f,
4825         13.0f, 14.0f,
4826         15.0f, 16.0f,
4827         17.0f, 18.0f,
4828         19.0f, 20.0f,
4829         21.0f, 22.0f,
4830
4831         21.0f, 22.0f,
4832         23.0f, 24.0f,
4833         25.0f, 26.0f,
4834         27.0f, 28.0f,
4835         29.0f, 30.0f,
4836         31.0f, 32.0f
4837     }));
4838
4839     return result;
4840 }
4841
4842 LayerTestResult<float, 4> Concatenation4dDiffShapeDim0Test(
4843     armnn::IWorkloadFactory& workloadFactory,
4844     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
4845 {
4846     return Concatenation4dDiffShapeDim0TestImpl<armnn::DataType::Float32>(
4847         workloadFactory, memoryManager, 0.0f, 0);
4848 }
4849
4850 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
4851 LayerTestResult<T, 4> Concatenation4dDiffShapeDim1TestImpl(
4852     armnn::IWorkloadFactory& workloadFactory,
4853     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4854     float qScale,
4855     int32_t qOffset)
4856 {
4857     unsigned int dimension = 1;
4858     armnn::TensorInfo inputTensorInfo0({ 1, 3, 2, 2 }, ArmnnType);
4859
4860     auto input0 = MakeTensor<T, 4>(inputTensorInfo0, QuantizedVector<T>(qScale, qOffset, {
4861         1.0f, 2.0f,
4862         3.0f, 4.0f,
4863         5.0f, 6.0f,
4864         7.0f, 8.0f,
4865         9.0f, 10.0f,
4866         11.0f, 12.0f
4867     }));
4868
4869     armnn::TensorInfo inputTensorInfo1({ 1, 2, 2, 2 }, ArmnnType);
4870
4871     auto input1 = MakeTensor<T, 4>(inputTensorInfo1, QuantizedVector<T>(qScale, qOffset, {
4872         11.0f, 12.0f,
4873         13.0f, 14.0f,
4874         15.0f, 16.0f,
4875         17.0f, 18.0f,
4876
4877     }));
4878
4879     armnn::TensorInfo outputTensorInfo({ 1, 5, 2, 2 }, ArmnnType);
4880
4881     LayerTestResult<T, 4> result(outputTensorInfo);
4882
4883     std::vector<T> output;
4884     output.resize(outputTensorInfo.GetNumElements());
4885     Concatenate<T>(workloadFactory,
4886                    memoryManager,
4887                    {inputTensorInfo0, inputTensorInfo1},
4888                    {input0.data(), input1.data()},
4889                    outputTensorInfo,
4890                    output.data(),
4891                    dimension,
4892                    true);
4893
4894     result.output = MakeTensor<T, 4>(outputTensorInfo, output);
4895     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4896         1.0f, 2.0f,
4897         3.0f, 4.0f,
4898         5.0f, 6.0f,
4899         7.0f, 8.0f,
4900         9.0f, 10.0f,
4901         11.0f, 12.0f,
4902         11.0f, 12.0f,
4903         13.0f, 14.0f,
4904         15.0f, 16.0f,
4905         17.0f, 18.0f
4906     }));
4907
4908     return result;
4909 }
4910
4911 LayerTestResult<float, 4> Concatenation4dDiffShapeDim1Test(
4912     armnn::IWorkloadFactory& workloadFactory,
4913     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
4914 {
4915     return Concatenation4dDiffShapeDim1TestImpl<armnn::DataType::Float32>(
4916         workloadFactory, memoryManager, 0.0f, 0);
4917 }
4918
4919 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
4920 LayerTestResult<T, 4> Concatenation4dDiffShapeDim2TestImpl(
4921     armnn::IWorkloadFactory& workloadFactory,
4922     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
4923     float qScale,
4924     int32_t qOffset)
4925 {
4926     unsigned int dimension = 2;
4927     armnn::TensorInfo inputTensorInfo0({ 1, 3, 2, 2 }, ArmnnType);
4928
4929     auto input0 = MakeTensor<T, 4>(inputTensorInfo0, QuantizedVector<T>(qScale, qOffset, {
4930         1.0f, 2.0f,
4931         3.0f, 4.0f,
4932         5.0f, 6.0f,
4933         7.0f, 8.0f,
4934         9.0f, 10.0f,
4935         11.0f, 12.0f
4936     }));
4937
4938     armnn::TensorInfo inputTensorInfo1({ 1, 3, 3, 2 }, ArmnnType);
4939
4940     auto input1 = MakeTensor<T, 4>(inputTensorInfo1, QuantizedVector<T>(qScale, qOffset, {
4941         11.0f, 12.0f,
4942         13.0f, 14.0f,
4943         15.0f, 16.0f,
4944         17.0f, 18.0f,
4945         19.0f, 20.0f,
4946         21.0f, 22.0f,
4947         23.0f, 24.0f,
4948         25.0f, 26.0f,
4949         27.0f, 28.0f
4950     }));
4951
4952     armnn::TensorInfo outputTensorInfo({ 1, 3, 5, 2 }, ArmnnType);
4953
4954     LayerTestResult<T, 4> result(outputTensorInfo);
4955
4956     std::vector<T> output;
4957     output.resize(outputTensorInfo.GetNumElements());
4958     Concatenate<T>(workloadFactory,
4959                    memoryManager,
4960                    {inputTensorInfo0, inputTensorInfo1},
4961                    {input0.data(), input1.data()},
4962                    outputTensorInfo,
4963                    output.data(),
4964                    dimension,
4965                    true);
4966
4967     result.output = MakeTensor<T, 4>(outputTensorInfo, output);
4968     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
4969         1.0f, 2.0f,
4970         3.0f, 4.0f,
4971         11.0f, 12.0f,
4972         13.0f, 14.0f,
4973         15.0f, 16.0f,
4974
4975         5.0f, 6.0f,
4976         7.0f, 8.0f,
4977         17.0f, 18.0f,
4978         19.0f, 20.0f,
4979         21.0f, 22.0f,
4980
4981         9.0f, 10.0f,
4982         11.0f, 12.0f,
4983         23.0f, 24.0f,
4984         25.0f, 26.0f,
4985         27.0f, 28.0f
4986     }));
4987
4988     return result;
4989 }
4990
4991 LayerTestResult<float, 4> Concatenation4dDiffShapeDim2Test(
4992     armnn::IWorkloadFactory& workloadFactory,
4993     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
4994 {
4995     return Concatenation4dDiffShapeDim2TestImpl<armnn::DataType::Float32>(
4996         workloadFactory, memoryManager, 0.0f, 0);
4997 }
4998
4999 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
5000 LayerTestResult<T, 4> Concatenation4dDiffShapeDim3TestImpl(
5001     armnn::IWorkloadFactory& workloadFactory,
5002     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
5003     float qScale,
5004     int32_t qOffset,
5005     bool useSubtensor)
5006 {
5007     unsigned int dimension = 3;
5008     armnn::TensorInfo inputTensorInfo0({ 1, 3, 2, 2 }, ArmnnType);
5009
5010     auto input0 = MakeTensor<T, 4>(inputTensorInfo0, QuantizedVector<T>(qScale, qOffset, {
5011         1.0f, 2.0f,
5012         3.0f, 4.0f,
5013         5.0f, 6.0f,
5014         7.0f, 8.0f,
5015         9.0f, 10.0f,
5016         11.0f, 12.0f
5017     }));
5018
5019     armnn::TensorInfo inputTensorInfo1({ 1, 3, 2, 3 }, ArmnnType);
5020
5021     auto input1 = MakeTensor<T, 4>(inputTensorInfo1, QuantizedVector<T>(qScale, qOffset, {
5022         11.0f, 12.0f, 13.0f,
5023         14.0f, 15.0f, 16.0f,
5024
5025         17.0f, 18.0f, 19.0f,
5026         20.0f, 21.0f, 22.0f,
5027
5028         23.0f, 24.0f, 25.0f,
5029         26.0f, 27.0f, 28.0f
5030     }));
5031
5032     armnn::TensorInfo outputTensorInfo({ 1, 3, 2, 5 }, ArmnnType);
5033
5034     LayerTestResult<T, 4> result(outputTensorInfo);
5035
5036     std::vector<T> output;
5037     output.resize(outputTensorInfo.GetNumElements());
5038     Concatenate<T>(workloadFactory,
5039                    memoryManager,
5040                    {inputTensorInfo0, inputTensorInfo1},
5041                    {input0.data(), input1.data()},
5042                    outputTensorInfo,
5043                    output.data(),
5044                    dimension,
5045                    useSubtensor);
5046
5047     result.output = MakeTensor<T, 4>(outputTensorInfo, output);
5048     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, {
5049         1.0f, 2.0f, 11.0f, 12.0f, 13.0f,
5050         3.0f, 4.0f, 14.0f, 15.0f, 16.0f,
5051         5.0f, 6.0f, 17.0f, 18.0f, 19.0f,
5052         7.0f, 8.0f, 20.0f, 21.0f, 22.0f,
5053         9.0f, 10.0f, 23.0f, 24.0f, 25.0f,
5054         11.0f, 12.0f, 26.0f, 27.0f, 28.0f
5055     }));
5056
5057     return result;
5058 }
5059
5060 LayerTestResult<float, 4> Concatenation4dDiffShapeDim3Test(
5061     armnn::IWorkloadFactory& workloadFactory,
5062     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
5063     bool useSubtensor)
5064 {
5065     return Concatenation4dDiffShapeDim3TestImpl<armnn::DataType::Float32>(
5066         workloadFactory, memoryManager, 0.0f, 0, useSubtensor);
5067 }
5068
5069 LayerTestResult<float, 4> ResizeBilinearNopTest(
5070     armnn::IWorkloadFactory& workloadFactory,
5071     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
5072     const armnn::DataLayout dataLayout)
5073 {
5074     const armnn::TensorInfo inputTensorInfo =
5075         armnnUtils::GetTensorInfo(1, 2, 4, 4, dataLayout, armnn::DataType::Float32);
5076
5077     const armnn::TensorInfo outputTensorInfo =
5078         armnnUtils::GetTensorInfo(1, 2, 4, 4, dataLayout, armnn::DataType::Float32);
5079
5080     std::vector<float> inputData({
5081         1.0f, 2.0f, 3.0f, 4.0f,
5082         2.0f, 3.0f, 4.0f, 5.0f,
5083         3.0f, 4.0f, 5.0f, 6.0f,
5084         4.0f, 5.0f, 6.0f, 7.0f,
5085
5086         1.0f, 2.0f, 3.0f, 4.0f,
5087         2.0f, 3.0f, 4.0f, 5.0f,
5088         3.0f, 4.0f, 5.0f, 6.0f,
5089         4.0f, 5.0f, 6.0f, 7.0f
5090     });
5091
5092     const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
5093     if (dataLayout == armnn::DataLayout::NHWC)
5094     {
5095         std::vector<float> tmp(inputData.size());
5096         armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data(), sizeof(float));
5097         inputData = tmp;
5098     }
5099
5100     auto input = MakeTensor<float, 4>(inputTensorInfo, inputData);
5101
5102     LayerTestResult<float, 4> result(outputTensorInfo);
5103     result.outputExpected = input;
5104
5105     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
5106     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
5107
5108     armnn::ResizeBilinearQueueDescriptor descriptor;
5109     descriptor.m_Parameters.m_DataLayout = dataLayout;
5110     armnn::WorkloadInfo info;
5111     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
5112     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
5113
5114     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateResizeBilinear(descriptor, info);
5115
5116     inputHandle->Allocate();
5117     outputHandle->Allocate();
5118     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
5119
5120     workload->PostAllocationConfigure();
5121     workload->Execute();
5122
5123     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
5124     return result;
5125 }
5126
5127 LayerTestResult<float, 4> SimpleResizeBilinearTest(
5128     armnn::IWorkloadFactory& workloadFactory,
5129     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
5130     const armnn::DataLayout dataLayout)
5131 {
5132     const armnn::TensorInfo inputTensorInfo =
5133         armnnUtils::GetTensorInfo(1, 2, 2, 2, dataLayout, armnn::DataType::Float32);
5134
5135     const armnn::TensorInfo outputTensorInfo =
5136         armnnUtils::GetTensorInfo(1, 2, 1, 1, dataLayout, armnn::DataType::Float32);
5137
5138     std::vector<float> inputData({
5139           1.0f, 255.0f,
5140         200.0f, 250.0f,
5141
5142         250.0f, 200.0f,
5143         250.0f,   1.0f
5144     });
5145
5146     // The 'resize bilinear' operation projects the top-left corner of output texels into the input image,
5147     // then figures out the interpolants and weights. Note this is different to projecting the centre of the
5148     // output texel. Thus, for a input matrix of 2x2, we'll expect the output 1x1 matrix to contain, as
5149     // its single element, the value that was at position (0,0) of the input matrix (rather than an average,
5150     // which we would expect if projecting the centre).
5151
5152     std::vector<float> outputData({
5153           1.0f,
5154
5155         250.0f
5156     });
5157
5158     const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
5159     if (dataLayout == armnn::DataLayout::NHWC)
5160     {
5161         std::vector<float> tmp(inputData.size());
5162         armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data(), sizeof(float));
5163         inputData = tmp;
5164
5165         std::vector<float> tmp1(outputData.size());
5166         armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data(), sizeof(float));
5167         outputData = tmp1;
5168     }
5169
5170     auto input = MakeTensor<float, 4>(inputTensorInfo, inputData);
5171
5172     LayerTestResult<float, 4> result(outputTensorInfo);
5173     result.outputExpected = MakeTensor<float, 4>(outputTensorInfo, outputData);
5174
5175     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
5176     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
5177
5178     armnn::ResizeBilinearQueueDescriptor descriptor;
5179     descriptor.m_Parameters.m_DataLayout = dataLayout;
5180     armnn::WorkloadInfo info;
5181     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
5182     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
5183
5184     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateResizeBilinear(descriptor, info);
5185
5186     inputHandle->Allocate();
5187     outputHandle->Allocate();
5188     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
5189
5190     workload->PostAllocationConfigure();
5191     workload->Execute();
5192
5193     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
5194     return result;
5195 }
5196
5197 LayerTestResult<float, 4> ResizeBilinearSqMinTest(
5198     armnn::IWorkloadFactory& workloadFactory,
5199     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
5200     const armnn::DataLayout dataLayout)
5201 {
5202     const armnn::TensorInfo inputTensorInfo =
5203         armnnUtils::GetTensorInfo(1, 2, 4, 4, dataLayout, armnn::DataType::Float32);
5204
5205     const armnn::TensorInfo outputTensorInfo =
5206         armnnUtils::GetTensorInfo(1, 2, 2, 2, dataLayout, armnn::DataType::Float32);
5207
5208     std::vector<float> inputData({
5209         1.0f, 2.0f, 3.0f, 4.0f,
5210         2.0f, 3.0f, 4.0f, 5.0f,
5211         3.0f, 4.0f, 5.0f, 6.0f,
5212         4.0f, 5.0f, 6.0f, 7.0f,
5213
5214         7.0f, 6.0f, 5.0f, 4.0f,
5215         6.0f, 5.0f, 4.0f, 3.0f,
5216         5.0f, 4.0f, 3.0f, 2.0f,
5217         4.0f, 3.0f, 2.0f, 1.0f
5218     });
5219
5220     std::vector<float> outputData({
5221         1.0f, 3.0f,
5222         3.0f, 5.0f,
5223
5224         7.0f, 5.0f,
5225         5.0f, 3.0f
5226     });
5227
5228     const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
5229     if (dataLayout == armnn::DataLayout::NHWC)
5230     {
5231         std::vector<float> tmp(inputData.size());
5232         armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data(), sizeof(float));
5233         inputData = tmp;
5234
5235         std::vector<float> tmp1(outputData.size());
5236         armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data(), sizeof(float));
5237         outputData = tmp1;
5238     }
5239
5240     auto input = MakeTensor<float, 4>(inputTensorInfo, inputData);
5241
5242     LayerTestResult<float, 4> result(outputTensorInfo);
5243     result.outputExpected = MakeTensor<float, 4>(outputTensorInfo, outputData);
5244
5245     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
5246     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
5247
5248     armnn::ResizeBilinearQueueDescriptor descriptor;
5249     descriptor.m_Parameters.m_DataLayout = dataLayout;
5250     armnn::WorkloadInfo info;
5251     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
5252     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
5253
5254     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateResizeBilinear(descriptor, info);
5255
5256     inputHandle->Allocate();
5257     outputHandle->Allocate();
5258     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
5259
5260     workload->PostAllocationConfigure();
5261     workload->Execute();
5262
5263     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
5264     return result;
5265 }
5266
5267 LayerTestResult<float, 4> ResizeBilinearMinTest(
5268     armnn::IWorkloadFactory& workloadFactory,
5269     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
5270     const armnn::DataLayout dataLayout)
5271 {
5272     const armnn::TensorInfo inputTensorInfo =
5273         armnnUtils::GetTensorInfo(1, 2, 3, 5, dataLayout, armnn::DataType::Float32);
5274
5275     const armnn::TensorInfo outputTensorInfo =
5276         armnnUtils::GetTensorInfo(1, 2, 2, 3, dataLayout, armnn::DataType::Float32);
5277
5278     std::vector<float> inputData({
5279           1.0f,   2.0f,   3.0f,   5.0f,   8.0f,
5280          13.0f,  21.0f,  34.0f,  55.0f,  89.0f,
5281         144.0f, 233.0f, 377.0f, 610.0f, 987.0f,
5282
5283         987.0f, 610.0f, 377.0f, 233.0f, 144.0f,
5284          89.0f,  55.0f,  34.0f,  21.0f,  13.0f,
5285           8.0f,   5.0f,   3.0f,   2.0f,   1.0f
5286     });
5287
5288     std::vector<float> outputData({
5289           1.0f,   2.6666f,   6.00f,
5290          78.5f, 179.3333f, 401.00f,
5291
5292         987.0f, 454.6670f, 203.33f,
5293          48.5f,  22.3333f,  10.00f
5294     });
5295
5296     const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
5297     if (dataLayout == armnn::DataLayout::NHWC)
5298     {
5299         std::vector<float> tmp(inputData.size());
5300         armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data(), sizeof(float));
5301         inputData = tmp;
5302
5303         std::vector<float> tmp1(outputData.size());
5304         armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data(), sizeof(float));
5305         outputData = tmp1;
5306     }
5307
5308     auto input = MakeTensor<float, 4>(inputTensorInfo, inputData);
5309
5310     LayerTestResult<float, 4> result(outputTensorInfo);
5311     result.outputExpected = MakeTensor<float, 4>(outputTensorInfo, outputData);
5312
5313     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
5314     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
5315
5316     armnn::ResizeBilinearQueueDescriptor descriptor;
5317     descriptor.m_Parameters.m_DataLayout = dataLayout;
5318     armnn::WorkloadInfo info;
5319     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
5320     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
5321
5322     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateResizeBilinear(descriptor, info);
5323
5324     inputHandle->Allocate();
5325     outputHandle->Allocate();
5326     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
5327
5328     workload->PostAllocationConfigure();
5329     workload->Execute();
5330
5331     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
5332     return result;
5333 }
5334
5335 LayerTestResult<float, 4> ResizeBilinearMagTest(
5336     armnn::IWorkloadFactory& workloadFactory,
5337     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
5338     const armnn::DataLayout dataLayout)
5339 {
5340     const armnn::TensorInfo inputTensorInfo =
5341         armnnUtils::GetTensorInfo(1, 2, 3, 2, dataLayout, armnn::DataType::Float32);
5342
5343     const armnn::TensorInfo outputTensorInfo =
5344         armnnUtils::GetTensorInfo(1, 2, 3, 5, dataLayout, armnn::DataType::Float32);
5345
5346     std::vector<float> inputData({
5347           1.0f,   2.0f,
5348          13.0f,  21.0f,
5349         144.0f, 233.0f,
5350
5351         233.0f, 144.0f,
5352          21.0f,  13.0f,
5353           2.0f,   1.0f
5354     });
5355
5356     std::vector<float> outputData({
5357           1.0f,   1.4f,   1.8f,   2.0f,   2.0f,
5358          13.0f,  16.2f,  19.4f,  21.0f,  21.0f,
5359         144.0f, 179.6f, 215.2f, 233.0f, 233.0f,
5360
5361         233.0f, 197.4f, 161.8f, 144.0f, 144.0f,
5362          21.0f,  17.8f,  14.6f,  13.0f,  13.0f,
5363           2.0f,   1.6f,   1.2f,   1.0f,   1.0f
5364     });
5365
5366     const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
5367     if (dataLayout == armnn::DataLayout::NHWC)
5368     {
5369         std::vector<float> tmp(inputData.size());
5370         armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data(), sizeof(float));
5371         inputData = tmp;
5372
5373         std::vector<float> tmp1(outputData.size());
5374         armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data(), sizeof(float));
5375         outputData = tmp1;
5376     }
5377
5378     auto input = MakeTensor<float, 4>(inputTensorInfo, inputData);
5379
5380     LayerTestResult<float, 4> result(outputTensorInfo);
5381     result.outputExpected = MakeTensor<float, 4>(outputTensorInfo, outputData);
5382
5383     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
5384     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
5385
5386     armnn::ResizeBilinearQueueDescriptor descriptor;
5387     descriptor.m_Parameters.m_DataLayout = dataLayout;
5388     armnn::WorkloadInfo info;
5389     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
5390     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
5391
5392     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateResizeBilinear(descriptor, info);
5393
5394     inputHandle->Allocate();
5395     outputHandle->Allocate();
5396     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
5397
5398     workload->PostAllocationConfigure();
5399     workload->Execute();
5400
5401     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
5402     return result;
5403 }
5404
5405 LayerTestResult<float, 2> FakeQuantizationTest(
5406     armnn::IWorkloadFactory& workloadFactory,
5407     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
5408 {
5409     constexpr unsigned int width = 2;
5410     constexpr unsigned int height = 3;
5411
5412     const armnn::TensorInfo tensorInfo({height, width },
5413         armnn::DataType::Float32);
5414     auto input = MakeTensor<float, 2>(tensorInfo, std::vector<float>({
5415        -10.0f,  -5.0f,
5416          0.0f,   5.0f,
5417         10.0f,  10.0f
5418     }));
5419
5420     LayerTestResult<float, 2> ret(tensorInfo);
5421
5422     std::unique_ptr<armnn::ITensorHandle> inputHandle  = workloadFactory.CreateTensorHandle(tensorInfo);
5423
5424     std::unique_ptr<armnn::ITensorHandle> outputHandle  = workloadFactory.CreateTensorHandle(tensorInfo);
5425
5426     armnn::FakeQuantizationQueueDescriptor data;
5427     armnn::WorkloadInfo info;
5428
5429     AddInputToWorkload(data, info, tensorInfo, inputHandle.get());
5430     AddOutputToWorkload(data, info, tensorInfo, outputHandle.get());
5431     float min = -10.f;
5432     float max = 10.f;
5433
5434     data.m_Parameters.m_Min = min;
5435     data.m_Parameters.m_Max = max;
5436
5437     armnn::PassthroughCpuTensorHandle refHandle(tensorInfo, &ret.outputExpected[0][0]);
5438     armnn::FakeQuantizationQueueDescriptor refData = data;
5439     armnn::WorkloadInfo refInfo = info;
5440     SetWorkloadOutput(refData, refInfo, 0, tensorInfo, &refHandle);
5441
5442     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateFakeQuantization(data, info);
5443
5444     inputHandle->Allocate();
5445     outputHandle->Allocate();
5446
5447     CopyDataToITensorHandle(inputHandle.get(), &input[0][0]);
5448
5449     workload->PostAllocationConfigure();
5450     workload->Execute();
5451
5452     CopyDataFromITensorHandle(&ret.output[0][0], outputHandle.get());
5453
5454     ret.outputExpected = MakeTensor<float, 2>(tensorInfo, std::vector<float>({
5455         0.0f,     63.0f,
5456         128.0f,   191.0f,
5457         255.0f,   255.0f
5458     }));
5459     return ret;
5460 }
5461
5462 namespace
5463 {
5464
5465 LayerTestResult<float, 4> L2NormalizationTestImpl(
5466     armnn::IWorkloadFactory& workloadFactory,
5467     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
5468     const armnn::TensorShape& inputOutputTensorShape,
5469     const std::vector<float>& inputValues,
5470     const std::vector<float>& expectedOutputValues,
5471     const armnn::DataLayout layout)
5472 {
5473     const armnn::TensorInfo inputTensorInfo(inputOutputTensorShape, armnn::DataType::Float32);
5474     const armnn::TensorInfo outputTensorInfo(inputOutputTensorShape, armnn::DataType::Float32);
5475
5476     // at this point if we require it permute the input data
5477     const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
5478     std::vector<float> inputData = inputValues;
5479     if (layout == armnn::DataLayout::NHWC)
5480     {
5481         std::vector<float> tmp(inputData.size());
5482         armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data(), sizeof(float));
5483         inputData = tmp;
5484     }
5485
5486     auto inputTensor = MakeTensor<float, 4>(inputTensorInfo, std::vector<float>(inputData));
5487
5488     LayerTestResult<float, 4> result(outputTensorInfo);
5489     std::vector<float> expectedOutputData = expectedOutputValues;
5490     if (layout == armnn::DataLayout::NHWC)
5491     {
5492         std::vector<float> tmp(expectedOutputData.size());
5493         armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC,
5494                             expectedOutputData.data(), tmp.data(), sizeof(float));
5495         expectedOutputData = tmp;
5496     }
5497     result.outputExpected = MakeTensor<float, 4>(inputTensorInfo, std::vector<float>(expectedOutputData));
5498
5499     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
5500     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
5501
5502     armnn::L2NormalizationQueueDescriptor descriptor;
5503     descriptor.m_Parameters.m_DataLayout = layout;
5504     armnn::WorkloadInfo info;
5505
5506     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
5507     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
5508
5509     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateL2Normalization(descriptor, info);
5510
5511     inputHandle->Allocate();
5512     outputHandle->Allocate();
5513
5514     CopyDataToITensorHandle(inputHandle.get(), &inputTensor[0][0][0][0]);
5515
5516     workload->PostAllocationConfigure();
5517     ExecuteWorkload(*workload, memoryManager);
5518
5519     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
5520
5521     return result;
5522 }
5523
5524 float CalcInvL2Norm(std::initializer_list<float> elements)
5525 {
5526     const float reduction = std::accumulate(elements.begin(), elements.end(), 0.0f,
5527         [](float acc, float element) { return acc + element * element; });
5528     return 1.0f / sqrtf(reduction);
5529 }
5530
5531 } // anonymous namespace
5532
5533 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
5534 LayerTestResult<T, 2> Pad2dTestCommon(
5535     armnn::IWorkloadFactory& workloadFactory,
5536     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
5537     float qScale,
5538     int32_t qOffset)
5539 {
5540     const armnn::TensorShape inputShape{ 3, 3 };
5541     const armnn::TensorShape outputShape{ 7, 7 };
5542
5543     const armnn::TensorInfo inputTensorInfo(inputShape, ArmnnType);
5544     const armnn::TensorInfo outputTensorInfo(outputShape, ArmnnType);
5545
5546     std::vector<T> inputValues(
5547     QuantizedVector<T>(qScale, qOffset,
5548     {
5549       // Height (3) x Width (3)
5550       4, 8, 6,
5551       7, 4, 4,
5552       3, 2, 4
5553     }));
5554
5555     std::vector<T> expectedOutputValues(
5556     QuantizedVector<T>(qScale, qOffset,
5557     {
5558       0, 0, 0, 0, 0, 0, 0,
5559       0, 0, 0, 0, 0, 0, 0,
5560       0, 0, 4, 8, 6, 0, 0,
5561       0, 0, 7, 4, 4, 0, 0,
5562       0, 0, 3, 2, 4, 0, 0,
5563       0, 0, 0, 0, 0, 0, 0,
5564       0, 0, 0, 0, 0, 0, 0
5565     }));
5566
5567     auto inputTensor = MakeTensor<T, 2>(inputTensorInfo, std::vector<T>(inputValues));
5568
5569     LayerTestResult<T, 2> result(outputTensorInfo);
5570     result.outputExpected = MakeTensor<T, 2>(outputTensorInfo, std::vector<T>(expectedOutputValues));
5571
5572     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
5573     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
5574
5575     armnn::PadQueueDescriptor descriptor;
5576
5577     std::vector<std::pair<unsigned int, unsigned int>> PadList;
5578     PadList.push_back(std::pair<unsigned int, unsigned int>(2,2));
5579     PadList.push_back(std::pair<unsigned int, unsigned int>(2,2));
5580
5581     descriptor.m_Parameters.m_PadList = PadList;
5582     armnn::WorkloadInfo info;
5583
5584     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
5585     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
5586
5587     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePad(descriptor, info);
5588
5589     inputHandle->Allocate();
5590     outputHandle->Allocate();
5591
5592     CopyDataToITensorHandle(inputHandle.get(), &inputTensor[0][0]);
5593
5594     workload->PostAllocationConfigure();
5595     workload->Execute();
5596
5597     CopyDataFromITensorHandle(&result.output[0][0], outputHandle.get());
5598
5599     return result;
5600 }
5601
5602 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
5603 LayerTestResult<T, 3> Pad3dTestCommon(
5604     armnn::IWorkloadFactory& workloadFactory,
5605     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
5606     float qScale,
5607     int32_t qOffset)
5608 {
5609     const armnn::TensorShape inputShape{ 2, 2, 2 };
5610     const armnn::TensorShape outputShape{ 3, 5, 6 };
5611
5612     const armnn::TensorInfo inputTensorInfo(inputShape, ArmnnType);
5613     const armnn::TensorInfo outputTensorInfo(outputShape, ArmnnType);
5614
5615     std::vector<T> inputValues(
5616       QuantizedVector<T>(qScale,qOffset,
5617     {
5618         // Channel 0, Height (2) x Width (2)
5619         0, 4,
5620         2, 5,
5621
5622         // Channel 1, Height (2) x Width (2)
5623         6, 1,
5624         5, 2
5625     }));
5626
5627     std::vector<T> expectedOutputValues(
5628       QuantizedVector<T>(qScale,qOffset,
5629     {
5630
5631         0, 0, 0, 0, 0, 0,
5632         0, 0, 0, 0, 0, 0,
5633         0, 0, 0, 4, 0, 0,
5634         0, 0, 2, 5, 0, 0,
5635         0, 0, 0, 0, 0, 0,
5636
5637         0, 0, 0, 0, 0, 0,
5638         0, 0, 0, 0, 0, 0,
5639         0, 0, 6, 1, 0, 0,
5640         0, 0, 5, 2, 0, 0,
5641         0, 0, 0, 0, 0, 0,
5642
5643         0, 0, 0, 0, 0, 0,
5644         0, 0, 0, 0, 0, 0,
5645         0, 0, 0, 0, 0, 0,
5646         0, 0, 0, 0, 0, 0,
5647         0, 0, 0, 0, 0, 0
5648
5649     }));
5650
5651     auto inputTensor = MakeTensor<T, 3>(inputTensorInfo, std::vector<T>(inputValues));
5652
5653     LayerTestResult<T, 3> result(outputTensorInfo);
5654     result.outputExpected = MakeTensor<T, 3>(outputTensorInfo, std::vector<T>(expectedOutputValues));
5655
5656     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
5657     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
5658
5659     armnn::PadQueueDescriptor descriptor;
5660
5661     std::vector<std::pair<unsigned int, unsigned int>> PadList;
5662     PadList.push_back(std::pair<unsigned int, unsigned int>(0,1));
5663     PadList.push_back(std::pair<unsigned int, unsigned int>(2,1));
5664     PadList.push_back(std::pair<unsigned int, unsigned int>(2,2));
5665
5666     descriptor.m_Parameters.m_PadList = PadList;
5667     armnn::WorkloadInfo info;
5668
5669     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
5670     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
5671
5672     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePad(descriptor, info);
5673
5674     inputHandle->Allocate();
5675     outputHandle->Allocate();
5676
5677     CopyDataToITensorHandle(inputHandle.get(), &inputTensor[0][0][0]);
5678
5679     workload->PostAllocationConfigure();
5680     workload->Execute();
5681
5682     CopyDataFromITensorHandle(&result.output[0][0][0], outputHandle.get());
5683
5684     return result;
5685 }
5686
5687 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
5688 LayerTestResult<T, 4> Pad4dTestCommon(
5689     armnn::IWorkloadFactory& workloadFactory,
5690     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
5691     float qScale,
5692     int32_t qOffset)
5693 {
5694     const armnn::TensorShape inputShape{ 2, 2, 3, 2 };
5695     const armnn::TensorShape outputShape{ 4, 5, 7, 4 };
5696
5697     const armnn::TensorInfo inputTensorInfo(inputShape, ArmnnType);
5698     const armnn::TensorInfo outputTensorInfo(outputShape, ArmnnType);
5699
5700     std::vector<T> inputValues(
5701       QuantizedVector<T>(qScale,qOffset,
5702     {
5703         // Batch 0, Channel 0, Height (3) x Width (2)
5704         0, 1,
5705         2, 3,
5706         4, 5,
5707
5708         // Batch 0, Channel 1, Height (3) x Width (2)
5709         6, 7,
5710         8, 9,
5711         10, 11,
5712
5713         // Batch 1, Channel 0, Height (3) x Width (2)
5714         12, 13,
5715         14, 15,
5716         16, 17,
5717
5718         // Batch 1, Channel 1, Height (3) x Width (2)
5719         18, 19,
5720         20, 21,
5721         22, 23
5722     }));
5723
5724     std::vector<T> expectedOutputValues(
5725       QuantizedVector<T>(qScale,qOffset,
5726     {
5727         0, 0, 0, 0,
5728         0, 0, 0, 0,
5729         0, 0, 0, 0,
5730         0, 0, 0, 0,
5731         0, 0, 0, 0,
5732         0, 0, 0, 0,
5733         0, 0, 0, 0,
5734
5735         0, 0, 0, 0,
5736         0, 0, 0, 0,
5737         0, 0, 0, 0,
5738         0, 0, 0, 0,
5739         0, 0, 0, 0,
5740         0, 0, 0, 0,
5741         0, 0, 0, 0,
5742
5743         0, 0, 0, 0,
5744         0, 0, 0, 0,
5745         0, 0, 0, 0,
5746         0, 0, 0, 0,
5747         0, 0, 0, 0,
5748         0, 0, 0, 0,
5749         0, 0, 0, 0,
5750
5751         0, 0, 0, 0,
5752         0, 0, 0, 0,
5753         0, 0, 0, 0,
5754         0, 0, 0, 0,
5755         0, 0, 0, 0,
5756         0, 0, 0, 0,
5757         0, 0, 0, 0,
5758
5759         0, 0, 0, 0,
5760         0, 0, 0, 0,
5761         0, 0, 0, 0,
5762         0, 0, 0, 0,
5763         0, 0, 0, 0,
5764         0, 0, 0, 0,
5765         0, 0, 0, 0,
5766
5767         0, 0, 0, 0,
5768         0, 0, 0, 0,
5769         0, 0, 0, 0,
5770         0, 0, 0, 0,
5771         0, 0, 0, 0,
5772         0, 0, 0, 0,
5773         0, 0, 0, 0,
5774
5775         0, 0, 0, 0,
5776         0, 0, 0, 0,
5777         0, 0, 0, 0,
5778         0, 0, 0, 0,
5779         0, 0, 0, 0,
5780         0, 0, 0, 0,
5781         0, 0, 0, 0,
5782
5783         0, 0, 0, 0,
5784         0, 0, 0, 0,
5785         0, 0, 0, 0,
5786         0, 0, 1, 0,
5787         0, 2, 3, 0,
5788         0, 4, 5, 0,
5789         0, 0, 0, 0,
5790
5791         0, 0, 0, 0,
5792         0, 0, 0, 0,
5793         0, 0, 0, 0,
5794         0, 6, 7, 0,
5795         0, 8, 9, 0,
5796         0, 10, 11, 0,
5797         0, 0, 0, 0,
5798
5799         0, 0, 0, 0,
5800         0, 0, 0, 0,
5801         0, 0, 0, 0,
5802         0, 0, 0, 0,
5803         0, 0, 0, 0,
5804         0, 0, 0, 0,
5805         0, 0, 0, 0,
5806
5807         0, 0, 0, 0,
5808         0, 0, 0, 0,
5809         0, 0, 0, 0,
5810         0, 0, 0, 0,
5811         0, 0, 0, 0,
5812         0, 0, 0, 0,
5813         0, 0, 0, 0,
5814
5815         0, 0, 0, 0,
5816         0, 0, 0, 0,
5817         0, 0, 0, 0,
5818         0, 0, 0, 0,
5819         0, 0, 0, 0,
5820         0, 0, 0, 0,
5821         0, 0, 0, 0,
5822
5823         0, 0, 0, 0,
5824         0, 0, 0, 0,
5825         0, 0, 0, 0,
5826         0, 12, 13, 0,
5827         0, 14, 15, 0,
5828         0, 16, 17, 0,
5829         0, 0, 0, 0,
5830
5831         0, 0, 0, 0,
5832         0, 0, 0, 0,
5833         0, 0, 0, 0,
5834         0, 18, 19, 0,
5835         0, 20, 21, 0,
5836         0, 22, 23, 0,
5837         0, 0, 0, 0,
5838
5839         0, 0, 0, 0,
5840         0, 0, 0, 0,
5841         0, 0, 0, 0,
5842         0, 0, 0, 0,
5843         0, 0, 0, 0,
5844         0, 0, 0, 0,
5845         0, 0, 0, 0,
5846
5847         0, 0, 0, 0,
5848         0, 0, 0, 0,
5849         0, 0, 0, 0,
5850         0, 0, 0, 0,
5851         0, 0, 0, 0,
5852         0, 0, 0, 0,
5853         0, 0, 0, 0,
5854
5855         0, 0, 0, 0,
5856         0, 0, 0, 0,
5857         0, 0, 0, 0,
5858         0, 0, 0, 0,
5859         0, 0, 0, 0,
5860         0, 0, 0, 0,
5861         0, 0, 0, 0,
5862
5863         0, 0, 0, 0,
5864         0, 0, 0, 0,
5865         0, 0, 0, 0,
5866         0, 0, 0, 0,
5867         0, 0, 0, 0,
5868         0, 0, 0, 0,
5869         0, 0, 0, 0,
5870
5871         0, 0, 0, 0,
5872         0, 0, 0, 0,
5873         0, 0, 0, 0,
5874         0, 0, 0, 0,
5875         0, 0, 0, 0,
5876         0, 0, 0, 0,
5877         0, 0, 0, 0,
5878
5879         0, 0, 0, 0,
5880         0, 0, 0, 0,
5881         0, 0, 0, 0,
5882         0, 0, 0, 0,
5883         0, 0, 0, 0,
5884         0, 0, 0, 0,
5885         0, 0, 0, 0
5886     }));
5887
5888     auto inputTensor = MakeTensor<T, 4>(inputTensorInfo, std::vector<T>(inputValues));
5889
5890     LayerTestResult<T, 4> result(outputTensorInfo);
5891     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, std::vector<T>(expectedOutputValues));
5892
5893     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
5894     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
5895
5896     armnn::PadQueueDescriptor descriptor;
5897
5898     std::vector<std::pair<unsigned int, unsigned int>> PadList;
5899     PadList.push_back(std::pair<unsigned int, unsigned int>(1,1));
5900     PadList.push_back(std::pair<unsigned int, unsigned int>(2,1));
5901     PadList.push_back(std::pair<unsigned int, unsigned int>(3,1));
5902     PadList.push_back(std::pair<unsigned int, unsigned int>(1,1));
5903
5904     descriptor.m_Parameters.m_PadList = PadList;
5905     armnn::WorkloadInfo info;
5906
5907     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
5908     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
5909
5910     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePad(descriptor, info);
5911
5912     inputHandle->Allocate();
5913     outputHandle->Allocate();
5914
5915     CopyDataToITensorHandle(inputHandle.get(), &inputTensor[0][0][0][0]);
5916
5917     workload->PostAllocationConfigure();
5918     workload->Execute();
5919
5920     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
5921
5922     return result;
5923 }
5924
5925 LayerTestResult<uint8_t, 2> PadUint82dTest(
5926     armnn::IWorkloadFactory& workloadFactory,
5927     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
5928 {
5929   return Pad2dTestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 1.0f, 0);
5930 }
5931
5932 LayerTestResult<uint8_t, 3> PadUint83dTest(
5933     armnn::IWorkloadFactory& workloadFactory,
5934     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
5935 {
5936   return Pad3dTestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 1.0f, 0);
5937 }
5938
5939 LayerTestResult<uint8_t, 4> PadUint84dTest(
5940     armnn::IWorkloadFactory& workloadFactory,
5941     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
5942 {
5943   return Pad4dTestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 1.0f, 0);
5944 }
5945
5946 LayerTestResult<float, 2> PadFloat322dTest(
5947     armnn::IWorkloadFactory& workloadFactory,
5948     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
5949 {
5950   return Pad2dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
5951 }
5952
5953 LayerTestResult<float, 3> PadFloat323dTest(
5954     armnn::IWorkloadFactory& workloadFactory,
5955     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
5956 {
5957   return Pad3dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
5958 }
5959
5960 LayerTestResult<float, 4> PadFloat324dTest(
5961     armnn::IWorkloadFactory& workloadFactory,
5962     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
5963 {
5964   return Pad4dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
5965 }
5966
5967 LayerTestResult<float, 4> L2Normalization1dTest(
5968     armnn::IWorkloadFactory& workloadFactory,
5969     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
5970     const armnn::DataLayout layout)
5971 {
5972     // Width: 1
5973     // Height: 1
5974     // Channels: 10
5975     // BatchSize: 1
5976     unsigned int numberOfBatches = 1;
5977     unsigned int numberOfChannels = 10;
5978     unsigned int height = 1;
5979     unsigned int width = 1;
5980
5981
5982     const armnn::TensorShape inputOutputShape = armnnUtils::GetTensorShape(
5983             numberOfBatches, numberOfChannels, height, width, layout);
5984     std::vector<float> inputValues
5985     {
5986         // Batch 0, Channel 0, Height (1) x Width (1)
5987          1.0f,
5988
5989         // Batch 0, Channel 1, Height (1) x Width (1)
5990          2.0f,
5991
5992         // Batch 0, Channel 2, Height (1) x Width (1)
5993          3.0f,
5994
5995         // Batch 0, Channel 3, Height (1) x Width (1)
5996          4.0f,
5997
5998         // Batch 0, Channel 4, Height (1) x Width (1)
5999          5.0f,
6000
6001         // Batch 0, Channel 5, Height (1) x Width (1)
6002          6.0f,
6003
6004         // Batch 0, Channel 6, Height (1) x Width (1)
6005          7.0f,
6006
6007         // Batch 0, Channel 7, Height (1) x Width (1)
6008          8.0f,
6009
6010         // Batch 0, Channel 8, Height (1) x Width (1)
6011          9.0f,
6012
6013         // Batch 0, Channel 9, Height (1) x Width (1)
6014         10.0f
6015     };
6016     const float approxInvL2Norm = 0.050964719f;
6017     std::vector<float> expectedOutputValues
6018     {
6019         // Batch 0, Channel 0, Height (1) x Width (1)
6020          1.0f * approxInvL2Norm,
6021          2.0f * approxInvL2Norm,
6022          3.0f * approxInvL2Norm,
6023          4.0f * approxInvL2Norm,
6024          5.0f * approxInvL2Norm,
6025          6.0f * approxInvL2Norm,
6026          7.0f * approxInvL2Norm,
6027          8.0f * approxInvL2Norm,
6028          9.0f * approxInvL2Norm,
6029         10.0f * approxInvL2Norm
6030     };
6031
6032
6033     return L2NormalizationTestImpl(workloadFactory, memoryManager, inputOutputShape,
6034                                    inputValues, expectedOutputValues, layout);
6035 }
6036
6037 LayerTestResult<float, 4> L2Normalization2dTest(
6038     armnn::IWorkloadFactory& workloadFactory,
6039     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
6040     const armnn::DataLayout layout)
6041 {
6042     // Width: 5
6043     // Height: 1
6044     // Channels: 2
6045     // BatchSize: 1
6046     unsigned int numberOfBatches = 1;
6047     unsigned int numberOfChannels = 2;
6048     unsigned int height = 1;
6049     unsigned int width = 5;
6050
6051     const armnn::TensorShape inputOutputShape = armnnUtils::GetTensorShape(
6052             numberOfBatches, numberOfChannels, height, width, layout);
6053     std::vector<float> inputValues
6054     {
6055         // Batch 0, Channel 0, Height (1) x Width (5)
6056         1.0f, 3.0f, 5.0f, 7.0f,  9.0f,
6057
6058         // Batch 0, Channel 1, Height (1) x Width (5)
6059         2.0f, 4.0f, 6.0f, 8.0f, 10.0f
6060     };
6061     std::vector<float> expectedOutputValues
6062     {
6063         // Batch 0, Channel 0, Height (1) x Width (5)
6064          1.0f * CalcInvL2Norm({ 1.0f,  2.0f }),
6065          3.0f * CalcInvL2Norm({ 3.0f,  4.0f }),
6066          5.0f * CalcInvL2Norm({ 5.0f,  6.0f }),
6067          7.0f * CalcInvL2Norm({ 7.0f,  8.0f }),
6068          9.0f * CalcInvL2Norm({ 9.0f, 10.0f }),
6069
6070         // Batch 0, Channel 1, Height (1) x Width (5)
6071          2.0f * CalcInvL2Norm({ 1.0f,  2.0f }),
6072          4.0f * CalcInvL2Norm({ 3.0f,  4.0f }),
6073          6.0f * CalcInvL2Norm({ 5.0f,  6.0f }),
6074          8.0f * CalcInvL2Norm({ 7.0f,  8.0f }),
6075         10.0f * CalcInvL2Norm({ 9.0f, 10.0f })
6076     };
6077
6078     return L2NormalizationTestImpl(workloadFactory, memoryManager, inputOutputShape,
6079                                    inputValues, expectedOutputValues, layout);
6080 }
6081
6082 LayerTestResult<float, 4> L2Normalization3dTest(
6083     armnn::IWorkloadFactory& workloadFactory,
6084     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
6085     const armnn::DataLayout layout)
6086 {
6087     // Width: 3
6088     // Height: 4
6089     // Channels: 2
6090     // BatchSize: 1
6091     unsigned int numberOfBatches = 1;
6092     unsigned int numberOfChannels = 2;
6093     unsigned int height = 4;
6094     unsigned int width = 3;
6095
6096     const armnn::TensorShape inputOutputShape = armnnUtils::GetTensorShape(
6097             numberOfBatches, numberOfChannels, height, width, layout);
6098     std::vector<float> inputValues
6099     {
6100         // Batch 0, Channel 0, Height (4) x Width (3)
6101         119.0f,  21.0f, 150.0f,
6102         149.0f,  32.0f, 179.0f,
6103          15.0f, 227.0f, 141.0f,
6104         147.0f, 199.0f, 220.0f,
6105
6106         // Batch 0, Channel 1, Height (4) x Width (3)
6107         110.0f, 140.0f,  73.0f,
6108         211.0f, 212.0f,  89.0f,
6109          24.0f, 138.0f, 188.0f,
6110         162.0f,  12.0f, 161.0f
6111     };
6112     std::vector<float> expectedOutputValues
6113     {
6114         // Batch 0, Channel 0, Height (4) x Width (3)
6115         119.0f * CalcInvL2Norm({ 119.0f, 110.0f }),
6116          21.0f * CalcInvL2Norm({  21.0f, 140.0f }),
6117         150.0f * CalcInvL2Norm({ 150.0f,  73.0f }),
6118         149.0f * CalcInvL2Norm({ 149.0f, 211.0f }),
6119          32.0f * CalcInvL2Norm({  32.0f, 212.0f }),
6120         179.0f * CalcInvL2Norm({ 179.0f,  89.0f }),
6121          15.0f * CalcInvL2Norm({  15.0f,  24.0f }),
6122         227.0f * CalcInvL2Norm({ 227.0f, 138.0f }),
6123         141.0f * CalcInvL2Norm({ 141.0f, 188.0f }),
6124         147.0f * CalcInvL2Norm({ 147.0f, 162.0f }),
6125         199.0f * CalcInvL2Norm({ 199.0f,  12.0f }),
6126         220.0f * CalcInvL2Norm({ 220.0f, 161.0f }),
6127
6128         // Batch 0, Channel 1, Height (4) x Width (3)
6129         110.0f * CalcInvL2Norm({ 119.0f, 110.0f }),
6130         140.0f * CalcInvL2Norm({  21.0f, 140.0f }),
6131          73.0f * CalcInvL2Norm({ 150.0f,  73.0f }),
6132         211.0f * CalcInvL2Norm({ 149.0f, 211.0f }),
6133         212.0f * CalcInvL2Norm({  32.0f, 212.0f }),
6134          89.0f * CalcInvL2Norm({ 179.0f,  89.0f }),
6135          24.0f * CalcInvL2Norm({  15.0f,  24.0f }),
6136         138.0f * CalcInvL2Norm({ 227.0f, 138.0f }),
6137         188.0f * CalcInvL2Norm({ 141.0f, 188.0f }),
6138         162.0f * CalcInvL2Norm({ 147.0f, 162.0f }),
6139          12.0f * CalcInvL2Norm({ 199.0f,  12.0f }),
6140         161.0f * CalcInvL2Norm({ 220.0f, 161.0f })
6141     };
6142
6143     return L2NormalizationTestImpl(workloadFactory, memoryManager, inputOutputShape,
6144                                    inputValues, expectedOutputValues, layout);
6145 }
6146
6147 LayerTestResult<float, 4> L2Normalization4dTest(
6148     armnn::IWorkloadFactory& workloadFactory,
6149     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
6150     const armnn::DataLayout layout)
6151 {
6152         // Width: 3
6153     // Height: 4
6154     // Channels: 3
6155     // BatchSize: 2
6156     unsigned int numberOfBatches = 2;
6157     unsigned int numberOfChannels = 3;
6158     unsigned int height = 4;
6159     unsigned int width = 3;
6160
6161     const armnn::TensorShape inputOutputShape = armnnUtils::GetTensorShape(
6162             numberOfBatches, numberOfChannels, height, width, layout);
6163     std::vector<float> inputValues
6164     {
6165         // Batch 0, Channel 0, Height (4) x Width (3)
6166         235.0f,  46.0f, 178.0f,
6167         100.0f, 123.0f,  19.0f,
6168         172.0f,  74.0f, 250.0f,
6169           6.0f, 195.0f,  80.0f,
6170
6171         // Batch 0, Channel 1, Height (4) x Width (3)
6172         113.0f,  95.0f, 202.0f,
6173          77.0f, 114.0f,  71.0f,
6174         122.0f, 246.0f, 166.0f,
6175          82.0f,  28.0f,  37.0f,
6176
6177         // Batch 0, Channel 2, Height (4) x Width (3)
6178          56.0f, 170.0f, 162.0f,
6179         194.0f,  89.0f, 254.0f,
6180          12.0f, 209.0f, 200.0f,
6181           1.0f,  64.0f,  54.0f,
6182
6183         // Batch 1, Channel 0, Height (4) x Width (3)
6184          67.0f,  90.0f,  49.0f,
6185           7.0f, 163.0f,  18.0f,
6186          25.0f, 117.0f, 103.0f,
6187         247.0f,  59.0f, 189.0f,
6188
6189         // Batch 1, Channel 1, Height (4) x Width (3)
6190         239.0f, 104.0f, 199.0f,
6191          17.0f, 124.0f, 153.0f,
6192         222.0f, 217.0f, 75.0f,
6193          32.0f, 126.0f, 21.0f,
6194
6195         // Batch 1, Channel 2, Height (4) x Width (3)
6196          97.0f, 145.0f, 215.0f,
6197         115.0f, 116.0f, 238.0f,
6198         226.0f,  16.0f, 132.0f,
6199          92.0f, 125.0f,  88.0f
6200     };
6201     std::vector<float> expectedOutputValues
6202     {
6203         // Batch 0, Channel 0, Height (4) x Width (3)
6204         235.0f * CalcInvL2Norm({ 235.0f, 113.0f,  56.0f }),
6205          46.0f * CalcInvL2Norm({  46.0f,  95.0f, 170.0f }),
6206         178.0f * CalcInvL2Norm({ 178.0f, 202.0F, 162.0f }),
6207         100.0f * CalcInvL2Norm({ 100.0f,  77.0f, 194.0f }),
6208         123.0f * CalcInvL2Norm({ 123.0f, 114.0f,  89.0f }),
6209          19.0f * CalcInvL2Norm({  19.0f,  71.0f, 254.0f }),
6210         172.0f * CalcInvL2Norm({ 172.0f, 122.0f,  12.0f }),
6211          74.0f * CalcInvL2Norm({  74.0f, 246.0f, 209.0f }),
6212         250.0f * CalcInvL2Norm({ 250.0f, 166.0f, 200.0f }),
6213           6.0f * CalcInvL2Norm({   6.0f,  82.0f,   1.0f }),
6214         195.0f * CalcInvL2Norm({ 195.0f,  28.0f,  64.0f }),
6215          80.0f * CalcInvL2Norm({  80.0f,  37.0f,  54.0f }),
6216
6217         // Batch 0, Channel 1, Height (4) x Width (3)
6218         113.0f * CalcInvL2Norm({ 235.0f, 113.0f,  56.0f }),
6219          95.0f * CalcInvL2Norm({  46.0f,  95.0f, 170.0f }),
6220         202.0f * CalcInvL2Norm({ 178.0f, 202.0F, 162.0f }),
6221          77.0f * CalcInvL2Norm({ 100.0f,  77.0f, 194.0f }),
6222         114.0f * CalcInvL2Norm({ 123.0f, 114.0f,  89.0f }),
6223          71.0f * CalcInvL2Norm({  19.0f,  71.0f, 254.0f }),
6224         122.0f * CalcInvL2Norm({ 172.0f, 122.0f,  12.0f }),
6225         246.0f * CalcInvL2Norm({  74.0f, 246.0f, 209.0f }),
6226         166.0f * CalcInvL2Norm({ 250.0f, 166.0f, 200.0f }),
6227          82.0f * CalcInvL2Norm({   6.0f,  82.0f,   1.0f }),
6228          28.0f * CalcInvL2Norm({ 195.0f,  28.0f,  64.0f }),
6229          37.0f * CalcInvL2Norm({  80.0f,  37.0f,  54.0f }),
6230
6231         // Batch 0, Channel 2, Height (4) x Width (3)
6232          56.0f * CalcInvL2Norm({ 235.0f, 113.0f,  56.0f }),
6233         170.0f * CalcInvL2Norm({  46.0f,  95.0f, 170.0f }),
6234         162.0f * CalcInvL2Norm({ 178.0f, 202.0F, 162.0f }),
6235         194.0f * CalcInvL2Norm({ 100.0f,  77.0f, 194.0f }),
6236          89.0f * CalcInvL2Norm({ 123.0f, 114.0f,  89.0f }),
6237         254.0f * CalcInvL2Norm({  19.0f,  71.0f, 254.0f }),
6238          12.0f * CalcInvL2Norm({ 172.0f, 122.0f,  12.0f }),
6239         209.0f * CalcInvL2Norm({  74.0f, 246.0f, 209.0f }),
6240         200.0f * CalcInvL2Norm({ 250.0f, 166.0f, 200.0f }),
6241           1.0f * CalcInvL2Norm({   6.0f,  82.0f,   1.0f }),
6242          64.0f * CalcInvL2Norm({ 195.0f,  28.0f,  64.0f }),
6243          54.0f * CalcInvL2Norm({  80.0f,  37.0f,  54.0f }),
6244
6245         // Batch 1, Channel 0, Height (4) x Width (3)
6246          67.0f * CalcInvL2Norm({  67.0f, 239.0f,  97.0f }),
6247          90.0f * CalcInvL2Norm({  90.0f, 104.0f, 145.0f }),
6248          49.0f * CalcInvL2Norm({  49.0f, 199.0f, 215.0f }),
6249           7.0f * CalcInvL2Norm({   7.0f,  17.0f, 115.0f }),
6250         163.0f * CalcInvL2Norm({ 163.0f, 124.0f, 116.0f }),
6251          18.0f * CalcInvL2Norm({  18.0f, 153.0f, 238.0f }),
6252          25.0f * CalcInvL2Norm({  25.0f, 222.0f, 226.0f }),
6253         117.0f * CalcInvL2Norm({ 117.0f, 217.0f,  16.0f }),
6254         103.0f * CalcInvL2Norm({ 103.0f,  75.0f, 132.0f }),
6255         247.0f * CalcInvL2Norm({ 247.0f,  32.0f,  92.0f }),
6256          59.0f * CalcInvL2Norm({  59.0f, 126.0f, 125.0f }),
6257         189.0f * CalcInvL2Norm({ 189.0f,  21.0f,  88.0f }),
6258
6259         // Batch 1, Channel 1, Height (4) x Width (3)
6260         239.0f * CalcInvL2Norm({  67.0f, 239.0f,  97.0f }),
6261         104.0f * CalcInvL2Norm({  90.0f, 104.0f, 145.0f }),
6262         199.0f * CalcInvL2Norm({  49.0f, 199.0f, 215.0f }),
6263          17.0f * CalcInvL2Norm({   7.0f,  17.0f, 115.0f }),
6264         124.0f * CalcInvL2Norm({ 163.0f, 124.0f, 116.0f }),
6265         153.0f * CalcInvL2Norm({  18.0f, 153.0f, 238.0f }),
6266         222.0f * CalcInvL2Norm({  25.0f, 222.0f, 226.0f }),
6267         217.0f * CalcInvL2Norm({ 117.0f, 217.0f,  16.0f }),
6268          75.0f * CalcInvL2Norm({ 103.0f,  75.0f, 132.0f }),
6269          32.0f * CalcInvL2Norm({ 247.0f,  32.0f,  92.0f }),
6270         126.0f * CalcInvL2Norm({  59.0f, 126.0f, 125.0f }),
6271          21.0f * CalcInvL2Norm({ 189.0f,  21.0f,  88.0f }),
6272
6273         // Batch 1, Channel 2, Height (4) x Width (3)
6274          97.0f * CalcInvL2Norm({  67.0f, 239.0f,  97.0f }),
6275         145.0f * CalcInvL2Norm({  90.0f, 104.0f, 145.0f }),
6276         215.0f * CalcInvL2Norm({  49.0f, 199.0f, 215.0f }),
6277         115.0f * CalcInvL2Norm({   7.0f,  17.0f, 115.0f }),
6278         116.0f * CalcInvL2Norm({ 163.0f, 124.0f, 116.0f }),
6279         238.0f * CalcInvL2Norm({  18.0f, 153.0f, 238.0f }),
6280         226.0f * CalcInvL2Norm({  25.0f, 222.0f, 226.0f }),
6281          16.0f * CalcInvL2Norm({ 117.0f, 217.0f,  16.0f }),
6282         132.0f * CalcInvL2Norm({ 103.0f,  75.0f, 132.0f }),
6283          92.0f * CalcInvL2Norm({ 247.0f,  32.0f,  92.0f }),
6284         125.0f * CalcInvL2Norm({  59.0f, 126.0f, 125.0f }),
6285          88.0f * CalcInvL2Norm({ 189.0f,  21.0f,  88.0f })
6286     };
6287
6288     return L2NormalizationTestImpl(workloadFactory, memoryManager, inputOutputShape,
6289                                    inputValues, expectedOutputValues, layout);
6290 }
6291
6292 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
6293 LayerTestResult<T, 4> ConstantTestImpl(
6294     armnn::IWorkloadFactory& workloadFactory,
6295     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
6296     float qScale,
6297     int32_t qOffset)
6298 {
6299     constexpr unsigned int inputWidth = 3;
6300     constexpr unsigned int inputHeight = 4;
6301     constexpr unsigned int inputChannels = 3;
6302     constexpr unsigned int inputBatchSize = 2;
6303
6304     constexpr unsigned int outputWidth = inputWidth;
6305     constexpr unsigned int outputHeight = inputHeight;
6306     constexpr unsigned int outputChannels = inputChannels;
6307     constexpr unsigned int outputBatchSize = inputBatchSize;
6308
6309     armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth }, ArmnnType);
6310
6311     armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth }, ArmnnType);
6312
6313     // Set quantization parameters if the requested type is a quantized type.
6314     if(armnn::IsQuantizedType<T>())
6315     {
6316         inputTensorInfo.SetQuantizationScale(qScale);
6317         inputTensorInfo.SetQuantizationOffset(qOffset);
6318         outputTensorInfo.SetQuantizationScale(qScale);
6319         outputTensorInfo.SetQuantizationOffset(qOffset);
6320     }
6321
6322     auto input = MakeTensor<T, 4>(inputTensorInfo, std::vector<T>(
6323         QuantizedVector<T>(qScale, qOffset, {
6324         // Batch 0, Channel 0
6325         235.0f,  46.0f, 178.0f,
6326         100.0f, 123.0f,  19.0f,
6327         172.0f,  74.0f, 250.0f,
6328           6.0f, 195.0f,  80.0f,
6329
6330         // Batch 0, Channel 1
6331         113.0f,  95.0f, 202.0f,
6332          77.0f, 114.0f,  71.0f,
6333         122.0f, 246.0f, 166.0f,
6334          82.0f,  28.0f,  37.0f,
6335
6336         // Batch 0, Channel 2
6337          56.0f, 170.0f, 162.0f,
6338         194.0f,  89.0f, 254.0f,
6339          12.0f, 209.0f, 200.0f,
6340           1.0f,  64.0f,  54.0f,
6341
6342         // Batch 1, Channel 0
6343          67.0f,  90.0f,  49.0f,
6344           7.0f, 163.0f,  18.0f,
6345          25.0f, 117.0f, 103.0f,
6346         247.0f,  59.0f, 189.0f,
6347
6348         // Batch 1, Channel 1
6349         239.0f, 104.0f, 199.0f,
6350          17.0f, 124.0f, 153.0f,
6351         222.0f, 217.0f, 75.0f,
6352          32.0f, 126.0f, 21.0f,
6353
6354         // Batch 1, Channel 2
6355          97.0f, 145.0f, 215.0f,
6356         115.0f, 116.0f, 238.0f,
6357         226.0f,  16.0f, 132.0f,
6358          92.0f, 125.0f,  88.0f,
6359     })));
6360
6361     LayerTestResult<T, 4> result(outputTensorInfo);
6362     result.outputExpected = input;
6363
6364     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
6365
6366     armnn::ScopedCpuTensorHandle constantTensor(inputTensorInfo);
6367     AllocateAndCopyDataToITensorHandle(&constantTensor, &input[0][0][0][0]);
6368
6369     armnn::ConstantQueueDescriptor descriptor;
6370     descriptor.m_LayerOutput = &constantTensor;
6371
6372     armnn::WorkloadInfo info;
6373     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
6374
6375     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateConstant(descriptor, info);
6376
6377     outputHandle->Allocate();
6378
6379     workload->PostAllocationConfigure();
6380     workload->Execute();
6381
6382     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
6383     return result;
6384 }
6385
6386 LayerTestResult<float, 4> ConstantTest(
6387     armnn::IWorkloadFactory& workloadFactory,
6388     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
6389 {
6390     return ConstantTestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
6391 }
6392
6393 LayerTestResult<uint8_t, 4> ConstantTestUint8(
6394     armnn::IWorkloadFactory& workloadFactory,
6395     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
6396 {
6397     return ConstantTestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 1.0f, 0);
6398 }
6399
6400 LayerTestResult<uint8_t, 3> MergerUint8DifferentQParamsTest(
6401         armnn::IWorkloadFactory& workloadFactory,
6402         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
6403 {
6404     unsigned int outputWidth = 3;
6405     unsigned int outputHeight = 6;
6406     unsigned int outputChannels = 3;
6407
6408     unsigned int inputWidth1 = 3;
6409     unsigned int inputHeight1 = 6;
6410     unsigned int inputChannels1 = 2;
6411
6412     unsigned int inputWidth2 = 3;
6413     unsigned int inputHeight2 = 6;
6414     unsigned int inputChannels2 = 1;
6415
6416     // Defines the tensor descriptors.
6417     armnn::TensorInfo outputTensorInfo({ outputChannels, outputHeight, outputWidth }, armnn::DataType::QuantisedAsymm8);
6418     armnn::TensorInfo inputTensorInfo1({ inputChannels1, inputHeight1, inputWidth1 }, armnn::DataType::QuantisedAsymm8);
6419     armnn::TensorInfo inputTensorInfo2({ inputChannels2, inputHeight2, inputWidth2 }, armnn::DataType::QuantisedAsymm8);
6420
6421     // Quantized input1 tensor. Range [-3, 1]
6422     const float inputScale1 = 0.015686f;
6423     const int32_t inputOffset1 = 192;
6424
6425     auto input1 = MakeTensor<uint8_t, 3>(inputTensorInfo1, std::vector<uint8_t>(
6426     {
6427         1, 2, 3,
6428         4, 5, 6,
6429         7, 8, 9,
6430         10, 11, 12,
6431         13, 14, 15,
6432         16, 17, 18,
6433
6434         19, 20, 21,
6435         22, 23, 24,
6436         25, 26, 27,
6437         28, 29, 30,
6438         31, 32, 33,
6439         34, 35, 36,
6440     })
6441     );
6442
6443     // Quatized input2 tensor. Range [-1, 4]
6444     const float inputScale2 = 0.019608f;
6445     const int32_t inputOffset2 = 50;
6446
6447     auto input2 = MakeTensor<uint8_t, 3>(inputTensorInfo2, std::vector<uint8_t>(
6448     {
6449         37, 38, 39,
6450         40, 41, 42,
6451         43, 44, 45,
6452         46, 47, 48,
6453         49, 50, 51,
6454         52, 53, 54,
6455     })
6456     );
6457
6458     // Output has the same quantization parameters than input1,
6459     // so that only the requantization of input2 is required
6460     const float outputScale = 0.015686f;
6461     const int32_t outputOffset = 192;
6462
6463     LayerTestResult<uint8_t, 3> ret(outputTensorInfo);
6464
6465     ret.outputExpected = MakeTensor<uint8_t, 3>(outputTensorInfo, std::vector<uint8_t>(
6466     {
6467         1, 2, 3,
6468         4, 5, 6,
6469         7, 8, 9,
6470         10, 11, 12,
6471         13, 14, 15,
6472         16, 17, 18,
6473
6474         19, 20, 21,
6475         22, 23, 24,
6476         25, 26, 27,
6477         28, 29, 30,
6478         31, 32, 33,
6479         34, 35, 36,
6480
6481         176, 177, 178,
6482         179, 181, 182,
6483         183, 184, 186,
6484         187, 188, 189,
6485         191, 192, 193,
6486         195, 196, 197,
6487     })
6488     );
6489
6490     outputTensorInfo.SetQuantizationScale(outputScale);
6491     outputTensorInfo.SetQuantizationOffset(outputOffset);
6492     inputTensorInfo1.SetQuantizationScale(inputScale1);
6493     inputTensorInfo1.SetQuantizationOffset(inputOffset1);
6494     inputTensorInfo2.SetQuantizationScale(inputScale2);
6495     inputTensorInfo2.SetQuantizationOffset(inputOffset2);
6496
6497     std::vector<unsigned int> wOrigin1 = { 0, 0, 0 }; //Extent of the window is defined by size of input[0].
6498     armnn::MergerQueueDescriptor::ViewOrigin window1(wOrigin1);
6499
6500     std::vector<unsigned int> wOrigin2 = { 2, 0, 0 }; //Extent of the window is defined by size of input[1].
6501     armnn::MergerQueueDescriptor::ViewOrigin window2(wOrigin2);
6502
6503     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
6504
6505     bool subTensorsSupported = workloadFactory.SupportsSubTensors();
6506
6507     std::unique_ptr<armnn::ITensorHandle> inputHandle1 =
6508             subTensorsSupported ?
6509             workloadFactory.CreateSubTensorHandle(*outputHandle, inputTensorInfo1.GetShape(), wOrigin1.data()) :
6510             workloadFactory.CreateTensorHandle(inputTensorInfo1);
6511
6512     std::unique_ptr<armnn::ITensorHandle> inputHandle2 =
6513             subTensorsSupported ?
6514             workloadFactory.CreateSubTensorHandle(*outputHandle, inputTensorInfo2.GetShape(), wOrigin2.data()) :
6515             workloadFactory.CreateTensorHandle(inputTensorInfo2);
6516
6517     armnn::MergerQueueDescriptor data;
6518     armnn::WorkloadInfo info;
6519     AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get());
6520     AddInputToWorkload(data, info, inputTensorInfo2, inputHandle2.get());
6521     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
6522
6523     data.m_ViewOrigins.push_back(window1);
6524     data.m_ViewOrigins.push_back(window2);
6525
6526     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateMerger(data, info);
6527
6528     inputHandle1->Allocate();
6529     inputHandle2->Allocate();
6530     outputHandle->Allocate();
6531
6532     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0]);
6533     CopyDataToITensorHandle(inputHandle2.get(), &input2[0][0][0]);
6534
6535     workload->PostAllocationConfigure();
6536     workload->Execute();
6537
6538     CopyDataFromITensorHandle(&ret.output[0][0][0], outputHandle.get());
6539
6540     return ret;
6541 }
6542
6543 LayerTestResult<uint8_t, 3> MergerUint8Test(
6544     armnn::IWorkloadFactory& workloadFactory,
6545     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
6546 {
6547     unsigned int outputWidth = 3;
6548     unsigned int outputHeight = 6;
6549     unsigned int outputChannels = 3;
6550
6551     unsigned int inputWidth1 = 3;
6552     unsigned int inputHeight1 = 6;
6553     unsigned int inputChannels1 = 2;
6554
6555     unsigned int inputWidth2 = 3;
6556     unsigned int inputHeight2 = 6;
6557     unsigned int inputChannels2 = 1;
6558
6559     // Defines the tensor descriptors.
6560     armnn::TensorInfo outputTensorInfo({ outputChannels, outputHeight, outputWidth }, armnn::DataType::QuantisedAsymm8);
6561     armnn::TensorInfo inputTensorInfo1({ inputChannels1, inputHeight1, inputWidth1 }, armnn::DataType::QuantisedAsymm8);
6562     armnn::TensorInfo inputTensorInfo2({ inputChannels2, inputHeight2, inputWidth2 }, armnn::DataType::QuantisedAsymm8);
6563
6564     // Arbitrary scale and offsets. They don't really matter as the merger operator doesn't dequantize/quantize them.
6565     const float scale = 0.13497836f;
6566     const int32_t offset = -7;
6567
6568     outputTensorInfo.SetQuantizationScale(scale);
6569     outputTensorInfo.SetQuantizationOffset(offset);
6570     inputTensorInfo1.SetQuantizationScale(scale);
6571     inputTensorInfo1.SetQuantizationOffset(offset);
6572     inputTensorInfo2.SetQuantizationScale(scale);
6573     inputTensorInfo2.SetQuantizationOffset(offset);
6574
6575     LayerTestResult<uint8_t, 3> ret(outputTensorInfo);
6576
6577     ret.outputExpected = MakeTensor<uint8_t, 3>(outputTensorInfo, std::vector<uint8_t>(
6578         {
6579             1, 2, 3,
6580             4, 5, 6,
6581             7, 8, 9,
6582             10, 11, 12,
6583             13, 14, 15,
6584             16, 17, 18,
6585
6586             19, 20, 21,
6587             22, 23, 24,
6588             25, 26, 27,
6589             28, 29, 30,
6590             31, 32, 33,
6591             34, 35, 36,
6592
6593             37, 38, 39,
6594             40, 41, 42,
6595             43, 44, 45,
6596             46, 47, 48,
6597             49, 50, 51,
6598             52, 53, 54,
6599         })
6600     );
6601
6602     auto input1 = MakeTensor<uint8_t, 3>(inputTensorInfo1, std::vector<uint8_t>(
6603     {
6604         1, 2, 3,
6605         4, 5, 6,
6606         7, 8, 9,
6607         10, 11, 12,
6608         13, 14, 15,
6609         16, 17, 18,
6610
6611         19, 20, 21,
6612         22, 23, 24,
6613         25, 26, 27,
6614         28, 29, 30,
6615         31, 32, 33,
6616         34, 35, 36,
6617     })
6618     );
6619
6620     auto input2 = MakeTensor<uint8_t, 3>(inputTensorInfo2, std::vector<uint8_t>(
6621     {
6622         37, 38, 39,
6623         40, 41, 42,
6624         43, 44, 45,
6625         46, 47, 48,
6626         49, 50, 51,
6627         52, 53, 54,
6628     })
6629     );
6630
6631     std::vector<unsigned int> wOrigin1 = { 0, 0, 0 }; //Extent of the window is defined by size of input[0].
6632     armnn::MergerQueueDescriptor::ViewOrigin window1(wOrigin1);
6633
6634     std::vector<unsigned int> wOrigin2 = { 2, 0, 0 }; //Extent of the window is defined by size of input[1].
6635     armnn::MergerQueueDescriptor::ViewOrigin window2(wOrigin2);
6636
6637
6638     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
6639
6640     bool subTensorsSupported = workloadFactory.SupportsSubTensors();
6641
6642     std::unique_ptr<armnn::ITensorHandle> inputHandle1 =
6643         subTensorsSupported ?
6644             workloadFactory.CreateSubTensorHandle(*outputHandle, inputTensorInfo1.GetShape(), wOrigin1.data()) :
6645             workloadFactory.CreateTensorHandle(inputTensorInfo1);
6646
6647     std::unique_ptr<armnn::ITensorHandle> inputHandle2 =
6648         subTensorsSupported ?
6649             workloadFactory.CreateSubTensorHandle(*outputHandle, inputTensorInfo2.GetShape(), wOrigin2.data()) :
6650             workloadFactory.CreateTensorHandle(inputTensorInfo2);
6651
6652
6653     armnn::MergerQueueDescriptor data;
6654     armnn::WorkloadInfo info;
6655     AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get());
6656     AddInputToWorkload(data, info, inputTensorInfo2, inputHandle2.get());
6657     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
6658
6659     data.m_ViewOrigins.push_back(window1);
6660     data.m_ViewOrigins.push_back(window2);
6661
6662     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateMerger(data, info);
6663
6664     inputHandle1->Allocate();
6665     inputHandle2->Allocate();
6666     outputHandle->Allocate();
6667
6668     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0]);
6669     CopyDataToITensorHandle(inputHandle2.get(), &input2[0][0][0]);
6670
6671     workload->PostAllocationConfigure();
6672     workload->Execute();
6673
6674     CopyDataFromITensorHandle(&ret.output[0][0][0], outputHandle.get());
6675
6676     return ret;
6677 }
6678
6679
6680 namespace
6681 {
6682 template <typename T>
6683 LayerTestResult<T, 4> AdditionQuantizeTestHelper(
6684     armnn::IWorkloadFactory& workloadFactory,
6685     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
6686     const unsigned int shape0[4],
6687     const std::vector<T>& values0,
6688     float scale0,
6689     int32_t offset0,
6690     const unsigned int shape1[4],
6691     const std::vector<T> & values1,
6692     float scale1,
6693     int32_t offset1,
6694     const unsigned int outShape[4],
6695     const std::vector<T> & outValues,
6696     float outScale,
6697     int32_t outOffset)
6698 {
6699     auto dataType = (std::is_same<T, uint8_t>::value ?
6700                      armnn::DataType::QuantisedAsymm8 :
6701                      armnn::DataType::QuantisedSymm16);
6702
6703     armnn::TensorInfo inputTensorInfo0(4, shape0, dataType);
6704     armnn::TensorInfo inputTensorInfo1(4, shape1, dataType);
6705     armnn::TensorInfo outputTensorInfo(4, outShape, dataType);
6706
6707     inputTensorInfo0.SetQuantizationScale(scale0);
6708     inputTensorInfo0.SetQuantizationOffset(offset0);
6709
6710     inputTensorInfo1.SetQuantizationScale(scale1);
6711     inputTensorInfo1.SetQuantizationOffset(offset1);
6712
6713     outputTensorInfo.SetQuantizationScale(outScale);
6714     outputTensorInfo.SetQuantizationOffset(outOffset);
6715
6716     auto input0 = MakeTensor<T, 4>(inputTensorInfo0, values0);
6717     auto input1 = MakeTensor<T, 4>(inputTensorInfo1, values1);
6718
6719     LayerTestResult<T, 4> result(outputTensorInfo);
6720     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, outValues);
6721
6722     std::unique_ptr<armnn::ITensorHandle> inputHandle0 = workloadFactory.CreateTensorHandle(inputTensorInfo0);
6723     std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
6724     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
6725
6726     armnn::AdditionQueueDescriptor data;
6727     armnn::WorkloadInfo info;
6728     AddInputToWorkload(data,  info, inputTensorInfo0, inputHandle0.get());
6729     AddInputToWorkload(data,  info, inputTensorInfo1, inputHandle1.get());
6730     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
6731
6732     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateAddition(data, info);
6733
6734     inputHandle0->Allocate();
6735     inputHandle1->Allocate();
6736     outputHandle->Allocate();
6737
6738     CopyDataToITensorHandle(inputHandle0.get(), &input0[0][0][0][0]);
6739     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
6740
6741     workload->PostAllocationConfigure();
6742     workload->Execute();
6743
6744     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
6745
6746     return result;
6747 }
6748 } // anonymous namespace
6749
6750 LayerTestResult<uint8_t, 4> AdditionUint8Test(
6751     armnn::IWorkloadFactory& workloadFactory,
6752     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
6753 {
6754     const unsigned int shape0[] = { 1, 2, 2, 3 };
6755     const unsigned int shape1[] = { 1, 2, 2, 3 };
6756
6757     std::vector<uint8_t> input0(
6758     {
6759         63,  35,  77,  70,  56, 112, //  420, 224,  518,  469,  371, 763
6760         203,  28, 252, 168, 245,  91  // 1400, 175, 1743, 1155, 1694, 616
6761     });
6762
6763     std::vector<uint8_t> input1(
6764     {
6765         21,   7, 175, 231, 175, 210, // 126,   28, 1204, 1596, 1204, 1449
6766         126, 161,  63,  21, 105, 126  // 861, 1106,  420,  126,  714,  861
6767     });
6768
6769     std::vector<uint8_t> output(
6770     {
6771         81,  39, 249, 255, 228, 255, //  546,  252, 1722, 2065(clamped), 1575, 2212(clamped)
6772         255, 186, 255, 186, 255, 214, // 2261(clamped), 1281, 2163(clamped), 1281, 2408(clamped), 1477
6773     });
6774
6775     return AdditionQuantizeTestHelper(workloadFactory,
6776                                       memoryManager,
6777                                       shape0, input0, 7.0f, 3,
6778                                       shape1, input1, 7.0f, 3,
6779                                       shape0, output, 7.0f, 3);
6780 }
6781
6782 LayerTestResult<int16_t, 4> AdditionInt16Test(
6783     armnn::IWorkloadFactory& workloadFactory,
6784     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
6785 {
6786     const unsigned int shape0[] = { 1, 2, 2, 3 };
6787     const unsigned int shape1[] = { 1, 2, 2, 3 };
6788
6789     std::vector<int16_t> input0(
6790         {
6791             63,  35,  77,  70,  56, 112, //  441, 245,  539,  490,  392, 184
6792             203,  28, 252, 168, 245,  91  // 1421, 196, 1764, 1176, 1715, 637
6793         });
6794
6795     std::vector<int16_t> input1(
6796         {
6797             21,   7, 175, 231, 175, 210, // 126,   28, 1204, 1596, 1204, 1449
6798             126, 161,  63,  21, 105, 126  // 861, 1106,  420,  126,  714,  861
6799         });
6800
6801     std::vector<int16_t> output(
6802         {
6803             84,  42, 252, 301, 231, 322, //  588,  294, 1764, 2107(clamped), 1617, 2254(clamped)
6804             329, 189, 315, 189, 350, 217, // 2303(clamped), 1323, 2205(clamped), 1323, 2450(clamped), 1519
6805         });
6806
6807     return AdditionQuantizeTestHelper(workloadFactory,
6808                                       memoryManager,
6809                                       shape0, input0, 7.0f, 0,
6810                                       shape1, input1, 7.0f, 0,
6811                                       shape0, output, 7.0f, 0);
6812 }
6813
6814 namespace
6815 {
6816 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
6817 LayerTestResult<T, 4> MultiplicationQuantizeTestHelper(
6818     armnn::IWorkloadFactory& workloadFactory,
6819     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
6820     const unsigned int shape0[4],
6821     const std::vector<T> & values0,
6822     float scale0,
6823     int32_t offset0,
6824     const unsigned int shape1[4],
6825     const std::vector<T> & values1,
6826     float scale1,
6827     int32_t offset1,
6828     const unsigned int outShape[4],
6829     const std::vector<T> & outValues,
6830     float outScale,
6831     int32_t outOffset)
6832 {
6833     armnn::TensorInfo inputTensorInfo0(4, shape0, ArmnnType);
6834     armnn::TensorInfo inputTensorInfo1(4, shape1, ArmnnType);
6835     armnn::TensorInfo outputTensorInfo(4, outShape, ArmnnType);
6836
6837     inputTensorInfo0.SetQuantizationScale(scale0);
6838     inputTensorInfo0.SetQuantizationOffset(offset0);
6839
6840     inputTensorInfo1.SetQuantizationScale(scale1);
6841     inputTensorInfo1.SetQuantizationOffset(offset1);
6842
6843     outputTensorInfo.SetQuantizationScale(outScale);
6844     outputTensorInfo.SetQuantizationOffset(outOffset);
6845
6846     auto input0 = MakeTensor<T, 4>(inputTensorInfo0, values0);
6847     auto input1 = MakeTensor<T, 4>(inputTensorInfo1, values1);
6848
6849     LayerTestResult<T, 4> result(outputTensorInfo);
6850     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, outValues);
6851
6852     std::unique_ptr<armnn::ITensorHandle> inputHandle0 = workloadFactory.CreateTensorHandle(inputTensorInfo0);
6853     std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
6854     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
6855
6856     armnn::MultiplicationQueueDescriptor data;
6857     armnn::WorkloadInfo info;
6858     AddInputToWorkload(data,  info, inputTensorInfo0, inputHandle0.get());
6859     AddInputToWorkload(data,  info, inputTensorInfo1, inputHandle1.get());
6860     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
6861
6862     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateMultiplication(data, info);
6863
6864     inputHandle0->Allocate();
6865     inputHandle1->Allocate();
6866     outputHandle->Allocate();
6867
6868     CopyDataToITensorHandle(inputHandle0.get(), &input0[0][0][0][0]);
6869     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
6870
6871     workload->PostAllocationConfigure();
6872     workload->Execute();
6873
6874     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
6875
6876     return result;
6877 }
6878 } // anonymous namespace
6879
6880 LayerTestResult<uint8_t, 4> MultiplicationUint8Test(
6881     armnn::IWorkloadFactory& workloadFactory,
6882     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
6883 {
6884     unsigned int batchSize = 1;
6885     unsigned int channels = 2;
6886     unsigned int height = 2;
6887     unsigned int width = 3;
6888     const unsigned int shape[] = { batchSize, channels, height, width };
6889
6890     // See dequantized values to the right.
6891     std::vector<uint8_t> input0({
6892          62,  37,   3, 172,  13, 111, // 244, 144,   8, 684,  48, 440,
6893         188,  20,  73,  31,  23,  31  // 748,  76, 288, 120,  88, 120
6894     });
6895
6896     // See dequantized values to the right.
6897     std::vector<uint8_t> input1({
6898         126, 240, 252, 183, 121, 247, // 384, 726, 762, 555, 369, 747,
6899          48, 115, 151,  79,  78,  97  // 150, 351, 459, 243, 240, 297
6900     });
6901
6902     // See dequantized values to the right.
6903     std::vector<uint8_t> output(
6904     {
6905          64,  72,   0, 255,   8, 236, //  93696, 104544, 6096(clamped), 379620(clamped), 17712, 328680,
6906          77,  15,  92,  16,  10,  21, // 112200,  26676,        132192,           29160, 21120,  35640
6907     });
6908
6909     // Scale/offset chosen to have output values out of range.
6910     return MultiplicationQuantizeTestHelper<armnn::DataType::QuantisedAsymm8>(workloadFactory,
6911                                                                               memoryManager,
6912                                                                               shape,
6913                                                                               input0,
6914                                                                               4.0f,
6915                                                                               1,
6916                                                                               shape,
6917                                                                               input1,
6918                                                                               3.0f,
6919                                                                               -2,
6920                                                                               shape,
6921                                                                               output,
6922                                                                               1366.255f,
6923                                                                               -5);
6924 }
6925
6926 LayerTestResult<uint8_t, 4> MultiplicationBroadcast1ElementUint8Test(
6927     armnn::IWorkloadFactory& workloadFactory,
6928     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
6929 {
6930     const unsigned int shape0[] = { 1, 2, 2, 3 };
6931     const unsigned int shape1[] = { 1, 1, 1, 1 };
6932
6933     std::vector<uint8_t> input0({
6934         1, 2, 3,    4,  5,  6,
6935         7, 8, 9,   10, 11, 12
6936     });
6937
6938     std::vector<uint8_t> input1({2});
6939
6940     std::vector<uint8_t> output({
6941         2,  4,   6,     8, 10, 12,
6942         14, 16, 18,    20, 22, 24
6943     });
6944
6945     return MultiplicationQuantizeTestHelper<armnn::DataType::QuantisedAsymm8>(workloadFactory,
6946                                                                               memoryManager,
6947                                                                               shape0,
6948                                                                               input0,
6949                                                                               1.0f,
6950                                                                               0,
6951                                                                               shape1,
6952                                                                               input1,
6953                                                                               1.0f,
6954                                                                               0,
6955                                                                               shape0,
6956                                                                               output,
6957                                                                               1.0f,
6958                                                                               0);
6959 }
6960
6961 LayerTestResult<uint8_t, 4> MultiplicationBroadcast1DVectorUint8Test(
6962     armnn::IWorkloadFactory& workloadFactory,
6963     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
6964 {
6965     const unsigned int shape0[] = { 1, 2, 2, 3 };
6966     const unsigned int shape1[] = { 1, 1, 1, 3 };
6967
6968     std::vector<uint8_t> input0({
6969         1, 2, 3,    4,  5,  6,
6970         7, 8, 9,   10, 11, 12
6971     });
6972
6973     std::vector<uint8_t> input1({1, 2, 3});
6974
6975     std::vector<uint8_t> output({
6976         1,  4,   9,     4, 10, 18,
6977         7, 16,  27,    10, 22, 36
6978     });
6979
6980     return MultiplicationQuantizeTestHelper<armnn::DataType::QuantisedAsymm8>(workloadFactory,
6981                                                                               memoryManager,
6982                                                                               shape0,
6983                                                                               input0,
6984                                                                               1.0f,
6985                                                                               0,
6986                                                                               shape1,
6987                                                                               input1,
6988                                                                               1.0f,
6989                                                                               0,
6990                                                                               shape0,
6991                                                                               output,
6992                                                                               1.0f,
6993                                                                               0);
6994 }
6995
6996 LayerTestResult<int16_t, 4> MultiplicationInt16Test(
6997     armnn::IWorkloadFactory& workloadFactory,
6998     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
6999 {
7000     const unsigned int shape[] = { 1, 2, 2, 3 };
7001
7002     std::vector<int16_t> input0(
7003     {
7004         6,   7,  8,  9, 10, 11,
7005         12, 13, 14, 15, 16, 17
7006     });
7007
7008     std::vector<int16_t> input1(
7009     {
7010         1, 2, 3,  4,  5,  6,
7011         7, 8, 9, 10, 11, 12
7012     });
7013
7014     std::vector<int16_t> output(
7015     {
7016         6,   14,  24,  36,  50,  66,
7017         84, 104, 126, 150, 176, 204
7018     });
7019
7020     return MultiplicationQuantizeTestHelper<armnn::DataType::QuantisedSymm16>(workloadFactory,
7021                                                                               memoryManager,
7022                                                                               shape,
7023                                                                               input0,
7024                                                                               1.0f,
7025                                                                               0,
7026                                                                               shape,
7027                                                                               input1,
7028                                                                               1.0f,
7029                                                                               0,
7030                                                                               shape,
7031                                                                               output,
7032                                                                               1.0f,
7033                                                                               0);
7034 }
7035
7036 LayerTestResult<int16_t, 4> MultiplicationBroadcast1ElementInt16Test(
7037     armnn::IWorkloadFactory& workloadFactory,
7038     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7039 {
7040     const unsigned int shape0[] = { 1, 2, 2, 3 };
7041     const unsigned int shape1[] = { 1, 1, 1, 1 };
7042
7043     std::vector<int16_t> input0(
7044     {
7045         1, 2, 3,  4,  5,  6,
7046         7, 8, 9, 10, 11, 12
7047     });
7048
7049     std::vector<int16_t> input1({2});
7050
7051     std::vector<int16_t> output(
7052     {
7053         2,   4,  6,  8, 10, 12,
7054         14, 16, 18, 20, 22, 24
7055     });
7056
7057     return MultiplicationQuantizeTestHelper<armnn::DataType::QuantisedSymm16>(workloadFactory,
7058                                                                               memoryManager,
7059                                                                               shape0,
7060                                                                               input0,
7061                                                                               1.0f,
7062                                                                               0,
7063                                                                               shape1,
7064                                                                               input1,
7065                                                                               1.0f,
7066                                                                               0,
7067                                                                               shape0,
7068                                                                               output,
7069                                                                               1.0f,
7070                                                                               0);
7071 }
7072
7073 LayerTestResult<int16_t, 4> MultiplicationBroadcast1DVectorInt16Test(
7074     armnn::IWorkloadFactory& workloadFactory,
7075     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7076 {
7077     const unsigned int shape0[] = { 1, 2, 2, 3 };
7078     const unsigned int shape1[] = { 1, 1, 1, 3 };
7079
7080     std::vector<int16_t> input0(
7081     {
7082         1, 2, 3,  4,  5,  6,
7083         7, 8, 9, 10, 11, 12
7084     });
7085
7086     std::vector<int16_t> input1({1, 2, 3});
7087
7088     std::vector<int16_t> output(
7089     {
7090         1,  4,  9,  4, 10, 18,
7091         7, 16, 27, 10, 22, 36
7092     });
7093
7094     return MultiplicationQuantizeTestHelper<armnn::DataType::QuantisedSymm16>(workloadFactory,
7095                                                                               memoryManager,
7096                                                                               shape0,
7097                                                                               input0,
7098                                                                               1.0f,
7099                                                                               0,
7100                                                                               shape1,
7101                                                                               input1,
7102                                                                               1.0f,
7103                                                                               0,
7104                                                                               shape0,
7105                                                                               output,
7106                                                                               1.0f,
7107                                                                               0);
7108 }
7109
7110 namespace
7111 {
7112 template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
7113 LayerTestResult<T, 4> SubtractionTestHelper(
7114     armnn::IWorkloadFactory& workloadFactory,
7115     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
7116     const unsigned int shape0[4],
7117     const std::vector<T>& values0,
7118     float scale0,
7119     int32_t offset0,
7120     const unsigned int shape1[4],
7121     const std::vector<T> & values1,
7122     float scale1,
7123     int32_t offset1,
7124     const unsigned int outShape[4],
7125     const std::vector<T> & outValues,
7126     float outScale,
7127     int32_t outOffset)
7128 {
7129     armnn::TensorInfo inputTensorInfo0(4, shape0, ArmnnType);
7130     armnn::TensorInfo inputTensorInfo1(4, shape1, ArmnnType);
7131     armnn::TensorInfo outputTensorInfo(4, outShape, ArmnnType);
7132
7133     inputTensorInfo0.SetQuantizationScale(scale0);
7134     inputTensorInfo0.SetQuantizationOffset(offset0);
7135
7136     inputTensorInfo1.SetQuantizationScale(scale1);
7137     inputTensorInfo1.SetQuantizationOffset(offset1);
7138
7139     outputTensorInfo.SetQuantizationScale(outScale);
7140     outputTensorInfo.SetQuantizationOffset(outOffset);
7141
7142     auto input0 = MakeTensor<T, 4>(inputTensorInfo0, values0);
7143     auto input1 = MakeTensor<T, 4>(inputTensorInfo1, values1);
7144
7145     LayerTestResult<T, 4> result(outputTensorInfo);
7146     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, outValues);
7147
7148     std::unique_ptr<armnn::ITensorHandle> inputHandle0 = workloadFactory.CreateTensorHandle(inputTensorInfo0);
7149     std::unique_ptr<armnn::ITensorHandle> inputHandle1 = workloadFactory.CreateTensorHandle(inputTensorInfo1);
7150     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
7151
7152     armnn::SubtractionQueueDescriptor data;
7153     armnn::WorkloadInfo info;
7154     AddInputToWorkload(data,  info, inputTensorInfo0, inputHandle0.get());
7155     AddInputToWorkload(data,  info, inputTensorInfo1, inputHandle1.get());
7156     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
7157
7158     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateSubtraction(data, info);
7159
7160     inputHandle0->Allocate();
7161     inputHandle1->Allocate();
7162     outputHandle->Allocate();
7163
7164     CopyDataToITensorHandle(inputHandle0.get(), &input0[0][0][0][0]);
7165     CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0][0]);
7166
7167     workload->PostAllocationConfigure();
7168     workload->Execute();
7169
7170     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
7171
7172     return result;
7173 }
7174 } // anonymous namespace
7175
7176 LayerTestResult<uint8_t, 4> SubtractionUint8Test(
7177     armnn::IWorkloadFactory& workloadFactory,
7178     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7179 {
7180     const unsigned int shape0[] = { 1, 1, 2, 2 };
7181     const unsigned int shape1[] = { 1, 1, 2, 2 };
7182
7183     std::vector<uint8_t> input0({ 10, 12, 14, 16 });
7184     std::vector<uint8_t> input1({ 1, 2, 1, 2 });
7185     std::vector<uint8_t> output({ 3, 3, 5, 5 });
7186
7187     return SubtractionTestHelper<armnn::DataType::QuantisedAsymm8>(workloadFactory,
7188                                                                    memoryManager,
7189                                                                    shape0, input0, 0.5f, 2,
7190                                                                    shape1, input1, 1.0f, 0,
7191                                                                    shape0, output, 1.0f, 0);
7192 }
7193
7194 LayerTestResult<uint8_t, 4> SubtractionBroadcast1ElementUint8Test(
7195     armnn::IWorkloadFactory& workloadFactory,
7196     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7197 {
7198     const unsigned int shape0[] = { 1, 1, 2, 2 };
7199     const unsigned int shape1[] = { 1, 1, 1, 1 };
7200
7201     std::vector<uint8_t> input0({ 10, 12, 14, 16 });
7202     std::vector<uint8_t> input1({ 2 });
7203     std::vector<uint8_t> output({ 5, 6, 7, 8 });
7204
7205     return SubtractionTestHelper<armnn::DataType::QuantisedAsymm8>(workloadFactory,
7206                                                                    memoryManager,
7207                                                                    shape0, input0, 0.5f, 2,
7208                                                                    shape1, input1, 1.0f, 0,
7209                                                                    shape0, output, 1.0f, 3);
7210 }
7211
7212 LayerTestResult<uint8_t, 4> SubtractionBroadcastUint8Test(
7213     armnn::IWorkloadFactory& workloadFactory,
7214     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7215 {
7216     const unsigned int shape0[] = { 1, 1, 2, 2 };
7217     const unsigned int shape1[] = { 1, 1, 2, 1 };
7218
7219     std::vector<uint8_t> input0({ 10, 12, 14, 16 });
7220     std::vector<uint8_t> input1({ 2, 1 });
7221     std::vector<uint8_t> output({ 8, 11, 12, 15 });
7222
7223     return SubtractionTestHelper<armnn::DataType::QuantisedAsymm8>(workloadFactory,
7224                                                                    memoryManager,
7225                                                                    shape0, input0, 1.0f, 0,
7226                                                                    shape1, input1, 1.0f, 0,
7227                                                                    shape0, output, 1.0f, 0);
7228 }
7229
7230 LayerTestResult<float, 4> SubtractionTest(
7231     armnn::IWorkloadFactory& workloadFactory,
7232     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7233 {
7234     const unsigned int shape0[] = { 1, 1, 2, 2 };
7235     const unsigned int shape1[] = { 1, 1, 2, 2 };
7236
7237     std::vector<float> input0({ 1,  2, 3, 4 });
7238     std::vector<float> input1({ 1, -1, 0, 2 });
7239     std::vector<float> output({ 0,  3, 3, 2 });
7240
7241     return SubtractionTestHelper<armnn::DataType::Float32>(workloadFactory,
7242                                                            memoryManager,
7243                                                            shape0, input0, 1.0f, 0,
7244                                                            shape1, input1, 1.0f, 0,
7245                                                            shape0, output, 1.0f, 0);
7246 }
7247
7248 LayerTestResult<float, 4> SubtractionBroadcast1ElementTest(
7249     armnn::IWorkloadFactory& workloadFactory,
7250     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7251 {
7252     const unsigned int shape0[] = { 1, 1, 2, 2 };
7253     const unsigned int shape1[] = { 1, 1, 1, 1 };
7254
7255     std::vector<float> input0({ 1,  2, 3, 4 });
7256     std::vector<float> input1({ 10 });
7257     std::vector<float> output({ -9,  -8, -7, -6 });
7258
7259     return SubtractionTestHelper<armnn::DataType::Float32>(workloadFactory,
7260                                                            memoryManager,
7261                                                            shape0, input0, 1.0f, 0,
7262                                                            shape1, input1, 1.0f, 0,
7263                                                            shape0, output, 1.0f, 0);
7264 }
7265
7266 LayerTestResult<float, 4> SubtractionBroadcastTest(
7267     armnn::IWorkloadFactory& workloadFactory,
7268     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7269 {
7270     const unsigned int shape0[] = { 1, 1, 2, 2 };
7271     const unsigned int shape1[] = { 1, 1, 1, 2 };
7272
7273     std::vector<float> input0({ 1,  2, 3, 4 });
7274     std::vector<float> input1({ 10, -5 });
7275     std::vector<float> output({ -9,  7, -7, 9 });
7276
7277     return SubtractionTestHelper<armnn::DataType::Float32>(workloadFactory,
7278                                                            memoryManager,
7279                                                            shape0, input0, 1.0f, 0,
7280                                                            shape1, input1, 1.0f, 0,
7281                                                            shape0, output, 1.0f, 0);
7282 }
7283
7284 LayerTestResult<int16_t, 4> SubtractionInt16Test(
7285     armnn::IWorkloadFactory& workloadFactory,
7286     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7287 {
7288     const unsigned int shape0[] = { 1, 1, 2, 2 };
7289     const unsigned int shape1[] = { 1, 1, 2, 2 };
7290
7291     std::vector<int16_t> input0({ 10, 12, 14, 16 });
7292     std::vector<int16_t> input1({ 1, 2, 1, 2 });
7293     std::vector<int16_t> output({ 3, 3, 5, 5 });
7294
7295     return SubtractionTestHelper<armnn::DataType::QuantisedSymm16>(workloadFactory,
7296                                                                    memoryManager,
7297                                                                    shape0, input0, 0.5f, 0,
7298                                                                    shape1, input1, 1.0f, 0,
7299                                                                    shape0, output, 1.0f, 0);
7300 }
7301
7302 LayerTestResult<int16_t, 4> SubtractionBroadcast1ElementInt16Test(
7303     armnn::IWorkloadFactory& workloadFactory,
7304     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7305 {
7306     const unsigned int shape0[] = { 1, 1, 2, 2 };
7307     const unsigned int shape1[] = { 1, 1, 1, 1 };
7308
7309     std::vector<int16_t> input0({ 10, 12, 14, 16 });
7310     std::vector<int16_t> input1({ 2 });
7311     std::vector<int16_t> output({ 3, 4, 5, 6 });
7312
7313     return SubtractionTestHelper<armnn::DataType::QuantisedSymm16>(workloadFactory,
7314                                                                    memoryManager,
7315                                                                    shape0, input0, 0.5f, 0,
7316                                                                    shape1, input1, 1.0f, 0,
7317                                                                    shape0, output, 1.0f, 0);
7318 }
7319
7320 LayerTestResult<int16_t, 4> SubtractionBroadcastInt16Test(
7321     armnn::IWorkloadFactory& workloadFactory,
7322     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7323 {
7324     const unsigned int shape0[] = { 1, 1, 2, 2 };
7325     const unsigned int shape1[] = { 1, 1, 2, 1 };
7326
7327     std::vector<int16_t> input0({ 10, 12, 14, 16 });
7328     std::vector<int16_t> input1({ 2, 1 });
7329     std::vector<int16_t> output({ 8, 11, 12, 15 });
7330
7331     return SubtractionTestHelper<armnn::DataType::QuantisedSymm16>(workloadFactory,
7332                                                                    memoryManager,
7333                                                                    shape0, input0, 1.0f, 0,
7334                                                                    shape1, input1, 1.0f, 0,
7335                                                                    shape0, output, 1.0f, 0);
7336 }
7337
7338 LayerTestResult<uint8_t, 4> ResizeBilinearNopUint8Test(
7339     armnn::IWorkloadFactory& workloadFactory,
7340     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7341 {
7342     constexpr unsigned int inputWidth = 4;
7343     constexpr unsigned int inputHeight = 4;
7344     constexpr unsigned int inputChannels = 1;
7345     constexpr unsigned int inputBatchSize = 1;
7346
7347     constexpr unsigned int outputWidth = inputWidth;
7348     constexpr unsigned int outputHeight = inputHeight;
7349     constexpr unsigned int outputChannels = inputChannels;
7350     constexpr unsigned int outputBatchSize = inputBatchSize;
7351
7352     armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth },
7353         armnn::DataType::QuantisedAsymm8);
7354     inputTensorInfo.SetQuantizationScale(1.5f);
7355     inputTensorInfo.SetQuantizationOffset(-3);
7356
7357     armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth },
7358         armnn::DataType::QuantisedAsymm8);
7359     outputTensorInfo.SetQuantizationScale(1.5f);
7360     outputTensorInfo.SetQuantizationOffset(-3);
7361
7362     auto input = MakeTensor<uint8_t, 4>(inputTensorInfo, std::vector<uint8_t>({
7363         1, 2, 3, 4,
7364         2, 3, 4, 5,
7365         3, 4, 5, 6,
7366         4, 5, 6, 7
7367     }));
7368
7369     LayerTestResult<uint8_t, 4> result(outputTensorInfo);
7370     result.outputExpected = input;
7371
7372     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
7373     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
7374
7375     armnn::ResizeBilinearQueueDescriptor descriptor;
7376     armnn::WorkloadInfo info;
7377     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
7378     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
7379
7380     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateResizeBilinear(descriptor, info);
7381
7382     inputHandle->Allocate();
7383     outputHandle->Allocate();
7384     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
7385
7386     workload->PostAllocationConfigure();
7387     workload->Execute();
7388
7389     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
7390     return result;
7391 }
7392
7393 LayerTestResult<uint8_t, 4> SimpleResizeBilinearUint8Test(
7394     armnn::IWorkloadFactory& workloadFactory,
7395     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7396 {
7397     constexpr unsigned int inputWidth = 2;
7398     constexpr unsigned int inputHeight = 2;
7399     constexpr unsigned int inputChannels = 1;
7400     constexpr unsigned int inputBatchSize = 1;
7401
7402     constexpr unsigned int outputWidth = inputWidth / 2;
7403     constexpr unsigned int outputHeight = inputHeight / 2;
7404     constexpr unsigned int outputChannels = inputChannels;
7405     constexpr unsigned int outputBatchSize = inputBatchSize;
7406
7407     armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth },
7408         armnn::DataType::QuantisedAsymm8);
7409     inputTensorInfo.SetQuantizationScale(0.1567f);
7410     inputTensorInfo.SetQuantizationOffset(1);
7411
7412     armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth },
7413         armnn::DataType::QuantisedAsymm8);
7414     outputTensorInfo.SetQuantizationScale(0.1567f);
7415     outputTensorInfo.SetQuantizationOffset(1);
7416
7417     auto input = MakeTensor<uint8_t, 4>(inputTensorInfo, std::vector<uint8_t>({
7418         1, 255,
7419         200, 250
7420     }));
7421
7422     // The 'resize bilinear' operation projects the top-left corner of output texels into the input image,
7423     // then figures out the interpolants and weights. Note this is different to projecting the centre of the
7424     // output texel - and thus we'll expect the output 1x1 matrix to contain, as its single element, the value
7425     // that was at position (0,0) of the input matrix (rather than an average, which we would expect if projecting
7426     // the centre).
7427     LayerTestResult<uint8_t, 4> result(outputTensorInfo);
7428     result.outputExpected = MakeTensor<uint8_t, 4>(outputTensorInfo, std::vector<uint8_t>({
7429         1
7430     }));
7431
7432     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
7433     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
7434
7435     armnn::ResizeBilinearQueueDescriptor descriptor;
7436     armnn::WorkloadInfo info;
7437     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
7438     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
7439
7440     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateResizeBilinear(descriptor, info);
7441
7442     inputHandle->Allocate();
7443     outputHandle->Allocate();
7444     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
7445
7446     workload->PostAllocationConfigure();
7447     workload->Execute();
7448
7449     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
7450     return result;
7451 }
7452
7453 LayerTestResult<uint8_t, 4> ResizeBilinearSqMinUint8Test(
7454     armnn::IWorkloadFactory& workloadFactory,
7455     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7456 {
7457     constexpr unsigned int inputWidth = 4;
7458     constexpr unsigned int inputHeight = 4;
7459     constexpr unsigned int inputChannels = 1;
7460     constexpr unsigned int inputBatchSize = 1;
7461
7462     constexpr unsigned int outputWidth = inputWidth / 2;
7463     constexpr unsigned int outputHeight = inputHeight / 2;
7464     constexpr unsigned int outputChannels = inputChannels;
7465     constexpr unsigned int outputBatchSize = inputBatchSize;
7466
7467     armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth },
7468         armnn::DataType::QuantisedAsymm8);
7469     inputTensorInfo.SetQuantizationScale(3.141592f);
7470     inputTensorInfo.SetQuantizationOffset(3);
7471
7472     armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth },
7473         armnn::DataType::QuantisedAsymm8);
7474     outputTensorInfo.SetQuantizationScale(3.141592f);
7475     outputTensorInfo.SetQuantizationOffset(3);
7476
7477     auto input = MakeTensor<uint8_t, 4>(inputTensorInfo, std::vector<uint8_t>({
7478         1, 2, 3, 4,
7479         2, 3, 4, 5,
7480         3, 4, 5, 6,
7481         4, 5, 6, 7
7482     }));
7483
7484     LayerTestResult<uint8_t, 4> result(outputTensorInfo);
7485     result.outputExpected = MakeTensor<uint8_t, 4>(outputTensorInfo, std::vector<uint8_t>({
7486         1, 3,
7487         3, 5
7488     }));
7489
7490     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
7491     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
7492
7493     armnn::ResizeBilinearQueueDescriptor descriptor;
7494     armnn::WorkloadInfo info;
7495     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
7496     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
7497
7498     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateResizeBilinear(descriptor, info);
7499
7500     inputHandle->Allocate();
7501     outputHandle->Allocate();
7502     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
7503
7504     workload->PostAllocationConfigure();
7505     workload->Execute();
7506
7507     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
7508     return result;
7509 }
7510
7511 LayerTestResult<uint8_t, 4> ResizeBilinearMinUint8Test(
7512     armnn::IWorkloadFactory& workloadFactory,
7513     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7514 {
7515     constexpr unsigned int inputWidth = 3;
7516     constexpr unsigned int inputHeight = 2;
7517     constexpr unsigned int inputChannels = 1;
7518     constexpr unsigned int inputBatchSize = 1;
7519
7520     constexpr unsigned int outputWidth = 2;
7521     constexpr unsigned int outputHeight = 1;
7522     constexpr unsigned int outputChannels = inputChannels;
7523     constexpr unsigned int outputBatchSize = inputBatchSize;
7524
7525     armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth },
7526         armnn::DataType::QuantisedAsymm8);
7527     inputTensorInfo.SetQuantizationScale(1.5f);
7528     inputTensorInfo.SetQuantizationOffset(-1);
7529
7530     armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth },
7531         armnn::DataType::QuantisedAsymm8);
7532     outputTensorInfo.SetQuantizationScale(1.5f);
7533     outputTensorInfo.SetQuantizationOffset(-1);
7534
7535     auto input = MakeTensor<uint8_t, 4>(inputTensorInfo, std::vector<uint8_t>({
7536         1,  2,  3, // 3.0, 4.5, 6.0
7537         5,  8, 13  // 9.0, 13.5, 21.0
7538     }));
7539
7540     LayerTestResult<uint8_t, 4> result(outputTensorInfo);
7541     result.outputExpected = MakeTensor<uint8_t, 4>(outputTensorInfo, std::vector<uint8_t>({
7542         1, 3 // 3.0, 5.25
7543     }));
7544
7545     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
7546     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
7547
7548     armnn::ResizeBilinearQueueDescriptor descriptor;
7549     armnn::WorkloadInfo info;
7550     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
7551     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
7552
7553     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateResizeBilinear(descriptor, info);
7554
7555     inputHandle->Allocate();
7556     outputHandle->Allocate();
7557
7558     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
7559
7560     workload->PostAllocationConfigure();
7561     workload->Execute();
7562
7563     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
7564     return result;
7565 }
7566
7567 LayerTestResult<uint8_t, 4> ResizeBilinearMagUint8Test(
7568     armnn::IWorkloadFactory& workloadFactory,
7569     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7570 {
7571     constexpr unsigned int inputWidth = 2;
7572     constexpr unsigned int inputHeight = 3;
7573     constexpr unsigned int inputChannels = 1;
7574     constexpr unsigned int inputBatchSize = 1;
7575
7576     constexpr unsigned int outputWidth = 5;
7577     constexpr unsigned int outputHeight = 3;
7578     constexpr unsigned int outputChannels = inputChannels;
7579     constexpr unsigned int outputBatchSize = inputBatchSize;
7580
7581     armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth },
7582         armnn::DataType::QuantisedAsymm8);
7583     inputTensorInfo.SetQuantizationScale(0.010765f);
7584     inputTensorInfo.SetQuantizationOffset(7);
7585
7586     armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth },
7587         armnn::DataType::QuantisedAsymm8);
7588     outputTensorInfo.SetQuantizationScale(0.010132f);
7589     outputTensorInfo.SetQuantizationOffset(-18);
7590
7591     auto input = MakeTensor<uint8_t, 4>(inputTensorInfo, std::vector<uint8_t>({
7592          24, 228, // 0.183005, 2.379065,
7593         105, 128, // 1.05497, 1.302565
7594         230,  71  // 2.400595, 0.68896
7595     }));
7596
7597     LayerTestResult<uint8_t, 4> result(outputTensorInfo);
7598     result.outputExpected = MakeTensor<uint8_t, 4>(outputTensorInfo, std::vector<uint8_t>({
7599           0,  87, 173, 217, 217, // 0.18300501, 1.06142902, 1.93985295, 2.37906504, 2.37906504
7600          86,  96, 106, 111, 111, // 1.05497003, 1.15400803, 1.25304604, 1.30256498, 1.30256498
7601         219, 151,  84,  50,  50  // 2.40059495, 1.71594095, 1.03128707, 0.68896002, 0.68896002
7602     }));
7603
7604     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
7605     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
7606
7607     armnn::ResizeBilinearQueueDescriptor descriptor;
7608     armnn::WorkloadInfo info;
7609     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
7610     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
7611
7612     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateResizeBilinear(descriptor, info);
7613
7614     inputHandle->Allocate();
7615     outputHandle->Allocate();
7616     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
7617
7618     workload->PostAllocationConfigure();
7619     workload->Execute();
7620
7621     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
7622     return result;
7623 }
7624
7625 LayerTestResult<float, 2> Rsqrt2dTestCommon(
7626     armnn::IWorkloadFactory& workloadFactory,
7627     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
7628     const armnn::TensorInfo inputTensorInfo,
7629     const armnn::TensorInfo outputTensorInfo,
7630     std::vector<float> inputValues,
7631     std::vector<float> expectedOutputValues)
7632 {
7633     auto inputTensor = MakeTensor<float, 2>(inputTensorInfo, std::vector<float>(inputValues));
7634
7635     LayerTestResult<float, 2> result(outputTensorInfo);
7636     result.outputExpected = MakeTensor<float, 2>(outputTensorInfo, std::vector<float>(expectedOutputValues));
7637
7638     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
7639     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
7640
7641     armnn::RsqrtQueueDescriptor descriptor;
7642
7643     armnn::WorkloadInfo info;
7644
7645     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
7646     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
7647
7648     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateRsqrt(descriptor, info);
7649
7650     inputHandle->Allocate();
7651     outputHandle->Allocate();
7652
7653     CopyDataToITensorHandle(inputHandle.get(), &inputTensor[0][0]);
7654
7655     workload->PostAllocationConfigure();
7656     workload->Execute();
7657
7658     CopyDataFromITensorHandle(&result.output[0][0], outputHandle.get());
7659
7660     return result;
7661 }
7662 LayerTestResult<float, 2> Rsqrt2dTest(
7663     armnn::IWorkloadFactory& workloadFactory,
7664     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7665 {
7666     const armnn::TensorShape inputShape{ 2, 2 };
7667     const armnn::TensorShape outputShape{ 2, 2 };
7668
7669     const armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32);
7670     const armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32);
7671
7672     std::vector<float> inputValues
7673             {
7674                     1.f, 4.f,
7675                     16.f, 25.f
7676             };
7677
7678     std::vector<float> expectedOutputValues
7679             {
7680                     1.f, 0.5f,
7681                     0.25f, 0.2f
7682             };
7683
7684     return Rsqrt2dTestCommon(workloadFactory, memoryManager,
7685                              inputTensorInfo, outputTensorInfo,
7686                              inputValues, expectedOutputValues);
7687 }
7688
7689 LayerTestResult<float, 3> Rsqrt3dTest(
7690     armnn::IWorkloadFactory& workloadFactory,
7691     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7692 {
7693     const armnn::TensorShape inputShape{ 3, 1, 2 };
7694     const armnn::TensorShape outputShape{ 3, 1, 2 };
7695
7696     const armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32);
7697     const armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32);
7698
7699     std::vector<float> inputValues
7700             {
7701                     1.f, 4.f, 16.f,
7702                     25.f, 64.f, 100.f
7703             };
7704
7705     std::vector<float> expectedOutputValues
7706             {
7707                     1.f, 0.5f, 0.25f,
7708                     0.2f, 0.125f, 0.1f
7709             };
7710
7711     auto inputTensor = MakeTensor<float, 3>(inputTensorInfo, std::vector<float>(inputValues));
7712
7713     LayerTestResult<float, 3> result(outputTensorInfo);
7714     result.outputExpected = MakeTensor<float, 3>(outputTensorInfo, std::vector<float >(expectedOutputValues));
7715
7716     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
7717     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
7718
7719     armnn::RsqrtQueueDescriptor descriptor;
7720
7721     armnn::WorkloadInfo info;
7722
7723     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
7724     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
7725
7726     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateRsqrt(descriptor, info);
7727
7728     inputHandle->Allocate();
7729     outputHandle->Allocate();
7730
7731     CopyDataToITensorHandle(inputHandle.get(), &inputTensor[0][0][0]);
7732
7733     workload->PostAllocationConfigure();
7734     workload->Execute();
7735
7736     CopyDataFromITensorHandle(&result.output[0][0][0], outputHandle.get());
7737
7738     return result;
7739 }
7740
7741 LayerTestResult<float, 2> RsqrtZeroTest(
7742     armnn::IWorkloadFactory& workloadFactory,
7743     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7744 {
7745     const armnn::TensorShape inputShape{ 1, 2 };
7746     const armnn::TensorShape outputShape{ 1, 2 };
7747
7748     const armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32);
7749     const armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32);
7750
7751     std::vector<float> inputValues
7752             {
7753                     0.f, -0.f
7754             };
7755
7756     std::vector<float> expectedOutputValues
7757             {
7758                     INFINITY, -INFINITY
7759             };
7760
7761     return Rsqrt2dTestCommon(workloadFactory, memoryManager,
7762                              inputTensorInfo, outputTensorInfo,
7763                              inputValues, expectedOutputValues);
7764 }
7765
7766 LayerTestResult<float, 2> RsqrtNegativeTest(
7767     armnn::IWorkloadFactory& workloadFactory,
7768     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7769 {
7770     const armnn::TensorShape inputShape{ 1, 2 };
7771     const armnn::TensorShape outputShape{ 1, 2 };
7772
7773     const armnn::TensorInfo inputTensorInfo(inputShape, armnn::DataType::Float32);
7774     const armnn::TensorInfo outputTensorInfo(outputShape, armnn::DataType::Float32);
7775
7776     std::vector<float> inputValues
7777             {
7778                     -25.f, -16.f
7779             };
7780
7781     std::vector<float> expectedOutputValues
7782             {
7783                     -NAN, -NAN
7784             };
7785
7786     return Rsqrt2dTestCommon(workloadFactory, memoryManager,
7787                              inputTensorInfo, outputTensorInfo,
7788                              inputValues, expectedOutputValues);
7789 }
7790
7791 LayerTestResult<float, 4> BatchNormTest(
7792     armnn::IWorkloadFactory& workloadFactory,
7793     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7794 {
7795     // BatchSize: 1
7796     // Channels: 2
7797     // Height: 3
7798     // Width: 2
7799
7800     const armnn::TensorShape inputOutputShape{ 1, 2, 3, 2 };
7801     std::vector<float> inputValues
7802     {
7803         // Batch 0, Channel 0, Height (3) x Width (2)
7804          1.f, 4.f,
7805          4.f, 2.f,
7806          1.f, 6.f,
7807
7808         // Batch 0, Channel 1, Height (3) x Width (2)
7809          1.f, 1.f,
7810          4.f, 1.f,
7811         -2.f, 4.f
7812     };
7813     std::vector<float> expectedOutputValues
7814     {
7815         // Batch 0, Channel 0, Height (3) x Width (2)
7816         1.f, 4.f,
7817         4.f, 2.f,
7818         1.f, 6.f,
7819
7820         // Batch 0, Channel 1, Height (3) x Width (2)
7821         3.f, 3.f,
7822         4.f, 3.f,
7823         2.f, 4.f
7824     };
7825
7826     return BatchNormTestImpl<armnn::DataType::Float32>(
7827         workloadFactory, memoryManager,
7828         inputOutputShape, inputValues, expectedOutputValues,
7829         0.f, 0, armnn::DataLayout::NCHW);
7830 }
7831
7832 LayerTestResult<float, 4> BatchNormNhwcTest(
7833     armnn::IWorkloadFactory& workloadFactory,
7834     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7835 {
7836     // BatchSize: 1
7837     // Height: 3
7838     // Width: 2
7839     // Channels: 2
7840
7841     const armnn::TensorShape inputOutputShape{ 1, 3, 2, 2 };
7842     std::vector<float> inputValues
7843     {
7844         // Batch 0, Height 0, Width (2) x Channel (2)
7845         1.f,  1.f,
7846         4.f,  1.f,
7847
7848         // Batch 0, Height 1, Width (2) x Channel (2)
7849         4.f,  4.f,
7850         2.f,  1.f,
7851
7852         // Batch 0, Height 2, Width (2) x Channel (2)
7853         1.f, -2.f,
7854         6.f,  4.f
7855     };
7856     std::vector<float> expectedOutputValues
7857     {
7858         // Batch 0, Height 0, Width (2) x Channel (2)
7859         1.f, 3.f,
7860         4.f, 3.f,
7861
7862         // Batch 0, Height 1, Width (2) x Channel (2)
7863         4.f, 4.f,
7864         2.f, 3.f,
7865
7866         // Batch 0, Height 2, Width (2) x Channel (2)
7867         1.f, 2.f,
7868         6.f, 4.f
7869     };
7870
7871     return BatchNormTestImpl<armnn::DataType::Float32>(
7872         workloadFactory, memoryManager,
7873         inputOutputShape, inputValues, expectedOutputValues,
7874         0.f, 0, armnn::DataLayout::NHWC);
7875 }
7876
7877 LayerTestResult<uint8_t, 4> BatchNormUint8Test(
7878     armnn::IWorkloadFactory& workloadFactory,
7879     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7880 {
7881     // BatchSize: 1
7882     // Channels: 2
7883     // Height: 3
7884     // Width: 2
7885
7886     const armnn::TensorShape inputOutputShape{ 1, 2, 3, 2 };
7887     std::vector<float> inputValues
7888     {
7889         // Batch 0, Channel 0, Height (3) x Width (2)
7890          1.f, 4.f,
7891          4.f, 2.f,
7892          1.f, 6.f,
7893
7894         // Batch 0, Channel 1, Height (3) x Width (2)
7895          1.f, 1.f,
7896          4.f, 1.f,
7897         -2.f, 4.f
7898     };
7899     std::vector<float> expectedOutputValues
7900     {
7901         // Batch 0, Channel 0, Height (3) x Width (2)
7902         1.f, 4.f,
7903         4.f, 2.f,
7904         1.f, 6.f,
7905
7906         // Batch 0, Channel 1, Height (3) x Width (2)
7907         3.f, 3.f,
7908         4.f, 3.f,
7909         2.f, 4.f
7910     };
7911
7912     return BatchNormTestImpl<armnn::DataType::QuantisedAsymm8>(
7913         workloadFactory, memoryManager,
7914         inputOutputShape, inputValues, expectedOutputValues,
7915         1.f/20.f, 50, armnn::DataLayout::NCHW);
7916 }
7917
7918 LayerTestResult<uint8_t, 4> BatchNormUint8NhwcTest(
7919     armnn::IWorkloadFactory& workloadFactory,
7920     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7921 {
7922     // BatchSize: 1
7923     // Height: 3
7924     // Width: 2
7925     // Channels: 2
7926
7927     const armnn::TensorShape inputOutputShape{ 1, 3, 2, 2 };
7928     std::vector<float> inputValues
7929     {
7930         // Batch 0, Height 0, Width (2) x Channel (2)
7931         1.f,  1.f,
7932         4.f,  1.f,
7933
7934         // Batch 0, Height 1, Width (2) x Channel (2)
7935         4.f,  4.f,
7936         2.f,  1.f,
7937
7938         // Batch 0, Height 2, Width (2) x Channel (2)
7939         1.f, -2.f,
7940         6.f,  4.f
7941     };
7942     std::vector<float> expectedOutputValues
7943     {
7944         // Batch 0, Height 0, Width (2) x Channel (2)
7945         1.f, 3.f,
7946         4.f, 3.f,
7947
7948         // Batch 0, Height 1, Width (2) x Channel (2)
7949         4.f, 4.f,
7950         2.f, 3.f,
7951
7952         // Batch 0, Height 2, Width (2) x Channel (2)
7953         1.f, 2.f,
7954         6.f, 4.f
7955     };
7956
7957     return BatchNormTestImpl<armnn::DataType::QuantisedAsymm8>
7958         (workloadFactory, memoryManager,
7959          inputOutputShape, inputValues, expectedOutputValues,
7960          1.f/20.f, 50, armnn::DataLayout::NHWC);
7961 }
7962
7963 LayerTestResult<uint8_t, 4> ConstantUint8Test(
7964     armnn::IWorkloadFactory& workloadFactory,
7965     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7966 {
7967     return ConstantTestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 2e-6f, 1);
7968 }
7969
7970 LayerTestResult<uint8_t, 1> Concatenation1dUint8Test(
7971     armnn::IWorkloadFactory& workloadFactory,
7972     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7973 {
7974     return Concatenation1dTestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 0.5f, -1);
7975 }
7976
7977 LayerTestResult<uint8_t, 2> Concatenation2dDim0Uint8Test(
7978     armnn::IWorkloadFactory& workloadFactory,
7979     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7980 {
7981     return Concatenation2dDim0TestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 0.5f, -1);
7982 }
7983
7984 LayerTestResult<uint8_t, 2> Concatenation2dDim1Uint8Test(
7985     armnn::IWorkloadFactory& workloadFactory,
7986     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7987 {
7988     return Concatenation2dDim1TestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 0.5f, -1);
7989 }
7990
7991 LayerTestResult<uint8_t, 2> Concatenation2dDim0DiffInputDimsUint8Test(
7992     armnn::IWorkloadFactory& workloadFactory,
7993     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
7994 {
7995     return Concatenation2dDim0DiffInputDimsTestImpl<armnn::DataType::QuantisedAsymm8>(
7996         workloadFactory, memoryManager, 0.5f, -1);
7997 }
7998
7999 LayerTestResult<uint8_t, 2> Concatenation2dDim1DiffInputDimsUint8Test(
8000     armnn::IWorkloadFactory& workloadFactory,
8001     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8002 {
8003     return Concatenation2dDim1DiffInputDimsTestImpl<armnn::DataType::QuantisedAsymm8>(
8004         workloadFactory, memoryManager, 0.5f, -1);
8005 }
8006
8007 LayerTestResult<uint8_t, 3> Concatenation3dDim0Uint8Test(
8008     armnn::IWorkloadFactory& workloadFactory,
8009     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8010 {
8011     return Concatenation3dDim0TestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 0.5f, -1);
8012 }
8013
8014 LayerTestResult<uint8_t, 3> Concatenation3dDim1Uint8Test(
8015     armnn::IWorkloadFactory& workloadFactory,
8016     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8017 {
8018     return Concatenation3dDim1TestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 0.5f, -1);
8019 }
8020
8021 LayerTestResult<uint8_t, 3> Concatenation3dDim2Uint8Test(
8022     armnn::IWorkloadFactory& workloadFactory,
8023     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8024     bool useSubtensor)
8025 {
8026     return Concatenation3dDim2TestImpl<armnn::DataType::QuantisedAsymm8>(
8027         workloadFactory, memoryManager, useSubtensor, 0.5f, -1);
8028 }
8029
8030 LayerTestResult<uint8_t, 3> Concatenation3dDim0DiffInputDimsUint8Test(
8031     armnn::IWorkloadFactory& workloadFactory,
8032     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8033 {
8034     return Concatenation3dDim0TestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 0.5f, -1);
8035 }
8036
8037 LayerTestResult<uint8_t, 3> Concatenation3dDim1DiffInputDimsUint8Test(
8038     armnn::IWorkloadFactory& workloadFactory,
8039     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8040 {
8041     return Concatenation3dDim1DiffInputDimsTestImpl<armnn::DataType::QuantisedAsymm8>(
8042         workloadFactory, memoryManager, 0.5f, -1);
8043 }
8044
8045 LayerTestResult<uint8_t, 3> Concatenation3dDim2DiffInputDimsUint8Test(
8046     armnn::IWorkloadFactory& workloadFactory,
8047     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8048     bool useSubtensor)
8049 {
8050     return Concatenation3dDim2DiffInputDimsTestImpl<armnn::DataType::QuantisedAsymm8>(
8051         workloadFactory, memoryManager, useSubtensor, 0.5f, -1);
8052 }
8053
8054 LayerTestResult<uint8_t, 4> Concatenation4dDim0Uint8Test(
8055     armnn::IWorkloadFactory& workloadFactory,
8056     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8057 {
8058     return Concatenation4dDim0TestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 0.5f, -1);
8059 }
8060
8061 LayerTestResult<uint8_t, 4> Concatenation4dDim1Uint8Test(
8062     armnn::IWorkloadFactory& workloadFactory,
8063     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8064 {
8065     return Concatenation4dDim1TestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 0.5f, -1);
8066 }
8067
8068 LayerTestResult<uint8_t, 4> Concatenation4dDim2Uint8Test(
8069     armnn::IWorkloadFactory& workloadFactory,
8070     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8071 {
8072     return Concatenation4dDim2TestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 0.5f, -1);
8073 }
8074
8075 LayerTestResult<uint8_t, 4> Concatenation4dDim3Uint8Test(
8076     armnn::IWorkloadFactory& workloadFactory,
8077     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, bool useSubtensor)
8078 {
8079     return Concatenation4dDim3TestImpl<armnn::DataType::QuantisedAsymm8>(
8080         workloadFactory, memoryManager, 0.5f, -1, useSubtensor);
8081 }
8082
8083 LayerTestResult<uint8_t, 4> Concatenation4dDiffShapeDim0Uint8Test(
8084     armnn::IWorkloadFactory& workloadFactory,
8085     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8086 {
8087     return Concatenation4dDiffShapeDim0TestImpl<armnn::DataType::QuantisedAsymm8>(
8088         workloadFactory, memoryManager, 0.5f, -1);
8089 }
8090
8091 LayerTestResult<uint8_t, 4> Concatenation4dDiffShapeDim1Uint8Test(
8092     armnn::IWorkloadFactory& workloadFactory,
8093     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8094 {
8095     return Concatenation4dDiffShapeDim1TestImpl<armnn::DataType::QuantisedAsymm8>(
8096         workloadFactory, memoryManager, 0.5f, -1);
8097 }
8098
8099 LayerTestResult<uint8_t, 4> Concatenation4dDiffShapeDim2Uint8Test(
8100     armnn::IWorkloadFactory& workloadFactory,
8101     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8102 {
8103     return Concatenation4dDiffShapeDim2TestImpl<armnn::DataType::QuantisedAsymm8>(
8104         workloadFactory, memoryManager, 0.5f, -1);
8105 }
8106
8107 LayerTestResult<uint8_t, 4> Concatenation4dDiffShapeDim3Uint8Test(
8108     armnn::IWorkloadFactory& workloadFactory,
8109     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8110     bool useSubtensor)
8111 {
8112     return Concatenation4dDiffShapeDim3TestImpl<armnn::DataType::QuantisedAsymm8>(
8113         workloadFactory, memoryManager, 0.5f, -1, useSubtensor);
8114 }
8115
8116 LayerTestResult<float, 4> SimpleMaxPooling2dSize2x2Stride2x2Test(
8117     armnn::IWorkloadFactory& workloadFactory,
8118     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8119     bool forceNoPadding)
8120 {
8121     return SimpleMaxPooling2dSize2x2Stride2x2TestCommon<armnn::DataType::Float32>(
8122         workloadFactory, memoryManager, forceNoPadding);
8123 }
8124
8125 LayerTestResult<uint8_t, 4> SimpleMaxPooling2dSize2x2Stride2x2Uint8Test(
8126     armnn::IWorkloadFactory& workloadFactory,
8127     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8128     bool forceNoPadding)
8129 {
8130     return SimpleMaxPooling2dSize2x2Stride2x2TestCommon<armnn::DataType::QuantisedAsymm8>(
8131         workloadFactory, memoryManager, forceNoPadding, 3.0f, -5);
8132 }
8133
8134 LayerTestResult<float, 4> SimpleMaxPooling2dSize3x3Stride2x4Test(
8135     armnn::IWorkloadFactory& workloadFactory,
8136     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8137     bool forceNoPadding)
8138 {
8139     return SimpleMaxPooling2dSize3x3Stride2x4TestCommon<armnn::DataType::Float32>(
8140         workloadFactory, memoryManager, forceNoPadding);
8141 }
8142
8143 LayerTestResult<uint8_t, 4> SimpleMaxPooling2dSize3x3Stride2x4Uint8Test(
8144     armnn::IWorkloadFactory& workloadFactory,
8145     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8146     bool forceNoPadding)
8147 {
8148     return SimpleMaxPooling2dSize3x3Stride2x4TestCommon<armnn::DataType::QuantisedAsymm8>(
8149         workloadFactory, memoryManager, forceNoPadding, 0.1f, 128);
8150 }
8151
8152 LayerTestResult<float, 4> SimpleMaxPooling2dTest(
8153     armnn::IWorkloadFactory& workloadFactory,
8154     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8155     const armnn::DataLayout dataLayout)
8156 {
8157     return SimpleMaxPooling2dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, dataLayout);
8158 }
8159
8160 LayerTestResult<uint8_t, 4> SimpleMaxPooling2dUint8Test(
8161     armnn::IWorkloadFactory& workloadFactory,
8162     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8163     const armnn::DataLayout dataLayout)
8164 {
8165     return SimpleMaxPooling2dTestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, dataLayout);
8166 }
8167
8168 LayerTestResult<float, 4> SimpleAveragePooling2dTest(
8169     armnn::IWorkloadFactory& workloadFactory,
8170     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8171     const armnn::DataLayout dataLayout)
8172 {
8173     return SimpleAveragePooling2dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, dataLayout);
8174 }
8175
8176 LayerTestResult<uint8_t, 4> SimpleAveragePooling2dUint8Test(
8177     armnn::IWorkloadFactory& workloadFactory,
8178     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8179     const armnn::DataLayout dataLayout)
8180 {
8181     return SimpleAveragePooling2dTestCommon<armnn::DataType::QuantisedAsymm8>(
8182         workloadFactory, memoryManager, dataLayout, 0.5, -1);
8183 }
8184
8185 LayerTestResult<float, 4> IgnorePaddingAveragePooling2dSize3x2Stride2x2Test(
8186     armnn::IWorkloadFactory& workloadFactory,
8187     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8188     bool forceNoPadding)
8189 {
8190     return IgnorePaddingAveragePooling2dSize3x2Stride2x2TestCommon<armnn::DataType::Float32>(
8191         workloadFactory, memoryManager, forceNoPadding);
8192 }
8193
8194 LayerTestResult<float, 4> LargeTensorsAveragePooling2dTest(
8195     armnn::IWorkloadFactory& workloadFactory,
8196     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8197 {
8198     return LargeTensorsAveragePooling2dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8199 }
8200
8201 LayerTestResult<uint8_t, 4> LargeTensorsAveragePooling2dUint8Test(
8202     armnn::IWorkloadFactory& workloadFactory,
8203     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8204 {
8205     return LargeTensorsAveragePooling2dTestCommon<armnn::DataType::QuantisedAsymm8>(
8206         workloadFactory, memoryManager, 0.5, -1);
8207 }
8208
8209 LayerTestResult<float, 4> SimpleL2Pooling2dTest(
8210     armnn::IWorkloadFactory& workloadFactory,
8211     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8212     const armnn::DataLayout dataLayout)
8213 {
8214     return SimpleL2Pooling2dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, dataLayout);
8215 }
8216
8217 LayerTestResult<uint8_t, 4> SimpleL2Pooling2dUint8Test(
8218     armnn::IWorkloadFactory& workloadFactory,
8219     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8220     const armnn::DataLayout dataLayout)
8221 {
8222     return SimpleL2Pooling2dTestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, dataLayout);
8223 }
8224
8225 LayerTestResult<float, 4> L2Pooling2dSize3Stride1Test(
8226     armnn::IWorkloadFactory& workloadFactory,
8227     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8228 {
8229     return L2Pooling2dSize3Stride1TestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8230 }
8231
8232 LayerTestResult<uint8_t, 4> L2Pooling2dSize3Stride1Uint8Test(
8233     armnn::IWorkloadFactory& workloadFactory,
8234     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8235 {
8236     return L2Pooling2dSize3Stride1TestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8237 }
8238
8239 LayerTestResult<float, 4> L2Pooling2dSize3Stride3Test(
8240     armnn::IWorkloadFactory& workloadFactory,
8241     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8242 {
8243     return L2Pooling2dSize3Stride3TestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8244 }
8245
8246 LayerTestResult<uint8_t, 4> L2Pooling2dSize3Stride3Uint8Test(
8247     armnn::IWorkloadFactory& workloadFactory,
8248     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8249 {
8250     return L2Pooling2dSize3Stride3TestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8251 }
8252
8253 LayerTestResult<float, 4> L2Pooling2dSize3Stride4Test(
8254     armnn::IWorkloadFactory& workloadFactory,
8255     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8256 {
8257     return L2Pooling2dSize3Stride4TestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8258 }
8259
8260 LayerTestResult<uint8_t, 4> L2Pooling2dSize3Stride4Uint8Test(
8261     armnn::IWorkloadFactory& workloadFactory,
8262     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8263 {
8264     return L2Pooling2dSize3Stride4TestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8265 }
8266
8267 LayerTestResult<float, 4> L2Pooling2dSize7Test(
8268     armnn::IWorkloadFactory& workloadFactory,
8269     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8270 {
8271     return L2Pooling2dSize7TestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8272 }
8273
8274 LayerTestResult<uint8_t, 4> L2Pooling2dSize7Uint8Test(
8275     armnn::IWorkloadFactory& workloadFactory,
8276     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8277 {
8278     return L2Pooling2dSize7TestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8279 }
8280
8281 LayerTestResult<float, 4> L2Pooling2dSize9Test(
8282     armnn::IWorkloadFactory& workloadFactory,
8283     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8284 {
8285     return L2Pooling2dSize9TestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8286 }
8287
8288 LayerTestResult<uint8_t, 4> L2Pooling2dSize9Uint8Test(
8289     armnn::IWorkloadFactory& workloadFactory,
8290     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8291 {
8292     return L2Pooling2dSize9TestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8293 }
8294
8295 LayerTestResult<float, 4> AsymmetricNonSquarePooling2dTest(
8296     armnn::IWorkloadFactory& workloadFactory,
8297     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8298 {
8299     return AsymmetricNonSquarePooling2dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8300 }
8301
8302 LayerTestResult<uint8_t, 4> AsymmetricNonSquarePooling2dUint8Test(
8303     armnn::IWorkloadFactory& workloadFactory,
8304     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8305 {
8306     return AsymmetricNonSquarePooling2dTestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8307 }
8308
8309 LayerTestResult<float, 4> ComparePooling2dTest(
8310     armnn::IWorkloadFactory& workloadFactory,
8311     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8312     armnn::IWorkloadFactory& refWorkloadFactory,
8313     armnn::PoolingAlgorithm  poolingType)
8314 {
8315     return ComparePooling2dTestCommon<armnn::DataType::Float32>(
8316         workloadFactory, memoryManager, refWorkloadFactory, poolingType);
8317 }
8318
8319 LayerTestResult<uint8_t, 4> ComparePooling2dUint8Test(
8320     armnn::IWorkloadFactory& workloadFactory,
8321     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8322     armnn::IWorkloadFactory& refWorkloadFactory,
8323     armnn::PoolingAlgorithm  poolingType)
8324 {
8325     return ComparePooling2dTestCommon<armnn::DataType::QuantisedAsymm8>(
8326         workloadFactory, memoryManager, refWorkloadFactory, poolingType, 0.1f, 128);
8327 }
8328
8329 LayerTestResult<float, 2> FullyConnectedLargeTest(
8330     armnn::IWorkloadFactory& workloadFactory,
8331     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8332     bool transposeWeights)
8333 {
8334     return FullyConnectedLargeTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, transposeWeights);
8335 }
8336
8337 LayerTestResult<float, 4> IgnorePaddingSimpleMaxPooling2dTest(
8338     armnn::IWorkloadFactory& workloadFactory,
8339     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8340 {
8341     return IgnorePaddingSimpleMaxPooling2dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8342 }
8343
8344 LayerTestResult<uint8_t, 4> IgnorePaddingSimpleMaxPooling2dUint8Test(
8345     armnn::IWorkloadFactory& workloadFactory,
8346     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8347 {
8348     return IgnorePaddingSimpleMaxPooling2dTestCommon<armnn::DataType::QuantisedAsymm8>(
8349         workloadFactory, memoryManager, 1.0f, -5);
8350 }
8351
8352 LayerTestResult<float, 4> IgnorePaddingMaxPooling2dSize3Test(
8353     armnn::IWorkloadFactory& workloadFactory,
8354     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8355 {
8356     return IgnorePaddingMaxPooling2dSize3TestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8357 }
8358
8359 LayerTestResult<uint8_t, 4> IgnorePaddingMaxPooling2dSize3Uint8Test(
8360     armnn::IWorkloadFactory& workloadFactory,
8361     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8362 {
8363     return IgnorePaddingMaxPooling2dSize3TestCommon<armnn::DataType::QuantisedAsymm8>(
8364         workloadFactory, memoryManager, 1.0f, -5);
8365 }
8366
8367 LayerTestResult<float, 4> IgnorePaddingSimpleAveragePooling2dTest(
8368     armnn::IWorkloadFactory& workloadFactory,
8369     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8370 {
8371     return IgnorePaddingSimpleAveragePooling2dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8372 }
8373
8374 LayerTestResult<uint8_t, 4> IgnorePaddingSimpleAveragePooling2dUint8Test(
8375     armnn::IWorkloadFactory& workloadFactory,
8376     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8377 {
8378     return IgnorePaddingSimpleAveragePooling2dTestCommon<armnn::DataType::QuantisedAsymm8>(
8379         workloadFactory, memoryManager);
8380 }
8381
8382 LayerTestResult<float, 4> IgnorePaddingSimpleAveragePooling2dNoPaddingTest(
8383     armnn::IWorkloadFactory& workloadFactory,
8384     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8385 {
8386     return IgnorePaddingSimpleAveragePooling2dNoPaddingTestCommon<armnn::DataType::Float32>(
8387         workloadFactory, memoryManager);
8388 }
8389
8390 LayerTestResult<uint8_t, 4> IgnorePaddingSimpleAveragePooling2dNoPaddingUint8Test(
8391     armnn::IWorkloadFactory& workloadFactory,
8392     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8393 {
8394     return IgnorePaddingSimpleAveragePooling2dNoPaddingTestCommon<armnn::DataType::QuantisedAsymm8>(
8395         workloadFactory, memoryManager);
8396 }
8397
8398 LayerTestResult<float, 4> IgnorePaddingAveragePooling2dSize3Test(
8399     armnn::IWorkloadFactory& workloadFactory,
8400     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8401 {
8402     return IgnorePaddingAveragePooling2dSize3TestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8403 }
8404
8405 LayerTestResult<uint8_t, 4> IgnorePaddingAveragePooling2dSize3Uint8Test(
8406     armnn::IWorkloadFactory& workloadFactory,
8407     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8408 {
8409     return IgnorePaddingAveragePooling2dSize3TestCommon<armnn::DataType::QuantisedAsymm8>(
8410         workloadFactory, memoryManager);
8411 }
8412
8413 LayerTestResult<float, 4> IgnorePaddingSimpleL2Pooling2dTest(
8414     armnn::IWorkloadFactory& workloadFactory,
8415     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8416 {
8417     return IgnorePaddingSimpleL2Pooling2dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8418 }
8419
8420 LayerTestResult<uint8_t, 4> IgnorePaddingSimpleL2Pooling2dUint8Test(
8421     armnn::IWorkloadFactory& workloadFactory,
8422     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8423 {
8424     return IgnorePaddingSimpleL2Pooling2dTestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8425 }
8426
8427 LayerTestResult<float, 4> IgnorePaddingL2Pooling2dSize3Test(
8428     armnn::IWorkloadFactory& workloadFactory,
8429     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8430 {
8431     return IgnorePaddingL2Pooling2dSize3TestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
8432 }
8433
8434 LayerTestResult<uint8_t, 4> IgnorePaddingL2Pooling2dSize3Uint8Test(
8435     armnn::IWorkloadFactory& workloadFactory,
8436     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8437 {
8438     return IgnorePaddingL2Pooling2dSize3TestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8439 }
8440
8441 LayerTestResult<float, 4> SimplePermuteFloat32Test(
8442     armnn::IWorkloadFactory& workloadFactory,
8443     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8444 {
8445     return SimplePermuteFloat32TestCommon(workloadFactory, memoryManager);
8446 };
8447
8448 LayerTestResult<uint8_t, 4> SimplePermuteUint8Test(
8449     armnn::IWorkloadFactory& workloadFactory,
8450     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8451 {
8452     return SimplePermuteUint8TestCommon(workloadFactory, memoryManager);
8453 };
8454
8455 LayerTestResult<float, 4> PermuteFloat32ValueSet1Test(
8456     armnn::IWorkloadFactory& workloadFactory,
8457     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8458 {
8459     return PermuteFloat32ValueSet1TestCommon(workloadFactory, memoryManager);
8460 };
8461
8462 LayerTestResult<float, 4> PermuteFloat32ValueSet2Test(
8463     armnn::IWorkloadFactory& workloadFactory,
8464     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8465 {
8466     return PermuteFloat32ValueSet2TestCommon(workloadFactory, memoryManager);
8467 };
8468
8469 LayerTestResult<float, 4> PermuteFloat32ValueSet3Test(
8470     armnn::IWorkloadFactory& workloadFactory,
8471     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8472 {
8473     return PermuteFloat32ValueSet3TestCommon(workloadFactory, memoryManager);
8474 };
8475
8476 namespace
8477 {
8478
8479 template <typename T, std::size_t InputDim, std::size_t OutputDim>
8480 LayerTestResult<T, OutputDim> MeanTestHelper(
8481     armnn::IWorkloadFactory& workloadFactory,
8482     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8483     const unsigned int* inputShape,
8484     const std::vector<T>& inputData,
8485     const std::vector<unsigned int>& axis,
8486     bool keepDims,
8487     const unsigned int* outputShape,
8488     const std::vector<T>& outputData,
8489     float scale = 1.0f,
8490     int32_t offset = 0)
8491 {
8492     auto dataType = (std::is_same<T, uint8_t>::value ? armnn::DataType::QuantisedAsymm8 : armnn::DataType::Float32);
8493
8494     armnn::TensorInfo inputTensorInfo(InputDim, inputShape, dataType);
8495     armnn::TensorInfo outputTensorInfo(OutputDim, outputShape, dataType);
8496
8497     inputTensorInfo.SetQuantizationScale(scale);
8498     inputTensorInfo.SetQuantizationOffset(offset);
8499
8500     outputTensorInfo.SetQuantizationScale(scale);
8501     outputTensorInfo.SetQuantizationOffset(offset);
8502
8503     auto input = MakeTensor<T, InputDim>(inputTensorInfo, inputData);
8504
8505     LayerTestResult<T, OutputDim> result(outputTensorInfo);
8506     result.outputExpected = MakeTensor<T, OutputDim>(outputTensorInfo, outputData);
8507
8508     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
8509     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
8510
8511     armnn::MeanQueueDescriptor data;
8512     data.m_Parameters.m_Axis = axis;
8513     data.m_Parameters.m_KeepDims = keepDims;
8514     armnn::WorkloadInfo info;
8515     AddInputToWorkload(data,  info, inputTensorInfo, inputHandle.get());
8516     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
8517
8518     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateMean(data, info);
8519
8520     inputHandle->Allocate();
8521     outputHandle->Allocate();
8522
8523     CopyDataToITensorHandle(inputHandle.get(), input.origin());
8524
8525     workload->PostAllocationConfigure();
8526     workload->Execute();
8527
8528     CopyDataFromITensorHandle(result.output.origin(), outputHandle.get());
8529
8530     return result;
8531 }
8532
8533 } // anonymous namespace
8534
8535 LayerTestResult<uint8_t, 1> MeanUint8SimpleTest(
8536     armnn::IWorkloadFactory& workloadFactory,
8537     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8538 {
8539     const unsigned int inputShape[] = { 3, 2 };
8540     const unsigned int outputShape[] = { 1 };
8541
8542     std::vector<uint8_t> input({ 1, 1, 2, 2, 3, 3 });
8543     std::vector<uint8_t> output({ 2 });
8544
8545     return MeanTestHelper<uint8_t, 2, 1>(
8546         workloadFactory, memoryManager, inputShape, input, {}, false, outputShape, output);
8547 }
8548
8549 LayerTestResult<uint8_t, 3> MeanUint8SimpleAxisTest(
8550     armnn::IWorkloadFactory& workloadFactory,
8551     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8552 {
8553     const unsigned int inputShape[] = { 1, 1, 3, 2 };
8554     const unsigned int outputShape[] = { 1, 1, 2 };
8555
8556     std::vector<uint8_t> input({ 1, 1, 2, 2, 3, 3 });
8557     std::vector<uint8_t> output({ 2, 2 });
8558
8559     return MeanTestHelper<uint8_t, 4, 3>(
8560         workloadFactory, memoryManager, inputShape, input, { 2 }, false, outputShape, output);
8561 }
8562
8563 LayerTestResult<uint8_t, 4> MeanUint8KeepDimsTest(
8564     armnn::IWorkloadFactory& workloadFactory,
8565     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8566 {
8567     const unsigned int inputShape[] = { 1, 1, 3, 2 };
8568     const unsigned int outputShape[] = { 1, 1, 1, 2 };
8569
8570     std::vector<uint8_t> input({ 1, 1, 2, 2, 3, 3 });
8571     std::vector<uint8_t> output({ 2, 2 });
8572
8573     return MeanTestHelper<uint8_t, 4, 4>(
8574         workloadFactory, memoryManager, inputShape, input, { 2 }, true, outputShape, output);
8575 }
8576
8577 LayerTestResult<uint8_t, 4> MeanUint8MultipleDimsTest(
8578     armnn::IWorkloadFactory& workloadFactory,
8579     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8580 {
8581     const unsigned int inputShape[] = { 2, 3, 1, 2 };
8582     const unsigned int outputShape[] = { 1, 3, 1, 1 };
8583
8584     std::vector<uint8_t> input({ 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6 });
8585     std::vector<uint8_t> output({ 1, 3, 5 });
8586
8587     return MeanTestHelper<uint8_t, 4, 4>(
8588         workloadFactory, memoryManager, inputShape, input, { 0, 3 }, true, outputShape, output);
8589 }
8590
8591 LayerTestResult<uint8_t, 1> MeanVtsUint8Test(
8592     armnn::IWorkloadFactory& workloadFactory,
8593     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8594 {
8595     const unsigned int inputShape[] = { 4, 3, 2 };
8596     const unsigned int outputShape[] = { 2 };
8597
8598     std::vector<uint8_t> input({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
8599                                  24 });
8600     std::vector<uint8_t> output({ 12, 13 });
8601
8602     return MeanTestHelper<uint8_t, 3, 1>(workloadFactory, memoryManager,
8603                                          inputShape, input, { 0, 1 }, false, outputShape,
8604                                          output, 0.8f, 5);
8605 }
8606
8607 LayerTestResult<float, 1> MeanFloatSimpleTest(
8608     armnn::IWorkloadFactory& workloadFactory,
8609     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8610 {
8611     const unsigned int inputShape[] = { 3, 2 };
8612     const unsigned int outputShape[] = { 1 };
8613
8614     std::vector<float> input({ 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f });
8615     std::vector<float> output({ 2.0f });
8616
8617     return MeanTestHelper<float, 2, 1>(
8618         workloadFactory, memoryManager, inputShape, input, {}, false, outputShape, output);
8619 }
8620
8621 LayerTestResult<float, 3> MeanFloatSimpleAxisTest(
8622     armnn::IWorkloadFactory& workloadFactory,
8623     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8624 {
8625     const unsigned int inputShape[] = { 2, 3, 1, 2 };
8626     const unsigned int outputShape[] = { 3, 1, 2 };
8627
8628     std::vector<float> input({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f });
8629     std::vector<float> output({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f });
8630
8631     return MeanTestHelper<float, 4, 3>(
8632         workloadFactory, memoryManager, inputShape, input, { 0 }, false, outputShape, output);
8633 }
8634
8635 LayerTestResult<float, 4> MeanFloatKeepDimsTest(
8636     armnn::IWorkloadFactory& workloadFactory,
8637     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8638 {
8639     const unsigned int inputShape[] = { 1, 1, 3, 2 };
8640     const unsigned int outputShape[] = { 1, 1, 1, 2 };
8641
8642     std::vector<float> input({ 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f });
8643     std::vector<float> output({ 2.0f, 2.0f });
8644
8645     return MeanTestHelper<float, 4, 4>(
8646         workloadFactory, memoryManager, inputShape, input, { 2 }, true, outputShape, output);
8647 }
8648
8649 LayerTestResult<float, 4> MeanFloatMultipleDimsTest(
8650     armnn::IWorkloadFactory& workloadFactory,
8651     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8652 {
8653     const unsigned int inputShape[] = { 2, 3, 1, 2 };
8654     const unsigned int outputShape[] = { 1, 3, 1, 1 };
8655
8656     std::vector<float> input({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f });
8657     std::vector<float> output({ 1.5f, 3.5f, 5.5f });
8658
8659     return MeanTestHelper<float, 4, 4>(
8660         workloadFactory, memoryManager, inputShape, input, { 0, 3 }, true, outputShape, output);
8661 }
8662
8663 LayerTestResult<float, 1> MeanVtsFloat1Test(
8664     armnn::IWorkloadFactory& workloadFactory,
8665     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8666 {
8667     const unsigned int inputShape[] = { 4, 3, 2 };
8668     const unsigned int outputShape[] = { 2 };
8669
8670     std::vector<float> input({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f,
8671                                15.0f, 16.0f, 17.0f, 18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f, 24.0f });
8672     std::vector<float> output({ 12.0f, 13.0f });
8673
8674     return MeanTestHelper<float, 3, 1>(
8675         workloadFactory, memoryManager, inputShape, input, { 0, 1 }, false, outputShape, output);
8676 }
8677
8678 LayerTestResult<float, 3> MeanVtsFloat2Test(
8679     armnn::IWorkloadFactory& workloadFactory,
8680     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8681 {
8682     const unsigned int inputShape[] = { 4, 3, 2 };
8683     const unsigned int outputShape[] = { 1, 3, 1 };
8684
8685     std::vector<float> input({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f,
8686                                15.0f, 16.0f, 17.0f, 18.0f, 19.0f, 20.0f, 21.0f, 22.0f, 23.0f, 24.0f });
8687     std::vector<float> output({ 10.5f, 12.5f, 14.5f });
8688
8689     return MeanTestHelper<float, 3, 3>(
8690         workloadFactory, memoryManager, inputShape, input, { 0, 2 }, true, outputShape, output);
8691 }
8692
8693 LayerTestResult<float, 3> MeanVtsFloat3Test(
8694     armnn::IWorkloadFactory& workloadFactory,
8695     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8696 {
8697     const unsigned int inputShape[] = { 1, 2, 2, 1 };
8698     const unsigned int outputShape[] = { 1, 2, 1 };
8699
8700     std::vector<float> input({ 1.0f, 2.0f, 3.0f, 4.0f });
8701     std::vector<float> output({ 1.5f, 3.5f });
8702
8703     return MeanTestHelper<float, 4, 3>(
8704         workloadFactory, memoryManager, inputShape, input, { 2 }, false, outputShape, output);
8705 }
8706
8707 LayerTestResult<float, 4> AdditionAfterMaxPoolTest(
8708     armnn::IWorkloadFactory& workloadFactory,
8709     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8710 {
8711     // Create Initial Tensor
8712     // 1, 2, 3
8713     // 4, 5, 6
8714     // 7, 8, 9
8715
8716     armnn::TensorInfo poolingInputTensorInfo({ 1, 1, 3, 3}, armnn::DataType::Float32);
8717     armnn::TensorInfo poolingOutputTensorInfo({ 1, 1, 2, 2}, armnn::DataType::Float32);
8718
8719     boost::multi_array<float, 4> poolingInput = MakeTensor<float,4>(poolingInputTensorInfo,
8720                                                             {1, 2, 3,
8721                                                              4, 5, 6,
8722                                                              7, 8, 9
8723                                                             });
8724
8725     std::unique_ptr<armnn::ITensorHandle> poolingInputHandle =
8726             workloadFactory.CreateTensorHandle(poolingInputTensorInfo);
8727     std::unique_ptr<armnn::ITensorHandle> poolingOutputHandle =
8728             workloadFactory.CreateTensorHandle(poolingOutputTensorInfo);
8729
8730     // Apply MaxPool poolSize = 1x1, stride=2x2
8731     // Result =
8732     // 1, 3
8733     // 7, 9
8734     armnn::Pooling2dDescriptor descriptor;
8735     descriptor.m_PoolHeight = 1;
8736     descriptor.m_PoolWidth = 1;
8737     descriptor.m_StrideX = 2;
8738     descriptor.m_StrideY = 2;
8739     descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
8740
8741     armnn::Pooling2dQueueDescriptor queueDescriptor;
8742     queueDescriptor.m_Parameters = descriptor;
8743     armnn::WorkloadInfo workloadInfo;
8744     AddInputToWorkload(queueDescriptor, workloadInfo, poolingInputTensorInfo, poolingInputHandle.get());
8745     AddOutputToWorkload(queueDescriptor, workloadInfo, poolingOutputTensorInfo, poolingOutputHandle.get());
8746
8747     // Create the MaxPool
8748     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePooling2d(queueDescriptor, workloadInfo);
8749
8750     //LayerTestResult<float, 4> result(poolingOutputTensorInfo);
8751     auto shape( GetTensorShapeAsArray<4>(poolingOutputTensorInfo));
8752     boost::multi_array<float, 4> resultMaxPool;
8753     resultMaxPool.resize(shape);
8754
8755
8756     // Create addition with another tensor the same size
8757     // This would be the result to apply a Conv2d with kernel ones(2) and stride 1x1
8758     // with the initial tensor.
8759     // 12, 16
8760     // 24, 28
8761
8762     armnn::TensorInfo addInputTensorInfo({ 1,1,2,2}, armnn::DataType::Float32);
8763     armnn::TensorInfo addOutputTensorInfo({ 1,1,2,2}, armnn::DataType::Float32);
8764
8765     boost::multi_array<float, 4> addInput = MakeTensor<float,4>(addInputTensorInfo,
8766                                                                     {12, 16,
8767                                                                      24, 28,
8768                                                                     });
8769
8770     // Expected output tensor after MaxPool and Addition.
8771     LayerTestResult<float,4> addRet(addOutputTensorInfo);
8772     addRet.outputExpected = MakeTensor<float, 4>(addOutputTensorInfo, std::vector<float>(
8773             {
8774                     13, 19,
8775                     31, 37
8776             }));
8777
8778     std::unique_ptr<armnn::ITensorHandle> addInputHandle = workloadFactory.CreateTensorHandle(addInputTensorInfo);
8779     std::unique_ptr<armnn::ITensorHandle> addOutputHandle = workloadFactory.CreateTensorHandle(addOutputTensorInfo);
8780
8781     armnn::AdditionQueueDescriptor data;
8782     armnn::WorkloadInfo info;
8783
8784     // Add the output of the MaxPool and the new tensor
8785     AddInputToWorkload(data, info, poolingOutputTensorInfo, poolingOutputHandle.get());
8786     AddInputToWorkload(data, info, addInputTensorInfo, addInputHandle.get());
8787     AddOutputToWorkload(data, info, addOutputTensorInfo, addOutputHandle.get());
8788
8789     std::unique_ptr<armnn::IWorkload> addWorkload = workloadFactory.CreateAddition(data, info);
8790
8791     poolingInputHandle->Allocate();
8792     poolingOutputHandle->Allocate();
8793     addInputHandle->Allocate();
8794     addOutputHandle->Allocate();
8795
8796     CopyDataToITensorHandle(poolingInputHandle.get(), &poolingInput[0][0][0][0]);
8797     CopyDataFromITensorHandle(&resultMaxPool[0][0][0][0], poolingOutputHandle.get());
8798
8799     CopyDataToITensorHandle(poolingOutputHandle.get(), &resultMaxPool[0][0][0][0]);
8800     CopyDataToITensorHandle(addInputHandle.get(), &addInput[0][0][0][0]);
8801
8802     workload->PostAllocationConfigure();
8803     workload->Execute();
8804     addWorkload->PostAllocationConfigure();
8805     addWorkload->Execute();
8806
8807     CopyDataFromITensorHandle(&addRet.output[0][0][0][0], addOutputHandle.get());
8808
8809     return addRet;
8810 }
8811
8812 LayerTestResult<float, 4> SpaceToBatchNdSimpleFloat32Test(
8813     armnn::IWorkloadFactory& workloadFactory,
8814     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8815 {
8816     return SpaceToBatchNdSimpleTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
8817 }
8818
8819 LayerTestResult<float, 4> SpaceToBatchNdMultiChannelsFloat32Test(
8820     armnn::IWorkloadFactory& workloadFactory,
8821     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8822 {
8823     return SpaceToBatchNdMultiChannelsTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
8824 }
8825
8826 LayerTestResult<float, 4> SpaceToBatchNdMultiBlockFloat32Test(
8827     armnn::IWorkloadFactory& workloadFactory,
8828     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8829 {
8830     return SpaceToBatchNdMultiBlockTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
8831 }
8832
8833 LayerTestResult<float, 4> SpaceToBatchNdPaddingFloat32Test(
8834     armnn::IWorkloadFactory& workloadFactory,
8835     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8836 {
8837     return SpaceToBatchNdPaddingTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
8838 }
8839
8840 LayerTestResult<uint8_t, 4> SpaceToBatchNdSimpleUint8Test(
8841     armnn::IWorkloadFactory& workloadFactory,
8842     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8843 {
8844     return SpaceToBatchNdSimpleTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8845 }
8846
8847 LayerTestResult<uint8_t, 4> SpaceToBatchNdMultiChannelsUint8Test(
8848     armnn::IWorkloadFactory& workloadFactory,
8849     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8850 {
8851     return SpaceToBatchNdMultiChannelsTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8852 }
8853
8854 LayerTestResult<uint8_t, 4> SpaceToBatchNdMultiBlockUint8Test(
8855     armnn::IWorkloadFactory& workloadFactory,
8856     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8857 {
8858     return SpaceToBatchNdMultiBlockTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8859 }
8860
8861 LayerTestResult<uint8_t, 4> SpaceToBatchNdPaddingUint8Test(
8862     armnn::IWorkloadFactory& workloadFactory,
8863     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8864 {
8865     return SpaceToBatchNdPaddingTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8866 }
8867
8868 LayerTestResult<float, 4> SpaceToBatchNdSimpleNHWCFloat32Test(
8869     armnn::IWorkloadFactory& workloadFactory,
8870     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8871 {
8872     return SpaceToBatchNdSimpleNHWCTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
8873 }
8874
8875 LayerTestResult<float, 4> SpaceToBatchNdMultiChannelsNHWCFloat32Test(
8876     armnn::IWorkloadFactory& workloadFactory,
8877     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8878 {
8879     return SpaceToBatchNdMultiChannelsNHWCTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
8880 }
8881
8882 LayerTestResult<float, 4> SpaceToBatchNdMultiBlockNHWCFloat32Test(
8883     armnn::IWorkloadFactory& workloadFactory,
8884     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8885 {
8886     return SpaceToBatchNdMultiBlockNHWCTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
8887 }
8888
8889 LayerTestResult<float, 4> SpaceToBatchNdPaddingNHWCFloat32Test(
8890     armnn::IWorkloadFactory& workloadFactory,
8891     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8892 {
8893     return SpaceToBatchNdPaddingNHWCTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
8894 }
8895
8896 LayerTestResult<uint8_t, 4> SpaceToBatchNdSimpleNHWCUint8Test(
8897     armnn::IWorkloadFactory& workloadFactory,
8898     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8899 {
8900     return SpaceToBatchNdSimpleNHWCTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8901 }
8902
8903 LayerTestResult<uint8_t, 4> SpaceToBatchNdMultiChannelsNHWCUint8Test(
8904     armnn::IWorkloadFactory& workloadFactory,
8905     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8906 {
8907     return SpaceToBatchNdMultiChannelsNHWCTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8908 }
8909
8910 LayerTestResult<uint8_t, 4> SpaceToBatchNdMultiBlockNHWCUint8Test(
8911     armnn::IWorkloadFactory& workloadFactory,
8912     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8913 {
8914     return SpaceToBatchNdMultiBlockNHWCTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8915 }
8916
8917 LayerTestResult<uint8_t, 4> SpaceToBatchNdPaddingNHWCUint8Test(
8918     armnn::IWorkloadFactory& workloadFactory,
8919     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8920 {
8921     return SpaceToBatchNdPaddingNHWCTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
8922 }
8923
8924 namespace {
8925
8926 template<typename T, std::size_t InputDim, std::size_t OutputDim>
8927 LayerTestResult<T, OutputDim> BatchToSpaceNdHelper(
8928     armnn::IWorkloadFactory &workloadFactory,
8929     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
8930     const armnn::DataLayout& dataLayout,
8931     const unsigned int *inputShape,
8932     const std::vector<T> &inputData,
8933     const std::vector<unsigned int> &blockShape,
8934     const std::vector<std::pair<unsigned int, unsigned int>> &crops,
8935     const unsigned int *outputShape,
8936     const std::vector<T> &outputData,
8937     float scale = 1.0f,
8938     int32_t offset = 0)
8939 {
8940     auto dataType = (std::is_same<T, uint8_t>::value ? armnn::DataType::QuantisedAsymm8 : armnn::DataType::Float32);
8941
8942     armnn::TensorInfo inputTensorInfo(InputDim, inputShape, dataType);
8943     armnn::TensorInfo outputTensorInfo(OutputDim, outputShape, dataType);
8944
8945     inputTensorInfo.SetQuantizationScale(scale);
8946     inputTensorInfo.SetQuantizationOffset(offset);
8947
8948     outputTensorInfo.SetQuantizationScale(scale);
8949     outputTensorInfo.SetQuantizationOffset(offset);
8950
8951     auto input = MakeTensor<T, InputDim>(inputTensorInfo, inputData);
8952
8953     LayerTestResult<T, OutputDim> result(outputTensorInfo);
8954     result.outputExpected = MakeTensor<T, OutputDim>(outputTensorInfo, outputData);
8955
8956     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
8957     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
8958
8959     armnn::BatchToSpaceNdQueueDescriptor data;
8960     data.m_Parameters.m_DataLayout = dataLayout;
8961     data.m_Parameters.m_BlockShape = blockShape;
8962     data.m_Parameters.m_Crops = crops;
8963     armnn::WorkloadInfo info;
8964     AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
8965     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
8966
8967     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateBatchToSpaceNd(data, info);
8968
8969     inputHandle->Allocate();
8970     outputHandle->Allocate();
8971
8972     CopyDataToITensorHandle(inputHandle.get(), input.origin());
8973
8974     workload->PostAllocationConfigure();
8975     workload->Execute();
8976
8977     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
8978
8979     return result;
8980 }
8981
8982 } // anonymous namespace
8983
8984 LayerTestResult<float, 4> BatchToSpaceNdNhwcFloat32Test1(
8985     armnn::IWorkloadFactory& workloadFactory,
8986     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
8987 {
8988     const unsigned int inputShape[] = {4, 2, 2, 1};
8989     const unsigned int outputShape[] = {1, 4, 4, 1};
8990
8991     std::vector<float> input({
8992         // Batch 0, Height 0, Width (2) x Channel (1)
8993         1.0f, 3.0f,
8994         // Batch 0, Height 1, Width (2) x Channel (1)
8995         9.0f, 11.0f,
8996
8997
8998         // Batch 1, Height 0, Width (2) x Channel (1)
8999         2.0f, 4.0f,
9000         // Batch 1, Height 1, Width (2) x Channel (1)
9001         10.0f, 12.0f,
9002
9003
9004         // Batch 2, Height 0, Width (2) x Channel (1)
9005         5.0f, 7.0f,
9006         // Batch 2, Height 1, Width (2) x Channel (1)
9007         13.0f, 15.0f,
9008
9009         // Batch 3, Height 0, Width (2) x Channel (3)
9010         6.0f, 8.0f,
9011         // Batch 3, Height 1, Width (2) x Channel (1)
9012         14.0f, 16.0f
9013     });
9014
9015     std::vector<float> expectedOutput({
9016         1.0f,   2.0f,  3.0f,  4.0f,
9017         5.0f,   6.0f,  7.0f,  8.0f,
9018         9.0f,  10.0f, 11.0f,  12.0f,
9019         13.0f, 14.0f, 15.0f,  16.0f
9020     });
9021
9022     std::vector<unsigned int> blockShape {2, 2};
9023     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
9024
9025     return BatchToSpaceNdHelper<float, 4, 4>(workloadFactory, memoryManager,
9026             armnn::DataLayout::NHWC, inputShape, input, blockShape,
9027             crops, outputShape, expectedOutput);
9028 }
9029
9030 LayerTestResult<float, 4> BatchToSpaceNdNhwcFloat32Test2(
9031     armnn::IWorkloadFactory& workloadFactory,
9032     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9033 {
9034     const unsigned int inputShape[] = {4, 1, 1, 1};
9035     const unsigned int outputShape[] = {1, 2, 2, 1};
9036
9037     std::vector<float> input({
9038         // Batch 0, Height 0, Width (2) x Channel (1)
9039         1.0f, 2.0f, 3.0f, 4.0f
9040     });
9041
9042     std::vector<float> expectedOutput({1.0f, 2.0f, 3.0f, 4.0f});
9043
9044     std::vector<unsigned int> blockShape({2, 2});
9045     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
9046
9047     return BatchToSpaceNdHelper<float, 4, 4>(workloadFactory, memoryManager,
9048         armnn::DataLayout::NHWC, inputShape, input, blockShape,
9049         crops, outputShape, expectedOutput);
9050 }
9051
9052 LayerTestResult<float, 4> BatchToSpaceNdNhwcFloat32Test3(
9053     armnn::IWorkloadFactory& workloadFactory,
9054     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9055 {
9056     const unsigned int inputShape[] = {4, 1, 1, 3};
9057     const unsigned int outputShape[] = {1, 2, 2, 3};
9058
9059     std::vector<float> input({1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f});
9060
9061     std::vector<float> expectedOutput({1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f});
9062
9063     std::vector<unsigned int> blockShape({2, 2});
9064     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
9065
9066     return BatchToSpaceNdHelper<float, 4, 4>(workloadFactory, memoryManager,
9067         armnn::DataLayout::NHWC, inputShape, input, blockShape,
9068         crops, outputShape, expectedOutput);
9069 }
9070
9071 LayerTestResult<float, 4> BatchToSpaceNdNhwcFloat32Test4(
9072     armnn::IWorkloadFactory& workloadFactory,
9073     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9074 {
9075     const unsigned int inputShape[] = {8, 1, 3, 1};
9076     const unsigned int outputShape[] = {2, 2, 4, 1};
9077
9078     std::vector<float> input({
9079         0.0f, 1.0f, 3.0f,
9080         0.0f, 9.0f, 11.0f,
9081         0.0f, 2.0f, 4.0f,
9082         0.0f, 10.0f, 12.0f,
9083         0.0f, 5.0f, 7.0f,
9084         0.0f, 13.0f, 15.0f,
9085         0.0f, 6.0f, 8.0f,
9086         0.0f, 14.0f, 16.0f
9087     });
9088
9089     std::vector<float> expectedOutput({
9090         1.0f, 2.0f, 3.0f, 4.0f,
9091         5.0f, 6.0f, 7.0f, 8.0f,
9092         9.0f, 10.0f, 11.0f, 12.0f,
9093         13.0f, 14.0f, 15.0f, 16.0f
9094     });
9095
9096     std::vector<unsigned int> blockShape({2, 2});
9097     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {2, 0}};
9098
9099     return BatchToSpaceNdHelper<float, 4, 4>(workloadFactory, memoryManager,
9100         armnn::DataLayout::NHWC, inputShape, input, blockShape,
9101         crops, outputShape, expectedOutput);
9102 }
9103
9104 LayerTestResult<float, 4> BatchToSpaceNdNchwFloat32Test1(
9105     armnn::IWorkloadFactory &workloadFactory,
9106     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9107 {
9108     const unsigned int inputShape[] = {4, 3, 1, 1};
9109     const unsigned int outputShape[] = {1, 3, 2, 2};
9110
9111     std::vector<float> input({1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f});
9112
9113     std::vector<float> expectedOutput({
9114         // Batch 0, Channel 0, Height (2) x Width (2)
9115         1.0f,  4.0f,
9116         7.0f, 10.0f,
9117
9118         // Batch 0, Channel 1, Height (2) x Width (2)
9119         2.0f,  5.0f,
9120         8.0f, 11.0f,
9121
9122         // Batch 0, Channel 2, Height (2) x Width (2)
9123         3.0f,  6.0f,
9124         9.0f, 12.0f,
9125     });
9126
9127     std::vector<unsigned int> blockShape({2, 2});
9128     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
9129
9130     return BatchToSpaceNdHelper<float, 4, 4>(workloadFactory, memoryManager,
9131         armnn::DataLayout::NCHW, inputShape, input, blockShape,
9132         crops, outputShape, expectedOutput);
9133 }
9134
9135 LayerTestResult<float, 4> BatchToSpaceNdNchwFloat32Test2(
9136     armnn::IWorkloadFactory& workloadFactory,
9137     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9138 {
9139     const unsigned int inputShape[] = {4, 1, 1, 1};
9140     const unsigned int outputShape[] = {1, 1, 2, 2};
9141
9142     std::vector<float> input({
9143         // Batch 0, Height 0, Width (2) x Channel (1)
9144         1.0f, 2.0f, 3.0f, 4.0f
9145     });
9146
9147     std::vector<float> expectedOutput({1.0f, 2.0f, 3.0f, 4.0f});
9148
9149     std::vector<unsigned int> blockShape({2, 2});
9150     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
9151
9152     return BatchToSpaceNdHelper<float, 4, 4>(workloadFactory, memoryManager,
9153                                              armnn::DataLayout::NCHW, inputShape, input, blockShape,
9154                                              crops, outputShape, expectedOutput);
9155 }
9156
9157 LayerTestResult<float, 4> BatchToSpaceNdNchwFloat32Test3(
9158     armnn::IWorkloadFactory& workloadFactory,
9159     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9160 {
9161     const unsigned int inputShape[] = {4, 3, 1, 1};
9162     const unsigned int outputShape[] = {1, 3, 2, 2};
9163
9164     std::vector<float> input({1.0f, 3.0f, 5.0f, 7.0f, 9.0f, 11.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f, 12.0f});
9165
9166     std::vector<float> expectedOutput({
9167         // Batch 0, Channel 0, Height (2) x Width (2)
9168         1.0f,  7.0f,
9169         2.0f,  8.0f,
9170
9171         // Batch 0, Channel 1, Height (2) x Width (2)
9172         3.0f,  9.0f,
9173         4.0f, 10.0f,
9174
9175         // Batch 0, Channel 2, Height (2) x Width (2)
9176         5.0f, 11.0f,
9177         6.0f, 12.0f,
9178     });
9179
9180     std::vector<unsigned int> blockShape({2, 2});
9181     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
9182
9183     return BatchToSpaceNdHelper<float, 4, 4>(workloadFactory, memoryManager,
9184                                              armnn::DataLayout::NCHW, inputShape, input, blockShape,
9185                                              crops, outputShape, expectedOutput);
9186 }
9187
9188 LayerTestResult<uint8_t, 4> BatchToSpaceNdNhwcUintTest1(
9189     armnn::IWorkloadFactory& workloadFactory,
9190     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9191 {
9192     const unsigned int inputShape[] = {4, 2, 2, 1};
9193     const unsigned int outputShape[] = {1, 4, 4, 1};
9194
9195     std::vector<uint8_t> input({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16});
9196     std::vector<uint8_t> expectedOutput({1, 5, 2, 6, 9, 13, 10, 14, 3, 7, 4, 8, 11, 15, 12, 16});
9197
9198     std::vector<unsigned int> blockShape({2, 2});
9199     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
9200
9201     return BatchToSpaceNdHelper<uint8_t, 4, 4>(workloadFactory, memoryManager, armnn::DataLayout::NHWC, inputShape,
9202                                                input, blockShape, crops, outputShape, expectedOutput);
9203 }
9204
9205 LayerTestResult<uint8_t, 4> BatchToSpaceNdNhwcUintTest2(
9206     armnn::IWorkloadFactory& workloadFactory,
9207     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9208 {
9209     const unsigned int inputShape[] = {4, 1, 1, 1};
9210     const unsigned int outputShape[] = {1, 2, 2, 1};
9211
9212     std::vector<uint8_t> input({
9213         // Batch 0, Height 0, Width (2) x Channel (1)
9214         1, 2, 3, 4
9215     });
9216
9217     std::vector<uint8_t> expectedOutput({1, 2, 3, 4});
9218
9219     std::vector<unsigned int> blockShape({2, 2});
9220     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
9221
9222     return BatchToSpaceNdHelper<uint8_t, 4, 4>(workloadFactory, memoryManager,
9223                                                armnn::DataLayout::NHWC, inputShape, input, blockShape,
9224                                                crops, outputShape, expectedOutput);
9225 }
9226
9227 LayerTestResult<uint8_t, 4> BatchToSpaceNdNhwcUintTest3(
9228     armnn::IWorkloadFactory& workloadFactory,
9229     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9230 {
9231     const unsigned int inputShape[] = {4, 1, 1, 3};
9232     const unsigned int outputShape[] = {1, 2, 2, 3};
9233
9234     std::vector<uint8_t> input({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});
9235
9236     std::vector<uint8_t> expectedOutput({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});
9237
9238     std::vector<unsigned int> blockShape({2, 2});
9239     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
9240
9241     return BatchToSpaceNdHelper<uint8_t, 4, 4>(workloadFactory, memoryManager,
9242                                                armnn::DataLayout::NHWC, inputShape, input, blockShape,
9243                                                crops, outputShape, expectedOutput);
9244 }
9245
9246
9247 LayerTestResult<uint8_t, 4> BatchToSpaceNdNchwUintTest1(
9248     armnn::IWorkloadFactory &workloadFactory,
9249     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9250 {
9251     const unsigned int inputShape[] = {4, 3, 1, 1};
9252     const unsigned int outputShape[] = {1, 3, 2, 2};
9253
9254     std::vector<uint8_t> input({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});
9255
9256     std::vector<uint8_t> expectedOutput({
9257         // Batch 0, Channel 0, Height (2) x Width (2)
9258         1,  4,
9259         7, 10,
9260
9261         // Batch 0, Channel 1, Height (2) x Width (2)
9262         2,  5,
9263         8, 11,
9264
9265         // Batch 0, Channel 2, Height (2) x Width (2)
9266         3,  6,
9267         9, 12,
9268     });
9269
9270     std::vector<unsigned int> blockShape({2, 2});
9271     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
9272
9273     return BatchToSpaceNdHelper<uint8_t, 4, 4>(workloadFactory, memoryManager,
9274                                                armnn::DataLayout::NCHW, inputShape, input, blockShape,
9275                                                crops, outputShape, expectedOutput);
9276 }
9277
9278 LayerTestResult<uint8_t, 4> BatchToSpaceNdNchwUintTest2(
9279     armnn::IWorkloadFactory& workloadFactory,
9280     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9281 {
9282     const unsigned int inputShape[] = {4, 1, 1, 1};
9283     const unsigned int outputShape[] = {1, 1, 2, 2};
9284
9285     std::vector<uint8_t> input({
9286         // Batch 0, Height 0, Width (2) x Channel (1)
9287         1, 2, 3, 4
9288     });
9289
9290     std::vector<uint8_t> expectedOutput({1, 2, 3, 4});
9291
9292     std::vector<unsigned int> blockShape({2, 2});
9293     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
9294
9295     return BatchToSpaceNdHelper<uint8_t, 4, 4>(workloadFactory, memoryManager,
9296                                                armnn::DataLayout::NCHW, inputShape, input, blockShape,
9297                                                crops, outputShape, expectedOutput);
9298 }
9299
9300 LayerTestResult<uint8_t, 4> BatchToSpaceNdNchwUintTest3(
9301     armnn::IWorkloadFactory& workloadFactory,
9302     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9303 {
9304     const unsigned int inputShape[] = {4, 3, 1, 1};
9305     const unsigned int outputShape[] = {1, 3, 2, 2};
9306
9307     std::vector<uint8_t> input({1, 3, 5, 7, 9, 11, 2, 4, 6, 8, 10, 12});
9308
9309     std::vector<uint8_t> expectedOutput({
9310         // Batch 0, Channel 0, Height (2) x Width (2)
9311         1,  7,
9312         2,  8,
9313
9314         // Batch 0, Channel 1, Height (2) x Width (2)
9315         3,  9,
9316         4, 10,
9317
9318         // Batch 0, Channel 2, Height (2) x Width (2)
9319         5, 11,
9320         6, 12,
9321     });
9322
9323     std::vector<unsigned int> blockShape({2, 2});
9324     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
9325
9326     return BatchToSpaceNdHelper<uint8_t, 4, 4>(workloadFactory, memoryManager,
9327                                                armnn::DataLayout::NCHW, inputShape, input, blockShape,
9328                                                crops, outputShape, expectedOutput);
9329 }
9330
9331 LayerTestResult<uint8_t, 4> BatchToSpaceNdNchwUintTest4(
9332         armnn::IWorkloadFactory& workloadFactory,
9333         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9334 {
9335     const unsigned int inputShape[] = {8, 1, 1, 3};
9336     const unsigned int outputShape[] = {2, 1, 2, 4};
9337
9338     std::vector<uint8_t> input({
9339         0, 1, 3, 0,  9, 11,
9340         0, 2, 4, 0, 10, 12,
9341         0, 5, 7, 0, 13, 15,
9342         0, 6, 8, 0, 14, 16
9343     });
9344
9345     std::vector<uint8_t> expectedOutput({
9346         1,  2,  3,  4,
9347         5,  6,  7,  8,
9348         9, 10, 11, 12,
9349        13, 14, 15, 16
9350     });
9351
9352     std::vector<unsigned int> blockShape({2, 2});
9353     std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {2, 0}};
9354
9355     return BatchToSpaceNdHelper<uint8_t, 4, 4>(workloadFactory, memoryManager,
9356         armnn::DataLayout::NCHW, inputShape, input, blockShape,
9357         crops, outputShape, expectedOutput);
9358 }
9359
9360 LayerTestResult<float, 4> StridedSlice4DFloat32Test(
9361     armnn::IWorkloadFactory& workloadFactory,
9362     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9363 {
9364     return StridedSlice4DTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9365 }
9366
9367 LayerTestResult<float, 4> StridedSlice4DReverseFloat32Test(
9368     armnn::IWorkloadFactory& workloadFactory,
9369     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9370 {
9371     return StridedSlice4DReverseTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9372 }
9373
9374 LayerTestResult<float, 4> StridedSliceSimpleStrideFloat32Test(
9375     armnn::IWorkloadFactory& workloadFactory,
9376     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9377 {
9378     return StridedSliceSimpleStrideTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9379 }
9380
9381 LayerTestResult<float, 4> StridedSliceSimpleRangeMaskFloat32Test(
9382     armnn::IWorkloadFactory& workloadFactory,
9383     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9384 {
9385     return StridedSliceSimpleRangeMaskTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9386 }
9387
9388 LayerTestResult<float, 2> StridedSliceShrinkAxisMaskFloat32Test(
9389     armnn::IWorkloadFactory& workloadFactory,
9390     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9391 {
9392     return StridedSliceShrinkAxisMaskTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9393 }
9394
9395 LayerTestResult<float, 3> StridedSlice3DFloat32Test(
9396     armnn::IWorkloadFactory& workloadFactory,
9397     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9398 {
9399     return StridedSlice3DTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9400 }
9401
9402 LayerTestResult<float, 3> StridedSlice3DReverseFloat32Test(
9403     armnn::IWorkloadFactory& workloadFactory,
9404     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9405 {
9406     return StridedSlice3DReverseTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9407 }
9408
9409 LayerTestResult<float, 2> StridedSlice2DFloat32Test(
9410     armnn::IWorkloadFactory& workloadFactory,
9411     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9412 {
9413     return StridedSlice2DTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9414 }
9415
9416 LayerTestResult<float, 2> StridedSlice2DReverseFloat32Test(
9417     armnn::IWorkloadFactory& workloadFactory,
9418     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9419 {
9420     return StridedSlice2DReverseTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9421 }
9422
9423 LayerTestResult<uint8_t, 4> StridedSlice4DUint8Test(
9424     armnn::IWorkloadFactory& workloadFactory,
9425     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9426 {
9427     return StridedSlice4DTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9428 }
9429
9430 LayerTestResult<uint8_t, 4> StridedSlice4DReverseUint8Test(
9431     armnn::IWorkloadFactory& workloadFactory,
9432     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9433 {
9434     return StridedSlice4DReverseTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9435 }
9436
9437 LayerTestResult<uint8_t, 4> StridedSliceSimpleStrideUint8Test(
9438     armnn::IWorkloadFactory& workloadFactory,
9439     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9440 {
9441     return StridedSliceSimpleStrideTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9442 }
9443
9444 LayerTestResult<uint8_t, 4> StridedSliceSimpleRangeMaskUint8Test(
9445     armnn::IWorkloadFactory& workloadFactory,
9446     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9447 {
9448     return StridedSliceSimpleRangeMaskTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9449 }
9450
9451 LayerTestResult<uint8_t, 2> StridedSliceShrinkAxisMaskUint8Test(
9452     armnn::IWorkloadFactory& workloadFactory,
9453     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9454 {
9455     return StridedSliceShrinkAxisMaskTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9456 }
9457
9458 LayerTestResult<uint8_t, 3> StridedSlice3DUint8Test(
9459     armnn::IWorkloadFactory& workloadFactory,
9460     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9461 {
9462     return StridedSlice3DTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9463 }
9464
9465 LayerTestResult<uint8_t, 3> StridedSlice3DReverseUint8Test(
9466     armnn::IWorkloadFactory& workloadFactory,
9467     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9468 {
9469     return StridedSlice3DReverseTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9470 }
9471
9472 LayerTestResult<uint8_t, 2> StridedSlice2DUint8Test(
9473     armnn::IWorkloadFactory& workloadFactory,
9474     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9475 {
9476     return StridedSlice2DTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9477 }
9478
9479 LayerTestResult<uint8_t, 2> StridedSlice2DReverseUint8Test(
9480     armnn::IWorkloadFactory& workloadFactory,
9481     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9482 {
9483     return StridedSlice2DReverseTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9484 }
9485
9486 LayerTestResult<float, 4> Debug4DFloat32Test(
9487     armnn::IWorkloadFactory& workloadFactory,
9488     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9489 {
9490     return Debug4DTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9491 }
9492
9493 LayerTestResult<float, 3> Debug3DFloat32Test(
9494     armnn::IWorkloadFactory& workloadFactory,
9495     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9496 {
9497     return Debug3DTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9498 }
9499
9500 LayerTestResult<float, 2> Debug2DFloat32Test(
9501     armnn::IWorkloadFactory& workloadFactory,
9502     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9503 {
9504     return Debug2DTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9505 }
9506
9507 LayerTestResult<float, 1> Debug1DFloat32Test(
9508     armnn::IWorkloadFactory& workloadFactory,
9509     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9510 {
9511     return Debug1DTest<armnn::DataType::Float32>(workloadFactory, memoryManager);
9512 }
9513
9514 LayerTestResult<uint8_t, 4> Debug4DUint8Test(
9515     armnn::IWorkloadFactory& workloadFactory,
9516     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9517 {
9518     return Debug4DTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9519 }
9520
9521 LayerTestResult<uint8_t, 3> Debug3DUint8Test(
9522     armnn::IWorkloadFactory& workloadFactory,
9523     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9524 {
9525     return Debug3DTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9526 }
9527
9528 LayerTestResult<uint8_t, 2> Debug2DUint8Test(
9529     armnn::IWorkloadFactory& workloadFactory,
9530     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9531 {
9532     return Debug2DTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9533 }
9534
9535 LayerTestResult<uint8_t, 1> Debug1DUint8Test(
9536     armnn::IWorkloadFactory& workloadFactory,
9537     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9538 {
9539     return Debug1DTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9540 }
9541
9542 LayerTestResult<float, 1> Gather1DParamsFloatTest(
9543     armnn::IWorkloadFactory& workloadFactory,
9544     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9545 {
9546     return Gather1DParamsTestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager);
9547 }
9548
9549 LayerTestResult<uint8_t, 1> Gather1DParamsUint8Test(
9550     armnn::IWorkloadFactory& workloadFactory,
9551     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9552 {
9553     return Gather1DParamsTestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9554 }
9555
9556 LayerTestResult<float, 2> GatherMultiDimParamsFloatTest(
9557     armnn::IWorkloadFactory& workloadFactory,
9558     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9559 {
9560     return GatherMultiDimParamsTestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager);
9561 }
9562
9563 LayerTestResult<uint8_t, 2> GatherMultiDimParamsUint8Test(
9564     armnn::IWorkloadFactory& workloadFactory,
9565     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9566 {
9567     return GatherMultiDimParamsTestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9568 }
9569
9570 LayerTestResult<float, 4> GatherMultiDimParamsMultiDimIndicesFloatTest(
9571     armnn::IWorkloadFactory& workloadFactory,
9572     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9573 {
9574     return GatherMultiDimParamsMultiDimIndicesTestImpl<armnn::DataType::Float32>(workloadFactory, memoryManager);
9575 }
9576
9577 LayerTestResult<uint8_t, 4> GatherMultiDimParamsMultiDimIndicesUint8Test(
9578     armnn::IWorkloadFactory& workloadFactory,
9579     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9580 {
9581     return GatherMultiDimParamsMultiDimIndicesTestImpl<armnn::DataType::QuantisedAsymm8>(
9582         workloadFactory, memoryManager);
9583 }
9584
9585 LayerTestResult<float, 4> DequantizeSimpleUint8Test(
9586     armnn::IWorkloadFactory& workloadFactory,
9587     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9588 {
9589     return DequantizeSimpleTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9590 }
9591
9592 LayerTestResult<float, 4> DequantizeOffsetUint8Test(
9593     armnn::IWorkloadFactory& workloadFactory,
9594     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9595 {
9596     return DequantizeOffsetTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9597 }
9598
9599 LayerTestResult<float, 4> DequantizeSimpleInt16Test(
9600     armnn::IWorkloadFactory& workloadFactory,
9601     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9602 {
9603     return DequantizeSimpleTest<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager);
9604 }
9605
9606 LayerTestResult<uint8_t, 4> QuantizeSimpleUint8Test(
9607     armnn::IWorkloadFactory& workloadFactory,
9608     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9609 {
9610     return QuantizeSimpleTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9611 }
9612
9613 LayerTestResult<uint8_t, 4> QuantizeClampUint8Test(
9614     armnn::IWorkloadFactory& workloadFactory,
9615     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9616 {
9617     return QuantizeClampTest<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
9618 }
9619
9620 LayerTestResult<int16_t, 4> QuantizeClampInt16Test(
9621     armnn::IWorkloadFactory& workloadFactory,
9622     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
9623 {
9624     return QuantizeClampTest<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager);
9625 }