Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Ref][Core][Opset13] Add BitwiseNot operation #19956

Merged
merged 17 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/core/include/openvino/op/bitwise_not.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include "openvino/op/op.hpp"

namespace ov {
namespace op {
namespace v13 {
/// \brief Elementwise bitwise negation operation.
/// \ingroup ov_ops_cpp_api
class OPENVINO_API BitwiseNot : public op::Op {
public:
OPENVINO_OP("BitwiseNot", "opset13", op::Op);
/// \brief Constructs a bitwise negation operation.
BitwiseNot() = default;
/// \brief Constructs a bitwise negation operation.
///
/// \param arg Node that produces the input tensor.
BitwiseNot(const Output<Node>& arg);

void validate_and_infer_types() override;

std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
};
} // namespace v13
} // namespace op
} // namespace ov
1 change: 1 addition & 0 deletions src/core/include/openvino/op/ops.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "openvino/op/batch_norm.hpp"
#include "openvino/op/batch_to_space.hpp"
#include "openvino/op/binary_convolution.hpp"
#include "openvino/op/bitwise_not.hpp"
#include "openvino/op/broadcast.hpp"
#include "openvino/op/bucketize.hpp"
#include "openvino/op/ceiling.hpp"
Expand Down
1 change: 1 addition & 0 deletions src/core/include/openvino/opsets/opset13_tbl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,4 @@ _OPENVINO_OP_REG(Pad, ov::op::v12)
_OPENVINO_OP_REG(ScatterElementsUpdate, ov::op::v12)

// New operations added in opset13
_OPENVINO_OP_REG(BitwiseNot, ov::op::v13)
36 changes: 36 additions & 0 deletions src/core/reference/include/openvino/reference/bitwise_not.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include <algorithm>
#include <cstddef>

namespace ov {
namespace reference {
namespace func {
// Check for char datatype used by ov::element::boolean
template <class T, typename std::enable_if<std::is_same<typename std::decay<T>::type, char>::value>::type* = nullptr>
T bitwise_not(const T in) {
return static_cast<T>(!in);
}

template <class T, typename std::enable_if<!std::is_same<typename std::decay<T>::type, char>::value>::type* = nullptr>
T bitwise_not(const T in) {
return static_cast<T>(~in);
}
} // namespace func
/**
* @brief Reference implementation of BitwiseNot operator.
*
* @param in Input pointer to data.
* @param out Output pointer to results.
* @param count Number of elements in input buffer.
*/
template <class T>
void bitwise_not(const T* in, T* out, size_t count) {
std::transform(in, std::next(in, count), out, &func::bitwise_not<T>);
}
} // namespace reference
} // namespace ov
33 changes: 33 additions & 0 deletions src/core/src/op/bitwise_not.cpp
mmikolajcz marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/bitwise_not.hpp"

#include "itt.hpp"
#include "openvino/core/validation_util.hpp"
#include "openvino/op/op.hpp"

namespace ov {
namespace op {
namespace v13 {
BitwiseNot::BitwiseNot(const Output<Node>& arg) : op::Op({arg}) {
constructor_validate_and_infer_types();
}
void BitwiseNot::validate_and_infer_types() {
OV_OP_SCOPE(v13_BitwiseNot_validate_and_infer_types);
const auto& element_type = get_input_element_type(0);
NODE_VALIDATION_CHECK(this,
element_type.is_dynamic() || element_type.is_integral(),
"The element type of the input tensor must be integer or boolean.");
set_output_type(0, element_type, get_input_partial_shape(0));
}

std::shared_ptr<Node> BitwiseNot::clone_with_new_inputs(const OutputVector& new_args) const {
OV_OP_SCOPE(v13_BitwiseNot_clone_with_new_inputs);
check_new_args_count(this, new_args);
return std::make_shared<BitwiseNot>(new_args.at(0));
}

} // namespace v13
} // namespace op
} // namespace ov
1 change: 1 addition & 0 deletions src/core/tests/op_version_tbl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ _OPENVINO_OP_REG(AvgPool, ov::op::v1)
_OPENVINO_OP_REG(BatchNormInference, ov::op::v0)
_OPENVINO_OP_REG(BatchToSpace, ov::op::v1)
_OPENVINO_OP_REG(BinaryConvolution, ov::op::v1)
_OPENVINO_OP_REG(BitwiseNot, ov::op::v13)
_OPENVINO_OP_REG(Broadcast, ov::op::v1)
_OPENVINO_OP_REG(Broadcast, ov::op::v3)
_OPENVINO_OP_REG(Bucketize, ov::op::v3)
Expand Down
2 changes: 1 addition & 1 deletion src/core/tests/opset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ INSTANTIATE_TEST_SUITE_P(opset,
OpsetTestParams{ov::get_opset10, 177},
OpsetTestParams{ov::get_opset11, 177},
OpsetTestParams{ov::get_opset12, 178},
OpsetTestParams{ov::get_opset13, 178}),
OpsetTestParams{ov::get_opset13, 179}),
OpsetTestNameGenerator{});

