aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSang-Hoon Park <sang-hoon.park@arm.com>2020-06-24 13:34:04 +0100
committerSang-Hoon Park <sang-hoon.park@arm.com>2020-06-30 11:03:10 +0000
commit3687ee1e7719436ff155a35911946b045903e8b6 (patch)
tree127d4b9da3996f473cef51f01a07fb02b75c0f1b
parent781cba7f33e056b1ca470ab34eb478177768eaf4 (diff)
downloadComputeLibrary-3687ee1e7719436ff155a35911946b045903e8b6.tar.gz
COMPMID-3539: Ignore align_corners for scaled size of 1
Scale kernels failed to validate when align_corners is true for scaled output size 1. Change this behavior to ignoring align_corners value to be aligned with expected behavior of higher-level frameworks. Also the minimum output size generated by the fixture for Scale kernels is changed to 1. Change-Id: Ib8e479af8bc43de3780005545f0c53fe195dc22e Signed-off-by: Sang-Hoon Park <sang-hoon.park@arm.com> Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/3478 Tested-by: Arm Jenkins <bsgcomp@arm.com> Reviewed-by: Georgios Pinitas <georgios.pinitas@arm.com> Comments-Addressed: Arm Jenkins <bsgcomp@arm.com>
-rw-r--r--Android.bp1
-rw-r--r--SConscript1
-rw-r--r--arm_compute/core/Utils.h21
-rw-r--r--src/core/CL/kernels/CLScaleKernel.cpp30
-rw-r--r--src/core/NEON/kernels/NEScaleKernel.cpp32
-rw-r--r--src/core/Utils.cpp12
-rw-r--r--src/core/utils/ScaleUtils.cpp44
-rw-r--r--src/core/utils/ScaleUtils.h67
-rw-r--r--src/runtime/NEON/functions/NEScale.cpp9
-rw-r--r--tests/validation/CL/Scale.cpp17
-rw-r--r--tests/validation/NEON/Scale.cpp17
-rw-r--r--tests/validation/fixtures/ScaleFixture.h7
-rw-r--r--tests/validation/reference/Scale.cpp7
13 files changed, 145 insertions, 120 deletions
diff --git a/Android.bp b/Android.bp
index e22aaea513..92c420a4dc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -415,6 +415,7 @@ cc_library_static {
"src/core/Utils.cpp",
"src/core/Validate.cpp",
"src/core/Version.cpp",
+ "src/core/utils/ScaleUtils.cpp",
"src/core/utils/helpers/fft.cpp",
"src/core/utils/helpers/tensor_transform.cpp",
"src/core/utils/io/FileHandler.cpp",
diff --git a/SConscript b/SConscript
index 87571a3bf4..9428d10f45 100644
--- a/SConscript
+++ b/SConscript
@@ -178,6 +178,7 @@ arm_compute_env.Append(LIBS = ['dl'])
core_files = Glob('src/core/*.cpp')
core_files += Glob('src/core/CPP/*.cpp')
core_files += Glob('src/core/CPP/kernels/*.cpp')
+core_files += Glob('src/core/utils/*.cpp')
core_files += Glob('src/core/utils/helpers/*.cpp')
core_files += Glob('src/core/utils/io/*.cpp')
core_files += Glob('src/core/utils/quantization/*.cpp')
diff --git a/arm_compute/core/Utils.h b/arm_compute/core/Utils.h
index 481dab3526..289df40890 100644
--- a/arm_compute/core/Utils.h
+++ b/arm_compute/core/Utils.h
@@ -981,27 +981,6 @@ bool needs_serialized_reduction(ReductionOperation op, DataType dt, unsigned int
*/
QuantizationInfo get_softmax_output_quantization_info(DataType input_type, bool is_log);
-/** Returns resize ratio between input and output with consideration of aligned corners
- *
- * @param[in] input_size The input size
- * @param[in] output_size the output size
- * @param[in] align_corners True to align corners of input and output. Defaults to false.
- *
- * @return The ratio between input and output (i.e., the input size divided by the output size)
- */
-float calculate_resize_ratio(size_t input_size, size_t output_size, bool align_corners = false);
-
-/** Returns if aligned corners are allowed for the given sampling policy
- *
- * @param[in] sampling_policy The sampling policy to consider
- *
- * @return True if aligned corners are allowed
- */
-inline bool is_align_corners_allowed(SamplingPolicy sampling_policy)
-{
- return sampling_policy != SamplingPolicy::CENTER;
-}
-
/** Returns a pair of minimum and maximum values for a quantized activation
*
* @param[in] act_info The information for activation
diff --git a/src/core/CL/kernels/CLScaleKernel.cpp b/src/core/CL/kernels/CLScaleKernel.cpp
index 872ba5b6cc..f3acc3b31c 100644
--- a/src/core/CL/kernels/CLScaleKernel.cpp
+++ b/src/core/CL/kernels/CLScaleKernel.cpp
@@ -35,6 +35,8 @@
#include "arm_compute/core/TensorInfo.h"
#include "support/StringSupport.h"
+#include "src/core/utils/ScaleUtils.h"
+
#include <set>
#include <string>
@@ -54,8 +56,8 @@ inline std::pair<float, float> calculate_scale_factors(const ITensorInfo &input,
const unsigned int output_width = output.dimension(idx_width);
const unsigned int output_height = output.dimension(idx_height);
- float wr = arm_compute::calculate_resize_ratio(input_width, output_width, align_corners);
- float hr = arm_compute::calculate_resize_ratio(input_height, output_height, align_corners);
+ float wr = arm_compute::scale_utils::calculate_resize_ratio(input_width, output_width, align_corners);
+ float hr = arm_compute::scale_utils::calculate_resize_ratio(input_height, output_height, align_corners);
return std::make_pair(wr, hr);
}
@@ -68,29 +70,13 @@ Status validate_arguments(const ITensorInfo *input, const ITensorInfo *output, c
ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(input, output);
ARM_COMPUTE_RETURN_ERROR_ON(output == input);
- ARM_COMPUTE_RETURN_ERROR_ON(info.align_corners && !is_align_corners_allowed(info.sampling_policy));
+ ARM_COMPUTE_RETURN_ERROR_ON(info.align_corners && !arm_compute::scale_utils::is_align_corners_allowed_sampling_policy(info.sampling_policy));
- if(info.align_corners)
- {
- // For bilinear method with aligned corners, the resize ratio will
- // be calculated by (input_size - 1)/(output_size - 1). Belows are
- // checking possible overflows.
- const auto data_layout = input->data_layout();
- const auto width_index = get_data_layout_dimension_index(data_layout, DataLayoutDimension::WIDTH);
- const auto height_index = get_data_layout_dimension_index(data_layout, DataLayoutDimension::HEIGHT);
-
- const auto input_width = input->dimension(width_index);
- const auto input_height = input->dimension(height_index);
- const auto output_width = output->dimension(width_index);
- const auto output_height = output->dimension(height_index);
-
- ARM_COMPUTE_RETURN_ERROR_ON(input_width == 0 || input_height == 0 || output_width == 0 || output_height == 0);
- ARM_COMPUTE_RETURN_ERROR_ON((output_width - 1 == 0) || (output_height - 1 == 0));
- }
+ const bool will_use_align_corners = info.align_corners && arm_compute::scale_utils::is_align_corners_allowed_output_shape(output->tensor_shape(), output->data_layout());
float wr = 0.f;
float hr = 0.f;
- std::tie(wr, hr) = calculate_scale_factors(*input, *output, info.align_corners);
+ std::tie(wr, hr) = calculate_scale_factors(*input, *output, will_use_align_corners);
ARM_COMPUTE_RETURN_ERROR_ON(info.interpolation_policy == InterpolationPolicy::AREA && (wr > 1.f || hr > 1.f));
@@ -191,7 +177,7 @@ void CLScaleKernel::configure(const CLCompileContext &compile_context, const ICL
_output = output;
_interpolation_policy = info.interpolation_policy;
_data_layout = input->info()->data_layout();
- _align_corners = info.align_corners;
+ _align_corners = info.align_corners && arm_compute::scale_utils::is_align_corners_allowed_output_shape(output->info()->tensor_shape(), _data_layout);
float wr = 0.f;
float hr = 0.f;
diff --git a/src/core/NEON/kernels/NEScaleKernel.cpp b/src/core/NEON/kernels/NEScaleKernel.cpp
index 857084ef7e..0f329a1c2c 100644
--- a/src/core/NEON/kernels/NEScaleKernel.cpp
+++ b/src/core/NEON/kernels/NEScaleKernel.cpp
@@ -30,6 +30,8 @@
#include "arm_compute/core/Window.h"
#include "arm_compute/core/utils/misc/Utility.h"
+#include "src/core/utils/ScaleUtils.h"
+
#include <arm_neon.h>
namespace arm_compute
@@ -68,19 +70,7 @@ Status validate_arguments(const ITensorInfo *input, const ITensorInfo *dx, const
ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(dy, 1, DataType::F32);
}
- ARM_COMPUTE_RETURN_ERROR_ON(info.align_corners && !is_align_corners_allowed(info.sampling_policy));
-
- if(info.align_corners && is_align_corners_allowed(info.sampling_policy))
- {
- // For bilinear method with aligned corners, the resize ratio will
- // be calculated by (input_size - 1)/(output_size - 1). Belows are
- // checking possible overflows.
- const auto input_width = input->dimension(width_index);
- const auto input_height = input->dimension(height_index);
-
- ARM_COMPUTE_RETURN_ERROR_ON(input_width == 0 || input_height == 0);
- ARM_COMPUTE_RETURN_ERROR_ON((output_width - 1 == 0) || (output_height - 1 == 0));
- }
+ ARM_COMPUTE_RETURN_ERROR_ON(info.align_corners && !arm_compute::scale_utils::is_align_corners_allowed_sampling_policy(info.sampling_policy));
if(info.interpolation_policy == InterpolationPolicy::AREA)
{
@@ -378,7 +368,7 @@ void NEScaleKernel::configure(const ITensor *input, const ITensor *dx, const ITe
_border_mode = info.border_mode;
_constant_border_value = info.constant_border_value;
_use_padding = info.use_padding;
- _align_corners = info.align_corners;
+ _align_corners = info.align_corners && arm_compute::scale_utils::is_align_corners_allowed_output_shape(output->info()->tensor_shape(), data_layout);
if(info.sampling_policy == SamplingPolicy::CENTER)
{
@@ -386,8 +376,8 @@ void NEScaleKernel::configure(const ITensor *input, const ITensor *dx, const ITe
}
// Compute the ratio between source width/height and destination width/height
- const auto wr = arm_compute::calculate_resize_ratio(input->info()->dimension(idx_width), output->info()->dimension(idx_width), _align_corners);
- const auto hr = arm_compute::calculate_resize_ratio(input->info()->dimension(idx_height), output->info()->dimension(idx_height), _align_corners);
+ const auto wr = arm_compute::scale_utils::calculate_resize_ratio(input->info()->dimension(idx_width), output->info()->dimension(idx_width), _align_corners);
+ const auto hr = arm_compute::scale_utils::calculate_resize_ratio(input->info()->dimension(idx_height), output->info()->dimension(idx_height), _align_corners);
// Add constant border only on top in case of NHWC layout
if(data_layout == DataLayout::NHWC)
@@ -437,7 +427,7 @@ void NEScaleKernel::scale_nearest_nchw(const Window &window)
const size_t input_stride = _input->info()->strides_in_bytes()[1];
// Compute the ratio between source height and destination height
- const auto hr = arm_compute::calculate_resize_ratio(_input->info()->dimension(1), _output->info()->dimension(1), _align_corners);
+ const auto hr = arm_compute::scale_utils::calculate_resize_ratio(_input->info()->dimension(1), _output->info()->dimension(1), _align_corners);
// Don't increment in X and Y direction for the input tensor
// A pointer to the start of this plane is needed as base for the precomputed offsets
@@ -670,7 +660,7 @@ void NEScaleKernel::scale_bilinear_nchw(const Window &window)
ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(_input, 1, DataType::U8, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::S16, DataType::F16, DataType::F32);
// Compute the ratio between source height and destination height
- const auto hr = arm_compute::calculate_resize_ratio(_input->info()->dimension(1), _output->info()->dimension(1), _align_corners);
+ const auto hr = arm_compute::scale_utils::calculate_resize_ratio(_input->info()->dimension(1), _output->info()->dimension(1), _align_corners);
// Don't increment in X and Y direction for the input tensor
// A pointer to the start of this plane is needed as base for the precomputed offsets
@@ -971,8 +961,8 @@ void NEScaleKernel::scale_area_nchw(const Window &window)
Iterator in(_input, win_in);
Iterator out(_output, window);
- const auto wr = arm_compute::calculate_resize_ratio(_input->info()->dimension(0), _output->info()->dimension(0), _align_corners);
- const auto hr = arm_compute::calculate_resize_ratio(_input->info()->dimension(1), _output->info()->dimension(1), _align_corners);
+ const auto wr = arm_compute::scale_utils::calculate_resize_ratio(_input->info()->dimension(0), _output->info()->dimension(0), _align_corners);
+ const auto hr = arm_compute::scale_utils::calculate_resize_ratio(_input->info()->dimension(1), _output->info()->dimension(1), _align_corners);
const auto w = _input->info()->dimension(0);
const auto h = _input->info()->dimension(1);
const size_t in_stride = _input->info()->strides_in_bytes()[1];
@@ -1019,7 +1009,7 @@ void NEScaleKernel::scale_nhwc(const Window &window)
const size_t input_stride_c = _input->info()->strides_in_bytes()[idx_channels];
// Compute the ratio between source height and destination height
- const auto hr = arm_compute::calculate_resize_ratio(_input->info()->dimension(idx_height), _output->info()->dimension(idx_height), _align_corners);
+ const auto hr = arm_compute::scale_utils::calculate_resize_ratio(_input->info()->dimension(idx_height), _output->info()->dimension(idx_height), _align_corners);
// Don't increment in width/height/channels for the input tensor
// A pointer to the start of this plane is needed as base for the precomputed offsets
diff --git a/src/core/Utils.cpp b/src/core/Utils.cpp
index bdde082a1f..4d7e964695 100644
--- a/src/core/Utils.cpp
+++ b/src/core/Utils.cpp
@@ -456,18 +456,6 @@ QuantizationInfo arm_compute::get_softmax_output_quantization_info(DataType inpu
return QuantizationInfo(1.f / 256, 0);
}
-float arm_compute::calculate_resize_ratio(size_t input_size, size_t output_size, bool align_corners)
-{
- const size_t offset = align_corners ? 1 : 0;
- const auto in = input_size - offset;
- const auto out = output_size - offset;
-
- ARM_COMPUTE_ERROR_ON((input_size == 0 || output_size == 0) && offset == 1);
- ARM_COMPUTE_ERROR_ON(out == 0);
-
- return static_cast<float>(in) / static_cast<float>(out);
-}
-
std::pair<int32_t, int32_t> arm_compute::get_quantized_activation_min_max(ActivationLayerInfo act_info, DataType data_type, UniformQuantizationInfo oq_info)
{
const bool is_qasymm8_signed = is_data_type_quantized_asymmetric_signed(data_type);
diff --git a/src/core/utils/ScaleUtils.cpp b/src/core/utils/ScaleUtils.cpp
new file mode 100644
index 0000000000..488b3dfaf5
--- /dev/null
+++ b/src/core/utils/ScaleUtils.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2020 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 "src/core/utils/ScaleUtils.h"
+#include "arm_compute/core/Helpers.h"
+
+float arm_compute::scale_utils::calculate_resize_ratio(size_t input_size, size_t output_size, bool align_corners)
+{
+ const size_t offset = align_corners ? 1 : 0;
+ const auto in = input_size - offset;
+ const auto out = output_size - offset;
+
+ ARM_COMPUTE_ERROR_ON((input_size == 0 || output_size == 0) && offset == 1);
+ ARM_COMPUTE_ERROR_ON(out == 0);
+
+ return static_cast<float>(in) / static_cast<float>(out);
+}
+
+bool arm_compute::scale_utils::is_align_corners_allowed_output_shape(const TensorShape &output_shape, DataLayout layout)
+{
+ const size_t idx_width = get_data_layout_dimension_index(layout, DataLayoutDimension::WIDTH);
+ const size_t idx_height = get_data_layout_dimension_index(layout, DataLayoutDimension::HEIGHT);
+ return (output_shape[idx_width] > 1) && (output_shape[idx_height] > 1);
+} \ No newline at end of file
diff --git a/src/core/utils/ScaleUtils.h b/src/core/utils/ScaleUtils.h
new file mode 100644
index 0000000000..c3895d4ec0
--- /dev/null
+++ b/src/core/utils/ScaleUtils.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2020 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 UTILS_CORE_SCALEUTILS_H
+#define UTILS_CORE_SCALEUTILS_H
+
+#include "arm_compute/core/Types.h"
+
+#include <cstdint>
+#include <cstdlib>
+
+namespace arm_compute
+{
+namespace scale_utils
+{
+/** Returns resize ratio between input and output with consideration of aligned corners
+ *
+ * @param[in] input_size The input size
+ * @param[in] output_size the output size
+ * @param[in] align_corners True to align corners of input and output. Defaults to false.
+ *
+ * @return The ratio between input and output (i.e., the input size divided by the output size)
+ */
+float calculate_resize_ratio(size_t input_size, size_t output_size, bool align_corners = false);
+
+/** Returns if aligned corners are allowed for the given sampling policy
+ *
+ * @param[in] sampling_policy The sampling policy to consider
+ *
+ * @return True if aligned corners are allowed
+ */
+inline bool is_align_corners_allowed_sampling_policy(SamplingPolicy sampling_policy)
+{
+ return sampling_policy != SamplingPolicy::CENTER;
+}
+
+/** Returns if aligned corners are allowed for the given output shape
+ *
+ * @param[in] output_shape The shape of the scaled output tensor
+ * @param[in] layout The data layout of the output tensor
+ *
+ * @return True if aligned corners are allowed
+ */
+bool is_align_corners_allowed_output_shape(const TensorShape &output_shape, DataLayout layout);
+} // namespace scale_utils
+} // namespace arm_compute
+#endif /* UTILS_CORE_SCALEUTILS_H */ \ No newline at end of file
diff --git a/src/runtime/NEON/functions/NEScale.cpp b/src/runtime/NEON/functions/NEScale.cpp
index 170b2ee3eb..28fbab4303 100644
--- a/src/runtime/NEON/functions/NEScale.cpp
+++ b/src/runtime/NEON/functions/NEScale.cpp
@@ -33,6 +33,8 @@
#include "arm_compute/runtime/NEON/NEScheduler.h"
#include "arm_compute/runtime/TensorAllocator.h"
+#include "src/core/utils/ScaleUtils.h"
+
#include <cmath>
#include <cstddef>
#include <utility>
@@ -107,7 +109,8 @@ void NEScale::configure(ITensor *input, ITensor *output, const ScaleKernelInfo &
ARM_COMPUTE_ERROR_THROW_ON(NEScale::validate(input->info(), output->info(), info));
_use_padding = info.use_padding;
- const bool is_align_corners_used = info.align_corners && is_align_corners_allowed(info.sampling_policy);
+ const bool is_align_corners_used = info.align_corners && arm_compute::scale_utils::is_align_corners_allowed_sampling_policy(info.sampling_policy)
+ && arm_compute::scale_utils::is_align_corners_allowed_output_shape(output->info()->tensor_shape(), output->info()->data_layout());
// Get data layout and width/height indices
const DataLayout data_layout = input->info()->data_layout();
@@ -118,8 +121,8 @@ void NEScale::configure(ITensor *input, ITensor *output, const ScaleKernelInfo &
const TensorShape shape(output->info()->dimension(idx_width), output->info()->dimension(idx_height));
// Compute the ratio between source width/height and destination width/height
- const auto wr = arm_compute::calculate_resize_ratio(input->info()->dimension(idx_width), output->info()->dimension(idx_width), is_align_corners_used);
- const auto hr = arm_compute::calculate_resize_ratio(input->info()->dimension(idx_height), output->info()->dimension(idx_height), is_align_corners_used);
+ const auto wr = arm_compute::scale_utils::calculate_resize_ratio(input->info()->dimension(idx_width), output->info()->dimension(idx_width), is_align_corners_used);
+ const auto hr = arm_compute::scale_utils::calculate_resize_ratio(input->info()->dimension(idx_height), output->info()->dimension(idx_height), is_align_corners_used);
// Get the element size of the input image
const size_t input_element_size = input->info()->element_size();
diff --git a/tests/validation/CL/Scale.cpp b/tests/validation/CL/Scale.cpp
index 50c148dfba..8a010032a3 100644
--- a/tests/validation/CL/Scale.cpp
+++ b/tests/validation/CL/Scale.cpp
@@ -186,23 +186,6 @@ TEST_CASE(AlignedCornerNotSupported, framework::DatasetMode::ALL)
ARM_COMPUTE_EXPECT(bool(result) == false, framework::LogLevel::ERRORS);
}
-TEST_CASE(InvalidAlignedCornerOutput, framework::DatasetMode::ALL)
-{
- // Bilinear with aligned corners require at least 2x2 output to prevent overflow.
- // Also, aligned corners require sampling policy to be TOP_LEFT.
- constexpr auto interpolation_policy = InterpolationPolicy::BILINEAR;
- constexpr bool align_corners = true;
- constexpr auto sampling_policy = SamplingPolicy::TOP_LEFT;
- const auto invalid_output_shape = TensorShape{ 1, 1, 3, 2 };
-
- const auto input = TensorInfo{ default_input_shape, 1, default_data_type, default_data_layout };
- const auto output = TensorInfo{ invalid_output_shape, 1, default_data_type, default_data_layout };
- Status result{};
-
- result = CLScale::validate(&input, &output, ScaleKernelInfo{ interpolation_policy, default_border_mode, PixelValue(), sampling_policy, default_use_padding, align_corners });
- ARM_COMPUTE_EXPECT(bool(result) == false, framework::LogLevel::ERRORS);
-}
-
TEST_CASE(WindowShrink, framework::DatasetMode::ALL)
{
const auto input = TensorInfo{ TensorShape(37U, 37U, 2U), 1, DataType::F32 };
diff --git a/tests/validation/NEON/Scale.cpp b/tests/validation/NEON/Scale.cpp
index f4a9b9df56..a7eb4b2d8d 100644
--- a/tests/validation/NEON/Scale.cpp
+++ b/tests/validation/NEON/Scale.cpp
@@ -244,23 +244,6 @@ TEST_CASE(AlignedCornerNotSupported, framework::DatasetMode::ALL)
result = NEScale::validate(&input, &output, ScaleKernelInfo{ interpolation_policy, default_border_mode, PixelValue(), sampling_policy, default_use_padding, align_corners });
ARM_COMPUTE_EXPECT(bool(result) == false, framework::LogLevel::ERRORS);
}
-
-TEST_CASE(InvalidAlignedCornerOutput, framework::DatasetMode::ALL)
-{
- // Bilinear with aligned corners require at least 2x2 output to prevent overflow.
- // Also, aligned corners require sampling policy to be TOP_LEFT.
- constexpr auto interpolation_policy = InterpolationPolicy::BILINEAR;
- constexpr bool align_corners = true;
- constexpr auto sampling_policy = SamplingPolicy::TOP_LEFT;
- const auto invalid_output_shape = TensorShape{ 1, 1, 3, 2 };
-
- const auto input = TensorInfo{ input_shape, 1, default_data_type, default_data_layout };
- const auto output = TensorInfo{ invalid_output_shape, 1, default_data_type, default_data_layout };
- Status result{};
-
- result = NEScale::validate(&input, &output, ScaleKernelInfo{ interpolation_policy, default_border_mode, PixelValue(), sampling_policy, default_use_padding, align_corners });
- ARM_COMPUTE_EXPECT(bool(result) == false, framework::LogLevel::ERRORS);
-}
TEST_SUITE_END() // Validate
template <typename T>
diff --git a/tests/validation/fixtures/ScaleFixture.h b/tests/validation/fixtures/ScaleFixture.h
index 12d9012ece..b7a821fad4 100644
--- a/tests/validation/fixtures/ScaleFixture.h
+++ b/tests/validation/fixtures/ScaleFixture.h
@@ -74,11 +74,8 @@ protected:
constexpr float max_width{ 8192.0f };
constexpr float max_height{ 6384.0f };
-
- const bool is_align_corners_used = _align_corners && arm_compute::is_align_corners_allowed(_sampling_policy);
-
- const float min_width = is_align_corners_used ? 2.f : 1.f;
- const float min_height = is_align_corners_used ? 2.f : 1.f;
+ const float min_width{ 1.f };
+ const float min_height{ 1.f };
std::mt19937 generator(library->seed());
std::uniform_real_distribution<float> distribution_float(_min_scale, _max_scale);
diff --git a/tests/validation/reference/Scale.cpp b/tests/validation/reference/Scale.cpp
index cb4ad6f909..44beabb2d4 100644
--- a/tests/validation/reference/Scale.cpp
+++ b/tests/validation/reference/Scale.cpp
@@ -26,6 +26,7 @@
#include "Utils.h"
#include "arm_compute/core/utils/misc/Utility.h"
+#include "src/core/utils/ScaleUtils.h"
namespace arm_compute
{
@@ -46,9 +47,11 @@ SimpleTensor<T> scale_core(const SimpleTensor<T> &in, float scale_x, float scale
shape_scaled.set(1, (in.shape()[1] + round_value) * scale_y, /* apply_dim_correction = */ false);
SimpleTensor<T> out(shape_scaled, in.data_type());
+ align_corners = align_corners && arm_compute::scale_utils::is_align_corners_allowed_output_shape(out.shape(), DataLayout::NCHW);
+
// Compute the ratio between source width/height and destination width/height
- const auto wr = arm_compute::calculate_resize_ratio(in.shape()[0], out.shape()[0], align_corners);
- const auto hr = arm_compute::calculate_resize_ratio(in.shape()[1], out.shape()[1], align_corners);
+ const auto wr = arm_compute::scale_utils::calculate_resize_ratio(in.shape()[0], out.shape()[0], align_corners);
+ const auto hr = arm_compute::scale_utils::calculate_resize_ratio(in.shape()[1], out.shape()[1], align_corners);
const auto width = static_cast<int>(in.shape().x());
const auto height = static_cast<int>(in.shape().y());