| 475 | } |
| 476 | |
| 477 | std::optional<ValueRefList> removeAxis_grad_rule( |
| 478 | const OpDef& op, Span<ValueRef> inputs, Span<bool> inputs_require_grad, |
| 479 | CustomBackward& backward) { |
| 480 | auto&& removeAxis = op.cast_final_safe<RemoveAxis>(); |
| 481 | mgb_assert(inputs.size() == 1); |
| 482 | bool flag = inputs_require_grad[0]; |
| 483 | auto&& grad_op = AddAxis::make(removeAxis.axis); |
| 484 | std::sort(grad_op->axis.begin(), grad_op->axis.end()); |
| 485 | auto maker = CustomGradMaker(backward, inputs.size()); |
| 486 | maker.output_size(1).output_captured(0, false); |
| 487 | maker.backward([grad_op_ = std::move(grad_op), flag_ = flag](Span<ValueRef> grads) { |
| 488 | mgb_assert(grads.size() == 1); |
| 489 | ValueRef grad = grads[0]; |
| 490 | SmallVector<ValueRef> ret(1); |
| 491 | if (grad && flag_) { |
| 492 | ret[0] = imperative::apply(*grad_op_, grad)[0]; |
| 493 | } |
| 494 | return ret; |
| 495 | }); |
| 496 | maker.finalize(); |
| 497 | return imperative::apply(op, inputs); |
| 498 | } |
| 499 | |
| 500 | std::optional<ValueRefList> pixelShuffle_grad_rule( |
| 501 | const OpDef& op, Span<ValueRef> inputs, Span<bool> inputs_require_grad, |
nothing calls this directly
no test coverage detected