class MyOpOld : public ov::op::Op {
Expand Down
85 changes: 85 additions & 0 deletions src/core/tests/type_prop/bitwise_not.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "openvino/op/bitwise_not.hpp"

#include <gtest/gtest.h>

#include "common_test_utils/test_assertions.hpp"
#include "common_test_utils/type_prop.hpp"

using namespace ov;
using namespace testing;

using BitwiseNotTestParam = std::tuple<element::Type, PartialShape>;

namespace {
using namespace ov::element;
constexpr size_t exp_num_of_outputs = 1;

const auto types = Values(boolean, i8, i16, i32, i64, u8, u16, u32, u64);

const auto static_shapes = Values(PartialShape{0}, PartialShape{1}, PartialShape{2, 3, 7, 8});
const auto dynamic_shapes =
Values(PartialShape::dynamic(3), PartialShape{2, {0, 5}, {4, -1}, -1, {3, 8}}, PartialShape::dynamic());
} // namespace

class BitwiseNotTest : public TypePropOpTest<ov::op::v13::BitwiseNot>, public WithParamInterface<BitwiseNotTestParam> {
protected:
void SetUp() override {
std::tie(exp_type, exp_shape) = GetParam();
}

element::Type exp_type;
PartialShape exp_shape;
mmikolajcz marked this conversation as resolved.
Show resolved Hide resolved
};

INSTANTIATE_TEST_SUITE_P(type_prop_static_shape,
BitwiseNotTest,
Combine(types, static_shapes),
PrintToStringParamName());
INSTANTIATE_TEST_SUITE_P(type_prop_dynamic_shape,
BitwiseNotTest,
Combine(types, dynamic_shapes),
PrintToStringParamName());

TEST_P(BitwiseNotTest, propagate_dimensions) {
const auto input = std::make_shared<ov::op::v0::Parameter>(exp_type, exp_shape);
const auto op = make_op(input);

EXPECT_EQ(op->get_element_type(), exp_type);
EXPECT_EQ(op->get_output_size(), exp_num_of_outputs);
EXPECT_EQ(op->get_output_partial_shape(0), exp_shape);
}

TEST_P(BitwiseNotTest, propagate_labels) {
if (exp_shape.rank().is_static()) {
set_shape_labels(exp_shape, 10);
}
const auto exp_labels = get_shape_labels(exp_shape);

const auto input = std::make_shared<ov::op::v0::Parameter>(exp_type, exp_shape);
const auto op = make_op(input);

EXPECT_EQ(get_shape_labels(op->get_output_partial_shape(0)), exp_labels);
}

TEST_P(BitwiseNotTest, default_ctor) {
const auto op = make_op();
const auto input = std::make_shared<ov::op::v0::Parameter>(exp_type, exp_shape);

op->set_argument(0, input);
op->validate_and_infer_types();

EXPECT_EQ(op->get_element_type(), exp_type);
EXPECT_EQ(op->get_output_size(), exp_num_of_outputs);
EXPECT_EQ(op->get_output_partial_shape(0), exp_shape);
}

TEST(BitwiseNotTest, invalid_element_type) {
auto data = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{2, 2});
OV_EXPECT_THROW(std::ignore = std::make_shared<ov::op::v13::BitwiseNot>(data),
ov::NodeValidationFailure,
HasSubstr("The element type of the input tensor must be integer or boolean."));
}
11 changes: 11 additions & 0 deletions src/core/tests/visitors/op/bitwise_not.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "openvino/op/bitwise_not.hpp"

#include "unary_ops.hpp"

using Type = ::testing::Types<UnaryOperatorType<ov::op::v13::BitwiseNot, ov::element::i32>>;

INSTANTIATE_TYPED_TEST_SUITE_P(visitor_without_attribute, UnaryOperatorVisitor, Type, UnaryOperatorTypeName);
52 changes: 52 additions & 0 deletions src/plugins/template/backend/ops/bitwise_not.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "openvino/op/bitwise_not.hpp"

