IVGCVSW-2093 Add SpaceToBatchNd layer and corresponding no-op factory implementations
[platform/upstream/armnn.git] / src / backends / test / ActivationTestImpl.hpp
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6
7 #include <armnn/ArmNN.hpp>
8 #include <armnn/Tensor.hpp>
9 #include <armnn/TypesUtils.hpp>
10
11 #include <test/TensorHelpers.hpp>
12 #include "QuantizeHelper.hpp"
13
14 #include <backends/CpuTensorHandle.hpp>
15 #include <backends/WorkloadFactory.hpp>
16 #include "ActivationFixture.hpp"
17
18 #include <algorithm>
19
20 template<typename T>
21 LayerTestResult<T, 4> BoundedReLuTestCommon(armnn::IWorkloadFactory& workloadFactory,
22                                         float upperBound, float lowerBound,
23                                         float inputScale, int32_t inputOffset, float outputScale, int32_t outputOffset,
24                                         const std::vector<T>& inputData, const std::vector<T>& outputExpectedData,
25                                         unsigned int inputWidth, unsigned int inputHeight,
26                                         unsigned int inputChannels, unsigned int inputBatchSize)
27 {
28     unsigned int outputWidth = inputWidth;
29     unsigned int outputHeight = inputHeight;
30     unsigned int outputChannels = inputChannels;
31     unsigned int outputBatchSize = inputBatchSize;
32
33     armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth },
34         armnn::GetDataType<T>());
35
36     armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth },
37         armnn::GetDataType<T>());
38
39     if(armnn::IsQuantizedType<T>())
40     {
41         inputTensorInfo.SetQuantizationScale(inputScale);
42         inputTensorInfo.SetQuantizationOffset(inputOffset);
43
44         outputTensorInfo.SetQuantizationScale(outputScale);
45         outputTensorInfo.SetQuantizationOffset(outputOffset);
46     }
47
48     LayerTestResult<T, 4> result(inputTensorInfo);
49
50     auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
51
52     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
53     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
54
55     // Setup bounded ReLu.
56     armnn::ActivationQueueDescriptor descriptor;
57     armnn::WorkloadInfo workloadInfo;
58     AddInputToWorkload(descriptor, workloadInfo, inputTensorInfo, inputHandle.get());
59     AddOutputToWorkload(descriptor, workloadInfo, outputTensorInfo, outputHandle.get());
60
61     descriptor.m_Parameters.m_Function = armnn::ActivationFunction::BoundedReLu;
62     descriptor.m_Parameters.m_A = upperBound;
63     descriptor.m_Parameters.m_B = lowerBound;
64
65     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateActivation(descriptor, workloadInfo);
66
67     inputHandle->Allocate();
68     outputHandle->Allocate();
69
70     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
71
72     workload->Execute();
73
74     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
75
76     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputExpectedData);
77
78     return result;
79 }
80
81 LayerTestResult<float, 4> BoundedReLuUpperAndLowerBoundTest(armnn::IWorkloadFactory& workloadFactory)
82 {
83     unsigned int inputWidth = 4u;
84     unsigned int inputHeight = 5u;
85     unsigned int inputChannels = 1u;
86     unsigned int inputBatchSize = 1;
87
88     std::vector<float> input = std::vector<float>{
89       -2.0f,       0.1f,     0.5f,     1.25f,
90      0.786f,    0.9875f,    -1.5f,    0.384f,
91     1.0001f,       3.5f,     7.5f,    0.896f,
92      2.126f,       2.0f,     0.3f,     0.15f,
93      0.999f,       1.2f,    0.89f,      6.1f,
94     };
95
96     // Calculated manually.
97     std::vector<float> output = std::vector<float>{
98       -1.0f,       0.1f,     0.5f,      1.0f,
99      0.786f,    0.9875f,    -1.0f,    0.384f,
100        1.0f,       1.0f,     1.0f,    0.896f,
101        1.0f,       1.0f,     0.3f,     0.15f,
102      0.999f,       1.0f,    0.89f,      1.0f,
103     };
104
105     return BoundedReLuTestCommon(workloadFactory, 1.0f, -1.0f, 1.0f, 0, 1.0f, 0, input, output,
106                                  inputWidth, inputHeight, inputChannels, inputBatchSize);
107 }
108
109 LayerTestResult<float, 4> BoundedReLuUpperBoundOnlyTest(armnn::IWorkloadFactory& workloadFactory)
110 {
111     unsigned int inputWidth = 4u;
112     unsigned int inputHeight = 5u;
113     unsigned int inputChannels = 1u;
114     unsigned int inputBatchSize = 1;
115
116     std::vector<float> input = std::vector<float>{
117       -1.0f,       0.1f,     0.5f,      6.25f,
118      0.786f,    5.9875f,    -0.5f,     0.384f,
119     6.0001f,       3.5f,     7.5f,     0.896f,
120      2.126f,      12.0f,     0.3f,      0.15f,
121      0.999f,       1.2f,    0.89f,       6.1f,
122     };
123
124     // Calculated manually.
125     std::vector<float> output = std::vector<float>{
126        0.0f,       0.1f,     0.5f,       6.0f,
127      0.786f,    5.9875f,     0.0f,     0.384f,
128        6.0f,       3.5f,     6.0f,     0.896f,
129      2.126f,       6.0f,     0.3f,      0.15f,
130      0.999f,       1.2f,    0.89f,       6.0f,
131     };
132
133     return BoundedReLuTestCommon(workloadFactory, 6.0f, 0.0f, 1.0f, 0, 1.0f, 0, input, output,
134                                  inputWidth, inputHeight, inputChannels, inputBatchSize);
135 }
136
137 LayerTestResult<uint8_t, 4> BoundedReLuUint8UpperBoundOnlyTest(armnn::IWorkloadFactory& workloadFactory)
138 {
139     unsigned int inputWidth     = 3u;
140     unsigned int inputHeight    = 2u;
141     unsigned int inputChannels  = 1u;
142     unsigned int inputBatchSize = 1;
143
144     std::vector<uint8_t> input = std::vector<uint8_t>{
145          51, 124, 28,
146         251,   8, 92
147     };
148
149     // Calculated manually.
150     std::vector<uint8_t> output = std::vector<uint8_t>{
151           0, 122,  0,
152         255,   0, 58
153     };
154
155     float inputScale     = 12.0f / 255.0f;
156     int32_t inputOffset  = 63;
157     float outputScale    = 6.0f / 255.0f;
158     int32_t outputOffset = 0;
159
160     return BoundedReLuTestCommon(workloadFactory, 6.0f, 0.0f,
161                                  inputScale, inputOffset, outputScale, outputOffset,
162                                  input, output,
163                                  inputWidth, inputHeight, inputChannels, inputBatchSize);
164 }
165
166 LayerTestResult<uint8_t, 4> BoundedReLuUint8UpperAndLowerBoundTest(armnn::IWorkloadFactory& workloadFactory)
167 {
168     unsigned int inputWidth     = 3u;
169     unsigned int inputHeight    = 2u;
170     unsigned int inputChannels  = 1u;
171     unsigned int inputBatchSize = 1;
172
173     std::vector<uint8_t> input = std::vector<uint8_t>{
174          51, 230, 28,
175         251,   8, 92
176     };
177
178     // Calculated manually.
179     std::vector<uint8_t> output = std::vector<uint8_t>{
180          51, 192, 32,
181         192,  32, 92
182     };
183
184     int32_t inputOffset = 112;
185     float inputScale    = 0.0125f;
186
187     return BoundedReLuTestCommon(workloadFactory, 1.0f, -1.0f,
188                                  inputScale, inputOffset, inputScale, inputOffset, // Input/output scale & offset same.
189                                  input, output,
190                                  inputWidth, inputHeight, inputChannels, inputBatchSize);
191 }
192
193 namespace
194 {
195
196 struct BoundedReLuRandomInputTestTraits
197 {
198     constexpr static unsigned int inputHeight = 31u;
199     constexpr static unsigned int inputWidth = 19u;
200     constexpr static unsigned int inputChannels = 4u;
201     constexpr static unsigned int inputBatchSize = 2;
202
203     constexpr static unsigned int outputHeight = inputHeight;
204     constexpr static unsigned int outputWidth = inputWidth;
205     constexpr static unsigned int outputChannels = inputChannels;
206     constexpr static unsigned int outputBatchSize = inputBatchSize;
207
208     static armnn::TensorInfo GetInputTensorInfo()
209     {
210         return armnn::TensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth },
211             armnn::DataType::Float32);
212     }
213
214     static armnn::TensorInfo GetOutputTensorInfo()
215     {
216         return armnn::TensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth },
217             armnn::DataType::Float32);
218     }
219 };
220
221 boost::multi_array<float, 4> BoundedReLuRandomInputTest(armnn::IWorkloadFactory& workloadFactory,
222                                                         float lowerBound,
223                                                         float upperBound,
224                                                         const armnn::ActivationDescriptor& activationDescriptor)
225 {
226     const armnn::TensorInfo inputTensorInfo = BoundedReLuRandomInputTestTraits::GetInputTensorInfo();
227     const armnn::TensorInfo outputTensorInfo = BoundedReLuRandomInputTestTraits::GetOutputTensorInfo();
228
229     boost::multi_array<float, 4> output(GetTensorShapeAsArray<4>(outputTensorInfo));
230
231     // Min/max random values passed to MakeRandomTensor are purposely outside of the ReLu
232     // range [lowerBound, upperBound].
233     auto input = MakeRandomTensor<float, 4>(inputTensorInfo, 4605828, lowerBound - 5.0f, upperBound * 2.0f);
234
235     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
236     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
237
238     // Set up bounded ReLu.
239     armnn::ActivationQueueDescriptor descriptor;
240     armnn::WorkloadInfo workloadInfo;
241     AddInputToWorkload(descriptor, workloadInfo, inputTensorInfo, inputHandle.get());
242     AddOutputToWorkload(descriptor, workloadInfo, outputTensorInfo, outputHandle.get());
243     descriptor.m_Parameters = activationDescriptor;
244
245     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateActivation(descriptor, workloadInfo);
246
247     inputHandle->Allocate();
248     outputHandle->Allocate();
249
250     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
251
252     workload->Execute();
253
254     CopyDataFromITensorHandle(&output[0][0][0][0], outputHandle.get());
255
256     return output;
257 }
258
259 } // namespace
260
261 LayerTestResult<float, 4> CompareBoundedReLuTest(armnn::IWorkloadFactory& workloadFactory,
262                                           armnn::IWorkloadFactory& otherWorkloadFactory,
263                                           float upperBound,
264                                           float lowerBound)
265 {
266     LayerTestResult<float, 4> result(BoundedReLuRandomInputTestTraits::GetOutputTensorInfo());
267
268     armnn::ActivationDescriptor activationDescriptor;
269     activationDescriptor.m_Function = armnn::ActivationFunction::BoundedReLu;
270     activationDescriptor.m_A = upperBound;
271     activationDescriptor.m_B = lowerBound;
272
273     result.output = BoundedReLuRandomInputTest(workloadFactory, 0.0f, upperBound, activationDescriptor);
274     result.outputExpected = BoundedReLuRandomInputTest(otherWorkloadFactory, 0.0f, upperBound, activationDescriptor);
275
276     return result;
277 }
278
279 template<typename T>
280 LayerTestResult<T,4> ConstantLinearActivationTestCommon(armnn::IWorkloadFactory& workloadFactory,
281                                                         float qScale = 0.0f,
282                                                         int32_t qOffset = 0)
283 {
284     unsigned int inputHeight    = 20;
285     unsigned int inputWidth     = 17;
286     unsigned int inputChannels  = 3;
287     unsigned int batchSize      = 5;
288
289     armnn::TensorInfo inputTensorInfo;
290     armnn::TensorInfo outputTensorInfo;
291
292     unsigned int shape[]  = {batchSize, inputChannels, inputHeight, inputWidth};
293
294     inputTensorInfo = armnn::TensorInfo(4, shape, armnn::GetDataType<T>());
295     outputTensorInfo = armnn::TensorInfo(4, shape, armnn::GetDataType<T>());
296
297     // Set quantization parameters if the requested type is a quantized type.
298     if(armnn::IsQuantizedType<T>())
299     {
300         inputTensorInfo.SetQuantizationScale(qScale);
301         inputTensorInfo.SetQuantizationOffset(qOffset);
302         outputTensorInfo.SetQuantizationScale(qScale);
303         outputTensorInfo.SetQuantizationOffset(qOffset);
304     }
305
306     LayerTestResult<T, 4> ret(outputTensorInfo);
307
308     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
309     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
310
311     // Do linear activation that should leave the tensor unchanged.
312     armnn::ActivationQueueDescriptor data;
313     armnn::WorkloadInfo info;
314     AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
315     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
316     data.m_Parameters.m_A = 1.0f;
317     data.m_Parameters.m_B = 0.0f;
318     data.m_Parameters.m_Function = armnn::ActivationFunction::Linear;
319
320     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateActivation(data, info);
321
322     inputHandle->Allocate();
323     outputHandle->Allocate();
324
325     boost::multi_array<T, 4> input = MakeRandomTensor<T, 4>(inputTensorInfo, 7123561);
326     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
327
328     workload->Execute();
329
330     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
331
332     // Ensure output equals input.
333     ret.outputExpected = input;
334
335     return ret;
336 }
337
338 LayerTestResult<float, 4> ConstantLinearActivationTest(armnn::IWorkloadFactory& workloadFactory)
339 {
340     return ConstantLinearActivationTestCommon<float>(workloadFactory);
341 }
342
343 LayerTestResult<uint8_t, 4> ConstantLinearActivationUint8Test(armnn::IWorkloadFactory& workloadFactory)
344 {
345     return ConstantLinearActivationTestCommon<uint8_t>(workloadFactory, 4.0f, 3);
346 }
347
348 template<typename T>
349 LayerTestResult<T, 4> SimpleActivationTest(armnn::IWorkloadFactory& workloadFactory,
350                                            armnn::ActivationFunction activationFunction,
351                                            float activationParameterA,
352                                            float activationParameterB,
353                                            float qScale,
354                                            int32_t qOffset,
355                                            const std::vector<float>& inputData,
356                                            const std::vector<float>& outputExpectedData)
357 {
358     constexpr static unsigned int inputWidth = 16u;
359     constexpr static unsigned int inputHeight = 1u;
360     constexpr static unsigned int inputChannels = 1u;
361     constexpr static unsigned int inputBatchSize = 1u;
362
363     constexpr static unsigned int outputWidth = inputWidth;
364     constexpr static unsigned int outputHeight = inputHeight;
365     constexpr static unsigned int outputChannels = inputChannels;
366     constexpr static unsigned int outputBatchSize = inputBatchSize;
367
368     armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth },
369                                       armnn::GetDataType<T>());
370     armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth },
371                                        armnn::GetDataType<T>());
372
373     // Set quantization parameters if the requested type is a quantized type.
374     if(armnn::IsQuantizedType<T>())
375     {
376         inputTensorInfo.SetQuantizationScale(qScale);
377         inputTensorInfo.SetQuantizationOffset(qOffset);
378         outputTensorInfo.SetQuantizationScale(qScale);
379         outputTensorInfo.SetQuantizationOffset(qOffset);
380     }
381
382     LayerTestResult<T, 4> result(inputTensorInfo);
383
384     auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
385
386     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
387     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
388
389     // Setup bounded ReLu.
390     armnn::ActivationQueueDescriptor descriptor;
391     armnn::WorkloadInfo workloadInfo;
392     AddInputToWorkload(descriptor, workloadInfo, inputTensorInfo, inputHandle.get());
393     AddOutputToWorkload(descriptor, workloadInfo, outputTensorInfo, outputHandle.get());
394
395     descriptor.m_Parameters.m_Function = activationFunction;
396     descriptor.m_Parameters.m_A = activationParameterA;
397     descriptor.m_Parameters.m_B = activationParameterB;
398
399     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateActivation(descriptor, workloadInfo);
400
401     inputHandle->Allocate();
402     outputHandle->Allocate();
403
404     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
405
406     workload->Execute();
407
408     CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
409
410     // Calculated manually.
411     result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, outputExpectedData));
412
413     return result;
414 }
415
416 template<typename T>
417 LayerTestResult<T, 4> SimpleSigmoidTestCommon(armnn::IWorkloadFactory& workloadFactory, float qScale, int32_t qOffset)
418 {
419     std::vector<float> inputData = {
420         -0.1f, -0.2f, -0.3f, -0.4f,
421         0.1f,  0.2f,  0.3f,  0.4f,
422         -1.0f, -2.0f, -3.0f, -4.0f,
423         1.0f,  2.0f,  3.0f,  4.0f
424     };
425
426     // Calculate output values for input.
427     auto f = [](float value)
428     {
429         return 1.0f / (1.0f + std::exp(-value));
430     };
431     std::vector<float> outputExpectedData(inputData.size());
432     std::transform(inputData.begin(), inputData.end(), outputExpectedData.begin(), f);
433
434     return SimpleActivationTest<T>(workloadFactory,
435                                    armnn::ActivationFunction::Sigmoid,
436                                    0.f,
437                                    0.f,
438                                    qScale,
439                                    qOffset,
440                                    inputData,
441                                    outputExpectedData);
442 }
443
444 LayerTestResult<float, 4> SimpleSigmoidTest(armnn::IWorkloadFactory& workloadFactory)
445 {
446     return SimpleSigmoidTestCommon<float>(workloadFactory, 0.0f, 0);
447 }
448
449 LayerTestResult<uint8_t, 4> SimpleSigmoidUint8Test(armnn::IWorkloadFactory& workloadFactory)
450 {
451     return SimpleSigmoidTestCommon<uint8_t>(workloadFactory, 0.1f, 50);
452 }
453
454 template<typename T>
455 LayerTestResult<T,4> CompareActivationTestImpl(armnn::IWorkloadFactory& workloadFactory,
456                                                armnn::IWorkloadFactory& refWorkloadFactory,
457                                                armnn::ActivationFunction f,
458                                                unsigned int batchSize = 5,
459                                                float qScale = 0.0f,
460                                                int32_t qOffset = 0)
461 {
462     unsigned int width     = 17;
463     unsigned int height    = 29;
464     unsigned int channels  = 2;
465
466     float a = 0.234f;
467     float b = -12.345f;
468
469     armnn::TensorInfo inputTensorInfo;
470     armnn::TensorInfo outputTensorInfo;
471
472     unsigned int shape[] = {batchSize, channels, height, width};
473
474     inputTensorInfo = armnn::TensorInfo(4, shape, armnn::GetDataType<T>());
475     outputTensorInfo = armnn::TensorInfo(4, shape, armnn::GetDataType<T>());
476
477     // Set quantization parameters if the requested type is a quantized type.
478     if(armnn::IsQuantizedType<T>())
479     {
480         inputTensorInfo.SetQuantizationScale(qScale);
481         inputTensorInfo.SetQuantizationOffset(qOffset);
482         outputTensorInfo.SetQuantizationScale(qScale);
483         outputTensorInfo.SetQuantizationOffset(qOffset);
484     }
485
486     float minVal = -10.f;
487     if (f == armnn::ActivationFunction::Sqrt)
488     {
489         minVal = 0.f;
490     }
491
492     boost::multi_array<T, 4> input = MakeRandomTensor<T, 4>(inputTensorInfo, 21453, minVal, 10.f);
493
494
495     LayerTestResult<T,4> ret(outputTensorInfo);
496     auto boostArrayExtents = boost::extents
497         [boost::numeric_cast<boost::multi_array_types::extent_gen::index>(batchSize)]
498     [boost::numeric_cast<boost::multi_array_types::extent_gen::index>(channels)]
499     [boost::numeric_cast<boost::multi_array_types::extent_gen::index>(height)]
500     [boost::numeric_cast<boost::multi_array_types::extent_gen::index>(width)];
501     ret.output.resize(boostArrayExtents);
502     ret.outputExpected.resize(boostArrayExtents);
503
504
505     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
506     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
507
508     std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refWorkloadFactory.CreateTensorHandle(inputTensorInfo);
509     std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refWorkloadFactory.CreateTensorHandle(outputTensorInfo);
510
511     armnn::ActivationQueueDescriptor data;
512     armnn::WorkloadInfo info;
513     AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
514     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
515     data.m_Parameters.m_A        = a;
516     data.m_Parameters.m_B        = b;
517     data.m_Parameters.m_Function = f;
518
519     armnn::ActivationQueueDescriptor refData = data;
520     armnn::WorkloadInfo refInfo = info;
521     SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
522     SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
523
524     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateActivation(data, info);
525     BOOST_ASSERT(workload != nullptr);
526     std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreateActivation(refData, refInfo);
527     BOOST_ASSERT(workloadRef != nullptr);
528
529     inputHandle->Allocate();
530     outputHandle->Allocate();
531     inputHandleRef->Allocate();
532     outputHandleRef->Allocate();
533
534     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
535     CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0][0][0]);
536
537     workload->Execute();
538     workloadRef->Execute();
539
540     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
541     CopyDataFromITensorHandle(&ret.outputExpected[0][0][0][0], outputHandleRef.get());
542
543     return ret;
544 }
545
546 LayerTestResult<float,4> CompareActivationTest(armnn::IWorkloadFactory& workloadFactory,
547                                                armnn::IWorkloadFactory& refWorkloadFactory,
548                                                armnn::ActivationFunction f,
549                                                unsigned int batchSize)
550 {
551     return CompareActivationTestImpl<float>(workloadFactory, refWorkloadFactory, f, batchSize);
552 }
553
554 LayerTestResult<uint8_t,4> CompareActivationUint8Test(armnn::IWorkloadFactory& workloadFactory,
555                                                       armnn::IWorkloadFactory& refWorkloadFactory,
556                                                       armnn::ActivationFunction f)
557 {
558     return CompareActivationTestImpl<uint8_t>(workloadFactory, refWorkloadFactory, f, 5, 0.1f, 50);
559 }