IVGCVSW-4446 Add HardSwish EndToEnd tests

* adds convert from armnn HardSwish to Acl HardSwish
* adds EndToEnd tests for Ref, Cl and Neon

Signed-off-by: Jan Eilers <jan.eilers@arm.com>
Change-Id: If997dad783ff45d7f061254e7e30bb69d4d4d564
diff --git a/src/backends/aclCommon/ArmComputeUtils.hpp b/src/backends/aclCommon/ArmComputeUtils.hpp
index 01a5445..c3cfb5c 100644
--- a/src/backends/aclCommon/ArmComputeUtils.hpp
+++ b/src/backends/aclCommon/ArmComputeUtils.hpp
@@ -66,6 +66,7 @@
         case ActivationFunction::Square:        return AclActivationFunction::SQUARE;
         case ActivationFunction::TanH:          return AclActivationFunction::TANH;
         case ActivationFunction::Elu:           return AclActivationFunction::ELU;
+        case ActivationFunction::HardSwish:     return AclActivationFunction::HARD_SWISH;
         default:                                throw InvalidArgumentException("Unsupported activation function");
     }
 }
diff --git a/src/backends/backendsCommon/test/ActivationEndToEndTestImpl.hpp b/src/backends/backendsCommon/test/ActivationEndToEndTestImpl.hpp
index 23884b0..1b735be 100644
--- a/src/backends/backendsCommon/test/ActivationEndToEndTestImpl.hpp
+++ b/src/backends/backendsCommon/test/ActivationEndToEndTestImpl.hpp
@@ -32,6 +32,8 @@
         // The following values are taken from ArmComputeLibrary/tests/validation/CL/ActivationLayer.cpp
         case ActivationFunction::Elu:
             return (dataType == DataType::Float16 ? 0.01f : 0.00001f);
+        case ActivationFunction::HardSwish:
+            return (dataType == DataType::Float16 ? 0.01f : defaultTolerance);
         default:
             return defaultTolerance;
     }
@@ -123,7 +125,7 @@
                                         1.0f,  2.0f,  3.0f, 4.0f };
 
     std::vector<float> floatExpectedOutputData{ -0.86466471676f,  -0.63212055882f,  -0.0f, 0.0f,
-                                                 1.0f          ,             2.0f,   3.0f, 4.0f };
+                                                 1.0f          ,   2.0f          ,   3.0f, 4.0f };
 
     float qScale = 1.0f;
     int32_t qOffset = 0;
@@ -140,4 +142,33 @@
                                       descriptor);
 }
 
+/** Executes an end to end test for HardSwish activation with specific input and expected-output data
+ *
+ * @tparam ArmnnType  The armnn data type for the input and expected-output data
+ * @param backends  The backends on which to run the test
+ */
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+void HardSwishEndToEndTest(const std::vector<BackendId>& backends)
+{
+    std::vector<float> floatInputData{ -2.0f, -1.0f, -0.5f, 0.0f,
+                                       1.0f,  2.0f,  3.0f, 4.0f };
+
+    std::vector<float> floatExpectedOutputData{ -0.33333333333f,  -0.33333333333f, -0.208333f, 0.0f,
+                                                 0.66666666667f,   1.66666666667f,  3.0f     , 4.0f };
+
+    float qScale = 1.0f;
+    int32_t qOffset = 0;
+    armnn::TensorInfo inputInfo({ 2, 2, 2, 1 }, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo outputInfo({ 2, 2, 2, 1 }, ArmnnType, qScale, qOffset);
+
+    armnn::ActivationDescriptor descriptor(ActivationFunction::HardSwish, 1.0);
+
+    ActivationEndToEndImpl<ArmnnType>(backends,
+                                      floatInputData,
+                                      floatExpectedOutputData,
+                                      inputInfo,
+                                      outputInfo,
+                                      descriptor);
+}
+
 } // anonymous namespace
