Skip to main content

burn_dispatch/ops/
module.rs

1use burn_backend::{
2    IntDType,
3    ops::{
4        BatchNormTrain, BatchNormTrainBackward, DeformConv2dBackward, MaxPool1dBackward,
5        MaxPool1dWithIndices, MaxPool2dBackward, MaxPool2dWithIndices, ModuleOps,
6    },
7    tensor::{FloatTensor, IntTensor},
8};
9use burn_backend_extension::backend_dispatch;
10
11use crate::Dispatch;
12
13#[backend_dispatch]
14impl ModuleOps<Self> for Dispatch {
15    fn batch_norm(
16        x: FloatTensor<Self>,
17        gamma: FloatTensor<Self>,
18        beta: FloatTensor<Self>,
19        mean: FloatTensor<Self>,
20        variance: FloatTensor<Self>,
21        epsilon: f64,
22    ) -> FloatTensor<Self> {
23        B::batch_norm(x, gamma, beta, mean, variance, epsilon)
24    }
25
26    #[backend_dispatch(skip)]
27    fn batch_norm_train(
28        x: FloatTensor<Self>,
29        gamma: FloatTensor<Self>,
30        beta: FloatTensor<Self>,
31        epsilon: f64,
32    ) -> BatchNormTrain<Self> {
33        let (output, mean, variance) = Self::batch_norm_train_dispatch(x, gamma, beta, epsilon);
34        BatchNormTrain::new(output, mean, variance)
35    }
36
37    #[backend_dispatch(skip)]
38    fn batch_norm_train_backward(
39        x: FloatTensor<Self>,
40        gamma: FloatTensor<Self>,
41        mean: FloatTensor<Self>,
42        variance: FloatTensor<Self>,
43        epsilon: f64,
44        output_grad: FloatTensor<Self>,
45    ) -> BatchNormTrainBackward<Self> {
46        let (x_grad, gamma_grad, beta_grad) = Self::batch_norm_train_backward_dispatch(
47            x,
48            gamma,
49            mean,
50            variance,
51            epsilon,
52            output_grad,
53        );
54        BatchNormTrainBackward::new(x_grad, gamma_grad, beta_grad)
55    }
56
57    fn conv2d(
58        x: FloatTensor<Self>,
59        weight: FloatTensor<Self>,
60        bias: Option<FloatTensor<Self>>,
61        options: burn_backend::ops::ConvOptions<2>,
62    ) -> FloatTensor<Self> {
63        B::conv2d(x, weight, bias, options)
64    }
65
66    fn deform_conv2d(
67        x: FloatTensor<Self>,
68        offset: FloatTensor<Self>,
69        weight: FloatTensor<Self>,
70        mask: Option<FloatTensor<Self>>,
71        bias: Option<FloatTensor<Self>>,
72        options: burn_backend::ops::DeformConvOptions<2>,
73    ) -> FloatTensor<Self> {
74        B::deform_conv2d(x, offset, weight, mask, bias, options)
75    }
76
77    #[backend_dispatch(skip)]
78    fn deform_conv2d_backward(
79        x: FloatTensor<Self>,
80        offset: FloatTensor<Self>,
81        weight: FloatTensor<Self>,
82        mask: Option<FloatTensor<Self>>,
83        bias: Option<FloatTensor<Self>>,
84        output_grad: FloatTensor<Self>,
85        options: burn_backend::ops::DeformConvOptions<2>,
86    ) -> DeformConv2dBackward<Self> {
87        let (x_grad, offset_grad, weight_grad, mask_grad, bias_grad) =
88            Self::deform_conv2d_backward_dispatch(
89                x,
90                offset,
91                weight,
92                mask,
93                bias,
94                output_grad,
95                options,
96            );
97        DeformConv2dBackward::new(x_grad, offset_grad, weight_grad, mask_grad, bias_grad)
98    }
99
100    fn conv3d(
101        x: FloatTensor<Self>,
102        weight: FloatTensor<Self>,
103        bias: Option<FloatTensor<Self>>,
104        options: burn_backend::ops::ConvOptions<3>,
105    ) -> FloatTensor<Self> {
106        B::conv3d(x, weight, bias, options)
107    }
108
109    fn conv_transpose2d(
110        x: FloatTensor<Self>,
111        weight: FloatTensor<Self>,
112        bias: Option<FloatTensor<Self>>,
113        options: burn_backend::ops::ConvTransposeOptions<2>,
114    ) -> FloatTensor<Self> {
115        B::conv_transpose2d(x, weight, bias, options)
116    }
117
118    fn conv_transpose3d(
119        x: FloatTensor<Self>,
120        weight: FloatTensor<Self>,
121        bias: Option<FloatTensor<Self>>,
122        options: burn_backend::ops::ConvTransposeOptions<3>,
123    ) -> FloatTensor<Self> {
124        B::conv_transpose3d(x, weight, bias, options)
125    }
126
127    fn avg_pool2d(
128        x: FloatTensor<Self>,
129        kernel_size: [usize; 2],
130        stride: [usize; 2],
131        padding: [usize; 2],
132        count_include_pad: bool,
133        ceil_mode: bool,
134    ) -> FloatTensor<Self> {
135        B::avg_pool2d(
136            x,
137            kernel_size,
138            stride,
139            padding,
140            count_include_pad,
141            ceil_mode,
142        )
143    }
144
145    fn avg_pool2d_backward(
146        x: FloatTensor<Self>,
147        grad: FloatTensor<Self>,
148        kernel_size: [usize; 2],
149        stride: [usize; 2],
150        padding: [usize; 2],
151        count_include_pad: bool,
152        ceil_mode: bool,
153    ) -> FloatTensor<Self> {
154        B::avg_pool2d_backward(
155            x,
156            grad,
157            kernel_size,
158            stride,
159            padding,
160            count_include_pad,
161            ceil_mode,
162        )
163    }
164
165    fn adaptive_avg_pool2d(x: FloatTensor<Self>, output_size: [usize; 2]) -> FloatTensor<Self> {
166        B::adaptive_avg_pool2d(x, output_size)
167    }
168
169    fn adaptive_avg_pool2d_backward(
170        x: FloatTensor<Self>,
171        grad: FloatTensor<Self>,
172    ) -> FloatTensor<Self> {
173        B::adaptive_avg_pool2d_backward(x, grad)
174    }
175
176    fn adaptive_avg_pool3d(x: FloatTensor<Self>, output_size: [usize; 3]) -> FloatTensor<Self> {
177        B::adaptive_avg_pool3d(x, output_size)
178    }
179
180    fn adaptive_avg_pool3d_backward(
181        x: FloatTensor<Self>,
182        grad: FloatTensor<Self>,
183    ) -> FloatTensor<Self> {
184        B::adaptive_avg_pool3d_backward(x, grad)
185    }
186
187    fn max_pool2d(
188        x: FloatTensor<Self>,
189        kernel_size: [usize; 2],
190        stride: [usize; 2],
191        padding: [usize; 2],
192        dilation: [usize; 2],
193        ceil_mode: bool,
194    ) -> FloatTensor<Self> {
195        B::max_pool2d(x, kernel_size, stride, padding, dilation, ceil_mode)
196    }
197
198    #[backend_dispatch(skip)]
199    fn max_pool2d_with_indices(
200        x: FloatTensor<Self>,
201        kernel_size: [usize; 2],
202        stride: [usize; 2],
203        padding: [usize; 2],
204        dilation: [usize; 2],
205        ceil_mode: bool,
206        indices_dtype: IntDType,
207    ) -> MaxPool2dWithIndices<Self> {
208        let (output, indices) = Self::max_pool2d_with_indices_dispatch(
209            x,
210            kernel_size,
211            stride,
212            padding,
213            dilation,
214            ceil_mode,
215            indices_dtype,
216        );
217        MaxPool2dWithIndices::new(output, indices)
218    }
219
220    #[backend_dispatch(skip)]
221    fn max_pool2d_with_indices_backward(
222        x: FloatTensor<Self>,
223        kernel_size: [usize; 2],
224        stride: [usize; 2],
225        padding: [usize; 2],
226        dilation: [usize; 2],
227        ceil_mode: bool,
228        output_grad: FloatTensor<Self>,
229        indices: IntTensor<Self>,
230    ) -> MaxPool2dBackward<Self> {
231        let x_grad = Self::max_pool2d_with_indices_backward_dispatch(
232            x,
233            kernel_size,
234            stride,
235            padding,
236            dilation,
237            ceil_mode,
238            output_grad,
239            indices,
240        );
241        MaxPool2dBackward::new(x_grad)
242    }
243
244    fn interpolate(
245        x: FloatTensor<Self>,
246        output_size: [usize; 2],
247        options: burn_backend::ops::InterpolateOptions,
248    ) -> FloatTensor<Self> {
249        B::interpolate(x, output_size, options)
250    }
251
252    fn interpolate_backward(
253        x: FloatTensor<Self>,
254        grad: FloatTensor<Self>,
255        output_size: [usize; 2],
256        options: burn_backend::ops::InterpolateOptions,
257    ) -> FloatTensor<Self> {
258        B::interpolate_backward(x, grad, output_size, options)
259    }
260
261    fn embedding(weights: FloatTensor<Self>, indices: IntTensor<Self>) -> FloatTensor<Self> {
262        B::embedding(weights, indices)
263    }
264
265    fn embedding_backward(
266        weights: FloatTensor<Self>,
267        output_grad: FloatTensor<Self>,
268        indices: IntTensor<Self>,
269    ) -> FloatTensor<Self> {
270        B::embedding_backward(weights, output_grad, indices)
271    }
272
273    fn conv1d(
274        x: FloatTensor<Self>,
275        weight: FloatTensor<Self>,
276        bias: Option<FloatTensor<Self>>,
277        options: burn_backend::ops::ConvOptions<1>,
278    ) -> FloatTensor<Self> {
279        B::conv1d(x, weight, bias, options)
280    }
281
282    fn conv1d_x_backward(
283        x: FloatTensor<Self>,
284        weight: FloatTensor<Self>,
285        output_grad: FloatTensor<Self>,
286        options: burn_backend::ops::ConvOptions<1>,
287    ) -> FloatTensor<Self> {
288        B::conv1d_x_backward(x, weight, output_grad, options)
289    }
290
291    fn conv1d_weight_backward(
292        x: FloatTensor<Self>,
293        weight: FloatTensor<Self>,
294        output_grad: FloatTensor<Self>,
295        options: burn_backend::ops::ConvOptions<1>,
296    ) -> FloatTensor<Self> {
297        B::conv1d_weight_backward(x, weight, output_grad, options)
298    }
299
300    fn conv1d_bias_backward(
301        x: FloatTensor<Self>,
302        bias: FloatTensor<Self>,
303        output_grad: FloatTensor<Self>,
304    ) -> FloatTensor<Self> {
305        B::conv1d_bias_backward(x, bias, output_grad)
306    }
307
308    fn conv2d_x_backward(
309        x: FloatTensor<Self>,
310        weight: FloatTensor<Self>,
311        output_grad: FloatTensor<Self>,
312        options: burn_backend::ops::ConvOptions<2>,
313    ) -> FloatTensor<Self> {
314        B::conv2d_x_backward(x, weight, output_grad, options)
315    }
316
317    fn conv2d_weight_backward(
318        x: FloatTensor<Self>,
319        weight: FloatTensor<Self>,
320        output_grad: FloatTensor<Self>,
321        options: burn_backend::ops::ConvOptions<2>,
322    ) -> FloatTensor<Self> {
323        B::conv2d_weight_backward(x, weight, output_grad, options)
324    }
325
326    fn conv2d_bias_backward(
327        x: FloatTensor<Self>,
328        bias: FloatTensor<Self>,
329        output_grad: FloatTensor<Self>,
330    ) -> FloatTensor<Self> {
331        B::conv2d_bias_backward(x, bias, output_grad)
332    }
333
334    fn conv3d_x_backward(
335        x: FloatTensor<Self>,
336        weight: FloatTensor<Self>,
337        output_grad: FloatTensor<Self>,
338        options: burn_backend::ops::ConvOptions<3>,
339    ) -> FloatTensor<Self> {
340        B::conv3d_x_backward(x, weight, output_grad, options)
341    }
342
343    fn conv3d_weight_backward(
344        x: FloatTensor<Self>,
345        weight: FloatTensor<Self>,
346        output_grad: FloatTensor<Self>,
347        options: burn_backend::ops::ConvOptions<3>,
348    ) -> FloatTensor<Self> {
349        B::conv3d_weight_backward(x, weight, output_grad, options)
350    }
351
352    fn conv3d_bias_backward(
353        x: FloatTensor<Self>,
354        bias: FloatTensor<Self>,
355        output_grad: FloatTensor<Self>,
356    ) -> FloatTensor<Self> {
357        B::conv3d_bias_backward(x, bias, output_grad)
358    }
359
360    fn conv_transpose1d(
361        x: FloatTensor<Self>,
362        weight: FloatTensor<Self>,
363        bias: Option<FloatTensor<Self>>,
364        options: burn_backend::ops::ConvTransposeOptions<1>,
365    ) -> FloatTensor<Self> {
366        B::conv_transpose1d(x, weight, bias, options)
367    }
368
369    fn conv_transpose1d_x_backward(
370        weight: FloatTensor<Self>,
371        output_grad: FloatTensor<Self>,
372        options: burn_backend::ops::ConvTransposeOptions<1>,
373    ) -> FloatTensor<Self> {
374        B::conv_transpose1d_x_backward(weight, output_grad, options)
375    }
376
377    fn conv_transpose1d_weight_backward(
378        x: FloatTensor<Self>,
379        weight: FloatTensor<Self>,
380        output_grad: FloatTensor<Self>,
381        options: burn_backend::ops::ConvTransposeOptions<1>,
382    ) -> FloatTensor<Self> {
383        B::conv_transpose1d_weight_backward(x, weight, output_grad, options)
384    }
385
386    fn conv_transpose1d_bias_backward(
387        x: FloatTensor<Self>,
388        bias: FloatTensor<Self>,
389        output_grad: FloatTensor<Self>,
390    ) -> FloatTensor<Self> {
391        B::conv_transpose1d_bias_backward(x, bias, output_grad)
392    }
393
394    fn conv_transpose2d_x_backward(
395        weight: FloatTensor<Self>,
396        output_grad: FloatTensor<Self>,
397        options: burn_backend::ops::ConvTransposeOptions<2>,
398    ) -> FloatTensor<Self> {
399        B::conv_transpose2d_x_backward(weight, output_grad, options)
400    }
401
402    fn conv_transpose2d_weight_backward(
403        x: FloatTensor<Self>,
404        weight: FloatTensor<Self>,
405        output_grad: FloatTensor<Self>,
406        options: burn_backend::ops::ConvTransposeOptions<2>,
407    ) -> FloatTensor<Self> {
408        B::conv_transpose2d_weight_backward(x, weight, output_grad, options)
409    }
410
411    fn conv_transpose2d_bias_backward(
412        x: FloatTensor<Self>,
413        bias: FloatTensor<Self>,
414        output_grad: FloatTensor<Self>,
415    ) -> FloatTensor<Self> {
416        B::conv_transpose2d_bias_backward(x, bias, output_grad)
417    }
418
419    fn conv_transpose3d_x_backward(
420        weight: FloatTensor<Self>,
421        output_grad: FloatTensor<Self>,
422        options: burn_backend::ops::ConvTransposeOptions<3>,
423    ) -> FloatTensor<Self> {
424        B::conv_transpose3d_x_backward(weight, output_grad, options)
425    }
426
427    fn conv_transpose3d_weight_backward(
428        x: FloatTensor<Self>,
429        weight: FloatTensor<Self>,
430        output_grad: FloatTensor<Self>,
431        options: burn_backend::ops::ConvTransposeOptions<3>,
432    ) -> FloatTensor<Self> {
433        B::conv_transpose3d_weight_backward(x, weight, output_grad, options)
434    }
435
436    fn conv_transpose3d_bias_backward(
437        x: FloatTensor<Self>,
438        bias: FloatTensor<Self>,
439        output_grad: FloatTensor<Self>,
440    ) -> FloatTensor<Self> {
441        B::conv_transpose3d_bias_backward(x, bias, output_grad)
442    }
443
444    fn unfold4d(
445        x: FloatTensor<Self>,
446        kernel_size: [usize; 2],
447        options: burn_backend::ops::UnfoldOptions,
448    ) -> FloatTensor<Self> {
449        B::unfold4d(x, kernel_size, options)
450    }
451
452    fn avg_pool1d(
453        x: FloatTensor<Self>,
454        kernel_size: usize,
455        stride: usize,
456        padding: usize,
457        count_include_pad: bool,
458        ceil_mode: bool,
459    ) -> FloatTensor<Self> {
460        B::avg_pool1d(
461            x,
462            kernel_size,
463            stride,
464            padding,
465            count_include_pad,
466            ceil_mode,
467        )
468    }
469
470    fn avg_pool1d_backward(
471        x: FloatTensor<Self>,
472        grad: FloatTensor<Self>,
473        kernel_size: usize,
474        stride: usize,
475        padding: usize,
476        count_include_pad: bool,
477        ceil_mode: bool,
478    ) -> FloatTensor<Self> {
479        B::avg_pool1d_backward(
480            x,
481            grad,
482            kernel_size,
483            stride,
484            padding,
485            count_include_pad,
486            ceil_mode,
487        )
488    }
489
490    fn adaptive_avg_pool1d(x: FloatTensor<Self>, output_size: usize) -> FloatTensor<Self> {
491        B::adaptive_avg_pool1d(x, output_size)
492    }
493
494    fn adaptive_avg_pool1d_backward(
495        x: FloatTensor<Self>,
496        grad: FloatTensor<Self>,
497    ) -> FloatTensor<Self> {
498        B::adaptive_avg_pool1d_backward(x, grad)
499    }
500
501    fn max_pool1d(
502        x: FloatTensor<Self>,
503        kernel_size: usize,
504        stride: usize,
505        padding: usize,
506        dilation: usize,
507        ceil_mode: bool,
508    ) -> FloatTensor<Self> {
509        B::max_pool1d(x, kernel_size, stride, padding, dilation, ceil_mode)
510    }
511
512    #[backend_dispatch(skip)]
513    fn max_pool1d_with_indices(
514        x: FloatTensor<Self>,
515        kernel_size: usize,
516        stride: usize,
517        padding: usize,
518        dilation: usize,
519        ceil_mode: bool,
520        indices_dtype: IntDType,
521    ) -> MaxPool1dWithIndices<Self> {
522        let (output, indices) = Self::max_pool1d_with_indices_dispatch(
523            x,
524            kernel_size,
525            stride,
526            padding,
527            dilation,
528            ceil_mode,
529            indices_dtype,
530        );
531        MaxPool1dWithIndices::new(output, indices)
532    }
533
534    #[backend_dispatch(skip)]
535    fn max_pool1d_with_indices_backward(
536        x: FloatTensor<Self>,
537        kernel_size: usize,
538        stride: usize,
539        padding: usize,
540        dilation: usize,
541        ceil_mode: bool,
542        output_grad: FloatTensor<Self>,
543        indices: IntTensor<Self>,
544    ) -> MaxPool1dBackward<Self> {
545        let x_grad = Self::max_pool1d_with_indices_backward_dispatch(
546            x,
547            kernel_size,
548            stride,
549            padding,
550            dilation,
551            ceil_mode,
552            output_grad,
553            indices,
554        );
555        MaxPool1dBackward::new(x_grad)
556    }
557
558    fn attention(
559        query: FloatTensor<Self>,
560        key: FloatTensor<Self>,
561        value: FloatTensor<Self>,
562        mask: Option<burn_backend::tensor::BoolTensor<Self>>,
563        attn_bias: Option<FloatTensor<Self>>,
564        options: burn_backend::ops::AttentionModuleOptions,
565    ) -> FloatTensor<Self> {
566        B::attention(query, key, value, mask, attn_bias, options)
567    }
568
569    fn layer_norm(
570        tensor: FloatTensor<Self>,
571        gamma: FloatTensor<Self>,
572        beta: Option<FloatTensor<Self>>,
573        epsilon: f64,
574    ) -> FloatTensor<Self> {
575        B::layer_norm(tensor, gamma, beta, epsilon)
576    }
577
578    #[backend_dispatch(skip)]
579    fn has_ctc_loss_backward() -> bool {
580        // Dispatch routes per-tensor at runtime, but autodiff queries this flag
581        // statically. Returning `false` makes autodiff differentiate through
582        // the default decomposed forward, which is safe for every inner
583        // backend regardless of whether it has its own ctc_loss_backward.
584        false
585    }
586
587    fn ctc_loss(
588        log_probs: FloatTensor<Self>,
589        targets: IntTensor<Self>,
590        input_lengths: IntTensor<Self>,
591        target_lengths: IntTensor<Self>,
592        blank: usize,
593    ) -> FloatTensor<Self> {
594        B::ctc_loss(log_probs, targets, input_lengths, target_lengths, blank)
595    }
596
597    fn ctc_loss_backward(
598        log_probs: FloatTensor<Self>,
599        targets: IntTensor<Self>,
600        input_lengths: IntTensor<Self>,
601        target_lengths: IntTensor<Self>,
602        grad_loss: FloatTensor<Self>,
603        blank: usize,
604    ) -> FloatTensor<Self> {
605        B::ctc_loss_backward(
606            log_probs,
607            targets,
608            input_lengths,
609            target_lengths,
610            grad_loss,
611            blank,
612        )
613    }
614
615    // TODO: linear ops
616    // fn linear(
617    //         x: FloatTensor<Self>,
618    //         weight: FloatTensor<Self>,
619    //         bias: Option<FloatTensor<Self>>,
620    //     ) -> FloatTensor<Self> {
621
622    // }
623}
624
625#[backend_dispatch]
626impl Dispatch {
627    fn deform_conv2d_backward_dispatch(
628        x: FloatTensor<Self>,
629        offset: FloatTensor<Self>,
630        weight: FloatTensor<Self>,
631        mask: Option<FloatTensor<Self>>,
632        bias: Option<FloatTensor<Self>>,
633        output_grad: FloatTensor<Self>,
634        options: burn_backend::ops::DeformConvOptions<2>,
635    ) -> (
636        FloatTensor<Self>,
637        FloatTensor<Self>,
638        FloatTensor<Self>,
639        Option<FloatTensor<Self>>,
640        Option<FloatTensor<Self>>,
641    ) {
642        let output = B::deform_conv2d_backward(x, offset, weight, mask, bias, output_grad, options);
643        (
644            output.x_grad,
645            output.offset_grad,
646            output.weight_grad,
647            output.mask_grad,
648            output.bias_grad,
649        )
650    }
651
652    fn batch_norm_train_dispatch(
653        x: FloatTensor<Self>,
654        gamma: FloatTensor<Self>,
655        beta: FloatTensor<Self>,
656        epsilon: f64,
657    ) -> (FloatTensor<Self>, FloatTensor<Self>, FloatTensor<Self>) {
658        let result = B::batch_norm_train(x, gamma, beta, epsilon);
659        (result.output, result.mean, result.variance)
660    }
661
662    fn batch_norm_train_backward_dispatch(
663        x: FloatTensor<Self>,
664        gamma: FloatTensor<Self>,
665        mean: FloatTensor<Self>,
666        variance: FloatTensor<Self>,
667        epsilon: f64,
668        output_grad: FloatTensor<Self>,
669    ) -> (FloatTensor<Self>, FloatTensor<Self>, FloatTensor<Self>) {
670        let result = B::batch_norm_train_backward(x, gamma, mean, variance, epsilon, output_grad);
671        (result.x_grad, result.gamma_grad, result.beta_grad)
672    }
673
674    fn max_pool2d_with_indices_dispatch(
675        x: FloatTensor<Self>,
676        kernel_size: [usize; 2],
677        stride: [usize; 2],
678        padding: [usize; 2],
679        dilation: [usize; 2],
680        ceil_mode: bool,
681        indices_dtype: IntDType,
682    ) -> (FloatTensor<Self>, IntTensor<Self>) {
683        let output = B::max_pool2d_with_indices(
684            x,
685            kernel_size,
686            stride,
687            padding,
688            dilation,
689            ceil_mode,
690            indices_dtype,
691        );
692        (output.output, output.indices)
693    }
694
695    fn max_pool2d_with_indices_backward_dispatch(
696        x: FloatTensor<Self>,
697        kernel_size: [usize; 2],
698        stride: [usize; 2],
699        padding: [usize; 2],
700        dilation: [usize; 2],
701        ceil_mode: bool,
702        output_grad: FloatTensor<Self>,
703        indices: IntTensor<Self>,
704    ) -> FloatTensor<Self> {
705        B::max_pool2d_with_indices_backward(
706            x,
707            kernel_size,
708            stride,
709            padding,
710            dilation,
711            ceil_mode,
712            output_grad,
713            indices,
714        )
715        .x_grad
716    }
717
718    fn max_pool1d_with_indices_dispatch(
719        x: FloatTensor<Self>,
720        kernel_size: usize,
721        stride: usize,
722        padding: usize,
723        dilation: usize,
724        ceil_mode: bool,
725        indices_dtype: IntDType,
726    ) -> (FloatTensor<Self>, IntTensor<Self>) {
727        let output = B::max_pool1d_with_indices(
728            x,
729            kernel_size,
730            stride,
731            padding,
732            dilation,
733            ceil_mode,
734            indices_dtype,
735        );
736        (output.output, output.indices)
737    }
738
739    fn max_pool1d_with_indices_backward_dispatch(
740        x: FloatTensor<Self>,
741        kernel_size: usize,
742        stride: usize,
743        padding: usize,
744        dilation: usize,
745        ceil_mode: bool,
746        output_grad: FloatTensor<Self>,
747        indices: IntTensor<Self>,
748    ) -> FloatTensor<Self> {
749        B::max_pool1d_with_indices_backward(
750            x,
751            kernel_size,
752            stride,
753            padding,
754            dilation,
755            ceil_mode,
756            output_grad,
757            indices,
758        )
759        .x_grad
760    }
761}