1use alloc::vec::Vec;
4use ruda_tensor::{
5 Distribution, ExecutionError, FloatDType, Scalar, TensorData,
6 ops::{FloatTensorOps, GridSampleOptions},
7 tensor::{BoolTensor, Device, FloatTensor, IntTensor},
8};
9use ruda_tensor::{Shape, Slice};
10
11
12use crate::ops::matmul;
13use crate::ops::unary;
14use crate::{Host, HostTensor};
15
16impl FloatTensorOps<Host> for Host {
17 fn float_from_data(data: TensorData, _device: &Device<Host>) -> FloatTensor<Host> {
18 HostTensor::from_data(data)
19 }
20
21 fn float_random(
22 shape: Shape,
23 distribution: Distribution,
24 _device: &Device<Host>,
25 dtype: FloatDType,
26 ) -> FloatTensor<Host> {
27 rurand_host::float_random(shape, distribution, dtype)
28 }
29
30 async fn float_into_data(tensor: FloatTensor<Host>) -> Result<TensorData, ExecutionError> {
31 Ok(tensor.into_data())
32 }
33
34 fn float_device(_tensor: &FloatTensor<Host>) -> Device<Host> {
35 Default::default()
37 }
38
39 fn float_to_device(tensor: FloatTensor<Host>, _device: &Device<Host>) -> FloatTensor<Host> {
40 tensor
42 }
43
44 fn float_detach(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
45 tensor
46 }
47
48 fn float_into_int(tensor: FloatTensor<Host>, out_dtype: ruda_tensor::IntDType) -> IntTensor<Host> {
49 ruprim_host::cast::float_into_int(tensor, out_dtype)
50 }
51
52 fn float_empty(shape: Shape, _device: &Device<Host>, dtype: FloatDType) -> FloatTensor<Host> {
53 HostTensor::empty(shape, dtype.into())
54 }
55
56 fn float_add(lhs: FloatTensor<Host>, rhs: FloatTensor<Host>) -> FloatTensor<Host> {
57 ruprim_host::binary::dispatch_float::float_add(lhs, rhs)
58 }
59
60 fn float_add_scalar(lhs: FloatTensor<Host>, rhs: Scalar) -> FloatTensor<Host> {
61 ruprim_host::binary::dispatch_float::float_add_scalar(lhs, rhs)
62 }
63
64 fn float_sub(lhs: FloatTensor<Host>, rhs: FloatTensor<Host>) -> FloatTensor<Host> {
65 ruprim_host::binary::dispatch_float::float_sub(lhs, rhs)
66 }
67
68 fn float_sub_scalar(lhs: FloatTensor<Host>, rhs: Scalar) -> FloatTensor<Host> {
69 ruprim_host::binary::dispatch_float::float_sub_scalar(lhs, rhs)
70 }
71
72 fn float_mul(lhs: FloatTensor<Host>, rhs: FloatTensor<Host>) -> FloatTensor<Host> {
73 ruprim_host::binary::dispatch_float::float_mul(lhs, rhs)
74 }
75
76 fn float_mul_scalar(lhs: FloatTensor<Host>, rhs: Scalar) -> FloatTensor<Host> {
77 ruprim_host::binary::dispatch_float::float_mul_scalar(lhs, rhs)
78 }
79
80 fn float_div(lhs: FloatTensor<Host>, rhs: FloatTensor<Host>) -> FloatTensor<Host> {
81 ruprim_host::binary::dispatch_float::float_div(lhs, rhs)
82 }
83
84 fn float_div_scalar(lhs: FloatTensor<Host>, rhs: Scalar) -> FloatTensor<Host> {
85 ruprim_host::binary::dispatch_float::float_div_scalar(lhs, rhs)
86 }
87
88 fn float_remainder(lhs: FloatTensor<Host>, rhs: FloatTensor<Host>) -> FloatTensor<Host> {
89 ruprim_host::binary::dispatch_float::float_remainder(lhs, rhs)
90 }
91
92 fn float_remainder_scalar(lhs: FloatTensor<Host>, rhs: Scalar) -> FloatTensor<Host> {
93 ruprim_host::binary::dispatch_float::float_remainder_scalar(lhs, rhs)
94 }
95
96 fn float_matmul(lhs: FloatTensor<Host>, rhs: FloatTensor<Host>) -> FloatTensor<Host> {
97 matmul::matmul(lhs, rhs)
98 }
99
100 fn float_cross(
101 lhs: FloatTensor<Host>,
102 rhs: FloatTensor<Host>,
103 dim: usize,
104 ) -> FloatTensor<Host> {
105 rublas_host::cross(lhs, rhs, dim)
106 }
107
108 fn float_recip(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
109 unary::recip(tensor)
110 }
111
112 fn float_swap_dims(tensor: FloatTensor<Host>, dim1: usize, dim2: usize) -> FloatTensor<Host> {
113 tensor.transpose(dim1, dim2)
114 }
115
116 fn float_permute(tensor: FloatTensor<Host>, axes: &[usize]) -> FloatTensor<Host> {
117 tensor.permute(axes)
118 }
119
120 fn float_flip(tensor: FloatTensor<Host>, axes: &[usize]) -> FloatTensor<Host> {
121 crate::ops::flip::flip(tensor, axes)
122 }
123
124 fn float_cat(tensors: Vec<FloatTensor<Host>>, dim: usize) -> FloatTensor<Host> {
125 crate::ops::cat::cat(tensors, dim)
126 }
127
128 fn float_reshape(tensor: FloatTensor<Host>, shape: Shape) -> FloatTensor<Host> {
129 tensor.reshape(shape)
130 }
131
132 fn float_gather(
133 dim: usize,
134 tensor: FloatTensor<Host>,
135 indices: IntTensor<Host>,
136 ) -> FloatTensor<Host> {
137 ruprim_host::gather_scatter::dispatch_float::float_gather(dim, tensor, indices)
138 }
139
140 fn float_scatter_add(
141 dim: usize,
142 tensor: FloatTensor<Host>,
143 indices: IntTensor<Host>,
144 value: FloatTensor<Host>,
145 ) -> FloatTensor<Host> {
146 ruprim_host::gather_scatter::dispatch_float::float_scatter_add(dim, tensor, indices, value)
147 }
148
149 fn float_scatter_nd(
150 data: FloatTensor<Host>,
151 indices: IntTensor<Host>,
152 values: FloatTensor<Host>,
153 reduction: ruda_tensor::tensor::IndexingUpdateOp,
154 ) -> FloatTensor<Host> {
155 ruprim_host::gather_scatter::dispatch_float::float_scatter_nd(data, indices, values, reduction)
156 }
157
158 fn float_gather_nd(data: FloatTensor<Host>, indices: IntTensor<Host>) -> FloatTensor<Host> {
159 ruprim_host::gather_scatter::dispatch_float::float_gather_nd(data, indices)
160 }
161
162 fn float_select(
163 tensor: FloatTensor<Host>,
164 dim: usize,
165 indices: IntTensor<Host>,
166 ) -> FloatTensor<Host> {
167 ruprim_host::gather_scatter::dispatch_float::float_select(tensor, dim, indices)
168 }
169
170 fn float_select_add(
171 tensor: FloatTensor<Host>,
172 dim: usize,
173 indices: IntTensor<Host>,
174 value: FloatTensor<Host>,
175 ) -> FloatTensor<Host> {
176 ruprim_host::gather_scatter::dispatch_float::float_select_add(tensor, dim, indices, value)
177 }
178
179 fn float_slice(tensor: FloatTensor<Host>, slices: &[Slice]) -> FloatTensor<Host> {
180 crate::ops::slice::slice(tensor, slices)
181 }
182
183 fn float_slice_assign(
184 tensor: FloatTensor<Host>,
185 slices: &[Slice],
186 value: FloatTensor<Host>,
187 ) -> FloatTensor<Host> {
188 crate::ops::slice::slice_assign(tensor, slices, value)
189 }
190
191 fn float_mask_where(
192 tensor: FloatTensor<Host>,
193 mask: BoolTensor<Host>,
194 value: FloatTensor<Host>,
195 ) -> FloatTensor<Host> {
196 ruprim_host::mask::dispatch::float_mask_where(tensor, mask, value)
197 }
198
199 fn float_mask_fill(
200 tensor: FloatTensor<Host>,
201 mask: BoolTensor<Host>,
202 value: Scalar,
203 ) -> FloatTensor<Host> {
204 ruprim_host::mask::dispatch::float_mask_fill(tensor, mask, value)
205 }
206
207 fn float_equal(
208 lhs: FloatTensor<Host>,
209 rhs: FloatTensor<Host>,
210 out_dtype: ruda_tensor::BoolDType,
211 ) -> BoolTensor<Host> {
212 crate::ops::comparison::equal(lhs, rhs, out_dtype)
213 }
214
215 fn float_equal_elem(
216 lhs: FloatTensor<Host>,
217 rhs: Scalar,
218 out_dtype: ruda_tensor::BoolDType,
219 ) -> BoolTensor<Host> {
220 ruprim_host::comparison::dispatch::float_equal_elem(lhs, rhs, out_dtype)
221 }
222
223 fn float_greater(
224 lhs: FloatTensor<Host>,
225 rhs: FloatTensor<Host>,
226 out_dtype: ruda_tensor::BoolDType,
227 ) -> BoolTensor<Host> {
228 crate::ops::comparison::greater(lhs, rhs, out_dtype)
229 }
230
231 fn float_greater_elem(
232 lhs: FloatTensor<Host>,
233 rhs: Scalar,
234 out_dtype: ruda_tensor::BoolDType,
235 ) -> BoolTensor<Host> {
236 ruprim_host::comparison::dispatch::float_greater_elem(lhs, rhs, out_dtype)
237 }
238
239 fn float_greater_equal(
240 lhs: FloatTensor<Host>,
241 rhs: FloatTensor<Host>,
242 out_dtype: ruda_tensor::BoolDType,
243 ) -> BoolTensor<Host> {
244 crate::ops::comparison::greater_equal(lhs, rhs, out_dtype)
245 }
246
247 fn float_greater_equal_elem(
248 lhs: FloatTensor<Host>,
249 rhs: Scalar,
250 out_dtype: ruda_tensor::BoolDType,
251 ) -> BoolTensor<Host> {
252 ruprim_host::comparison::dispatch::float_greater_equal_elem(lhs, rhs, out_dtype)
253 }
254
255 fn float_lower(
256 lhs: FloatTensor<Host>,
257 rhs: FloatTensor<Host>,
258 out_dtype: ruda_tensor::BoolDType,
259 ) -> BoolTensor<Host> {
260 crate::ops::comparison::lower(lhs, rhs, out_dtype)
261 }
262
263 fn float_lower_elem(
264 lhs: FloatTensor<Host>,
265 rhs: Scalar,
266 out_dtype: ruda_tensor::BoolDType,
267 ) -> BoolTensor<Host> {
268 ruprim_host::comparison::dispatch::float_lower_elem(lhs, rhs, out_dtype)
269 }
270
271 fn float_lower_equal(
272 lhs: FloatTensor<Host>,
273 rhs: FloatTensor<Host>,
274 out_dtype: ruda_tensor::BoolDType,
275 ) -> BoolTensor<Host> {
276 crate::ops::comparison::lower_equal(lhs, rhs, out_dtype)
277 }
278
279 fn float_lower_equal_elem(
280 lhs: FloatTensor<Host>,
281 rhs: Scalar,
282 out_dtype: ruda_tensor::BoolDType,
283 ) -> BoolTensor<Host> {
284 ruprim_host::comparison::dispatch::float_lower_equal_elem(lhs, rhs, out_dtype)
285 }
286
287 fn float_not_equal(
288 lhs: FloatTensor<Host>,
289 rhs: FloatTensor<Host>,
290 out_dtype: ruda_tensor::BoolDType,
291 ) -> BoolTensor<Host> {
292 crate::ops::comparison::not_equal(lhs, rhs, out_dtype)
293 }
294
295 fn float_not_equal_elem(
296 lhs: FloatTensor<Host>,
297 rhs: Scalar,
298 out_dtype: ruda_tensor::BoolDType,
299 ) -> BoolTensor<Host> {
300 ruprim_host::comparison::dispatch::float_not_equal_elem(lhs, rhs, out_dtype)
301 }
302
303 fn float_neg(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
304 ruprim_host::unary::dispatch_float::float_neg(tensor)
305 }
306
307 fn float_clamp(tensor: FloatTensor<Host>, min: Scalar, max: Scalar) -> FloatTensor<Host> {
308 ruprim_host::unary::dispatch_float::float_clamp(tensor, min, max)
309 }
310
311 fn float_clamp_min(tensor: FloatTensor<Host>, min: Scalar) -> FloatTensor<Host> {
312 ruprim_host::unary::dispatch_float::float_clamp_min(tensor, min)
313 }
314
315 fn float_clamp_max(tensor: FloatTensor<Host>, max: Scalar) -> FloatTensor<Host> {
316 ruprim_host::unary::dispatch_float::float_clamp_max(tensor, max)
317 }
318
319 fn float_sign(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
320 ruprim_host::unary::dispatch_float::float_sign(tensor)
321 }
322
323 fn float_mean(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
324 crate::ops::reduce::mean(tensor)
325 }
326
327 fn float_max(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
328 crate::ops::reduce::max(tensor)
329 }
330
331 fn float_max_dim(tensor: FloatTensor<Host>, dim: usize) -> FloatTensor<Host> {
332 crate::ops::reduce::max_dim(tensor, dim)
333 }
334
335 fn float_min(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
336 crate::ops::reduce::min(tensor)
337 }
338
339 fn float_min_dim(tensor: FloatTensor<Host>, dim: usize) -> FloatTensor<Host> {
340 crate::ops::reduce::min_dim(tensor, dim)
341 }
342
343 fn float_max_dim_with_indices(
344 tensor: FloatTensor<Host>,
345 dim: usize,
346 indices_dtype: ruda_tensor::IntDType,
347 ) -> (FloatTensor<Host>, IntTensor<Host>) {
348 ruprim_host::reduce::dispatch::float_max_dim_with_indices(tensor, dim, indices_dtype)
349 }
350
351 fn float_min_dim_with_indices(
352 tensor: FloatTensor<Host>,
353 dim: usize,
354 indices_dtype: ruda_tensor::IntDType,
355 ) -> (FloatTensor<Host>, IntTensor<Host>) {
356 ruprim_host::reduce::dispatch::float_min_dim_with_indices(tensor, dim, indices_dtype)
357 }
358
359 fn float_any(tensor: FloatTensor<Host>, out_dtype: ruda_tensor::BoolDType) -> BoolTensor<Host> {
360 crate::ops::comparison::any_float(tensor, out_dtype)
361 }
362
363 fn float_any_dim(
364 tensor: FloatTensor<Host>,
365 dim: usize,
366 out_dtype: ruda_tensor::BoolDType,
367 ) -> BoolTensor<Host> {
368 crate::ops::comparison::any_float_dim(tensor, dim, out_dtype)
369 }
370
371 fn float_all(tensor: FloatTensor<Host>, out_dtype: ruda_tensor::BoolDType) -> BoolTensor<Host> {
372 crate::ops::comparison::all_float(tensor, out_dtype)
373 }
374
375 fn float_all_dim(
376 tensor: FloatTensor<Host>,
377 dim: usize,
378 out_dtype: ruda_tensor::BoolDType,
379 ) -> BoolTensor<Host> {
380 crate::ops::comparison::all_float_dim(tensor, dim, out_dtype)
381 }
382
383 fn float_sum(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
384 crate::ops::reduce::sum(tensor)
385 }
386
387 fn float_sum_dim(tensor: FloatTensor<Host>, dim: usize) -> FloatTensor<Host> {
388 crate::ops::reduce::sum_dim(tensor, dim)
389 }
390
391 fn float_mean_dim(tensor: FloatTensor<Host>, dim: usize) -> FloatTensor<Host> {
392 crate::ops::reduce::mean_dim(tensor, dim)
393 }
394
395 fn float_prod(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
396 crate::ops::reduce::prod(tensor)
397 }
398
399 fn float_prod_dim(tensor: FloatTensor<Host>, dim: usize) -> FloatTensor<Host> {
400 crate::ops::reduce::prod_dim(tensor, dim)
401 }
402
403 fn float_cumsum(tensor: FloatTensor<Host>, dim: usize) -> FloatTensor<Host> {
404 ruprim_host::cumulative::dispatch::float_cumsum(tensor, dim)
405 }
406
407 fn float_cumprod(tensor: FloatTensor<Host>, dim: usize) -> FloatTensor<Host> {
408 ruprim_host::cumulative::dispatch::float_cumprod(tensor, dim)
409 }
410
411 fn float_cummin(tensor: FloatTensor<Host>, dim: usize) -> FloatTensor<Host> {
412 ruprim_host::cumulative::dispatch::float_cummin(tensor, dim)
413 }
414
415 fn float_cummax(tensor: FloatTensor<Host>, dim: usize) -> FloatTensor<Host> {
416 ruprim_host::cumulative::dispatch::float_cummax(tensor, dim)
417 }
418
419 fn float_cast(tensor: FloatTensor<Host>, dtype: FloatDType) -> FloatTensor<Host> {
420 ruprim_host::cast::float_cast(tensor, dtype)
421 }
422
423 fn float_exp(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
424 unary::exp(tensor)
425 }
426
427 fn float_log(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
428 unary::log(tensor)
429 }
430
431 fn float_log1p(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
432 unary::log1p(tensor)
433 }
434
435 fn float_powf(lhs: FloatTensor<Host>, rhs: FloatTensor<Host>) -> FloatTensor<Host> {
436 ruprim_host::binary::dispatch_float::float_powf(lhs, rhs)
437 }
438
439 fn float_powf_scalar_impl(tensor: FloatTensor<Host>, value: Scalar) -> FloatTensor<Host> {
440 ruprim_host::binary::dispatch_float::float_powf_scalar_impl(tensor, value)
441 }
442
443 fn float_sqrt(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
444 unary::sqrt(tensor)
445 }
446
447 fn float_abs(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
448 unary::abs(tensor)
449 }
450
451 fn float_cos(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
452 unary::cos(tensor)
453 }
454
455 fn float_sin(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
456 unary::sin(tensor)
457 }
458
459 fn float_tan(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
460 unary::tan(tensor)
461 }
462
463 fn float_cosh(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
464 unary::cosh(tensor)
465 }
466
467 fn float_sinh(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
468 unary::sinh(tensor)
469 }
470
471 fn float_tanh(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
472 unary::tanh(tensor)
473 }
474
475 fn float_acos(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
476 unary::acos(tensor)
477 }
478
479 fn float_acosh(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
480 unary::acosh(tensor)
481 }
482
483 fn float_asin(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
484 unary::asin(tensor)
485 }
486
487 fn float_asinh(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
488 unary::asinh(tensor)
489 }
490
491 fn float_atan(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
492 unary::atan(tensor)
493 }
494
495 fn float_atanh(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
496 unary::atanh(tensor)
497 }
498
499 fn float_atan2(lhs: FloatTensor<Host>, rhs: FloatTensor<Host>) -> FloatTensor<Host> {
500 ruprim_host::binary::dispatch_float::float_atan2(lhs, rhs)
501 }
502
503 fn float_hypot(lhs: FloatTensor<Host>, rhs: FloatTensor<Host>) -> FloatTensor<Host> {
504 ruprim_host::binary::dispatch_float::float_hypot(lhs, rhs)
505 }
506
507 fn float_round(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
508 unary::round(tensor)
509 }
510
511 fn float_floor(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
512 unary::floor(tensor)
513 }
514
515 fn float_ceil(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
516 unary::ceil(tensor)
517 }
518
519 fn float_trunc(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
520 unary::trunc(tensor)
521 }
522
523 fn float_erf(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
524 unary::erf(tensor)
525 }
526
527 fn float_argmax(
528 tensor: FloatTensor<Host>,
529 dim: usize,
530 out_dtype: ruda_tensor::IntDType,
531 ) -> IntTensor<Host> {
532 ruprim_host::reduce::dispatch::float_argmax(tensor, dim, out_dtype)
533 }
534
535 fn float_argtopk(
536 tensor: FloatTensor<Host>,
537 dim: usize,
538 k: usize,
539 out_dtype: ruda_tensor::IntDType,
540 ) -> IntTensor<Host> {
541 ruprim_host::sort::dispatch::float_argtopk(tensor, dim, k, out_dtype)
542 }
543
544 fn float_argmin(
545 tensor: FloatTensor<Host>,
546 dim: usize,
547 out_dtype: ruda_tensor::IntDType,
548 ) -> IntTensor<Host> {
549 ruprim_host::reduce::dispatch::float_argmin(tensor, dim, out_dtype)
550 }
551
552 fn float_expand(tensor: FloatTensor<Host>, shape: Shape) -> FloatTensor<Host> {
553 crate::ops::expand::expand(tensor, shape)
554 }
555
556 fn float_unfold(
557 tensor: FloatTensor<Host>,
558 dim: usize,
559 size: usize,
560 step: usize,
561 ) -> FloatTensor<Host> {
562 crate::ops::unfold::unfold(tensor, dim, size, step)
564 }
565
566 fn float_grid_sample_2d(
567 tensor: FloatTensor<Host>,
568 grid: FloatTensor<Host>,
569 options: GridSampleOptions,
570 ) -> FloatTensor<Host> {
571 crate::ops::grid_sample::grid_sample_2d(tensor, grid, options)
572 }
573
574 fn float_zeros(shape: Shape, _device: &Device<Host>, dtype: FloatDType) -> FloatTensor<Host> {
575 HostTensor::zeros(shape, dtype.into())
576 }
577
578 fn float_ones(shape: Shape, _device: &Device<Host>, dtype: FloatDType) -> FloatTensor<Host> {
579 ruprim_host::fill::float_ones(shape, dtype)
580 }
581
582 fn float_full(
583 shape: Shape,
584 fill_value: Scalar,
585 _device: &Device<Host>,
586 dtype: FloatDType,
587 ) -> FloatTensor<Host> {
588 ruprim_host::fill::float_full(shape, fill_value, dtype)
589 }
590
591 fn float_transpose(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
592 let ndims = tensor.layout().num_dims();
593 if ndims < 2 {
594 return tensor;
595 }
596 tensor.transpose(ndims - 2, ndims - 1)
597 }
598
599 fn float_repeat_dim(tensor: FloatTensor<Host>, dim: usize, times: usize) -> FloatTensor<Host> {
600 crate::ops::repeat_dim::repeat_dim(tensor, dim, times)
601 }
602
603 fn float_sort(tensor: FloatTensor<Host>, dim: usize, descending: bool) -> FloatTensor<Host> {
604 crate::ops::sort::sort(tensor, dim, descending)
605 }
606
607 fn float_sort_with_indices(
608 tensor: FloatTensor<Host>,
609 dim: usize,
610 descending: bool,
611 indices_dtype: ruda_tensor::IntDType,
612 ) -> (FloatTensor<Host>, IntTensor<Host>) {
613 ruprim_host::sort::dispatch::float_sort_with_indices(tensor, dim, descending, indices_dtype)
614 }
615
616 fn float_argsort(
617 tensor: FloatTensor<Host>,
618 dim: usize,
619 descending: bool,
620 out_dtype: ruda_tensor::IntDType,
621 ) -> IntTensor<Host> {
622 ruprim_host::sort::dispatch::float_argsort(tensor, dim, descending, out_dtype)
623 }
624
625 fn float_powi(lhs: FloatTensor<Host>, rhs: IntTensor<Host>) -> FloatTensor<Host> {
626 ruprim_host::binary::dispatch_float::float_powi(lhs, rhs)
627 }
628
629 fn float_powi_scalar(lhs: FloatTensor<Host>, rhs: Scalar) -> FloatTensor<Host> {
630 ruprim_host::binary::dispatch_float::float_powi_scalar(lhs, rhs)
631 }
632
633 fn float_powi_scalar_impl(lhs: FloatTensor<Host>, rhs: Scalar) -> FloatTensor<Host> {
634 ruprim_host::binary::dispatch_float::float_powi_scalar(lhs, rhs)
635 }
636
637 fn float_powf_scalar(tensor: FloatTensor<Host>, value: Scalar) -> FloatTensor<Host> {
638 ruprim_host::binary::dispatch_float::float_powf_scalar(tensor, value)
639 }
640
641 fn float_max_abs(tensor: FloatTensor<Host>) -> FloatTensor<Host> {
642 ruprim_host::reduce::dispatch::float_max_abs(tensor)
643 }
644
645 fn float_max_abs_dim(tensor: FloatTensor<Host>, dim: usize) -> FloatTensor<Host> {
646 ruprim_host::reduce::dispatch::float_max_abs_dim(tensor, dim)
647 }
648
649 fn float_is_nan(tensor: FloatTensor<Host>, out_dtype: ruda_tensor::BoolDType) -> BoolTensor<Host> {
650 ruprim_host::unary::dispatch_float::float_is_nan(tensor, out_dtype)
651 }
652
653 fn float_is_inf(tensor: FloatTensor<Host>, out_dtype: ruda_tensor::BoolDType) -> BoolTensor<Host> {
654 ruprim_host::unary::dispatch_float::float_is_inf(tensor, out_dtype)
655 }
656}
657
658#[cfg(test)]
667mod tests {
668 use ruda_tensor::TensorData;
669
670 use crate::Host;
671
672 #[test]
673 fn test_float_into_int_i32() {
674 use ruda_tensor::ops::FloatTensorOps;
675 use ruda_tensor::IntDType;
676
677 let t = crate::HostTensor::from_data(TensorData::from([1.5f32, -2.7, 0.0, 255.9]));
678 let result = Host::float_into_int(t, IntDType::I32);
679 assert_eq!(result.dtype(), ruda_tensor::DType::I32);
680 let data: Vec<i32> = result.into_data().to_vec().unwrap();
681 assert_eq!(data, vec![1, -2, 0, 255]);
682 }
683
684 #[test]
685 fn test_float_into_int_u8() {
686 use ruda_tensor::ops::FloatTensorOps;
687 use ruda_tensor::IntDType;
688
689 let t = crate::HostTensor::from_data(TensorData::from([0.0f32, 1.9, 127.5, 255.0]));
690 let result = Host::float_into_int(t, IntDType::U8);
691 assert_eq!(result.dtype(), ruda_tensor::DType::U8);
692 let data: Vec<u8> = result.into_data().to_vec().unwrap();
693 assert_eq!(data, vec![0, 1, 127, 255]);
694 }
695
696 #[test]
697 fn test_float_argmax_i32_out_dtype() {
698 use ruda_tensor::ops::FloatTensorOps;
699 use ruda_tensor::IntDType;
700
701 let t = crate::HostTensor::from_data(TensorData::from([[1.0f32, 3.0, 2.0]]));
702 let result = Host::float_argmax(t, 1, IntDType::I32);
703 assert_eq!(result.dtype(), ruda_tensor::DType::I32);
704 let data: Vec<i32> = result.into_data().to_vec().unwrap();
705 assert_eq!(data, vec![1]);
706 }
707
708 #[test]
709 fn test_float_argmin_i32_out_dtype() {
710 use ruda_tensor::ops::FloatTensorOps;
711 use ruda_tensor::IntDType;
712
713 let t = crate::HostTensor::from_data(TensorData::from([[3.0f32, 1.0, 2.0]]));
714 let result = Host::float_argmin(t, 1, IntDType::I32);
715 assert_eq!(result.dtype(), ruda_tensor::DType::I32);
716 let data: Vec<i32> = result.into_data().to_vec().unwrap();
717 assert_eq!(data, vec![1]);
718 }
719
720 #[test]
721 fn test_float_argmax_i64_out_dtype() {
722 use ruda_tensor::ops::FloatTensorOps;
723 use ruda_tensor::IntDType;
724
725 let t = crate::HostTensor::from_data(TensorData::from([[1.0f32, 3.0, 2.0]]));
726 let result = Host::float_argmax(t, 1, IntDType::I64);
727 assert_eq!(result.dtype(), ruda_tensor::DType::I64);
728 let data: Vec<i64> = result.into_data().to_vec().unwrap();
729 assert_eq!(data, vec![1]);
730 }
731
732 #[test]
733 fn test_float_max_dim_with_indices_i32() {
734 use ruda_tensor::ops::FloatTensorOps;
735 use ruda_tensor::IntDType;
736
737 let t = crate::HostTensor::from_data(TensorData::from([[1.0f32, 5.0], [3.0, 2.0]]));
738 let (values, indices) = Host::float_max_dim_with_indices(t, 1, IntDType::I32);
739 assert_eq!(indices.dtype(), ruda_tensor::DType::I32);
740 let idx: Vec<i32> = indices.into_data().to_vec().unwrap();
741 assert_eq!(idx, vec![1, 0]);
742 let vals: Vec<f32> = values.into_data().to_vec().unwrap();
743 assert_eq!(vals, vec![5.0, 3.0]);
744 }
745
746 #[test]
747 fn test_float_min_dim_with_indices_i32() {
748 use ruda_tensor::ops::FloatTensorOps;
749 use ruda_tensor::IntDType;
750
751 let t = crate::HostTensor::from_data(TensorData::from([[1.0f32, 5.0], [3.0, 2.0]]));
752 let (values, indices) = Host::float_min_dim_with_indices(t, 1, IntDType::I32);
753 assert_eq!(indices.dtype(), ruda_tensor::DType::I32);
754 let idx: Vec<i32> = indices.into_data().to_vec().unwrap();
755 assert_eq!(idx, vec![0, 1]);
756 let vals: Vec<f32> = values.into_data().to_vec().unwrap();
757 assert_eq!(vals, vec![1.0, 2.0]);
758 }
759
760 #[test]
761 fn test_float_random_f64() {
762 use ruda_tensor::{DType, FloatDType, ops::FloatTensorOps};
763
764 let shape = ruda_tensor::Shape::from(vec![100]);
765 let dist = ruda_tensor::Distribution::Uniform(0.0, 1.0);
766 let device = crate::HostDevice;
767 let t = Host::float_random(shape, dist, &device, FloatDType::F64);
768 assert_eq!(t.dtype(), DType::F64);
769 let data: Vec<f64> = t.into_data().to_vec().unwrap();
770 assert!(data.iter().all(|&v| (0.0..=1.0).contains(&v)));
771 }
772
773 #[test]
774 fn test_float_random_f16() {
775 use ruda_tensor::{DType, FloatDType, ops::FloatTensorOps};
776
777 let shape = ruda_tensor::Shape::from(vec![100]);
778 let dist = ruda_tensor::Distribution::Uniform(0.0, 1.0);
779 let device = crate::HostDevice;
780 let t = Host::float_random(shape, dist, &device, FloatDType::F16);
781 assert_eq!(t.dtype(), DType::F16);
782 }
783}