IVGCVSW-2982 Refactor reference Activation workload

Change-Id: Ia3b9a56787cc68822a3c1635de82e03ecc0aae27
Signed-off-by: Nattapat Chaimanowong <nattapat.chaimanowong@arm.com>
diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp
index b1c3ad7..8887bb7 100644
--- a/src/backends/reference/RefWorkloadFactory.cpp
+++ b/src/backends/reference/RefWorkloadFactory.cpp
@@ -113,7 +113,11 @@
 std::unique_ptr<IWorkload> RefWorkloadFactory::CreateActivation(const ActivationQueueDescriptor& descriptor,
                                                                 const WorkloadInfo&              info) const
 {
-    return MakeWorkload<RefActivationFloat32Workload, RefActivationUint8Workload>(descriptor, info);
+    if (IsFloat16(info))
+    {
+        return MakeWorkload<NullWorkload, NullWorkload>(descriptor, info);
+    }
+    return std::make_unique<RefActivationWorkload>(descriptor, info);
 }
 
 std::unique_ptr<IWorkload> RefWorkloadFactory::CreateSoftmax(const SoftmaxQueueDescriptor& descriptor,
diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk
index e74e853..06459ed 100644
--- a/src/backends/reference/backend.mk
+++ b/src/backends/reference/backend.mk
@@ -24,8 +24,7 @@
         workloads/Merger.cpp \
         workloads/Pad.cpp \
         workloads/Pooling2d.cpp \
-        workloads/RefActivationFloat32Workload.cpp \
-        workloads/RefActivationUint8Workload.cpp \
+        workloads/RefActivationWorkload.cpp \
         workloads/RefBatchNormalizationFloat32Workload.cpp \
         workloads/RefBatchNormalizationUint8Workload.cpp \
         workloads/RefBatchToSpaceNdFloat32Workload.cpp \
diff --git a/src/backends/reference/test/RefCreateWorkloadTests.cpp b/src/backends/reference/test/RefCreateWorkloadTests.cpp
index 4b4e544..5da1f94 100644
--- a/src/backends/reference/test/RefCreateWorkloadTests.cpp
+++ b/src/backends/reference/test/RefCreateWorkloadTests.cpp
@@ -55,12 +55,12 @@
 
 BOOST_AUTO_TEST_CASE(CreateActivationFloat32Workload)
 {
-    RefCreateActivationWorkloadTest<RefActivationFloat32Workload, armnn::DataType::Float32>();
+    RefCreateActivationWorkloadTest<RefActivationWorkload, armnn::DataType::Float32>();
 }
 
 BOOST_AUTO_TEST_CASE(CreateActivationUint8Workload)
 {
-    RefCreateActivationWorkloadTest<RefActivationUint8Workload, armnn::DataType::QuantisedAsymm8>();
+    RefCreateActivationWorkloadTest<RefActivationWorkload, armnn::DataType::QuantisedAsymm8>();
 }
 
 template <typename WorkloadType,
@@ -527,13 +527,13 @@
 
 BOOST_AUTO_TEST_CASE(CreateSingleOutputMultipleInputsFloat32)
 {
-    RefCreateSingleOutputMultipleInputsTest<RefSplitterFloat32Workload, RefActivationFloat32Workload,
+    RefCreateSingleOutputMultipleInputsTest<RefSplitterFloat32Workload, RefActivationWorkload,
         armnn::DataType::Float32>();
 }
 
 BOOST_AUTO_TEST_CASE(CreateSingleOutputMultipleInputsUint8)
 {
-    RefCreateSingleOutputMultipleInputsTest<RefSplitterUint8Workload, RefActivationUint8Workload,
+    RefCreateSingleOutputMultipleInputsTest<RefSplitterUint8Workload, RefActivationWorkload,
         armnn::DataType::QuantisedAsymm8>();
 }
 
diff --git a/src/backends/reference/workloads/Activation.cpp b/src/backends/reference/workloads/Activation.cpp
index ef49030..760c9a0 100644
--- a/src/backends/reference/workloads/Activation.cpp
+++ b/src/backends/reference/workloads/Activation.cpp
@@ -11,6 +11,91 @@
 
 namespace armnn
 {
+float Activation(float in,
+                 ActivationFunction function,
+                 float a,
+                 float b)
+{
+    float output;
+
+    // Compute the result of the activation function.
+    switch (function)
+    {
+        case ActivationFunction::Linear:
+        {
+            output = a * in + b;
+            break;
+        }
+        case ActivationFunction::Sigmoid:
+        {
+            output = 1.f / (1.f + expf(-in));
+            break;
+        }
+        case ActivationFunction::ReLu:
+        {
+            output = std::max(0.f, in);
+            break;
+        }
+        case ActivationFunction::BoundedReLu:
+        {
+            output = std::min(a, std::max(b, in));
+            break;
+        }
+        case ActivationFunction::SoftReLu:
+        {
+            output = logf(1.0f + expf(in));
+            break;
+        }
+        case ActivationFunction::LeakyReLu:
+        {
+            output = in > 0.0f ? in : (in * a);
+            break;
+        }
+        case ActivationFunction::Abs:
+        {
+            output = in < 0 ? -in : in;
+            break;
+        }
+        case ActivationFunction::Sqrt:
+        {
+            output = sqrtf(in);
+            break;
+        }
+        case ActivationFunction::Square:
+        {
+            output = in * in;
+            break;
+        }
+        case ActivationFunction::TanH:
+        {
+            output = a * tanhf(b * in);
+            break;
+        }
+        default:
+        {
+            throw InvalidArgumentException("Unsupported activation function");
+        }
+    }
+
+    return output;
+}
+
+
+void Activation(Decoder<float>& in,
+                Encoder<float>& out,
+                const TensorInfo& tensorInfo,
+                ActivationFunction function,
+                float a,
+                float b)
+{
+    for (size_t i = 0; i<tensorInfo.GetNumElements(); i++)
+    {
+        out.Set(Activation(in.Get(), function, a, b));
+
+        ++in;
+        ++out;
+    }
+}
 
 void Activation(const float* in,
                float* out,
@@ -21,70 +106,7 @@
 {
     for (size_t i = 0; i<tensorInfo.GetNumElements(); i++)
     {
-        float input = in[i];
-        float output;
-
-        // Compute the result of the activation function.
-        switch (function)
-        {
-            case ActivationFunction::Linear:
-            {
-                output = a * input + b;
-                break;
-            }
-            case ActivationFunction::Sigmoid:
-            {
-                output = 1.f / (1.f + expf(-input));
-                break;
-            }
-            case ActivationFunction::ReLu:
-            {
-                output = std::max(0.f, input);
-                break;
-            }
-            case ActivationFunction::BoundedReLu:
-            {
-                output = std::min(a, std::max(b, input));
-                break;
-            }
-            case ActivationFunction::SoftReLu:
-            {
-                output = logf(1.0f + expf(input));
-                break;
-            }
-            case ActivationFunction::LeakyReLu:
-            {
-                output = input > 0.0f ? input : (input * a);
-                break;
-            }
-            case ActivationFunction::Abs:
-            {
-                output = input < 0 ? -input : input;
-                break;
-            }
-            case ActivationFunction::Sqrt:
-            {
-                output = sqrtf(input);
-                break;
-            }
-            case ActivationFunction::Square:
-            {
-                output = input * input;
-                break;
-            }
-            case ActivationFunction::TanH:
-            {
-                output = a * tanhf(b * input);
-                break;
-            }
-            default:
-            {
-                BOOST_LOG_TRIVIAL(error) << "Unsupported activation function";
-                return;
-            }
-        }
-
-        out[i] = output;
+        out[i] = Activation(in[i], function, a, b);
     }
 }
 
diff --git a/src/backends/reference/workloads/Activation.hpp b/src/backends/reference/workloads/Activation.hpp
index c8a2311..ffe3c5f 100644
--- a/src/backends/reference/workloads/Activation.hpp
+++ b/src/backends/reference/workloads/Activation.hpp
@@ -3,18 +3,30 @@
 // SPDX-License-Identifier: MIT
 //
 
+#include "BaseIterator.hpp"
+
 #include <armnn/Tensor.hpp>
 #include <armnn/Types.hpp>
 
 namespace armnn
 {
+float Activation(float in,
+                 ActivationFunction function,
+                 float a,
+                 float b);
 
-/// Performs the ActivationFunction elementwise on the inputs to give the outputs.
+void Activation(Decoder<float>& in,
+                Encoder<float>& out,
+                const TensorInfo& tensorInfo,
+                ActivationFunction function,
+                float a,
+                float b);
+
+// This is still used by Reference LSTM implementation
 void Activation(const float* in,
                 float* out,
                 const TensorInfo& tensorInfo,
                 ActivationFunction function,
                 float a,
                 float b);
-
 } //namespace armnn
diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt
index e94b031..596c099 100644
--- a/src/backends/reference/workloads/CMakeLists.txt
+++ b/src/backends/reference/workloads/CMakeLists.txt
@@ -34,10 +34,8 @@
     Pad.hpp
     Pooling2d.cpp
     Pooling2d.hpp
-    RefActivationFloat32Workload.cpp
-    RefActivationFloat32Workload.hpp
-    RefActivationUint8Workload.cpp
-    RefActivationUint8Workload.hpp
+    RefActivationWorkload.cpp
+    RefActivationWorkload.hpp
     RefBatchNormalizationFloat32Workload.cpp
     RefBatchNormalizationFloat32Workload.hpp
     RefBatchNormalizationUint8Workload.cpp
diff --git a/src/backends/reference/workloads/Decoders.hpp b/src/backends/reference/workloads/Decoders.hpp
index 4112e7d..acf20c4 100644
--- a/src/backends/reference/workloads/Decoders.hpp
+++ b/src/backends/reference/workloads/Decoders.hpp
@@ -11,10 +11,10 @@
 {
 
 template<typename T>
-std::unique_ptr<Decoder<T>> MakeDecoder(const TensorInfo& info, const void* data);
+inline std::unique_ptr<Decoder<T>> MakeDecoder(const TensorInfo& info, const void* data);
 
 template<>
-std::unique_ptr<Decoder<float>> MakeDecoder(const TensorInfo& info, const void* data)
+inline std::unique_ptr<Decoder<float>> MakeDecoder(const TensorInfo& info, const void* data)
 {
     switch(info.GetDataType())
     {
@@ -45,4 +45,4 @@
     return nullptr;
 }
 
-} //namespace armnn
\ No newline at end of file
+} //namespace armnn
diff --git a/src/backends/reference/workloads/Encoders.hpp b/src/backends/reference/workloads/Encoders.hpp
index 90300aa..547bead 100644
--- a/src/backends/reference/workloads/Encoders.hpp
+++ b/src/backends/reference/workloads/Encoders.hpp
@@ -11,10 +11,10 @@
 {
 
 template<typename T>
-std::unique_ptr<Encoder<T>> MakeEncoder(const TensorInfo& info, void* data);
+inline std::unique_ptr<Encoder<T>> MakeEncoder(const TensorInfo& info, void* data);
 
 template<>
-std::unique_ptr<Encoder<float>> MakeEncoder(const TensorInfo& info, void* data)
+inline std::unique_ptr<Encoder<float>> MakeEncoder(const TensorInfo& info, void* data)
 {
     switch(info.GetDataType())
     {
@@ -46,7 +46,7 @@
 }
 
 template<>
-std::unique_ptr<Encoder<bool>> MakeEncoder(const TensorInfo& info, void* data)
+inline std::unique_ptr<Encoder<bool>> MakeEncoder(const TensorInfo& info, void* data)
 {
     switch(info.GetDataType())
     {
@@ -63,4 +63,4 @@
     return nullptr;
 }
 
-} //namespace armnn
\ No newline at end of file
+} //namespace armnn
diff --git a/src/backends/reference/workloads/RefActivationFloat32Workload.cpp b/src/backends/reference/workloads/RefActivationFloat32Workload.cpp
deleted file mode 100644
index 3cc59be..0000000
--- a/src/backends/reference/workloads/RefActivationFloat32Workload.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright © 2017 Arm Ltd. All rights reserved.
-// SPDX-License-Identifier: MIT
-//
-
-#include "RefActivationFloat32Workload.hpp"
-
-#include "Activation.hpp"
-#include "RefWorkloadUtils.hpp"
-
-#include "Profiling.hpp"
-
-namespace armnn
-{
-
-void RefActivationFloat32Workload::Execute() const
-{
-    ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefActivationFloat32Workload_Execute");
-
-    Activation(GetInputTensorDataFloat(0, m_Data),
-               GetOutputTensorDataFloat(0, m_Data),
-               GetTensorInfo(m_Data.m_Inputs[0]),
-               m_Data.m_Parameters.m_Function,
-               m_Data.m_Parameters.m_A,
-               m_Data.m_Parameters.m_B);
-}
-
-} //namespace armnn
diff --git a/src/backends/reference/workloads/RefActivationFloat32Workload.hpp b/src/backends/reference/workloads/RefActivationFloat32Workload.hpp
deleted file mode 100644
index dd65697..0000000
--- a/src/backends/reference/workloads/RefActivationFloat32Workload.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Copyright © 2017 Arm Ltd. All rights reserved.
-// SPDX-License-Identifier: MIT
-//
-
-#pragma once
-
-#include <backendsCommon/Workload.hpp>
-
-namespace armnn
-{
-
-class RefActivationFloat32Workload : public Float32Workload<ActivationQueueDescriptor>
-{
-public:
-    using Float32Workload<ActivationQueueDescriptor>::Float32Workload;
-    virtual void Execute() const override;
-};
-
-} //namespace armnn
diff --git a/src/backends/reference/workloads/RefActivationUint8Workload.cpp b/src/backends/reference/workloads/RefActivationUint8Workload.cpp
deleted file mode 100644
index b95c2e2..0000000
--- a/src/backends/reference/workloads/RefActivationUint8Workload.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright © 2017 Arm Ltd. All rights reserved.
-// SPDX-License-Identifier: MIT
-//
-
-#include "RefActivationUint8Workload.hpp"
-
-#include "Activation.hpp"
-#include "RefWorkloadUtils.hpp"
-
-#include "Profiling.hpp"
-
-#include <vector>
-
-namespace armnn
-{
-
-void RefActivationUint8Workload::Execute() const
-{
-    ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefActivationUint8Workload_Execute");
-
-    const TensorInfo& tensorInfo = GetTensorInfo(m_Data.m_Inputs[0]);
-
-    auto dequant = Dequantize(GetInputTensorDataU8(0, m_Data), tensorInfo);
-
-    std::vector<float> results(tensorInfo.GetNumElements());
-
-    Activation(dequant.data(),
-               results.data(),
-               tensorInfo,
-               m_Data.m_Parameters.m_Function,
-               m_Data.m_Parameters.m_A,
-               m_Data.m_Parameters.m_B);
-
-    Quantize(GetOutputTensorDataU8(0, m_Data), results.data(), GetTensorInfo(m_Data.m_Outputs[0]));
-}
-
-} //namespace armnn
diff --git a/src/backends/reference/workloads/RefActivationWorkload.cpp b/src/backends/reference/workloads/RefActivationWorkload.cpp
new file mode 100644
index 0000000..78c971e
--- /dev/null
+++ b/src/backends/reference/workloads/RefActivationWorkload.cpp
@@ -0,0 +1,33 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "RefActivationWorkload.hpp"
+
+#include "Activation.hpp"
+#include "Decoders.hpp"
+#include "Encoders.hpp"
+#include "RefWorkloadUtils.hpp"
+
+#include "Profiling.hpp"
+
+namespace armnn
+{
+
+void RefActivationWorkload::Execute() const
+{
+    ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefActivationWorkload_Execute");
+
+    const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]);
+    const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]);
+
+    Activation(*MakeDecoder<float>(inputInfo, m_Data.m_Inputs[0]->Map()),
+               *MakeEncoder<float>(outputInfo, m_Data.m_Outputs[0]->Map()),
+               inputInfo,
+               m_Data.m_Parameters.m_Function,
+               m_Data.m_Parameters.m_A,
+               m_Data.m_Parameters.m_B);
+}
+
+} //namespace armnn
diff --git a/src/backends/reference/workloads/RefActivationUint8Workload.hpp b/src/backends/reference/workloads/RefActivationWorkload.hpp
similarity index 65%
rename from src/backends/reference/workloads/RefActivationUint8Workload.hpp
rename to src/backends/reference/workloads/RefActivationWorkload.hpp
index 66f5e32..a3b001e 100644
--- a/src/backends/reference/workloads/RefActivationUint8Workload.hpp
+++ b/src/backends/reference/workloads/RefActivationWorkload.hpp
@@ -11,10 +11,10 @@
 namespace armnn
 {
 
-class RefActivationUint8Workload : public Uint8Workload<ActivationQueueDescriptor>
+class RefActivationWorkload : public BaseWorkload<ActivationQueueDescriptor>
 {
 public:
-    using Uint8Workload<ActivationQueueDescriptor>::Uint8Workload;
+    using BaseWorkload<ActivationQueueDescriptor>::BaseWorkload;
     virtual void Execute() const override;
 };
 
diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp
index a1b5847..7871a1b 100644
--- a/src/backends/reference/workloads/RefWorkloads.hpp
+++ b/src/backends/reference/workloads/RefWorkloads.hpp
@@ -13,7 +13,7 @@
 #include "RefSplitterUint8Workload.hpp"
 #include "RefResizeBilinearUint8Workload.hpp"
 #include "RefL2NormalizationFloat32Workload.hpp"
-#include "RefActivationUint8Workload.hpp"
+#include "RefActivationWorkload.hpp"
 #include "RefPooling2dFloat32Workload.hpp"
 #include "RefWorkloadUtils.hpp"
 #include "RefMergerUint8Workload.hpp"
@@ -47,7 +47,6 @@
 #include "RefSpaceToBatchNdWorkload.hpp"
 #include "RefSplitterFloat32Workload.hpp"
 #include "RefStridedSliceWorkload.hpp"
-#include "RefActivationFloat32Workload.hpp"
 #include "RefConvolution2dFloat32Workload.hpp"
 #include "Pooling2d.hpp"
 #include "RefFakeQuantizationFloat32Workload.hpp"
@@ -64,4 +63,4 @@
 #include "RefRsqrtFloat32Workload.hpp"
 #include "RefDequantizeWorkload.hpp"
 
-#include "RefQuantizeWorkload.hpp"
\ No newline at end of file
+#include "RefQuantizeWorkload.hpp"