From 9412a125ab09e38a88656fc3a122be86b181022a Mon Sep 17 00:00:00 2001
From: Noam ZERAH <noam.zerah@cea.fr>
Date: Fri, 4 Oct 2024 16:19:16 +0000
Subject: [PATCH] Adding new operator Round

---
 include/aidge/aidge.hpp                  |  1 +
 include/aidge/operator/Round.hpp         | 64 ++++++++++++++++++++++++
 python_binding/operator/pybind_Round.cpp | 36 +++++++++++++
 python_binding/pybind_core.cpp           |  2 +
 src/operator/Round.cpp                   | 50 ++++++++++++++++++
 5 files changed, 153 insertions(+)
 create mode 100644 include/aidge/operator/Round.hpp
 create mode 100644 python_binding/operator/pybind_Round.cpp
 create mode 100644 src/operator/Round.cpp

diff --git a/include/aidge/aidge.hpp b/include/aidge/aidge.hpp
index cadd8c85c..dc0a12c76 100644
--- a/include/aidge/aidge.hpp
+++ b/include/aidge/aidge.hpp
@@ -65,6 +65,7 @@
 #include "aidge/operator/ReLU.hpp"
 #include "aidge/operator/Reshape.hpp"
 #include "aidge/operator/Resize.hpp"
+#include "aidge/operator/Round.hpp"
 #include "aidge/operator/Shape.hpp"
 #include "aidge/operator/Scaling.hpp"
 #include "aidge/operator/Slice.hpp"
diff --git a/include/aidge/operator/Round.hpp b/include/aidge/operator/Round.hpp
new file mode 100644
index 000000000..00352421d
--- /dev/null
+++ b/include/aidge/operator/Round.hpp
@@ -0,0 +1,64 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#ifndef AIDGE_CORE_OPERATOR_ROUND_H_
+#define AIDGE_CORE_OPERATOR_ROUND_H_
+
+#include <memory>
+#include <vector>
+#include <string>
+
+#include "aidge/graph/Node.hpp"
+#include "aidge/operator/OperatorTensor.hpp"
+#include "aidge/utils/StaticAttributes.hpp"
+#include "aidge/utils/Registrar.hpp"
+#include "aidge/utils/Types.h"
+
+namespace Aidge {
+
+class Round_Op : public OperatorTensor,
+                public Registrable<Round_Op,
+                                std::string,
+                                std::function<std::shared_ptr<OperatorImpl>(const Round_Op&)>> {
+
+
+public:
+    static const std::string Type;
+
+    Round_Op() : OperatorTensor(Type, {InputCategory::Data}, 1) {}
+
+    /**
+     * @brief Copy-constructor. Copy the operator attributes and its output tensor(s), but not its input tensors (the new operator has no input associated).
+     * @param op Operator to copy.
+     */
+    Round_Op(const Round_Op& op);
+
+    /**
+     * @brief Clone the operator using its copy-constructor.
+     * @see Operator::Round_Op
+     */
+    std::shared_ptr<Operator> clone() const override;
+
+    void setBackend(const std::string& name, DeviceIdx_t device = 0) override final;
+    std::set<std::string> getAvailableBackends() const override;
+    static const std::vector<std::string> getInputsName(){
+        return {"data_input"};
+    }
+    static const std::vector<std::string> getOutputsName(){
+        return {"data_output"};
+    }
+};
+
+std::shared_ptr<Node> Round(const std::string& name = "");
+}
+
+
+#endif /* AIDGE_CORE_OPERATOR_ROUND_H_ */
diff --git a/python_binding/operator/pybind_Round.cpp b/python_binding/operator/pybind_Round.cpp
new file mode 100644
index 000000000..e9ed0e473
--- /dev/null
+++ b/python_binding/operator/pybind_Round.cpp
@@ -0,0 +1,36 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#include <pybind11/pybind11.h>
+
+#include "aidge/operator/Round.hpp"
+#include "aidge/operator/OperatorTensor.hpp"
+
+namespace py = pybind11;
+namespace Aidge {
+
+void init_Round(py::module& m) {
+    py::class_<Round_Op, std::shared_ptr<Round_Op>, OperatorTensor>(m, "RoundOp", py::multiple_inheritance())
+    .def(py::init<>())
+    .def_static("get_inputs_name", &Round_Op::getInputsName)
+    .def_static("get_outputs_name", &Round_Op::getOutputsName)
+    .def_readonly_static("Type", &Round_Op::Type);
+    declare_registrable<Round_Op>(m, "RoundOp");
+    m.def("Round", &Round, py::arg("name") = "", R"mydelimiter(
+    RoundOp is a tensor operator that rounds the values of a tensor element-wise.
+        This class rounds each value to the nearest integer. In the case of halves, 
+        the rule is to round them to the nearest even integer.
+        :param X: input tensor.
+        :type X: tensor of type float, double, float16, or bfloat16.
+        :param Y: output tensor with the same shape and type as the input tensor.
+    )mydelimiter");
+}
+}  // namespace Aidge
diff --git a/python_binding/pybind_core.cpp b/python_binding/pybind_core.cpp
index 52c8cc8a0..bac071e02 100644
--- a/python_binding/pybind_core.cpp
+++ b/python_binding/pybind_core.cpp
@@ -61,6 +61,7 @@ void init_ReduceMean(py::module&);
 void init_ReduceSum(py::module&);
 void init_Reshape(py::module&);
 void init_Resize(py::module&);
+void init_Round(py::module&);
 void init_Scaling(py::module&);
 void init_Shape(py::module&);
 void init_Sigmoid(py::module&);
@@ -143,6 +144,7 @@ void init_Aidge(py::module& m) {
     init_ReduceSum(m);
     init_Reshape(m);
     init_Resize(m);
+    init_Round(m);
     init_Scaling(m);
     init_Shape(m);
     init_Sigmoid(m);
diff --git a/src/operator/Round.cpp b/src/operator/Round.cpp
new file mode 100644
index 000000000..ba4eff9d1
--- /dev/null
+++ b/src/operator/Round.cpp
@@ -0,0 +1,50 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#include "aidge/operator/Round.hpp"
+
+#include <memory>
+#include <string>
+
+#include "aidge/backend/OperatorImpl.hpp"
+#include "aidge/data/Tensor.hpp"
+#include "aidge/utils/Registrar.hpp"
+#include "aidge/utils/Types.h"
+
+const std::string Aidge::Round_Op::Type = "Round";
+
+Aidge::Round_Op::Round_Op(const Aidge::Round_Op& op)
+    : OperatorTensor(op)
+{
+    if (op.mImpl){
+        SET_IMPL_MACRO(Round_Op, *this, op.backend());
+    }else{
+        mImpl = nullptr;
+    }
+}
+
+
+std::shared_ptr<Aidge::Operator> Aidge::Round_Op::clone() const {
+    return std::make_shared<Round_Op>(*this);
+}
+
+void Aidge::Round_Op::setBackend(const std::string& name, Aidge::DeviceIdx_t device) {
+    mImpl = Registrar<Round_Op>::create(name)(*this);
+    mOutputs[0]->setBackend(name, device);
+}
+
+std::set<std::string> Aidge::Round_Op::getAvailableBackends() const {
+    return Registrar<Round_Op>::getKeys();
+}
+
+std::shared_ptr<Aidge::Node> Aidge::Round(const std::string& name) {
+    return std::make_shared<Node>(std::make_shared<Round_Op>(), name);
+}
\ No newline at end of file
-- 
GitLab