Handle aten.constant_pad_nd - pad with a constant value. PyTorch pad format: [left_0, right_0, left_1, right_1, ...] MLX pad_width format: [(before_0, after_0), (before_1, after_1), ...] Note: PyTorch pads in reverse order (last dimensions first).
(P: MLXProgramBuilder, n: Node)
| 2813 | |
| 2814 | @REGISTRY.register(target=[torch.ops.aten.constant_pad_nd.default]) |
| 2815 | def _constant_pad_nd_handler(P: MLXProgramBuilder, n: Node) -> Slot: |
| 2816 | """Handle aten.constant_pad_nd - pad with a constant value. |
| 2817 | |
| 2818 | PyTorch pad format: [left_0, right_0, left_1, right_1, ...] |
| 2819 | MLX pad_width format: [(before_0, after_0), (before_1, after_1), ...] |
| 2820 | |
| 2821 | Note: PyTorch pads in reverse order (last dimensions first). |
| 2822 | """ |
| 2823 | args = P.args(n) |
| 2824 | require_args(args, 2, 3, "aten.constant_pad_nd") |
| 2825 | require_kwargs(P.kwargs(n), set(), "aten.constant_pad_nd") |
| 2826 | x_node, pad = args[0], args[1] |
| 2827 | value = args[2] if len(args) > 2 else 0 |
| 2828 | |
| 2829 | if not isinstance(value, (int, float)): |
| 2830 | raise ValueError( |
| 2831 | f"aten.constant_pad_nd: constant value must be a scalar, got {type(value)}" |
| 2832 | ) |
| 2833 | |
| 2834 | # Convert PyTorch pad format to MLX pad_width format |
| 2835 | # PyTorch: [left_D, right_D, left_D-1, right_D-1, ...] |
| 2836 | # MLX: [(before_0, after_0), (before_1, after_1), ..., (before_D, after_D)] |
| 2837 | if len(pad) % 2 != 0: |
| 2838 | raise ValueError( |
| 2839 | f"aten.constant_pad_nd: pad length must be even, got {len(pad)}" |
| 2840 | ) |
| 2841 | |
| 2842 | x = P.slot_map([x_node])[0] |
| 2843 | x_meta = n.args[0].meta.get("val") |
| 2844 | if x_meta is None: |
| 2845 | raise ValueError("Input tensor metadata not found for constant_pad_nd") |
| 2846 | |
| 2847 | ndim = len(x_meta.shape) |
| 2848 | num_pad_dims = len(pad) // 2 |
| 2849 | |
| 2850 | if num_pad_dims > ndim: |
| 2851 | raise ValueError( |
| 2852 | f"aten.constant_pad_nd: trying to pad {num_pad_dims} dimensions " |
| 2853 | f"but input has only {ndim} dimensions" |
| 2854 | ) |
| 2855 | |
| 2856 | # Build MLX pad_width: start with zeros for non-padded dims |
| 2857 | pad_width = [] |
| 2858 | for _ in range(ndim - num_pad_dims): |
| 2859 | pad_width.extend([0, 0]) # No padding for these dimensions |
| 2860 | |
| 2861 | # Add padding for the padded dimensions (reverse order) |
| 2862 | for i in range(num_pad_dims - 1, -1, -1): |
| 2863 | left = pad[i * 2] |
| 2864 | right = pad[i * 2 + 1] |
| 2865 | pad_width.extend([left, right]) |
| 2866 | |
| 2867 | out = P.make_or_get_slot(n) |
| 2868 | P.emit( |
| 2869 | PadNode( |
| 2870 | x=P.slot_to_tid(x), |
| 2871 | out=P.slot_to_tid(out), |
| 2872 | pad_width=[P.to_int_or_vid(v) for v in pad_width], |
nothing calls this directly
no test coverage detected