Skip to content
Snippets Groups Projects
Commit a1ca1f8d authored by Houssem ROUIS's avatar Houssem ROUIS Committed by Maxence Naud
Browse files

add ArithmeticOperator class

parent 59c97851
No related branches found
No related tags found
2 merge requests!105version 0.2.0,!65[Add] broadcasting for Arithmetic Operators
This commit is part of merge request !65. Comments created here will be created in the context of that merge request.
/********************************************************************************
* Copyright (c) 2024 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_ARITHMETICOPERATOR_H_
#define AIDGE_CORE_OPERATOR_ARITHMETICOPERATOR_H_
#include <memory>
#include <string>
#include <vector>
#include "aidge/backend/OperatorImpl.hpp"
#include "aidge/data/Tensor.hpp"
#include "aidge/operator/Operator.hpp"
#include "aidge/utils/Types.h"
namespace Aidge {
class ArithmeticOperator : public Operator {
/* TODO: Add an attribute specifying the type of Data used by the Operator.
* The same way ``Type`` attribute specifies the type of Operator. Hence this
* attribute could be checked in the forwardDims function to assert Operators
* being used work with Tensors and cast them to OpertorTensor instead of
* Operator.
*/
/* TODO: Maybe change type attribute of Data object by an enum instead of an
* array of char. Faster comparisons.
*/
protected:
std::vector<std::shared_ptr<Tensor>> mInputs;
std::vector<std::shared_ptr<Tensor>> mOutputs;
public:
ArithmeticOperator() = delete;
ArithmeticOperator(const std::string& type)
: Operator(type, 2, 0, 1, OperatorType::Tensor),
mInputs(std::vector<std::shared_ptr<Tensor>>(2, nullptr)),
mOutputs(std::vector<std::shared_ptr<Tensor>>(1)) {
mOutputs[0] = std::make_shared<Tensor>();
mOutputs[0]->setDataType(DataType::Float32);
}
ArithmeticOperator(const ArithmeticOperator& other)
: Operator(other),
mInputs(std::vector<std::shared_ptr<Tensor>>(2, nullptr)),
mOutputs(std::vector<std::shared_ptr<Tensor>>(1)) {
mOutputs[0] = std::make_shared<Tensor>();
}
~ArithmeticOperator();
public:
///////////////////////////////////////////////////
virtual void associateInput(const IOIndex_t inputIdx,
const std::shared_ptr<Data>& data) override;
///////////////////////////////////////////////////
///////////////////////////////////////////////////
// Tensor access
// input management
void setInput(const IOIndex_t inputIdx, const std::shared_ptr<Data>& data) override final;
void setInput(const IOIndex_t inputIdx, std::shared_ptr<Data>&& data) override final;
const std::shared_ptr<Tensor>& getInput(const IOIndex_t inputIdx) const;
inline std::shared_ptr<Data> getRawInput(const IOIndex_t inputIdx) const override final {
return std::static_pointer_cast<Data>(getInput(inputIdx));
}
// output management
void setOutput(const IOIndex_t outputIdx, const std::shared_ptr<Data>& data) override;
void setOutput(const IOIndex_t outputIdx, std::shared_ptr<Data>&& data) override;
virtual const std::shared_ptr<Tensor>& getOutput(const IOIndex_t outputIdx) const;
inline std::shared_ptr<Aidge::Data> getRawOutput(const Aidge::IOIndex_t outputIdx) const override final {
return std::static_pointer_cast<Data>(getOutput(outputIdx));
}
static const std::vector<std::string> getInputsName(){
return {"data_input1", "data_input2"};
}
static const std::vector<std::string> getOutputsName(){
return {"data_output"};
}
///////////////////////////////////////////////////
///////////////////////////////////////////////////
// Tensor dimensions
/**
* @brief For a given output feature area, compute the associated receptive
* field for each data input.
* @param firstIdx First index of the output feature.
* @param outputDims Size of output feature.
* @param outputIdx Index of the output. Default 0.
* @return std::vector<std::pair<std::size_t, std::vector<DimSize_t>>>
* For each dataInput Tensor of the Operator, the first index and dimensions of the feature area.
*/
virtual std::vector<std::pair<std::vector<Aidge::DimSize_t>, std::vector<DimSize_t>>> computeReceptiveField(const std::vector<DimSize_t>& firstEltDims, const std::vector<DimSize_t>& outputDims, const IOIndex_t outputIdx = 0) const;
virtual void computeOutputDims();
virtual bool outputDimsForwarded() const;
///////////////////////////////////////////////////
virtual void setDataType(const DataType& dataType) const override;
};
} // namespace Aidge
#endif // AIDGE_CORE_OPERATOR_ARITHMETICOPERATOR_H_
\ No newline at end of file
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <vector> #include <vector>
#include "aidge/utils/Registrar.hpp" #include "aidge/utils/Registrar.hpp"
#include "aidge/operator/OperatorTensor.hpp" #include "aidge/operator/ArithmeticOperator.hpp"
#include "aidge/backend/OperatorImpl.hpp" #include "aidge/backend/OperatorImpl.hpp"
#include "aidge/data/Tensor.hpp" #include "aidge/data/Tensor.hpp"
#include "aidge/graph/Node.hpp" #include "aidge/graph/Node.hpp"
...@@ -25,21 +25,19 @@ ...@@ -25,21 +25,19 @@
namespace Aidge { namespace Aidge {
class Div_Op : public OperatorTensor, class Div_Op : public ArithmeticOperator,
public Registrable<Div_Op, std::string, std::unique_ptr<OperatorImpl>(const Div_Op&)> { public Registrable<Div_Op, std::string, std::unique_ptr<OperatorImpl>(const Div_Op&)> {
public: public:
static const std::string Type; static const std::string Type;
Div_Op() : OperatorTensor(Type, 2, 0, 1) {} Div_Op() : ArithmeticOperator(Type) {}
/** /**
* @brief Copy-constructor. Copy the operator attributes and its output tensor(s), but not its input tensors (the new operator has no input associated). * @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. * @param op Operator to copy.
*/ */
Div_Op(const Div_Op& op) Div_Op(const Div_Op& op) : ArithmeticOperator(op){
: OperatorTensor(op)
{
mImpl = op.mImpl ? Registrar<Div_Op>::create(op.mOutputs[0]->getImpl()->backend())(*this) : nullptr; mImpl = op.mImpl ? Registrar<Div_Op>::create(op.mOutputs[0]->getImpl()->backend())(*this) : nullptr;
} }
...@@ -51,20 +49,10 @@ public: ...@@ -51,20 +49,10 @@ public:
return std::make_shared<Div_Op>(*this); return std::make_shared<Div_Op>(*this);
} }
void computeOutputDims() override final;
void setBackend(const std::string& name, DeviceIdx_t device = 0) override { void setBackend(const std::string& name, DeviceIdx_t device = 0) override {
mImpl = Registrar<Div_Op>::create(name)(*this); mImpl = Registrar<Div_Op>::create(name)(*this);
mOutputs[0]->setBackend(name, device); mOutputs[0]->setBackend(name, device);
} }
static const std::vector<std::string> getInputsName(){
return {"data_input"};
}
static const std::vector<std::string> getOutputsName(){
return {"data_output"};
}
}; };
inline std::shared_ptr<Node> Div(const std::string& name = "") { inline std::shared_ptr<Node> Div(const std::string& name = "") {
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <vector> #include <vector>
#include "aidge/utils/Registrar.hpp" #include "aidge/utils/Registrar.hpp"
#include "aidge/operator/OperatorTensor.hpp" #include "aidge/operator/ArithmeticOperator.hpp"
#include "aidge/backend/OperatorImpl.hpp" #include "aidge/backend/OperatorImpl.hpp"
#include "aidge/data/Tensor.hpp" #include "aidge/data/Tensor.hpp"
#include "aidge/graph/Node.hpp" #include "aidge/graph/Node.hpp"
...@@ -28,21 +28,19 @@ namespace Aidge { ...@@ -28,21 +28,19 @@ namespace Aidge {
/** /**
* @brief Tensor element-wise multiplication. * @brief Tensor element-wise multiplication.
*/ */
class Mul_Op : public OperatorTensor, class Mul_Op : public ArithmeticOperator,
public Registrable<Mul_Op, std::string, std::unique_ptr<OperatorImpl>(const Mul_Op&)> { public Registrable<Mul_Op, std::string, std::unique_ptr<OperatorImpl>(const Mul_Op&)> {
public: public:
static const std::string Type; static const std::string Type;
Mul_Op() : OperatorTensor(Type, 2, 0, 1) {} Mul_Op() : ArithmeticOperator(Type) {}
/** /**
* @brief Copy-constructor. Copy the operator attributes and its output tensor(s), * @brief Copy-constructor. Copy the operator attributes and its output tensor(s),
* but not its input tensors (the new operator has no input associated). * but not its input tensors (the new operator has no input associated).
* @param op Operator to copy. * @param op Operator to copy.
*/ */
Mul_Op(const Mul_Op& op) Mul_Op(const Mul_Op& op) : ArithmeticOperator(op){
: OperatorTensor(op)
{
mImpl = op.mImpl ? Registrar<Mul_Op>::create(op.mOutputs[0]->getImpl()->backend())(*this) : nullptr; mImpl = op.mImpl ? Registrar<Mul_Op>::create(op.mOutputs[0]->getImpl()->backend())(*this) : nullptr;
} }
...@@ -54,19 +52,10 @@ public: ...@@ -54,19 +52,10 @@ public:
return std::make_shared<Mul_Op>(*this); return std::make_shared<Mul_Op>(*this);
} }
void computeOutputDims() override final;
void setBackend(const std::string& name, DeviceIdx_t device = 0) override { void setBackend(const std::string& name, DeviceIdx_t device = 0) override {
mImpl = Registrar<Mul_Op>::create(name)(*this); mImpl = Registrar<Mul_Op>::create(name)(*this);
mOutputs[0]->setBackend(name, device); mOutputs[0]->setBackend(name, device);
} }
static const std::vector<std::string> getInputsName(){
return {"data_input"};
}
static const std::vector<std::string> getOutputsName(){
return {"data_output"};
}
}; };
inline std::shared_ptr<Node> Mul(const std::string& name = "") { inline std::shared_ptr<Node> Mul(const std::string& name = "") {
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <vector> #include <vector>
#include "aidge/utils/Registrar.hpp" #include "aidge/utils/Registrar.hpp"
#include "aidge/operator/OperatorTensor.hpp" #include "aidge/operator/ArithmeticOperator.hpp"
#include "aidge/backend/OperatorImpl.hpp" #include "aidge/backend/OperatorImpl.hpp"
#include "aidge/data/Tensor.hpp" #include "aidge/data/Tensor.hpp"
#include "aidge/data/Data.hpp" #include "aidge/data/Data.hpp"
...@@ -26,20 +26,18 @@ ...@@ -26,20 +26,18 @@
namespace Aidge { namespace Aidge {
class Pow_Op : public OperatorTensor, class Pow_Op : public ArithmeticOperator,
public Registrable<Pow_Op, std::string, std::unique_ptr<OperatorImpl>(const Pow_Op&)> { public Registrable<Pow_Op, std::string, std::unique_ptr<OperatorImpl>(const Pow_Op&)> {
public: public:
static const std::string Type; static const std::string Type;
Pow_Op() : OperatorTensor(Type, 2, 0, 1) {} Pow_Op() : ArithmeticOperator(Type) {}
/** /**
* @brief Copy-constructor. Copy the operator attributes and its output tensor(s), but not its input tensors (the new operator has no input associated). * @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. * @param op Operator to copy.
*/ */
Pow_Op(const Pow_Op& op) Pow_Op(const Pow_Op& op) : ArithmeticOperator(op){
: OperatorTensor(op)
{
mImpl = op.mImpl ? Registrar<Pow_Op>::create(op.mOutputs[0]->getImpl()->backend())(*this) : nullptr; mImpl = op.mImpl ? Registrar<Pow_Op>::create(op.mOutputs[0]->getImpl()->backend())(*this) : nullptr;
} }
...@@ -51,20 +49,10 @@ public: ...@@ -51,20 +49,10 @@ public:
return std::make_shared<Pow_Op>(*this); return std::make_shared<Pow_Op>(*this);
} }
void computeOutputDims() override final;
void setBackend(const std::string& name, DeviceIdx_t device = 0) override { void setBackend(const std::string& name, DeviceIdx_t device = 0) override {
mImpl = Registrar<Pow_Op>::create(name)(*this); mImpl = Registrar<Pow_Op>::create(name)(*this);
mOutputs[0]->setBackend(name, device); mOutputs[0]->setBackend(name, device);
} }
static const std::vector<std::string> getInputsName(){
return {"data_input"};
}
static const std::vector<std::string> getOutputsName(){
return {"data_output"};
}
}; };
inline std::shared_ptr<Node> Pow(const std::string& name = "") { inline std::shared_ptr<Node> Pow(const std::string& name = "") {
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <vector> #include <vector>
#include "aidge/utils/Registrar.hpp" #include "aidge/utils/Registrar.hpp"
#include "aidge/operator/OperatorTensor.hpp" #include "aidge/operator/ArithmeticOperator.hpp"
#include "aidge/backend/OperatorImpl.hpp" #include "aidge/backend/OperatorImpl.hpp"
#include "aidge/data/Tensor.hpp" #include "aidge/data/Tensor.hpp"
#include "aidge/data/Data.hpp" #include "aidge/data/Data.hpp"
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
namespace Aidge { namespace Aidge {
class Sub_Op : public OperatorTensor, class Sub_Op : public ArithmeticOperator,
public Registrable<Sub_Op, std::string, std::unique_ptr<OperatorImpl>(const Sub_Op&)> { public Registrable<Sub_Op, std::string, std::unique_ptr<OperatorImpl>(const Sub_Op&)> {
public: public:
// FIXME: change accessibility // FIXME: change accessibility
...@@ -36,15 +36,13 @@ public: ...@@ -36,15 +36,13 @@ public:
public: public:
static const std::string Type; static const std::string Type;
Sub_Op() : OperatorTensor(Type, 2, 0, 1) {} Sub_Op() : ArithmeticOperator(Type) {}
/** /**
* @brief Copy-constructor. Copy the operator attributes and its output tensor(s), but not its input tensors (the new operator has no input associated). * @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. * @param op Operator to copy.
*/ */
Sub_Op(const Sub_Op& op) Sub_Op(const Sub_Op& op) : ArithmeticOperator(op){
: OperatorTensor(op)
{
mImpl = op.mImpl ? Registrar<Sub_Op>::create(op.mOutputs[0]->getImpl()->backend())(*this) : nullptr; mImpl = op.mImpl ? Registrar<Sub_Op>::create(op.mOutputs[0]->getImpl()->backend())(*this) : nullptr;
} }
...@@ -56,20 +54,10 @@ public: ...@@ -56,20 +54,10 @@ public:
return std::make_shared<Sub_Op>(*this); return std::make_shared<Sub_Op>(*this);
} }
void computeOutputDims() override final;
void setBackend(const std::string& name, DeviceIdx_t device = 0) override { void setBackend(const std::string& name, DeviceIdx_t device = 0) override {
mImpl = Registrar<Sub_Op>::create(name)(*this); mImpl = Registrar<Sub_Op>::create(name)(*this);
mOutputs[0]->setBackend(name, device); mOutputs[0]->setBackend(name, device);
} }
static const std::vector<std::string> getInputsName(){
return {"data_input"};
}
static const std::vector<std::string> getOutputsName(){
return {"data_output"};
}
}; };
inline std::shared_ptr<Node> Sub(const std::string& name = "") { inline std::shared_ptr<Node> Sub(const std::string& name = "") {
......
...@@ -12,13 +12,13 @@ ...@@ -12,13 +12,13 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include "aidge/operator/Div.hpp" #include "aidge/operator/Div.hpp"
#include "aidge/operator/OperatorTensor.hpp" #include "aidge/operator/ArithmeticOperator.hpp"
namespace py = pybind11; namespace py = pybind11;
namespace Aidge { namespace Aidge {
void init_Div(py::module& m) { void init_Div(py::module& m) {
py::class_<Div_Op, std::shared_ptr<Div_Op>, OperatorTensor>(m, "DivOp", py::multiple_inheritance()) py::class_<Div_Op, std::shared_ptr<Div_Op>, ArithmeticOperator>(m, "DivOp", py::multiple_inheritance())
.def("get_inputs_name", &Div_Op::getInputsName) .def("get_inputs_name", &Div_Op::getInputsName)
.def("get_outputs_name", &Div_Op::getOutputsName); .def("get_outputs_name", &Div_Op::getOutputsName);
......
...@@ -12,13 +12,13 @@ ...@@ -12,13 +12,13 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include "aidge/operator/Mul.hpp" #include "aidge/operator/Mul.hpp"
#include "aidge/operator/OperatorTensor.hpp" #include "aidge/operator/ArithmeticOperator.hpp"
namespace py = pybind11; namespace py = pybind11;
namespace Aidge { namespace Aidge {
void init_Mul(py::module& m) { void init_Mul(py::module& m) {
py::class_<Mul_Op, std::shared_ptr<Mul_Op>, OperatorTensor>(m, "MulOp", py::multiple_inheritance()) py::class_<Mul_Op, std::shared_ptr<Mul_Op>, ArithmeticOperator>(m, "MulOp", py::multiple_inheritance())
.def("get_inputs_name", &Mul_Op::getInputsName) .def("get_inputs_name", &Mul_Op::getInputsName)
.def("get_outputs_name", &Mul_Op::getOutputsName); .def("get_outputs_name", &Mul_Op::getOutputsName);
......
...@@ -12,13 +12,13 @@ ...@@ -12,13 +12,13 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include "aidge/operator/Pow.hpp" #include "aidge/operator/Pow.hpp"
#include "aidge/operator/OperatorTensor.hpp" #include "aidge/operator/ArithmeticOperator.hpp"
namespace py = pybind11; namespace py = pybind11;
namespace Aidge { namespace Aidge {
void init_Pow(py::module& m) { void init_Pow(py::module& m) {
py::class_<Pow_Op, std::shared_ptr<Pow_Op>, OperatorTensor>(m, "PowOp", py::multiple_inheritance()) py::class_<Pow_Op, std::shared_ptr<Pow_Op>, ArithmeticOperator>(m, "PowOp", py::multiple_inheritance())
.def("get_inputs_name", &Pow_Op::getInputsName) .def("get_inputs_name", &Pow_Op::getInputsName)
.def("get_outputs_name", &Pow_Op::getOutputsName); .def("get_outputs_name", &Pow_Op::getOutputsName);
......
...@@ -12,13 +12,13 @@ ...@@ -12,13 +12,13 @@
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include "aidge/operator/Sub.hpp" #include "aidge/operator/Sub.hpp"
#include "aidge/operator/OperatorTensor.hpp" #include "aidge/operator/ArithmeticOperator.hpp"
namespace py = pybind11; namespace py = pybind11;
namespace Aidge { namespace Aidge {
void init_Sub(py::module& m) { void init_Sub(py::module& m) {
py::class_<Sub_Op, std::shared_ptr<Sub_Op>, OperatorTensor>(m, "SubOp", py::multiple_inheritance()) py::class_<Sub_Op, std::shared_ptr<Sub_Op>, ArithmeticOperator>(m, "SubOp", py::multiple_inheritance())
.def("get_inputs_name", &Sub_Op::getInputsName) .def("get_inputs_name", &Sub_Op::getInputsName)
.def("get_outputs_name", &Sub_Op::getOutputsName); .def("get_outputs_name", &Sub_Op::getOutputsName);
......
/********************************************************************************
* 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 <cassert>
#include <memory>
#include "aidge/operator/ArithmeticOperator.hpp"
#include "aidge/data/Data.hpp"
#include "aidge/data/Tensor.hpp"
#include "aidge/utils/Types.h"
#include "aidge/utils/ErrorHandling.hpp"
void Aidge::ArithmeticOperator::associateInput(const Aidge::IOIndex_t inputIdx, const std::shared_ptr<Aidge::Data>& data) {
if (inputIdx >= 2) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "%s Operator has %hu inputs", type().c_str(),2);
}
if (strcmp((data)->type(), Tensor::Type) != 0) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "Input data must be of Tensor type");
}
mInputs[inputIdx] = std::dynamic_pointer_cast<Tensor>(data);
}
void Aidge::ArithmeticOperator::setInput(const Aidge::IOIndex_t inputIdx, const std::shared_ptr<Aidge::Data>& data) {
if (strcmp(data->type(), "Tensor") != 0) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "%s Operator only accepts Tensors as inputs", type().c_str());
}
if (getInput(inputIdx)) {
*mInputs[inputIdx] = *std::dynamic_pointer_cast<Tensor>(data);
} else {
mInputs[inputIdx] = std::make_shared<Tensor>(*std::dynamic_pointer_cast<Tensor>(data));
}
}
Aidge::ArithmeticOperator::~ArithmeticOperator() = default;
void Aidge::ArithmeticOperator::setInput(const Aidge::IOIndex_t inputIdx, std::shared_ptr<Aidge::Data>&& data) {
if (strcmp(data->type(), "Tensor") != 0) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "%s Operator only accepts Tensors as inputs", type().c_str());
}
if (getInput(inputIdx)) {
*mInputs[inputIdx] = std::move(*std::dynamic_pointer_cast<Tensor>(data));
} else {
mInputs[inputIdx] = std::make_shared<Tensor>(std::move(*std::dynamic_pointer_cast<Tensor>(data)));
}
}
const std::shared_ptr<Aidge::Tensor>& Aidge::ArithmeticOperator::getInput(const Aidge::IOIndex_t inputIdx) const {
if (inputIdx >= nbInputs()) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "%s Operator has %hu inputs", type().c_str(), nbInputs());
}
return mInputs[inputIdx];
}
void Aidge::ArithmeticOperator::setOutput(const Aidge::IOIndex_t outputIdx, const std::shared_ptr<Aidge::Data>& data) {
if (strcmp(data->type(), "Tensor") != 0) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "%s Operator only accepts Tensors as inputs", type().c_str());
}
if (outputIdx >= nbOutputs()) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "%s Operator has %hu outputs", type().c_str(), nbOutputs());
}
*mOutputs[outputIdx] = *std::dynamic_pointer_cast<Tensor>(data);
}
void Aidge::ArithmeticOperator::setOutput(const Aidge::IOIndex_t outputIdx, std::shared_ptr<Aidge::Data>&& data) {
if (strcmp(data->type(), "Tensor") != 0) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "%s Operator only accepts Tensors as inputs", type().c_str());
}
if (outputIdx >= nbOutputs()) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "%s Operator has %hu outputs", type().c_str(), nbOutputs());
}
*mOutputs[outputIdx] = std::move(*std::dynamic_pointer_cast<Tensor>(data));
}
const std::shared_ptr<Aidge::Tensor>& Aidge::ArithmeticOperator::getOutput(const Aidge::IOIndex_t outputIdx) const {
if (outputIdx >= nbOutputs()) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "%s Operator has %hu outputs", type().c_str(), nbOutputs());
}
return mOutputs[outputIdx];
}
std::vector<std::pair<std::vector<Aidge::DimSize_t>, std::vector<Aidge::DimSize_t>>> Aidge::ArithmeticOperator::computeReceptiveField(
const std::vector<DimSize_t>& firstEltDims,
const std::vector<Aidge::DimSize_t>& outputDims,
const Aidge::IOIndex_t outputIdx) const
{
static_cast<void>(outputIdx);
if (outputIdx >= nbOutputs()) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "Operator output index out of range.");
}
if (nbInputs() != nbData()) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "Operator has attributes. Must be handled in an overrided function.");
}
if (!outputDimsForwarded() || getOutput(0)->nbDims() != outputDims.size()) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "Given outputDim out of range or output dim not forwarded yet.");
}
for (DimIdx_t i = 0; i < outputDims.size(); ++i) {
if (((outputDims[i] + firstEltDims[i]) > getOutput(0)->dims()[i]) || (outputDims[i] == 0)) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "Given outputDim out of range for dimension %lu (%lu + %lu)", static_cast<std::size_t>(i), firstEltDims[i], outputDims[i]);
}
}
// return the same Tensor description as given in function parameter for each data input
return std::vector<std::pair<std::vector<Aidge::DimSize_t>, std::vector<Aidge::DimSize_t>>>(nbData(),std::pair<std::vector<Aidge::DimSize_t>, std::vector<Aidge::DimSize_t>>(firstEltDims, outputDims));
}
void Aidge::ArithmeticOperator::computeOutputDims() {
// check inputs have been associated
if (!getInput(0) || !getInput(1)) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "At least one input was not connected");
}
// if (getInput(0)->empty() || getInput(1)->empty()) {
// AIDGE_THROW_OR_ABORT(std::runtime_error, "At least one input is empty");
// }
std::vector<std::vector<std::size_t>> inputsDims;
for (std::size_t i = 0; i < nbInputs(); i++)
{
inputsDims.push_back(getInput(i)->dims());
}
std::size_t outNbDims = 1;
for(size_t i=0; i<inputsDims.size() ; ++i)
outNbDims = inputsDims[i].size()>outNbDims?inputsDims[i].size():outNbDims;
std::vector<std::size_t> outDims(outNbDims, 1);
std::vector<std::size_t>::iterator it = outDims.end();
while (it != outDims.begin())
{
--it;
for (size_t i = 0; i < inputsDims.size(); i++)
{
if(!inputsDims[i].empty())
{
std::size_t dim = inputsDims[i].back();
inputsDims[i].pop_back();
if (*it != dim)
{
if(dim != 1)
{
if (*it != 1)
{
AIDGE_THROW_OR_ABORT(std::runtime_error, "Unsopported Tensor shape for Arithmetic Operation");
}
else
{
*it = dim;
}
}
}
}
}
}
mOutputs[0]->resize(outDims);
}
bool Aidge::ArithmeticOperator::outputDimsForwarded() const {
bool forwarded = true;
// check both inputs and outputs have been filled
for (IOIndex_t i = 0; i < nbInputs(); ++i) {
forwarded &= mInputs[i] ? !(getInput(i)->empty()) : false;
}
for (IOIndex_t i = 0; i < nbOutputs(); ++i) {
forwarded &= !(getOutput(i)->empty());
}
return forwarded;
}
void Aidge::ArithmeticOperator::setDataType(const DataType& dataType) const {
for (IOIndex_t i = 0; i < nbOutputs(); ++i) {
getOutput(i)->setDataType(dataType);
}
for (IOIndex_t i = 0; i < nbInputs(); ++i) {
if (!getInput(i)) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "Input was not set");
}
else {
getInput(i)->setDataType(dataType);
}
}
}
\ No newline at end of file
...@@ -20,19 +20,4 @@ ...@@ -20,19 +20,4 @@
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/utils/ErrorHandling.hpp" #include "aidge/utils/ErrorHandling.hpp"
const std::string Aidge::Div_Op::Type = "Div"; const std::string Aidge::Div_Op::Type = "Div";
\ No newline at end of file
void Aidge::Div_Op::computeOutputDims() {
// check inputs have been associated
if (!getInput(0) || !getInput(1)) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "At least one input was not connected");
}
if ((!getInput(0)->empty()) &&
((getInput(1)->size() == 1) || // div by a single value
(getInput(1)->size() == getInput(0)->size()) || // div elem-wise
(getInput(1)->nbDims() == 1 && getInput(1)->size() == getInput(0)->dims()[getInput(0)->nbDims()-1]))) // div by a Tensor with one dimension of output size
{
mOutputs[0]->resize(getInput(0)->dims());
}
}
\ No newline at end of file
...@@ -19,19 +19,4 @@ ...@@ -19,19 +19,4 @@
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/utils/ErrorHandling.hpp" #include "aidge/utils/ErrorHandling.hpp"
const std::string Aidge::Mul_Op::Type = "Mul"; const std::string Aidge::Mul_Op::Type = "Mul";
\ No newline at end of file
void Aidge::Mul_Op::computeOutputDims() {
// check inputs have been associated
if (!getInput(0) || !getInput(1)) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "At least one input was not connected");
}
if ((!getInput(0)->empty()) &&
((getInput(1)->size() == 1) || // mul by a single value
(getInput(1)->size() == getInput(0)->size()) || // mul elem-wise
(getInput(1)->nbDims() == 1 && getInput(1)->size() == getInput(0)->dims()[getInput(0)->nbDims()-1]))) // mul by a Tensor with one dimension of output size
{
mOutputs[0]->resize(getInput(0)->dims());
}
}
\ No newline at end of file
...@@ -19,19 +19,4 @@ ...@@ -19,19 +19,4 @@
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/utils/ErrorHandling.hpp" #include "aidge/utils/ErrorHandling.hpp"
const std::string Aidge::Pow_Op::Type = "Pow"; const std::string Aidge::Pow_Op::Type = "Pow";
\ No newline at end of file
void Aidge::Pow_Op::computeOutputDims() {
// check inputs have been associated
if (!getInput(0) || !getInput(1)) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "At least one input was not connected");
}
if ((!getInput(0)->empty()) &&
((getInput(1)->size() == 1) || // pow by a single value
(getInput(1)->size() == getInput(0)->size()) || // pow elem-wise
(getInput(1)->nbDims() == 1 && getInput(1)->size() == getInput(0)->dims()[getInput(0)->nbDims()-1]))) // pow by a Tensor with one dimension of output size
{
mOutputs[0]->resize(getInput(0)->dims());
}
}
\ No newline at end of file
...@@ -19,19 +19,4 @@ ...@@ -19,19 +19,4 @@
#include "aidge/utils/Types.h" #include "aidge/utils/Types.h"
#include "aidge/utils/ErrorHandling.hpp" #include "aidge/utils/ErrorHandling.hpp"
const std::string Aidge::Sub_Op::Type = "Sub"; const std::string Aidge::Sub_Op::Type = "Sub";
\ No newline at end of file
void Aidge::Sub_Op::computeOutputDims() {
// check inputs have been associated
if (!getInput(0) || !getInput(1)) {
AIDGE_THROW_OR_ABORT(std::runtime_error, "At least one input was not connected");
}
if ((!getInput(0)->empty()) &&
((getInput(1)->size() == 1) || // sub by a single value
(getInput(1)->size() == getInput(0)->size()) || // sub elem-wise
(getInput(1)->nbDims() == 1 && getInput(1)->size() == getInput(0)->dims()[getInput(0)->nbDims()-1]))) // sub by a Tensor with one dimension of output size
{
mOutputs[0]->resize(getInput(0)->dims());
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment