Fix for Resize with align corners = true creates a memory leak when using valgrind

* Add end to end unit test to CpuRef, CpuAcc and GpuAcc backends

Resolves: IVGCVSW-8193

Signed-off-by: Teresa Charlin <teresa.charlinreyes@arm.com>
Change-Id: I7be226f084ec814ac72c2c9b3c47c07b3baf0aa5
diff --git a/include/armnn/Utils.hpp b/include/armnn/Utils.hpp
index 7c1f096..8976b38 100644
--- a/include/armnn/Utils.hpp
+++ b/include/armnn/Utils.hpp
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <string>
+#include <cmath>
 
 namespace armnn
 {
@@ -39,4 +40,10 @@
 
 const std::string GetVersion();
 
+inline float roundf(float value)
+{
+    // Workaround Valgrind's mismatches: when running from Valgrind the call to std::round(4.5) == 4.0 instead of 5.0
+    return (value < 0.f) ? ::floorf(value - 0.5f) : ::floorf(value + 0.5f);
+}
+
 } // namespace armnn
diff --git a/src/backends/cl/test/ClEndToEndTests.cpp b/src/backends/cl/test/ClEndToEndTests.cpp
index 78d2dea..b83bb1b 100644
--- a/src/backends/cl/test/ClEndToEndTests.cpp
+++ b/src/backends/cl/test/ClEndToEndTests.cpp
@@ -22,6 +22,7 @@
 #include <backendsCommon/test/QuantizedLstmEndToEndTestImpl.hpp>
 #include <backendsCommon/test/ReduceEndToEndTestImpl.hpp>
 #include <backendsCommon/test/ReshapeEndToEndTestImpl.hpp>
+#include <backendsCommon/test/ResizeEndToEndTestImpl.hpp>
 #include <backendsCommon/test/ReverseV2EndToEndTestImpl.hpp>
 #include <backendsCommon/test/SliceEndToEndTestImpl.hpp>
 #include <backendsCommon/test/SpaceToDepthEndToEndTestImpl.hpp>
@@ -346,6 +347,38 @@
     ReshapeEndToEndFloat16<armnn::DataType::Float16>(clDefaultBackends);
 }
 
+// Resize Bilinear
+TEST_CASE("ClResizeBilinearEndToEndFloatNchwTest")
+{
+    ResizeBilinearEndToEnd<armnn::DataType::Float32>(clDefaultBackends, armnn::DataLayout::NCHW);
+}
+
+TEST_CASE("ClResizeBilinearEndToEndFloatNhwcTest")
+{
+    ResizeBilinearEndToEnd<armnn::DataType::Float32>(clDefaultBackends, armnn::DataLayout::NHWC);
+}
+
+// Resize NearestNeighbor
+TEST_CASE("ClResizeNearestNeighborEndToEndFloatNchwTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(clDefaultBackends, armnn::DataLayout::NCHW);
+}
+
+TEST_CASE("ClResizeNearestNeighborEndToEndFloatNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(clDefaultBackends, armnn::DataLayout::NHWC);
+}
+
+TEST_CASE("ClResizeNearestNeighborEndToEndFloatAlignCornersNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(clDefaultBackends, armnn::DataLayout::NHWC, true, false);
+}
+
+TEST_CASE("ClResizeNearestNeighborEndToEndFloatHalfPixelNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(clDefaultBackends, armnn::DataLayout::NHWC, false, true);
+}
+
 // ReverseV2
 TEST_CASE("ClReverseV2EndToEndTest")
 {
diff --git a/src/backends/neon/test/NeonEndToEndTests.cpp b/src/backends/neon/test/NeonEndToEndTests.cpp
index 1e2636b..9baded6 100644
--- a/src/backends/neon/test/NeonEndToEndTests.cpp
+++ b/src/backends/neon/test/NeonEndToEndTests.cpp
@@ -23,6 +23,7 @@
 #include <backendsCommon/test/QuantizedLstmEndToEndTestImpl.hpp>
 #include <backendsCommon/test/ReduceEndToEndTestImpl.hpp>
 #include <backendsCommon/test/ReshapeEndToEndTestImpl.hpp>
+#include <backendsCommon/test/ResizeEndToEndTestImpl.hpp>
 #include <backendsCommon/test/ReverseV2EndToEndTestImpl.hpp>
 #include <backendsCommon/test/SliceEndToEndTestImpl.hpp>
 #include <backendsCommon/test/SpaceToDepthEndToEndTestImpl.hpp>
@@ -672,6 +673,38 @@
     ReshapeEndToEndFloat16<armnn::DataType::Float16>(neonDefaultBackends);
 }
 
