| repeat | No |
| rnn | No |
| rnn_param_concat | No |
+| round | No |
| sigmoid | No |
| slice | No |
| slice_axis | No |
| Reshape | No |
| Resize | Coordinate transformation mode `tf_crop_and_resize` is not supported, `nearest` mode is not supported for 5D+ inputs. |
| ReverseSequence | No |
+| Round | No |
| Scatter | Supported if fuse-able to ScatterUpdate. MYRIAD only |
| ScatterND | No |
| ScatterElements | Supported if fuse-able to ScatterUpdate. MYRIAD only |
--- /dev/null
+// Copyright (C) 2018-2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include <string>
+#include "ngraph_reader_tests.hpp"
+TEST_F(NGraphReaderTests, ReadRoundEvenNetwork) {
+ std::string model = R"V0G0N(
+<net name="Network" version="10">
+ <layers>
+ <layer name="in1" type="Parameter" id="0" version="opset1">
+ <data element_type="f32" shape="1,3,22,22"/>
+ <output>
+ <port id="0" precision="FP32">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </output>
+ </layer>
+ <layer name="Round" id="1" type="Round" version="opset5">
+ <data mode="half_to_even"/>
+ <input>
+ <port id="1" precision="FP32">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </input>
+ <output>
+ <port id="2" precision="FP32">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </output>
+ </layer>
+ <layer name="output" type="Result" id="2" version="opset1">
+ <input>
+ <port id="0" precision="FP32">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </input>
+ </layer>
+ </layers>
+ <edges>
+ <edge from-layer="0" from-port="0" to-layer="1" to-port="1"/>
+ <edge from-layer="1" from-port="2" to-layer="2" to-port="0"/>
+ </edges>
+</net>
+)V0G0N";
+ std::string modelV5 = R"V0G0N(
+<net name="Network" version="5" precision="FP32" batch="1">
+ <layers>
+ <layer name="in1" type="Input" precision="FP32" id="0">
+ <output>
+ <port id="0">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </output>
+ </layer>
+ <layer name="Round" id="1" type="Round" version="opset5">
+ <data mode="half_to_even"/>
+ <input>
+ <port id="1">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </input>
+ <output>
+ <port id="2">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </output>
+ </layer>
+ </layers>
+ <edges>
+ <edge from-layer="0" from-port="0" to-layer="1" to-port="1"/>
+ </edges>
+</net>
+)V0G0N";
+
+ compareIRs(model, modelV5, 0);
+}
+
+TEST_F(NGraphReaderTests, ReadRoundAwayNetwork) {
+ std::string model = R"V0G0N(
+<net name="Network" version="10">
+ <layers>
+ <layer name="in1" type="Parameter" id="0" version="opset1">
+ <data element_type="f32" shape="1,3,22,22"/>
+ <output>
+ <port id="0" precision="FP32">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </output>
+ </layer>
+ <layer name="Round" id="1" type="Round" version="opset5">
+ <data mode="half_away_from_zero"/>
+ <input>
+ <port id="1" precision="FP32">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </input>
+ <output>
+ <port id="2" precision="FP32">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </output>
+ </layer>
+ <layer name="output" type="Result" id="2" version="opset1">
+ <input>
+ <port id="0" precision="FP32">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </input>
+ </layer>
+ </layers>
+ <edges>
+ <edge from-layer="0" from-port="0" to-layer="1" to-port="1"/>
+ <edge from-layer="1" from-port="2" to-layer="2" to-port="0"/>
+ </edges>
+</net>
+)V0G0N";
+ std::string modelV5 = R"V0G0N(
+<net name="Network" version="5" precision="FP32" batch="1">
+ <layers>
+ <layer name="in1" type="Input" precision="FP32" id="0">
+ <output>
+ <port id="0">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </output>
+ </layer>
+ <layer name="Round" id="1" type="Round" version="opset5">
+ <data mode="half_away_from_zero"/>
+ <input>
+ <port id="1">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </input>
+ <output>
+ <port id="2">
+ <dim>1</dim>
+ <dim>3</dim>
+ <dim>22</dim>
+ <dim>22</dim>
+ </port>
+ </output>
+ </layer>
+ </layers>
+ <edges>
+ <edge from-layer="0" from-port="0" to-layer="1" to-port="1"/>
+ </edges>
+</net>
+)V0G0N";
+
+compareIRs(model, modelV5, 0);
+}
import numpy as np
from extensions.ops.elementwise import Mul, Sub, Add, Maximum, Minimum, Div, Greater, GreaterEqual, Equal, Less, \
- LessEqual, Pow, NotEqual, LogicalAnd, LogicalOr
+ LessEqual, Pow, NotEqual, LogicalAnd, LogicalOr, Round
from mo.front.extractor import FrontExtractorOp
from mo.front.mxnet.extractors.utils import get_mxnet_layer_attrs
from mo.graph.graph import Node
def extract(cls, node):
AttributedPower.update_node_stat(node, {'scale': 0, 'shift': 1})
return cls.enabled
+
+
+class RoundExtractor(FrontExtractorOp):
+ op = 'round'
+ enabled = True
+
+ @classmethod
+ def extract(cls, node):
+ Round.update_node_stat(node, {'mode': 'half_away_from_zero'})
+ return cls.enabled
import numpy as np
from extensions.ops.elementwise import Add, Sub, Mul, Div, Pow, Less, Equal, Greater, \
- LogicalAnd, LogicalOr, LogicalXor
+ LogicalAnd, LogicalOr, LogicalXor, Round
from mo.front.extractor import FrontExtractorOp
from mo.front.onnx.extractors.utils import onnx_attr
from mo.graph.graph import Node
def extract(cls, node):
LogicalXor.update_node_stat(node)
return cls.enabled
+
+
+class RoundFrontExtractor(FrontExtractorOp):
+ op = 'Round'
+ enabled = True
+
+ @classmethod
+ def extract(cls, node: Node):
+ Round.update_node_stat(node, {'mode': 'half_to_even'})
+ return cls.enabled
limitations under the License.
"""
from extensions.ops.elementwise import Add, Mul, Sub, Div, Maximum, Minimum, Pow, LogicalAnd, LogicalOr, Equal, \
- GreaterEqual, Greater, Less, LessEqual, NotEqual, FloorMod, BiasAdd, SquaredDifference
+ GreaterEqual, Greater, Less, LessEqual, NotEqual, FloorMod, BiasAdd, SquaredDifference, Round
from mo.front.extractor import FrontExtractorOp
from mo.front.tf.extractors.utils import tf_dtype_extractor
from mo.ops.eltwise_n import EltwiseNAdd
def extract(cls, node):
FloorMod.update_node_stat(node)
return cls.enabled
+
+
+class RoundExtractor(FrontExtractorOp):
+ op = 'Round'
+ enabled = True
+
+ @classmethod
+ def extract(cls, node):
+ Round.update_node_stat(node, {'mode': 'half_to_even'})
+ return cls.enabled
operation = None
op = None
op_type = None
+ version = 'opset1'
def __init__(self, graph: Graph, attrs: dict):
super().__init__(graph, {
'op': self.op,
'type': self.op_type,
- 'version': 'opset1',
+ 'version': self.version,
'infer': lambda node: eltwise_infer(node, self.operation),
'type_infer': self.type_infer,
'can_be_bias': True,
node.out_port(0).set_data_type(node.in_port(0).get_data_type())
+class UnaryElementwise(Elementwise):
+ def __init__(self, graph: Graph, attrs: dict):
+ super().__init__(graph, {**{
+ 'in_ports_count': 1,
+ }, **attrs})
+
+ @staticmethod
+ def type_infer(node):
+ copy_type_infer(node)
+
+
class Add(Elementwise):
- enabled = False
op = 'Add'
op_type = 'Add'
operation = staticmethod(lambda a, b: a + b)
class Sub(Elementwise):
- enabled = False
op = 'Sub'
op_type = 'Subtract'
operation = staticmethod(lambda a, b: a - b)
class Mul(Elementwise):
- enabled = False
op = 'Mul'
op_type = 'Multiply'
operation = staticmethod(lambda a, b: a * b)
class Div(Elementwise):
- enabled = False
op = 'Div'
op_type = 'Divide'
operation = staticmethod(lambda a, b: a // b if both_types_are_integer(a, b) else a / b)
class SquaredDifference(Elementwise):
- enabled = False
op = 'SquaredDifference'
op_type = 'SquaredDifference'
operation = staticmethod(lambda a, b: (a - b) * (a - b))
class Pow(Elementwise):
- enabled = False
op = 'Pow'
op_type = 'Power'
class Greater(LogicalElementwise):
- enabled = False
op = 'Greater'
op_type = 'Greater'
operation = staticmethod(lambda a, b: a > b)
class GreaterEqual(LogicalElementwise):
- enabled = False
op = 'GreaterEqual'
op_type = 'GreaterEqual'
operation = staticmethod(lambda a, b: a >= b)
class Less(LogicalElementwise):
- enabled = False
op = 'Less'
op_type = 'Less'
operation = staticmethod(lambda a, b: a < b)
class LessEqual(LogicalElementwise):
- enabled = False
op = 'LessEqual'
op_type = 'LessEqual'
operation = staticmethod(lambda a, b: a <= b)
class Equal(LogicalElementwise):
- enabled = False
op = 'Equal'
op_type = 'Equal'
operation = staticmethod(lambda a, b: a == b)
class NotEqual(LogicalElementwise):
- enabled = False
op = 'NotEqual'
op_type = 'NotEqual'
operation = staticmethod(lambda a, b: a != b)
class Maximum(Elementwise):
- enabled = False
op = 'Maximum'
op_type = 'Maximum'
operation = staticmethod(lambda a, b: np.maximum(a, b))
class Minimum(Elementwise):
- enabled = False
op = 'Minimum'
op_type = 'Minimum'
operation = staticmethod(lambda a, b: np.minimum(a, b))
-class Round(Elementwise):
- enabled = False
+class Round(UnaryElementwise):
op = 'Round'
- op_type = None
- version = 'extension'
- operation = staticmethod(lambda a: np.round(a))
+ op_type = 'Round'
+ version = 'opset5'
+
+ def __init__(self, graph: Graph, attrs):
+ round_attrs = {'mode': 'half_to_even',
+ 'infer': self.infer
+ }
+ round_attrs.update(attrs)
+ super().__init__(graph, round_attrs)
+
+ def backend_attrs(self):
+ return ['mode']
+
+ @classmethod
+ def infer(cls, node: Node):
+ node.out_port(0).data.set_shape(node.in_port(0).data.get_shape())
+
+ a = node.in_port(0).data.get_value()
+ if a is not None:
+ assert node.soft_get('mode') in ['half_to_even', 'half_away_from_zero'], \
+ 'Round node {} has unsupported "mode" attribute value: {}'.format(node.soft_get('name', node.id),
+ node.soft_get('mode'))
+ if node.mode == 'half_away_from_zero':
+ mask = (a >= 0)
+ out = np.empty_like(a)
+ out[mask] = np.floor(a[mask] + 0.5)
+ out[~mask] = np.ceil(a[~mask] - 0.5)
+ else:
+ out = np.round(a)
+ node.out_port(0).data.set_value(out)
class LogicalOr(LogicalElementwise):
- enabled = False
op = 'LogicalOr'
op_type = 'LogicalOr'
operation = staticmethod(lambda a, b: np.logical_or(a, b))
class LogicalXor(Elementwise):
- enabled = False
op = 'LogicalXor'
op_type = 'LogicalXor'
operation = staticmethod(lambda a, b: np.logical_xor(a, b))
class LogicalAnd(LogicalElementwise):
- enabled = False
op = 'LogicalAnd'
op_type = 'LogicalAnd'
operation = staticmethod(lambda a, b: np.logical_and(a, b))
class FloorMod(Elementwise):
- enabled = False
op = 'FloorMod'
op_type = 'FloorMod'
operation = staticmethod(lambda a, b: a % b)
-class Negative(Elementwise):
- enabled = False
+class Negative(UnaryElementwise):
op = 'Negative'
op_type = 'Negative'
operation = staticmethod(lambda a: -a)
-
- @staticmethod
- def type_infer(node):
- copy_type_infer(node)
--- /dev/null
+"""
+ Copyright (C) 2018-2020 Intel Corporation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+
+import unittest
+
+import numpy as np
+
+from extensions.ops.elementwise import Round
+from mo.graph.graph import Node
+from mo.utils.unittest.graph import build_graph
+
+def round_test_graph(nodes_attributes, value, mode: str):
+ graph = build_graph(nodes_attributes,
+ [
+ ('node_1', 'elementwise_node'),
+ ('elementwise_node', 'node_3')
+ ],
+ {
+ 'node_1': {
+ 'value': value
+ },
+ 'elementwise_node': {
+ 'op': 'Round',
+ 'mode': mode,
+ },
+ 'node_3': {
+ 'value': None
+ }
+ })
+ return graph
+
+
+class TestElementwiseOp(unittest.TestCase):
+ nodes_attributes = {
+ 'node_1': {
+ 'shape': np.array([13]),
+ 'value': None
+ },
+ 'elementwise_node': {
+ 'op': None,
+ 'kind': 'op',
+ 'operation': None
+ },
+ 'node_3': {
+ 'shape': None
+ }
+ }
+
+ value = np.array([-23.5, -22.5, -2.5, -1.5, -0.5, 0.5, 0.9, 1.5, 2.3, 2.5, 3.5, 22.5, 23.5])
+
+ def test_elementwise_round_even_infer(self):
+ graph = round_test_graph(self.nodes_attributes, self.value, 'half_to_even')
+
+ graph.graph['layout'] = 'NCHW'
+ elementwise_node = Node(graph, 'elementwise_node')
+ Round.infer(elementwise_node)
+ exp_shape = np.array([13])
+ res_shape = graph.node['node_3']['shape']
+ res_value = graph.node['node_3']['value']
+ exp_value = np.array([-24., -22., -2., -2., -0., 0., 1., 2., 2., 2., 4., 22., 24.,])
+ for i, value in enumerate(exp_shape):
+ self.assertEqual(res_shape[i], value)
+ for i, value in enumerate(exp_value):
+ self.assertAlmostEqual(res_value[i], value)
+
+ def test_elementwise_round_away_infer(self):
+ graph = round_test_graph(self.nodes_attributes, self.value, 'half_away_from_zero')
+
+ graph.graph['layout'] = 'NCHW'
+ elementwise_node = Node(graph, 'elementwise_node')
+ Round.infer(elementwise_node)
+ exp_shape = np.array([13])
+ res_shape = graph.node['node_3']['shape']
+ res_value = graph.node['node_3']['value']
+ exp_value = np.array([-24., -23., -3., -2., -1., 1., 1., 2., 2., 3., 4., 23., 24.])
+ for i, value in enumerate(exp_shape):
+ self.assertEqual(res_shape[i], value)
+ for i, value in enumerate(exp_value):
+ self.assertAlmostEqual(res_value[i], value)
from extensions.ops.Cast import Cast
from extensions.ops.ReduceOps import ReduceOp
from extensions.ops.activation_ops import Activation
-from extensions.ops.elementwise import Elementwise, LogicalElementwise, BiasAdd, Div, Mul, Pow, Sub
+from extensions.ops.elementwise import Elementwise, UnaryElementwise, LogicalElementwise, BiasAdd, Div, Mul, Pow, Sub
from extensions.ops.embedding_bag import EmbeddingBagBase
from extensions.ops.psroipooling import DeformablePSROIPoolingOp
from extensions.ops.scatter import Scatter
"""
import_by_path(os.path.join(path, 'mo', 'ops'), ['mo', 'ops'])
import_by_path(os.path.join(path, 'extensions', 'ops'), ['extensions', 'ops'])
- update_registration(classes=[Op, Activation, Elementwise, EmbeddingBagBase,
- LogicalElementwise, ReduceOp, Scatter, ScatterNDBase],
+ update_registration(classes=[Op, Activation, Elementwise, UnaryElementwise, LogicalElementwise,
+ EmbeddingBagBase, ReduceOp, Scatter, ScatterNDBase],
enabled_transforms=[], disabled_transforms=[])
virtual std::shared_ptr<Node>
clone_with_new_inputs(const OutputVector& new_args) const override;
+ bool evaluate(const HostTensorVector& outputs,
+ const HostTensorVector& inputs) const override;
+
RoundMode get_mode() const { return m_mode; }
private:
RoundMode m_mode;
}
template <typename T>
- void round(const T* arg, T* out, size_t count)
+ void round(const T* arg, T* out, size_t count, const op::v5::Round::RoundMode mode)
{
for (size_t i = 0; i < count; ++i)
{
- out[i] = round_to_nearest_even(arg[i]);
+ if (mode == op::v5::Round::RoundMode::HALF_TO_EVEN)
+ {
+ out[i] = round_to_nearest_even(arg[i]);
+ }
+ else
+ {
+ out[i] = std::round(arg[i]);
+ }
}
}
}
{
// function used by TYPE_CASE
template <element::Type_t ET>
- inline bool evaluate(const HostTensorPtr& arg0, const HostTensorPtr& out, const size_t count)
+ inline bool evaluate(const HostTensorPtr& arg0,
+ const HostTensorPtr& out,
+ const size_t count,
+ const op::v5::Round::RoundMode mode)
{
using T = typename element_type_traits<ET>::value_type;
- runtime::reference::round<T>(arg0->get_data_ptr<ET>(), out->get_data_ptr<ET>(), count);
+ runtime::reference::round<T>(
+ arg0->get_data_ptr<ET>(), out->get_data_ptr<ET>(), count, mode);
return true;
}
return true;
}
- bool evaluate_round(const HostTensorPtr& arg0, const HostTensorPtr& out, const size_t count)
+ bool evaluate_round(const HostTensorPtr& arg0,
+ const HostTensorPtr& out,
+ const size_t count,
+ const op::v5::Round::RoundMode mode)
{
bool rc = true;
out->set_unary(arg0);
break;
COPY_TENSOR(u64)(arg0, out, count);
break;
- TYPE_CASE(f16)(arg0, out, count);
+ TYPE_CASE(f16)(arg0, out, count, mode);
break;
- TYPE_CASE(f32)(arg0, out, count);
+ TYPE_CASE(f32)(arg0, out, count, mode);
+ break;
+ TYPE_CASE(bf16)(arg0, out, count, mode);
break;
default: rc = false; break;
}
bool op::v0::Round::evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const
{
OV_ITT_SCOPED_TASK(itt::domains::nGraphOp, "op::v0::Round::evaluate");
- return roundop::evaluate_round(inputs[0], outputs[0], shape_size(get_output_shape(0)));
+ return roundop::evaluate_round(inputs[0],
+ outputs[0],
+ shape_size(get_output_shape(0)),
+ op::v5::Round::RoundMode::HALF_TO_EVEN);
}
NGRAPH_SUPPRESS_DEPRECATED_END
return make_shared<v5::Round>(new_args.at(0), m_mode);
}
+bool op::v5::Round::evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const
+{
+ OV_ITT_SCOPED_TASK(itt::domains::nGraphOp, "op::v5::Round::evaluate");
+ return roundop::evaluate_round(
+ inputs[0], outputs[0], shape_size(get_output_shape(0)), get_mode());
+}
+
namespace ngraph
{
template <>
from ngraph.opset5 import rnn_cell
from ngraph.opset5 import roi_align
from ngraph.opset5 import roi_pooling
+from ngraph.opset5 import round
from ngraph.opset5 import scatter_elements_update
from ngraph.opset5 import scatter_update
from ngraph.opset5 import select
from ngraph.opset3.ops import rnn_cell
from ngraph.opset3.ops import roi_align
from ngraph.opset2.ops import roi_pooling
+from ngraph.opset5.ops import round
from ngraph.opset3.ops import scatter_elements_update
from ngraph.opset3.ops import scatter_update
from ngraph.opset1.ops import select
:return: The new node with LogSoftmax operation applied on each element.
"""
return _get_node_factory_opset5().create("LogSoftmax", [as_node(data)], {"axis": axis})
+
+
+@nameable_op
+def round(data: NodeInput, mode: str = "half_to_even", name: Optional[str] = None) -> Node:
+ """Apply Round operation on each element of input tensor.
+
+ :param data: The tensor providing input data.
+ :param mode: Rule to round halfway cases. If set to 'half_to_even' then halfs round to the nearest even
+ integer or rounding in such a way that the result heads away from zero if `mode` attribute is
+ 'half_away_from_zero`.
+ :param name: An optional name of the output node.
+ :return: The new node with Round operation applied on each element.
+ """
+ return _get_node_factory_opset5().create("Round", as_nodes(data), {"mode": mode.upper()})
assert node.get_output_size() == 1
assert list(node.get_output_shape(0)) == [3, 10]
assert node.get_output_element_type(0) == Type.f32
+
+
+def test_round_even():
+ float_dtype = np.float32
+ data = ng.parameter(Shape([3, 10]), dtype=float_dtype, name="data")
+
+ node = ng.round(data, "HALF_TO_EVEN")
+ assert node.get_type_name() == "Round"
+ assert node.get_output_size() == 1
+ assert list(node.get_output_shape(0)) == [3, 10]
+ assert node.get_output_element_type(0) == Type.f32
+
+ # Excluded because this part needs mklddn implementation of Round operation
+ # Need to uncomment and check when 37651 will be done.
+ # input_tensor = np.array([-2.5, -1.5, -0.5, 0.5, 0.9, 1.5, 2.3, 2.5, 3.5], dtype=np.float32)
+ # expected = [-2.0, -2.0, 0.0, 0.0, 1.0, 2.0, 2.0, 2.0, 4.0]
+
+ # result = run_op_node([input_tensor], ng.round, "HALF_TO_EVEN")
+ # assert np.allclose(result, expected)
+
+
+def test_round_away():
+ float_dtype = np.float32
+ data = ng.parameter(Shape([3, 10]), dtype=float_dtype, name="data")
+
+ node = ng.round(data, "HALF_AWAY_FROM_ZERO")
+ assert node.get_type_name() == "Round"
+ assert node.get_output_size() == 1
+ assert list(node.get_output_shape(0)) == [3, 10]
+ assert node.get_output_element_type(0) == Type.f32
+
+ # Excluded because this part needs mklddn implementation of Round operation
+ # Need to uncomment and check when 37651 will be done.
+ # input_tensor = np.array([-2.5, -1.5, -0.5, 0.5, 0.9, 1.5, 2.3, 2.5, 3.5], dtype=np.float32)
+ # expected = [-3.0, -2.0, -1.0, 1.0, 1.0, 2.0, 2.0, 3.0, 4.0]
+
+ # result = run_op_node([input_tensor], ng.round, "HALF_AWAY_FROM_ZERO")
+ # assert np.allclose(result, expected)
op_eval/reduce_l1.cpp
op_eval/reduce_l2.cpp
op_eval/roi_align.cpp
+ op_eval/round.cpp
op_eval/softplus.cpp
op_eval/split.cpp
op_eval/swish.cpp
type_prop/round.cpp
type_prop/rnn_cell.cpp
type_prop/rnn_sequence.cpp
+ type_prop/round.cpp
type_prop/scatter_elements_update.cpp
type_prop/scatter_nd_update.cpp
type_prop/scatter_update.cpp
--- /dev/null
+//*****************************************************************************
+// Copyright 2017-2020 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//*****************************************************************************
+
+#include <string>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+#include "ngraph/op/round.hpp"
+#include "ngraph/runtime/host_tensor.hpp"
+#include "ngraph/validation_util.hpp"
+#include "runtime/backend.hpp"
+#include "util/test_tools.hpp"
+
+using namespace std;
+using namespace ngraph;
+
+TEST(op_eval, rounding_to_even)
+{
+ auto p = make_shared<op::Parameter>(element::f32, Shape{9});
+ auto round = make_shared<op::v5::Round>(p, op::v5::Round::RoundMode::HALF_TO_EVEN);
+ auto fun = make_shared<Function>(OutputVector{round}, ParameterVector{p});
+
+ std::vector<float> inputs{-2.5f, -1.5f, -0.5f, 0.5f, 0.9f, 1.5f, 2.3f, 2.5f, 3.5f};
+ std::vector<float> expected_result{-2.f, -2.f, -0.f, 0.f, 1.f, 2.f, 2.f, 2.f, 4.f};
+
+ auto result = make_shared<HostTensor>();
+ ASSERT_TRUE(
+ fun->evaluate({result}, {make_host_tensor<element::Type_t::f32>(Shape{9}, inputs)}));
+ EXPECT_EQ(result->get_element_type(), element::f32);
+ EXPECT_EQ(result->get_shape(), Shape{9});
+ auto result_data = read_vector<float>(result);
+ for (auto i = 0; i < inputs.size(); i++)
+ EXPECT_NEAR(result_data[i], expected_result[i], 0.000001);
+}
+
+TEST(op_eval, rounding_away)
+{
+ auto p = make_shared<op::Parameter>(element::f32, Shape{9});
+ auto round = make_shared<op::v5::Round>(p, op::v5::Round::RoundMode::HALF_AWAY_FROM_ZERO);
+ auto fun = make_shared<Function>(OutputVector{round}, ParameterVector{p});
+
+ std::vector<float> inputs{-2.5f, -1.5f, -0.5f, 0.5f, 0.9f, 1.5f, 2.3f, 2.5f, 3.5f};
+ std::vector<float> expected_result{-3.f, -2.f, -1.f, 1.f, 1.f, 2.f, 2.f, 3.f, 4.f};
+
+ auto result = make_shared<HostTensor>();
+ ASSERT_TRUE(
+ fun->evaluate({result}, {make_host_tensor<element::Type_t::f32>(Shape{9}, inputs)}));
+ EXPECT_EQ(result->get_element_type(), element::f32);
+ EXPECT_EQ(result->get_shape(), Shape{9});
+ auto result_data = read_vector<float>(result);
+ for (auto i = 0; i < inputs.size(); i++)
+ EXPECT_NEAR(result_data[i], expected_result[i], 0.000001);
+}
case OP_TYPEID::Round:
{
size_t element_count = shape_size(node.get_output_shape(0));
- reference::round<T>(
- args[0]->get_data_ptr<const T>(), out[0]->get_data_ptr<T>(), element_count);
+ reference::round<T>(args[0]->get_data_ptr<const T>(),
+ out[0]->get_data_ptr<T>(),
+ element_count,
+ op::v5::Round::RoundMode::HALF_TO_EVEN);
break;
}
case OP_TYPEID::Select:
case OP_TYPEID::Range:
case OP_TYPEID::Reshape:
case OP_TYPEID::Result:
+ case OP_TYPEID::Round_v5:
case OP_TYPEID::ShapeOf_v3:
case OP_TYPEID::ShapeOf:
case OP_TYPEID::Softmax:
NGRAPH_OP(LSTMSequence, op::v5)
NGRAPH_OP(GRUSequence, op::v5)
NGRAPH_OP(RNNSequence, op::v5)
+NGRAPH_OP(Round, op::v5)
NGRAPH_OP(LogSoftmax, op::v5)
#undef ID_SUFFIX
TEST(type_prop, rounding_to_even_partial)
{
auto data = make_shared<op::Parameter>(element::f32, PartialShape{1, Dimension::dynamic(), 6});
- auto softplus_func = make_shared<op::v5::Round>(data, op::v5::Round::RoundMode::HALF_TO_EVEN);
- EXPECT_EQ(softplus_func->get_element_type(), element::f32);
- ASSERT_TRUE(softplus_func->get_output_partial_shape(0).same_scheme(
+ auto round_func = make_shared<op::v5::Round>(data, op::v5::Round::RoundMode::HALF_TO_EVEN);
+ EXPECT_EQ(round_func->get_element_type(), element::f32);
+ ASSERT_TRUE(round_func->get_output_partial_shape(0).same_scheme(
(PartialShape{1, Dimension::dynamic(), 6})));
// rank unknown
- auto softplus_partial = make_shared<op::v5::Round>(
+ auto round_partial = make_shared<op::v5::Round>(
make_shared<op::Parameter>(element::f32, PartialShape::dynamic()),
op::v5::Round::RoundMode::HALF_TO_EVEN);
- ASSERT_TRUE(softplus_partial->get_output_partial_shape(0).same_scheme(PartialShape::dynamic()));
+ ASSERT_TRUE(round_partial->get_output_partial_shape(0).same_scheme(PartialShape::dynamic()));
}
TEST(type_prop, rounding_away_partial)
{
auto data = make_shared<op::Parameter>(element::f32, PartialShape{1, Dimension::dynamic(), 6});
- auto softplus_func =
+ auto round_func =
make_shared<op::v5::Round>(data, op::v5::Round::RoundMode::HALF_AWAY_FROM_ZERO);
- EXPECT_EQ(softplus_func->get_element_type(), element::f32);
- ASSERT_TRUE(softplus_func->get_output_partial_shape(0).same_scheme(
+ EXPECT_EQ(round_func->get_element_type(), element::f32);
+ ASSERT_TRUE(round_func->get_output_partial_shape(0).same_scheme(
(PartialShape{1, Dimension::dynamic(), 6})));
// rank unknown
- auto softplus_partial = make_shared<op::v5::Round>(
+ auto round_partial = make_shared<op::v5::Round>(
make_shared<op::Parameter>(element::f32, PartialShape::dynamic()),
op::v5::Round::RoundMode::HALF_AWAY_FROM_ZERO);
- ASSERT_TRUE(softplus_partial->get_output_partial_shape(0).same_scheme(PartialShape::dynamic()));
+ ASSERT_TRUE(round_partial->get_output_partial_shape(0).same_scheme(PartialShape::dynamic()));
}
TEST(type_prop, rounding_to_even_partial_static_rank)
{
auto data = make_shared<op::Parameter>(element::f32, PartialShape{1, Dimension::dynamic(), 6});
- auto softplus_func = make_shared<op::v5::Round>(data, op::v5::Round::RoundMode::HALF_TO_EVEN);
- EXPECT_EQ(softplus_func->get_element_type(), element::f32);
- ASSERT_TRUE(softplus_func->get_output_partial_shape(0).same_scheme(
+ auto round_func = make_shared<op::v5::Round>(data, op::v5::Round::RoundMode::HALF_TO_EVEN);
+ EXPECT_EQ(round_func->get_element_type(), element::f32);
+ ASSERT_TRUE(round_func->get_output_partial_shape(0).same_scheme(
(PartialShape{1, Dimension::dynamic(), 6})));
- ASSERT_TRUE(softplus_func->get_output_partial_shape(0).rank().is_static());
+ ASSERT_TRUE(round_func->get_output_partial_shape(0).rank().is_static());
}
TEST(type_prop, rounding_away_partial_static_rank)
{
auto data = make_shared<op::Parameter>(element::f32, PartialShape{1, Dimension::dynamic(), 6});
- auto softplus_func =
+ auto round_func =
make_shared<op::v5::Round>(data, op::v5::Round::RoundMode::HALF_AWAY_FROM_ZERO);
- EXPECT_EQ(softplus_func->get_element_type(), element::f32);
- ASSERT_TRUE(softplus_func->get_output_partial_shape(0).same_scheme(
+ EXPECT_EQ(round_func->get_element_type(), element::f32);
+ ASSERT_TRUE(round_func->get_output_partial_shape(0).same_scheme(
(PartialShape{1, Dimension::dynamic(), 6})));
- ASSERT_TRUE(softplus_func->get_output_partial_shape(0).rank().is_static());
+ ASSERT_TRUE(round_func->get_output_partial_shape(0).rank().is_static());
}