Skip to main content

burn_dispatch/ops/
module.rs

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