+// Resize Bilinear
+TEST_CASE("NeonResizeBilinearEndToEndFloatNchwTest")
+{
+    ResizeBilinearEndToEnd<armnn::DataType::Float32>(neonDefaultBackends, armnn::DataLayout::NCHW);
+}
+
+TEST_CASE("NeonResizeBilinearEndToEndFloatNhwcTest")
+{
+    ResizeBilinearEndToEnd<armnn::DataType::Float32>(neonDefaultBackends, armnn::DataLayout::NHWC);
+}
+
+// Resize NearestNeighbor
+TEST_CASE("NeonResizeNearestNeighborEndToEndFloatNchwTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(neonDefaultBackends, armnn::DataLayout::NCHW);
+}
+
+TEST_CASE("NeonResizeNearestNeighborEndToEndFloatNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(neonDefaultBackends, armnn::DataLayout::NHWC);
+}
+
+TEST_CASE("NeonResizeNearestNeighborEndToEndFloatAlignCornersNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(neonDefaultBackends, armnn::DataLayout::NHWC, true, false);
+}
+
+TEST_CASE("NeonResizeNearestNeighborEndToEndFloatHalfPixelNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(neonDefaultBackends, armnn::DataLayout::NHWC, false, true);
+}
+
 // ReverseV2
 TEST_CASE("NeonReverseV2EndToEndTest")
 {
diff --git a/src/backends/reference/test/RefEndToEndTests.cpp b/src/backends/reference/test/RefEndToEndTests.cpp
index 143d85a..78852bc 100644
--- a/src/backends/reference/test/RefEndToEndTests.cpp
+++ b/src/backends/reference/test/RefEndToEndTests.cpp
@@ -1404,11 +1404,21 @@
     ResizeNearestNeighborEndToEnd<armnn::DataType::QSymmS16>(defaultBackends, armnn::DataLayout::NHWC);
 }
 
+TEST_CASE("RefResizeNearestNeighborEndToEndFloatAlignCornersNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(defaultBackends, armnn::DataLayout::NHWC, true, false);
+}
+
 TEST_CASE("RefResizeNearestNeighborEndToEndFloatHalfPixelNhwcTest")
 {
     ResizeNearestNeighborEndToEnd<armnn::DataType::Float32>(defaultBackends, armnn::DataLayout::NHWC, false, true);
 }
 
