1use alloc::vec::Vec;
2use burn_backend::{
3 BoolDType, ExecutionError, FloatDType, IntDType, Scalar, Shape, Slice, TensorData,
4 ops::{FloatTensorOps, PadMode},
5 tensor::{BoolTensor, FloatTensor, IndexingUpdateOp, IntTensor},
6};
7use burn_backend_extension::backend_dispatch;
8
9use crate::{Dispatch, DispatchDevice};
10
11#[backend_dispatch]
12impl FloatTensorOps<Self> for Dispatch {
13 fn float_pad(
14 tensor: FloatTensor<Self>,
15 padding: &[(usize, usize)],
16 mode: PadMode,
17 ) -> FloatTensor<Self> {
18 B::float_pad(tensor, padding, mode)
19 }
20
21 fn float_from_data(
22 data: burn_backend::TensorData,
23 device: &DispatchDevice,
24 ) -> FloatTensor<Self> {
25 B::float_from_data(data, device)
26 }
27
28 fn float_random(
29 shape: Shape,
30 distribution: burn_backend::Distribution,
31 device: &DispatchDevice,
32 dtype: FloatDType,
33 ) -> FloatTensor<Self> {
34 B::float_random(shape, distribution, device, dtype)
35 }
36
37 async fn float_into_data(tensor: FloatTensor<Self>) -> Result<TensorData, ExecutionError> {
38 B::float_into_data(tensor).await
39 }
40
41 #[backend_dispatch(skip)]
42 fn float_to_device(tensor: FloatTensor<Self>, device: &DispatchDevice) -> FloatTensor<Self> {
43 float_to_device!(
47 Float,
48 float,
49 tensor,
50 device,
51 float_to_device,
52 |inner, device| { super::transfer::float_transfer::<B1, B2>(inner, device) }
53 )
54 }
55
56 fn float_into_int(tensor: FloatTensor<Self>, dtype: burn_backend::IntDType) -> IntTensor<Self> {
57 B::float_into_int(tensor, dtype)
58 }
59
60 fn float_empty(shape: Shape, device: &DispatchDevice, dtype: FloatDType) -> FloatTensor<Self> {
61 B::float_empty(shape, device, dtype)
62 }
63
64 fn float_add(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
65 B::float_add(lhs, rhs)
66 }
67
68 fn float_add_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
69 B::float_add_scalar(lhs, rhs)
70 }
71
72 fn float_sub(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
73 B::float_sub(lhs, rhs)
74 }
75
76 fn float_sub_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
77 B::float_sub_scalar(lhs, rhs)
78 }
79
80 fn float_mul(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
81 B::float_mul(lhs, rhs)
82 }
83
84 fn float_mul_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
85 B::float_mul_scalar(lhs, rhs)
86 }
87
88 fn float_div(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
89 B::float_div(lhs, rhs)
90 }
91
92 fn float_div_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
93 B::float_div_scalar(lhs, rhs)
94 }
95
96 fn float_remainder(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
97 B::float_remainder(lhs, rhs)
98 }
99
100 fn float_remainder_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
101 B::float_remainder_scalar(lhs, rhs)
102 }
103
104 fn float_matmul(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
105 B::float_matmul(lhs, rhs)
106 }
107
108 fn float_cross(
109 lhs: FloatTensor<Self>,
110 rhs: FloatTensor<Self>,
111 dim: usize,
112 ) -> FloatTensor<Self> {
113 B::float_cross(lhs, rhs, dim)
114 }
115
116 fn float_recip(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
117 B::float_recip(tensor)
118 }
119
120 fn float_swap_dims(tensor: FloatTensor<Self>, dim1: usize, dim2: usize) -> FloatTensor<Self> {
121 B::float_swap_dims(tensor, dim1, dim2)
122 }
123
124 fn float_permute(tensor: FloatTensor<Self>, axes: &[usize]) -> FloatTensor<Self> {
125 B::float_permute(tensor, axes)
126 }
127
128 fn float_flip(tensor: FloatTensor<Self>, axes: &[usize]) -> FloatTensor<Self> {
129 B::float_flip(tensor, axes)
130 }
131
132 fn float_reshape(tensor: FloatTensor<Self>, shape: Shape) -> FloatTensor<Self> {
133 B::float_reshape(tensor, shape)
134 }
135
136 fn float_gather(
137 dim: usize,
138 tensor: FloatTensor<Self>,
139 indices: IntTensor<Self>,
140 ) -> FloatTensor<Self> {
141 B::float_gather(dim, tensor, indices)
142 }
143
144 fn float_scatter(
145 dim: usize,
146 tensor: FloatTensor<Self>,
147 indices: IntTensor<Self>,
148 value: FloatTensor<Self>,
149 update: IndexingUpdateOp,
150 ) -> FloatTensor<Self> {
151 B::float_scatter(dim, tensor, indices, value, update)
152 }
153
154 fn float_scatter_nd(
155 data: FloatTensor<Self>,
156 indices: IntTensor<Self>,
157 values: FloatTensor<Self>,
158 reduction: burn_backend::tensor::IndexingUpdateOp,
159 ) -> FloatTensor<Self> {
160 B::float_scatter_nd(data, indices, values, reduction)
161 }
162
163 fn float_gather_nd(data: FloatTensor<Self>, indices: IntTensor<Self>) -> FloatTensor<Self> {
164 B::float_gather_nd(data, indices)
165 }
166
167 fn float_select(
168 tensor: FloatTensor<Self>,
169 dim: usize,
170 indices: IntTensor<Self>,
171 ) -> FloatTensor<Self> {
172 B::float_select(tensor, dim, indices)
173 }
174
175 fn float_select_assign(
176 tensor: FloatTensor<Self>,
177 dim: usize,
178 indices: IntTensor<Self>,
179 value: FloatTensor<Self>,
180 update: IndexingUpdateOp,
181 ) -> FloatTensor<Self> {
182 B::float_select_assign(tensor, dim, indices, value, update)
183 }
184
185 fn float_slice(tensor: FloatTensor<Self>, slices: &[Slice]) -> FloatTensor<Self> {
186 B::float_slice(tensor, slices)
187 }
188
189 fn float_slice_assign(
190 tensor: FloatTensor<Self>,
191 slices: &[Slice],
192 value: FloatTensor<Self>,
193 ) -> FloatTensor<Self> {
194 B::float_slice_assign(tensor, slices, value)
195 }
196
197 fn float_mask_where(
198 tensor: FloatTensor<Self>,
199 mask: BoolTensor<Self>,
200 value: FloatTensor<Self>,
201 ) -> FloatTensor<Self> {
202 B::float_mask_where(tensor, mask, value)
203 }
204
205 fn float_mask_fill(
206 tensor: FloatTensor<Self>,
207 mask: BoolTensor<Self>,
208 value: Scalar,
209 ) -> FloatTensor<Self> {
210 B::float_mask_fill(tensor, mask, value)
211 }
212
213 async fn float_mask_select(
214 tensor: FloatTensor<Self>,
215 mask: BoolTensor<Self>,
216 ) -> FloatTensor<Self> {
217 B::float_mask_select(tensor, mask).await
218 }
219
220 fn float_equal(
221 lhs: FloatTensor<Self>,
222 rhs: FloatTensor<Self>,
223 out_dtype: BoolDType,
224 ) -> BoolTensor<Self> {
225 B::float_equal(lhs, rhs, out_dtype)
226 }
227
228 fn float_equal_elem(
229 lhs: FloatTensor<Self>,
230 rhs: Scalar,
231 out_dtype: BoolDType,
232 ) -> BoolTensor<Self> {
233 B::float_equal_elem(lhs, rhs, out_dtype)
234 }
235
236 fn float_greater(
237 lhs: FloatTensor<Self>,
238 rhs: FloatTensor<Self>,
239 out_dtype: BoolDType,
240 ) -> BoolTensor<Self> {
241 B::float_greater(lhs, rhs, out_dtype)
242 }
243
244 fn float_greater_elem(
245 lhs: FloatTensor<Self>,
246 rhs: Scalar,
247 out_dtype: BoolDType,
248 ) -> BoolTensor<Self> {
249 B::float_greater_elem(lhs, rhs, out_dtype)
250 }
251
252 fn float_greater_equal(
253 lhs: FloatTensor<Self>,
254 rhs: FloatTensor<Self>,
255 out_dtype: BoolDType,
256 ) -> BoolTensor<Self> {
257 B::float_greater_equal(lhs, rhs, out_dtype)
258 }
259
260 fn float_greater_equal_elem(
261 lhs: FloatTensor<Self>,
262 rhs: Scalar,
263 out_dtype: BoolDType,
264 ) -> BoolTensor<Self> {
265 B::float_greater_equal_elem(lhs, rhs, out_dtype)
266 }
267
268 fn float_lower(
269 lhs: FloatTensor<Self>,
270 rhs: FloatTensor<Self>,
271 out_dtype: BoolDType,
272 ) -> BoolTensor<Self> {
273 B::float_lower(lhs, rhs, out_dtype)
274 }
275
276 fn float_lower_elem(
277 lhs: FloatTensor<Self>,
278 rhs: Scalar,
279 out_dtype: BoolDType,
280 ) -> BoolTensor<Self> {
281 B::float_lower_elem(lhs, rhs, out_dtype)
282 }
283
284 fn float_lower_equal(
285 lhs: FloatTensor<Self>,
286 rhs: FloatTensor<Self>,
287 out_dtype: BoolDType,
288 ) -> BoolTensor<Self> {
289 B::float_lower_equal(lhs, rhs, out_dtype)
290 }
291
292 fn float_lower_equal_elem(
293 lhs: FloatTensor<Self>,
294 rhs: Scalar,
295 out_dtype: BoolDType,
296 ) -> BoolTensor<Self> {
297 B::float_lower_equal_elem(lhs, rhs, out_dtype)
298 }
299
300 fn float_sum(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
301 B::float_sum(tensor)
302 }
303
304 fn float_sum_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
305 B::float_sum_dim(tensor, dim)
306 }
307
308 fn float_sum_dims(tensor: FloatTensor<Self>, dims: &[usize]) -> FloatTensor<Self> {
309 B::float_sum_dims(tensor, dims)
310 }
311
312 fn float_mean_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
313 B::float_mean_dim(tensor, dim)
314 }
315
316 fn float_cumsum(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
317 B::float_cumsum(tensor, dim)
318 }
319
320 fn float_cumprod(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
321 B::float_cumprod(tensor, dim)
322 }
323
324 fn float_cummin(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
325 B::float_cummin(tensor, dim)
326 }
327
328 fn float_cummax(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
329 B::float_cummax(tensor, dim)
330 }
331
332 fn float_cast(tensor: FloatTensor<Self>, dtype: FloatDType) -> FloatTensor<Self> {
333 B::float_cast(tensor, dtype)
334 }
335
336 fn float_exp(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
337 B::float_exp(tensor)
338 }
339
340 fn float_log(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
341 B::float_log(tensor)
342 }
343
344 fn float_log1p(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
345 B::float_log1p(tensor)
346 }
347
348 fn float_powf(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
349 B::float_powf(lhs, rhs)
350 }
351
352 fn float_powf_scalar_impl(tensor: FloatTensor<Self>, value: Scalar) -> FloatTensor<Self> {
353 B::float_powf_scalar_impl(tensor, value)
354 }
355
356 fn float_sqrt(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
357 B::float_sqrt(tensor)
358 }
359
360 fn float_abs(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
361 B::float_abs(tensor)
362 }
363
364 fn float_cos(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
365 B::float_cos(tensor)
366 }
367
368 fn float_sin(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
369 B::float_sin(tensor)
370 }
371
372 fn float_tan(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
373 B::float_tan(tensor)
374 }
375
376 fn float_cosh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
377 B::float_cosh(tensor)
378 }
379
380 fn float_sinh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
381 B::float_sinh(tensor)
382 }
383
384 fn float_tanh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
385 B::float_tanh(tensor)
386 }
387
388 fn float_acos(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
389 B::float_acos(tensor)
390 }
391
392 fn float_acosh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
393 B::float_acosh(tensor)
394 }
395
396 fn float_asin(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
397 B::float_asin(tensor)
398 }
399
400 fn float_asinh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
401 B::float_asinh(tensor)
402 }
403
404 fn float_atan(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
405 B::float_atan(tensor)
406 }
407
408 fn float_atanh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
409 B::float_atanh(tensor)
410 }
411
412 fn float_atan2(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
413 B::float_atan2(lhs, rhs)
414 }
415
416 fn float_round(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
417 B::float_round(tensor)
418 }
419
420 fn float_floor(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
421 B::float_floor(tensor)
422 }
423
424 fn float_ceil(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
425 B::float_ceil(tensor)
426 }
427
428 fn float_trunc(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
429 B::float_trunc(tensor)
430 }
431
432 fn float_erf(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
433 B::float_erf(tensor)
434 }
435
436 fn float_argmax(tensor: FloatTensor<Self>, dim: usize, out_dtype: IntDType) -> IntTensor<Self> {
437 B::float_argmax(tensor, dim, out_dtype)
438 }
439
440 fn float_argtopk(
441 tensor: FloatTensor<Self>,
442 dim: usize,
443 k: usize,
444 out_dtype: IntDType,
445 ) -> IntTensor<Self> {
446 B::float_argtopk(tensor, dim, k, out_dtype)
447 }
448
449 fn float_topk(tensor: FloatTensor<Self>, dim: usize, k: usize) -> FloatTensor<Self> {
450 B::float_topk(tensor, dim, k)
451 }
452
453 fn float_topk_with_indices(
454 tensor: FloatTensor<Self>,
455 dim: usize,
456 k: usize,
457 out_dtype: IntDType,
458 ) -> (FloatTensor<Self>, IntTensor<Self>) {
459 B::float_topk_with_indices(tensor, dim, k, out_dtype)
460 }
461
462 fn float_argmin(tensor: FloatTensor<Self>, dim: usize, out_dtype: IntDType) -> IntTensor<Self> {
463 B::float_argmin(tensor, dim, out_dtype)
464 }
465
466 fn float_expand(tensor: FloatTensor<Self>, shape: Shape) -> FloatTensor<Self> {
467 B::float_expand(tensor, shape)
468 }
469
470 fn float_unfold(
471 tensor: FloatTensor<Self>,
472 dim: usize,
473 size: usize,
474 step: usize,
475 ) -> FloatTensor<Self> {
476 B::float_unfold(tensor, dim, size, step)
477 }
478
479 fn float_detach(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
480 B::float_detach(tensor)
481 }
482
483 fn float_set_require_grad(tensor: FloatTensor<Self>, require_grad: bool) -> FloatTensor<Self> {
484 B::float_set_require_grad(tensor, require_grad)
485 }
486
487 fn float_is_require_grad(tensor: &FloatTensor<Self>) -> bool {
488 B::float_is_require_grad(tensor)
489 }
490
491 fn float_zeros(shape: Shape, device: &DispatchDevice, dtype: FloatDType) -> FloatTensor<Self> {
493 B::float_zeros(shape, device, dtype)
494 }
495
496 fn float_ones(shape: Shape, device: &DispatchDevice, dtype: FloatDType) -> FloatTensor<Self> {
497 B::float_ones(shape, device, dtype)
498 }
499
500 fn float_full(
501 shape: Shape,
502 fill_value: Scalar,
503 device: &DispatchDevice,
504 dtype: FloatDType,
505 ) -> FloatTensor<Self> {
506 B::float_full(shape, fill_value, device, dtype)
507 }
508
509 fn float_repeat_dim(tensor: FloatTensor<Self>, dim: usize, times: usize) -> FloatTensor<Self> {
510 B::float_repeat_dim(tensor, dim, times)
511 }
512
513 fn float_clamp_min(tensor: FloatTensor<Self>, min: Scalar) -> FloatTensor<Self> {
514 B::float_clamp_min(tensor, min)
515 }
516
517 fn float_clamp_max(tensor: FloatTensor<Self>, max: Scalar) -> FloatTensor<Self> {
518 B::float_clamp_max(tensor, max)
519 }
520
521 fn float_clamp(tensor: FloatTensor<Self>, min: Scalar, max: Scalar) -> FloatTensor<Self> {
522 B::float_clamp(tensor, min, max)
523 }
524
525 fn float_neg(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
526 B::float_neg(tensor)
527 }
528
529 fn float_transpose(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
530 B::float_transpose(tensor)
531 }
532
533 fn float_not_equal(
534 lhs: FloatTensor<Self>,
535 rhs: FloatTensor<Self>,
536 out_dtype: BoolDType,
537 ) -> BoolTensor<Self> {
538 B::float_not_equal(lhs, rhs, out_dtype)
539 }
540
541 fn float_not_equal_elem(
542 lhs: FloatTensor<Self>,
543 rhs: Scalar,
544 out_dtype: BoolDType,
545 ) -> BoolTensor<Self> {
546 B::float_not_equal_elem(lhs, rhs, out_dtype)
547 }
548
549 fn float_prod(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
550 B::float_prod(tensor)
551 }
552
553 fn float_prod_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
554 B::float_prod_dim(tensor, dim)
555 }
556
557 fn float_mean(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
558 B::float_mean(tensor)
559 }
560
561 fn float_powi(lhs: FloatTensor<Self>, rhs: IntTensor<Self>) -> FloatTensor<Self> {
562 B::float_powi(lhs, rhs)
563 }
564
565 fn float_powi_scalar_impl(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
566 B::float_powi_scalar_impl(lhs, rhs)
567 }
568
569 fn float_powf_scalar(tensor: FloatTensor<Self>, value: Scalar) -> FloatTensor<Self> {
570 B::float_powf_scalar(tensor, value)
571 }
572
573 fn float_cat(tensors: Vec<FloatTensor<Self>>, dim: usize) -> FloatTensor<Self> {
574 B::float_cat(tensors, dim)
575 }
576
577 fn float_max(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
578 B::float_max(tensor)
579 }
580
581 fn float_max_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
582 B::float_max_dim(tensor, dim)
583 }
584
585 fn float_max_dim_with_indices(
586 tensor: FloatTensor<Self>,
587 dim: usize,
588 indices_dtype: IntDType,
589 ) -> (FloatTensor<Self>, IntTensor<Self>) {
590 B::float_max_dim_with_indices(tensor, dim, indices_dtype)
591 }
592
593 fn float_min(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
594 B::float_min(tensor)
595 }
596
597 fn float_min_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
598 B::float_min_dim(tensor, dim)
599 }
600
601 fn float_min_dim_with_indices(
602 tensor: FloatTensor<Self>,
603 dim: usize,
604 indices_dtype: IntDType,
605 ) -> (FloatTensor<Self>, IntTensor<Self>) {
606 B::float_min_dim_with_indices(tensor, dim, indices_dtype)
607 }
608
609 fn float_max_abs(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
610 B::float_max_abs(tensor)
611 }
612
613 fn float_max_abs_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
614 B::float_max_abs_dim(tensor, dim)
615 }
616
617 fn float_any(tensor: FloatTensor<Self>, out_dtype: BoolDType) -> BoolTensor<Self> {
618 B::float_any(tensor, out_dtype)
619 }
620
621 fn float_any_dim(
622 tensor: FloatTensor<Self>,
623 dim: usize,
624 out_dtype: BoolDType,
625 ) -> BoolTensor<Self> {
626 B::float_any_dim(tensor, dim, out_dtype)
627 }
628
629 fn float_all(tensor: FloatTensor<Self>, out_dtype: BoolDType) -> BoolTensor<Self> {
630 B::float_all(tensor, out_dtype)
631 }
632
633 fn float_all_dim(
634 tensor: FloatTensor<Self>,
635 dim: usize,
636 out_dtype: BoolDType,
637 ) -> BoolTensor<Self> {
638 B::float_all_dim(tensor, dim, out_dtype)
639 }
640
641 fn float_sign(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
642 B::float_sign(tensor)
643 }
644
645 fn float_sort(tensor: FloatTensor<Self>, dim: usize, descending: bool) -> FloatTensor<Self> {
646 B::float_sort(tensor, dim, descending)
647 }
648
649 fn float_sort_with_indices(
650 tensor: FloatTensor<Self>,
651 dim: usize,
652 descending: bool,
653 indices_dtype: IntDType,
654 ) -> (FloatTensor<Self>, IntTensor<Self>) {
655 B::float_sort_with_indices(tensor, dim, descending, indices_dtype)
656 }
657
658 fn float_argsort(
659 tensor: FloatTensor<Self>,
660 dim: usize,
661 descending: bool,
662 out_dtype: IntDType,
663 ) -> IntTensor<Self> {
664 B::float_argsort(tensor, dim, descending, out_dtype)
665 }
666
667 fn float_grid_sample_2d(
668 tensor: FloatTensor<Self>,
669 grid: FloatTensor<Self>,
670 options: burn_backend::ops::GridSampleOptions,
671 ) -> FloatTensor<Self> {
672 B::float_grid_sample_2d(tensor, grid, options)
673 }
674
675 fn float_is_nan(tensor: FloatTensor<Self>, out_dtype: BoolDType) -> BoolTensor<Self> {
676 B::float_is_nan(tensor, out_dtype)
677 }
678
679 fn float_is_inf(tensor: FloatTensor<Self>, out_dtype: BoolDType) -> BoolTensor<Self> {
680 B::float_is_inf(tensor, out_dtype)
681 }
682
683 fn float_hypot(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
684 B::float_hypot(lhs, rhs)
685 }
686}
687
688#[cfg(all(test, feature = "capture", feature = "flex"))]
689mod tests {
690 use super::*;
691 use burn_backend::ops::{BoolTensorOps, IntTensorOps};
692 use burn_capture::CaptureDevice;
693
694 #[test]
695 fn capture_tensor_movement_is_one_way() {
696 let source_device = DispatchDevice::Flex(Default::default());
697 let concrete_capture_device = CaptureDevice::default();
698 let capture_device = DispatchDevice::Capture(concrete_capture_device);
699 let float = Dispatch::float_from_data(TensorData::from([1.0f32, 2.0]), &source_device);
700 let int = Dispatch::int_from_data(TensorData::from([1i64, 2]), &source_device);
701
702 let graph = concrete_capture_device
703 .capture_scope(|scope| {
704 let captured_float = Dispatch::float_to_device(float, &capture_device);
705 let captured_float = Dispatch::float_to_device(captured_float, &capture_device);
706 let captured_int = Dispatch::int_to_device(int, &capture_device);
707 let captured_int = Dispatch::int_to_device(captured_int, &capture_device);
708 let float_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
709 Dispatch::float_to_device(captured_float, &source_device)
710 }));
711 let int_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
712 Dispatch::int_to_device(captured_int, &source_device)
713 }));
714
715 assert!(float_result.is_err());
716 assert!(int_result.is_err());
717 scope.complete([], [])
718 })
719 .unwrap();
720 assert_eq!(graph.values.len(), 2);
721 }
722
723 #[test]
724 fn initialized_tensors_can_move_between_capture_devices() {
725 let source_device = DispatchDevice::Flex(Default::default());
726 let first = CaptureDevice::default();
727 let second = CaptureDevice::default();
728 let first_dispatch = DispatchDevice::Capture(first);
729 let second_dispatch = DispatchDevice::Capture(second);
730 let float = Dispatch::float_from_data(TensorData::from([1.0f32]), &source_device);
731 let int = Dispatch::int_from_data(TensorData::from([1i64]), &source_device);
732 let bool = Dispatch::bool_from_data(TensorData::from([true]), &source_device);
733
734 let first_graph = first
735 .capture_scope(|first_scope| {
736 let float = Dispatch::float_to_device(float, &first_dispatch);
737 let int = Dispatch::int_to_device(int, &first_dispatch);
738 let bool = Dispatch::bool_to_device(bool, &first_dispatch);
739
740 let second_graph = second
741 .capture_scope(|second_scope| {
742 Dispatch::float_to_device(float, &second_dispatch);
743 Dispatch::int_to_device(int, &second_dispatch);
744 Dispatch::bool_to_device(bool, &second_dispatch);
745 second_scope.complete([], [])
746 })
747 .unwrap();
748 assert_eq!(second_graph.values.len(), 3);
749
750 first_scope.complete([], [])
751 })
752 .unwrap();
753
754 assert_eq!(first_graph.values.len(), 3);
755 }
756
757 #[test]
758 fn computed_tensors_cannot_move_between_capture_devices() {
759 let source_device = DispatchDevice::Flex(Default::default());
760 let first = CaptureDevice::default();
761 let second = CaptureDevice::default();
762 let first_dispatch = DispatchDevice::Capture(first);
763 let second_dispatch = DispatchDevice::Capture(second);
764 let float = Dispatch::float_from_data(TensorData::from([1.0f32]), &source_device);
765 let int = Dispatch::int_from_data(TensorData::from([1i64]), &source_device);
766 let bool = Dispatch::bool_from_data(TensorData::from([true]), &source_device);
767
768 let first_graph = first
769 .capture_scope(|first_scope| {
770 let float = Dispatch::float_neg(Dispatch::float_to_device(float, &first_dispatch));
771 let int = Dispatch::int_neg(Dispatch::int_to_device(int, &first_dispatch));
772 let bool = Dispatch::bool_not(Dispatch::bool_to_device(bool, &first_dispatch));
773
774 let second_graph = second
775 .capture_scope(|second_scope| {
776 let float_result =
777 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
778 Dispatch::float_to_device(float, &second_dispatch)
779 }));
780 let int_result =
781 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
782 Dispatch::int_to_device(int, &second_dispatch)
783 }));
784 let bool_result =
785 std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
786 Dispatch::bool_to_device(bool, &second_dispatch)
787 }));
788
789 assert!(float_result.is_err());
790 assert!(int_result.is_err());
791 assert!(bool_result.is_err());
792 second_scope.complete([], [])
793 })
794 .unwrap();
795 assert!(second_graph.values.is_empty());
796
797 first_scope.complete([], [])
798 })
799 .unwrap();
800
801 assert_eq!(first_graph.values.len(), 3);
802 }
803}