1use alloc::vec::Vec;
4use ruda_tensor::{
5 Distribution, ExecutionError, Scalar, TensorData,
6 ops::IntTensorOps,
7 tensor::{BoolTensor, Device, FloatTensor, IntTensor},
8};
9use ruda_tensor::{IntDType, Shape, Slice};
10
11use crate::{Host, HostTensor, ops::matmul};
12
13impl IntTensorOps<Host> for Host {
14 fn int_from_data(data: TensorData, _device: &Device<Host>) -> IntTensor<Host> {
15 HostTensor::from_data(data)
16 }
17
18 async fn int_into_data(tensor: IntTensor<Host>) -> Result<TensorData, ExecutionError> {
19 Ok(tensor.into_data())
20 }
21
22 fn int_device(_tensor: &IntTensor<Host>) -> Device<Host> {
23 Default::default()
24 }
25
26 fn int_to_device(tensor: IntTensor<Host>, _device: &Device<Host>) -> IntTensor<Host> {
27 tensor
28 }
29
30 fn int_cat(tensors: Vec<IntTensor<Host>>, dim: usize) -> IntTensor<Host> {
31 crate::ops::cat::cat(tensors, dim)
32 }
33
34 fn int_reshape(tensor: IntTensor<Host>, shape: Shape) -> IntTensor<Host> {
35 tensor.reshape(shape)
36 }
37
38 fn int_slice(tensor: IntTensor<Host>, slices: &[Slice]) -> IntTensor<Host> {
39 crate::ops::slice::slice(tensor, slices)
40 }
41
42 fn int_empty(shape: Shape, _device: &Device<Host>, dtype: IntDType) -> IntTensor<Host> {
43 HostTensor::empty(shape, dtype.into())
44 }
45
46 fn int_mask_where(
47 tensor: IntTensor<Host>,
48 mask: BoolTensor<Host>,
49 value: IntTensor<Host>,
50 ) -> IntTensor<Host> {
51 ruprim_host::mask::dispatch::int_mask_where(tensor, mask, value)
52 }
53
54 fn int_mask_fill(
55 tensor: IntTensor<Host>,
56 mask: BoolTensor<Host>,
57 value: Scalar,
58 ) -> IntTensor<Host> {
59 ruprim_host::mask::dispatch::int_mask_fill(tensor, mask, value)
60 }
61
62 fn int_slice_assign(
63 tensor: IntTensor<Host>,
64 slices: &[Slice],
65 value: IntTensor<Host>,
66 ) -> IntTensor<Host> {
67 crate::ops::slice::slice_assign(tensor, slices, value)
68 }
69
70 fn int_gather(
78 dim: usize,
79 tensor: IntTensor<Host>,
80 indices: IntTensor<Host>,
81 ) -> IntTensor<Host> {
82 ruprim_host::gather_scatter::dispatch_int::int_gather(dim, tensor, indices)
83 }
84
85 fn int_scatter_add(
91 dim: usize,
92 tensor: IntTensor<Host>,
93 indices: IntTensor<Host>,
94 value: IntTensor<Host>,
95 ) -> IntTensor<Host> {
96 ruprim_host::gather_scatter::dispatch_int::int_scatter_add(dim, tensor, indices, value)
97 }
98
99 fn int_scatter_nd(
100 data: IntTensor<Host>,
101 indices: IntTensor<Host>,
102 values: IntTensor<Host>,
103 reduction: ruda_tensor::tensor::IndexingUpdateOp,
104 ) -> IntTensor<Host> {
105 ruprim_host::gather_scatter::dispatch_int::int_scatter_nd(data, indices, values, reduction)
106 }
107
108 fn int_gather_nd(data: IntTensor<Host>, indices: IntTensor<Host>) -> IntTensor<Host> {
109 ruprim_host::gather_scatter::dispatch_int::int_gather_nd(data, indices)
110 }
111
112 fn int_select(
117 tensor: IntTensor<Host>,
118 dim: usize,
119 indices: IntTensor<Host>,
120 ) -> IntTensor<Host> {
121 ruprim_host::gather_scatter::dispatch_int::int_select(tensor, dim, indices)
122 }
123
124 fn int_select_add(
130 tensor: IntTensor<Host>,
131 dim: usize,
132 indices: IntTensor<Host>,
133 value: IntTensor<Host>,
134 ) -> IntTensor<Host> {
135 ruprim_host::gather_scatter::dispatch_int::int_select_add(tensor, dim, indices, value)
136 }
137
138 fn int_equal(
139 lhs: IntTensor<Host>,
140 rhs: IntTensor<Host>,
141 out_dtype: ruda_tensor::BoolDType,
142 ) -> BoolTensor<Host> {
143 crate::ops::comparison::int_equal(lhs, rhs, out_dtype)
144 }
145
146 fn int_equal_elem(
147 lhs: IntTensor<Host>,
148 rhs: Scalar,
149 out_dtype: ruda_tensor::BoolDType,
150 ) -> BoolTensor<Host> {
151 ruprim_host::comparison::dispatch::int_equal_elem(lhs, rhs, out_dtype)
152 }
153
154 fn int_greater(
155 lhs: IntTensor<Host>,
156 rhs: IntTensor<Host>,
157 out_dtype: ruda_tensor::BoolDType,
158 ) -> BoolTensor<Host> {
159 crate::ops::comparison::int_greater(lhs, rhs, out_dtype)
160 }
161
162 fn int_greater_elem(
163 lhs: IntTensor<Host>,
164 rhs: Scalar,
165 out_dtype: ruda_tensor::BoolDType,
166 ) -> BoolTensor<Host> {
167 ruprim_host::comparison::dispatch::int_greater_elem(lhs, rhs, out_dtype)
168 }
169
170 fn int_greater_equal(
171 lhs: IntTensor<Host>,
172 rhs: IntTensor<Host>,
173 out_dtype: ruda_tensor::BoolDType,
174 ) -> BoolTensor<Host> {
175 crate::ops::comparison::int_greater_equal(lhs, rhs, out_dtype)
176 }
177
178 fn int_greater_equal_elem(
179 lhs: IntTensor<Host>,
180 rhs: Scalar,
181 out_dtype: ruda_tensor::BoolDType,
182 ) -> BoolTensor<Host> {
183 ruprim_host::comparison::dispatch::int_greater_equal_elem(lhs, rhs, out_dtype)
184 }
185
186 fn int_lower(
187 lhs: IntTensor<Host>,
188 rhs: IntTensor<Host>,
189 out_dtype: ruda_tensor::BoolDType,
190 ) -> BoolTensor<Host> {
191 crate::ops::comparison::int_lower(lhs, rhs, out_dtype)
192 }
193
194 fn int_lower_elem(
195 lhs: IntTensor<Host>,
196 rhs: Scalar,
197 out_dtype: ruda_tensor::BoolDType,
198 ) -> BoolTensor<Host> {
199 ruprim_host::comparison::dispatch::int_lower_elem(lhs, rhs, out_dtype)
200 }
201
202 fn int_lower_equal(
203 lhs: IntTensor<Host>,
204 rhs: IntTensor<Host>,
205 out_dtype: ruda_tensor::BoolDType,
206 ) -> BoolTensor<Host> {
207 crate::ops::comparison::int_lower_equal(lhs, rhs, out_dtype)
208 }
209
210 fn int_lower_equal_elem(
211 lhs: IntTensor<Host>,
212 rhs: Scalar,
213 out_dtype: ruda_tensor::BoolDType,
214 ) -> BoolTensor<Host> {
215 ruprim_host::comparison::dispatch::int_lower_equal_elem(lhs, rhs, out_dtype)
216 }
217
218 fn int_add(lhs: IntTensor<Host>, rhs: IntTensor<Host>) -> IntTensor<Host> {
219 ruprim_host::binary::dispatch_int::int_add(lhs, rhs)
220 }
221
222 fn int_add_scalar(lhs: IntTensor<Host>, rhs: Scalar) -> IntTensor<Host> {
223 ruprim_host::binary::dispatch_int::int_add_scalar(lhs, rhs)
224 }
225
226 fn int_sub(lhs: IntTensor<Host>, rhs: IntTensor<Host>) -> IntTensor<Host> {
227 ruprim_host::binary::dispatch_int::int_sub(lhs, rhs)
228 }
229
230 fn int_sub_scalar(lhs: IntTensor<Host>, rhs: Scalar) -> IntTensor<Host> {
231 ruprim_host::binary::dispatch_int::int_sub_scalar(lhs, rhs)
232 }
233
234 fn int_mul(lhs: IntTensor<Host>, rhs: IntTensor<Host>) -> IntTensor<Host> {
235 ruprim_host::binary::dispatch_int::int_mul(lhs, rhs)
236 }
237
238 fn int_mul_scalar(lhs: IntTensor<Host>, rhs: Scalar) -> IntTensor<Host> {
239 ruprim_host::binary::dispatch_int::int_mul_scalar(lhs, rhs)
240 }
241
242 fn int_div(lhs: IntTensor<Host>, rhs: IntTensor<Host>) -> IntTensor<Host> {
243 ruprim_host::binary::dispatch_int::int_div(lhs, rhs)
244 }
245
246 fn int_div_scalar(lhs: IntTensor<Host>, rhs: Scalar) -> IntTensor<Host> {
247 ruprim_host::binary::dispatch_int::int_div_scalar(lhs, rhs)
248 }
249
250 fn int_remainder(lhs: IntTensor<Host>, rhs: IntTensor<Host>) -> IntTensor<Host> {
251 ruprim_host::binary::dispatch_int::int_remainder(lhs, rhs)
252 }
253
254 fn int_remainder_scalar(lhs: IntTensor<Host>, rhs: Scalar) -> IntTensor<Host> {
255 ruprim_host::binary::dispatch_int::int_remainder_scalar(lhs, rhs)
256 }
257
258 fn int_into_float(
260 tensor: IntTensor<Host>,
261 out_dtype: ruda_tensor::FloatDType,
262 ) -> FloatTensor<Host> {
263 ruprim_host::cast::int_into_float(tensor, out_dtype)
264 }
265
266 fn int_swap_dims(tensor: IntTensor<Host>, dim1: usize, dim2: usize) -> IntTensor<Host> {
267 tensor.transpose(dim1, dim2)
268 }
269
270 fn int_permute(tensor: IntTensor<Host>, axes: &[usize]) -> IntTensor<Host> {
271 tensor.permute(axes)
272 }
273
274 fn int_flip(tensor: IntTensor<Host>, axes: &[usize]) -> IntTensor<Host> {
275 crate::ops::flip::flip(tensor, axes)
276 }
277
278 fn int_random(
279 shape: Shape,
280 distribution: Distribution,
281 _device: &Device<Host>,
282 dtype: IntDType,
283 ) -> IntTensor<Host> {
284 rurand_host::int_random(shape, distribution, dtype)
285 }
286
287 fn int_expand(tensor: IntTensor<Host>, shape: Shape) -> IntTensor<Host> {
288 crate::ops::expand::expand(tensor, shape)
289 }
290
291 fn int_matmul(lhs: IntTensor<Host>, rhs: IntTensor<Host>) -> IntTensor<Host> {
292 matmul::int_matmul(lhs, rhs)
293 }
294
295 fn int_sum(tensor: IntTensor<Host>) -> IntTensor<Host> {
296 crate::ops::reduce::sum(tensor)
297 }
298
299 fn int_sum_dim(tensor: IntTensor<Host>, dim: usize) -> IntTensor<Host> {
300 crate::ops::reduce::sum_dim(tensor, dim)
301 }
302
303 fn int_prod(tensor: IntTensor<Host>) -> IntTensor<Host> {
304 crate::ops::reduce::prod(tensor)
305 }
306
307 fn int_prod_dim(tensor: IntTensor<Host>, dim: usize) -> IntTensor<Host> {
308 crate::ops::reduce::prod_dim(tensor, dim)
309 }
310
311 fn int_mean_dim(tensor: IntTensor<Host>, dim: usize) -> IntTensor<Host> {
312 crate::ops::reduce::mean_dim(tensor, dim)
313 }
314
315 fn int_cumsum(tensor: IntTensor<Host>, dim: usize) -> IntTensor<Host> {
316 ruprim_host::cumulative::dispatch::int_cumsum(tensor, dim)
317 }
318
319 fn int_cumprod(tensor: IntTensor<Host>, dim: usize) -> IntTensor<Host> {
320 ruprim_host::cumulative::dispatch::int_cumprod(tensor, dim)
321 }
322
323 fn int_cummin(tensor: IntTensor<Host>, dim: usize) -> IntTensor<Host> {
324 ruprim_host::cumulative::dispatch::int_cummin(tensor, dim)
325 }
326
327 fn int_cummax(tensor: IntTensor<Host>, dim: usize) -> IntTensor<Host> {
328 ruprim_host::cumulative::dispatch::int_cummax(tensor, dim)
329 }
330
331 fn int_argmax(tensor: IntTensor<Host>, dim: usize) -> IntTensor<Host> {
332 crate::ops::reduce::argmax(tensor, dim)
333 }
334
335 fn int_argtopk(tensor: IntTensor<Host>, dim: usize, k: usize) -> IntTensor<Host> {
336 ruprim_host::sort::dispatch::int_argtopk(tensor, dim, k)
337 }
338
339 fn int_argmin(tensor: IntTensor<Host>, dim: usize) -> IntTensor<Host> {
340 crate::ops::reduce::argmin(tensor, dim)
341 }
342
343 fn int_abs(tensor: IntTensor<Host>) -> IntTensor<Host> {
344 crate::ops::unary::int_abs(tensor)
345 }
346
347 fn bitwise_and(lhs: IntTensor<Host>, rhs: IntTensor<Host>) -> IntTensor<Host> {
348 ruprim_host::binary::dispatch_int::bitwise_and(lhs, rhs)
349 }
350
351 fn bitwise_and_scalar(lhs: IntTensor<Host>, rhs: Scalar) -> IntTensor<Host> {
352 ruprim_host::binary::dispatch_int::bitwise_and_scalar(lhs, rhs)
353 }
354
355 fn bitwise_or(lhs: IntTensor<Host>, rhs: IntTensor<Host>) -> IntTensor<Host> {
356 ruprim_host::binary::dispatch_int::bitwise_or(lhs, rhs)
357 }
358
359 fn bitwise_or_scalar(lhs: IntTensor<Host>, rhs: Scalar) -> IntTensor<Host> {
360 ruprim_host::binary::dispatch_int::bitwise_or_scalar(lhs, rhs)
361 }
362
363 fn bitwise_xor(lhs: IntTensor<Host>, rhs: IntTensor<Host>) -> IntTensor<Host> {
364 ruprim_host::binary::dispatch_int::bitwise_xor(lhs, rhs)
365 }
366
367 fn bitwise_xor_scalar(lhs: IntTensor<Host>, rhs: Scalar) -> IntTensor<Host> {
368 ruprim_host::binary::dispatch_int::bitwise_xor_scalar(lhs, rhs)
369 }
370
371 fn bitwise_not(tensor: IntTensor<Host>) -> IntTensor<Host> {
372 ruprim_host::binary::dispatch_int::bitwise_not(tensor)
373 }
374
375 fn bitwise_left_shift(lhs: IntTensor<Host>, rhs: IntTensor<Host>) -> IntTensor<Host> {
377 ruprim_host::binary::dispatch_int::bitwise_left_shift(lhs, rhs)
378 }
379
380 fn bitwise_left_shift_scalar(lhs: IntTensor<Host>, rhs: Scalar) -> IntTensor<Host> {
381 ruprim_host::binary::dispatch_int::bitwise_left_shift_scalar(lhs, rhs)
382 }
383
384 fn bitwise_right_shift(lhs: IntTensor<Host>, rhs: IntTensor<Host>) -> IntTensor<Host> {
385 ruprim_host::binary::dispatch_int::bitwise_right_shift(lhs, rhs)
386 }
387
388 fn bitwise_right_shift_scalar(lhs: IntTensor<Host>, rhs: Scalar) -> IntTensor<Host> {
389 ruprim_host::binary::dispatch_int::bitwise_right_shift_scalar(lhs, rhs)
390 }
391
392 fn int_cast(tensor: IntTensor<Host>, dtype: IntDType) -> IntTensor<Host> {
393 ruprim_host::cast::int_cast(tensor, dtype)
394 }
395
396 fn int_unfold(
397 tensor: IntTensor<Host>,
398 dim: usize,
399 size: usize,
400 step: usize,
401 ) -> IntTensor<Host> {
402 crate::ops::unfold::unfold_int(tensor, dim, size, step)
403 }
404
405 fn int_neg(tensor: IntTensor<Host>) -> IntTensor<Host> {
406 ruprim_host::unary::dispatch_int::int_neg(tensor)
407 }
408
409 fn int_clamp(tensor: IntTensor<Host>, min: Scalar, max: Scalar) -> IntTensor<Host> {
410 ruprim_host::unary::dispatch_int::int_clamp(tensor, min, max)
411 }
412
413 fn int_clamp_min(tensor: IntTensor<Host>, min: Scalar) -> IntTensor<Host> {
414 ruprim_host::unary::dispatch_int::int_clamp_min(tensor, min)
415 }
416
417 fn int_clamp_max(tensor: IntTensor<Host>, max: Scalar) -> IntTensor<Host> {
418 ruprim_host::unary::dispatch_int::int_clamp_max(tensor, max)
419 }
420
421 fn int_sign(tensor: IntTensor<Host>) -> IntTensor<Host> {
422 ruprim_host::unary::dispatch_int::int_sign(tensor)
423 }
424
425 fn int_mean(tensor: IntTensor<Host>) -> IntTensor<Host> {
426 ruprim_host::reduce::dispatch::int_mean(tensor)
427 }
428
429 fn int_max(tensor: IntTensor<Host>) -> IntTensor<Host> {
430 crate::ops::reduce::max(tensor)
431 }
432
433 fn int_max_dim(tensor: IntTensor<Host>, dim: usize) -> IntTensor<Host> {
434 crate::ops::reduce::max_dim(tensor, dim)
435 }
436
437 fn int_min(tensor: IntTensor<Host>) -> IntTensor<Host> {
438 crate::ops::reduce::min(tensor)
439 }
440
441 fn int_min_dim(tensor: IntTensor<Host>, dim: usize) -> IntTensor<Host> {
442 crate::ops::reduce::min_dim(tensor, dim)
443 }
444
445 fn int_max_dim_with_indices(
446 tensor: IntTensor<Host>,
447 dim: usize,
448 ) -> (IntTensor<Host>, IntTensor<Host>) {
449 crate::ops::reduce::max_dim_with_indices(tensor, dim)
450 }
451
452 fn int_min_dim_with_indices(
453 tensor: IntTensor<Host>,
454 dim: usize,
455 ) -> (IntTensor<Host>, IntTensor<Host>) {
456 crate::ops::reduce::min_dim_with_indices(tensor, dim)
457 }
458
459 fn int_any(tensor: IntTensor<Host>, out_dtype: ruda_tensor::BoolDType) -> BoolTensor<Host> {
460 crate::ops::comparison::any_int(tensor, out_dtype)
461 }
462
463 fn int_any_dim(
464 tensor: IntTensor<Host>,
465 dim: usize,
466 out_dtype: ruda_tensor::BoolDType,
467 ) -> BoolTensor<Host> {
468 crate::ops::comparison::any_int_dim(tensor, dim, out_dtype)
469 }
470
471 fn int_all(tensor: IntTensor<Host>, out_dtype: ruda_tensor::BoolDType) -> BoolTensor<Host> {
472 crate::ops::comparison::all_int(tensor, out_dtype)
473 }
474
475 fn int_all_dim(
476 tensor: IntTensor<Host>,
477 dim: usize,
478 out_dtype: ruda_tensor::BoolDType,
479 ) -> BoolTensor<Host> {
480 crate::ops::comparison::all_int_dim(tensor, dim, out_dtype)
481 }
482
483 fn int_powi(lhs: IntTensor<Host>, rhs: IntTensor<Host>) -> IntTensor<Host> {
484 ruprim_host::binary::dispatch_int::int_powi(lhs, rhs)
485 }
486
487 fn int_zeros(shape: Shape, _device: &Device<Host>, dtype: IntDType) -> IntTensor<Host> {
488 HostTensor::zeros(shape, dtype.into())
489 }
490
491 fn int_ones(shape: Shape, _device: &Device<Host>, dtype: IntDType) -> IntTensor<Host> {
492 ruprim_host::fill::int_ones(shape, dtype)
493 }
494
495 fn int_full(
496 shape: Shape,
497 fill_value: ruda_tensor::Scalar,
498 _device: &Device<Host>,
499 dtype: IntDType,
500 ) -> IntTensor<Host> {
501 ruprim_host::fill::int_full(shape, fill_value, dtype)
502 }
503
504 fn int_transpose(tensor: IntTensor<Host>) -> IntTensor<Host> {
505 let ndims = tensor.layout().num_dims();
506 if ndims < 2 {
507 return tensor;
508 }
509 tensor.transpose(ndims - 2, ndims - 1)
510 }
511
512 fn int_repeat_dim(tensor: IntTensor<Host>, dim: usize, times: usize) -> IntTensor<Host> {
513 crate::ops::repeat_dim::repeat_dim(tensor, dim, times)
514 }
515
516 fn int_not_equal(
517 lhs: IntTensor<Host>,
518 rhs: IntTensor<Host>,
519 out_dtype: ruda_tensor::BoolDType,
520 ) -> BoolTensor<Host> {
521 crate::ops::comparison::int_not_equal(lhs, rhs, out_dtype)
522 }
523
524 fn int_not_equal_elem(
525 lhs: IntTensor<Host>,
526 rhs: ruda_tensor::Scalar,
527 out_dtype: ruda_tensor::BoolDType,
528 ) -> BoolTensor<Host> {
529 ruprim_host::comparison::dispatch::int_not_equal_elem(lhs, rhs, out_dtype)
530 }
531
532 fn int_sort(tensor: IntTensor<Host>, dim: usize, descending: bool) -> IntTensor<Host> {
533 crate::ops::sort::sort(tensor, dim, descending)
534 }
535
536 fn int_sort_with_indices(
537 tensor: IntTensor<Host>,
538 dim: usize,
539 descending: bool,
540 ) -> (IntTensor<Host>, IntTensor<Host>) {
541 crate::ops::sort::sort_with_indices(tensor, dim, descending)
542 }
543
544 fn int_argsort(tensor: IntTensor<Host>, dim: usize, descending: bool) -> IntTensor<Host> {
545 crate::ops::sort::argsort(tensor, dim, descending)
546 }
547
548 fn int_powi_scalar(lhs: IntTensor<Host>, rhs: ruda_tensor::Scalar) -> IntTensor<Host> {
549 ruprim_host::binary::dispatch_int::int_powi_scalar(lhs, rhs)
550 }
551
552 fn int_powi_scalar_impl(lhs: IntTensor<Host>, rhs: ruda_tensor::Scalar) -> IntTensor<Host> {
553 ruprim_host::binary::dispatch_int::int_powi_scalar_impl(lhs, rhs)
554 }
555
556 fn int_max_abs(tensor: IntTensor<Host>) -> IntTensor<Host> {
557 ruprim_host::reduce::dispatch::int_max_abs(tensor)
558 }
559
560 fn int_max_abs_dim(tensor: IntTensor<Host>, dim: usize) -> IntTensor<Host> {
561 ruprim_host::reduce::dispatch::int_max_abs_dim(tensor, dim)
562 }
563
564 fn int_arange(
565 range: core::ops::Range<i64>,
566 _device: &Device<Host>,
567 dtype: IntDType,
568 ) -> IntTensor<Host> {
569 Self::int_arange_step(range, 1, &Default::default(), dtype)
570 }
571
572 fn int_arange_step(
573 range: core::ops::Range<i64>,
574 step: usize,
575 _device: &Device<Host>,
576 dtype: IntDType,
577 ) -> IntTensor<Host> {
578 ruprim_host::fill::int_arange_step(range, step, dtype)
579 }
580}
581
582#[cfg(test)]
592mod tests {
593 use alloc::vec;
594 use ruda_tensor::TensorData;
595 use ruda_tensor::ops::IntTensorOps;
596
597 use crate::Host;
598 use crate::HostTensor;
599
600 #[test]
601 fn test_u64_div_large_values() {
602 let a = HostTensor::from_data(TensorData::new(vec![u64::MAX], [1]));
603 let b = HostTensor::from_data(TensorData::new(vec![2u64], [1]));
604 let result = Host::int_div(a, b);
605 let values: Vec<u64> = bytemuck::cast_slice(&result.into_data().bytes).to_vec();
606 assert_eq!(values[0], u64::MAX / 2);
607 }
608
609 #[test]
610 fn test_u64_remainder_large_values() {
611 let a = HostTensor::from_data(TensorData::new(vec![u64::MAX], [1]));
612 let b = HostTensor::from_data(TensorData::new(vec![2u64], [1]));
613 let result = Host::int_remainder(a, b);
614 let values: Vec<u64> = bytemuck::cast_slice(&result.into_data().bytes).to_vec();
615 assert_eq!(values[0], u64::MAX % 2);
616 }
617
618 #[test]
619 fn test_int_abs_min_value() {
620 let a = HostTensor::from_data(TensorData::new(vec![i64::MIN], [1]));
622 let result = Host::int_abs(a);
623 let values: Vec<i64> = bytemuck::cast_slice(&result.into_data().bytes).to_vec();
624 assert_eq!(values[0], i64::MIN.wrapping_abs());
625 }
626
627 #[test]
628 fn test_int_neg_min_value() {
629 let a = HostTensor::from_data(TensorData::new(vec![i64::MIN], [1]));
631 let result = Host::int_neg(a);
632 let values: Vec<i64> = bytemuck::cast_slice(&result.into_data().bytes).to_vec();
633 assert_eq!(values[0], i64::MIN.wrapping_neg());
634 }
635
636 #[test]
637 fn test_int_shift_large_amount() {
638 let a = HostTensor::from_data(TensorData::new(vec![1i64], [1]));
640 let b = HostTensor::from_data(TensorData::new(vec![64i64], [1]));
641 let _left = Host::bitwise_left_shift(a.clone(), b.clone());
642 let _right = Host::bitwise_right_shift(a, b);
643 }
644
645 #[test]
646 fn test_int_into_float_f64() {
647 use ruda_tensor::ops::IntTensorOps;
648 use ruda_tensor::FloatDType;
649
650 let t = HostTensor::from_data(TensorData::new(vec![1i64, 2, -3], [3]));
651 let result = Host::int_into_float(t, FloatDType::F64);
652 assert_eq!(result.dtype(), ruda_tensor::DType::F64);
653 let data: Vec<f64> = result.into_data().to_vec().unwrap();
654 assert_eq!(data, vec![1.0f64, 2.0, -3.0]);
655 }
656
657 #[test]
658 fn test_u64_add_scalar_large() {
659 let t = HostTensor::from_data(TensorData::new(vec![1u64, 2, 3], [3]));
660 let big: u64 = (i64::MAX as u64) + 100;
661 let result = Host::int_add_scalar(t, ruda_tensor::Scalar::from(big));
662 let data: Vec<u64> = result.into_data().to_vec().unwrap();
663 assert_eq!(data, vec![big + 1, big + 2, big + 3]);
664 }
665
666 #[test]
667 fn test_u64_greater_elem_large() {
668 let big: u64 = (i64::MAX as u64) + 100;
669 let t = HostTensor::from_data(TensorData::new(vec![big, big + 1, big - 1], [3]));
670 let result = Host::int_greater_elem(
671 t,
672 ruda_tensor::Scalar::from(big),
673 ruda_tensor::BoolStore::Native,
674 );
675 let data: Vec<bool> = result.into_data().to_vec().unwrap();
676 assert_eq!(data, vec![false, true, false]);
677 }
678
679 #[test]
680 fn test_int_mask_fill_i32() {
681 let t = HostTensor::from_data(TensorData::new(vec![1i32, 2, 3, 4], [4]));
682 let mask = HostTensor::from_data(TensorData::new(vec![true, false, true, false], [4]));
683 let result = Host::int_mask_fill(t, mask, ruda_tensor::Scalar::from(0i64));
684 let data: Vec<i32> = result.into_data().to_vec().unwrap();
685 assert_eq!(data, vec![0, 2, 0, 4]);
686 }
687
688 #[test]
689 fn test_int_mask_fill_i16() {
690 let t = HostTensor::from_data(TensorData::new(vec![10i16, 20, 30, 40], [4]));
691 let mask = HostTensor::from_data(TensorData::new(vec![false, true, false, true], [4]));
692 let result = Host::int_mask_fill(t, mask, ruda_tensor::Scalar::from(-1i64));
693 let data: Vec<i16> = result.into_data().to_vec().unwrap();
694 assert_eq!(data, vec![10, -1, 30, -1]);
695 }
696
697 #[test]
698 fn test_int_mask_fill_u8() {
699 let t = HostTensor::from_data(TensorData::new(vec![1u8, 2, 3, 4], [4]));
700 let mask = HostTensor::from_data(TensorData::new(vec![true, true, false, false], [4]));
701 let result = Host::int_mask_fill(t, mask, ruda_tensor::Scalar::from(255i64));
702 let data: Vec<u8> = result.into_data().to_vec().unwrap();
703 assert_eq!(data, vec![255, 255, 3, 4]);
704 }
705
706 #[test]
707 fn test_int_mask_fill_u32() {
708 let t = HostTensor::from_data(TensorData::new(vec![100u32, 200, 300], [3]));
709 let mask = HostTensor::from_data(TensorData::new(vec![true, false, true], [3]));
710 let result = Host::int_mask_fill(t, mask, ruda_tensor::Scalar::from(0i64));
711 let data: Vec<u32> = result.into_data().to_vec().unwrap();
712 assert_eq!(data, vec![0, 200, 0]);
713 }
714
715 #[test]
716 fn test_int_mask_where_i32() {
717 let t = HostTensor::from_data(TensorData::new(vec![1i32, 2, 3, 4], [4]));
718 let mask = HostTensor::from_data(TensorData::new(vec![true, false, true, false], [4]));
719 let v = HostTensor::from_data(TensorData::new(vec![10i32, 20, 30, 40], [4]));
720 let result = Host::int_mask_where(t, mask, v);
721 let data: Vec<i32> = result.into_data().to_vec().unwrap();
722 assert_eq!(data, vec![10, 2, 30, 4]);
723 }
724
725 #[test]
726 fn test_int_mask_where_u8() {
727 let t = HostTensor::from_data(TensorData::new(vec![1u8, 2, 3, 4], [4]));
728 let mask = HostTensor::from_data(TensorData::new(vec![false, true, false, true], [4]));
729 let v = HostTensor::from_data(TensorData::new(vec![10u8, 20, 30, 40], [4]));
730 let result = Host::int_mask_where(t, mask, v);
731 let data: Vec<u8> = result.into_data().to_vec().unwrap();
732 assert_eq!(data, vec![1, 20, 3, 40]);
733 }
734
735 #[test]
736 fn test_int_gather_i32() {
737 let t = HostTensor::from_data(TensorData::new(vec![10i32, 20, 30, 40, 50, 60], [2, 3]));
738 let indices = HostTensor::from_data(TensorData::new(vec![2i64, 0, 1, 2], [2, 2]));
739 let result = Host::int_gather(1, t, indices);
740 let data: Vec<i32> = result.into_data().to_vec().unwrap();
741 assert_eq!(data, vec![30, 10, 50, 60]);
742 }
743
744 #[test]
745 fn test_int_select_u16() {
746 let t = HostTensor::from_data(TensorData::new(vec![10u16, 20, 30, 40, 50, 60], [2, 3]));
747 let indices = HostTensor::from_data(TensorData::new(vec![0i64, 1], [2]));
748 let result = Host::int_select(t, 1, indices);
749 let data: Vec<u16> = result.into_data().to_vec().unwrap();
750 assert_eq!(data, vec![10, 20, 40, 50]);
751 }
752
753 #[test]
754 fn test_int_cumsum_i32() {
755 let t = HostTensor::from_data(TensorData::new(vec![1i32, 2, 3, 4], [4]));
756 let result = Host::int_cumsum(t, 0);
757 let data: Vec<i32> = result.into_data().to_vec().unwrap();
758 assert_eq!(data, vec![1, 3, 6, 10]);
759 }
760
761 #[test]
762 fn test_int_cumprod_u8() {
763 let t = HostTensor::from_data(TensorData::new(vec![1u8, 2, 3, 4], [4]));
764 let result = Host::int_cumprod(t, 0);
765 let data: Vec<u8> = result.into_data().to_vec().unwrap();
766 assert_eq!(data, vec![1, 2, 6, 24]);
767 }
768
769 #[test]
770 fn test_int_cummin_i32() {
771 let t = HostTensor::from_data(TensorData::new(vec![3i32, 1, 4, 1, 5], [5]));
772 let result = Host::int_cummin(t, 0);
773 let data: Vec<i32> = result.into_data().to_vec().unwrap();
774 assert_eq!(data, vec![3, 1, 1, 1, 1]);
775 }
776
777 #[test]
778 fn test_int_cummax_u16() {
779 let t = HostTensor::from_data(TensorData::new(vec![3u16, 1, 4, 1, 5], [5]));
780 let result = Host::int_cummax(t, 0);
781 let data: Vec<u16> = result.into_data().to_vec().unwrap();
782 assert_eq!(data, vec![3, 3, 4, 4, 5]);
783 }
784
785 #[test]
786 fn test_int_scatter_add_i32() {
787 let t = HostTensor::from_data(TensorData::new(vec![0i32, 0, 0], [1, 3]));
788 let indices = HostTensor::from_data(TensorData::new(vec![0i64, 2, 1], [1, 3]));
789 let values = HostTensor::from_data(TensorData::new(vec![10i32, 20, 30], [1, 3]));
790 let result = Host::int_scatter_add(1, t, indices, values);
791 let data: Vec<i32> = result.into_data().to_vec().unwrap();
792 assert_eq!(data, vec![10, 30, 20]);
793 }
794
795 #[test]
796 fn test_int_select_add_u8() {
797 let t = HostTensor::from_data(TensorData::new(vec![1u8, 2, 3], [3]));
798 let indices = HostTensor::from_data(TensorData::new(vec![0i64, 2], [2]));
799 let values = HostTensor::from_data(TensorData::new(vec![10u8, 20], [2]));
800 let result = Host::int_select_add(t, 0, indices, values);
801 let data: Vec<u8> = result.into_data().to_vec().unwrap();
802 assert_eq!(data, vec![11, 2, 23]);
803 }
804
805 #[test]
806 fn test_int_random_i32() {
807 use ruda_tensor::{DType, Distribution, ops::IntTensorOps};
808 use ruda_tensor::{IntDType, Shape};
809
810 let shape = Shape::from(vec![100]);
811 let dist = Distribution::Uniform(0.0, 10.0);
812 let device = crate::HostDevice;
813 let t = Host::int_random(shape, dist, &device, IntDType::I32);
814 assert_eq!(t.dtype(), DType::I32);
815 let data: Vec<i32> = t.into_data().to_vec().unwrap();
816 assert!(data.iter().all(|&v| (0..=10).contains(&v)));
817 }
818
819 #[test]
820 fn test_int_random_u8() {
821 use ruda_tensor::{DType, Distribution, ops::IntTensorOps};
822 use ruda_tensor::{IntDType, Shape};
823
824 let shape = Shape::from(vec![50]);
825 let dist = Distribution::Uniform(0.0, 100.0);
826 let device = crate::HostDevice;
827 let t = Host::int_random(shape, dist, &device, IntDType::U8);
828 assert_eq!(t.dtype(), DType::U8);
829 }
830
831 #[test]
832 fn test_int_mean_i32() {
833 use ruda_tensor::{DType, ops::IntTensorOps};
834
835 let t = HostTensor::from_data(TensorData::new(vec![10i32, 20, 30], [3]));
836 let result = Host::int_mean(t);
837 assert_eq!(result.dtype(), DType::I32);
838 let data: Vec<i32> = result.into_data().to_vec().unwrap();
839 assert_eq!(data, vec![20]); }
841}