| 873 | |
| 874 | template <typename Op> |
| 875 | std::tuple<SmallVector<LogicalTensorDesc>, bool> infer_output_attrs_fallible( |
| 876 | const OpDef& def, const SmallVector<LogicalTensorDesc>& inputs) { |
| 877 | bool success = inputs[0].layout.ndim != 0; |
| 878 | LogicalTensorDesc dest; |
| 879 | auto&& xxx_rng_def = def.cast_final_safe<Op>(); |
| 880 | size_t nr_inp = inputs.size(); |
| 881 | constexpr bool rng_with_shape = OpMeth<Op>::DnnOp::NR_INPUTS == 0; |
| 882 | if (rng_with_shape) { |
| 883 | mgb_assert( |
| 884 | nr_inp == 1, "%s expects 1 inputs; got %lu actually", |
| 885 | xxx_rng_def.dyn_typeinfo()->name, nr_inp); |
| 886 | } |
| 887 | dest.comp_node = inputs[0].comp_node; |
| 888 | if (success) { |
| 889 | dest.layout = _InferLayout<rng_with_shape>::do_infer(inputs[0], xxx_rng_def); |
| 890 | } else { |
| 891 | dest.layout = TensorLayout(inputs[0].layout.dtype); |
| 892 | } |
| 893 | return {{dest}, inputs[0].layout.ndim != 0}; |
| 894 | } |
| 895 | |
| 896 | template <> |
| 897 | std::tuple<SmallVector<LogicalTensorDesc>, bool> infer_output_attrs_fallible< |