// // ShapeGatherV2.cpp // MNN // // Created by MNN on 2019/01/10. // Copyright © 2018, Alibaba Group Holding Limited // #include "shape/SizeComputer.hpp" #include "core/Macro.h" namespace MNN { class GatherV2Computer : public SizeComputer { virtual bool onComputeSize(const MNN::Op* op, const std::vector& inputs, const std::vector& outputs) const override { Tensor* indices = nullptr; int32_t paramShape[MNN_MAX_TENSOR_DIM]; int32_t paramDim = 0; if (inputs.size() == 1) { if (nullptr == op->main_as_Input()) { MNN_ERROR("One input GatherV2 should has blob parameter\n"); return false; } indices = inputs[0]; auto blob = op->main_as_Input(); outputs[0]->setType(blob->dtype()); if (nullptr != blob->dims()) { paramDim = blob->dims()->size(); ::memcpy(paramShape, blob->dims()->data(), paramDim * sizeof(int)); } TensorUtils::getDescribe(outputs[0])->dimensionFormat = blob->dformat(); } else { auto params = inputs[0]; indices = inputs[1]; paramDim = params->dimensions(); for (int i = 0; i < params->dimensions(); ++i) { paramShape[i] = params->length(i); } outputs[0]->buffer().type = params->buffer().type; TensorUtils::getDescribe(outputs[0])->dimensionFormat = TensorUtils::getDescribe(inputs[0])->dimensionFormat; } if (indices->getType().code != halide_type_int) { return false; } int axis = 0; if (inputs.size() == 3) { auto axis_tensor = inputs[2]; axis = axis_tensor->host()[0]; } if (op->main_type() == OpParameter_Axis && op->main_as_Axis()) { axis = op->main_as_Axis()->axis(); } if( axis <= -paramDim || axis >= paramDim) { return false; } if (axis < 0) { axis = paramDim + axis; } const int gather_dim_size = paramShape[axis]; MNN_ASSERT(gather_dim_size <= std::numeric_limits::max()); const int numDimensions = paramDim + indices->buffer().dimensions - 1; MNN_ASSERT(axis <= numDimensions); std::vector result_shape; for (int i = 0; i < axis; i++) { result_shape.push_back(paramShape[i]); } for (int i = 0; i < indices->buffer().dimensions; i++) { result_shape.push_back(indices->buffer().dim[i].extent); } for (int i = axis + 1; i < paramDim; i++) { result_shape.push_back(paramShape[i]); } outputs[0]->buffer().dimensions = (int)result_shape.size(); for (int i = 0; i < result_shape.size(); i++) { outputs[0]->buffer().dim[i].extent = result_shape.at(i); } return true; } }; REGISTER_SHAPE_INPUTS(GatherV2Computer, OpType_GatherV2, (std::vector{2})); REGISTER_SHAPE(GatherV2Computer, OpType_Gather); } // namespace MNN