/******************************************************************************** * 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_PRODUCER_H_ #define AIDGE_CORE_OPERATOR_PRODUCER_H_ #include <array> #include <vector> #include "aidge/utils/Types.h" #include "aidge/data/Tensor.hpp" #include "aidge/graph/Node.hpp" #include "aidge/operator/OperatorTensor.hpp" #include "aidge/utils/StaticAttributes.hpp" #include "aidge/utils/Registrar.hpp" namespace Aidge { class Producer_Op : public OperatorTensor, public Registrable<Producer_Op, std::string, std::unique_ptr<OperatorImpl>( const Producer_Op &)> { public: static constexpr const char* Type = "Producer"; template <std::size_t DIM> Producer_Op(const std::array<DimSize_t, DIM>& dims) : OperatorTensor(Type, 0, 0, 1) { mOutputs[0]->resize(dims); } Producer_Op(const std::shared_ptr<Tensor> tensor) : OperatorTensor(Type, 0, 0, 1) { mOutputs[0] = tensor; // copy the pointer of the Tensor } /** * @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 OperatorTensor to copy. */ Producer_Op(const Producer_Op& op) : OperatorTensor(op) { for (std::size_t i = 0; i < static_cast<std::size_t>(nbOutputs()); ++i) { mOutputs[i] = std::make_shared<Tensor>(*(op.getOutput(i))); } mImpl = op.mImpl ? Registrar<Producer_Op>::create(op.mOutputs[0]->getImpl()->backend())(*this) : nullptr; } /** * @brief Clone the operator using its copy-constructor. * @see Operator::Producer_Op */ std::shared_ptr<Operator> clone() const override { return std::make_shared<Producer_Op>(*this); } void associateInput(const IOIndex_t /*inputIdx*/, const std::shared_ptr<Data>& /*data*/) override final { AIDGE_THROW_OR_ABORT(std::runtime_error, "Producer operator takes no input."); } void computeOutputDims() override final {} bool outputDimsForwarded() const override final {return true;} inline const std::vector<DimSize_t> dims() const noexcept { return mOutputs[0]->dims(); } void setBackend(const std::string& name) override { mImpl = Registrar<Producer_Op>::create(name)(*this); mOutputs[0]->setBackend(name); } static const std::vector<std::string> getInputsName(){ return {}; } static const std::vector<std::string> getOutputsName(){ return {"data_output"}; } public: void forward() override final { printf("Basic Producer forward() function.\n"); } void backward() override final { printf("Basic Producer backward() function.\n"); } }; template <std::array<DimSize_t, 1>::size_type DIM> inline std::shared_ptr<Node> Producer(const std::array<DimSize_t, DIM> &dims, const std::string& name = "") { static_assert(DIM<=MaxDim,"Too many tensor dimensions required by Producer, not supported"); return std::make_shared<Node>(std::make_shared<Producer_Op>(dims), name); } // helper with C-style array instead of std::array for kernel_dims to allow automatic template DIM deduction template <std::size_t DIM> inline std::shared_ptr<Node> Producer(DimSize_t const (&dims)[DIM], const std::string& name = "") { return Producer(to_array(dims), name); } inline std::shared_ptr<Node> Producer(const std::shared_ptr<Tensor> tensor, const std::string& name = "") { return std::make_shared<Node>(std::make_shared<Producer_Op>(tensor), name); } template <std::array<DimSize_t, 1>::size_type DIM> void addProducer(std::shared_ptr<Node>& otherNode, const IOIndex_t inputIdx, const std::array<DimSize_t, DIM>& dims, const std::string& extension) { assert(inputIdx != gk_IODefaultIndex); static_assert(DIM<=MaxDim,"Too many tensor dimensions required by addProducer, not supported"); const std::string prodName = (otherNode->name().empty()) ? "" : (otherNode->name() + std::string("_") + extension); auto prod = Producer(dims, prodName); prod->addChild(otherNode, 0, inputIdx); otherNode->getOperator()->associateInput(inputIdx, prod->getOperator()->getRawOutput(0)); } // helper with C-style array instead of std::array for kernel_dims to allow automatic template DIM deduction template <std::size_t DIM> void addProducer(std::shared_ptr<Node>& otherNode, const IOIndex_t inputIdx, DimSize_t const (&dims)[DIM], const std::string& extension) { addProducer(otherNode, inputIdx, to_array(dims), extension); } } // namespace Aidge #endif /* AIDGE_CORE_OPERATOR_PRODUCER_H_ */