COMPMID-415: Move ActivationLayer to new validation

Change-Id: I38ce20d95640f9c1baf699a095c35e592ad4339f
Reviewed-on: http://mpd-gerrit.cambridge.arm.com/81115
Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
Tested-by: Kaizen <jeremy.johnson+kaizengerrit@arm.com>
diff --git a/tests/validation_new/CL/ActivationLayer.cpp b/tests/validation_new/CL/ActivationLayer.cpp
new file mode 100644
index 0000000..e1cc4e5
--- /dev/null
+++ b/tests/validation_new/CL/ActivationLayer.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/core/Types.h"
+#include "arm_compute/runtime/CL/CLTensor.h"
+#include "arm_compute/runtime/CL/CLTensorAllocator.h"
+#include "arm_compute/runtime/CL/functions/CLActivationLayer.h"
+#include "framework/Asserts.h"
+#include "framework/Macros.h"
+#include "framework/datasets/Datasets.h"
+#include "tests/CL/CLAccessor.h"
+#include "tests/PaddingCalculator.h"
+#include "tests/datasets_new/ActivationFunctionsDataset.h"
+#include "tests/datasets_new/ShapeDatasets.h"
+#include "tests/validation_new/Validation.h"
+#include "tests/validation_new/fixtures/ActivationLayerFixture.h"
+#include "tests/validation_new/half.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace
+{
+/** Define tolerance of the activation layer.
+ *
+ * @param[in] activation The activation function used.
+ * @param[in] data_type  Data type.
+ *
+ * @return Tolerance depending on the activation function.
+ */
+float tolerance(ActivationLayerInfo::ActivationFunction activation, DataType data_type)
+{
+    switch(activation)
+    {
+        case ActivationLayerInfo::ActivationFunction::LINEAR:
+            return data_type == DataType::F16 ? 0.2f : 0.f;
+        case ActivationLayerInfo::ActivationFunction::SQUARE:
+            return data_type == DataType::F16 ? 0.1f : 0.f;
+        case ActivationLayerInfo::ActivationFunction::LOGISTIC:
+            if(is_data_type_fixed_point(data_type))
+            {
+                return 5.f;
+            }
+            else
+            {
+                return data_type == DataType::F16 ? 0.001f : 0.f;
+            }
+        case ActivationLayerInfo::ActivationFunction::LEAKY_RELU:
+            return data_type == DataType::F16 ? 0.00001f : 0.f;
+        case ActivationLayerInfo::ActivationFunction::SOFT_RELU:
+        case ActivationLayerInfo::ActivationFunction::SQRT:
+            if(is_data_type_fixed_point(data_type))
+            {
+                return 5.f;
+            }
+            else
+            {
+                return data_type == DataType::F16 ? 0.01f : 0.00001f;
+            }
+        case ActivationLayerInfo::ActivationFunction::TANH:
+            if(is_data_type_fixed_point(data_type))
+            {
+                return 5.f;
+            }
+            else
+            {
+                return data_type == DataType::F16 ? 0.001f : 0.00001f;
+            }
+        default:
+            return 0.f;
+    }
+}
+
+/** CNN data types */
+const auto CNNDataTypes = framework::dataset::make("DataType",
+{
+    DataType::F16,
+    DataType::F32,
+    DataType::QS8,
+    DataType::QS16,
+});
+
+/** Input data sets. */
+const auto ActivationDataset = combine(combine(framework::dataset::make("InPlace", { false, true }), datasets::ActivationFunctions()), framework::dataset::make("AlphaBeta", { 0.5f, 1.f }));
+} // namespace
+
+TEST_SUITE(CL)
+TEST_SUITE(ActivationLayer)
+
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), CNNDataTypes), framework::dataset::make("InPlace", { false, true })),
+               shape, data_type, in_place)
+{
+    // Set fixed point position data type allowed
+    const int fixed_point_position = is_data_type_fixed_point(data_type) ? 3 : 0;
+
+    // Create tensors
+    CLTensor src = create_tensor<CLTensor>(shape, data_type, 1, fixed_point_position);
+    CLTensor dst = create_tensor<CLTensor>(shape, data_type, 1, fixed_point_position);
+
+    ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
+    ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+    // Create and configure function
+    CLActivationLayer act_layer;
+
+    if(in_place)
+    {
+        act_layer.configure(&src, nullptr, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::ABS));
+    }
+    else
+    {
+        act_layer.configure(&src, &dst, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::ABS));
+    }
+
+    // Validate valid region
+    const ValidRegion valid_region = shape_to_valid_region(shape);
+    validate(src.info()->valid_region(), valid_region);
+
+    if(!in_place)
+    {
+        validate(dst.info()->valid_region(), valid_region);
+    }
+
+    // Validate padding
+    const int         step    = 16 / arm_compute::data_size_from_type(data_type);
+    const PaddingSize padding = PaddingCalculator(shape.x(), step).required_padding();
+    validate(src.info()->padding(), padding);
+
+    if(!in_place)
+    {
+        validate(dst.info()->padding(), padding);
+    }
+}
+
+template <typename T>
+using CLActivationLayerFixture = ActivationValidationFixture<CLTensor, CLAccessor, CLActivationLayer, T>;
+
+TEST_SUITE(Float)
+TEST_SUITE(FP16)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLActivationLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), ActivationDataset),
+                                                                                                                        framework::dataset::make("DataType",
+                                                                                                                                DataType::F16)))
+{
+    // Validate output
+    validate(CLAccessor(_target), _reference, tolerance(_function, _data_type));
+}
+FIXTURE_DATA_TEST_CASE(RunLarge, CLActivationLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), ActivationDataset),
+                                                                                                                      framework::dataset::make("DataType",
+                                                                                                                              DataType::F16)))
+{
+    // Validate output
+    validate(CLAccessor(_target), _reference, tolerance(_function, _data_type));
+}
+TEST_SUITE_END()
+
+TEST_SUITE(FP32)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLActivationLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), ActivationDataset), framework::dataset::make("DataType",
+                                                                                                             DataType::F32)))
+{
+    // Validate output
+    validate(CLAccessor(_target), _reference, tolerance(_function, _data_type));
+}
+FIXTURE_DATA_TEST_CASE(RunLarge, CLActivationLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), ActivationDataset), framework::dataset::make("DataType",
+                                                                                                           DataType::F32)))
+{
+    // Validate output
+    validate(CLAccessor(_target), _reference, tolerance(_function, _data_type));
+}
+TEST_SUITE_END()
+TEST_SUITE_END()
+
+template <typename T>
+using CLActivationLayerFixedPointFixture = ActivationValidationFixedPointFixture<CLTensor, CLAccessor, CLActivationLayer, T>;
+
+TEST_SUITE(Quantized)
+TEST_SUITE(QS8)
+// We test for fixed point precision [3,5] because [1,2] and [6,7] ranges cause
+// overflowing issues in most of the transcendentals functions.
+FIXTURE_DATA_TEST_CASE(RunSmall, CLActivationLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), ActivationDataset),
+                                                                                                                        framework::dataset::make("DataType",
+                                                                                                                                DataType::QS8)),
+                                                                                                                        framework::dataset::make("FractionalBits", 3, 6)))
+{
+    // Validate output
+    validate(CLAccessor(_target), _reference, tolerance(_function, _data_type));
+}
+FIXTURE_DATA_TEST_CASE(RunLarge, CLActivationLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), ActivationDataset),
+                                                                                                                      framework::dataset::make("DataType",
+                                                                                                                              DataType::QS8)),
+                                                                                                                      framework::dataset::make("FractionalBits", 3, 6)))
+{
+    // Validate output
+    validate(CLAccessor(_target), _reference, tolerance(_function, _data_type));
+}
+TEST_SUITE_END()
+
+TEST_SUITE(QS16)
+// Testing for fixed point position [1,14) as reciprocal limits the maximum fixed point position to 14
+FIXTURE_DATA_TEST_CASE(RunSmall, CLActivationLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), ActivationDataset),
+                       framework::dataset::make("DataType",
+                                                DataType::QS16)),
+                       framework::dataset::make("FractionalBits", 1, 14)))
+{
+    // Validate output
+    validate(CLAccessor(_target), _reference, tolerance(_function, _data_type));
+}
+FIXTURE_DATA_TEST_CASE(RunLarge, CLActivationLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), ActivationDataset),
+                                                                                                                       framework::dataset::make("DataType",
+                                                                                                                               DataType::QS16)),
+                                                                                                                       framework::dataset::make("FractionalBits", 1, 14)))
+{
+    // Validate output
+    validate(CLAccessor(_target), _reference, tolerance(_function, _data_type));
+}
+TEST_SUITE_END()
+TEST_SUITE_END()
+
+TEST_SUITE_END()
+TEST_SUITE_END()
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation_new/CPP/ActivationLayer.cpp b/tests/validation_new/CPP/ActivationLayer.cpp
new file mode 100644
index 0000000..052c3aa
--- /dev/null
+++ b/tests/validation_new/CPP/ActivationLayer.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "ActivationLayer.h"
+
+#include "tests/validation_new/FixedPoint.h"
+#include "tests/validation_new/Helpers.h"
+#include "tests/validation_new/half.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type>
+SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo info)
+{
+    // Create reference
+    SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() };
+
+    // Compute reference
+    const T a(info.a());
+    const T b(info.b());
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        T x = src[i];
+
+        switch(info.activation())
+        {
+            case ActivationLayerInfo::ActivationFunction::ABS:
+                dst[i] = std::abs(x);
+                break;
+            case ActivationLayerInfo::ActivationFunction::LINEAR:
+                dst[i] = a * x + b;
+                break;
+            case ActivationLayerInfo::ActivationFunction::LOGISTIC:
+                dst[i] = static_cast<T>(1) / (static_cast<T>(1) + std::exp(-x));
+                break;
+            case ActivationLayerInfo::ActivationFunction::RELU:
+                dst[i] = std::max<T>(static_cast<T>(0), x);
+                break;
+            case ActivationLayerInfo::ActivationFunction::BOUNDED_RELU:
+                dst[i] = std::min<T>(a, std::max(static_cast<T>(0), x));
+                break;
+            case ActivationLayerInfo::ActivationFunction::LEAKY_RELU:
+                dst[i] = (x > 0) ? x : a * x;
+                break;
+            case ActivationLayerInfo::ActivationFunction::SOFT_RELU:
+                dst[i] = std::log(static_cast<T>(1) + std::exp(x));
+                break;
+            case ActivationLayerInfo::ActivationFunction::SQRT:
+                dst[i] = std::sqrt(x);
+                break;
+            case ActivationLayerInfo::ActivationFunction::SQUARE:
+                dst[i] = x * x;
+                break;
+            case ActivationLayerInfo::ActivationFunction::TANH:
+                dst[i] = a * std::tanh(b * x);
+                break;
+            default:
+                ARM_COMPUTE_ERROR("Unsupported activation function");
+        }
+    }
+
+    return dst;
+}
+
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type>
+SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo info)
+{
+    using namespace fixed_point_arithmetic;
+
+    // Create reference
+    SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() };
+
+    // Compute reference
+    const int            fixed_point_position = src.fixed_point_position();
+    const fixed_point<T> a(info.a(), fixed_point_position);
+    const fixed_point<T> b(info.b(), fixed_point_position);
+    const fixed_point<T> const_0(0, fixed_point_position);
+    const fixed_point<T> const_1(1, fixed_point_position);
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        fixed_point<T> x(src[i], fixed_point_position, true);
+
+        switch(info.activation())
+        {
+            case ActivationLayerInfo::ActivationFunction::ABS:
+                dst[i] = abs(x).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::LINEAR:
+                dst[i] = add(b, mul(a, x)).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::LOGISTIC:
+                dst[i] = (const_1 / (const_1 + exp(-x))).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::RELU:
+                dst[i] = max(const_0, x).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::BOUNDED_RELU:
+                dst[i] = min(a, max(const_0, x)).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::LEAKY_RELU:
+                dst[i] = (x > const_0) ? x.raw() : mul(a, x).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::SOFT_RELU:
+                dst[i] = log(const_1 + exp(x)).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::SQRT:
+                dst[i] = (const_1 / inv_sqrt(x)).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::SQUARE:
+                dst[i] = mul(x, x).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::TANH:
+                dst[i] = mul(a, tanh(mul(b, x))).raw();
+                break;
+            default:
+                ARM_COMPUTE_ERROR("Unsupported activation function");
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<float> activation_layer(const SimpleTensor<float> &src, ActivationLayerInfo info);
+template SimpleTensor<half_float::half> activation_layer(const SimpleTensor<half_float::half> &src, ActivationLayerInfo info);
+template SimpleTensor<qint8_t> activation_layer(const SimpleTensor<qint8_t> &src, ActivationLayerInfo info);
+template SimpleTensor<qint16_t> activation_layer(const SimpleTensor<qint16_t> &src, ActivationLayerInfo info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation_new/CPP/ActivationLayer.h b/tests/validation_new/CPP/ActivationLayer.h
new file mode 100644
index 0000000..5f4ef46
--- /dev/null
+++ b/tests/validation_new/CPP/ActivationLayer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_ACTIVATION_LAYER_H__
+#define __ARM_COMPUTE_TEST_ACTIVATION_LAYER_H__
+
+#include "tests/validation_new/Helpers.h"
+#include "tests/validation_new/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0>
+SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo info);
+
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
+SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_ACTIVATION_LAYER_H__ */
diff --git a/tests/validation_new/Helpers.h b/tests/validation_new/Helpers.h
index e25b684..3058b8e 100644
--- a/tests/validation_new/Helpers.h
+++ b/tests/validation_new/Helpers.h
@@ -24,9 +24,13 @@
 #ifndef __ARM_COMPUTE_TEST_VALIDATION_HELPERS_H__
 #define __ARM_COMPUTE_TEST_VALIDATION_HELPERS_H__
 
+#include "arm_compute/core/Types.h"
+#include "arm_compute/core/Utils.h"
 #include "tests/validation/half.h"
 
+#include <random>
 #include <type_traits>
+#include <utility>
 
 namespace arm_compute
 {
@@ -43,6 +47,87 @@
 struct is_floating_point<half_float::half> : public std::true_type
 {
 };
+
+/** Helper function to get the testing range for each activation layer.
+ *
+ * @param[in] activation           Activation function to test.
+ * @param[in] data_type            Data type.
+ * @param[in] fixed_point_position Number of bits for the fractional part. Defaults to 1.
+ *
+ * @return A pair containing the lower upper testing bounds for a given function.
+ */
+template <typename T>
+std::pair<T, T> get_activation_layer_test_bounds(ActivationLayerInfo::ActivationFunction activation, DataType data_type, int fixed_point_position = 0)
+{
+    std::pair<T, T> bounds;
+
+    switch(data_type)
+    {
+        case DataType::F16:
+        {
+            using namespace half_float::literal;
+
+            switch(activation)
+            {
+                case ActivationLayerInfo::ActivationFunction::SQUARE:
+                case ActivationLayerInfo::ActivationFunction::LOGISTIC:
+                case ActivationLayerInfo::ActivationFunction::SOFT_RELU:
+                    // Reduce range as exponent overflows
+                    bounds = std::make_pair(-10._h, 10._h);
+                    break;
+                case ActivationLayerInfo::ActivationFunction::SQRT:
+                    // Reduce range as sqrt should take a non-negative number
+                    bounds = std::make_pair(0._h, 255._h);
+                    break;
+                default:
+                    bounds = std::make_pair(-255._h, 255._h);
+                    break;
+            }
+            break;
+        }
+        case DataType::F32:
+            switch(activation)
+            {
+                case ActivationLayerInfo::ActivationFunction::LOGISTIC:
+                case ActivationLayerInfo::ActivationFunction::SOFT_RELU:
+                    // Reduce range as exponent overflows
+                    bounds = std::make_pair(-40.f, 40.f);
+                    break;
+                case ActivationLayerInfo::ActivationFunction::SQRT:
+                    // Reduce range as sqrt should take a non-negative number
+                    bounds = std::make_pair(0.f, 255.f);
+                    break;
+                default:
+                    bounds = std::make_pair(-255.f, 255.f);
+                    break;
+            }
+            break;
+        case DataType::QS8:
+        case DataType::QS16:
+            switch(activation)
+            {
+                case ActivationLayerInfo::ActivationFunction::LOGISTIC:
+                case ActivationLayerInfo::ActivationFunction::SOFT_RELU:
+                case ActivationLayerInfo::ActivationFunction::TANH:
+                    // Reduce range as exponent overflows
+                    bounds = std::make_pair(-(1 << fixed_point_position), 1 << fixed_point_position);
+                    break;
+                case ActivationLayerInfo::ActivationFunction::SQRT:
+                    // Reduce range as sqrt should take a non-negative number
+                    // Can't be zero either as inv_sqrt is used in NEON.
+                    bounds = std::make_pair(1, std::numeric_limits<T>::max());
+                    break;
+                default:
+                    bounds = std::make_pair(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max());
+                    break;
+            }
+            break;
+        default:
+            ARM_COMPUTE_ERROR("Unsupported data type");
+    }
+
+    return bounds;
+}
 } // namespace validation
 } // namespace test
 } // namespace arm_compute