#include "evaluate_node.hpp"
#include "openvino/reference/bitwise_not.hpp"
#include "utils.hpp"

using namespace ov;

template <element::Type_t ET>
bool evaluate(const std::shared_ptr<ov::op::v13::BitwiseNot>& node,
ov::TensorVector& outputs,
const ov::TensorVector& inputs) {
OPENVINO_ASSERT(inputs.size() == 1);
OPENVINO_ASSERT(outputs.size() == 1);
outputs[0].set_shape(inputs[0].get_shape());

using T = typename ov::element_type_traits<ET>::value_type;
ov::reference::bitwise_not(inputs[0].data<T>(), outputs[0].data<T>(), shape_size(inputs[0].get_shape()));
return true;
}

template <>
bool evaluate_node<op::v13::BitwiseNot>(std::shared_ptr<ov::Node> node,
ov::TensorVector& outputs,
const ov::TensorVector& inputs) {
switch (node->get_input_element_type(0)) {
case element::boolean:
return evaluate<element::boolean>(as_type_ptr<op::v13::BitwiseNot>(node), outputs, inputs);
case element::u8:
return evaluate<element::u8>(as_type_ptr<op::v13::BitwiseNot>(node), outputs, inputs);
case element::i8:
return evaluate<element::i8>(as_type_ptr<op::v13::BitwiseNot>(node), outputs, inputs);
case element::u16:
return evaluate<element::u16>(as_type_ptr<op::v13::BitwiseNot>(node), outputs, inputs);
case element::i16:
return evaluate<element::i16>(as_type_ptr<op::v13::BitwiseNot>(node), outputs, inputs);
case element::u32:
return evaluate<element::u32>(as_type_ptr<op::v13::BitwiseNot>(node), outputs, inputs);
case element::i32:
return evaluate<element::i32>(as_type_ptr<op::v13::BitwiseNot>(node), outputs, inputs);
case element::u64:
return evaluate<element::u64>(as_type_ptr<op::v13::BitwiseNot>(node), outputs, inputs);
case element::i64:
return evaluate<element::i64>(as_type_ptr<op::v13::BitwiseNot>(node), outputs, inputs);
default:
OPENVINO_THROW("Unhandled data type ", node->get_element_type().get_type_name(), "in evaluate_node()");
}
}
4 changes: 4 additions & 0 deletions src/plugins/template/backend/ops/ops_evaluates.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,10 @@ extern template bool evaluate_node<ov::op::v12::GroupNormalization>(std::shared_
ov::TensorVector& outputs,
const ov::TensorVector& inputs);

extern template bool evaluate_node<ov::op::v13::BitwiseNot>(std::shared_ptr<ov::Node> node,
ov::TensorVector& outputs,
const ov::TensorVector& inputs);

extern template bool evaluate_node<ov::op::internal::AUGRUCell>(std::shared_ptr<ov::Node> node,
ov::TensorVector& outputs,
const ov::TensorVector& inputs);
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/template/backend/opset_int_tbl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,5 +150,7 @@ _OPENVINO_OP_REG(Interpolate, op::v11)

_OPENVINO_OP_REG(GroupNormalization, ov::op::v12)

_OPENVINO_OP_REG(BitwiseNot, ov::op::v13)

_OPENVINO_OP_REG(AUGRUCell, ov::op::internal)
_OPENVINO_OP_REG(AUGRUSequence, ov::op::internal)
1 change: 1 addition & 0 deletions src/plugins/template/src/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ ov::SupportedOpsMap ov::template_plugin::Plugin::query_model(const std::shared_p
#include "openvino/opsets/opset10_tbl.hpp"
#include "openvino/opsets/opset11_tbl.hpp"
#include "openvino/opsets/opset12_tbl.hpp"
#include "openvino/opsets/opset13_tbl.hpp"
// clang-format on
#undef _OPENVINO_OP_REG
return op_super_set.contains_type(node->get_type_info());
Expand Down
17 changes: 17 additions & 0 deletions src/plugins/template/tests/functional/op_reference/bitwise.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "bitwise.hpp"

namespace reference_tests {
namespace BitwiseOpsRefTestDefinitions {
namespace {

TEST_P(ReferenceBitwiseLayerTest, BitwiseWithHardcodedRefs) {
Exec();
}

} // namespace
} // namespace BitwiseOpsRefTestDefinitions
} // namespace reference_tests
Loading