Skip to main content

burn_dispatch/ops/
tensor.rs

1use alloc::vec::Vec;
2use burn_backend::{
3    BoolDType, ExecutionError, FloatDType, IntDType, Scalar, Shape, Slice, TensorData,
4    ops::FloatTensorOps,
5    tensor::{BoolTensor, FloatTensor, IntTensor},
6};
7
8use crate::{Dispatch, DispatchDevice};
9
10impl FloatTensorOps<Self> for Dispatch {
11    fn float_from_data(
12        data: burn_backend::TensorData,
13        device: &DispatchDevice,
14    ) -> FloatTensor<Self> {
15        creation_op!(Float, device, |device| B::float_from_data(data, device))
16    }
17
18    fn float_random(
19        shape: Shape,
20        distribution: burn_backend::Distribution,
21        device: &DispatchDevice,
22        dtype: FloatDType,
23    ) -> FloatTensor<Self> {
24        creation_op!(Float, device, |device| {
25            B::float_random(shape, distribution, device, dtype)
26        })
27    }
28
29    async fn float_into_data(tensor: FloatTensor<Self>) -> Result<TensorData, ExecutionError> {
30        unary_float!(tensor, float, |tensor| B::float_into_data(tensor).await)
31    }
32
33    fn float_to_device(tensor: FloatTensor<Self>, device: &DispatchDevice) -> FloatTensor<Self> {
34        // Relocating a non-tracked float tensor onto an autodiff device is a plain data move:
35        // place it on the underlying hardware device and leave the tensor non-tracked. The
36        // int/bool `to_device` paths already handle this case; only the float path used to
37        // panic. This is what lets gradient tensors — which are never autodiff-tracked — be
38        // moved onto the autodiff `device_main` during multi-device training.
39        #[cfg(feature = "autodiff")]
40        if let DispatchDevice::Autodiff(device_ad) = device
41            && !matches!(&tensor.kind, crate::DispatchTensorKind::Autodiff(_))
42        {
43            return Self::float_to_device(tensor, &device_ad.inner);
44        }
45
46        float_to_device!(
47            Float,
48            float,
49            tensor,
50            device,
51            float_to_device,
52            |inner, device| {
53                let data =
54                    burn_backend::read_sync(B1::float_into_data(inner)).expect("Should read data");
55                B2::float_from_data(data, device)
56            }
57        )
58    }
59
60    fn float_into_int(tensor: FloatTensor<Self>, dtype: burn_backend::IntDType) -> IntTensor<Self> {
61        unary_float!(tensor, float, |tensor| B::float_into_int(tensor, dtype) => Int)
62    }
63
64    fn float_empty(shape: Shape, device: &DispatchDevice, dtype: FloatDType) -> FloatTensor<Self> {
65        creation_op!(Float, device, |device| B::float_empty(shape, device, dtype))
66    }
67
68    fn float_add(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
69        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_add(lhs, rhs) => Float)
70    }
71
72    fn float_add_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
73        unary_float!(lhs, float, |lhs| B::float_add_scalar(lhs, rhs) => Float)
74    }
75
76    fn float_sub(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
77        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_sub(lhs, rhs) => Float)
78    }
79
80    fn float_sub_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
81        unary_float!(lhs, float, |lhs| B::float_sub_scalar(lhs, rhs) => Float)
82    }
83
84    fn float_mul(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
85        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_mul(lhs, rhs) => Float)
86    }
87
88    fn float_mul_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
89        unary_float!(lhs, float, |lhs| B::float_mul_scalar(lhs, rhs) => Float)
90    }
91
92    fn float_div(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
93        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_div(lhs, rhs) => Float)
94    }
95
96    fn float_div_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
97        unary_float!(lhs, float, |lhs| B::float_div_scalar(lhs, rhs) => Float)
98    }
99
100    fn float_remainder(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
101        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_remainder(lhs, rhs) => Float)
102    }
103
104    fn float_remainder_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
105        unary_float!(lhs, float, |lhs| B::float_remainder_scalar(lhs, rhs) => Float)
106    }
107
108    fn float_matmul(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
109        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_matmul(lhs, rhs) => Float)
110    }
111
112    fn float_cross(
113        lhs: FloatTensor<Self>,
114        rhs: FloatTensor<Self>,
115        dim: usize,
116    ) -> FloatTensor<Self> {
117        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_cross(lhs, rhs, dim) => Float)
118    }
119
120    fn float_recip(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
121        unary_float!(tensor, float, |tensor| B::float_recip(tensor) => Float)
122    }
123
124    fn float_swap_dims(tensor: FloatTensor<Self>, dim1: usize, dim2: usize) -> FloatTensor<Self> {
125        unary_float!(tensor, float, |tensor| B::float_swap_dims(tensor, dim1, dim2) => Float)
126    }
127
128    fn float_permute(tensor: FloatTensor<Self>, axes: &[usize]) -> FloatTensor<Self> {
129        unary_float!(tensor, float, |tensor| B::float_permute(tensor, axes) => Float)
130    }
131
132    fn float_flip(tensor: FloatTensor<Self>, axes: &[usize]) -> FloatTensor<Self> {
133        unary_float!(tensor, float, |tensor| B::float_flip(tensor, axes) => Float)
134    }
135
136    fn float_reshape(tensor: FloatTensor<Self>, shape: Shape) -> FloatTensor<Self> {
137        unary_float!(tensor, float, |tensor| B::float_reshape(tensor, shape) => Float)
138    }
139
140    fn float_gather(
141        dim: usize,
142        tensor: FloatTensor<Self>,
143        indices: IntTensor<Self>,
144    ) -> FloatTensor<Self> {
145        binary_float!((tensor, float), (indices, int), |tensor, indices| B::float_gather(dim, tensor, indices) => Float)
146    }
147
148    fn float_scatter_add(
149        dim: usize,
150        tensor: FloatTensor<Self>,
151        indices: IntTensor<Self>,
152        value: FloatTensor<Self>,
153    ) -> FloatTensor<Self> {
154        multi_op!(
155            inputs[(tensor, float), (indices, int), (value, float)], => Float,
156            B::float_scatter_add(dim, tensor, indices, value)
157        )
158    }
159
160    fn float_scatter_nd(
161        data: FloatTensor<Self>,
162        indices: IntTensor<Self>,
163        values: FloatTensor<Self>,
164        reduction: burn_backend::tensor::IndexingUpdateOp,
165    ) -> FloatTensor<Self> {
166        multi_op!(
167            inputs[(data, float), (indices, int), (values, float)], => Float,
168            B::float_scatter_nd(data, indices, values, reduction)
169        )
170    }
171
172    fn float_gather_nd(data: FloatTensor<Self>, indices: IntTensor<Self>) -> FloatTensor<Self> {
173        binary_float!((data, float), (indices, int), |data, indices| B::float_gather_nd(data, indices) => Float)
174    }
175
176    fn float_select(
177        tensor: FloatTensor<Self>,
178        dim: usize,
179        indices: IntTensor<Self>,
180    ) -> FloatTensor<Self> {
181        binary_float!((tensor, float), (indices, int), |tensor, indices| B::float_select(tensor, dim, indices) => Float)
182    }
183
184    fn float_select_add(
185        tensor: FloatTensor<Self>,
186        dim: usize,
187        indices: IntTensor<Self>,
188        value: FloatTensor<Self>,
189    ) -> FloatTensor<Self> {
190        multi_op!(
191            inputs[(tensor, float), (indices, int), (value, float)], => Float,
192            B::float_select_add(tensor, dim, indices, value)
193        )
194    }
195
196    fn float_slice(tensor: FloatTensor<Self>, slices: &[Slice]) -> FloatTensor<Self> {
197        unary_float!(tensor, float, |tensor| B::float_slice(tensor, slices) => Float)
198    }
199
200    fn float_slice_assign(
201        tensor: FloatTensor<Self>,
202        slices: &[Slice],
203        value: FloatTensor<Self>,
204    ) -> FloatTensor<Self> {
205        binary_float!((tensor, float), (value, float), |tensor, value| B::float_slice_assign(tensor, slices, value) => Float)
206    }
207
208    fn float_mask_where(
209        tensor: FloatTensor<Self>,
210        mask: BoolTensor<Self>,
211        value: FloatTensor<Self>,
212    ) -> FloatTensor<Self> {
213        multi_op!(
214            inputs[(tensor, float), (mask, bool), (value, float)], => Float,
215            B::float_mask_where(tensor, mask, value)
216        )
217    }
218
219    fn float_mask_fill(
220        tensor: FloatTensor<Self>,
221        mask: BoolTensor<Self>,
222        value: Scalar,
223    ) -> FloatTensor<Self> {
224        binary_float!((tensor, float), (mask, bool), |tensor, mask| B::float_mask_fill(tensor, mask, value) => Float)
225    }
226
227    fn float_equal(
228        lhs: FloatTensor<Self>,
229        rhs: FloatTensor<Self>,
230        out_dtype: BoolDType,
231    ) -> BoolTensor<Self> {
232        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_equal(lhs, rhs, out_dtype) => Bool)
233    }
234
235    fn float_equal_elem(
236        lhs: FloatTensor<Self>,
237        rhs: Scalar,
238        out_dtype: BoolDType,
239    ) -> BoolTensor<Self> {
240        unary_float!(lhs, float, |lhs| B::float_equal_elem(lhs, rhs, out_dtype) => Bool)
241    }
242
243    fn float_greater(
244        lhs: FloatTensor<Self>,
245        rhs: FloatTensor<Self>,
246        out_dtype: BoolDType,
247    ) -> BoolTensor<Self> {
248        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_greater(lhs, rhs, out_dtype) => Bool)
249    }
250
251    fn float_greater_elem(
252        lhs: FloatTensor<Self>,
253        rhs: Scalar,
254        out_dtype: BoolDType,
255    ) -> BoolTensor<Self> {
256        unary_float!(lhs, float, |lhs| B::float_greater_elem(lhs, rhs, out_dtype) => Bool)
257    }
258
259    fn float_greater_equal(
260        lhs: FloatTensor<Self>,
261        rhs: FloatTensor<Self>,
262        out_dtype: BoolDType,
263    ) -> BoolTensor<Self> {
264        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_greater_equal(lhs, rhs, out_dtype) => Bool)
265    }
266
267    fn float_greater_equal_elem(
268        lhs: FloatTensor<Self>,
269        rhs: Scalar,
270        out_dtype: BoolDType,
271    ) -> BoolTensor<Self> {
272        unary_float!(lhs, float, |lhs| B::float_greater_equal_elem(lhs, rhs, out_dtype) => Bool)
273    }
274
275    fn float_lower(
276        lhs: FloatTensor<Self>,
277        rhs: FloatTensor<Self>,
278        out_dtype: BoolDType,
279    ) -> BoolTensor<Self> {
280        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_lower(lhs, rhs, out_dtype) => Bool)
281    }
282
283    fn float_lower_elem(
284        lhs: FloatTensor<Self>,
285        rhs: Scalar,
286        out_dtype: BoolDType,
287    ) -> BoolTensor<Self> {
288        unary_float!(lhs, float, |lhs| B::float_lower_elem(lhs, rhs, out_dtype) => Bool)
289    }
290
291    fn float_lower_equal(
292        lhs: FloatTensor<Self>,
293        rhs: FloatTensor<Self>,
294        out_dtype: BoolDType,
295    ) -> BoolTensor<Self> {
296        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_lower_equal(lhs, rhs, out_dtype) => Bool)
297    }
298
299    fn float_lower_equal_elem(
300        lhs: FloatTensor<Self>,
301        rhs: Scalar,
302        out_dtype: BoolDType,
303    ) -> BoolTensor<Self> {
304        unary_float!(lhs, float, |lhs| B::float_lower_equal_elem(lhs, rhs, out_dtype) => Bool)
305    }
306
307    fn float_sum(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
308        unary_float!(tensor, float, |tensor| B::float_sum(tensor) => Float)
309    }
310
311    fn float_sum_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
312        unary_float!(tensor, float, |tensor| B::float_sum_dim(tensor, dim) => Float)
313    }
314
315    fn float_mean_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
316        unary_float!(tensor, float, |tensor| B::float_mean_dim(tensor, dim) => Float)
317    }
318
319    fn float_cumsum(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
320        unary_float!(tensor, float, |tensor| B::float_cumsum(tensor, dim) => Float)
321    }
322
323    fn float_cumprod(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
324        unary_float!(tensor, float, |tensor| B::float_cumprod(tensor, dim) => Float)
325    }
326
327    fn float_cummin(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
328        unary_float!(tensor, float, |tensor| B::float_cummin(tensor, dim) => Float)
329    }
330
331    fn float_cummax(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
332        unary_float!(tensor, float, |tensor| B::float_cummax(tensor, dim) => Float)
333    }
334
335    fn float_cast(tensor: FloatTensor<Self>, dtype: FloatDType) -> FloatTensor<Self> {
336        unary_float!(tensor, float, |tensor| B::float_cast(tensor, dtype) => Float)
337    }
338
339    fn float_exp(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
340        unary_float!(tensor, float, |tensor| B::float_exp(tensor) => Float)
341    }
342
343    fn float_log(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
344        unary_float!(tensor, float, |tensor| B::float_log(tensor) => Float)
345    }
346
347    fn float_log1p(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
348        unary_float!(tensor, float, |tensor| B::float_log1p(tensor) => Float)
349    }
350
351    fn float_powf(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
352        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_powf(lhs, rhs) => Float)
353    }
354
355    fn float_powf_scalar_impl(tensor: FloatTensor<Self>, value: Scalar) -> FloatTensor<Self> {
356        unary_float!(tensor, float, |tensor| B::float_powf_scalar_impl(tensor, value) => Float)
357    }
358
359    fn float_sqrt(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
360        unary_float!(tensor, float, |tensor| B::float_sqrt(tensor) => Float)
361    }
362
363    fn float_abs(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
364        unary_float!(tensor, float, |tensor| B::float_abs(tensor) => Float)
365    }
366
367    fn float_cos(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
368        unary_float!(tensor, float, |tensor| B::float_cos(tensor) => Float)
369    }
370
371    fn float_sin(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
372        unary_float!(tensor, float, |tensor| B::float_sin(tensor) => Float)
373    }
374
375    fn float_tan(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
376        unary_float!(tensor, float, |tensor| B::float_tan(tensor) => Float)
377    }
378
379    fn float_cosh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
380        unary_float!(tensor, float, |tensor| B::float_cosh(tensor) => Float)
381    }
382
383    fn float_sinh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
384        unary_float!(tensor, float, |tensor| B::float_sinh(tensor) => Float)
385    }
386
387    fn float_tanh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
388        unary_float!(tensor, float, |tensor| B::float_tanh(tensor) => Float)
389    }
390
391    fn float_acos(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
392        unary_float!(tensor, float, |tensor| B::float_acos(tensor) => Float)
393    }
394
395    fn float_acosh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
396        unary_float!(tensor, float, |tensor| B::float_acosh(tensor) => Float)
397    }
398
399    fn float_asin(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
400        unary_float!(tensor, float, |tensor| B::float_asin(tensor) => Float)
401    }
402
403    fn float_asinh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
404        unary_float!(tensor, float, |tensor| B::float_asinh(tensor) => Float)
405    }
406
407    fn float_atan(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
408        unary_float!(tensor, float, |tensor| B::float_atan(tensor) => Float)
409    }
410
411    fn float_atanh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
412        unary_float!(tensor, float, |tensor| B::float_atanh(tensor) => Float)
413    }
414
415    fn float_atan2(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
416        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_atan2(lhs, rhs) => Float)
417    }
418
419    fn float_round(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
420        unary_float!(tensor, float, |tensor| B::float_round(tensor) => Float)
421    }
422
423    fn float_floor(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
424        unary_float!(tensor, float, |tensor| B::float_floor(tensor) => Float)
425    }
426
427    fn float_ceil(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
428        unary_float!(tensor, float, |tensor| B::float_ceil(tensor) => Float)
429    }
430
431    fn float_trunc(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
432        unary_float!(tensor, float, |tensor| B::float_trunc(tensor) => Float)
433    }
434
435    fn float_erf(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
436        unary_float!(tensor, float, |tensor| B::float_erf(tensor) => Float)
437    }
438
439    fn float_argmax(tensor: FloatTensor<Self>, dim: usize, out_dtype: IntDType) -> IntTensor<Self> {
440        unary_float!(tensor, float, |tensor| B::float_argmax(tensor, dim, out_dtype) => Int)
441    }
442
443    fn float_argtopk(
444        tensor: FloatTensor<Self>,
445        dim: usize,
446        k: usize,
447        out_dtype: IntDType,
448    ) -> IntTensor<Self> {
449        unary_float!(tensor, float, |tensor| B::float_argtopk(tensor, dim, k, out_dtype) => Int)
450    }
451
452    fn float_topk(tensor: FloatTensor<Self>, dim: usize, k: usize) -> FloatTensor<Self> {
453        unary_float!(tensor, float, |tensor| B::float_topk(tensor, dim, k) => Float)
454    }
455
456    fn float_topk_with_indices(
457        tensor: FloatTensor<Self>,
458        dim: usize,
459        k: usize,
460        out_dtype: IntDType,
461    ) -> (FloatTensor<Self>, IntTensor<Self>) {
462        multi_op!(
463            inputs[(tensor, float)],
464            outputs[(out, Float), (indices, Int)],
465            B::float_topk_with_indices(tensor, dim, k, out_dtype)
466        )
467    }
468
469    fn float_argmin(tensor: FloatTensor<Self>, dim: usize, out_dtype: IntDType) -> IntTensor<Self> {
470        unary_float!(tensor, float, |tensor| B::float_argmin(tensor, dim, out_dtype) => Int)
471    }
472
473    fn float_expand(tensor: FloatTensor<Self>, shape: Shape) -> FloatTensor<Self> {
474        unary_float!(tensor, float, |tensor| B::float_expand(tensor, shape) => Float)
475    }
476
477    fn float_unfold(
478        tensor: FloatTensor<Self>,
479        dim: usize,
480        size: usize,
481        step: usize,
482    ) -> FloatTensor<Self> {
483        unary_float!(tensor, float, |tensor| {
484            B::float_unfold(tensor, dim, size, step)
485        } => Float)
486    }
487
488    fn float_detach(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
489        unary_float!(tensor, float, |tensor| B::float_detach(tensor) => Float)
490    }
491
492    fn float_set_require_grad(tensor: FloatTensor<Self>, require_grad: bool) -> FloatTensor<Self> {
493        unary_float!(tensor, float, |tensor| B::float_set_require_grad(tensor, require_grad) => Float)
494    }
495
496    fn float_is_require_grad(tensor: &FloatTensor<Self>) -> bool {
497        unary_float!(ref tensor, float, |tensor| B::float_is_require_grad(tensor))
498    }
499
500    // Default implementation
501    fn float_zeros(shape: Shape, device: &DispatchDevice, dtype: FloatDType) -> FloatTensor<Self> {
502        creation_op!(Float, device, |device| B::float_zeros(shape, device, dtype))
503    }
504
505    fn float_ones(shape: Shape, device: &DispatchDevice, dtype: FloatDType) -> FloatTensor<Self> {
506        creation_op!(Float, device, |device| B::float_ones(shape, device, dtype))
507    }
508
509    fn float_full(
510        shape: Shape,
511        fill_value: Scalar,
512        device: &DispatchDevice,
513        dtype: FloatDType,
514    ) -> FloatTensor<Self> {
515        creation_op!(Float, device, |device| B::float_full(
516            shape, fill_value, device, dtype
517        ))
518    }
519
520    fn float_repeat_dim(tensor: FloatTensor<Self>, dim: usize, times: usize) -> FloatTensor<Self> {
521        unary_float!(tensor, float, |tensor| B::float_repeat_dim(tensor, dim, times) => Float)
522    }
523
524    fn float_clamp_min(tensor: FloatTensor<Self>, min: Scalar) -> FloatTensor<Self> {
525        unary_float!(tensor, float, |tensor| B::float_clamp_min(tensor, min) => Float)
526    }
527
528    fn float_clamp_max(tensor: FloatTensor<Self>, max: Scalar) -> FloatTensor<Self> {
529        unary_float!(tensor, float, |tensor| B::float_clamp_max(tensor, max) => Float)
530    }
531
532    fn float_clamp(tensor: FloatTensor<Self>, min: Scalar, max: Scalar) -> FloatTensor<Self> {
533        unary_float!(tensor, float, |tensor| B::float_clamp(tensor, min, max) => Float)
534    }
535
536    fn float_neg(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
537        unary_float!(tensor, float, |tensor| B::float_neg(tensor) => Float)
538    }
539
540    fn float_transpose(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
541        unary_float!(tensor, float, |tensor| B::float_transpose(tensor) => Float)
542    }
543
544    fn float_not_equal(
545        lhs: FloatTensor<Self>,
546        rhs: FloatTensor<Self>,
547        out_dtype: BoolDType,
548    ) -> BoolTensor<Self> {
549        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_not_equal(lhs, rhs, out_dtype) => Bool)
550    }
551
552    fn float_not_equal_elem(
553        lhs: FloatTensor<Self>,
554        rhs: Scalar,
555        out_dtype: BoolDType,
556    ) -> BoolTensor<Self> {
557        unary_float!(lhs, float, |lhs| B::float_not_equal_elem(lhs, rhs, out_dtype) => Bool)
558    }
559
560    fn float_prod(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
561        unary_float!(tensor, float, |tensor| B::float_prod(tensor) => Float)
562    }
563
564    fn float_prod_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
565        unary_float!(tensor, float, |tensor| B::float_prod_dim(tensor, dim) => Float)
566    }
567
568    fn float_mean(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
569        unary_float!(tensor, float, |tensor| B::float_mean(tensor) => Float)
570    }
571
572    fn float_powi(lhs: FloatTensor<Self>, rhs: IntTensor<Self>) -> FloatTensor<Self> {
573        binary_float!((lhs, float), (rhs, int), |lhs, rhs| B::float_powi(lhs, rhs) => Float)
574    }
575
576    fn float_powi_scalar_impl(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
577        unary_float!(lhs, float, |lhs| B::float_powi_scalar_impl(lhs, rhs) => Float)
578    }
579
580    fn float_powf_scalar(tensor: FloatTensor<Self>, value: Scalar) -> FloatTensor<Self> {
581        unary_float!(tensor, float, |tensor| B::float_powf_scalar(tensor, value) => Float)
582    }
583
584    fn float_cat(tensors: Vec<FloatTensor<Self>>, dim: usize) -> FloatTensor<Self> {
585        vec_op!(tensors, float, |tensors| B::float_cat(tensors, dim) => Float)
586    }
587
588    fn float_max(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
589        unary_float!(tensor, float, |tensor| B::float_max(tensor) => Float)
590    }
591
592    fn float_max_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
593        unary_float!(tensor, float, |tensor| B::float_max_dim(tensor, dim) => Float)
594    }
595
596    fn float_max_dim_with_indices(
597        tensor: FloatTensor<Self>,
598        dim: usize,
599        indices_dtype: IntDType,
600    ) -> (FloatTensor<Self>, IntTensor<Self>) {
601        multi_op!(
602            inputs[(tensor, float)],
603            outputs[(out, Float), (indices, Int)],
604            B::float_max_dim_with_indices(tensor, dim, indices_dtype)
605        )
606    }
607
608    fn float_min(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
609        unary_float!(tensor, float, |tensor| B::float_min(tensor) => Float)
610    }
611
612    fn float_min_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
613        unary_float!(tensor, float, |tensor| B::float_min_dim(tensor, dim) => Float)
614    }
615
616    fn float_min_dim_with_indices(
617        tensor: FloatTensor<Self>,
618        dim: usize,
619        indices_dtype: IntDType,
620    ) -> (FloatTensor<Self>, IntTensor<Self>) {
621        multi_op!(
622            inputs[(tensor, float)],
623            outputs[(out, Float), (indices, Int)],
624            B::float_min_dim_with_indices(tensor, dim, indices_dtype)
625        )
626    }
627
628    fn float_max_abs(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
629        unary_float!(tensor, float, |tensor| B::float_max_abs(tensor) => Float)
630    }
631
632    fn float_max_abs_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
633        unary_float!(tensor, float, |tensor| B::float_max_abs_dim(tensor, dim) => Float)
634    }
635
636    fn float_any(tensor: FloatTensor<Self>, out_dtype: BoolDType) -> BoolTensor<Self> {
637        unary_float!(tensor, float, |tensor| B::float_any(tensor, out_dtype) => Bool)
638    }
639
640    fn float_any_dim(
641        tensor: FloatTensor<Self>,
642        dim: usize,
643        out_dtype: BoolDType,
644    ) -> BoolTensor<Self> {
645        unary_float!(tensor, float, |tensor| B::float_any_dim(tensor, dim, out_dtype) => Bool)
646    }
647
648    fn float_all(tensor: FloatTensor<Self>, out_dtype: BoolDType) -> BoolTensor<Self> {
649        unary_float!(tensor, float, |tensor| B::float_all(tensor, out_dtype) => Bool)
650    }
651
652    fn float_all_dim(
653        tensor: FloatTensor<Self>,
654        dim: usize,
655        out_dtype: BoolDType,
656    ) -> BoolTensor<Self> {
657        unary_float!(tensor, float, |tensor| B::float_all_dim(tensor, dim, out_dtype) => Bool)
658    }
659
660    fn float_sign(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
661        unary_float!(tensor, float, |tensor| B::float_sign(tensor) => Float)
662    }
663
664    fn float_sort(tensor: FloatTensor<Self>, dim: usize, descending: bool) -> FloatTensor<Self> {
665        unary_float!(tensor, float, |tensor| B::float_sort(tensor, dim, descending) => Float)
666    }
667
668    fn float_sort_with_indices(
669        tensor: FloatTensor<Self>,
670        dim: usize,
671        descending: bool,
672        indices_dtype: IntDType,
673    ) -> (FloatTensor<Self>, IntTensor<Self>) {
674        multi_op!(
675            inputs[(tensor, float)],
676            outputs[(out, Float), (indices, Int)],
677            B::float_sort_with_indices(tensor, dim, descending, indices_dtype)
678        )
679    }
680
681    fn float_argsort(
682        tensor: FloatTensor<Self>,
683        dim: usize,
684        descending: bool,
685        out_dtype: IntDType,
686    ) -> IntTensor<Self> {
687        unary_float!(tensor, float, |tensor| B::float_argsort(tensor, dim, descending, out_dtype) => Int)
688    }
689
690    fn float_grid_sample_2d(
691        tensor: FloatTensor<Self>,
692        grid: FloatTensor<Self>,
693        options: burn_backend::ops::GridSampleOptions,
694    ) -> FloatTensor<Self> {
695        binary_float!((tensor, float), (grid, float), |tensor, grid| B::float_grid_sample_2d(tensor, grid, options) => Float)
696    }
697
698    fn float_is_nan(tensor: FloatTensor<Self>, out_dtype: BoolDType) -> BoolTensor<Self> {
699        unary_float!(tensor, float, |tensor| B::float_is_nan(tensor, out_dtype) => Bool)
700    }
701
702    fn float_is_inf(tensor: FloatTensor<Self>, out_dtype: BoolDType) -> BoolTensor<Self> {
703        unary_float!(tensor, float, |tensor| B::float_is_inf(tensor, out_dtype) => Bool)
704    }
705
706    fn float_hypot(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
707        binary_float!((lhs, float), (rhs, float), |lhs, rhs| B::float_hypot(lhs, rhs) => Float)
708    }
709}