1use super::{expand, numeric, permute, unfold};
2use crate::CubeBackend;
3use crate::CubeDevice;
4use crate::kernel::matmul::{MatmulStrategy, matmul};
5use crate::kernel::prng::{random_bernoulli, random_normal, random_uniform};
6use crate::kernel::unary_basic::BasicFloatUnaryKind;
7use crate::kernel::{
8 self, FloatUnaryOp, FloatUnaryOpFamily, launch_unary_float, reduce, unary_basic,
9};
10use burn_backend::cubecl::dtype_to_storage_type;
11use burn_backend::ops::GridSampleOptions;
12use burn_backend::tensor::{BoolTensor, Device, FloatTensor, IntTensor};
13use burn_backend::{DType, ElementConversion, FloatDType, Slice};
14use burn_backend::{Distribution, Shape, TensorData, ops::FloatTensorOps};
15use burn_backend::{ExecutionError, Scalar, get_or_init_device_settings};
16use burn_std::{BoolDType, IntDType};
17use cubecl::prelude::*;
18use cubek::reduce::components::instructions::ReduceOperationConfig;
19use std::ops::Range;
20
21impl FloatTensorOps<Self> for CubeBackend {
22 #[cfg_attr(feature = "tracing", tracing::instrument(
23 level="trace",
24 skip(data),
25 fields(shape = ?data.shape(), dtype = ?data.dtype())
26 ))]
27 fn float_from_data(data: TensorData, device: &Device<Self>) -> FloatTensor<Self> {
28 match data.dtype() {
29 DType::F64 | DType::F32 | DType::F16 | DType::BF16 => super::from_data(data, device),
30 _ => unimplemented!("Unsupported dtype for `float_from_data`"),
31 }
32 }
33
34 fn float_random(
35 shape: Shape,
36 distribution: Distribution,
37 device: &Device<Self>,
38 dtype: FloatDType,
39 ) -> FloatTensor<Self> {
40 let dtype = dtype.into();
41 match distribution {
42 Distribution::Default => random_uniform(shape, device, 0., 1., dtype),
43 Distribution::Uniform(low, high) => {
44 random_uniform(shape, device, low.elem(), high.elem(), dtype)
45 }
46 Distribution::Bernoulli(prob) => random_bernoulli(shape, device, prob as f32, dtype),
47 Distribution::Normal(mean, std) => {
48 random_normal(shape, device, mean.elem(), std.elem(), dtype)
49 }
50 }
51 }
52
53 #[cfg_attr(feature = "tracing", tracing::instrument(
54 level="trace",
55 skip(tensor),
56 fields(from = ?tensor.device, meta = ?tensor.meta, dtype = ?tensor.dtype)
57 ))]
58 async fn float_into_data(tensor: FloatTensor<Self>) -> Result<TensorData, ExecutionError> {
59 super::into_data(tensor).await
60 }
61
62 #[cfg_attr(feature = "tracing", tracing::instrument(
63 level="trace",
64 skip(tensor),
65 fields(from = ?tensor.device, meta = ?tensor.meta, dtype = ?tensor.dtype)
66 ))]
67 fn float_to_device(tensor: FloatTensor<Self>, device: &Device<Self>) -> FloatTensor<Self> {
68 super::to_device(tensor, device)
69 }
70
71 fn float_empty(shape: Shape, device: &Device<Self>, dtype: FloatDType) -> FloatTensor<Self> {
72 let dtype = dtype.into();
73 super::empty(shape, device, dtype)
74 }
75
76 fn float_add(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
77 numeric::add(lhs, rhs)
78 }
79
80 fn float_add_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
81 let dtype = lhs.dtype;
82 numeric::add_scalar(lhs, InputScalar::new(rhs, dtype_to_storage_type(dtype)))
83 }
84
85 fn float_zeros(shape: Shape, device: &Device<Self>, dtype: FloatDType) -> FloatTensor<Self> {
86 let dtype = dtype.into();
87 numeric::zeros(device.clone(), shape, dtype)
88 }
89
90 fn float_full(
91 shape: Shape,
92 fill_value: Scalar,
93 device: &CubeDevice,
94 dtype: FloatDType,
95 ) -> FloatTensor<Self> {
96 let dtype: DType = dtype.into();
97 let client = device.client();
98 numeric::full_device_dtype(
99 client,
100 shape,
101 device.clone(),
102 InputScalar::new(fill_value, dtype_to_storage_type(dtype)),
103 dtype,
104 )
105 }
106
107 fn float_ones(shape: Shape, device: &Device<Self>, dtype: FloatDType) -> FloatTensor<Self> {
108 let dtype = dtype.into();
109 numeric::ones(device.clone(), shape, dtype)
110 }
111
112 fn float_sub(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
113 numeric::sub(lhs, rhs)
114 }
115
116 fn float_sub_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
117 let dtype = lhs.dtype;
118 numeric::sub_scalar(lhs, InputScalar::new(rhs, dtype_to_storage_type(dtype)))
119 }
120
121 fn float_mul(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
122 numeric::mul(lhs, rhs)
123 }
124
125 fn float_mul_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
126 let dtype = lhs.dtype;
127 numeric::mul_scalar(lhs, InputScalar::new(rhs, dtype_to_storage_type(dtype)))
128 }
129
130 fn float_div(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
131 numeric::div(lhs, rhs)
132 }
133
134 fn float_div_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
135 let dtype = lhs.dtype;
136 numeric::div_scalar(lhs, InputScalar::new(rhs, dtype_to_storage_type(dtype)))
137 }
138
139 fn float_remainder(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
140 numeric::remainder(lhs, rhs)
141 }
142
143 fn float_remainder_scalar(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
144 let dtype = lhs.dtype;
145 numeric::remainder_scalar(lhs, InputScalar::new(rhs, dtype_to_storage_type(dtype)))
146 }
147
148 fn float_matmul(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
149 let dtype = lhs.dtype;
150 matmul(lhs, rhs, None, MatmulStrategy::default(), dtype).unwrap()
151 }
152
153 fn float_cross(
154 lhs: FloatTensor<Self>,
155 rhs: FloatTensor<Self>,
156 dim: usize,
157 ) -> FloatTensor<Self> {
158 kernel::cross(lhs, rhs, dim)
159 }
160
161 fn float_swap_dims(tensor: FloatTensor<Self>, dim1: usize, dim2: usize) -> FloatTensor<Self> {
162 super::swap_dims(tensor, dim1, dim2)
163 }
164
165 fn float_reshape(tensor: FloatTensor<Self>, shape: Shape) -> FloatTensor<Self> {
166 super::reshape(tensor, shape)
167 }
168
169 fn float_gather(
170 dim: usize,
171 tensor: FloatTensor<Self>,
172 indices: IntTensor<Self>,
173 ) -> FloatTensor<Self> {
174 kernel::gather(dim, tensor, indices)
175 }
176
177 fn float_scatter(
178 dim: usize,
179 tensor: FloatTensor<Self>,
180 indices: IntTensor<Self>,
181 value: FloatTensor<Self>,
182 update: burn_backend::tensor::IndexingUpdateOp,
183 ) -> FloatTensor<Self> {
184 match update {
185 burn_backend::tensor::IndexingUpdateOp::Assign => {
186 kernel::scatter_assign(dim, tensor, indices, value)
187 }
188 burn_backend::tensor::IndexingUpdateOp::Add => {
189 kernel::scatter(dim, tensor, indices, value, false)
190 }
191 burn_backend::tensor::IndexingUpdateOp::Mul => {
192 kernel::scatter_mul(dim, tensor, indices, value)
193 }
194 burn_backend::tensor::IndexingUpdateOp::Min => {
195 kernel::scatter_min(dim, tensor, indices, value)
196 }
197 burn_backend::tensor::IndexingUpdateOp::Max => {
198 kernel::scatter_max(dim, tensor, indices, value)
199 }
200 }
201 }
202
203 fn float_scatter_nd(
204 data: FloatTensor<Self>,
205 indices: IntTensor<Self>,
206 values: FloatTensor<Self>,
207 reduction: burn_backend::tensor::IndexingUpdateOp,
208 ) -> FloatTensor<Self> {
209 kernel::scatter_nd(data, indices, values, reduction)
210 }
211
212 fn float_gather_nd(data: FloatTensor<Self>, indices: IntTensor<Self>) -> FloatTensor<Self> {
213 kernel::gather_nd(data, indices)
214 }
215
216 fn float_select(
217 tensor: FloatTensor<Self>,
218 dim: usize,
219 indices: IntTensor<Self>,
220 ) -> FloatTensor<Self> {
221 kernel::select(tensor, dim, indices)
222 }
223
224 fn float_select_assign(
225 tensor: FloatTensor<Self>,
226 dim: usize,
227 indices: IntTensor<Self>,
228 value: FloatTensor<Self>,
229 update: burn_backend::tensor::IndexingUpdateOp,
230 ) -> FloatTensor<Self> {
231 match update {
232 burn_backend::tensor::IndexingUpdateOp::Assign => {
233 kernel::select_assign_replace(tensor, dim, indices, value)
234 }
235 burn_backend::tensor::IndexingUpdateOp::Add => {
236 kernel::select_assign(tensor, dim, indices, value, false)
237 }
238 burn_backend::tensor::IndexingUpdateOp::Mul => {
239 kernel::select_assign_mul(tensor, dim, indices, value)
240 }
241 burn_backend::tensor::IndexingUpdateOp::Min => {
242 kernel::select_assign_min(tensor, dim, indices, value)
243 }
244 burn_backend::tensor::IndexingUpdateOp::Max => {
245 kernel::select_assign_max(tensor, dim, indices, value)
246 }
247 }
248 }
249
250 fn float_slice(tensor: FloatTensor<Self>, slices: &[Slice]) -> FloatTensor<Self> {
251 let all_steps_one = slices.iter().all(|info| info.step == 1);
253
254 if all_steps_one {
255 let simple_ranges: Vec<Range<usize>> = slices
257 .iter()
258 .enumerate()
259 .map(|(i, slice)| slice.to_range(tensor.meta.shape()[i]))
260 .collect();
261
262 kernel::slice(tensor, &simple_ranges)
263 } else {
264 kernel::slice_with_steps(tensor, slices)
266 }
267 }
268
269 fn float_slice_assign(
270 tensor: FloatTensor<Self>,
271 ranges: &[Slice],
272 value: FloatTensor<Self>,
273 ) -> FloatTensor<Self> {
274 kernel::slice_assign(tensor, ranges, value)
275 }
276
277 fn float_mask_where(
278 tensor: FloatTensor<Self>,
279 mask: BoolTensor<Self>,
280 value: FloatTensor<Self>,
281 ) -> FloatTensor<Self> {
282 let bool_dtype = mask.dtype;
283 kernel::mask_where_auto(tensor, mask, value, bool_dtype)
284 }
285
286 fn float_mask_fill(
287 tensor: FloatTensor<Self>,
288 mask: BoolTensor<Self>,
289 value: Scalar,
290 ) -> FloatTensor<Self> {
291 let dtype = tensor.dtype;
292 let bool_dtype = mask.dtype;
293 kernel::mask_fill_auto(
294 tensor,
295 mask,
296 InputScalar::new(value, dtype_to_storage_type(dtype)),
297 bool_dtype,
298 )
299 }
300
301 fn float_equal(
302 lhs: FloatTensor<Self>,
303 rhs: FloatTensor<Self>,
304 out_dtype: BoolDType,
305 ) -> BoolTensor<Self> {
306 kernel::equal(lhs, rhs, out_dtype.into())
307 }
308
309 fn float_not_equal(
310 lhs: FloatTensor<Self>,
311 rhs: FloatTensor<Self>,
312 out_dtype: BoolDType,
313 ) -> BoolTensor<Self> {
314 kernel::not_equal(lhs, rhs, out_dtype.into())
315 }
316
317 fn float_equal_elem(
318 lhs: FloatTensor<Self>,
319 rhs: Scalar,
320 out_dtype: BoolDType,
321 ) -> BoolTensor<Self> {
322 let dtype = lhs.dtype;
323 kernel::equal_elem(
324 lhs,
325 InputScalar::new(rhs, dtype_to_storage_type(dtype)),
326 out_dtype.into(),
327 )
328 }
329
330 fn float_not_equal_elem(
331 lhs: FloatTensor<Self>,
332 rhs: Scalar,
333 out_dtype: BoolDType,
334 ) -> BoolTensor<Self> {
335 let dtype = lhs.dtype;
336 kernel::not_equal_elem(
337 lhs,
338 InputScalar::new(rhs, dtype_to_storage_type(dtype)),
339 out_dtype.into(),
340 )
341 }
342
343 fn float_greater(
344 lhs: FloatTensor<Self>,
345 rhs: FloatTensor<Self>,
346 out_dtype: BoolDType,
347 ) -> BoolTensor<Self> {
348 kernel::greater(lhs, rhs, out_dtype.into())
349 }
350
351 fn float_greater_elem(
352 lhs: FloatTensor<Self>,
353 rhs: Scalar,
354 out_dtype: BoolDType,
355 ) -> BoolTensor<Self> {
356 let dtype = lhs.dtype;
357 kernel::greater_elem(
358 lhs,
359 InputScalar::new(rhs, dtype_to_storage_type(dtype)),
360 out_dtype.into(),
361 )
362 }
363
364 fn float_greater_equal(
365 lhs: FloatTensor<Self>,
366 rhs: FloatTensor<Self>,
367 out_dtype: BoolDType,
368 ) -> BoolTensor<Self> {
369 kernel::greater_equal(lhs, rhs, out_dtype.into())
370 }
371
372 fn float_greater_equal_elem(
373 lhs: FloatTensor<Self>,
374 rhs: Scalar,
375 out_dtype: BoolDType,
376 ) -> BoolTensor<Self> {
377 let dtype = lhs.dtype;
378 kernel::greater_equal_elem(
379 lhs,
380 InputScalar::new(rhs, dtype_to_storage_type(dtype)),
381 out_dtype.into(),
382 )
383 }
384
385 fn float_lower(
386 lhs: FloatTensor<Self>,
387 rhs: FloatTensor<Self>,
388 out_dtype: BoolDType,
389 ) -> BoolTensor<Self> {
390 kernel::lower(lhs, rhs, out_dtype.into())
391 }
392
393 fn float_lower_elem(
394 lhs: FloatTensor<Self>,
395 rhs: Scalar,
396 out_dtype: BoolDType,
397 ) -> BoolTensor<Self> {
398 let dtype = lhs.dtype;
399 kernel::lower_elem(
400 lhs,
401 InputScalar::new(rhs, dtype_to_storage_type(dtype)),
402 out_dtype.into(),
403 )
404 }
405
406 fn float_lower_equal(
407 lhs: FloatTensor<Self>,
408 rhs: FloatTensor<Self>,
409 out_dtype: BoolDType,
410 ) -> BoolTensor<Self> {
411 kernel::lower_equal(lhs, rhs, out_dtype.into())
412 }
413
414 fn float_lower_equal_elem(
415 lhs: FloatTensor<Self>,
416 rhs: Scalar,
417 out_dtype: BoolDType,
418 ) -> BoolTensor<Self> {
419 let dtype = lhs.dtype;
420 kernel::lower_equal_elem(
421 lhs,
422 InputScalar::new(rhs, dtype_to_storage_type(dtype)),
423 out_dtype.into(),
424 )
425 }
426
427 fn float_sum(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
428 reduce::sum_fallback(tensor, Default::default()).unwrap()
429 }
430
431 fn float_max(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
432 reduce::reduce(tensor, None, Default::default(), ReduceOperationConfig::Max).unwrap()
433 }
434
435 fn float_max_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
436 reduce::reduce_dim(
437 tensor,
438 None,
439 dim,
440 Default::default(),
441 ReduceOperationConfig::Max,
442 )
443 .unwrap()
444 }
445
446 fn float_min(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
447 reduce::reduce(tensor, None, Default::default(), ReduceOperationConfig::Min).unwrap()
448 }
449
450 fn float_min_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
451 reduce::reduce_dim(
452 tensor,
453 None,
454 dim,
455 Default::default(),
456 ReduceOperationConfig::Min,
457 )
458 .unwrap()
459 }
460
461 fn float_max_abs(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
462 reduce::reduce(
463 tensor,
464 None,
465 Default::default(),
466 ReduceOperationConfig::MaxAbs,
467 )
468 .unwrap()
469 }
470
471 fn float_max_abs_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
472 reduce::reduce_dim(
473 tensor,
474 None,
475 dim,
476 Default::default(),
477 ReduceOperationConfig::MaxAbs,
478 )
479 .unwrap()
480 }
481
482 fn float_any(tensor: FloatTensor<Self>, out_dtype: BoolDType) -> BoolTensor<Self> {
483 reduce::reduce_logical(tensor, None, ReduceOperationConfig::Any, out_dtype)
484 }
485
486 fn float_any_dim(
487 tensor: FloatTensor<Self>,
488 dim: usize,
489 out_dtype: BoolDType,
490 ) -> BoolTensor<Self> {
491 reduce::reduce_logical(tensor, Some(dim), ReduceOperationConfig::Any, out_dtype)
492 }
493
494 fn float_all(tensor: FloatTensor<Self>, out_dtype: BoolDType) -> BoolTensor<Self> {
495 reduce::reduce_logical(tensor, None, ReduceOperationConfig::All, out_dtype)
496 }
497
498 fn float_all_dim(
499 tensor: FloatTensor<Self>,
500 dim: usize,
501 out_dtype: BoolDType,
502 ) -> BoolTensor<Self> {
503 reduce::reduce_logical(tensor, Some(dim), ReduceOperationConfig::All, out_dtype)
504 }
505
506 fn float_sum_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
507 reduce::reduce_dim(
508 tensor,
509 None,
510 dim,
511 Default::default(),
512 ReduceOperationConfig::Sum,
513 )
514 .unwrap()
515 }
516
517 fn float_sum_dims(tensor: FloatTensor<Self>, dims: &[usize]) -> FloatTensor<Self> {
518 reduce::reduce_dims(
519 tensor,
520 None,
521 dims,
522 Default::default(),
523 ReduceOperationConfig::Sum,
524 )
525 .unwrap()
526 }
527
528 fn float_mean_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
529 reduce::reduce_dim(
530 tensor,
531 None,
532 dim,
533 Default::default(),
534 ReduceOperationConfig::Mean,
535 )
536 .unwrap()
537 }
538
539 fn float_mean(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
540 reduce::reduce(
541 tensor,
542 None,
543 Default::default(),
544 ReduceOperationConfig::Mean,
545 )
546 .unwrap()
547 }
548
549 fn float_cumsum(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
550 numeric::cumsum(tensor, dim)
551 }
552
553 fn float_cumprod(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
554 numeric::cumprod(tensor, dim)
555 }
556
557 fn float_cummin(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
558 numeric::cummin(tensor, dim)
559 }
560
561 fn float_cummax(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
562 numeric::cummax(tensor, dim)
563 }
564
565 fn float_prod(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
566 reduce::reduce(
567 tensor,
568 None,
569 Default::default(),
570 ReduceOperationConfig::Prod,
571 )
572 .unwrap()
573 }
574
575 fn float_prod_dim(tensor: FloatTensor<Self>, dim: usize) -> FloatTensor<Self> {
576 reduce::reduce_dim(
577 tensor,
578 None,
579 dim,
580 Default::default(),
581 ReduceOperationConfig::Prod,
582 )
583 .unwrap()
584 }
585
586 fn float_exp(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
587 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Exp)
588 }
589
590 fn float_log(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
591 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Log)
592 }
593
594 fn float_log1p(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
595 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Log1p)
596 }
597
598 fn float_powf_scalar_impl(lhs: FloatTensor<Self>, rhs: Scalar) -> FloatTensor<Self> {
599 struct Powf;
600
601 #[cube]
602 impl<F: Float, N: Size> FloatUnaryOp<F, N> for Powf {
603 type Options = InputScalar;
604
605 fn execute(input: Vector<F, N>, options: &Self::Options) -> Vector<F, N> {
606 Vector::powf(input, Vector::new(options.get::<F>()))
607 }
608 }
609
610 impl FloatUnaryOpFamily for Powf {
611 type Options = InputScalar;
612 type Unary<F: Float, N: Size> = Self;
613 }
614
615 let dtype = lhs.dtype;
616 launch_unary_float::<Powf, _>(lhs, |_| InputScalar::new(rhs, dtype_to_storage_type(dtype)))
617 }
618
619 fn float_sqrt(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
620 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Sqrt)
621 }
622
623 fn float_abs(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
624 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Abs)
625 }
626
627 fn float_sign(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
628 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Sign)
629 }
630
631 fn float_cos(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
632 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Cos)
633 }
634
635 fn float_sin(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
636 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Sin)
637 }
638
639 fn float_tan(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
640 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Tan)
641 }
642
643 fn float_cosh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
644 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Cosh)
645 }
646
647 fn float_sinh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
648 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Sinh)
649 }
650
651 fn float_tanh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
652 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Tanh)
653 }
654
655 fn float_acos(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
656 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::ArcCos)
657 }
658
659 fn float_acosh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
660 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::ArcCosh)
661 }
662
663 fn float_asin(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
664 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::ArcSin)
665 }
666
667 fn float_asinh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
668 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::ArcSinh)
669 }
670
671 fn float_atan(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
672 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::ArcTan)
673 }
674
675 fn float_atanh(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
676 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::ArcTanh)
677 }
678
679 fn float_atan2(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
680 crate::kernel::atan2(lhs, rhs)
681 }
682
683 fn float_round(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
684 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Round)
685 }
686
687 fn float_floor(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
688 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Floor)
689 }
690
691 fn float_ceil(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
692 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Ceil)
693 }
694
695 fn float_trunc(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
696 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Trunc)
697 }
698
699 fn float_erf(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
700 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Erf)
701 }
702
703 fn float_argmax(tensor: FloatTensor<Self>, dim: usize, out_dtype: IntDType) -> IntTensor<Self> {
704 reduce::reduce_dim(
705 tensor,
706 Some(out_dtype.into()),
707 dim,
708 Default::default(),
709 ReduceOperationConfig::ArgMax,
710 )
711 .unwrap()
712 }
713
714 fn float_argtopk(
715 tensor: FloatTensor<Self>,
716 dim: usize,
717 k: usize,
718 out_dtype: IntDType,
719 ) -> IntTensor<Self> {
720 reduce::reduce_dim(
721 tensor,
722 Some(out_dtype.into()),
723 dim,
724 Default::default(),
725 ReduceOperationConfig::ArgTopK(k),
726 )
727 .unwrap()
728 }
729
730 fn float_topk(tensor: FloatTensor<Self>, dim: usize, k: usize) -> FloatTensor<Self> {
731 reduce::reduce_dim(
732 tensor,
733 None,
734 dim,
735 Default::default(),
736 ReduceOperationConfig::TopK(k),
737 )
738 .unwrap()
739 }
740
741 fn float_topk_with_indices(
742 tensor: FloatTensor<Self>,
743 dim: usize,
744 k: usize,
745 out_dtype: IntDType,
746 ) -> (FloatTensor<Self>, IntTensor<Self>) {
747 reduce::reduce_dim_with_indices(
750 tensor,
751 out_dtype.into(),
752 dim,
753 Default::default(),
754 ReduceOperationConfig::TopK(k),
755 )
756 .unwrap()
757 }
758
759 fn float_max_dim_with_indices(
760 tensor: FloatTensor<Self>,
761 dim: usize,
762 indices_dtype: IntDType,
763 ) -> (FloatTensor<Self>, IntTensor<Self>) {
764 reduce::reduce_dim_with_indices(
766 tensor,
767 indices_dtype.into(),
768 dim,
769 Default::default(),
770 ReduceOperationConfig::Max,
771 )
772 .unwrap()
773 }
774
775 fn float_min_dim_with_indices(
776 tensor: FloatTensor<Self>,
777 dim: usize,
778 indices_dtype: IntDType,
779 ) -> (FloatTensor<Self>, IntTensor<Self>) {
780 reduce::reduce_dim_with_indices(
782 tensor,
783 indices_dtype.into(),
784 dim,
785 Default::default(),
786 ReduceOperationConfig::Min,
787 )
788 .unwrap()
789 }
790
791 fn float_argmin(tensor: FloatTensor<Self>, dim: usize, out_dtype: IntDType) -> IntTensor<Self> {
792 reduce::reduce_dim(
793 tensor,
794 Some(out_dtype.into()),
795 dim,
796 Default::default(),
797 ReduceOperationConfig::ArgMin,
798 )
799 .unwrap()
800 }
801
802 fn float_into_int(tensor: FloatTensor<Self>, out_dtype: IntDType) -> IntTensor<Self> {
803 kernel::cast(tensor, out_dtype.into())
804 }
805
806 fn float_clamp(tensor: FloatTensor<Self>, min: Scalar, max: Scalar) -> FloatTensor<Self> {
807 let dtype = tensor.dtype;
808 kernel::clamp_float(
809 tensor,
810 InputScalar::new(min, dtype_to_storage_type(dtype)),
811 InputScalar::new(max, dtype_to_storage_type(dtype)),
812 )
813 }
814
815 fn float_recip(tensor: FloatTensor<Self>) -> FloatTensor<Self> {
816 unary_basic::launch::<_>(tensor, |_| BasicFloatUnaryKind::Recip)
817 }
818
819 fn float_repeat_dim(tensor: FloatTensor<Self>, dim: usize, times: usize) -> FloatTensor<Self> {
820 kernel::repeat_dim(tensor, dim, times)
821 }
822
823 fn float_powf(lhs: FloatTensor<Self>, rhs: FloatTensor<Self>) -> FloatTensor<Self> {
824 numeric::pow(lhs, rhs)
825 }
826
827 fn float_permute(tensor: FloatTensor<Self>, axes: &[usize]) -> FloatTensor<Self> {
828 permute(tensor, axes)
829 }
830
831 fn float_expand(tensor: FloatTensor<Self>, shape: Shape) -> FloatTensor<Self> {
832 expand(tensor, shape)
833 }
834
835 fn float_flip(tensor: FloatTensor<Self>, axes: &[usize]) -> FloatTensor<Self> {
836 let bool_dtype = get_or_init_device_settings::<Self>(&tensor.device).bool_dtype;
837 kernel::flip(tensor, axes, bool_dtype.into())
838 }
839
840 fn float_cast(tensor: FloatTensor<Self>, dtype: FloatDType) -> FloatTensor<Self> {
841 kernel::cast(tensor, dtype.into())
842 }
843
844 fn float_unfold(
845 tensor: FloatTensor<Self>,
846 dim: usize,
847 size: usize,
848 step: usize,
849 ) -> FloatTensor<Self> {
850 unfold(tensor, dim, size, step)
851 }
852
853 fn float_is_nan(tensor: FloatTensor<Self>, out_dtype: BoolDType) -> BoolTensor<Self> {
854 kernel::is_nan(tensor, out_dtype.into())
855 }
856
857 fn float_is_inf(tensor: FloatTensor<Self>, out_dtype: BoolDType) -> BoolTensor<Self> {
858 kernel::is_inf(tensor, out_dtype.into())
859 }
860
861 fn float_grid_sample_2d(
862 tensor: FloatTensor<Self>,
863 grid: FloatTensor<Self>,
864 options: GridSampleOptions,
865 ) -> FloatTensor<Self> {
866 kernel::grid_sample::grid_sample(tensor, grid, options)
867 }
868}