COMPMID-417: Fix PaddingCalculator

Change-Id: Idefa8c62d313e25808ea735c60967437035e266d
Reviewed-on: http://mpd-gerrit.cambridge.arm.com/78711
Reviewed-by: SiCong Li <sicong.li@arm.com>
Tested-by: Kaizen <jeremy.johnson+kaizengerrit@arm.com>
Reviewed-by: Georgios Pinitas <georgios.pinitas@arm.com>
diff --git a/tests/PaddingCalculator.h b/tests/PaddingCalculator.h
index 029312b..6906353 100644
--- a/tests/PaddingCalculator.h
+++ b/tests/PaddingCalculator.h
@@ -26,6 +26,8 @@
 
 #include "arm_compute/core/Types.h"
 
+#include <cmath>
+
 namespace arm_compute
 {
 namespace test
@@ -34,6 +36,13 @@
 class PaddingCalculator final
 {
 public:
+    /** Options for computing the padding */
+    enum class Option
+    {
+        EXCLUDE_BORDER,
+        INCLUDE_BORDER
+    };
+
     /** Construct calculator with size of tensor's dimension and step size.
      *
      * @param[in] size               Number of elements available.
@@ -62,6 +71,12 @@
      */
     void set_access_offset(int offset);
 
+    /** Set number of processed elements.
+     *
+     * @param[in] elements Number of processed elements per iteration.
+     */
+    void set_processed_elements(int elements);
+
     /** Set number of accessed elements.
      *
      * @param[in] elements Number of accessed elements per iteration.
@@ -70,9 +85,25 @@
 
     /** Compute the required padding.
      *
+     * If access offset is negative and border mode is not undefined, the top,
+     * bottom and left padding is set to boder size. Otherwise it is zero.
+     * The right padding is always computed based on the specified parameters.
+     *
      * @return Required padding in number of elements.
      */
-    int required_padding() const;
+    PaddingSize required_padding() const;
+
+    /** Compute the required padding.
+     *
+     * If @p option is INCLUDE_BORDER and border mode is not undefined, the top,
+     * bottom and left padding is set to boder size. Otherwise it is zero.
+     * The right padding is always computed based on the specified parameters.
+     *
+     * @param[in] option Padding option
+     *
+     * @return Required padding in number of elements.
+     */
+    PaddingSize required_padding(Option option) const;
 
 private:
     int        _size;
@@ -98,21 +129,38 @@
     _offset = offset;
 }
 
+inline void PaddingCalculator::set_processed_elements(int elements)
+{
+    _num_processed_elements = elements;
+}
 inline void PaddingCalculator::set_accessed_elements(int elements)
 {
     _num_accessed_elements = elements;
 }
 
-inline int PaddingCalculator::required_padding() const
+inline PaddingSize PaddingCalculator::required_padding() const
 {
+    return required_padding(_offset < 0 ? Option::INCLUDE_BORDER : Option::EXCLUDE_BORDER);
+}
+
+inline PaddingSize PaddingCalculator::required_padding(Option option) const
+{
+    PaddingSize padding{ (_mode == BorderMode::UNDEFINED || option == Option::EXCLUDE_BORDER) ? 0U : static_cast<unsigned int>(std::max(0, _border_size)) };
+
+    int padding_right = 0;
+
     if(_mode == BorderMode::UNDEFINED)
     {
-        return (((_size - _border_size + _num_processed_elements - 1) / _num_processed_elements) - 1) * _num_processed_elements + _num_accessed_elements - _size + _border_size + _offset;
+        padding_right = (((_size - 2 * _border_size + _num_processed_elements - 1) / _num_processed_elements) - 1) * _num_processed_elements + _num_accessed_elements - _size + _border_size + _offset;
     }
     else
     {
-        return (((_size + _num_processed_elements - 1) / _num_processed_elements) - 1) * _num_processed_elements + _num_accessed_elements - _size + _offset;
+        padding_right = (((_size + _num_processed_elements - 1) / _num_processed_elements) - 1) * _num_processed_elements + _num_accessed_elements - _size + _offset;
     }
+
+    padding.right = std::max(0, padding_right);
+
+    return padding;
 }
 } // namespace test
 } // namespace arm_compute