diff --git a/tests/validation_new/NEON/ActivationLayer.cpp b/tests/validation_new/NEON/ActivationLayer.cpp
new file mode 100644
index 0000000..db0faae
--- /dev/null
+++ b/tests/validation_new/NEON/ActivationLayer.cpp
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/core/Types.h"
+#include "arm_compute/runtime/NEON/functions/NEActivationLayer.h"
+#include "arm_compute/runtime/Tensor.h"
+#include "arm_compute/runtime/TensorAllocator.h"
+#include "framework/Asserts.h"
+#include "framework/Macros.h"
+#include "framework/datasets/Datasets.h"
+#include "tests/NEON/Accessor.h"
+#include "tests/PaddingCalculator.h"
+#include "tests/datasets_new/ActivationFunctionsDataset.h"
+#include "tests/datasets_new/ShapeDatasets.h"
+#include "tests/validation_new/Validation.h"
+#include "tests/validation_new/fixtures/ActivationLayerFixture.h"
+#include "tests/validation_new/half.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace
+{
+/** Define tolerance of the activation layer.
+ *
+ * @param[in] data_type  The data type used.
+ * @param[in] activation The activation function used.
+ *
+ * @return Tolerance depending on the activation function.
+ */
+float tolerance(DataType data_type, ActivationLayerInfo::ActivationFunction activation)
+{
+    switch(activation)
+    {
+        case ActivationLayerInfo::ActivationFunction::LOGISTIC:
+        case ActivationLayerInfo::ActivationFunction::SOFT_RELU:
+        case ActivationLayerInfo::ActivationFunction::SQRT:
+        case ActivationLayerInfo::ActivationFunction::TANH:
+            switch(data_type)
+            {
+                case DataType::QS8:
+                    return 5.f;
+                case DataType::QS16:
+                    return 11.f;
+                case DataType::F16:
+                    return 0.01f;
+                default:
+                    return 0.00001f;
+            }
+            break;
+        default:
+            return 0.f;
+    }
+}
+
+/** CNN data types */
+const auto CNNDataTypes = framework::dataset::make("DataType",
+{
+#ifdef ARM_COMPUTE_ENABLE_FP16
+    DataType::F16,
+#endif /* ARM_COMPUTE_ENABLE_FP16 */
+    DataType::F32,
+    DataType::QS8,
+    DataType::QS16,
+});
+
+/** Input data sets. */
+const auto ActivationDataset = combine(combine(framework::dataset::make("InPlace", { false, true }), datasets::ActivationFunctions()), framework::dataset::make("AlphaBeta", { 0.5f, 1.f }));
+} // namespace
+
+TEST_SUITE(NEON)
+TEST_SUITE(ActivationLayer)
+
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), CNNDataTypes), framework::dataset::make("InPlace", { false, true })),
+               shape, data_type, in_place)
+{
+    // Set fixed point position data type allowed
+    const int fixed_point_position = is_data_type_fixed_point(data_type) ? 3 : 0;
+
+    // Create tensors
+    Tensor src = create_tensor<Tensor>(shape, data_type, 1, fixed_point_position);
+    Tensor dst = create_tensor<Tensor>(shape, data_type, 1, fixed_point_position);
+
+    ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
+    ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+    // Create and configure function
+    NEActivationLayer act_layer;
+
+    if(in_place)
+    {
+        act_layer.configure(&src, nullptr, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::ABS));
+    }
+    else
+    {
+        act_layer.configure(&src, &dst, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::ABS));
+    }
+
+    // Validate valid region
+    const ValidRegion valid_region = shape_to_valid_region(shape);
+    validate(src.info()->valid_region(), valid_region);
+
+    if(!in_place)
+    {
+        validate(dst.info()->valid_region(), valid_region);
+    }
+
+    // Validate padding
+    const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding();
+    validate(src.info()->padding(), padding);
+
+    if(!in_place)
+    {
+        validate(dst.info()->padding(), padding);
+    }
+}
+
+template <typename T>
+using NEActivationLayerFixture = ActivationValidationFixture<Tensor, Accessor, NEActivationLayer, T>;
+
+TEST_SUITE(Float)
+#ifdef ARM_COMPUTE_ENABLE_FP16
+TEST_SUITE(FP16)
+FIXTURE_DATA_TEST_CASE(RunSmall, NEActivationLayerFixture<half_float::half>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), ActivationDataset),
+                                                                                                                        framework::dataset::make("DataType",
+                                                                                                                                DataType::F16)))
+{
+    // Validate output
+    validate(Accessor(_target), _reference, tolerance(_data_type, _function));
+}
+FIXTURE_DATA_TEST_CASE(RunLarge, NEActivationLayerFixture<half_float::half>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), ActivationDataset),
+                                                                                                                      framework::dataset::make("DataType",
+                                                                                                                              DataType::F16)))
+{
+    // Validate output
+    validate(Accessor(_target), _reference, tolerance(_data_type, _function));
+}
+TEST_SUITE_END()
+#endif /* ARM_COMPUTE_ENABLE_FP16 */
+
+TEST_SUITE(FP32)
+FIXTURE_DATA_TEST_CASE(RunSmall, NEActivationLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), ActivationDataset), framework::dataset::make("DataType",
+                                                                                                             DataType::F32)))
+{
+    // Validate output
+    validate(Accessor(_target), _reference, tolerance(_data_type, _function));
+}
+FIXTURE_DATA_TEST_CASE(RunLarge, NEActivationLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), ActivationDataset), framework::dataset::make("DataType",
+                                                                                                           DataType::F32)))
+{
+    // Validate output
+    validate(Accessor(_target), _reference, tolerance(_data_type, _function));
+}
+TEST_SUITE_END()
+TEST_SUITE_END()
+
+template <typename T>
+using NEActivationLayerFixedPointFixture = ActivationValidationFixedPointFixture<Tensor, Accessor, NEActivationLayer, T>;
+
+TEST_SUITE(Quantized)
+TEST_SUITE(QS8)
+// We test for fixed point precision [3,5] because [1,2] and [6,7] ranges cause
+// overflowing issues in most of the transcendentals functions.
+FIXTURE_DATA_TEST_CASE(RunSmall, NEActivationLayerFixedPointFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), ActivationDataset),
+                                                                                                                        framework::dataset::make("DataType",
+                                                                                                                                DataType::QS8)),
+                                                                                                                        framework::dataset::make("FractionalBits", 3, 6)))
+{
+    // Validate output
+    validate(Accessor(_target), _reference, tolerance(_data_type, _function));
+}
+FIXTURE_DATA_TEST_CASE(RunLarge, NEActivationLayerFixedPointFixture<int8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), ActivationDataset),
+                                                                                                                      framework::dataset::make("DataType",
+                                                                                                                              DataType::QS8)),
+                                                                                                                      framework::dataset::make("FractionalBits", 3, 6)))
+{
+    // Validate output
+    validate(Accessor(_target), _reference, tolerance(_data_type, _function));
+}
+TEST_SUITE_END()
+
+TEST_SUITE(QS16)
+// Testing for fixed point position [1,14) as reciprocal limits the maximum fixed point position to 14
+FIXTURE_DATA_TEST_CASE(RunSmall, NEActivationLayerFixedPointFixture<int16_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), ActivationDataset),
+                       framework::dataset::make("DataType",
+                                                DataType::QS16)),
+                       framework::dataset::make("FractionalBits", 1, 14)))
+{
+    // Validate output
+    validate(Accessor(_target), _reference, tolerance(_data_type, _function));
+}
+FIXTURE_DATA_TEST_CASE(RunLarge, NEActivationLayerFixedPointFixture<int16_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), ActivationDataset),
+                                                                                                                       framework::dataset::make("DataType",
+                                                                                                                               DataType::QS16)),
+                                                                                                                       framework::dataset::make("FractionalBits", 1, 14)))
+{
+    // Validate output
+    validate(Accessor(_target), _reference, tolerance(_data_type, _function));
+}
+TEST_SUITE_END()
+TEST_SUITE_END()
+
+TEST_SUITE_END()
+TEST_SUITE_END()
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation_new/fixtures/ActivationLayerFixture.h b/tests/validation_new/fixtures/ActivationLayerFixture.h
new file mode 100644
index 0000000..bf0e7ba
--- /dev/null
+++ b/tests/validation_new/fixtures/ActivationLayerFixture.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef ARM_COMPUTE_TEST_ACTIVATION_LAYER_FIXTURE
+#define ARM_COMPUTE_TEST_ACTIVATION_LAYER_FIXTURE
+
+#include "arm_compute/core/TensorShape.h"
+#include "arm_compute/core/Types.h"
+#include "framework/Asserts.h"
+#include "framework/Fixture.h"
+#include "tests/AssetsLibrary.h"
+#include "tests/Globals.h"
+#include "tests/IAccessor.h"
+#include "tests/validation_new/CPP/ActivationLayer.h"
+#include "tests/validation_new/Helpers.h"
+
+#include <random>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
+class ActivationValidationFixedPointFixture : public framework::Fixture
+{
+public:
+    template <typename...>
+    void setup(TensorShape shape, bool in_place, ActivationLayerInfo::ActivationFunction function, float alpha_beta, DataType data_type, int fractional_bits)
+    {
+        _fractional_bits = fractional_bits;
+        _data_type       = data_type;
+        _function        = function;
+
+        ActivationLayerInfo info(function, alpha_beta, alpha_beta);
+
+        _target    = compute_target(shape, in_place, info, data_type, fractional_bits);
+        _reference = compute_reference(shape, info, data_type, fractional_bits);
+    }
+
+protected:
+    template <typename U>
+    void fill(U &&tensor)
+    {
+        if(is_data_type_float(_data_type))
+        {
+            float min_bound = 0;
+            float max_bound = 0;
+            std::tie(min_bound, max_bound) = get_activation_layer_test_bounds<T>(_function, _data_type);
+            std::uniform_real_distribution<> distribution(min_bound, max_bound);
+            library->fill(tensor, distribution, 0);
+        }
+        else
+        {
+            int min_bound = 0;
+            int max_bound = 0;
+            std::tie(min_bound, max_bound) = get_activation_layer_test_bounds<T>(_function, _data_type, _fractional_bits);
+            std::uniform_int_distribution<> distribution(min_bound, max_bound);
+            library->fill(tensor, distribution, 0);
+        }
+    }
+
+    TensorType compute_target(const TensorShape &shape, bool in_place, ActivationLayerInfo info, DataType data_type, int fixed_point_position = 0)
+    {
+        // Create tensors
+        TensorType src = create_tensor<TensorType>(shape, data_type, 1, fixed_point_position);
+        TensorType dst = create_tensor<TensorType>(shape, data_type, 1, fixed_point_position);
+
+        // Create and configure function
+        FunctionType act_layer;
+
+        TensorType *dst_ptr = in_place ? &src : &dst;
+
+        act_layer.configure(&src, dst_ptr, info);
+
+        ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
+        ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+        // Allocate tensors
+        src.allocator()->allocate();
+        ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+        if(!in_place)
+        {
+            dst.allocator()->allocate();
+            ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+        }
+
+        // Fill tensors
+        fill(AccessorType(src));
+
+        // Compute function
+        act_layer.run();
+
+        if(in_place)
+        {
+            return src;
+        }
+        else
+        {
+            return dst;
+        }
+    }
+
+    SimpleTensor<T> compute_reference(const TensorShape &shape, ActivationLayerInfo info, DataType data_type, int fixed_point_position = 0)
+    {
+        // Create reference
+        SimpleTensor<T> src{ shape, data_type, 1, fixed_point_position };
+
+        // Fill reference
+        fill(src);
+
+        return reference::activation_layer<T>(src, info);
+    }
+
+    TensorType                              _target{};
+    SimpleTensor<T>                         _reference{};
+    int                                     _fractional_bits{};
+    DataType                                _data_type{};
+    ActivationLayerInfo::ActivationFunction _function{};
+};
+
+template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
+class ActivationValidationFixture : public ActivationValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>
+{
+public:
+    template <typename...>
+    void setup(TensorShape shape, bool in_place, ActivationLayerInfo::ActivationFunction function, float alpha_beta, DataType data_type)
+    {
+        ActivationValidationFixedPointFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, in_place, function, alpha_beta, data_type, 0);
+    }
+};
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* ARM_COMPUTE_TEST_ACTIVATION_LAYER_FIXTURE */