\ No newline at end of file
diff --git a/src/backends/cl/test/ClEndToEndTests.cpp b/src/backends/cl/test/ClEndToEndTests.cpp
index 8b4fbbb..5a9cf39 100644
--- a/src/backends/cl/test/ClEndToEndTests.cpp
+++ b/src/backends/cl/test/ClEndToEndTests.cpp
@@ -182,6 +182,32 @@
                                                                   expectedOutput);
 }
 
+// HardSwish
+BOOST_AUTO_TEST_CASE(ClHardSwishEndToEndTestFloat32)
+{
+    HardSwishEndToEndTest<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(ClHardSwishEndToEndTestFloat16)
+{
+    HardSwishEndToEndTest<armnn::DataType::Float16>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(ClHardSwishEndToEndTestQAsymmS8)
+{
+    HardSwishEndToEndTest<armnn::DataType::QAsymmS8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(ClHardSwishEndToEndTestQAsymmU8)
+{
+    HardSwishEndToEndTest<armnn::DataType::QAsymmU8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(ClHardSwishEndToEndTestQSymmS16)
+{
+    HardSwishEndToEndTest<armnn::DataType::QSymmS16>(defaultBackends);
+}
+
 // InstanceNormalization
 BOOST_AUTO_TEST_CASE(ClInstanceNormalizationNhwcEndToEndTest1)
 {
diff --git a/src/backends/neon/test/NeonEndToEndTests.cpp b/src/backends/neon/test/NeonEndToEndTests.cpp
index b2c43e1..487aaeb 100644
--- a/src/backends/neon/test/NeonEndToEndTests.cpp
+++ b/src/backends/neon/test/NeonEndToEndTests.cpp
@@ -218,6 +218,27 @@
     EluEndToEndTest<armnn::DataType::Float16>(defaultBackends);
 }
 
+// HardSwish
+BOOST_AUTO_TEST_CASE(NeonHardSwishEndToEndTestFloat32)
+{
+    HardSwishEndToEndTest<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(NeonHardSwishEndToEndTestFloat16)
+{
+    HardSwishEndToEndTest<armnn::DataType::Float16>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(NeonHardSwishEndToEndTestQAsymmS8)
+{
+    HardSwishEndToEndTest<armnn::DataType::QAsymmS8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(NeonHardSwishEndToEndTestQAsymmU8)
+{
+    HardSwishEndToEndTest<armnn::DataType::QAsymmU8>(defaultBackends);
+}
+
 BOOST_AUTO_TEST_CASE(NeonPreluEndToEndFloat32Test)
 {
     PreluEndToEndNegativeTest<armnn::DataType::Float32>(defaultBackends);
diff --git a/src/backends/reference/test/RefEndToEndTests.cpp b/src/backends/reference/test/RefEndToEndTests.cpp
index 83f947c..9c10a68 100644
--- a/src/backends/reference/test/RefEndToEndTests.cpp
+++ b/src/backends/reference/test/RefEndToEndTests.cpp
@@ -837,6 +837,37 @@
                                                                           1.0f, 1, 0.01f, 0, 0.5f, 0);
 }
 
+// HardSwish
+BOOST_AUTO_TEST_CASE(RefHardSwishEndToEndTestFloat32)
+{
+    HardSwishEndToEndTest<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(RefHardSwishEndToEndTestFloat16)
+{
+    HardSwishEndToEndTest<armnn::DataType::Float16>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(RefHardSwishEndToEndTestBFloat16)
+{
+HardSwishEndToEndTest<armnn::DataType::BFloat16>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(RefHardSwishEndToEndTestQAsymmS8)
+{
+    HardSwishEndToEndTest<armnn::DataType::QAsymmS8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(RefHardSwishEndToEndTestQAsymmU8)
+{
+    HardSwishEndToEndTest<armnn::DataType::QAsymmU8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(RefHardSwishEndToEndTestQSymmS16)
+{
+    HardSwishEndToEndTest<armnn::DataType::QSymmS16>(defaultBackends);
+}
+
 // LogSoftmax
 BOOST_AUTO_TEST_CASE(RefLogSoftmaxEndToEndTest)
 {