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