IVGCVSW-2054: Fixing issue with InferOutputShape implementation in BatchToSpaceNdLayer.
    * added Unit test

Change-Id: I80f55e8c7afb39d96006c8dd027fc9683ea8182e
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 95ca39f..0fa1907 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -350,6 +350,7 @@
         src/armnn/test/GraphTests.cpp
         src/armnn/test/GraphUtils.hpp
         src/armnn/test/InstrumentTests.cpp
+        src/armnn/test/LayerValidateOutputTest.cpp
         src/armnn/test/NetworkTests.cpp
         src/armnn/test/ObservableTest.cpp
         src/armnn/test/OptimizerTests.cpp
diff --git a/include/armnn/Descriptors.hpp b/include/armnn/Descriptors.hpp
index 32ac959..396e427 100644
--- a/include/armnn/Descriptors.hpp
+++ b/include/armnn/Descriptors.hpp
@@ -299,8 +299,7 @@
 struct BatchToSpaceNdDescriptor
 {
     BatchToSpaceNdDescriptor()
-        : m_BlockShape({0, 0})
-        , m_Crops({{0, 0}, {0, 0}})
+        : m_Crops({{0, 0}, {0, 0}})
         , m_DataLayout(DataLayout::NCHW)
     {}
 
diff --git a/src/armnn/layers/BatchToSpaceNdLayer.cpp b/src/armnn/layers/BatchToSpaceNdLayer.cpp
index 9366a87..aff818e 100644
--- a/src/armnn/layers/BatchToSpaceNdLayer.cpp
+++ b/src/armnn/layers/BatchToSpaceNdLayer.cpp
@@ -66,10 +66,41 @@
     std::pair<unsigned int, unsigned int> xCrops = crops[1];
 
     unsigned int inputHeight = inputShape[dataLayout.GetHeightIndex()];
-    unsigned int outputHeight = theBlockShape.at(0) * (inputHeight - (yCrops.first + yCrops.second));
+    unsigned int outputHeight;
 
+    unsigned int yCropsTotal = yCrops.first + yCrops.second;
+
+    BOOST_ASSERT_MSG(yCropsTotal <= inputHeight,
+                     "BatchToSpaceLayer: Overall height crop should be less than or equal to the input height.");
+
+    unsigned int croppedHeight = inputHeight - yCropsTotal;
+
+    if (theBlockShape.at(0) > 0)
+    {
+        outputHeight = theBlockShape.at(0) * croppedHeight;
+    }
+    else
+    {
+        outputHeight = croppedHeight;
+    }
+
+    unsigned int outputWidth;
     unsigned int inputWidth = inputShape[dataLayout.GetWidthIndex()];
-    unsigned int outputWidth = theBlockShape.at(1) * (inputWidth - (xCrops.first + xCrops.second));
+
+    unsigned int xCropsTotal = xCrops.first + xCrops.second;
+
+    BOOST_ASSERT_MSG(xCropsTotal <= inputWidth,
+                     "BatchToSpaceLayer: Overall width crop should be less than or equal to the input width.");
+    unsigned int croppedWidth = inputWidth - xCropsTotal;
+
+    if (theBlockShape.at(1) > 0)
+    {
+        outputWidth = theBlockShape.at(1) * croppedWidth;
+    }
+    else
+    {
+        outputWidth = croppedWidth;
+    }
 
     unsigned int outputBatchSize = overallSize / (outputHeight * outputWidth);
 
diff --git a/src/armnn/test/LayerValidateOutputTest.cpp b/src/armnn/test/LayerValidateOutputTest.cpp
new file mode 100644
index 0000000..62b9c4a
--- /dev/null
+++ b/src/armnn/test/LayerValidateOutputTest.cpp
@@ -0,0 +1,38 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#include <armnn/ArmNN.hpp>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/test/unit_test.hpp>
+#include <layers/BatchToSpaceNdLayer.hpp>
+#include <Graph.hpp>
+
+
+BOOST_AUTO_TEST_SUITE(LayerValidateOutput)
+
+BOOST_AUTO_TEST_CASE(TestBatchToSpaceInferOutputShape)
+{
+    armnn::Graph graph;
+
+    armnn::BatchToSpaceNdDescriptor descriptor;
+    std::vector<unsigned int> theBlockShape = {2, 2};
+    descriptor.m_BlockShape = theBlockShape;
+    descriptor.m_DataLayout = armnn::DataLayout::NHWC;
+
+    armnn::BatchToSpaceNdLayer* const batchToSpaceLayer =
+        graph.AddLayer<armnn::BatchToSpaceNdLayer>(descriptor, "batchToSpace");
+
+    std::vector<armnn::TensorShape> shapes;
+    const std::vector<unsigned int> theDimSizes = {4, 2, 2, 1};
+    armnn::TensorShape shape(4, theDimSizes.data());
+    shapes.push_back(shape);
+
+    const std::vector<unsigned int> expectedDimSizes = {1, 4, 4, 1};
+    armnn::TensorShape expectedShape(4, expectedDimSizes.data());
+
+    BOOST_CHECK(expectedShape == batchToSpaceLayer->InferOutputShapes(shapes).at(0));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file
diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp
index 2556a3e..1ce6914 100755
--- a/src/backends/backendsCommon/test/LayerTests.cpp
+++ b/src/backends/backendsCommon/test/LayerTests.cpp
@@ -6113,3 +6113,19 @@
     return BatchToSpaceNdHelper<float, 4, 4>(workloadFactory, armnn::DataLayout::NCHW, inputShape, input, blockShape,
                                              crops, outputShape, expectedOutput);
 }
+
+
+LayerTestResult<uint8_t, 4> BatchToSpaceNdNhwcUintTest1(armnn::IWorkloadFactory& workloadFactory)
+{
+    const unsigned int inputShape[] = {4, 2, 2, 1};
+    const unsigned int outputShape[] = {1, 4, 4, 1};
+
+    std::vector<uint8_t> input({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
+    std::vector<uint8_t> expectedOutput({ 1, 5, 2, 6, 9, 13, 10, 14, 3, 7, 4, 8, 11, 15, 12, 16});
+
+    std::vector<unsigned int> blockShape({2, 2});
+    std::vector<std::pair<unsigned int, unsigned int>> crops = {{0, 0}, {0, 0}};
+
+    return BatchToSpaceNdHelper<uint8_t, 4, 4>(workloadFactory, armnn::DataLayout::NHWC, inputShape, input, blockShape,
+                                               crops, outputShape, expectedOutput);
+}
\ No newline at end of file
diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp
index 34d5583..c38d84f 100644
--- a/src/backends/backendsCommon/test/LayerTests.hpp
+++ b/src/backends/backendsCommon/test/LayerTests.hpp
@@ -439,3 +439,5 @@
 LayerTestResult<float, 4> BatchToSpaceNdNhwcFloat32Test3(armnn::IWorkloadFactory& workloadFactory);
 
 LayerTestResult<float, 4> BatchToSpaceNdNchwFloat32Test1(armnn::IWorkloadFactory &workloadFactory);
+
+LayerTestResult<uint8_t, 4> BatchToSpaceNdNhwcUintTest1(armnn::IWorkloadFactory &workloadFactory);
\ No newline at end of file
diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp
index 8bbf11b..4ff5cf2 100644
--- a/src/backends/reference/test/RefLayerTests.cpp
+++ b/src/backends/reference/test/RefLayerTests.cpp
@@ -385,4 +385,6 @@
 
 ARMNN_AUTO_TEST_CASE(BatchToSpaceNdNchwFloat321, BatchToSpaceNdNchwFloat32Test1)
 
+ARMNN_AUTO_TEST_CASE(BatchToSpaceNdNhwcUint1, BatchToSpaceNdNhwcUintTest1)
+
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/backends/reference/workloads/RefBatchToSpaceNdUint8Workload.cpp b/src/backends/reference/workloads/RefBatchToSpaceNdUint8Workload.cpp
index a66bcd4..e4e108e 100644
--- a/src/backends/reference/workloads/RefBatchToSpaceNdUint8Workload.cpp
+++ b/src/backends/reference/workloads/RefBatchToSpaceNdUint8Workload.cpp
@@ -18,11 +18,10 @@
     const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]);
     const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]);
     auto dequantizedInputData = Dequantize(GetInputTensorDataU8(0, m_Data), inputInfo);
-    float* outputData = GetOutputTensorDataFloat(0, m_Data);
 
     std::vector<float> results(outputInfo.GetNumElements());
     BatchToSpaceNd(m_Data.m_Parameters.m_DataLayout, inputInfo, outputInfo, m_Data.m_Parameters.m_BlockShape,
-                   m_Data.m_Parameters.m_Crops, dequantizedInputData.data(), outputData);
+                   m_Data.m_Parameters.m_Crops, dequantizedInputData.data(), results.data());
 
     Quantize(GetOutputTensorDataU8(0, m_Data), results.data(), outputInfo);
 }