| 5 | namespace mgb::imperative::python { |
| 6 | |
| 7 | class CustomGradMaker { |
| 8 | bool output_size_set = false, input_has_grad_initialized = false; |
| 9 | CustomBackward& target; |
| 10 | size_t nr_inputs; |
| 11 | void init_input_has_grad() { |
| 12 | if (!input_has_grad_initialized) { |
| 13 | input_has_grad_initialized = true; |
| 14 | target.m_input_has_grad.resize(nr_inputs, true); |
| 15 | } |
| 16 | } |
| 17 | |
| 18 | public: |
| 19 | CustomGradMaker(CustomBackward& target, size_t nr_inputs) |
| 20 | : target(target), nr_inputs(nr_inputs) {} |
| 21 | |
| 22 | CustomGradMaker& backward(CustomBackward::BackwardFn f) { |
| 23 | mgb_assert(!target.m_backward); |
| 24 | target.m_backward = f; |
| 25 | return *this; |
| 26 | } |
| 27 | // mandatory |
| 28 | CustomGradMaker& output_size(size_t sz) { |
| 29 | mgb_assert(!output_size_set); |
| 30 | output_size_set = true; |
| 31 | target.m_output_attrs.resize(sz); |
| 32 | return *this; |
| 33 | } |
| 34 | // optional, defaults to all true |
| 35 | CustomGradMaker& input_has_grad(size_t i, bool v) { |
| 36 | init_input_has_grad(); |
| 37 | target.m_input_has_grad.at(i) = v; |
| 38 | return *this; |
| 39 | } |
| 40 | // optional, defaults to all true |
| 41 | CustomGradMaker& output_requires_grad(size_t i, bool v) { |
| 42 | target.m_output_attrs.at(i).requires_grad = v; |
| 43 | return *this; |
| 44 | } |
| 45 | // optional, defaults to all true |
| 46 | CustomGradMaker& output_captured(size_t i, bool v) { |
| 47 | target.m_output_attrs.at(i).captured = v; |
| 48 | return *this; |
| 49 | } |
| 50 | void finalize() { |
| 51 | mgb_assert(output_size_set); |
| 52 | init_input_has_grad(); |
| 53 | } |
| 54 | }; |
| 55 | |
| 56 | namespace { |
| 57 |
no test coverage detected