+TEST_CASE("RefResizeNearestNeighborEndToEndInt8AlignCornersNhwcTest")
+{
+    ResizeNearestNeighborEndToEnd<armnn::DataType::QAsymmS8>(defaultBackends, armnn::DataLayout::NHWC, true, false);
+}
+
 TEST_CASE("RefResizeNearestNeighborEndToEndInt8HalfPixelNhwcTest")
 {
     ResizeNearestNeighborEndToEnd<armnn::DataType::QSymmS8>(defaultBackends, armnn::DataLayout::NHWC, false, true);
diff --git a/src/backends/reference/workloads/Resize.cpp b/src/backends/reference/workloads/Resize.cpp
index b8bf1bc..e80a205 100644
--- a/src/backends/reference/workloads/Resize.cpp
+++ b/src/backends/reference/workloads/Resize.cpp
@@ -8,15 +8,13 @@
 #include "TensorBufferArrayView.hpp"
 
 #include <armnn/utility/NumericCast.hpp>
+#include <armnn/Utils.hpp>
 
 #include <cmath>
 #include <algorithm>
 
 using namespace armnnUtils;
 
-namespace armnn
-{
-
 namespace
 {
 
@@ -62,12 +60,14 @@
 
 }// anonymous namespace
 
+namespace armnn
+{
 void Resize(Decoder<float>&   in,
             const TensorInfo& inputInfo,
             Encoder<float>&   out,
             const TensorInfo& outputInfo,
             DataLayoutIndexed dataLayout,
-            armnn::ResizeMethod resizeMethod,
+            ResizeMethod resizeMethod,
             bool alignCorners,
             bool halfPixelCenters)
 {
@@ -91,8 +91,8 @@
     const float scaleY = CalculateResizeScale(inputHeight, outputHeight, alignCorners);
     const float scaleX = CalculateResizeScale(inputWidth, outputWidth, alignCorners);
 
-    TensorShape inputShape =  inputInfo.GetShape();
-    TensorShape outputShape =  outputInfo.GetShape();
+    const TensorShape& inputShape =  inputInfo.GetShape();
+    const TensorShape& outputShape =  outputInfo.GetShape();
 
     for (unsigned int n = 0; n < batchSize; ++n)
     {
@@ -104,8 +104,8 @@
                 float iy = PixelScaler(y, scaleY, halfPixelCenters, resizeMethod);
 
                 // Discrete height coordinate of top-left texel (in the 2x2 texel area used for interpolation).
-                const float fiy = (resizeMethod == armnn::ResizeMethod::NearestNeighbor && alignCorners) ?
-                                  roundf(iy) : floorf(iy);
+                const float fiy = (resizeMethod == ResizeMethod::NearestNeighbor && alignCorners) ? armnn::roundf(iy)
+                                                                                                  : floorf(iy);
                 // Pixel scaling a value with Half Pixel Centers can be negative, if so set to 0
                 const unsigned int y0 = static_cast<unsigned int>(std::max(fiy, 0.0f));
 
@@ -118,8 +118,8 @@
                     float ix = PixelScaler(x, scaleX, halfPixelCenters, resizeMethod);
 
                     // Nearest Neighbour uses rounding to align to corners
-                    const float fix = resizeMethod == armnn::ResizeMethod::NearestNeighbor && alignCorners ?
-                                      roundf(ix) : floorf(ix);
+                    const float fix = resizeMethod == ResizeMethod::NearestNeighbor && alignCorners ? armnn::roundf(ix)
+                                                                                                    : floorf(ix);
                     // Pixel scaling a value with Half Pixel Centers can be negative, if so set to 0
                     const unsigned int x0 = static_cast<unsigned int>(std::max(fix, 0.0f));
 
@@ -144,7 +144,7 @@
                     float interpolatedValue;
                     switch (resizeMethod)
                     {
-                        case armnn::ResizeMethod::Bilinear:
+                        case ResizeMethod::Bilinear:
                         {
                             in[dataLayout.GetIndex(inputShape, n, c, y0, x0)];
                             float input1 = in.Get();
@@ -160,7 +160,7 @@
                             interpolatedValue = Lerp(ly0, ly1, yw);
                             break;
                         }
-                        case armnn::ResizeMethod::NearestNeighbor:
+                        case ResizeMethod::NearestNeighbor:
                         {
                             // calculate euclidean distance to the 4 neighbours
                             auto distance00 = EuclideanDistance(fix, fiy, x0, y0);
@@ -195,7 +195,7 @@
                             }
                             else
                             {
-                                throw armnn::InvalidArgumentException("Resize Nearest Neighbor failure");
+                                throw InvalidArgumentException("Resize Nearest Neighbor failure");
                             }
 
                             in[dataLayout.GetIndex(inputShape, n, c, yNearest, xNearest)];
@@ -203,8 +203,8 @@
                             break;
                         }
                         default:
-                            throw armnn::InvalidArgumentException("Unknown resize method: " +
-                                                                  std::to_string(static_cast<int>(resizeMethod)));
+                            throw InvalidArgumentException("Unknown resize method: " +
+                                                            std::to_string(static_cast<int>(resizeMethod)));
                     }
                     out[dataLayout.GetIndex(outputShape, n, c, y, x)];
                     out.Set(interpolatedValue);