MCPcopy Create free account
hub / github.com/Oneflow-Inc/oneflow / Diagonal

Function Diagonal

oneflow/core/framework/tensor_methods.cpp:832–892  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

830}
831
832Maybe<Tensor> Diagonal(const std::shared_ptr<Tensor>& input, const int32_t offset,
833 const int32_t dim1, const int32_t dim2) {
834 const auto& shape = input->shape();
835 const auto& stride = JUST(input->stride());
836 const int64_t ndim = shape->NumAxes();
837 int64_t storage_offset = JUST(JUST(input->AsLocalTensor())->storage_offset());
838
839 // infer output storage_offset
840 int64_t diag_size = 0;
841 if (offset >= 0) {
842 diag_size = std::max<int64_t>(std::min(shape->At(dim1), shape->At(dim2) - offset), 0);
843 } else {
844 diag_size = std::max<int64_t>(std::min(shape->At(dim1) + offset, shape->At(dim2)), 0);
845 }
846 if (diag_size == 0) {
847 // skip
848 } else if (offset >= 0) {
849 storage_offset += offset * stride->at(dim2);
850 } else {
851 storage_offset -= offset * stride->at(dim1);
852 }
853
854 CHECK_GE_OR_RETURN(ndim, 2) << "input tensor's ndim should be >= 2, but got " << ndim;
855 // infer output shape and stride
856 DimVector out_shape(shape->dim_vec());
857 Stride out_stride(*stride);
858 out_shape.erase(out_shape.begin() + std::max(dim1, dim2));
859 out_stride.erase(out_stride.begin() + std::max(dim1, dim2));
860 out_shape.erase(out_shape.begin() + std::min(dim1, dim2));
861 out_stride.erase(out_stride.begin() + std::min(dim1, dim2));
862 out_shape.emplace_back(diag_size);
863 out_stride.emplace_back(stride->at(dim1) + stride->at(dim2));
864
865 // generate view tensor
866 auto output = JUST(BasicView(input, Shape(out_shape), out_stride, storage_offset));
867 // autograd
868 if (autograd::GradMode::is_enabled() && input->requires_grad()) {
869 std::vector<int32_t> input_index{dim1, dim2};
870 for (int32_t i = 0; i < ndim; i++) {
871 if (i != dim1 && i != dim2) { input_index.push_back(i); }
872 }
873
874 auto backward_fn = std::make_shared<BackwardFunction>();
875 backward_fn->body = [=](const TensorTuple& out_grads, TensorTuple* in_grads,
876 bool create_graph) -> Maybe<void> {
877 autograd::AutoGradMode mode(create_graph);
878 CHECK_EQ_OR_RETURN(out_grads.size(), 1)
879 << "out grad size should be 1, but got " << out_grads.size();
880 in_grads->resize(1);
881 std::shared_ptr<one::Tensor> d_x = JUST(functional::Transpose(input, input_index));
882 (*in_grads)[0] = JUST(functional::DiagonalGrad(out_grads[0], d_x, offset));
883 return Maybe<void>::Ok();
884 };
885 backward_fn->status = []() { return true; };
886 TensorTuple outputs{output};
887 JUST(GetThreadLocalAutogradEngine()->AddNode("view::diagonal_backward", backward_fn, {input},
888 &outputs));
889 }

Callers 4

operator()Method · 0.50
operator()Method · 0.50
operator()Method · 0.50
PyTensorObject_diagonalFunction · 0.50

Calls 15

BasicViewFunction · 0.85
push_backMethod · 0.80
AddNodeMethod · 0.80
ShapeClass · 0.70
is_enabledFunction · 0.70
TransposeFunction · 0.70
shapeMethod · 0.45
strideMethod · 0.45
NumAxesMethod · 0.45
storage_offsetMethod · 0.45
AsLocalTensorMethod · 0.45

Tested by

no test coverage detected