From 463ae19207526e3fa2072b63beef348630126a6a Mon Sep 17 00:00:00 2001 From: Pawel Raasz Date: Thu, 31 Aug 2023 09:57:09 +0200 Subject: [PATCH] Fix padding calculation if interval value is inf (#19383) --- .../include/pad_shape_inference.hpp | 65 ++-- src/core/tests/type_prop/pad.cpp | 302 +++++++----------- 2 files changed, 155 insertions(+), 212 deletions(-) diff --git a/src/core/shape_inference/include/pad_shape_inference.hpp b/src/core/shape_inference/include/pad_shape_inference.hpp index 760b128caee..2304db7d210 100644 --- a/src/core/shape_inference/include/pad_shape_inference.hpp +++ b/src/core/shape_inference/include/pad_shape_inference.hpp @@ -11,6 +11,13 @@ #include "utils.hpp" namespace ov { namespace op { +namespace pad { +constexpr bool is_inf_padding(const std::pair& pad_bounds) { + return (pad_bounds.first == 0) && + (ov::util::dim::is_inf_bound(pad_bounds.second) || ov::util::is_max(pad_bounds.second)); +} +} // namespace pad + template > std::vector shape_infer(const util::PadBase* op, const std::vector& input_shapes, @@ -22,28 +29,19 @@ std::vector shape_infer(const util::PadBase* op, // Check the shape of pad_value if (pad_mode == PadMode::CONSTANT && input_shapes.size() == 4) { const auto& pad_value_shape = input_shapes[3]; - NODE_VALIDATION_CHECK(op, - pad_value_shape.rank().compatible(0), - "Argument for padding value is not a scalar (shape: ", - pad_value_shape, - ")."); + NODE_SHAPE_INFER_CHECK(op, + input_shapes, + pad_value_shape.rank().compatible(0), + "Argument for padding value is not a scalar."); } const auto& pads_begin_shape = input_shapes[1]; const auto& pads_begin_rank = pads_begin_shape.rank(); - NODE_VALIDATION_CHECK(op, - pads_begin_rank.compatible(1), - "Argument for pads_begin is not 1D (shape: ", - pads_begin_rank, - ")."); + NODE_SHAPE_INFER_CHECK(op, input_shapes, pads_begin_rank.compatible(1), "Argument for pads_begin is not 1D."); const auto& pads_end_shape = input_shapes[2]; const auto& pads_end_rank = pads_end_shape.rank(); - NODE_VALIDATION_CHECK(op, - pads_end_rank.compatible(1), - "Argument for pads_end is not 1D (shape: ", - pads_end_rank, - ")."); + NODE_SHAPE_INFER_CHECK(op, input_shapes, pads_end_rank.compatible(1), "Argument for pads_end is not 1D."); const auto& arg_shape = input_shapes[0]; const auto& arg_shape_rank = arg_shape.rank(); @@ -94,13 +92,15 @@ std::vector shape_infer(const util::PadBase* op, "of at least 2 at each " "spatial axis."); } - NODE_VALIDATION_CHECK( + NODE_SHAPE_INFER_CHECK( op, + input_shapes, pad_mode != op::PadMode::REFLECT || (cmp::lt(begin_lb, dim_lb) && cmp::lt(end_lb, dim_lb)), "REFLECT padding mode requires that 'pads_begin[D]' and 'pads_end[D]' " "must be not greater than 'data_shape[D] - 1'."); - NODE_VALIDATION_CHECK( + NODE_SHAPE_INFER_CHECK( op, + input_shapes, pad_mode != op::PadMode::SYMMETRIC || (cmp::le(begin_lb, dim_lb) && cmp::le(end_lb, dim_lb)), "SYMMETRIC padding mode requires that 'pads_begin[D]' and 'pads_end[D]' " "must be not greater than 'data_shape[D]'."); @@ -111,28 +111,29 @@ std::vector shape_infer(const util::PadBase* op, if ((pad_dim_diff_lb != 0) || (pad_dim_diff_ub != 0)) { using namespace ov::util; const auto lb = dim::padded(dim_lb, pad_dim_diff_lb); - const auto ub = dim::padded(arg_shape[i].get_max_length(), pad_dim_diff_ub); - output_shape.emplace_back(lb, ub); + if (std::is_same::value) { + const auto ub = (pad::is_inf_padding(begin) || pad::is_inf_padding(end)) + ? dim::inf_bound + : dim::padded(arg_shape[i].get_max_length(), pad_dim_diff_ub); + output_shape.emplace_back(lb, ub); + } else { + output_shape.emplace_back(lb); + } } else { output_shape.push_back(arg_shape[i]); } } } else { - NODE_VALIDATION_CHECK( + NODE_SHAPE_INFER_CHECK( op, - pads_begin_rank.is_dynamic() || - static_cast(pads_begin_shape[0].get_length()) <= static_cast(arg_rank_len), - "Number of elements of pads_begin must be >= 0 and <= arg rank " - "(pads_begin_shape[0]: ", - pads_begin_shape[0], - ")."); - NODE_VALIDATION_CHECK( + input_shapes, + pads_begin_rank.is_dynamic() || cmp::le(pads_begin_shape[0].get_length(), arg_rank_len), + "Number of elements of pads_begin must be >= 0 and <= arg rank"); + NODE_SHAPE_INFER_CHECK( op, - pads_begin_rank.is_dynamic() || - static_cast(pads_end_shape[0].get_length()) <= static_cast(arg_rank_len), - "Number of elements of pads_end must be >= 0 and <= arg rank (pads_end_shape[0]: ", - pads_end_shape[0], - ")."); + input_shapes, + pads_begin_rank.is_dynamic() || cmp::le(pads_end_shape[0].get_length(), arg_rank_len), + "Number of elements of pads_end must be >= 0 and <= arg rank"); output_shape.resize(arg_shape_rank.get_length()); } } else { diff --git a/src/core/tests/type_prop/pad.cpp b/src/core/tests/type_prop/pad.cpp index 5b6bd525bb2..4fcc29acb00 100644 --- a/src/core/tests/type_prop/pad.cpp +++ b/src/core/tests/type_prop/pad.cpp @@ -6,8 +6,10 @@ #include "common_test_utils/test_assertions.hpp" #include "common_test_utils/type_prop.hpp" +#include "gtest/gtest.h" #include "openvino/op/broadcast.hpp" #include "openvino/op/constant.hpp" +#include "openvino/op/pad.hpp" #include "openvino/op/shape_of.hpp" using namespace std; @@ -15,17 +17,17 @@ using namespace ov; using namespace testing; template -class PadTest : public testing::Test {}; +class PadTest : public TypePropOpTest {}; TYPED_TEST_SUITE_P(PadTest); TYPED_TEST_P(PadTest, pad_default_ctor) { const auto arg_shape = PartialShape{{1, 2}, {4, 10}, {3, 8}, {1, 2}}; - const auto arg = make_shared(element::f32, arg_shape); - const auto pads_begin = make_shared(element::i64, Shape{4}, std::vector{0, 2, 1, 0}); - const auto pads_end = make_shared(element::i64, Shape{4}, std::vector{0, 1, 1, 0}); + const auto arg = make_shared(element::f32, arg_shape); + const auto pads_begin = make_shared(element::i64, Shape{4}, std::vector{0, 2, 1, 0}); + const auto pads_end = make_shared(element::i64, Shape{4}, std::vector{0, 1, 1, 0}); - const auto pad = make_shared(); + const auto pad = this->make_op(); pad->set_arguments(OutputVector{arg, pads_begin, pads_end}); pad->set_pad_mode(op::PadMode::REFLECT); pad->validate_and_infer_types(); @@ -35,196 +37,119 @@ TYPED_TEST_P(PadTest, pad_default_ctor) { } TYPED_TEST_P(PadTest, pad_arg_pad_value_type_mismatch) { - auto arg = make_shared(element::f32, Shape{1, 2, 3}); - auto pads_begin = make_shared(element::i64, Shape{1}); - auto pads_end = make_shared(element::i64, Shape{1}); - auto arg_pad_value = make_shared(element::f16, Shape{1}); + auto arg = make_shared(element::f32, Shape{1, 2, 3}); + auto pads_begin = make_shared(element::i64, Shape{1}); + auto pads_end = make_shared(element::i64, Shape{1}); + auto arg_pad_value = make_shared(element::f16, Shape{1}); - try { - auto pad_v1 = make_shared(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::CONSTANT); - - // Should have thrown, so fail if it didn't - FAIL() << "Incorrect arg_pad_value type exception not handled"; - } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), std::string("Argument element types do not match (input arg element type:")); - } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; - } + OV_EXPECT_THROW(ignore = this->make_op(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::CONSTANT), + NodeValidationFailure, + HasSubstr("Argument element types do not match (input arg element type:")); } TYPED_TEST_P(PadTest, pad_arg_pad_value_shape_not_compatible) { - auto arg = make_shared(element::f32, Shape{1, 2, 3}); - auto pads_begin = make_shared(element::i64, Shape{1}); - auto pads_end = make_shared(element::i64, Shape{1}); - auto arg_pad_value = make_shared(element::f32, Shape{1}); + auto arg = make_shared(element::f32, Shape{1, 2, 3}); + auto pads_begin = make_shared(element::i64, Shape{1}); + auto pads_end = make_shared(element::i64, Shape{1}); + auto arg_pad_value = make_shared(element::f32, Shape{1}); - try { - auto pad_v1 = make_shared(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::CONSTANT); - - // Should have thrown, so fail if it didn't - FAIL() << "Incorrect arg_pad_value shape exception not handled"; - } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), std::string("Argument for padding value is not a scalar (shape:")); - } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; - } + OV_EXPECT_THROW(ignore = this->make_op(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::CONSTANT), + NodeValidationFailure, + HasSubstr("Argument for padding value is not a scalar")); } TYPED_TEST_P(PadTest, pad_pads_begin_shape_not_1D) { - auto arg = make_shared(element::f32, Shape{1, 2, 3}); - auto pads_begin = make_shared(element::i64, Shape{1, 2}); - auto pads_end = make_shared(element::i64, Shape{1}); + auto arg = make_shared(element::f32, Shape{1, 2, 3}); + auto pads_begin = make_shared(element::i64, Shape{1, 2}); + auto pads_end = make_shared(element::i64, Shape{1}); - try { - auto pad_v1 = make_shared(arg, pads_begin, pads_end, op::PadMode::SYMMETRIC); - - // Should have thrown, so fail if it didn't - FAIL() << "Incorrect pads_begin shape exception not handled"; - } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), std::string("Argument for pads_begin is not 1D (shape:")); - } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; - } + OV_EXPECT_THROW(ignore = this->make_op(arg, pads_begin, pads_end, op::PadMode::SYMMETRIC), + NodeValidationFailure, + HasSubstr("Argument for pads_begin is not 1D")); } TYPED_TEST_P(PadTest, pad_pads_end_shape_not_1D) { - auto arg = make_shared(element::f32, Shape{1, 2, 3}); - auto pads_begin = make_shared(element::i64, Shape{1}); - auto pads_end = make_shared(element::i64, Shape{1, 2}); + auto arg = make_shared(element::f32, Shape{1, 2, 3}); + auto pads_begin = make_shared(element::i64, Shape{1}); + auto pads_end = make_shared(element::i64, Shape{1, 2}); - try { - auto pad_v1 = make_shared(arg, pads_begin, pads_end, op::PadMode::SYMMETRIC); - - // Should have thrown, so fail if it didn't - FAIL() << "Incorrect pads_end shape exception not handled"; - } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), std::string("Argument for pads_end is not 1D (shape:")); - } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; - } + OV_EXPECT_THROW(ignore = this->make_op(arg, pads_begin, pads_end, op::PadMode::SYMMETRIC), + NodeValidationFailure, + HasSubstr("Argument for pads_end is not 1D")); } TYPED_TEST_P(PadTest, pad_pads_begin_size_not_correct) { - auto arg = make_shared(element::f32, Shape{1, 2, 3}); - auto pads_begin = make_shared(element::i64, Shape{4}); - auto pads_end = make_shared(element::i64, Shape{1}); + auto arg = make_shared(element::f32, Shape{1, 2, 3}); + auto pads_begin = make_shared(element::i64, Shape{4}); + auto pads_end = make_shared(element::i64, Shape{1}); - try { - auto pad_v1 = make_shared(arg, pads_begin, pads_end, op::PadMode::SYMMETRIC); - - // Should have thrown, so fail if it didn't - FAIL() << "Incorrect pads_begin size exception not handled"; - } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), - std::string("Number of elements of pads_begin must be >= 0 and <= arg " - "rank (pads_begin_shape[0]:")); - } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; - } + OV_EXPECT_THROW(ignore = this->make_op(arg, pads_begin, pads_end, op::PadMode::SYMMETRIC), + NodeValidationFailure, + HasSubstr("Number of elements of pads_begin must be >= 0 and <= arg rank")); } TYPED_TEST_P(PadTest, pad_pads_end_size_not_correct) { - auto arg = make_shared(element::f32, Shape{1, 2, 3}); - auto pads_begin = make_shared(element::i64, Shape{1}); - auto pads_end = make_shared(element::i64, Shape{4}); - auto arg_pad_value = make_shared(element::f32, Shape{}); + auto arg = make_shared(element::f32, Shape{1, 2, 3}); + auto pads_begin = make_shared(element::i64, Shape{1}); + auto pads_end = make_shared(element::i64, Shape{4}); + auto arg_pad_value = make_shared(element::f32, Shape{}); - try { - auto pad_v1 = make_shared(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::CONSTANT); - - // Should have thrown, so fail if it didn't - FAIL() << "Incorrect pads_end size exception not handled"; - } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING( - error.what(), - std::string("Number of elements of pads_end must be >= 0 and <= arg rank (pads_end_shape[0]:")); - } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; - } + OV_EXPECT_THROW(ignore = this->make_op(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::CONSTANT), + NodeValidationFailure, + HasSubstr("Number of elements of pads_end must be >= 0 and <= arg rank")); } TYPED_TEST_P(PadTest, pad_arg_pads_begin_incompatible_type) { - auto arg = make_shared(element::f32, Shape{1, 2, 3}); - auto pads_begin = make_shared(element::f32, Shape{1}); - auto pads_end = make_shared(element::i64, Shape{1}); + auto arg = make_shared(element::f32, Shape{1, 2, 3}); + auto pads_begin = make_shared(element::f32, Shape{1}); + auto pads_end = make_shared(element::i64, Shape{1}); - try { - auto pad_v1 = make_shared(arg, pads_begin, pads_end, op::PadMode::REFLECT); - - // Should have thrown, so fail if it didn't - FAIL() << "Incorrect pad_begin type exception not handled"; - } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), std::string("pads_begin must be an integral number, but is:")); - } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; - } + OV_EXPECT_THROW(this->make_op(arg, pads_begin, pads_end, op::PadMode::REFLECT), + NodeValidationFailure, + HasSubstr("pads_begin must be an integral number, but is:")); } TYPED_TEST_P(PadTest, pad_arg_pads_end_incompatible_type) { - auto arg = make_shared(element::f32, Shape{1, 2, 3}); - auto pads_begin = make_shared(element::i64, Shape{1}); - auto pads_end = make_shared(element::f32, Shape{1}); + auto arg = make_shared(element::f32, Shape{1, 2, 3}); + auto pads_begin = make_shared(element::i64, Shape{1}); + auto pads_end = make_shared(element::f32, Shape{1}); - try { - auto pad = make_shared(arg, pads_begin, pads_end, op::PadMode::REFLECT); - - // Should have thrown, so fail if it didn't - FAIL() << "Incorrect pads_end type exception not thrown"; - } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), std::string("pads_end must be an integral number, but is:")); - } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; - } + OV_EXPECT_THROW(this->make_op(arg, pads_begin, pads_end, op::PadMode::REFLECT), + NodeValidationFailure, + HasSubstr("pads_end must be an integral number, but is:")); } TYPED_TEST_P(PadTest, pad_deduce_too_small_for_edge) { - auto arg = make_shared(element::f32, Shape{1, 5, 0, 2}); - auto pads_begin = make_shared(element::i64, Shape{4}, std::vector{0, 1, 2, 3}); - auto pads_end = make_shared(element::i64, Shape{4}, std::vector{0, 1, 2, 3}); - auto arg_pad_value = make_shared(element::f32, Shape{}); + auto arg = make_shared(element::f32, Shape{1, 5, 0, 2}); + auto pads_begin = make_shared(element::i64, Shape{4}, std::vector{0, 1, 2, 3}); + auto pads_end = make_shared(element::i64, Shape{4}, std::vector{0, 1, 2, 3}); + auto arg_pad_value = make_shared(element::f32, Shape{}); - try { - auto pad_v1 = make_shared(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::EDGE); - - // Should have thrown, so fail if it didn't - FAIL() << "Incorrect input shape exception for EDGE mode not thrown"; - } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), - std::string("EDGE padding mode requires an input of dimension of at " - "least 1 at each spatial axis")); - } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; - } + OV_EXPECT_THROW(this->make_op(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::EDGE), + NodeValidationFailure, + HasSubstr("EDGE padding mode requires an input of dimension of at least 1 at each spatial axis")); } TYPED_TEST_P(PadTest, pad_deduce_too_small_for_reflect) { - auto arg = make_shared(element::f32, Shape{1, 5, 1, 2}); - auto pads_begin = make_shared(element::i64, Shape{4}, std::vector{0, 1, 2, 3}); - auto pads_end = make_shared(element::i64, Shape{4}, std::vector{0, 1, 2, 3}); - auto arg_pad_value = make_shared(element::f32, Shape{}); + auto arg = make_shared(element::f32, Shape{1, 5, 1, 2}); + auto pads_begin = make_shared(element::i64, Shape{4}, std::vector{0, 1, 2, 3}); + auto pads_end = make_shared(element::i64, Shape{4}, std::vector{0, 1, 2, 3}); + auto arg_pad_value = make_shared(element::f32, Shape{}); - try { - auto pad_v1 = make_shared(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::REFLECT); - - // Should have thrown, so fail if it didn't - FAIL() << "Incorrect input shape exception for REFLECT mode not thrown"; - } catch (const NodeValidationFailure& error) { - EXPECT_HAS_SUBSTRING(error.what(), - std::string("REFLECT padding mode requires an input of dimension of " - "at least 2 at each spatial axis")); - } catch (...) { - FAIL() << "Deduced type check failed for unexpected reason"; - } + OV_EXPECT_THROW( + this->make_op(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::REFLECT), + NodeValidationFailure, + HasSubstr("REFLECT padding mode requires an input of dimension of at least 2 at each spatial axis")); } TYPED_TEST_P(PadTest, pad_pads_end_got_negative_value) { auto arg_shape = PartialShape{-1, {0, 10}, {2, -1}, {2, 8}, {3, 10}, 5}; set_shape_labels(arg_shape, 10); - const auto arg = std::make_shared(element::f32, arg_shape); - const auto pads_begin = ov::op::v0::Constant::create(element::i64, Shape{6}, {2, 0, 1, 3, 2, 1}); - const auto pads_end = ov::op::v0::Constant::create(element::i64, Shape{6}, {-3, -2, -2, -3, -1, -3}); + const auto arg = std::make_shared(element::f32, arg_shape); + const auto pads_begin = op::v0::Constant::create(element::i64, Shape{6}, {2, 0, 1, 3, 2, 1}); + const auto pads_end = op::v0::Constant::create(element::i64, Shape{6}, {-3, -2, -2, -3, -1, -3}); - const auto pad = make_shared(arg, pads_begin, pads_end, op::PadMode::REFLECT); + const auto pad = this->make_op(arg, pads_begin, pads_end, op::PadMode::REFLECT); EXPECT_EQ(pad->get_output_partial_shape(0), PartialShape({-1, {0, 8}, {1, -1}, {2, 8}, {4, 11}, 3})); EXPECT_THAT(get_shape_labels(pad->get_output_partial_shape(0)), @@ -234,9 +159,9 @@ TYPED_TEST_P(PadTest, pad_pads_end_got_negative_value) { TYPED_TEST_P(PadTest, pad_pads_begin_got_negative_value) { auto arg_shape = PartialShape{-1, {0, 10}, {2, -1}, {2, 8}, {3, 10}, 5}; set_shape_labels(arg_shape, 10); - const auto arg = std::make_shared(element::f32, arg_shape); - const auto pads_begin = ov::op::v0::Constant::create(element::i64, Shape{6}, {-1, -1, -2, -3, -8, -4}); - const auto pads_end = ov::op::v0::Constant::create(element::i64, Shape{6}, {0, 2, 0, 3, 5, 4}); + const auto arg = std::make_shared(element::f32, arg_shape); + const auto pads_begin = op::v0::Constant::create(element::i64, Shape{6}, {-1, -1, -2, -3, -8, -4}); + const auto pads_end = op::v0::Constant::create(element::i64, Shape{6}, {0, 2, 0, 3, 5, 4}); const auto pad = make_shared(arg, pads_begin, pads_end, op::PadMode::REFLECT); EXPECT_EQ(pad->get_output_partial_shape(0), PartialShape({-1, {1, 11}, {0, -1}, {2, 8}, {0, 7}, 5})); @@ -245,12 +170,12 @@ TYPED_TEST_P(PadTest, pad_pads_begin_got_negative_value) { } TYPED_TEST_P(PadTest, pad_dynamic_output_with_dynamic_rank) { - auto arg = make_shared(element::f32, PartialShape::dynamic()); - auto pads_begin = make_shared(element::i32, Shape{1}); - auto pads_end = make_shared(element::i32, Shape{1}); - auto arg_pad_value = ov::op::v0::Constant::create(element::f32, Shape{}, {0}); + auto arg = make_shared(element::f32, PartialShape::dynamic()); + auto pads_begin = make_shared(element::i32, Shape{1}); + auto pads_end = make_shared(element::i32, Shape{1}); + auto arg_pad_value = op::v0::Constant::create(element::f32, Shape{}, {0}); - auto pad = make_shared(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::CONSTANT); + auto pad = this->make_op(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::CONSTANT); ASSERT_EQ(pad->get_output_partial_shape(0), PartialShape::dynamic()); } @@ -279,25 +204,23 @@ TYPED_TEST_P(PadTest, pad_any_dim_for_padding_reflect) { TYPED_TEST_P(PadTest, pad_any_dim_for_padding_edge) { auto arg_shape = PartialShape{1, {0, 48}, -1, {20, -1}, {5, -1}, 10, 12}; set_shape_labels(arg_shape, 10); - auto arg = make_shared(element::f32, arg_shape); - auto pads_begin = - make_shared(element::i64, Shape{7}, std::vector{1, 2, 1, 2, 0, 0, 0}); - auto pads_end = - make_shared(element::i64, Shape{7}, std::vector{0, 3, 0, 1, 0, 5, 0}); + auto arg = make_shared(element::f32, arg_shape); + auto pads_begin = make_shared(element::i64, Shape{7}, std::vector{1, 2, 1, 2, 0, 0, 0}); + auto pads_end = make_shared(element::i64, Shape{7}, std::vector{0, 3, 0, 1, 0, 5, 0}); - auto pad = make_shared(arg, pads_begin, pads_end, op::PadMode::EDGE); + auto pad = this->make_op(arg, pads_begin, pads_end, op::PadMode::EDGE); EXPECT_EQ(pad->get_output_partial_shape(0), PartialShape({2, {5, 53}, {1, -1}, {23, -1}, {5, -1}, 15, 12})); EXPECT_THAT(get_shape_labels(pad->get_output_partial_shape(0)), ElementsAre(ov::no_label, ov::no_label, ov::no_label, ov::no_label, 14, ov::no_label, 16)); } TYPED_TEST_P(PadTest, pad_dynamic_input_type_with_static_value) { - auto arg = make_shared(element::dynamic, Shape{1, 2, 3}); - auto pads_begin = make_shared(element::i32, Shape{1}); - auto pads_end = make_shared(element::i32, Shape{1}); - auto arg_pad_value = ov::op::v0::Constant::create(element::f32, Shape{}, {0}); + auto arg = make_shared(element::dynamic, Shape{1, 2, 3}); + auto pads_begin = make_shared(element::i32, Shape{1}); + auto pads_end = make_shared(element::i32, Shape{1}); + auto arg_pad_value = op::v0::Constant::create(element::f32, Shape{}, {0}); - auto pad = make_shared(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::CONSTANT); + auto pad = this->make_op(arg, pads_begin, pads_end, arg_pad_value, op::PadMode::CONSTANT); EXPECT_EQ(pad->get_output_element_type(0), element::f32); EXPECT_EQ(pad->get_output_partial_shape(0), PartialShape::dynamic(3)); } @@ -310,11 +233,11 @@ TYPED_TEST_P(PadTest, pad_preserve_partial_values_and_labels_via_evaluates_bound set_shape_labels(begin_shape, 20); set_shape_labels(end_shape, 30); - auto arg = make_shared(element::f32, arg_shape); - auto s_begin = make_shared(make_shared(element::i64, begin_shape)); - auto s_end = make_shared(make_shared(element::i64, end_shape)); + auto arg = make_shared(element::f32, arg_shape); + auto s_begin = make_shared(make_shared(element::i64, begin_shape)); + auto s_end = make_shared(make_shared(element::i64, end_shape)); - auto pad = make_shared(arg, s_begin, s_end, op::PadMode::EDGE); + auto pad = this->make_op(arg, s_begin, s_end, op::PadMode::EDGE); EXPECT_EQ(pad->get_output_partial_shape(0), PartialShape({{4, 7}, {2, 5}, {2, 6}})); EXPECT_THAT(get_shape_labels(pad->get_output_partial_shape(0)), ElementsAre(ov::no_label, 11, ov::no_label)); @@ -323,20 +246,38 @@ TYPED_TEST_P(PadTest, pad_preserve_partial_values_and_labels_via_evaluates_bound TYPED_TEST_P(PadTest, pad_preserve_partial_values_and_labels_on_inputs) { auto arg_shape = PartialShape{1, {2, 5}, {1, 3}}; set_shape_labels(arg_shape, 10); - auto arg = make_shared(element::i32, arg_shape); + auto arg = make_shared(element::i32, arg_shape); auto s = make_shared(arg); - auto pads_begin = make_shared(element::i64, Shape{1}, std::vector{1}); - auto pads_end = make_shared(element::i64, Shape{1}, std::vector{2}); + auto pads_begin = make_shared(element::i64, Shape{1}, std::vector{1}); + auto pads_end = make_shared(element::i64, Shape{1}, std::vector{2}); - auto pad = make_shared(s, pads_begin, pads_end, op::PadMode::EDGE); - auto param = make_shared(element::f32, PartialShape{1}); + auto pad = this->make_op(s, pads_begin, pads_end, op::PadMode::EDGE); + auto param = make_shared(element::f32, PartialShape{1}); auto bc = std::make_shared(param, pad, op::BroadcastType::BIDIRECTIONAL); EXPECT_EQ(bc->get_output_partial_shape(0), PartialShape({1, 1, {2, 5}, {1, 3}, {1, 3}, {1, 3}})); EXPECT_THAT(get_shape_labels(bc->get_output_partial_shape(0)), ElementsAre(10, 10, 11, 12, 12, 12)); } +TYPED_TEST_P(PadTest, pad_begin_and_end_has_inf_interval_as_bounds) { + auto arg_shape = PartialShape{9, {3, 5}, {3, 5}, {3, 4}, {3, 4}}; + auto begin_shape = PartialShape{-1, {0, 2}, -1, -1, {0, 1}}; + auto end_shape = PartialShape{-1, -1, {0, 2}, {0, 1}, -1}; + set_shape_labels(arg_shape, 10); + set_shape_labels(begin_shape, 20); + set_shape_labels(end_shape, 30); + + auto arg = make_shared(element::f32, arg_shape); + auto s_begin = make_shared(make_shared(element::i32, begin_shape)); + auto s_end = make_shared(make_shared(element::i32, end_shape)); + + auto pad = this->make_op(arg, s_begin, s_end, op::PadMode::CONSTANT); + + EXPECT_EQ(pad->get_output_partial_shape(0), PartialShape({{9, -1}, {3, -1}, {3, -1}, {3, -1}, {3, -1}})); + EXPECT_THAT(get_shape_labels(pad->get_output_partial_shape(0)), Each(ov::no_label)); +} + REGISTER_TYPED_TEST_SUITE_P(PadTest, pad_default_ctor, pad_arg_pad_value_type_mismatch, @@ -357,6 +298,7 @@ REGISTER_TYPED_TEST_SUITE_P(PadTest, pad_any_dim_for_padding_edge, pad_dynamic_input_type_with_static_value, pad_preserve_partial_values_and_labels_via_evaluates_bounds, + pad_begin_and_end_has_inf_interval_as_bounds, pad_preserve_partial_values_and_labels_on_inputs); using PadOpTypes = Types;